]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 20 May 2017 00:46:51 +0000 (17:46 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 20 May 2017 00:46:51 +0000 (17:46 -0700)
Pull SCSI fixes from James Bottomley:
 "This is the first sweep of mostly minor fixes. There's one security
  one: the read past the end of a buffer in qedf, and a panic fix for
  lpfc SLI-3 adapters, but the rest are a set of include and build
  dependency tidy ups and assorted other small fixes and updates"

* tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi:
  scsi: pmcraid: remove redundant check to see if request_size is less than zero
  scsi: lpfc: ensure els_wq is being checked before destroying it
  scsi: cxlflash: Select IRQ_POLL
  scsi: qedf: Avoid reading past end of buffer
  scsi: qedf: Cleanup the type of io_log->op
  scsi: lpfc: double lock typo in lpfc_ns_rsp()
  scsi: qedf: properly update arguments position in function call
  scsi: scsi_lib: Add #include <scsi/scsi_transport.h>
  scsi: MAINTAINERS: update OSD entries
  scsi: Skip deleted devices in __scsi_device_lookup
  scsi: lpfc: Fix panic on BFS configuration
  scsi: libfc: do not flood console with messages 'libfc: queue full ...'

2937 files changed:
.gitignore
.mailmap
Documentation/00-INDEX
Documentation/ABI/testing/sysfs-bus-pci
Documentation/ABI/testing/sysfs-class-switchtec [new file with mode: 0644]
Documentation/PCI/00-INDEX
Documentation/PCI/endpoint/function/binding/pci-test.txt [new file with mode: 0644]
Documentation/PCI/endpoint/pci-endpoint-cfs.txt [new file with mode: 0644]
Documentation/PCI/endpoint/pci-endpoint.txt [new file with mode: 0644]
Documentation/PCI/endpoint/pci-test-function.txt [new file with mode: 0644]
Documentation/PCI/endpoint/pci-test-howto.txt [new file with mode: 0644]
Documentation/PCI/pci-iov-howto.txt
Documentation/RCU/00-INDEX
Documentation/RCU/Design/Data-Structures/Data-Structures.html
Documentation/RCU/Design/Data-Structures/nxtlist.svg
Documentation/RCU/Design/Expedited-Grace-Periods/Expedited-Grace-Periods.html
Documentation/RCU/Design/Requirements/Requirements.html
Documentation/RCU/rcu_dereference.txt
Documentation/RCU/rculist_nulls.txt
Documentation/RCU/stallwarn.txt
Documentation/RCU/whatisRCU.txt
Documentation/admin-guide/README.rst
Documentation/admin-guide/kernel-parameters.txt
Documentation/arm/stm32/stm32h743-overview.txt [new file with mode: 0644]
Documentation/arm64/tagged-pointers.txt
Documentation/block/bfq-iosched.txt
Documentation/cgroup-v2.txt
Documentation/devicetree/bindings/arm/amlogic.txt
Documentation/devicetree/bindings/arm/atmel-at91.txt
Documentation/devicetree/bindings/arm/cavium-thunder2.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/cpus.txt
Documentation/devicetree/bindings/arm/firmware/linaro,optee-tz.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/fsl.txt
Documentation/devicetree/bindings/arm/gemini.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/hisilicon/hisilicon.txt
Documentation/devicetree/bindings/arm/i2se.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/mediatek/mediatek,apmixedsys.txt
Documentation/devicetree/bindings/arm/mediatek/mediatek,imgsys.txt
Documentation/devicetree/bindings/arm/mediatek/mediatek,infracfg.txt
Documentation/devicetree/bindings/arm/mediatek/mediatek,mmsys.txt
Documentation/devicetree/bindings/arm/mediatek/mediatek,topckgen.txt
Documentation/devicetree/bindings/arm/mediatek/mediatek,vdecsys.txt
Documentation/devicetree/bindings/arm/mediatek/mediatek,vencsys.txt
Documentation/devicetree/bindings/arm/rockchip.txt
Documentation/devicetree/bindings/arm/shmobile.txt
Documentation/devicetree/bindings/arm/sprd.txt
Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/arm/tegra/nvidia,tegra20-flowctrl.txt
Documentation/devicetree/bindings/clock/amlogic,gxbb-clkc.txt
Documentation/devicetree/bindings/clock/idt,versaclock5.txt
Documentation/devicetree/bindings/clock/mvebu-core-clock.txt
Documentation/devicetree/bindings/clock/mvebu-gated-clock.txt
Documentation/devicetree/bindings/clock/qoriq-clock.txt
Documentation/devicetree/bindings/clock/rockchip,rv1108-cru.txt [moved from Documentation/devicetree/bindings/clock/rockchip,rk1108-cru.txt with 83% similarity]
Documentation/devicetree/bindings/clock/sunxi-ccu.txt
Documentation/devicetree/bindings/devfreq/exynos-bus.txt
Documentation/devicetree/bindings/display/imx/fsl,imx-fb.txt
Documentation/devicetree/bindings/display/sunxi/sun4i-drm.txt
Documentation/devicetree/bindings/gpu/arm,mali-utgard.txt
Documentation/devicetree/bindings/gpu/nvidia,gk20a.txt
Documentation/devicetree/bindings/iommu/arm,smmu.txt
Documentation/devicetree/bindings/mtd/atmel-nand.txt
Documentation/devicetree/bindings/mtd/denali-nand.txt
Documentation/devicetree/bindings/mtd/gpio-control-nand.txt
Documentation/devicetree/bindings/mtd/jedec,spi-nor.txt
Documentation/devicetree/bindings/mtd/stm32-quadspi.txt [new file with mode: 0644]
Documentation/devicetree/bindings/net/marvell,prestera.txt
Documentation/devicetree/bindings/pci/designware-pcie.txt
Documentation/devicetree/bindings/pci/faraday,ftpci100.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt
Documentation/devicetree/bindings/pci/ti-pci.txt
Documentation/devicetree/bindings/power/fsl,imx-gpc.txt
Documentation/devicetree/bindings/power/fsl,imx-gpcv2.txt [new file with mode: 0644]
Documentation/devicetree/bindings/power/power_domain.txt
Documentation/devicetree/bindings/power/supply/axp20x_battery.txt [new file with mode: 0644]
Documentation/devicetree/bindings/powerpc/ibm,powerpc-cpu-features.txt [new file with mode: 0644]
Documentation/devicetree/bindings/pwm/atmel-pwm.txt
Documentation/devicetree/bindings/pwm/nvidia,tegra20-pwm.txt
Documentation/devicetree/bindings/pwm/pwm-mediatek.txt [new file with mode: 0644]
Documentation/devicetree/bindings/reset/fsl,imx7-src.txt [new file with mode: 0644]
Documentation/devicetree/bindings/rtc/cpcap-rtc.txt [new file with mode: 0644]
Documentation/devicetree/bindings/rtc/rtc-sh.txt [new file with mode: 0644]
Documentation/devicetree/bindings/serial/sprd-uart.txt
Documentation/devicetree/bindings/soc/fsl/cpm_qe/gpio.txt
Documentation/devicetree/bindings/soc/rockchip/grf.txt
Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt [new file with mode: 0644]
Documentation/devicetree/bindings/thermal/brcm,bcm2835-thermal.txt
Documentation/devicetree/bindings/thermal/brcm,ns-thermal [new file with mode: 0644]
Documentation/devicetree/bindings/thermal/da9062-thermal.txt [new file with mode: 0644]
Documentation/devicetree/bindings/trivial-devices.txt
Documentation/devicetree/bindings/usb/da8xx-usb.txt
Documentation/devicetree/bindings/usb/dwc2.txt
Documentation/devicetree/bindings/vendor-prefixes.txt
Documentation/devicetree/bindings/watchdog/cortina,gemini-watchdog.txt [new file with mode: 0644]
Documentation/driver-model/devres.txt
Documentation/filesystems/bfs.txt
Documentation/filesystems/nfs/pnfs.txt
Documentation/filesystems/overlayfs.txt
Documentation/filesystems/sysfs-pci.txt
Documentation/filesystems/vfs.txt
Documentation/index.rst
Documentation/input/ff.rst
Documentation/ioctl/ioctl-number.txt
Documentation/kbuild/makefiles.txt
Documentation/memory-barriers.txt
Documentation/misc-devices/pci-endpoint-test.txt [new file with mode: 0644]
Documentation/powerpc/firmware-assisted-dump.txt
Documentation/switchtec.txt [new file with mode: 0644]
Documentation/target/target-export-device [new file with mode: 0755]
Documentation/tee.txt [new file with mode: 0644]
Documentation/thermal/sysfs-api.txt
Documentation/translations/ko_KR/memory-barriers.txt
Documentation/virtual/kvm/devices/arm-vgic-its.txt
Documentation/virtual/kvm/devices/arm-vgic-v3.txt
Documentation/vm/transhuge.txt
Documentation/x86/intel_rdt_ui.txt
Kbuild
MAINTAINERS
Makefile
arch/Kconfig
arch/alpha/include/uapi/asm/Kbuild
arch/alpha/lib/Makefile
arch/arc/Kconfig
arch/arc/Makefile
arch/arc/boot/dts/axs10x_mb.dtsi
arch/arc/include/asm/cache.h
arch/arc/include/asm/mmu.h
arch/arc/include/asm/pgtable.h
arch/arc/include/uapi/asm/Kbuild
arch/arc/include/uapi/asm/elf.h
arch/arc/include/uapi/asm/ptrace.h
arch/arc/kernel/ptrace.c
arch/arc/kernel/unwind.c
arch/arc/mm/cache.c
arch/arm/Kconfig
arch/arm/Makefile
arch/arm/boot/dts/Makefile
arch/arm/boot/dts/alpine.dtsi
arch/arm/boot/dts/am335x-baltos-ir2110.dts
arch/arm/boot/dts/am335x-baltos-ir3220.dts
arch/arm/boot/dts/am335x-baltos-ir5221.dts
arch/arm/boot/dts/am335x-baltos-leds.dtsi [new file with mode: 0644]
arch/arm/boot/dts/am335x-boneblack.dts
arch/arm/boot/dts/am335x-icev2.dts
arch/arm/boot/dts/am33xx.dtsi
arch/arm/boot/dts/am3517.dtsi
arch/arm/boot/dts/am4372.dtsi
arch/arm/boot/dts/am437x-gp-evm.dts
arch/arm/boot/dts/am57xx-idk-common.dtsi
arch/arm/boot/dts/armada-385-linksys-shelby.dts [new file with mode: 0644]
arch/arm/boot/dts/armada-385-linksys.dtsi
arch/arm/boot/dts/armada-385-synology-ds116.dts [new file with mode: 0644]
arch/arm/boot/dts/armada-385.dtsi
arch/arm/boot/dts/armada-388-clearfog.dts
arch/arm/boot/dts/armada-388.dtsi
arch/arm/boot/dts/armada-38x.dtsi
arch/arm/boot/dts/armada-xp-98dx3236.dtsi
arch/arm/boot/dts/armada-xp-98dx3336.dtsi
arch/arm/boot/dts/armada-xp-98dx4251.dtsi
arch/arm/boot/dts/armada-xp-db-dxbc2.dts
arch/arm/boot/dts/armada-xp-db-xc3-24g4xg.dts
arch/arm/boot/dts/armada-xp-linksys-mamba.dts
arch/arm/boot/dts/aspeed-ast2500-evb.dts
arch/arm/boot/dts/aspeed-bmc-opp-palmetto.dts
arch/arm/boot/dts/aspeed-bmc-opp-romulus.dts
arch/arm/boot/dts/aspeed-g4.dtsi
arch/arm/boot/dts/aspeed-g5.dtsi
arch/arm/boot/dts/at91-sama5d2_xplained.dts
arch/arm/boot/dts/at91-sama5d3_xplained.dts
arch/arm/boot/dts/at91-tse850-3.dts
arch/arm/boot/dts/at91sam9261.dtsi
arch/arm/boot/dts/at91sam9x5ek.dtsi
arch/arm/boot/dts/axp209.dtsi
arch/arm/boot/dts/axp22x.dtsi
arch/arm/boot/dts/bcm-cygnus.dtsi
arch/arm/boot/dts/bcm-nsp.dtsi
arch/arm/boot/dts/bcm2835-rpi.dtsi
arch/arm/boot/dts/bcm283x-rpi-smsc9512.dtsi
arch/arm/boot/dts/bcm283x-rpi-smsc9514.dtsi
arch/arm/boot/dts/bcm283x.dtsi
arch/arm/boot/dts/bcm4708-asus-rt-ac56u.dts
arch/arm/boot/dts/bcm4708-asus-rt-ac68u.dts
arch/arm/boot/dts/bcm4708-buffalo-wzr-1750dhp.dts
arch/arm/boot/dts/bcm4708-linksys-ea6300-v1.dts [new file with mode: 0644]
arch/arm/boot/dts/bcm4708-netgear-r6250.dts
arch/arm/boot/dts/bcm4708-netgear-r6300-v2.dts
arch/arm/boot/dts/bcm4708-smartrg-sr400ac.dts
arch/arm/boot/dts/bcm4708.dtsi
arch/arm/boot/dts/bcm47081-asus-rt-n18u.dts
arch/arm/boot/dts/bcm47081-buffalo-wzr-600dhp2.dts
arch/arm/boot/dts/bcm47081-buffalo-wzr-900dhp.dts
arch/arm/boot/dts/bcm47081-tplink-archer-c5-v2.dts [new file with mode: 0644]
arch/arm/boot/dts/bcm47081.dtsi
arch/arm/boot/dts/bcm4709-asus-rt-ac87u.dts
arch/arm/boot/dts/bcm4709-buffalo-wxr-1900dhp.dts
arch/arm/boot/dts/bcm4709-linksys-ea9200.dts [new file with mode: 0644]
arch/arm/boot/dts/bcm4709-netgear-r7000.dts
arch/arm/boot/dts/bcm4709-netgear-r8000.dts
arch/arm/boot/dts/bcm4709-tplink-archer-c9-v1.dts
arch/arm/boot/dts/bcm47094-dlink-dir-885l.dts
arch/arm/boot/dts/bcm47094-linksys-panamera.dts [new file with mode: 0644]
arch/arm/boot/dts/bcm47094-luxul-xwr-3100.dts
arch/arm/boot/dts/bcm47094-netgear-r8500.dts
arch/arm/boot/dts/bcm47189-tenda-ac9.dts
arch/arm/boot/dts/bcm5301x.dtsi
arch/arm/boot/dts/bcm53573.dtsi
arch/arm/boot/dts/bcm94708.dts
arch/arm/boot/dts/bcm94709.dts
arch/arm/boot/dts/bcm953012er.dts
arch/arm/boot/dts/bcm953012hr.dts [new file with mode: 0644]
arch/arm/boot/dts/bcm953012k.dts
arch/arm/boot/dts/bcm958522er.dts
arch/arm/boot/dts/bcm958525er.dts
arch/arm/boot/dts/bcm958525xmc.dts
arch/arm/boot/dts/bcm958622hr.dts
arch/arm/boot/dts/bcm958623hr.dts
arch/arm/boot/dts/bcm958625hr.dts
arch/arm/boot/dts/bcm958625k.dts
arch/arm/boot/dts/bcm988312hr.dts
arch/arm/boot/dts/da850-evm.dts
arch/arm/boot/dts/da850-lego-ev3.dts
arch/arm/boot/dts/da850.dtsi
arch/arm/boot/dts/dm8168-evm.dts
arch/arm/boot/dts/dm816x.dtsi
arch/arm/boot/dts/dra7-evm.dts
arch/arm/boot/dts/dra7.dtsi
arch/arm/boot/dts/dra74x.dtsi
arch/arm/boot/dts/exynos3250-rinato.dts
arch/arm/boot/dts/exynos3250.dtsi
arch/arm/boot/dts/exynos4.dtsi
arch/arm/boot/dts/exynos4210-origen.dts
arch/arm/boot/dts/exynos4210-trats.dts
arch/arm/boot/dts/exynos4210.dtsi
arch/arm/boot/dts/exynos4412-itop-scp-core.dtsi
arch/arm/boot/dts/exynos4412-odroid-common.dtsi
arch/arm/boot/dts/exynos4412-origen.dts
arch/arm/boot/dts/exynos4412-prime.dtsi
arch/arm/boot/dts/exynos4412-trats2.dts
arch/arm/boot/dts/exynos4412.dtsi
arch/arm/boot/dts/exynos5420-tmu-sensor-conf.dtsi [new file with mode: 0644]
arch/arm/boot/dts/exynos5420.dtsi
arch/arm/boot/dts/exynos5440.dtsi
arch/arm/boot/dts/exynos5800.dtsi
arch/arm/boot/dts/gemini-nas4220b.dts [new file with mode: 0644]
arch/arm/boot/dts/gemini-rut1xx.dts [new file with mode: 0644]
arch/arm/boot/dts/gemini-sq201.dts [new file with mode: 0644]
arch/arm/boot/dts/gemini-wbd111.dts [new file with mode: 0644]
arch/arm/boot/dts/gemini-wbd222.dts [new file with mode: 0644]
arch/arm/boot/dts/gemini.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx25-eukrea-mbimxsd25-baseboard.dts
arch/arm/boot/dts/imx25-pdk.dts
arch/arm/boot/dts/imx25-pinfunc.h
arch/arm/boot/dts/imx25.dtsi
arch/arm/boot/dts/imx28-duckbill-2-485.dts [new file with mode: 0644]
arch/arm/boot/dts/imx28-duckbill-2-enocean.dts [new file with mode: 0644]
arch/arm/boot/dts/imx28-duckbill-2-spi.dts [new file with mode: 0644]
arch/arm/boot/dts/imx28-duckbill-2.dts [new file with mode: 0644]
arch/arm/boot/dts/imx28-duckbill.dts
arch/arm/boot/dts/imx28-m28cu3.dts
arch/arm/boot/dts/imx28.dtsi
arch/arm/boot/dts/imx50.dtsi
arch/arm/boot/dts/imx53-qsb.dts
arch/arm/boot/dts/imx53-qsrb.dts
arch/arm/boot/dts/imx6dl-gw5903.dts [new file with mode: 0644]
arch/arm/boot/dts/imx6dl-gw5904.dts [new file with mode: 0644]
arch/arm/boot/dts/imx6q-b450v3.dts
arch/arm/boot/dts/imx6q-b650v3.dts
arch/arm/boot/dts/imx6q-b850v3.dts
arch/arm/boot/dts/imx6q-bx50v3.dtsi
arch/arm/boot/dts/imx6q-cm-fx6.dts
arch/arm/boot/dts/imx6q-gw5903.dts [new file with mode: 0644]
arch/arm/boot/dts/imx6q-gw5904.dts [new file with mode: 0644]
arch/arm/boot/dts/imx6q-icore-ofcap10.dts [new file with mode: 0644]
arch/arm/boot/dts/imx6q-icore-ofcap12.dts [new file with mode: 0644]
arch/arm/boot/dts/imx6q-icore.dts
arch/arm/boot/dts/imx6q-utilite-pro.dts
arch/arm/boot/dts/imx6q-zii-rdu2.dts [new file with mode: 0644]
arch/arm/boot/dts/imx6qdl-gw5903.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx6qdl-gw5904.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx6qdl-icore.dtsi
arch/arm/boot/dts/imx6qdl-sabresd.dtsi
arch/arm/boot/dts/imx6qdl-zii-rdu2.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx6qdl.dtsi
arch/arm/boot/dts/imx6qp-nitrogen6_som2.dts [new file with mode: 0644]
arch/arm/boot/dts/imx6qp-sabresd.dts
arch/arm/boot/dts/imx6qp-zii-rdu2.dts [new file with mode: 0644]
arch/arm/boot/dts/imx6qp.dtsi
arch/arm/boot/dts/imx6sx-sdb.dts
arch/arm/boot/dts/imx6sx.dtsi
arch/arm/boot/dts/imx6ul-14x14-evk.dts
arch/arm/boot/dts/imx6ul-geam.dtsi
arch/arm/boot/dts/imx6ul-isiot-common.dtsi [new file with mode: 0644]
arch/arm/boot/dts/imx6ul-isiot-emmc.dts
arch/arm/boot/dts/imx6ul-isiot-nand.dts
arch/arm/boot/dts/imx6ul-isiot.dtsi
arch/arm/boot/dts/imx7-colibri-eval-v3.dtsi
arch/arm/boot/dts/imx7-colibri.dtsi
arch/arm/boot/dts/imx7d-colibri-eval-v3.dts
arch/arm/boot/dts/imx7d-sdb-sht11.dts [new file with mode: 0644]
arch/arm/boot/dts/imx7s.dtsi
arch/arm/boot/dts/include/dt-bindings [deleted symlink]
arch/arm/boot/dts/logicpd-torpedo-37xx-devkit.dts
arch/arm/boot/dts/meson8.dtsi
arch/arm/boot/dts/meson8b.dtsi
arch/arm/boot/dts/motorola-cpcap-mapphone.dtsi [new file with mode: 0644]
arch/arm/boot/dts/moxart-uc7112lx.dts
arch/arm/boot/dts/moxart.dtsi
arch/arm/boot/dts/mt7623.dtsi
arch/arm/boot/dts/omap3-cpu-thermal.dtsi [new file with mode: 0644]
arch/arm/boot/dts/omap3-gta04.dtsi
arch/arm/boot/dts/omap3-igep.dtsi
arch/arm/boot/dts/omap3-n900.dts
arch/arm/boot/dts/omap3-n950-n9.dtsi
arch/arm/boot/dts/omap34xx.dtsi
arch/arm/boot/dts/omap36xx.dtsi
arch/arm/boot/dts/omap4-droid4-xt894.dts
arch/arm/boot/dts/omap4-panda-a4.dts
arch/arm/boot/dts/omap4-panda-es.dts
arch/arm/boot/dts/omap443x.dtsi
arch/arm/boot/dts/omap4460.dtsi
arch/arm/boot/dts/omap5.dtsi
arch/arm/boot/dts/qcom-apq8060-dragonboard.dts
arch/arm/boot/dts/qcom-msm8660.dtsi
arch/arm/boot/dts/qcom-msm8974-sony-xperia-honami.dts
arch/arm/boot/dts/qcom-msm8974.dtsi
arch/arm/boot/dts/r7s72100-genmai.dts
arch/arm/boot/dts/r7s72100-rskrza1.dts
arch/arm/boot/dts/r7s72100.dtsi
arch/arm/boot/dts/r8a73a4.dtsi
arch/arm/boot/dts/r8a7743.dtsi
arch/arm/boot/dts/r8a7745.dtsi
arch/arm/boot/dts/r8a7778-bockw.dts
arch/arm/boot/dts/r8a7779-marzen.dts
arch/arm/boot/dts/r8a7790-lager.dts
arch/arm/boot/dts/r8a7790.dtsi
arch/arm/boot/dts/r8a7791-koelsch.dts
arch/arm/boot/dts/r8a7791-porter.dts
arch/arm/boot/dts/r8a7791.dtsi
arch/arm/boot/dts/r8a7792.dtsi
arch/arm/boot/dts/r8a7793-gose.dts
arch/arm/boot/dts/r8a7793.dtsi
arch/arm/boot/dts/r8a7794-alt.dts
arch/arm/boot/dts/r8a7794-silk.dts
arch/arm/boot/dts/r8a7794.dtsi
arch/arm/boot/dts/rk1108.dtsi
arch/arm/boot/dts/rk3036.dtsi
arch/arm/boot/dts/rk3188.dtsi
arch/arm/boot/dts/rk322x.dtsi
arch/arm/boot/dts/rk3288-miqi.dts
arch/arm/boot/dts/rk3288-phycore-rdk.dts [new file with mode: 0644]
arch/arm/boot/dts/rk3288-phycore-som.dtsi [new file with mode: 0644]
arch/arm/boot/dts/rk3288-rock2-som.dtsi
arch/arm/boot/dts/rk3288-rock2-square.dts
arch/arm/boot/dts/rk3288-tinker.dts [new file with mode: 0644]
arch/arm/boot/dts/rk3288.dtsi
arch/arm/boot/dts/rk3xxx.dtsi
arch/arm/boot/dts/s3c64xx.dtsi
arch/arm/boot/dts/s5pv210.dtsi
arch/arm/boot/dts/sama5d2.dtsi
arch/arm/boot/dts/socfpga.dtsi
arch/arm/boot/dts/socfpga_arria10.dtsi
arch/arm/boot/dts/socfpga_arria10_socdk.dtsi
arch/arm/boot/dts/socfpga_arria5_socdk.dts
arch/arm/boot/dts/socfpga_cyclone5_de0_sockit.dts
arch/arm/boot/dts/socfpga_cyclone5_mcv.dtsi
arch/arm/boot/dts/socfpga_cyclone5_mcvevk.dts
arch/arm/boot/dts/socfpga_cyclone5_socdk.dts
arch/arm/boot/dts/socfpga_cyclone5_sockit.dts
arch/arm/boot/dts/socfpga_cyclone5_socrates.dts
arch/arm/boot/dts/socfpga_cyclone5_sodia.dts
arch/arm/boot/dts/socfpga_cyclone5_vining_fpga.dts
arch/arm/boot/dts/socfpga_vt.dts
arch/arm/boot/dts/spear600-evb.dts
arch/arm/boot/dts/spear600.dtsi
arch/arm/boot/dts/stih407-family.dtsi
arch/arm/boot/dts/stm32429i-eval.dts
arch/arm/boot/dts/stm32746g-eval.dts
arch/arm/boot/dts/stm32f429-disco.dts
arch/arm/boot/dts/stm32f429.dtsi
arch/arm/boot/dts/stm32f469-disco.dts
arch/arm/boot/dts/stm32f746.dtsi
arch/arm/boot/dts/stm32h743-pinctrl.dtsi [new file with mode: 0644]
arch/arm/boot/dts/stm32h743.dtsi [new file with mode: 0644]
arch/arm/boot/dts/stm32h743i-eval.dts [new file with mode: 0644]
arch/arm/boot/dts/sun4i-a10-a1000.dts
arch/arm/boot/dts/sun4i-a10-cubieboard.dts
arch/arm/boot/dts/sun4i-a10-dserve-dsrv9703c.dts
arch/arm/boot/dts/sun4i-a10-hackberry.dts
arch/arm/boot/dts/sun4i-a10-inet1.dts
arch/arm/boot/dts/sun4i-a10-inet9f-rev03.dts
arch/arm/boot/dts/sun4i-a10-jesurun-q5.dts
arch/arm/boot/dts/sun4i-a10-marsboard.dts
arch/arm/boot/dts/sun4i-a10-mini-xplus.dts
arch/arm/boot/dts/sun4i-a10-mk802.dts
arch/arm/boot/dts/sun4i-a10-olinuxino-lime.dts
arch/arm/boot/dts/sun4i-a10-pcduino.dts
arch/arm/boot/dts/sun4i-a10-pov-protab2-ips9.dts
arch/arm/boot/dts/sun4i-a10.dtsi
arch/arm/boot/dts/sun5i-a10s-auxtek-t003.dts
arch/arm/boot/dts/sun5i-a10s-auxtek-t004.dts
arch/arm/boot/dts/sun5i-a10s-olinuxino-micro.dts
arch/arm/boot/dts/sun5i-a10s-r7-tv-dongle.dts
arch/arm/boot/dts/sun5i-a10s-wobo-i5.dts
arch/arm/boot/dts/sun5i-a10s.dtsi
arch/arm/boot/dts/sun5i-a13-empire-electronix-d709.dts
arch/arm/boot/dts/sun5i-a13-hsg-h702.dts
arch/arm/boot/dts/sun5i-a13-licheepi-one.dts
arch/arm/boot/dts/sun5i-a13-olinuxino-micro.dts
arch/arm/boot/dts/sun5i-a13-olinuxino.dts
arch/arm/boot/dts/sun5i-a13.dtsi
arch/arm/boot/dts/sun5i-gr8-chip-pro.dts
arch/arm/boot/dts/sun5i-gr8-evb.dts
arch/arm/boot/dts/sun5i-gr8.dtsi
arch/arm/boot/dts/sun5i-r8-chip.dts
arch/arm/boot/dts/sun5i-r8.dtsi
arch/arm/boot/dts/sun5i.dtsi
arch/arm/boot/dts/sun6i-a31-app4-evb1.dts
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-primo81.dts
arch/arm/boot/dts/sun6i-a31s-sina31s-core.dtsi
arch/arm/boot/dts/sun6i-a31s-sina31s.dts
arch/arm/boot/dts/sun6i-a31s-sinovoip-bpi-m2.dts
arch/arm/boot/dts/sun6i-a31s-yones-toptech-bs1078-v2.dts
arch/arm/boot/dts/sun6i-reference-design-tablet.dtsi
arch/arm/boot/dts/sun7i-a20-bananapi.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-lamobo-r1.dts
arch/arm/boot/dts/sun7i-a20-m3.dts
arch/arm/boot/dts/sun7i-a20-mk808c.dts
arch/arm/boot/dts/sun7i-a20-olimex-som-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.dts
arch/arm/boot/dts/sun7i-a20.dtsi
arch/arm/boot/dts/sun8i-a23-a33.dtsi
arch/arm/boot/dts/sun8i-a23-evb.dts
arch/arm/boot/dts/sun8i-a23-q8-tablet.dts
arch/arm/boot/dts/sun8i-a33-sinlinx-sina33.dts
arch/arm/boot/dts/sun8i-a33.dtsi
arch/arm/boot/dts/sun8i-a83t.dtsi
arch/arm/boot/dts/sun8i-h2-plus-orangepi-zero.dts
arch/arm/boot/dts/sun8i-h3-bananapi-m2-plus.dts
arch/arm/boot/dts/sun8i-h3-beelink-x2.dts
arch/arm/boot/dts/sun8i-h3-nanopi-neo-air.dts [new file with mode: 0644]
arch/arm/boot/dts/sun8i-h3-nanopi.dtsi
arch/arm/boot/dts/sun8i-h3-orangepi-2.dts
arch/arm/boot/dts/sun8i-h3-orangepi-lite.dts
arch/arm/boot/dts/sun8i-h3-orangepi-one.dts
arch/arm/boot/dts/sun8i-h3-orangepi-pc.dts
arch/arm/boot/dts/sun8i-h3.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-common-regulators.dtsi
arch/arm/boot/dts/sunxi-h3-h5.dtsi [new file with mode: 0644]
arch/arm/boot/dts/sunxi-reference-design-tablet.dtsi
arch/arm/boot/dts/uniphier-ld4-ref.dts
arch/arm/boot/dts/uniphier-ld4.dtsi
arch/arm/boot/dts/uniphier-ld6b-ref.dts
arch/arm/boot/dts/uniphier-pinctrl.dtsi
arch/arm/boot/dts/uniphier-pro4-ace.dts
arch/arm/boot/dts/uniphier-pro4-ref.dts
arch/arm/boot/dts/uniphier-pro4-sanji.dts
arch/arm/boot/dts/uniphier-pro4.dtsi
arch/arm/boot/dts/uniphier-pro5.dtsi
arch/arm/boot/dts/uniphier-pxs2-gentil.dts
arch/arm/boot/dts/uniphier-pxs2-vodka.dts
arch/arm/boot/dts/uniphier-pxs2.dtsi
arch/arm/boot/dts/uniphier-ref-daughter.dtsi
arch/arm/boot/dts/uniphier-sld3-ref.dts
arch/arm/boot/dts/uniphier-sld3.dtsi
arch/arm/boot/dts/uniphier-sld8-ref.dts
arch/arm/boot/dts/uniphier-sld8.dtsi
arch/arm/boot/dts/uniphier-support-card.dtsi
arch/arm/boot/dts/vexpress-v2m-rs1.dtsi
arch/arm/boot/dts/vexpress-v2m.dtsi
arch/arm/boot/dts/vexpress-v2p-ca15-tc1.dts
arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
arch/arm/boot/dts/vexpress-v2p-ca5s.dts
arch/arm/boot/dts/vexpress-v2p-ca9.dts
arch/arm/boot/dts/vf610-zii-dev-rev-b.dts
arch/arm/boot/dts/vf610-zii-dev-rev-c.dts
arch/arm/boot/dts/vf610-zii-dev.dtsi
arch/arm/common/Kconfig
arch/arm/common/Makefile
arch/arm/configs/aspeed_g4_defconfig
arch/arm/configs/aspeed_g5_defconfig
arch/arm/configs/bcm2835_defconfig
arch/arm/configs/davinci_all_defconfig
arch/arm/configs/dram_0xd0000000.config [new file with mode: 0644]
arch/arm/configs/exynos_defconfig
arch/arm/configs/gemini_defconfig [new file with mode: 0644]
arch/arm/configs/imx_v6_v7_defconfig
arch/arm/configs/multi_v7_defconfig
arch/arm/configs/omap2plus_defconfig
arch/arm/configs/qcom_defconfig
arch/arm/configs/socfpga_defconfig
arch/arm/configs/stm32_defconfig
arch/arm/configs/sunxi_defconfig
arch/arm/include/asm/cacheflush.h
arch/arm/include/asm/io.h
arch/arm/include/asm/kvm_coproc.h
arch/arm/include/asm/pci.h
arch/arm/include/asm/set_memory.h [new file with mode: 0644]
arch/arm/include/debug/brcmstb.S
arch/arm/include/uapi/asm/Kbuild
arch/arm/include/uapi/asm/kvm.h
arch/arm/kernel/bios32.c
arch/arm/kernel/ftrace.c
arch/arm/kernel/kgdb.c
arch/arm/kernel/machine_kexec.c
arch/arm/kernel/module.c
arch/arm/kvm/Makefile
arch/arm/kvm/coproc.c
arch/arm/kvm/handle_exit.c
arch/arm/kvm/hyp/Makefile
arch/arm/kvm/hyp/switch.c
arch/arm/kvm/trace.h
arch/arm/mach-at91/Makefile
arch/arm/mach-at91/at91rm9200.c
arch/arm/mach-at91/at91sam9.c
arch/arm/mach-at91/generic.h
arch/arm/mach-at91/pm.c
arch/arm/mach-at91/pm.h
arch/arm/mach-at91/pm_data-offsets.c [new file with mode: 0644]
arch/arm/mach-at91/pm_suspend.S
arch/arm/mach-at91/sama5.c
arch/arm/mach-at91/soc.c [deleted file]
arch/arm/mach-bcm/Kconfig
arch/arm/mach-bcm/bcm_kona_smc.c
arch/arm/mach-cns3xxx/core.c
arch/arm/mach-davinci/board-da850-evm.c
arch/arm/mach-davinci/board-dm644x-evm.c
arch/arm/mach-davinci/board-dm646x-evm.c
arch/arm/mach-davinci/board-neuros-osd2.c
arch/arm/mach-davinci/da830.c
arch/arm/mach-davinci/da850.c
arch/arm/mach-davinci/da8xx-dt.c
arch/arm/mach-davinci/pdata-quirks.c
arch/arm/mach-davinci/pm.c
arch/arm/mach-gemini/Kconfig
arch/arm/mach-gemini/Makefile
arch/arm/mach-gemini/Makefile.boot [deleted file]
arch/arm/mach-gemini/board-dt.c [new file with mode: 0644]
arch/arm/mach-gemini/board-nas4220b.c [deleted file]
arch/arm/mach-gemini/board-rut1xx.c [deleted file]
arch/arm/mach-gemini/board-wbd111.c [deleted file]
arch/arm/mach-gemini/board-wbd222.c [deleted file]
arch/arm/mach-gemini/common.h [deleted file]
arch/arm/mach-gemini/devices.c [deleted file]
arch/arm/mach-gemini/gpio.c [deleted file]
arch/arm/mach-gemini/idle.c [deleted file]
arch/arm/mach-gemini/include/mach/entry-macro.S [deleted file]
arch/arm/mach-gemini/include/mach/global_reg.h [deleted file]
arch/arm/mach-gemini/include/mach/hardware.h [deleted file]
arch/arm/mach-gemini/include/mach/irqs.h [deleted file]
arch/arm/mach-gemini/include/mach/uncompress.h [deleted file]
arch/arm/mach-gemini/irq.c [deleted file]
arch/arm/mach-gemini/mm.c [deleted file]
arch/arm/mach-gemini/reset.c [deleted file]
arch/arm/mach-gemini/time.c [deleted file]
arch/arm/mach-hisi/platmcpm.c
arch/arm/mach-imx/gpc.c
arch/arm/mach-imx/mach-imx25.c
arch/arm/mach-imx/mach-mx31_3ds.c
arch/arm/mach-imx/mach-mx31moboard.c
arch/arm/mach-imx/mach-pcm037_eet.c
arch/arm/mach-imx/mmdc.c
arch/arm/mach-ixp4xx/common-pci.c
arch/arm/mach-keystone/Kconfig
arch/arm/mach-keystone/pm_domain.c
arch/arm/mach-mmp/clock.c
arch/arm/mach-mxs/mach-mxs.c
arch/arm/mach-omap1/pm.c
arch/arm/mach-omap2/board-n8x0.c
arch/arm/mach-omap2/clkt2xxx_dpllcore.c
arch/arm/mach-omap2/clock.c
arch/arm/mach-omap2/clock.h
arch/arm/mach-omap2/clockdomains7xx_data.c
arch/arm/mach-omap2/clockdomains81xx_data.c
arch/arm/mach-omap2/cm.h
arch/arm/mach-omap2/cm2xxx.c
arch/arm/mach-omap2/cm3xxx.c
arch/arm/mach-omap2/cm81xx.h
arch/arm/mach-omap2/cm_common.c
arch/arm/mach-omap2/common.h
arch/arm/mach-omap2/devices.c
arch/arm/mach-omap2/omap-mpuss-lowpower.c
arch/arm/mach-omap2/omap-smp.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod.h
arch/arm/mach-omap2/omap_hwmod_2xxx_ipblock_data.c
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/mach-omap2/omap_hwmod_54xx_data.c
arch/arm/mach-omap2/omap_hwmod_7xx_data.c
arch/arm/mach-omap2/omap_hwmod_81xx_data.c
arch/arm/mach-omap2/pm.c
arch/arm/mach-omap2/prm_common.c
arch/arm/mach-omap2/vc.c
arch/arm/mach-oxnas/Kconfig
arch/arm/mach-spear/time.c
arch/arm/mach-stm32/Kconfig [new file with mode: 0644]
arch/arm/mach-stm32/board-dt.c
arch/arm/mach-sunxi/Kconfig
arch/arm/mach-tegra/Makefile
arch/arm/mach-tegra/cpuidle-tegra20.c
arch/arm/mach-tegra/platsmp.c
arch/arm/mach-tegra/pm.c
arch/arm/mach-tegra/reset-handler.S
arch/arm/mach-tegra/sleep-tegra20.S
arch/arm/mach-tegra/sleep-tegra30.S
arch/arm/mach-tegra/sleep.S
arch/arm/mach-tegra/tegra.c
arch/arm/mach-w90x900/clock.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/ioremap.c
arch/arm/mm/nommu.c
arch/arm/mm/pageattr.c
arch/arm/net/bpf_jit_32.c
arch/arm/plat-samsung/devs.c
arch/arm/plat-versatile/include/plat/clock.h [deleted file]
arch/arm64/Kconfig.platforms
arch/arm64/Makefile
arch/arm64/boot/dts/allwinner/Makefile
arch/arm64/boot/dts/allwinner/sun50i-a64.dtsi
arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts [new file with mode: 0644]
arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/allwinner/sunxi-h3-h5.dtsi [new symlink]
arch/arm64/boot/dts/amlogic/Makefile
arch/arm64/boot/dts/amlogic/meson-gx-p23x-q20x.dtsi
arch/arm64/boot/dts/amlogic/meson-gx.dtsi
arch/arm64/boot/dts/amlogic/meson-gxbb-nexbox-a95x.dts
arch/arm64/boot/dts/amlogic/meson-gxbb-odroidc2.dts
arch/arm64/boot/dts/amlogic/meson-gxbb-p200.dts
arch/arm64/boot/dts/amlogic/meson-gxbb-p201.dts
arch/arm64/boot/dts/amlogic/meson-gxbb-p20x.dtsi
arch/arm64/boot/dts/amlogic/meson-gxbb-vega-s95.dtsi
arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-hub.dts
arch/arm64/boot/dts/amlogic/meson-gxbb-wetek-play2.dts
arch/arm64/boot/dts/amlogic/meson-gxbb.dtsi
arch/arm64/boot/dts/amlogic/meson-gxl-mali.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/amlogic/meson-gxl-s905d-p230.dts
arch/arm64/boot/dts/amlogic/meson-gxl-s905d.dtsi
arch/arm64/boot/dts/amlogic/meson-gxl-s905x-hwacom-amazetv.dts [new file with mode: 0644]
arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts [new file with mode: 0644]
arch/arm64/boot/dts/amlogic/meson-gxl-s905x-nexbox-a95x.dts
arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dts
arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/amlogic/meson-gxl-s905x.dtsi
arch/arm64/boot/dts/amlogic/meson-gxl.dtsi
arch/arm64/boot/dts/amlogic/meson-gxm-nexbox-a1.dts
arch/arm64/boot/dts/amlogic/meson-gxm-q200.dts
arch/arm64/boot/dts/amlogic/meson-gxm.dtsi
arch/arm64/boot/dts/arm/juno-base.dtsi
arch/arm64/boot/dts/arm/juno-motherboard.dtsi
arch/arm64/boot/dts/arm/juno-r1.dts
arch/arm64/boot/dts/arm/juno-r2.dts
arch/arm64/boot/dts/arm/juno.dts
arch/arm64/boot/dts/broadcom/Makefile
arch/arm64/boot/dts/broadcom/ns2-svk.dts
arch/arm64/boot/dts/broadcom/ns2-xmc.dts
arch/arm64/boot/dts/broadcom/ns2.dtsi
arch/arm64/boot/dts/cavium/Makefile
arch/arm64/boot/dts/cavium/thunder2-99xx.dts [moved from arch/arm64/boot/dts/broadcom/vulcan-eval.dts with 72% similarity]
arch/arm64/boot/dts/cavium/thunder2-99xx.dtsi [moved from arch/arm64/boot/dts/broadcom/vulcan.dtsi with 88% similarity]
arch/arm64/boot/dts/exynos/exynos5433-bus.dtsi
arch/arm64/boot/dts/exynos/exynos5433-tm2-common.dtsi
arch/arm64/boot/dts/exynos/exynos5433-tm2.dts
arch/arm64/boot/dts/exynos/exynos5433-tm2e.dts
arch/arm64/boot/dts/exynos/exynos5433.dtsi
arch/arm64/boot/dts/freescale/Makefile
arch/arm64/boot/dts/freescale/fsl-ls1012a-frdm.dts
arch/arm64/boot/dts/freescale/fsl-ls1012a-qds.dts
arch/arm64/boot/dts/freescale/fsl-ls1012a-rdb.dts
arch/arm64/boot/dts/freescale/fsl-ls1012a.dtsi
arch/arm64/boot/dts/freescale/fsl-ls1043a.dtsi
arch/arm64/boot/dts/freescale/fsl-ls1046a.dtsi
arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts [new file with mode: 0644]
arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts [new file with mode: 0644]
arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/freescale/fsl-ls2080a-qds.dts
arch/arm64/boot/dts/freescale/fsl-ls2080a-rdb.dts
arch/arm64/boot/dts/freescale/fsl-ls2080a.dtsi
arch/arm64/boot/dts/freescale/fsl-ls2088a-qds.dts [new file with mode: 0644]
arch/arm64/boot/dts/freescale/fsl-ls2088a-rdb.dts [new file with mode: 0644]
arch/arm64/boot/dts/freescale/fsl-ls2088a.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/freescale/fsl-ls208xa-qds.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/freescale/fsl-ls208xa-rdb.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/hisilicon/Makefile
arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts
arch/arm64/boot/dts/hisilicon/hi3798cv200-poplar.dts [new file with mode: 0644]
arch/arm64/boot/dts/hisilicon/hi3798cv200.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/hisilicon/hi6220-hikey.dts
arch/arm64/boot/dts/hisilicon/hi6220.dtsi
arch/arm64/boot/dts/hisilicon/hikey960-pinctrl.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/hisilicon/hip07-d05.dts
arch/arm64/boot/dts/hisilicon/hip07.dtsi
arch/arm64/boot/dts/include/dt-bindings [deleted symlink]
arch/arm64/boot/dts/marvell/armada-3720-db.dts
arch/arm64/boot/dts/marvell/armada-37xx.dtsi
arch/arm64/boot/dts/marvell/armada-7040-db.dts
arch/arm64/boot/dts/marvell/armada-8020.dtsi
arch/arm64/boot/dts/marvell/armada-8040-db.dts
arch/arm64/boot/dts/marvell/armada-8040.dtsi
arch/arm64/boot/dts/marvell/armada-ap806.dtsi
arch/arm64/boot/dts/marvell/armada-cp110-master.dtsi
arch/arm64/boot/dts/marvell/armada-cp110-slave.dtsi
arch/arm64/boot/dts/mediatek/mt8173-evb.dts
arch/arm64/boot/dts/nvidia/tegra132.dtsi
arch/arm64/boot/dts/nvidia/tegra186-p2771-0000.dts
arch/arm64/boot/dts/nvidia/tegra186-p3310.dtsi
arch/arm64/boot/dts/nvidia/tegra186.dtsi
arch/arm64/boot/dts/nvidia/tegra210.dtsi
arch/arm64/boot/dts/qcom/apq8016-sbc.dtsi
arch/arm64/boot/dts/qcom/msm8916.dtsi
arch/arm64/boot/dts/qcom/msm8996.dtsi
arch/arm64/boot/dts/qcom/pm8994.dtsi
arch/arm64/boot/dts/renesas/r8a7795-h3ulcb.dts
arch/arm64/boot/dts/renesas/r8a7795-salvator-x.dts
arch/arm64/boot/dts/renesas/r8a7795.dtsi
arch/arm64/boot/dts/renesas/r8a7796-m3ulcb.dts
arch/arm64/boot/dts/renesas/r8a7796-salvator-x.dts
arch/arm64/boot/dts/renesas/r8a7796.dtsi
arch/arm64/boot/dts/rockchip/Makefile
arch/arm64/boot/dts/rockchip/rk3328-evb.dts [new file with mode: 0644]
arch/arm64/boot/dts/rockchip/rk3328.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/rockchip/rk3368-px5-evb.dts
arch/arm64/boot/dts/rockchip/rk3368.dtsi
arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts [new file with mode: 0644]
arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/rockchip/rk3399-opp.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/rockchip/rk3399.dtsi
arch/arm64/boot/dts/socionext/uniphier-ld11-ref.dts
arch/arm64/boot/dts/socionext/uniphier-ld11.dtsi
arch/arm64/boot/dts/socionext/uniphier-ld20-ref.dts
arch/arm64/boot/dts/socionext/uniphier-ld20.dtsi
arch/arm64/boot/dts/sprd/Makefile
arch/arm64/boot/dts/sprd/sc9860.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/sprd/sp9860g-1h10.dts [new file with mode: 0644]
arch/arm64/boot/dts/sprd/whale2.dtsi [new file with mode: 0644]
arch/arm64/boot/dts/zte/zx296718-evb.dts
arch/arm64/boot/dts/zte/zx296718.dtsi
arch/arm64/configs/defconfig
arch/arm64/include/asm/Kbuild
arch/arm64/include/asm/asm-uaccess.h
arch/arm64/include/asm/atomic_ll_sc.h
arch/arm64/include/asm/atomic_lse.h
arch/arm64/include/asm/barrier.h
arch/arm64/include/asm/cacheflush.h
arch/arm64/include/asm/cmpxchg.h
arch/arm64/include/asm/cpufeature.h
arch/arm64/include/asm/io.h
arch/arm64/include/asm/kvm_emulate.h
arch/arm64/include/asm/kvm_host.h
arch/arm64/include/asm/pci.h
arch/arm64/include/asm/uaccess.h
arch/arm64/include/uapi/asm/Kbuild
arch/arm64/include/uapi/asm/kvm.h
arch/arm64/kernel/armv8_deprecated.c
arch/arm64/kernel/cpufeature.c
arch/arm64/kernel/entry.S
arch/arm64/kernel/hw_breakpoint.c
arch/arm64/kernel/module.c
arch/arm64/kernel/perf_event.c
arch/arm64/kernel/traps.c
arch/arm64/kvm/Makefile
arch/arm64/kvm/hyp/Makefile
arch/arm64/kvm/sys_regs.c
arch/arm64/mm/dma-mapping.c
arch/arm64/mm/pageattr.c
arch/arm64/net/bpf_jit_comp.c
arch/blackfin/include/uapi/asm/Kbuild
arch/c6x/include/uapi/asm/Kbuild
arch/cris/arch-v32/drivers/Kconfig
arch/cris/arch-v32/drivers/pci/bios.c
arch/cris/boot/dts/include/dt-bindings [deleted symlink]
arch/cris/include/arch-v10/arch/Kbuild [deleted file]
arch/cris/include/arch-v32/arch/Kbuild [deleted file]
arch/cris/include/asm/pci.h
arch/cris/include/uapi/arch-v10/arch/Kbuild [deleted file]
arch/cris/include/uapi/arch-v32/arch/Kbuild [deleted file]
arch/cris/include/uapi/asm/Kbuild
arch/frv/include/uapi/asm/Kbuild
arch/frv/kernel/asm-offsets.c
arch/h8300/include/uapi/asm/Kbuild
arch/h8300/include/uapi/asm/bitsperlong.h [moved from arch/h8300/include/asm/bitsperlong.h with 67% similarity]
arch/hexagon/include/asm/Kbuild
arch/hexagon/include/uapi/asm/Kbuild
arch/ia64/include/asm/pci.h
arch/ia64/include/uapi/asm/Kbuild
arch/ia64/kernel/Makefile
arch/ia64/kernel/Makefile.gate
arch/ia64/kernel/crash.c
arch/ia64/pci/pci.c
arch/m32r/include/uapi/asm/Kbuild
arch/m68k/ifpsp060/src/ilsp.S
arch/m68k/ifpsp060/src/isp.S
arch/m68k/include/uapi/asm/Kbuild
arch/metag/boot/dts/include/dt-bindings [deleted symlink]
arch/metag/include/asm/uaccess.h
arch/metag/include/uapi/asm/Kbuild
arch/metag/lib/usercopy.c
arch/metag/mm/mmu-meta1.c
arch/microblaze/include/asm/pci.h
arch/microblaze/include/uapi/asm/Kbuild
arch/microblaze/pci/pci-common.c
arch/mips/Kbuild
arch/mips/Kconfig
arch/mips/Kconfig.debug
arch/mips/boot/dts/include/dt-bindings [deleted symlink]
arch/mips/cavium-octeon/Kconfig
arch/mips/cavium-octeon/Platform
arch/mips/cavium-octeon/executive/cvmx-helper-rgmii.c
arch/mips/cavium-octeon/executive/cvmx-l2c.c
arch/mips/cavium-octeon/executive/octeon-model.c
arch/mips/cavium-octeon/octeon-platform.c
arch/mips/cavium-octeon/setup.c
arch/mips/configs/generic_defconfig
arch/mips/dec/prom/init.c
arch/mips/include/asm/cache.h
arch/mips/include/asm/cpu-info.h
arch/mips/include/asm/cpufeature.h [new file with mode: 0644]
arch/mips/include/asm/mach-rm/cpu-feature-overrides.h
arch/mips/include/asm/octeon/cvmx-helper-rgmii.h
arch/mips/include/asm/octeon/cvmx-l2c-defs.h
arch/mips/include/asm/octeon/cvmx-l2c.h
arch/mips/include/asm/octeon/cvmx-l2d-defs.h [deleted file]
arch/mips/include/asm/octeon/cvmx-l2t-defs.h
arch/mips/include/asm/octeon/cvmx-pciercx-defs.h
arch/mips/include/asm/octeon/cvmx-sli-defs.h
arch/mips/include/asm/octeon/cvmx.h
arch/mips/include/asm/pci.h
arch/mips/include/asm/pgalloc.h
arch/mips/include/asm/pgtable-64.h
arch/mips/include/asm/uasm.h
arch/mips/include/uapi/asm/Kbuild
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/mips-r2-to-r6-emul.c
arch/mips/kernel/perf_event_mipsxx.c
arch/mips/kernel/process.c
arch/mips/kernel/r4k_switch.S
arch/mips/kernel/smp-cps.c
arch/mips/kernel/smp-mt.c
arch/mips/kernel/smp.c
arch/mips/kernel/traps.c
arch/mips/lantiq/irq.c
arch/mips/math-emu/cp1emu.c
arch/mips/mm/fault.c
arch/mips/mm/init.c
arch/mips/mm/pgtable-64.c
arch/mips/mm/tlbex.c
arch/mips/mm/uasm-mips.c
arch/mips/mm/uasm.c
arch/mips/mti-malta/malta-int.c
arch/mips/net/bpf_jit.c
arch/mips/net/bpf_jit_asm.S
arch/mips/pci/pci.c
arch/mips/pci/pcie-octeon.c
arch/mips/sibyte/bcm1480/setup.c
arch/mips/sibyte/sb1250/setup.c
arch/mn10300/include/asm/pci.h
arch/mn10300/include/uapi/asm/Kbuild
arch/mn10300/unit-asb2305/pci-asb2305.c
arch/nios2/Kconfig
arch/nios2/Kconfig.debug
arch/nios2/Makefile
arch/nios2/boot/.gitignore [new file with mode: 0644]
arch/nios2/boot/dts/10m50_devboard.dts
arch/nios2/include/asm/Kbuild
arch/nios2/include/asm/cacheflush.h
arch/nios2/include/asm/cmpxchg.h [deleted file]
arch/nios2/include/asm/cpuinfo.h
arch/nios2/include/asm/setup.h
arch/nios2/include/asm/uaccess.h
arch/nios2/include/uapi/asm/Kbuild
arch/nios2/kernel/.gitignore [new file with mode: 0644]
arch/nios2/kernel/Makefile
arch/nios2/kernel/cpuinfo.c
arch/nios2/kernel/early_printk.c [deleted file]
arch/nios2/kernel/irq.c
arch/nios2/kernel/prom.c
arch/nios2/kernel/setup.c
arch/nios2/mm/uaccess.c
arch/nios2/platform/Kconfig.platform
arch/openrisc/include/asm/Kbuild
arch/openrisc/include/uapi/asm/Kbuild
arch/parisc/include/asm/pci.h
arch/parisc/include/uapi/asm/Kbuild
arch/parisc/kernel/entry.S
arch/parisc/kernel/module.c
arch/parisc/kernel/pci.c
arch/powerpc/Kconfig
arch/powerpc/Makefile.postlink
arch/powerpc/boot/dts/include/dt-bindings [deleted symlink]
arch/powerpc/include/asm/book3s/64/hash-64k.h
arch/powerpc/include/asm/cpm1.h
arch/powerpc/include/asm/cpu_has_feature.h
arch/powerpc/include/asm/cputable.h
arch/powerpc/include/asm/dt_cpu_ftrs.h [new file with mode: 0644]
arch/powerpc/include/asm/fadump.h
arch/powerpc/include/asm/kvm_book3s_asm.h
arch/powerpc/include/asm/kvm_host.h
arch/powerpc/include/asm/kvm_ppc.h
arch/powerpc/include/asm/machdep.h
arch/powerpc/include/asm/module.h
arch/powerpc/include/asm/page.h
arch/powerpc/include/asm/pci.h
arch/powerpc/include/asm/processor.h
arch/powerpc/include/asm/reg.h
arch/powerpc/include/asm/xive.h
arch/powerpc/include/uapi/asm/Kbuild
arch/powerpc/include/uapi/asm/cputable.h
arch/powerpc/kernel/Makefile
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/crash.c
arch/powerpc/kernel/dt_cpu_ftrs.c [new file with mode: 0644]
arch/powerpc/kernel/exceptions-64e.S
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/fadump.c
arch/powerpc/kernel/idle_book3s.S
arch/powerpc/kernel/kprobes.c
arch/powerpc/kernel/pci-common.c
arch/powerpc/kernel/process.c
arch/powerpc/kernel/prom.c
arch/powerpc/kernel/setup-common.c
arch/powerpc/kernel/setup_64.c
arch/powerpc/kvm/Kconfig
arch/powerpc/kvm/Makefile
arch/powerpc/kvm/book3s.c
arch/powerpc/kvm/book3s_64_vio_hv.c
arch/powerpc/kvm/book3s_hv.c
arch/powerpc/kvm/book3s_hv_builtin.c
arch/powerpc/kvm/book3s_hv_rm_xics.c
arch/powerpc/kvm/book3s_hv_rm_xive.c [new file with mode: 0644]
arch/powerpc/kvm/book3s_hv_rmhandlers.S
arch/powerpc/kvm/book3s_pr_papr.c
arch/powerpc/kvm/book3s_rtas.c
arch/powerpc/kvm/book3s_xics.c
arch/powerpc/kvm/book3s_xics.h
arch/powerpc/kvm/book3s_xive.c [new file with mode: 0644]
arch/powerpc/kvm/book3s_xive.h [new file with mode: 0644]
arch/powerpc/kvm/book3s_xive_template.c [new file with mode: 0644]
arch/powerpc/kvm/irq.h
arch/powerpc/kvm/powerpc.c
arch/powerpc/mm/dump_linuxpagetables.c
arch/powerpc/mm/icswx.c
arch/powerpc/platforms/powernv/eeh-powernv.c
arch/powerpc/platforms/powernv/opal.c
arch/powerpc/platforms/powernv/pci-ioda.c
arch/powerpc/sysdev/cpm1.c
arch/powerpc/sysdev/xive/common.c
arch/powerpc/sysdev/xive/native.c
arch/s390/include/asm/Kbuild
arch/s390/include/asm/debug.h
arch/s390/include/asm/dis.h
arch/s390/include/asm/kprobes.h
arch/s390/include/asm/set_memory.h [moved from arch/s390/include/asm/cacheflush.h with 80% similarity]
arch/s390/include/asm/sysinfo.h
arch/s390/include/uapi/asm/Kbuild
arch/s390/kernel/debug.c
arch/s390/kernel/entry.S
arch/s390/kernel/ftrace.c
arch/s390/kernel/kprobes.c
arch/s390/kernel/machine_kexec.c
arch/s390/kernel/perf_cpum_sf.c
arch/s390/kernel/vmlinux.lds.S
arch/s390/kvm/kvm-s390.c
arch/s390/lib/probes.c
arch/s390/lib/uaccess.c
arch/s390/mm/init.c
arch/s390/mm/pageattr.c
arch/s390/mm/vmem.c
arch/s390/net/bpf_jit_comp.c
arch/score/include/asm/Kbuild
arch/score/include/uapi/asm/Kbuild
arch/sh/Makefile
arch/sh/drivers/pci/pci.c
arch/sh/include/asm/pci.h
arch/sh/include/uapi/asm/Kbuild
arch/sparc/include/asm/hugetlb.h
arch/sparc/include/asm/pci_64.h
arch/sparc/include/asm/pgtable_32.h
arch/sparc/include/asm/setup.h
arch/sparc/include/uapi/asm/Kbuild
arch/sparc/kernel/ftrace.c
arch/sparc/kernel/head_64.S
arch/sparc/kernel/led.c
arch/sparc/kernel/pci.c
arch/sparc/kernel/setup_32.c
arch/sparc/kernel/setup_64.c
arch/sparc/lib/GENbzero.S
arch/sparc/lib/NGbzero.S
arch/sparc/mm/init_32.c
arch/tile/include/arch/Kbuild [deleted file]
arch/tile/include/asm/Kbuild
arch/tile/include/uapi/arch/Kbuild [deleted file]
arch/tile/include/uapi/asm/Kbuild
arch/um/Kconfig.common
arch/um/kernel/initrd.c
arch/um/kernel/sysrq.c
arch/um/kernel/um_arch.c
arch/um/os-Linux/skas/process.c
arch/unicore32/Makefile
arch/unicore32/include/asm/pci.h
arch/unicore32/include/uapi/asm/Kbuild
arch/unicore32/kernel/pci.c
arch/x86/Makefile
arch/x86/boot/compressed/error.h
arch/x86/boot/compressed/pagetable.c
arch/x86/events/intel/rapl.c
arch/x86/include/asm/asm.h
arch/x86/include/asm/cacheflush.h
arch/x86/include/asm/init.h
arch/x86/include/asm/kvm_host.h
arch/x86/include/asm/pci.h
arch/x86/include/asm/pmem.h
arch/x86/include/asm/set_memory.h [new file with mode: 0644]
arch/x86/include/uapi/asm/Kbuild
arch/x86/kernel/amd_gart_64.c
arch/x86/kernel/cpu/amd.c
arch/x86/kernel/cpu/bugs.c
arch/x86/kernel/cpu/microcode/amd.c
arch/x86/kernel/cpu/microcode/core.c
arch/x86/kernel/cpu/microcode/intel.c
arch/x86/kernel/fpu/init.c
arch/x86/kernel/ftrace.c
arch/x86/kernel/i8259.c
arch/x86/kernel/kprobes/core.c
arch/x86/kernel/kprobes/opt.c
arch/x86/kernel/machine_kexec_32.c
arch/x86/kernel/machine_kexec_64.c
arch/x86/kernel/module.c
arch/x86/kernel/setup.c
arch/x86/kernel/setup_percpu.c
arch/x86/kernel/tboot.c
arch/x86/kvm/emulate.c
arch/x86/kvm/lapic.c
arch/x86/kvm/mmu.c
arch/x86/kvm/mmu.h
arch/x86/kvm/page_track.c
arch/x86/kvm/paging_tmpl.h
arch/x86/kvm/pmu_intel.c
arch/x86/kvm/svm.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/lib/csum-copy_64.S
arch/x86/lib/kaslr.c
arch/x86/mm/ident_map.c
arch/x86/mm/init.c
arch/x86/mm/init_32.c
arch/x86/mm/init_64.c
arch/x86/mm/ioremap.c
arch/x86/mm/numa_32.c
arch/x86/mm/pageattr.c
arch/x86/mm/testmmiotrace.c
arch/x86/net/bpf_jit_comp.c
arch/x86/pci/i386.c
arch/x86/pci/pcbios.c
arch/x86/platform/efi/efi.c
arch/x86/power/hibernate_64.c
arch/x86/realmode/init.c
arch/x86/um/ptrace_64.c
arch/x86/um/shared/sysdep/kernel-offsets.h
arch/x86/xen/enlighten_pv.c
arch/x86/xen/mmu.c
arch/x86/xen/mmu_pv.c
arch/x86/xen/time.c
arch/xtensa/include/asm/pci.h
arch/xtensa/include/uapi/asm/Kbuild
arch/xtensa/kernel/pci.c
block/Kconfig
block/bfq-iosched.c
block/bfq-wf2q.c
block/blk-core.c
block/blk-mq.c
block/blk-stat.c
block/elevator.c
certs/blacklist.c
crypto/lzo.c
drivers/Kconfig
drivers/Makefile
drivers/acpi/Makefile
drivers/acpi/acpi_apd.c
drivers/acpi/acpi_lpss.c
drivers/acpi/acpica/Makefile
drivers/acpi/acpica/acconvert.h [new file with mode: 0644]
drivers/acpi/acpica/acglobal.h
drivers/acpi/acpica/aclocal.h
drivers/acpi/acpica/acmacros.h
drivers/acpi/acpica/acopcode.h
drivers/acpi/acpica/amlcode.h
drivers/acpi/acpica/dbmethod.c
drivers/acpi/acpica/dbxface.c
drivers/acpi/acpica/dscontrol.c
drivers/acpi/acpica/dsmthdat.c
drivers/acpi/acpica/dsobject.c
drivers/acpi/acpica/dsopcode.c
drivers/acpi/acpica/dsutils.c
drivers/acpi/acpica/dswexec.c
drivers/acpi/acpica/dswload2.c
drivers/acpi/acpica/exmisc.c
drivers/acpi/acpica/exnames.c
drivers/acpi/acpica/exoparg1.c
drivers/acpi/acpica/exoparg2.c
drivers/acpi/acpica/exoparg6.c
drivers/acpi/acpica/exresolv.c
drivers/acpi/acpica/exstore.c
drivers/acpi/acpica/exstoren.c
drivers/acpi/acpica/hwvalid.c
drivers/acpi/acpica/nsaccess.c
drivers/acpi/acpica/nsrepair.c
drivers/acpi/acpica/nsrepair2.c
drivers/acpi/acpica/nsutils.c
drivers/acpi/acpica/psargs.c
drivers/acpi/acpica/psloop.c
drivers/acpi/acpica/psobject.c
drivers/acpi/acpica/psopcode.c
drivers/acpi/acpica/psopinfo.c
drivers/acpi/acpica/psparse.c
drivers/acpi/acpica/pstree.c
drivers/acpi/acpica/psutils.c
drivers/acpi/acpica/utalloc.c
drivers/acpi/acpica/utcache.c
drivers/acpi/acpica/utdebug.c
drivers/acpi/acpica/utresrc.c
drivers/acpi/acpica/utxferror.c
drivers/acpi/apei/erst.c
drivers/acpi/arm64/iort.c
drivers/acpi/battery.c
drivers/acpi/bus.c
drivers/acpi/button.c
drivers/acpi/cppc_acpi.c
drivers/acpi/device_pm.c
drivers/acpi/glue.c
drivers/acpi/pci_mcfg.c
drivers/acpi/pmic/intel_pmic_xpower.c
drivers/acpi/power.c
drivers/acpi/scan.c
drivers/acpi/sleep.c
drivers/acpi/sleep.h
drivers/acpi/x86/utils.c [new file with mode: 0644]
drivers/ata/Kconfig
drivers/ata/Makefile
drivers/ata/pata_bk3710.c [new file with mode: 0644]
drivers/base/dd.c
drivers/base/dma-mapping.c
drivers/base/power/domain.c
drivers/base/power/main.c
drivers/base/power/wakeup.c
drivers/base/soc.c
drivers/block/drbd/drbd_bitmap.c
drivers/block/nbd.c
drivers/block/rbd.c
drivers/block/virtio_blk.c
drivers/char/agp/amd-k7-agp.c
drivers/char/agp/ati-agp.c
drivers/char/agp/generic.c
drivers/char/agp/intel-gtt.c
drivers/char/agp/sworks-agp.c
drivers/char/applicom.c
drivers/char/dsp56k.c
drivers/char/ipmi/ipmi_si_intf.c
drivers/char/mwave/mwavedd.c
drivers/char/virtio_console.c
drivers/clk/Kconfig
drivers/clk/Makefile
drivers/clk/at91/clk-pll.c
drivers/clk/bcm/clk-iproc-pll.c
drivers/clk/bcm/clk-ns2.c
drivers/clk/clk-cs2000-cp.c
drivers/clk/clk-hi655x.c [new file with mode: 0644]
drivers/clk/clk-nomadik.c
drivers/clk/clk-si5351.c
drivers/clk/clk-stm32f4.c
drivers/clk/clk-versaclock5.c
drivers/clk/clk.c
drivers/clk/hisilicon/clk-hi3620.c
drivers/clk/hisilicon/clk-hi6220.c
drivers/clk/hisilicon/clk.c
drivers/clk/imx/clk-imx6ul.c
drivers/clk/imx/clk-imx7d.c
drivers/clk/mediatek/Kconfig
drivers/clk/mediatek/Makefile
drivers/clk/mediatek/clk-mt2701-eth.c
drivers/clk/mediatek/clk-mt6797-img.c [new file with mode: 0644]
drivers/clk/mediatek/clk-mt6797-mm.c [new file with mode: 0644]
drivers/clk/mediatek/clk-mt6797-vdec.c [new file with mode: 0644]
drivers/clk/mediatek/clk-mt6797-venc.c [new file with mode: 0644]
drivers/clk/mediatek/clk-mt6797.c [new file with mode: 0644]
drivers/clk/meson/Makefile
drivers/clk/meson/clk-audio-divider.c [new file with mode: 0644]
drivers/clk/meson/clk-mpll.c
drivers/clk/meson/clk-pll.c
drivers/clk/meson/clkc.h
drivers/clk/meson/gxbb.c
drivers/clk/meson/gxbb.h
drivers/clk/meson/meson8b.c
drivers/clk/meson/meson8b.h
drivers/clk/mvebu/clk-cpu.c
drivers/clk/mvebu/common.c
drivers/clk/qcom/clk-smd-rpm.c
drivers/clk/qcom/common.c
drivers/clk/qcom/mmcc-msm8996.c
drivers/clk/renesas/r8a7795-cpg-mssr.c
drivers/clk/renesas/r8a7796-cpg-mssr.c
drivers/clk/renesas/rcar-gen3-cpg.c
drivers/clk/renesas/rcar-gen3-cpg.h
drivers/clk/renesas/renesas-cpg-mssr.c
drivers/clk/renesas/renesas-cpg-mssr.h
drivers/clk/rockchip/Makefile
drivers/clk/rockchip/clk-pll.c
drivers/clk/rockchip/clk-rk3328.c
drivers/clk/rockchip/clk-rk3368.c
drivers/clk/rockchip/clk-rk3399.c
drivers/clk/rockchip/clk-rv1108.c [moved from drivers/clk/rockchip/clk-rk1108.c with 57% similarity]
drivers/clk/rockchip/clk.h
drivers/clk/spear/spear6xx_clock.c
drivers/clk/sunxi-ng/Kconfig
drivers/clk/sunxi-ng/Makefile
drivers/clk/sunxi-ng/ccu-sun5i.c
drivers/clk/sunxi-ng/ccu-sun8i-a33.c
drivers/clk/sunxi-ng/ccu-sun8i-h3.c
drivers/clk/sunxi-ng/ccu-sun8i-h3.h
drivers/clk/sunxi-ng/ccu-sun8i-r.c [new file with mode: 0644]
drivers/clk/sunxi-ng/ccu-sun8i-r.h [new file with mode: 0644]
drivers/clk/sunxi-ng/ccu-sun9i-a80.c
drivers/clk/sunxi-ng/ccu_common.c
drivers/clk/sunxi-ng/ccu_gate.c
drivers/clk/sunxi-ng/ccu_mult.c
drivers/clk/sunxi-ng/ccu_mult.h
drivers/clk/sunxi-ng/ccu_nk.c
drivers/clk/sunxi-ng/ccu_nkm.c
drivers/clk/sunxi-ng/ccu_nkmp.c
drivers/clk/sunxi-ng/ccu_nm.c
drivers/clk/tegra/clk-id.h
drivers/clk/tegra/clk-periph-gate.c
drivers/clk/tegra/clk-periph.c
drivers/clk/tegra/clk-pll.c
drivers/clk/tegra/clk-super.c
drivers/clk/tegra/clk-tegra-audio.c
drivers/clk/tegra/clk-tegra-periph.c
drivers/clk/tegra/clk-tegra-pmc.c
drivers/clk/tegra/clk-tegra114.c
drivers/clk/tegra/clk-tegra124.c
drivers/clk/tegra/clk-tegra210.c
drivers/clk/tegra/clk-tegra30.c
drivers/clk/tegra/clk.c
drivers/clk/tegra/clk.h
drivers/clk/ti/apll.c
drivers/clk/ti/autoidle.c
drivers/clk/ti/clk-3xxx.c
drivers/clk/ti/clk-44xx.c
drivers/clk/ti/clk-dra7-atl.c
drivers/clk/ti/clk.c
drivers/clk/ti/clkt_dflt.c
drivers/clk/ti/clkt_dpll.c
drivers/clk/ti/clkt_iclk.c
drivers/clk/ti/clock.h
drivers/clk/ti/clockdomain.c
drivers/clk/ti/composite.c
drivers/clk/ti/divider.c
drivers/clk/ti/dpll.c
drivers/clk/ti/dpll3xxx.c
drivers/clk/ti/dpll44xx.c
drivers/clk/ti/fixed-factor.c
drivers/clk/ti/gate.c
drivers/clk/ti/interface.c
drivers/clk/ti/mux.c
drivers/clk/versatile/Kconfig
drivers/clk/versatile/Makefile
drivers/clk/versatile/clk-icst.c
drivers/clk/versatile/clk-icst.h
drivers/clk/versatile/clk-impd1.c
drivers/clk/versatile/clk-realview.c
drivers/clk/versatile/clk-versatile.c
drivers/clk/versatile/icst.c [moved from arch/arm/common/icst.c with 98% similarity]
drivers/clk/versatile/icst.h [moved from arch/arm/include/asm/hardware/icst.h with 94% similarity]
drivers/clk/x86/clk-pmc-atom.c
drivers/clk/zte/clk-zx296718.c
drivers/clk/zte/clk.c
drivers/clk/zte/clk.h
drivers/clocksource/arm_arch_timer.c
drivers/clocksource/cs5535-clockevt.c
drivers/cpufreq/loongson2_cpufreq.c
drivers/cpufreq/powernow-k8.c
drivers/cpufreq/speedstep-smi.c
drivers/cpufreq/sti-cpufreq.c
drivers/cpuidle/cpuidle.c
drivers/crypto/virtio/virtio_crypto_core.c
drivers/dax/Kconfig
drivers/dax/super.c
drivers/dma/Kconfig
drivers/dma/amba-pl08x.c
drivers/dma/cppi41.c
drivers/dma/dmatest.c
drivers/dma/imx-sdma.c
drivers/dma/ioat/init.c
drivers/dma/mv_xor.c
drivers/dma/pl330.c
drivers/dma/qcom/hidma.c
drivers/dma/qcom/hidma_ll.c
drivers/dma/sh/rcar-dmac.c
drivers/dma/stm32-dma.c
drivers/dma/sun4i-dma.c
drivers/dma/virt-dma.c
drivers/dma/xilinx/xilinx_dma.c
drivers/edac/amd64_edac.c
drivers/firmware/arm_scpi.c
drivers/firmware/efi/efi-pstore.c
drivers/firmware/meson/meson_sm.c
drivers/firmware/qcom_scm-32.c
drivers/firmware/qcom_scm-64.c
drivers/firmware/qcom_scm.c
drivers/firmware/qcom_scm.h
drivers/firmware/ti_sci.c
drivers/gpio/gpio-104-dio-48e.c
drivers/gpio/gpio-104-idi-48.c
drivers/gpio/gpio-104-idio-16.c
drivers/gpio/gpio-gpio-mm.c
drivers/gpio/gpio-ws16c48.c
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_atombios.c
drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.c
drivers/gpu/drm/amd/amdgpu/amdgpu_atomfirmware.h
drivers/gpu/drm/amd/amdgpu/amdgpu_benchmark.c
drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c
drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_display.c
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c
drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
drivers/gpu/drm/amd/amdgpu/amdgpu_object.c
drivers/gpu/drm/amd/amdgpu/amdgpu_object.h
drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_prime.c
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.h
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
drivers/gpu/drm/amd/amdgpu/amdgpu_sa.c
drivers/gpu/drm/amd/amdgpu/amdgpu_trace.h
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_ucode.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c
drivers/gpu/drm/amd/amdgpu/amdgpu_virt.h
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
drivers/gpu/drm/amd/amdgpu/ci_dpm.c
drivers/gpu/drm/amd/amdgpu/dce_v10_0.c
drivers/gpu/drm/amd/amdgpu/dce_v11_0.c
drivers/gpu/drm/amd/amdgpu/dce_v6_0.c
drivers/gpu/drm/amd/amdgpu/dce_v8_0.c
drivers/gpu/drm/amd/amdgpu/dce_virtual.c
drivers/gpu/drm/amd/amdgpu/gfx_v6_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/gmc_v6_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c
drivers/gpu/drm/amd/amdgpu/gmc_v9_0.c
drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c
drivers/gpu/drm/amd/amdgpu/mmsch_v1_0.h
drivers/gpu/drm/amd/amdgpu/mxgpu_vi.c
drivers/gpu/drm/amd/amdgpu/psp_v3_1.c
drivers/gpu/drm/amd/amdgpu/psp_v3_1.h
drivers/gpu/drm/amd/amdgpu/sdma_v4_0.c
drivers/gpu/drm/amd/amdgpu/soc15.c
drivers/gpu/drm/amd/amdgpu/soc15_common.h
drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
drivers/gpu/drm/amd/amdgpu/vce_v4_0.c
drivers/gpu/drm/amd/include/amd_shared.h
drivers/gpu/drm/amd/include/cgs_common.h
drivers/gpu/drm/amd/powerplay/amd_powerplay.c
drivers/gpu/drm/amd/powerplay/eventmgr/eventsubchains.c
drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.c
drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.h
drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c
drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.c
drivers/gpu/drm/amd/powerplay/hwmgr/ppatomfwctrl.h
drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.c
drivers/gpu/drm/amd/powerplay/hwmgr/smu7_thermal.h
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.h
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_powertune.h
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_processpptables.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.c
drivers/gpu/drm/amd/powerplay/hwmgr/vega10_thermal.h
drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h
drivers/gpu/drm/amd/powerplay/inc/hwmgr.h
drivers/gpu/drm/amd/powerplay/inc/smu9_driver_if.h
drivers/gpu/drm/amd/powerplay/inc/vega10_ppsmc.h
drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.c
drivers/gpu/drm/amd/powerplay/smumgr/vega10_smumgr.h
drivers/gpu/drm/amd/scheduler/gpu_scheduler.c
drivers/gpu/drm/amd/scheduler/gpu_scheduler.h
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/drm_fb_helper.c
drivers/gpu/drm/etnaviv/etnaviv_dump.c
drivers/gpu/drm/gma500/gtt.c
drivers/gpu/drm/gma500/psb_drv.c
drivers/gpu/drm/i915/Kconfig.debug
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_gem_request.h
drivers/gpu/drm/i915/intel_sprite.c
drivers/gpu/drm/i915/selftests/mock_gem_device.c
drivers/gpu/drm/nouveau/nouveau_gem.c
drivers/gpu/drm/nouveau/nv50_display.c
drivers/gpu/drm/nouveau/nvkm/core/object.c
drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramgf100.c
drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c
drivers/gpu/drm/nouveau/nvkm/subdev/therm/fan.c
drivers/gpu/drm/nouveau/nvkm/subdev/therm/fantog.c
drivers/gpu/drm/nouveau/nvkm/subdev/therm/temp.c
drivers/gpu/drm/nouveau/nvkm/subdev/timer/base.c
drivers/gpu/drm/nouveau/nvkm/subdev/timer/nv04.c
drivers/gpu/drm/radeon/cik.c
drivers/gpu/drm/radeon/evergreen.c
drivers/gpu/drm/radeon/r420.c
drivers/gpu/drm/radeon/radeon_cs.c
drivers/gpu/drm/radeon/radeon_gart.c
drivers/gpu/drm/radeon/radeon_object.c
drivers/gpu/drm/radeon/radeon_test.c
drivers/gpu/drm/radeon/radeon_uvd.c
drivers/gpu/drm/radeon/si.c
drivers/gpu/drm/ttm/ttm_bo.c
drivers/gpu/drm/ttm/ttm_page_alloc.c
drivers/gpu/drm/ttm/ttm_page_alloc_dma.c
drivers/gpu/drm/ttm/ttm_tt.c
drivers/gpu/drm/virtio/virtgpu_kms.c
drivers/hwmon/coretemp.c
drivers/hwtracing/intel_th/msu.c
drivers/i2c/busses/i2c-ali15x3.c
drivers/i2c/busses/i2c-designware-platdrv.c
drivers/i2c/busses/i2c-elektor.c
drivers/i2c/busses/i2c-mv64xxx.c
drivers/i2c/busses/i2c-parport-light.c
drivers/i2c/busses/i2c-pca-isa.c
drivers/i2c/busses/i2c-piix4.c
drivers/i2c/busses/i2c-sis5595.c
drivers/i2c/busses/i2c-viapro.c
drivers/i2c/busses/i2c-xgene-slimpro.c
drivers/i2c/busses/scx200_acb.c
drivers/i2c/i2c-mux.c
drivers/i2c/muxes/i2c-mux-reg.c
drivers/ide/ide-io.c
drivers/ide/ide-probe.c
drivers/idle/intel_idle.c
drivers/iio/adc/stx104.c
drivers/iio/dac/cio-dac.c
drivers/infiniband/hw/hfi1/chip.c
drivers/infiniband/hw/hfi1/chip.h
drivers/infiniband/hw/hfi1/driver.c
drivers/infiniband/hw/hfi1/file_ops.c
drivers/infiniband/hw/hfi1/hfi.h
drivers/infiniband/hw/hfi1/init.c
drivers/infiniband/hw/hfi1/intr.c
drivers/infiniband/hw/hfi1/pcie.c
drivers/infiniband/hw/hfi1/qp.c
drivers/infiniband/hw/hfi1/rc.c
drivers/infiniband/hw/hfi1/ruc.c
drivers/infiniband/hw/hfi1/trace_ctxts.h
drivers/infiniband/hw/hfi1/trace_tx.h
drivers/infiniband/hw/hfi1/user_exp_rcv.c
drivers/infiniband/hw/hfi1/user_exp_rcv.h
drivers/infiniband/hw/hfi1/user_sdma.c
drivers/infiniband/hw/hfi1/user_sdma.h
drivers/infiniband/hw/hfi1/verbs.h
drivers/infiniband/hw/hfi1/vnic_main.c
drivers/infiniband/hw/hns/hns_roce_hw_v1.c
drivers/infiniband/hw/hns/hns_roce_mr.c
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/qedr/main.c
drivers/infiniband/hw/qib/qib_fs.c
drivers/infiniband/sw/rxe/rxe_mr.c
drivers/infiniband/sw/rxe/rxe_param.h
drivers/infiniband/sw/rxe/rxe_verbs.c
drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
drivers/infiniband/ulp/srpt/ib_srpt.c
drivers/input/joystick/Kconfig
drivers/input/joystick/Makefile
drivers/input/joystick/psxpad-spi.c [new file with mode: 0644]
drivers/input/joystick/xpad.c
drivers/input/keyboard/cros_ec_keyb.c
drivers/input/mouse/inport.c
drivers/input/mouse/logibm.c
drivers/input/touchscreen/mk712.c
drivers/iommu/amd_iommu_v2.c
drivers/iommu/arm-smmu-v3.c
drivers/iommu/arm-smmu.c
drivers/iommu/dma-iommu.c
drivers/iommu/dmar.c
drivers/iommu/exynos-iommu.c
drivers/iommu/fsl_pamu.h
drivers/iommu/intel-iommu.c
drivers/iommu/intel_irq_remapping.c
drivers/iommu/io-pgtable-arm.c
drivers/iommu/iommu.c
drivers/iommu/iova.c
drivers/iommu/mtk_iommu_v1.c
drivers/iommu/of_iommu.c
drivers/iommu/omap-iommu.c
drivers/iommu/omap-iommu.h
drivers/iommu/rockchip-iommu.c
drivers/iommu/tegra-smmu.c
drivers/irqchip/Kconfig
drivers/irqchip/irq-mips-cpu.c
drivers/isdn/hardware/avm/b1isa.c
drivers/isdn/hardware/avm/t1isa.c
drivers/isdn/hisax/config.c
drivers/leds/leds-lp5521.c
drivers/leds/leds-lp5523.c
drivers/leds/leds-lp5562.c
drivers/md/bcache/super.c
drivers/md/bcache/util.h
drivers/md/dm-bufio.c
drivers/md/dm-cache-background-tracker.c
drivers/md/dm-cache-policy-smq.c
drivers/md/dm-cache-target.c
drivers/md/dm-ioctl.c
drivers/md/dm-mpath.c
drivers/md/dm-rq.c
drivers/md/dm-stats.c
drivers/md/dm-thin-metadata.c
drivers/md/md.c
drivers/md/md.h
drivers/md/persistent-data/dm-space-map-disk.c
drivers/md/raid0.c
drivers/md/raid1.c
drivers/md/raid10.c
drivers/md/raid5-cache.c
drivers/md/raid5-log.h
drivers/md/raid5.c
drivers/media/dvb-frontends/drx39xyj/drx_dap_fasi.h
drivers/media/pci/zoran/zoran_card.c
drivers/media/platform/mtk-vpu/mtk_vpu.c
drivers/media/platform/omap3isp/isp.c
drivers/media/platform/omap3isp/isp.h
drivers/media/rc/serial_ir.c
drivers/memory/Kconfig
drivers/memory/omap-gpmc.c
drivers/misc/Kconfig
drivers/misc/Makefile
drivers/misc/c2port/c2port-duramar2150.c
drivers/misc/dummy-irq.c
drivers/misc/mic/vop/vop_main.c
drivers/misc/pci_endpoint_test.c [new file with mode: 0644]
drivers/misc/sram-exec.c
drivers/misc/vmw_vmci/vmci_queue_pair.c
drivers/mmc/host/wbsd.c
drivers/mtd/chips/cfi_cmdset_0002.c
drivers/mtd/maps/Makefile
drivers/mtd/maps/physmap_of_core.c [moved from drivers/mtd/maps/physmap_of.c with 96% similarity]
drivers/mtd/mtdswap.c
drivers/mtd/nand/Kconfig
drivers/mtd/nand/Makefile
drivers/mtd/nand/atmel/Makefile [new file with mode: 0644]
drivers/mtd/nand/atmel/nand-controller.c [new file with mode: 0644]
drivers/mtd/nand/atmel/pmecc.c [new file with mode: 0644]
drivers/mtd/nand/atmel/pmecc.h [new file with mode: 0644]
drivers/mtd/nand/atmel_nand.c [deleted file]
drivers/mtd/nand/atmel_nand_ecc.h [deleted file]
drivers/mtd/nand/atmel_nand_nfc.h [deleted file]
drivers/mtd/nand/brcmnand/brcmnand.c
drivers/mtd/nand/cmx270_nand.c
drivers/mtd/nand/davinci_nand.c
drivers/mtd/nand/denali.c
drivers/mtd/nand/denali.h
drivers/mtd/nand/denali_dt.c
drivers/mtd/nand/fsmc_nand.c
drivers/mtd/nand/gpio.c
drivers/mtd/nand/nand_amd.c [new file with mode: 0644]
drivers/mtd/nand/nand_base.c
drivers/mtd/nand/nand_hynix.c [new file with mode: 0644]
drivers/mtd/nand/nand_ids.c
drivers/mtd/nand/nand_macronix.c [new file with mode: 0644]
drivers/mtd/nand/nand_micron.c [new file with mode: 0644]
drivers/mtd/nand/nand_samsung.c [new file with mode: 0644]
drivers/mtd/nand/nand_toshiba.c [new file with mode: 0644]
drivers/mtd/nand/nandsim.c
drivers/mtd/nand/omap2.c
drivers/mtd/nand/orion_nand.c
drivers/mtd/nand/oxnas_nand.c
drivers/mtd/nand/sunxi_nand.c
drivers/mtd/nand/tango_nand.c
drivers/mtd/ofpart.c
drivers/mtd/spi-nor/Kconfig
drivers/mtd/spi-nor/Makefile
drivers/mtd/spi-nor/hisi-sfc.c
drivers/mtd/spi-nor/intel-spi.c
drivers/mtd/spi-nor/mtk-quadspi.c
drivers/mtd/spi-nor/spi-nor.c
drivers/mtd/spi-nor/stm32-quadspi.c [new file with mode: 0644]
drivers/mtd/ubi/build.c
drivers/mtd/ubi/debug.c
drivers/mtd/ubi/fastmap.c
drivers/net/appletalk/cops.c
drivers/net/appletalk/ltpc.c
drivers/net/arcnet/com20020-isa.c
drivers/net/arcnet/com90io.c
drivers/net/arcnet/com90xx.c
drivers/net/bonding/bond_netlink.c
drivers/net/caif/caif_virtio.c
drivers/net/can/cc770/cc770_isa.c
drivers/net/can/rcar/rcar_canfd.c
drivers/net/can/sja1000/sja1000_isa.c
drivers/net/dsa/dsa_loop.c
drivers/net/dsa/mv88e6xxx/chip.c
drivers/net/ethernet/3com/3c509.c
drivers/net/ethernet/3com/3c59x.c
drivers/net/ethernet/8390/ne.c
drivers/net/ethernet/8390/smc-ultra.c
drivers/net/ethernet/8390/wd.c
drivers/net/ethernet/amd/amd8111e.h
drivers/net/ethernet/amd/atarilance.c
drivers/net/ethernet/amd/declance.c
drivers/net/ethernet/amd/lance.c
drivers/net/ethernet/amd/ni65.c
drivers/net/ethernet/amd/sun3lance.c
drivers/net/ethernet/aquantia/atlantic/aq_nic.c
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_a0.c
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c
drivers/net/ethernet/atheros/alx/main.c
drivers/net/ethernet/atheros/atl1c/atl1c_hw.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c
drivers/net/ethernet/broadcom/bnxt/bnxt.c
drivers/net/ethernet/broadcom/bnxt/bnxt_dcb.c
drivers/net/ethernet/broadcom/sb1250-mac.c
drivers/net/ethernet/brocade/bna/bfa_ioc.c
drivers/net/ethernet/brocade/bna/bnad_ethtool.c
drivers/net/ethernet/chelsio/cxgb3/cxgb3_defs.h
drivers/net/ethernet/chelsio/cxgb3/cxgb3_offload.c
drivers/net/ethernet/chelsio/cxgb3/l2t.c
drivers/net/ethernet/chelsio/cxgb3/l2t.h
drivers/net/ethernet/chelsio/cxgb4/clip_tbl.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
drivers/net/ethernet/chelsio/cxgb4/cxgb4_debugfs.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_ethtool.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c
drivers/net/ethernet/chelsio/cxgb4/l2t.c
drivers/net/ethernet/chelsio/cxgb4/sched.c
drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
drivers/net/ethernet/chelsio/cxgb4/t4fw_api.h
drivers/net/ethernet/chelsio/cxgb4/t4fw_version.h
drivers/net/ethernet/cirrus/cs89x0.c
drivers/net/ethernet/cirrus/mac89x0.c
drivers/net/ethernet/dec/tulip/de4x5.c
drivers/net/ethernet/faraday/ftmac100.c
drivers/net/ethernet/freescale/ucc_geth.c
drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.h
drivers/net/ethernet/hp/hp100.c
drivers/net/ethernet/intel/igb/e1000_phy.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/mellanox/mlx4/cmd.c
drivers/net/ethernet/mellanox/mlx4/en_ethtool.c
drivers/net/ethernet/mellanox/mlx4/en_rx.c
drivers/net/ethernet/mellanox/mlx4/en_tx.c
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx4/mr.c
drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
drivers/net/ethernet/mellanox/mlx5/core/Kconfig
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c
drivers/net/ethernet/mellanox/mlx5/core/en_fs.c
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h
drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
drivers/net/ethernet/mellanox/mlx5/core/fs_core.h
drivers/net/ethernet/mellanox/mlx5/core/ipoib.c
drivers/net/ethernet/mellanox/mlx5/core/ipoib.h
drivers/net/ethernet/mellanox/mlxsw/spectrum_dpipe.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c
drivers/net/ethernet/mellanox/mlxsw/spectrum_switchdev.c
drivers/net/ethernet/natsemi/sonic.h
drivers/net/ethernet/qlogic/netxen/netxen_nic_ctx.c
drivers/net/ethernet/qlogic/qed/qed_cxt.c
drivers/net/ethernet/qlogic/qed/qed_dev.c
drivers/net/ethernet/qlogic/qed/qed_init_fw_funcs.c
drivers/net/ethernet/qlogic/qed/qed_int.c
drivers/net/ethernet/qlogic/qed/qed_main.c
drivers/net/ethernet/qlogic/qed/qed_sriov.c
drivers/net/ethernet/qlogic/qede/qede_filter.c
drivers/net/ethernet/qlogic/qede/qede_main.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic.h
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_hw.h
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ethtool.c
drivers/net/ethernet/qlogic/qlge/qlge_dbg.c
drivers/net/ethernet/qualcomm/qca_spi.c
drivers/net/ethernet/realtek/atp.c
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c
drivers/net/ethernet/sfc/nic.h
drivers/net/ethernet/smsc/smc9194.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_pci.c
drivers/net/ethernet/sun/ldmvsw.c
drivers/net/ethernet/ti/cpsw.c
drivers/net/ethernet/ti/netcp_core.c
drivers/net/ethernet/ti/netcp_ethss.c
drivers/net/ethernet/toshiba/tc35815.c
drivers/net/fddi/defxx.c
drivers/net/hamradio/baycom_epp.c
drivers/net/hamradio/baycom_par.c
drivers/net/hamradio/baycom_ser_fdx.c
drivers/net/hamradio/baycom_ser_hdx.c
drivers/net/hamradio/dmascc.c
drivers/net/hamradio/yam.c
drivers/net/hippi/rrunner.c
drivers/net/irda/ali-ircc.c
drivers/net/irda/irda-usb.c
drivers/net/irda/nsc-ircc.c
drivers/net/irda/smsc-ircc2.c
drivers/net/irda/w83977af_ir.c
drivers/net/macvlan.c
drivers/net/phy/mdio-mux-bcm-iproc.c
drivers/net/phy/mdio-mux.c
drivers/net/phy/mdio_bus.c
drivers/net/usb/cdc_ncm.c
drivers/net/usb/ch9200.c
drivers/net/usb/qmi_wwan.c
drivers/net/virtio_net.c
drivers/net/vmxnet3/vmxnet3_drv.c
drivers/net/vrf.c
drivers/net/wan/cosa.c
drivers/net/wan/hostess_sv11.c
drivers/net/wan/sbni.c
drivers/net/wan/sealevel.c
drivers/net/wimax/i2400m/i2400m-usb.h
drivers/net/wireless/ath/ath9k/ar9003_mac.c
drivers/net/wireless/ath/ath9k/mac.c
drivers/net/wireless/cisco/airo.c
drivers/net/wireless/intel/iwlegacy/4965-mac.c
drivers/net/wireless/intel/iwlwifi/dvm/rx.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/xen-netfront.c
drivers/nvdimm/blk.c
drivers/nvdimm/btt.c
drivers/nvdimm/btt_devs.c
drivers/nvdimm/claim.c
drivers/nvdimm/dimm_devs.c
drivers/nvdimm/nd.h
drivers/nvdimm/pfn_devs.c
drivers/nvme/host/lightnvm.c
drivers/nvme/host/pci.c
drivers/nvmem/meson-efuse.c
drivers/of/device.c
drivers/of/fdt.c
drivers/of/of_pci.c
drivers/of/of_reserved_mem.c
drivers/of/platform.c
drivers/parport/parport_pc.c
drivers/pci/Kconfig
drivers/pci/Makefile
drivers/pci/access.c
drivers/pci/dwc/Kconfig
drivers/pci/dwc/Makefile
drivers/pci/dwc/pci-dra7xx.c
drivers/pci/dwc/pci-exynos.c
drivers/pci/dwc/pci-imx6.c
drivers/pci/dwc/pci-keystone-dw.c
drivers/pci/dwc/pci-layerscape.c
drivers/pci/dwc/pcie-armada8k.c
drivers/pci/dwc/pcie-artpec6.c
drivers/pci/dwc/pcie-designware-ep.c [new file with mode: 0644]
drivers/pci/dwc/pcie-designware-host.c
drivers/pci/dwc/pcie-designware-plat.c
drivers/pci/dwc/pcie-designware.c
drivers/pci/dwc/pcie-designware.h
drivers/pci/dwc/pcie-hisi.c
drivers/pci/dwc/pcie-qcom.c
drivers/pci/dwc/pcie-spear13xx.c
drivers/pci/ecam.c
drivers/pci/endpoint/Kconfig [new file with mode: 0644]
drivers/pci/endpoint/Makefile [new file with mode: 0644]
drivers/pci/endpoint/functions/Kconfig [new file with mode: 0644]
drivers/pci/endpoint/functions/Makefile [new file with mode: 0644]
drivers/pci/endpoint/functions/pci-epf-test.c [new file with mode: 0644]
drivers/pci/endpoint/pci-ep-cfs.c [new file with mode: 0644]
drivers/pci/endpoint/pci-epc-core.c [new file with mode: 0644]
drivers/pci/endpoint/pci-epc-mem.c [new file with mode: 0644]
drivers/pci/endpoint/pci-epf-core.c [new file with mode: 0644]
drivers/pci/host/Kconfig
drivers/pci/host/Makefile
drivers/pci/host/pci-aardvark.c
drivers/pci/host/pci-ftpci100.c [new file with mode: 0644]
drivers/pci/host/pci-host-generic.c
drivers/pci/host/pci-hyperv.c
drivers/pci/host/pci-mvebu.c
drivers/pci/host/pci-tegra.c
drivers/pci/host/pci-thunder-ecam.c
drivers/pci/host/pci-thunder-pem.c
drivers/pci/host/pci-versatile.c
drivers/pci/host/pci-xgene.c
drivers/pci/host/pcie-iproc-platform.c
drivers/pci/host/pcie-rockchip.c
drivers/pci/host/pcie-xilinx-nwl.c
drivers/pci/host/pcie-xilinx.c
drivers/pci/hotplug/cpcihp_generic.c
drivers/pci/hotplug/pciehp_pci.c
drivers/pci/iov.c
drivers/pci/irq.c
drivers/pci/mmap.c [new file with mode: 0644]
drivers/pci/msi.c
drivers/pci/pci-driver.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.c
drivers/pci/pci.h
drivers/pci/pcie/pcie-dpc.c
drivers/pci/probe.c
drivers/pci/proc.c
drivers/pci/quirks.c
drivers/pci/search.c
drivers/pci/setup-bus.c
drivers/pci/setup-res.c
drivers/pci/switch/Kconfig [new file with mode: 0644]
drivers/pci/switch/Makefile [new file with mode: 0644]
drivers/pci/switch/switchtec.c [new file with mode: 0644]
drivers/pcmcia/i82365.c
drivers/pcmcia/tcic.c
drivers/power/supply/Kconfig
drivers/power/supply/Makefile
drivers/power/supply/ab8500_charger.c
drivers/power/supply/axp20x_battery.c [new file with mode: 0644]
drivers/power/supply/bq24190_charger.c
drivers/power/supply/cpcap-charger.c
drivers/power/supply/generic-adc-battery.c
drivers/power/supply/isp1704_charger.c
drivers/power/supply/max17042_battery.c
drivers/power/supply/pda_power.c
drivers/power/supply/power_supply_core.c
drivers/power/supply/rx51_battery.c
drivers/power/supply/sbs-battery.c
drivers/power/supply/twl4030_charger.c
drivers/power/supply/twl4030_madc_battery.c
drivers/powercap/intel_rapl.c
drivers/pwm/Kconfig
drivers/pwm/Makefile
drivers/pwm/pwm-atmel-hlcdc.c
drivers/pwm/pwm-atmel.c
drivers/pwm/pwm-mediatek.c [new file with mode: 0644]
drivers/pwm/pwm-pca9685.c
drivers/pwm/pwm-tegra.c
drivers/remoteproc/remoteproc_virtio.c
drivers/reset/Kconfig
drivers/reset/Makefile
drivers/reset/reset-a10sr.c [new file with mode: 0644]
drivers/reset/reset-ath79.c
drivers/reset/reset-imx7.c [new file with mode: 0644]
drivers/reset/reset-meson.c
drivers/reset/reset-oxnas.c
drivers/reset/reset-pistachio.c
drivers/reset/reset-socfpga.c
drivers/reset/reset-sunxi.c
drivers/reset/reset-uniphier.c
drivers/rpmsg/virtio_rpmsg_bus.c
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/rtc/rtc-bq32k.c
drivers/rtc/rtc-cmos.c
drivers/rtc/rtc-cpcap.c [new file with mode: 0644]
drivers/rtc/rtc-ds1307.c
drivers/rtc/rtc-ds1374.c
drivers/rtc/rtc-ds1672.c
drivers/rtc/rtc-ds3232.c
drivers/rtc/rtc-gemini.c
drivers/rtc/rtc-hid-sensor-time.c
drivers/rtc/rtc-isl1208.c
drivers/rtc/rtc-m41t80.c
drivers/rtc/rtc-omap.c
drivers/rtc/rtc-rs5c372.c
drivers/rtc/rtc-rv3029c2.c
drivers/rtc/rtc-rv8803.c
drivers/rtc/rtc-rx8010.c
drivers/rtc/rtc-rx8581.c
drivers/rtc/rtc-s35390a.c
drivers/rtc/rtc-sh.c
drivers/rtc/rtc-snvs.c
drivers/rtc/rtc-wm8350.c
drivers/s390/cio/ccwgroup.c
drivers/s390/cio/qdio_debug.h
drivers/s390/net/qeth_core.h
drivers/s390/net/qeth_core_main.c
drivers/s390/net/qeth_core_sys.c
drivers/s390/net/qeth_l2.h
drivers/s390/net/qeth_l2_main.c
drivers/s390/net/qeth_l2_sys.c
drivers/s390/net/qeth_l3_main.c
drivers/s390/virtio/kvm_virtio.c
drivers/s390/virtio/virtio_ccw.c
drivers/scsi/aha152x.c
drivers/scsi/aha1542.c
drivers/scsi/g_NCR5380.c
drivers/scsi/gdth.c
drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c
drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.h
drivers/scsi/isci/registers.h
drivers/scsi/iscsi_tcp.c
drivers/scsi/megaraid/megaraid_sas_base.c
drivers/scsi/mpt3sas/mpt3sas_base.h
drivers/scsi/qlogicfas.c
drivers/scsi/virtio_scsi.c
drivers/soc/Kconfig
drivers/soc/Makefile
drivers/soc/atmel/Kconfig [new file with mode: 0644]
drivers/soc/atmel/Makefile [new file with mode: 0644]
drivers/soc/atmel/soc.c [new file with mode: 0644]
drivers/soc/atmel/soc.h [moved from arch/arm/mach-at91/soc.h with 100% similarity]
drivers/soc/bcm/brcmstb/common.c
drivers/soc/fsl/qbman/qman.c
drivers/soc/fsl/qbman/qman_priv.h
drivers/soc/fsl/qe/qe.c
drivers/soc/fsl/qe/qe_tdm.c
drivers/soc/imx/Kconfig [new file with mode: 0644]
drivers/soc/imx/Makefile [new file with mode: 0644]
drivers/soc/imx/gpc.c [new file with mode: 0644]
drivers/soc/imx/gpcv2.c [new file with mode: 0644]
drivers/soc/renesas/r8a7795-sysc.c
drivers/soc/renesas/rcar-sysc.c
drivers/soc/renesas/rcar-sysc.h
drivers/soc/renesas/renesas-soc.c
drivers/soc/samsung/Kconfig
drivers/soc/samsung/Makefile
drivers/soc/samsung/exynos-pmu.c
drivers/soc/samsung/exynos-pmu.h
drivers/soc/tegra/Kconfig
drivers/soc/tegra/Makefile
drivers/soc/tegra/flowctrl.c [moved from arch/arm/mach-tegra/flowctrl.c with 67% similarity]
drivers/soc/tegra/fuse/fuse-tegra.c
drivers/soc/tegra/pmc-tegra186.c [new file with mode: 0644]
drivers/soc/ti/Kconfig
drivers/soc/ti/Makefile
drivers/soc/ti/knav_dma.c
drivers/soc/ti/ti_sci_pm_domains.c [new file with mode: 0644]
drivers/soc/zte/zx296718_pm_domains.c
drivers/soc/zte/zx2967_pm_domains.c
drivers/staging/ccree/ssi_hash.c
drivers/staging/lustre/lnet/libcfs/linux/linux-mem.c
drivers/staging/lustre/lustre/ldlm/ldlm_lockd.c
drivers/staging/lustre/lustre/llite/llite_lib.c
drivers/staging/lustre/lustre/osc/osc_io.c
drivers/staging/media/atomisp/pci/atomisp2/hmm/hmm_bo.c
drivers/staging/media/atomisp/pci/atomisp2/hmm/hmm_dynamic_pool.c
drivers/staging/media/atomisp/pci/atomisp2/hmm/hmm_reserved_pool.c
drivers/staging/media/atomisp/pci/atomisp2/mmu/isp_mmu.c
drivers/staging/most/mostcore/core.c
drivers/staging/speakup/speakup_acntpc.c
drivers/staging/speakup/speakup_dtlk.c
drivers/staging/speakup/speakup_keypc.c
drivers/staging/vme/devices/vme_pio2_core.c
drivers/target/iscsi/iscsi_target.c
drivers/target/iscsi/iscsi_target_configfs.c
drivers/target/iscsi/iscsi_target_login.c
drivers/target/target_core_configfs.c
drivers/target/target_core_device.c
drivers/target/target_core_file.c
drivers/target/target_core_iblock.c
drivers/target/target_core_iblock.h
drivers/target/target_core_pr.c
drivers/target/target_core_pr.h
drivers/target/target_core_pscsi.c
drivers/target/target_core_rd.c
drivers/target/target_core_sbc.c
drivers/target/target_core_tpg.c
drivers/target/target_core_transport.c
drivers/target/target_core_user.c
drivers/tee/Kconfig [new file with mode: 0644]
drivers/tee/Makefile [new file with mode: 0644]
drivers/tee/optee/Kconfig [new file with mode: 0644]
drivers/tee/optee/Makefile [new file with mode: 0644]
drivers/tee/optee/call.c [new file with mode: 0644]
drivers/tee/optee/core.c [new file with mode: 0644]
drivers/tee/optee/optee_msg.h [new file with mode: 0644]
drivers/tee/optee/optee_private.h [new file with mode: 0644]
drivers/tee/optee/optee_smc.h [new file with mode: 0644]
drivers/tee/optee/rpc.c [new file with mode: 0644]
drivers/tee/optee/supp.c [new file with mode: 0644]
drivers/tee/tee_core.c [new file with mode: 0644]
drivers/tee/tee_private.h [new file with mode: 0644]
drivers/tee/tee_shm.c [new file with mode: 0644]
drivers/tee/tee_shm_pool.c [new file with mode: 0644]
drivers/thermal/Kconfig
drivers/thermal/Makefile
drivers/thermal/broadcom/Kconfig [new file with mode: 0644]
drivers/thermal/broadcom/Makefile [new file with mode: 0644]
drivers/thermal/broadcom/bcm2835_thermal.c [new file with mode: 0644]
drivers/thermal/broadcom/ns-thermal.c [new file with mode: 0644]
drivers/thermal/da9062-thermal.c [new file with mode: 0644]
drivers/thermal/devfreq_cooling.c
drivers/thermal/intel_soc_dts_thermal.c
drivers/thermal/mtk_thermal.c
drivers/thermal/rcar_gen3_thermal.c
drivers/thermal/thermal_core.c
drivers/thermal/ti-soc-thermal/dra752-thermal-data.c
drivers/thermal/ti-soc-thermal/omap3-thermal-data.c
drivers/thermal/ti-soc-thermal/omap4-thermal-data.c
drivers/thermal/ti-soc-thermal/omap5-thermal-data.c
drivers/thermal/ti-soc-thermal/ti-bandgap.h
drivers/thermal/ti-soc-thermal/ti-thermal-common.c
drivers/thermal/ti-soc-thermal/ti-thermal.h
drivers/tty/Makefile
drivers/tty/cyclades.c
drivers/tty/hvc/hvc_console.c
drivers/tty/hvc/hvcs.c
drivers/tty/moxa.c
drivers/tty/mxser.c
drivers/tty/n_gsm.c
drivers/tty/n_hdlc.c
drivers/tty/pty.c
drivers/tty/rocket.c
drivers/tty/serdev/core.c
drivers/tty/serial/8250/8250_core.c
drivers/tty/serial/8250/8250_dw.c
drivers/tty/serial/8250/8250_early.c
drivers/tty/serial/8250/8250_exar.c
drivers/tty/serial/8250/8250_fintek.c
drivers/tty/serial/8250/8250_lpss.c
drivers/tty/serial/8250/8250_port.c
drivers/tty/serial/Kconfig
drivers/tty/serial/Makefile
drivers/tty/serial/altera_jtaguart.c
drivers/tty/serial/altera_uart.c
drivers/tty/serial/amba-pl011.c
drivers/tty/serial/atmel_serial.c
drivers/tty/serial/atmel_serial.h [moved from include/linux/atmel_serial.h with 100% similarity]
drivers/tty/serial/fsl_lpuart.c
drivers/tty/serial/imx.c
drivers/tty/serial/omap-serial.c
drivers/tty/serial/samsung.c
drivers/tty/serial/sb1250-duart.c
drivers/tty/serial/serial_core.c
drivers/tty/serial/sh-sci.c
drivers/tty/serial/sprd_serial.c
drivers/tty/serial/st-asc.c
drivers/tty/serial/uartlite.c
drivers/tty/serial/xilinx_uartps.c
drivers/tty/synclink.c
drivers/tty/tty_baudrate.c [new file with mode: 0644]
drivers/tty/tty_io.c
drivers/tty/tty_ioctl.c
drivers/tty/tty_jobctrl.c [new file with mode: 0644]
drivers/tty/vt/selection.c
drivers/tty/vt/vt.c
drivers/vhost/net.c
drivers/vhost/vhost.c
drivers/vhost/vsock.c
drivers/video/Makefile
drivers/video/console/Kconfig
drivers/video/fbdev/Kconfig
drivers/video/fbdev/acornfb.c
drivers/video/fbdev/amba-clcd.c
drivers/video/fbdev/arcfb.c
drivers/video/fbdev/aty/radeon_base.c
drivers/video/fbdev/core/fbmon.c
drivers/video/fbdev/i810/i810_main.c
drivers/video/fbdev/imxfb.c
drivers/video/fbdev/intelfb/intelfbdrv.c
drivers/video/fbdev/n411.c
drivers/video/fbdev/omap/lcd_mipid.c
drivers/video/fbdev/omap2/omapfb/dss/dss.c
drivers/video/fbdev/pmag-aa-fb.c
drivers/video/fbdev/pmag-ba-fb.c
drivers/video/fbdev/pmagb-b-fb.c
drivers/video/fbdev/pxafb.c
drivers/video/fbdev/sm501fb.c
drivers/video/fbdev/udlfb.c
drivers/video/fbdev/vermilion/vermilion.c
drivers/video/fbdev/xen-fbfront.c
drivers/video/logo/logo.c
drivers/virt/fsl_hypervisor.c
drivers/virtio/virtio_balloon.c
drivers/virtio/virtio_input.c
drivers/virtio/virtio_mmio.c
drivers/virtio/virtio_pci_common.c
drivers/virtio/virtio_pci_common.h
drivers/virtio/virtio_pci_legacy.c
drivers/virtio/virtio_pci_modern.c
drivers/virtio/virtio_ring.c
drivers/watchdog/cpu5wdt.c
drivers/watchdog/eurotechwdt.c
drivers/watchdog/hpwdt.c
drivers/watchdog/pc87413_wdt.c
drivers/watchdog/sc1200wdt.c
drivers/watchdog/wdt.c
drivers/xen/evtchn.c
drivers/xen/xenfs/super.c
firmware/Makefile
fs/Kconfig
fs/affs/affs.h
fs/affs/amigaffs.h [moved from include/linux/amigaffs.h with 100% similarity]
fs/affs/dir.c
fs/affs/file.c
fs/affs/inode.c
fs/affs/namei.c
fs/bfs/inode.c
fs/binfmt_misc.c
fs/block_dev.c
fs/btrfs/backref.c
fs/btrfs/btrfs_inode.h
fs/btrfs/compression.c
fs/btrfs/ctree.c
fs/btrfs/ctree.h
fs/btrfs/delayed-inode.c
fs/btrfs/delayed-inode.h
fs/btrfs/delayed-ref.c
fs/btrfs/delayed-ref.h
fs/btrfs/dev-replace.c
fs/btrfs/disk-io.c
fs/btrfs/disk-io.h
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/extent_io.h
fs/btrfs/extent_map.c
fs/btrfs/extent_map.h
fs/btrfs/file.c
fs/btrfs/free-space-cache.c
fs/btrfs/free-space-tree.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/ordered-data.c
fs/btrfs/ordered-data.h
fs/btrfs/qgroup.c
fs/btrfs/qgroup.h
fs/btrfs/raid56.c
fs/btrfs/reada.c
fs/btrfs/root-tree.c
fs/btrfs/scrub.c
fs/btrfs/send.c
fs/btrfs/super.c
fs/btrfs/tests/btrfs-tests.c
fs/btrfs/transaction.c
fs/btrfs/transaction.h
fs/btrfs/tree-log.c
fs/btrfs/volumes.c
fs/btrfs/volumes.h
fs/buffer.c
fs/ceph/addr.c
fs/ceph/caps.c
fs/ceph/debugfs.c
fs/ceph/dir.c
fs/ceph/file.c
fs/ceph/inode.c
fs/ceph/mds_client.c
fs/ceph/mds_client.h
fs/ceph/mdsmap.c
fs/ceph/snap.c
fs/ceph/super.c
fs/ceph/super.h
fs/ceph/xattr.c
fs/cifs/cifsacl.c
fs/cifs/cifsencrypt.c
fs/cifs/cifsglob.h
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/smb2pdu.c
fs/cifs/transport.c
fs/cifs/xattr.c
fs/compat_ioctl.c
fs/dax.c
fs/dcache.c
fs/debugfs/inode.c
fs/exofs/dir.c
fs/ext2/inode.c
fs/ext2/super.c
fs/ext4/file.c
fs/ext4/inode.c
fs/ext4/mballoc.c
fs/ext4/super.c
fs/f2fs/f2fs.h
fs/f2fs/file.c
fs/f2fs/node.c
fs/f2fs/segment.c
fs/f2fs/segment.h
fs/fcntl.c
fs/file.c
fs/fuse/control.c
fs/fuse/dev.c
fs/fuse/file.c
fs/fuse/fuse_i.h
fs/fuse/inode.c
fs/gfs2/bmap.c
fs/hfs/extent.c
fs/hfsplus/extents.c
fs/inode.c
fs/internal.h
fs/iomap.c
fs/jbd2/journal.c
fs/jffs2/readinode.c
fs/libfs.c
fs/lockd/clntlock.c
fs/lockd/clntproc.c
fs/lockd/svc.c
fs/lockd/svclock.c
fs/locks.c
fs/namei.c
fs/namespace.c
fs/nfs/Kconfig
fs/nfs/Makefile
fs/nfs/callback.c
fs/nfs/callback_proc.c
fs/nfs/callback_xdr.c
fs/nfs/client.c
fs/nfs/dir.c
fs/nfs/direct.c
fs/nfs/file.c
fs/nfs/filelayout/filelayout.c
fs/nfs/flexfilelayout/flexfilelayout.c
fs/nfs/flexfilelayout/flexfilelayoutdev.c
fs/nfs/inode.c
fs/nfs/internal.h
fs/nfs/namespace.c
fs/nfs/nfs3proc.c
fs/nfs/nfs42proc.c
fs/nfs/nfs42xdr.c
fs/nfs/nfs4client.c
fs/nfs/nfs4getroot.c
fs/nfs/nfs4namespace.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4state.c
fs/nfs/nfs4xdr.c
fs/nfs/objlayout/Kbuild [deleted file]
fs/nfs/objlayout/objio_osd.c [deleted file]
fs/nfs/objlayout/objlayout.c [deleted file]
fs/nfs/objlayout/objlayout.h [deleted file]
fs/nfs/objlayout/pnfs_osd_xdr_cli.c [deleted file]
fs/nfs/pagelist.c
fs/nfs/pnfs.c
fs/nfs/pnfs.h
fs/nfs/pnfs_nfs.c
fs/nfs/proc.c
fs/nfs/read.c
fs/nfs/write.c
fs/nfsd/nfs3xdr.c
fs/nfsd/nfs4proc.c
fs/nfsd/nfs4state.c
fs/nfsd/nfs4xdr.c
fs/nfsd/nfsctl.c
fs/nfsd/nfsxdr.c
fs/nfsd/vfs.c
fs/nsfs.c
fs/open.c
fs/overlayfs/copy_up.c
fs/overlayfs/dir.c
fs/overlayfs/inode.c
fs/overlayfs/namei.c
fs/overlayfs/overlayfs.h
fs/overlayfs/ovl_entry.h
fs/overlayfs/super.c
fs/overlayfs/util.c
fs/proc/base.c
fs/proc/inode.c
fs/proc/namespaces.c
fs/pstore/ram.c
fs/reiserfs/item_ops.c
fs/select.c
fs/seq_file.c
fs/signalfd.c
fs/tracefs/inode.c
fs/ubifs/Kconfig
fs/ubifs/debug.c
fs/ubifs/dir.c
fs/ubifs/file.c
fs/ubifs/ioctl.c
fs/ubifs/misc.h
fs/ubifs/recovery.c
fs/ubifs/sb.c
fs/ubifs/ubifs.h
fs/ubifs/xattr.c
fs/ufs/ialloc.c
fs/xattr.c
fs/xfs/kmem.c
fs/xfs/xfs_iomap.c
fs/xfs/xfs_log_recover.c
fs/xfs/xfs_super.c
include/Kbuild [deleted file]
include/acpi/acconfig.h
include/acpi/acpi_bus.h
include/acpi/acpixf.h
include/acpi/actbl2.h
include/asm-generic/Kbuild.asm [deleted file]
include/asm-generic/set_memory.h [new file with mode: 0644]
include/asm-generic/vmlinux.lds.h
include/drm/drm_mem_util.h
include/dt-bindings/clock/gxbb-clkc.h
include/dt-bindings/clock/hi6220-clock.h
include/dt-bindings/clock/mt6797-clk.h [new file with mode: 0644]
include/dt-bindings/clock/r7s72100-clock.h
include/dt-bindings/clock/r8a73a4-clock.h
include/dt-bindings/clock/r8a7790-clock.h
include/dt-bindings/clock/r8a7791-clock.h
include/dt-bindings/clock/r8a7792-clock.h
include/dt-bindings/clock/r8a7793-clock.h
include/dt-bindings/clock/r8a7794-clock.h
include/dt-bindings/clock/r8a7795-cpg-mssr.h
include/dt-bindings/clock/rk3328-cru.h
include/dt-bindings/clock/rk3368-cru.h
include/dt-bindings/clock/rv1108-cru.h [moved from include/dt-bindings/clock/rk1108-cru.h with 97% similarity]
include/dt-bindings/clock/sun8i-h3-ccu.h
include/dt-bindings/clock/sun8i-r-ccu.h [new file with mode: 0644]
include/dt-bindings/clock/tegra114-car.h
include/dt-bindings/clock/tegra124-car-common.h
include/dt-bindings/clock/tegra210-car.h
include/dt-bindings/clock/tegra30-car.h
include/dt-bindings/genpd/k2g.h [new file with mode: 0644]
include/dt-bindings/mfd/stm32f7-rcc.h [new file with mode: 0644]
include/dt-bindings/pinctrl/hisi.h
include/dt-bindings/power/imx7-power.h [new file with mode: 0644]
include/dt-bindings/power/r8a7795-sysc.h
include/dt-bindings/reset/altr,rst-mgr-a10sr.h [moved from arch/nios2/include/asm/prom.h with 56% similarity]
include/dt-bindings/reset/imx7-reset.h [new file with mode: 0644]
include/dt-bindings/reset/mt2701-resets.h
include/dt-bindings/reset/sun8i-h3-ccu.h
include/dt-bindings/reset/sun8i-r-ccu.h [new file with mode: 0644]
include/dt-bindings/reset/tegra210-car.h [new file with mode: 0644]
include/kvm/arm_vgic.h
include/linux/acpi.h
include/linux/acpi_iort.h
include/linux/amba/pl080.h
include/linux/amba/pl330.h [deleted file]
include/linux/bcma/bcma_driver_pci.h
include/linux/blkdev.h
include/linux/bpf_verifier.h
include/linux/buffer_head.h
include/linux/ceph/ceph_features.h
include/linux/ceph/ceph_fs.h
include/linux/ceph/cls_lock_client.h
include/linux/ceph/libceph.h
include/linux/ceph/mdsmap.h
include/linux/ceph/osd_client.h
include/linux/ceph/pagelist.h
include/linux/clk/tegra.h
include/linux/clk/ti.h
include/linux/console.h
include/linux/cpumask.h
include/linux/crash_core.h [new file with mode: 0644]
include/linux/dax.h
include/linux/devfreq_cooling.h
include/linux/dma-fence.h
include/linux/dma-iommu.h
include/linux/dma-mapping.h
include/linux/dma_remapping.h
include/linux/elf.h
include/linux/fcntl.h
include/linux/filter.h
include/linux/firmware/meson/meson_sm.h
include/linux/fs.h
include/linux/ftrace.h
include/linux/intel-iommu.h
include/linux/interrupt.h
include/linux/io.h
include/linux/iommu.h
include/linux/ipc.h
include/linux/irqchip/arm-gic-v3.h
include/linux/jiffies.h
include/linux/kbuild.h
include/linux/kexec.h
include/linux/kref.h
include/linux/kvm_host.h
include/linux/lockd/bind.h
include/linux/lockd/lockd.h
include/linux/mfd/syscon/imx7-iomuxc-gpr.h
include/linux/mlx4/device.h
include/linux/mlx5/driver.h
include/linux/mlx5/fs.h
include/linux/mm.h
include/linux/mmzone.h
include/linux/mod_devicetable.h
include/linux/moduleparam.h
include/linux/mtd/mtd.h
include/linux/mtd/nand.h
include/linux/namei.h
include/linux/nd.h
include/linux/netdevice.h
include/linux/nfs_fs.h
include/linux/nfs_fs_sb.h
include/linux/nfs_page.h
include/linux/nfs_xdr.h
include/linux/of_device.h
include/linux/of_fdt.h
include/linux/of_irq.h
include/linux/of_pci.h
include/linux/page-isolation.h
include/linux/pci-ecam.h
include/linux/pci-ep-cfs.h [new file with mode: 0644]
include/linux/pci-epc.h [new file with mode: 0644]
include/linux/pci-epf.h [new file with mode: 0644]
include/linux/pci.h
include/linux/pci_ids.h
include/linux/platform_data/iommu-omap.h
include/linux/platform_data/video-imxfb.h
include/linux/pm_domain.h
include/linux/pm_wakeup.h
include/linux/power/max17042_battery.h
include/linux/printk.h
include/linux/proc_ns.h
include/linux/ptr_ring.h
include/linux/qcom_scm.h
include/linux/rcu_node_tree.h [new file with mode: 0644]
include/linux/rcu_segcblist.h [new file with mode: 0644]
include/linux/rculist.h
include/linux/rcupdate.h
include/linux/rcutiny.h
include/linux/rcutree.h
include/linux/sched/mm.h
include/linux/sem.h
include/linux/serdev.h
include/linux/serial_core.h
include/linux/slab.h
include/linux/soc/renesas/rcar-rst.h
include/linux/srcu.h
include/linux/srcuclassic.h [new file with mode: 0644]
include/linux/srcutiny.h [new file with mode: 0644]
include/linux/srcutree.h [new file with mode: 0644]
include/linux/sunrpc/rpc_rdma.h
include/linux/sunrpc/svc.h
include/linux/sunrpc/svc_rdma.h
include/linux/suspend.h
include/linux/tee_drv.h [new file with mode: 0644]
include/linux/time.h
include/linux/tty.h
include/linux/types.h
include/linux/uaccess.h
include/linux/virtio.h
include/linux/virtio_config.h
include/linux/virtio_ring.h
include/linux/vmalloc.h
include/net/addrconf.h
include/net/cfg80211.h
include/net/mac80211.h
include/net/secure_seq.h
include/net/sock.h
include/net/tcp.h
include/net/x25.h
include/rdma/ib_verbs.h
include/rdma/rdmavt_qp.h
include/scsi/fc/Kbuild [deleted file]
include/scsi/scsi_proto.h
include/soc/fsl/qe/immap_qe.h
include/soc/fsl/qe/qe.h
include/soc/tegra/flowctrl.h [moved from arch/arm/mach-tegra/flowctrl.h with 77% similarity]
include/soc/tegra/pmc.h
include/target/target_core_backend.h
include/target/target_core_base.h
include/trace/events/btrfs.h
include/trace/events/fs_dax.h
include/trace/events/iommu.h
include/trace/events/thermal.h
include/uapi/Kbuild [deleted file]
include/uapi/asm-generic/Kbuild [deleted file]
include/uapi/asm-generic/Kbuild.asm
include/uapi/drm/Kbuild [deleted file]
include/uapi/drm/amdgpu_drm.h
include/uapi/linux/Kbuild
include/uapi/linux/android/Kbuild [deleted file]
include/uapi/linux/bcache.h
include/uapi/linux/bpf.h
include/uapi/linux/btrfs.h
include/uapi/linux/btrfs_tree.h
include/uapi/linux/byteorder/Kbuild [deleted file]
include/uapi/linux/caif/Kbuild [deleted file]
include/uapi/linux/can/Kbuild [deleted file]
include/uapi/linux/cryptouser.h
include/uapi/linux/dvb/Kbuild [deleted file]
include/uapi/linux/elf.h
include/uapi/linux/ethtool.h
include/uapi/linux/hdlc/Kbuild [deleted file]
include/uapi/linux/hsi/Kbuild [deleted file]
include/uapi/linux/if_link.h
include/uapi/linux/iio/Kbuild [deleted file]
include/uapi/linux/ipmi.h
include/uapi/linux/isdn/Kbuild [deleted file]
include/uapi/linux/mmc/Kbuild [deleted file]
include/uapi/linux/netfilter/Kbuild [deleted file]
include/uapi/linux/netfilter/ipset/Kbuild [deleted file]
include/uapi/linux/netfilter_arp/Kbuild [deleted file]
include/uapi/linux/netfilter_bridge/Kbuild [deleted file]
include/uapi/linux/netfilter_ipv4/Kbuild [deleted file]
include/uapi/linux/netfilter_ipv6/Kbuild [deleted file]
include/uapi/linux/nfsd/Kbuild [deleted file]
include/uapi/linux/nfsd/cld.h
include/uapi/linux/pci_regs.h
include/uapi/linux/pcitest.h [new file with mode: 0644]
include/uapi/linux/pr.h
include/uapi/linux/qrtr.h
include/uapi/linux/raid/Kbuild [deleted file]
include/uapi/linux/smc_diag.h
include/uapi/linux/spi/Kbuild [deleted file]
include/uapi/linux/sunrpc/Kbuild [deleted file]
include/uapi/linux/switchtec_ioctl.h [new file with mode: 0644]
include/uapi/linux/tc_act/Kbuild [deleted file]
include/uapi/linux/tc_ematch/Kbuild [deleted file]
include/uapi/linux/tee.h [new file with mode: 0644]
include/uapi/linux/usb/Kbuild [deleted file]
include/uapi/linux/wimax/Kbuild [deleted file]
include/uapi/misc/Kbuild [deleted file]
include/uapi/mtd/Kbuild [deleted file]
include/uapi/rdma/Kbuild [deleted file]
include/uapi/rdma/bnxt_re-abi.h
include/uapi/rdma/hfi/Kbuild [deleted file]
include/uapi/rdma/ib_user_verbs.h
include/uapi/scsi/Kbuild [deleted file]
include/uapi/scsi/fc/Kbuild [deleted file]
include/uapi/sound/Kbuild [deleted file]
include/uapi/video/Kbuild [deleted file]
include/uapi/xen/Kbuild [deleted file]
include/video/Kbuild [deleted file]
init/Kconfig
init/do_mounts.h
init/initramfs.c
init/main.c
ipc/shm.c
ipc/util.c
kernel/Makefile
kernel/bpf/core.c
kernel/bpf/inode.c
kernel/bpf/syscall.c
kernel/bpf/verifier.c
kernel/crash_core.c [new file with mode: 0644]
kernel/events/callchain.c
kernel/fork.c
kernel/gcov/base.c
kernel/gcov/gcc_4_7.c
kernel/groups.c
kernel/hung_task.c
kernel/irq/manage.c
kernel/kcov.c
kernel/kexec_core.c
kernel/ksysfs.c
kernel/locking/lockdep.c
kernel/locking/rtmutex-debug.c
kernel/module.c
kernel/pid.c
kernel/pid_namespace.c
kernel/power/process.c
kernel/power/snapshot.c
kernel/power/suspend.c
kernel/printk/braille.c
kernel/printk/braille.h
kernel/printk/printk.c
kernel/rcu/Makefile
kernel/rcu/rcu.h
kernel/rcu/rcu_segcblist.c [new file with mode: 0644]
kernel/rcu/rcu_segcblist.h [new file with mode: 0644]
kernel/rcu/rcutorture.c
kernel/rcu/srcu.c
kernel/rcu/srcutiny.c [new file with mode: 0644]
kernel/rcu/srcutree.c [new file with mode: 0644]
kernel/rcu/tiny.c
kernel/rcu/tiny_plugin.h
kernel/rcu/tree.c
kernel/rcu/tree.h
kernel/rcu/tree_exp.h
kernel/rcu/tree_plugin.h
kernel/rcu/tree_trace.c
kernel/rcu/update.c
kernel/sched/core.c
kernel/signal.c
kernel/sysctl.c
kernel/taskstats.c
kernel/time/time.c
kernel/trace/ftrace.c
kernel/trace/trace.c
kernel/trace/trace_entries.h
kernel/trace/trace_hwlat.c
kernel/trace/trace_output.c
lib/Kconfig.debug
lib/Makefile
lib/devres.c
lib/dma-debug.c
lib/fault-inject.c
lib/iov_iter.c
lib/list_sort.c
lib/rhashtable.c
lib/test_list_sort.c [new file with mode: 0644]
lib/test_sort.c
lib/vsprintf.c
lib/zlib_inflate/inftrees.c
mm/compaction.c
mm/filemap.c
mm/frame_vector.c
mm/huge_memory.c
mm/internal.h
mm/kasan/kasan.c
mm/khugepaged.c
mm/kmemcheck.c
mm/memcontrol.c
mm/memory-failure.c
mm/mmu_notifier.c
mm/nommu.c
mm/page_alloc.c
mm/page_isolation.c
mm/rmap.c
mm/slab.c
mm/slab.h
mm/slab_common.c
mm/slob.c
mm/slub.c
mm/swap_slots.c
mm/swap_state.c
mm/swapfile.c
mm/truncate.c
mm/util.c
mm/vmalloc.c
mm/vmscan.c
mm/vmstat.c
net/8021q/vlan_dev.c
net/9p/trans_xen.c
net/bridge/br_netlink.c
net/ceph/ceph_common.c
net/ceph/cls_lock_client.c
net/ceph/debugfs.c
net/ceph/messenger.c
net/ceph/osd_client.c
net/ceph/pagelist.c
net/ceph/snapshot.c
net/core/dev.c
net/core/neighbour.c
net/core/rtnetlink.c
net/core/secure_seq.c
net/core/sock.c
net/dccp/ipv4.c
net/dccp/ipv6.c
net/decnet/af_decnet.c
net/decnet/dn_neigh.c
net/ipv4/arp.c
net/ipv4/fib_frontend.c
net/ipv4/fib_trie.c
net/ipv4/inet_connection_sock.c
net/ipv4/inet_hashtables.c
net/ipv4/ip_vti.c
net/ipv4/ipmr.c
net/ipv4/syncookies.c
net/ipv4/tcp_input.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_metrics.c
net/ipv4/tcp_output.c
net/ipv4/udp.c
net/ipv4/udp_impl.h
net/ipv6/addrconf.c
net/ipv6/ila/ila_xlat.c
net/ipv6/ip6_offload.c
net/ipv6/ip6_output.c
net/ipv6/output_core.c
net/ipv6/route.c
net/ipv6/syncookies.c
net/ipv6/tcp_ipv6.c
net/ipv6/udp.c
net/ipv6/udp_impl.h
net/ipv6/udp_offload.c
net/llc/af_llc.c
net/llc/llc_conn.c
net/llc/llc_sap.c
net/mac80211/ibss.c
net/mac80211/mlme.c
net/mpls/af_mpls.c
net/netfilter/nf_conntrack_core.c
net/netfilter/x_tables.c
net/netfilter/xt_recent.c
net/packet/af_packet.c
net/sched/sch_api.c
net/sched/sch_choke.c
net/sched/sch_fq.c
net/sched/sch_fq_codel.c
net/sched/sch_hhf.c
net/sched/sch_netem.c
net/sched/sch_sfq.c
net/sctp/ipv6.c
net/smc/Kconfig
net/smc/af_smc.c
net/smc/smc_clc.c
net/smc/smc_core.c
net/smc/smc_core.h
net/smc/smc_ib.c
net/smc/smc_ib.h
net/sunrpc/Kconfig
net/sunrpc/clnt.c
net/sunrpc/sched.c
net/sunrpc/svc.c
net/sunrpc/xdr.c
net/sunrpc/xprt.c
net/sunrpc/xprtrdma/Makefile
net/sunrpc/xprtrdma/rpc_rdma.c
net/sunrpc/xprtrdma/svc_rdma.c
net/sunrpc/xprtrdma/svc_rdma_backchannel.c
net/sunrpc/xprtrdma/svc_rdma_marshal.c
net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
net/sunrpc/xprtrdma/svc_rdma_rw.c [new file with mode: 0644]
net/sunrpc/xprtrdma/svc_rdma_sendto.c
net/sunrpc/xprtrdma/svc_rdma_transport.c
net/sunrpc/xprtrdma/transport.c
net/sunrpc/xprtrdma/verbs.c
net/sunrpc/xprtrdma/xprt_rdma.h
net/tipc/socket.c
net/vmw_vsock/virtio_transport.c
net/wireless/nl80211.c
net/x25/af_x25.c
net/x25/sysctl_net_x25.c
samples/bpf/cookie_uid_helper_example.c
samples/bpf/offwaketime_user.c
samples/bpf/sampleip_user.c
samples/bpf/trace_event_user.c
samples/bpf/tracex2_user.c
samples/bpf/xdp1_user.c
samples/bpf/xdp_tx_iptunnel_user.c
scripts/Kbuild.include
scripts/Makefile.build
scripts/Makefile.dtbinst
scripts/Makefile.extrawarn
scripts/Makefile.headersinst
scripts/Makefile.lib
scripts/checkpatch.pl
scripts/dtc/checks.c
scripts/dtc/include-prefixes/arc [new symlink]
scripts/dtc/include-prefixes/arm [new symlink]
scripts/dtc/include-prefixes/arm64 [new symlink]
scripts/dtc/include-prefixes/c6x [new symlink]
scripts/dtc/include-prefixes/cris [new symlink]
scripts/dtc/include-prefixes/dt-bindings [new symlink]
scripts/dtc/include-prefixes/h8300 [new symlink]
scripts/dtc/include-prefixes/metag [new symlink]
scripts/dtc/include-prefixes/microblaze [new symlink]
scripts/dtc/include-prefixes/mips [new symlink]
scripts/dtc/include-prefixes/nios2 [new symlink]
scripts/dtc/include-prefixes/openrisc [new symlink]
scripts/dtc/include-prefixes/powerpc [new symlink]
scripts/dtc/include-prefixes/sh [new symlink]
scripts/dtc/include-prefixes/xtensa [new symlink]
scripts/genksyms/parse.tab.c_shipped
scripts/genksyms/parse.y
scripts/mod/Makefile
scripts/objdiff
scripts/package/builddeb
scripts/spelling.txt
security/apparmor/apparmorfs.c
security/apparmor/include/lib.h
security/apparmor/lib.c
security/apparmor/match.c
security/apparmor/policy_unpack.c
security/inode.c
security/keys/keyctl.c
security/selinux/selinuxfs.c
security/smack/smackfs.c
sound/Kconfig
sound/drivers/mpu401/mpu401.c
sound/drivers/mtpav.c
sound/drivers/serial-u16550.c
sound/hda/hdac_controller.c
sound/isa/ad1848/ad1848.c
sound/isa/adlib.c
sound/isa/cmi8328.c
sound/isa/cmi8330.c
sound/isa/cs423x/cs4231.c
sound/isa/cs423x/cs4236.c
sound/isa/es1688/es1688.c
sound/isa/es18xx.c
sound/isa/galaxy/galaxy.c
sound/isa/gus/gusclassic.c
sound/isa/gus/gusextreme.c
sound/isa/gus/gusmax.c
sound/isa/gus/interwave.c
sound/isa/msnd/msnd_pinnacle.c
sound/isa/opl3sa2.c
sound/isa/opti9xx/miro.c
sound/isa/opti9xx/opti92x-ad1848.c
sound/isa/sb/jazz16.c
sound/isa/sb/sb16.c
sound/isa/sb/sb8.c
sound/isa/sc6000.c
sound/isa/sscape.c
sound/isa/wavefront/wavefront.c
sound/oss/ad1848.c
sound/oss/aedsp16.c
sound/oss/mpu401.c
sound/oss/msnd_pinnacle.c
sound/oss/opl3.c
sound/oss/pas2_card.c
sound/oss/pss.c
sound/oss/sb_card.c
sound/oss/trix.c
sound/oss/uart401.c
sound/oss/uart6850.c
sound/oss/waveartist.c
sound/pci/als4000.c
sound/pci/cmipci.c
sound/pci/ens1370.c
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_conexant.c
sound/pci/intel8x0.c
sound/pci/riptide/riptide.c
sound/pci/sonicvibes.c
sound/pci/via82xx.c
sound/pci/ymfpci/ymfpci.c
sound/soc/soc-core.c
sound/x86/intel_hdmi_audio.c
tools/build/feature/test-bpf.c
tools/build/feature/test-sched_getcpu.c
tools/include/linux/string.h
tools/include/uapi/linux/bpf.h
tools/lib/bpf/bpf.c
tools/lib/bpf/bpf.h
tools/lib/string.c
tools/lib/subcmd/help.c
tools/lib/subcmd/parse-options.c
tools/lib/subcmd/subcmd-util.h
tools/pci/pcitest.c [new file with mode: 0644]
tools/pci/pcitest.sh [new file with mode: 0644]
tools/perf/Documentation/perf-c2c.txt
tools/perf/Documentation/perf-record.txt
tools/perf/Documentation/perf-report.txt
tools/perf/Documentation/perf.data-file-format.txt
tools/perf/Documentation/tips.txt
tools/perf/arch/arm64/annotate/instructions.c
tools/perf/arch/powerpc/util/sym-handling.c
tools/perf/builtin-buildid-cache.c
tools/perf/builtin-c2c.c
tools/perf/builtin-config.c
tools/perf/builtin-top.c
tools/perf/builtin-trace.c
tools/perf/perf.c
tools/perf/tests/hists_cumulate.c
tools/perf/tests/hists_filter.c
tools/perf/tests/hists_output.c
tools/perf/tests/kmod-path.c
tools/perf/tests/sdt.c
tools/perf/ui/setup.c
tools/perf/util/Build
tools/perf/util/build-id.h
tools/perf/util/event.c
tools/perf/util/event.h
tools/perf/util/evsel.c
tools/perf/util/header.c
tools/perf/util/intel-pt.c
tools/perf/util/machine.c
tools/perf/util/map.c
tools/perf/util/map.h
tools/perf/util/memswap.c [new file with mode: 0644]
tools/perf/util/memswap.h [new file with mode: 0644]
tools/perf/util/scripting-engines/trace-event-perl.c
tools/perf/util/session.c
tools/perf/util/strbuf.c
tools/perf/util/symbol.c
tools/perf/util/symbol.h
tools/perf/util/units.c
tools/perf/util/units.h
tools/perf/util/util.c
tools/perf/util/util.h
tools/testing/selftests/.gitignore
tools/testing/selftests/Makefile
tools/testing/selftests/bpf/Makefile
tools/testing/selftests/bpf/include/uapi/linux/types.h [new file with mode: 0644]
tools/testing/selftests/bpf/test_align.c [new file with mode: 0644]
tools/testing/selftests/bpf/test_pkt_access.c
tools/testing/selftests/breakpoints/Makefile
tools/testing/selftests/cpufreq/config [new file with mode: 0644]
tools/testing/selftests/ftrace/config
tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_type.tc
tools/testing/selftests/futex/Makefile
tools/testing/selftests/gpio/Makefile
tools/testing/selftests/gpio/config [new file with mode: 0644]
tools/testing/selftests/lib.mk
tools/testing/selftests/lib/config [new file with mode: 0644]
tools/testing/selftests/powerpc/Makefile
tools/testing/selftests/powerpc/tm/.gitignore
tools/testing/selftests/powerpc/tm/Makefile
tools/testing/selftests/powerpc/tm/tm-vmx-unavail.c [new file with mode: 0644]
tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
tools/testing/selftests/splice/Makefile
tools/testing/selftests/sync/Makefile
tools/testing/selftests/timers/clocksource-switch.c
tools/testing/selftests/vm/Makefile
tools/testing/selftests/vm/config
tools/testing/selftests/vm/map_hugetlb.c
tools/testing/selftests/vm/mlock2-tests.c
tools/testing/selftests/vm/on-fault-limit.c
tools/testing/selftests/vm/run_vmtests
tools/testing/selftests/vm/thuge-gen.c
tools/testing/selftests/vm/virtual_address_range.c [new file with mode: 0644]
tools/testing/selftests/watchdog/watchdog-test.c
tools/testing/selftests/x86/.gitignore
tools/testing/selftests/x86/Makefile
tools/virtio/linux/virtio.h
tools/virtio/ringtest/main.c
tools/virtio/ringtest/main.h
tools/virtio/ringtest/ptr_ring.c
tools/virtio/virtio_test.c
tools/virtio/vringh_test.c
usr/Kconfig
virt/kvm/arm/arm.c [moved from arch/arm/kvm/arm.c with 99% similarity]
virt/kvm/arm/hyp/vgic-v3-sr.c
virt/kvm/arm/mmio.c [moved from arch/arm/kvm/mmio.c with 100% similarity]
virt/kvm/arm/mmu.c [moved from arch/arm/kvm/mmu.c with 98% similarity]
virt/kvm/arm/perf.c [moved from arch/arm/kvm/perf.c with 100% similarity]
virt/kvm/arm/psci.c [moved from arch/arm/kvm/psci.c with 100% similarity]
virt/kvm/arm/trace.h
virt/kvm/arm/vgic/trace.h [new file with mode: 0644]
virt/kvm/arm/vgic/vgic-init.c
virt/kvm/arm/vgic/vgic-its.c
virt/kvm/arm/vgic/vgic-kvm-device.c
virt/kvm/arm/vgic/vgic-mmio-v3.c
virt/kvm/arm/vgic/vgic-mmio.c
virt/kvm/arm/vgic/vgic-mmio.h
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 c2ed4ecb0acd28126d8703e17e86775ccbed1bb6..0c39aa20b6ba8d2afbc69670636b9223b3bf23fa 100644 (file)
@@ -33,6 +33,7 @@
 *.lzo
 *.patch
 *.gcno
+*.ll
 modules.builtin
 Module.symvers
 *.dwo
index d2aeb146efed7991391841aff9ab21e567b886ec..5273cfd70ad62996ba8374698fb5e22e91d33f45 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -146,6 +146,8 @@ Santosh Shilimkar <ssantosh@kernel.org>
 Santosh Shilimkar <santosh.shilimkar@oracle.org>
 Sascha Hauer <s.hauer@pengutronix.de>
 S.Çağlar Onur <caglar@pardus.org.tr>
+Sebastian Reichel <sre@kernel.org> <sre@debian.org>
+Sebastian Reichel <sre@kernel.org> <sebastian.reichel@collabora.co.uk>
 Shiraz Hashim <shiraz.linux.kernel@gmail.com> <shiraz.hashim@st.com>
 Shuah Khan <shuah@kernel.org> <shuahkhan@gmail.com>
 Shuah Khan <shuah@kernel.org> <shuah.khan@hp.com>
index 793acf999e9eac87057af3214ca1f98ad65b922f..ed3e5e949fce303efec625259b527d503cf82f8d 100644 (file)
@@ -412,6 +412,8 @@ sysctl/
        - directory with info on the /proc/sys/* files.
 target/
        - directory with info on generating TCM v4 fabric .ko modules
+tee.txt
+       - info on the TEE subsystem and drivers
 this_cpu_ops.txt
        - List rationale behind and the way to use this_cpu operations.
 thermal/
index e4e90104d7c38ff89bae718df7485337ee3e9108..44d4b2be92fd4a56ab2420944f76669a2466a304 100644 (file)
@@ -301,3 +301,25 @@ Contact:   Emil Velikov <emil.l.velikov@gmail.com>
 Description:
                This file contains the revision field of the PCI device.
                The value comes from device config space. The file is read only.
+
+What:          /sys/bus/pci/devices/.../sriov_drivers_autoprobe
+Date:          April 2017
+Contact:       Bodong Wang<bodong@mellanox.com>
+Description:
+               This file is associated with the PF of a device that
+               supports SR-IOV.  It determines whether newly-enabled VFs
+               are immediately bound to a driver.  It initially contains
+               1, which means the kernel automatically binds VFs to a
+               compatible driver immediately after they are enabled.  If
+               an application writes 0 to the file before enabling VFs,
+               the kernel will not bind VFs to a driver.
+
+               A typical use case is to write 0 to this file, then enable
+               VFs, then assign the newly-created VFs to virtual machines.
+               Note that changing this file does not affect already-
+               enabled VFs.  In this scenario, the user must first disable
+               the VFs, write 0 to sriov_drivers_autoprobe, then re-enable
+               the VFs.
+
+               This is similar to /sys/bus/pci/drivers_autoprobe, but
+               affects only the VFs associated with a specific PF.
diff --git a/Documentation/ABI/testing/sysfs-class-switchtec b/Documentation/ABI/testing/sysfs-class-switchtec
new file mode 100644 (file)
index 0000000..48cb4c1
--- /dev/null
@@ -0,0 +1,96 @@
+switchtec - Microsemi Switchtec PCI Switch Management Endpoint
+
+For details on this subsystem look at Documentation/switchtec.txt.
+
+What:          /sys/class/switchtec
+Date:          05-Jan-2017
+KernelVersion: v4.11
+Contact:       Logan Gunthorpe <logang@deltatee.com>
+Description:   The switchtec class subsystem folder.
+               Each registered switchtec driver is represented by a switchtecX
+               subfolder (X being an integer >= 0).
+
+
+What:          /sys/class/switchtec/switchtec[0-9]+/component_id
+Date:          05-Jan-2017
+KernelVersion: v4.11
+Contact:       Logan Gunthorpe <logang@deltatee.com>
+Description:   Component identifier as stored in the hardware (eg. PM8543)
+               (read only)
+Values:        arbitrary string.
+
+
+What:          /sys/class/switchtec/switchtec[0-9]+/component_revision
+Date:          05-Jan-2017
+KernelVersion: v4.11
+Contact:       Logan Gunthorpe <logang@deltatee.com>
+Description:   Component revision stored in the hardware (read only)
+Values:        integer.
+
+
+What:          /sys/class/switchtec/switchtec[0-9]+/component_vendor
+Date:          05-Jan-2017
+KernelVersion: v4.11
+Contact:       Logan Gunthorpe <logang@deltatee.com>
+Description:   Component vendor as stored in the hardware (eg. MICROSEM)
+               (read only)
+Values:        arbitrary string.
+
+
+What:          /sys/class/switchtec/switchtec[0-9]+/device_version
+Date:          05-Jan-2017
+KernelVersion: v4.11
+Contact:       Logan Gunthorpe <logang@deltatee.com>
+Description:   Device version as stored in the hardware (read only)
+Values:        integer.
+
+
+What:          /sys/class/switchtec/switchtec[0-9]+/fw_version
+Date:          05-Jan-2017
+KernelVersion: v4.11
+Contact:       Logan Gunthorpe <logang@deltatee.com>
+Description:   Currently running firmware version (read only)
+Values:        integer (in hexadecimal).
+
+
+What:          /sys/class/switchtec/switchtec[0-9]+/partition
+Date:          05-Jan-2017
+KernelVersion: v4.11
+Contact:       Logan Gunthorpe <logang@deltatee.com>
+Description:   Partition number for this device in the switch (read only)
+Values:        integer.
+
+
+What:          /sys/class/switchtec/switchtec[0-9]+/partition_count
+Date:          05-Jan-2017
+KernelVersion: v4.11
+Contact:       Logan Gunthorpe <logang@deltatee.com>
+Description:   Total number of partitions in the switch (read only)
+Values:        integer.
+
+
+What:          /sys/class/switchtec/switchtec[0-9]+/product_id
+Date:          05-Jan-2017
+KernelVersion: v4.11
+Contact:       Logan Gunthorpe <logang@deltatee.com>
+Description:   Product identifier as stored in the hardware (eg. PSX 48XG3)
+               (read only)
+Values:        arbitrary string.
+
+
+What:          /sys/class/switchtec/switchtec[0-9]+/product_revision
+Date:          05-Jan-2017
+KernelVersion: v4.11
+Contact:       Logan Gunthorpe <logang@deltatee.com>
+Description:   Product revision stored in the hardware (eg. RevB)
+               (read only)
+Values:        arbitrary string.
+
+
+What:          /sys/class/switchtec/switchtec[0-9]+/product_vendor
+Date:          05-Jan-2017
+KernelVersion: v4.11
+Contact:       Logan Gunthorpe <logang@deltatee.com>
+Description:   Product vendor as stored in the hardware (eg. MICROSEM)
+               (read only)
+Values:        arbitrary string.
index 147231f1613ef3a0a8df8d9addc2a754d5ac69af..00c9a90b6f3854050f1778961be557b10c25fa0d 100644 (file)
@@ -12,3 +12,13 @@ pci.txt
        - info on the PCI subsystem for device driver authors
 pcieaer-howto.txt
        - the PCI Express Advanced Error Reporting Driver Guide HOWTO
+endpoint/pci-endpoint.txt
+       - guide to add endpoint controller driver and endpoint function driver.
+endpoint/pci-endpoint-cfs.txt
+       - guide to use configfs to configure the PCI endpoint function.
+endpoint/pci-test-function.txt
+       - specification of *PCI test* function device.
+endpoint/pci-test-howto.txt
+       - userguide for PCI endpoint test function.
+endpoint/function/binding/
+       - binding documentation for PCI endpoint function
diff --git a/Documentation/PCI/endpoint/function/binding/pci-test.txt b/Documentation/PCI/endpoint/function/binding/pci-test.txt
new file mode 100644 (file)
index 0000000..3b68b95
--- /dev/null
@@ -0,0 +1,17 @@
+PCI TEST ENDPOINT FUNCTION
+
+name: Should be "pci_epf_test" to bind to the pci_epf_test driver.
+
+Configurable Fields:
+vendorid        : should be 0x104c
+deviceid        : should be 0xb500 for DRA74x and 0xb501 for DRA72x
+revid           : don't care
+progif_code     : don't care
+subclass_code   : don't care
+baseclass_code  : should be 0xff
+cache_line_size         : don't care
+subsys_vendor_id : don't care
+subsys_id       : don't care
+interrupt_pin   : Should be 1 - INTA, 2 - INTB, 3 - INTC, 4 -INTD
+msi_interrupts  : Should be 1 to 32 depending on the number of MSI interrupts
+                  to test
diff --git a/Documentation/PCI/endpoint/pci-endpoint-cfs.txt b/Documentation/PCI/endpoint/pci-endpoint-cfs.txt
new file mode 100644 (file)
index 0000000..d740f29
--- /dev/null
@@ -0,0 +1,105 @@
+                   CONFIGURING PCI ENDPOINT USING CONFIGFS
+                    Kishon Vijay Abraham I <kishon@ti.com>
+
+The PCI Endpoint Core exposes configfs entry (pci_ep) to configure the
+PCI endpoint function and to bind the endpoint function
+with the endpoint controller. (For introducing other mechanisms to
+configure the PCI Endpoint Function refer to [1]).
+
+*) Mounting configfs
+
+The PCI Endpoint Core layer creates pci_ep directory in the mounted configfs
+directory. configfs can be mounted using the following command.
+
+       mount -t configfs none /sys/kernel/config
+
+*) Directory Structure
+
+The pci_ep configfs has two directories at its root: controllers and
+functions. Every EPC device present in the system will have an entry in
+the *controllers* directory and and every EPF driver present in the system
+will have an entry in the *functions* directory.
+
+/sys/kernel/config/pci_ep/
+       .. controllers/
+       .. functions/
+
+*) Creating EPF Device
+
+Every registered EPF driver will be listed in controllers directory. The
+entries corresponding to EPF driver will be created by the EPF core.
+
+/sys/kernel/config/pci_ep/functions/
+       .. <EPF Driver1>/
+               ... <EPF Device 11>/
+               ... <EPF Device 21>/
+       .. <EPF Driver2>/
+               ... <EPF Device 12>/
+               ... <EPF Device 22>/
+
+In order to create a <EPF device> of the type probed by <EPF Driver>, the
+user has to create a directory inside <EPF DriverN>.
+
+Every <EPF device> directory consists of the following entries that can be
+used to configure the standard configuration header of the endpoint function.
+(These entries are created by the framework when any new <EPF Device> is
+created)
+
+       .. <EPF Driver1>/
+               ... <EPF Device 11>/
+                       ... vendorid
+                       ... deviceid
+                       ... revid
+                       ... progif_code
+                       ... subclass_code
+                       ... baseclass_code
+                       ... cache_line_size
+                       ... subsys_vendor_id
+                       ... subsys_id
+                       ... interrupt_pin
+
+*) EPC Device
+
+Every registered EPC device will be listed in controllers directory. The
+entries corresponding to EPC device will be created by the EPC core.
+
+/sys/kernel/config/pci_ep/controllers/
+       .. <EPC Device1>/
+               ... <Symlink EPF Device11>/
+               ... <Symlink EPF Device12>/
+               ... start
+       .. <EPC Device2>/
+               ... <Symlink EPF Device21>/
+               ... <Symlink EPF Device22>/
+               ... start
+
+The <EPC Device> directory will have a list of symbolic links to
+<EPF Device>. These symbolic links should be created by the user to
+represent the functions present in the endpoint device.
+
+The <EPC Device> directory will also have a *start* field. Once
+"1" is written to this field, the endpoint device will be ready to
+establish the link with the host. This is usually done after
+all the EPF devices are created and linked with the EPC device.
+
+
+                        | controllers/
+                               | <Directory: EPC name>/
+                                       | <Symbolic Link: Function>
+                                       | start
+                        | functions/
+                               | <Directory: EPF driver>/
+                                       | <Directory: EPF device>/
+                                               | vendorid
+                                               | deviceid
+                                               | revid
+                                               | progif_code
+                                               | subclass_code
+                                               | baseclass_code
+                                               | cache_line_size
+                                               | subsys_vendor_id
+                                               | subsys_id
+                                               | interrupt_pin
+                                               | function
+
+[1] -> Documentation/PCI/endpoint/pci-endpoint.txt
diff --git a/Documentation/PCI/endpoint/pci-endpoint.txt b/Documentation/PCI/endpoint/pci-endpoint.txt
new file mode 100644 (file)
index 0000000..9b1d668
--- /dev/null
@@ -0,0 +1,215 @@
+                           PCI ENDPOINT FRAMEWORK
+                   Kishon Vijay Abraham I <kishon@ti.com>
+
+This document is a guide to use the PCI Endpoint Framework in order to create
+endpoint controller driver, endpoint function driver, and using configfs
+interface to bind the function driver to the controller driver.
+
+1. Introduction
+
+Linux has a comprehensive PCI subsystem to support PCI controllers that
+operates in Root Complex mode. The subsystem has capability to scan PCI bus,
+assign memory resources and IRQ resources, load PCI driver (based on
+vendor ID, device ID), support other services like hot-plug, power management,
+advanced error reporting and virtual channels.
+
+However the PCI controller IP integrated in some SoCs is capable of operating
+either in Root Complex mode or Endpoint mode. PCI Endpoint Framework will
+add endpoint mode support in Linux. This will help to run Linux in an
+EP system which can have a wide variety of use cases from testing or
+validation, co-processor accelerator, etc.
+
+2. PCI Endpoint Core
+
+The PCI Endpoint Core layer comprises 3 components: the Endpoint Controller
+library, the Endpoint Function library, and the configfs layer to bind the
+endpoint function with the endpoint controller.
+
+2.1 PCI Endpoint Controller(EPC) Library
+
+The EPC library provides APIs to be used by the controller that can operate
+in endpoint mode. It also provides APIs to be used by function driver/library
+in order to implement a particular endpoint function.
+
+2.1.1 APIs for the PCI controller Driver
+
+This section lists the APIs that the PCI Endpoint core provides to be used
+by the PCI controller driver.
+
+*) devm_pci_epc_create()/pci_epc_create()
+
+   The PCI controller driver should implement the following ops:
+        * write_header: ops to populate configuration space header
+        * set_bar: ops to configure the BAR
+        * clear_bar: ops to reset the BAR
+        * alloc_addr_space: ops to allocate in PCI controller address space
+        * free_addr_space: ops to free the allocated address space
+        * raise_irq: ops to raise a legacy or MSI interrupt
+        * start: ops to start the PCI link
+        * stop: ops to stop the PCI link
+
+   The PCI controller driver can then create a new EPC device by invoking
+   devm_pci_epc_create()/pci_epc_create().
+
+*) devm_pci_epc_destroy()/pci_epc_destroy()
+
+   The PCI controller driver can destroy the EPC device created by either
+   devm_pci_epc_create() or pci_epc_create() using devm_pci_epc_destroy() or
+   pci_epc_destroy().
+
+*) pci_epc_linkup()
+
+   In order to notify all the function devices that the EPC device to which
+   they are linked has established a link with the host, the PCI controller
+   driver should invoke pci_epc_linkup().
+
+*) pci_epc_mem_init()
+
+   Initialize the pci_epc_mem structure used for allocating EPC addr space.
+
+*) pci_epc_mem_exit()
+
+   Cleanup the pci_epc_mem structure allocated during pci_epc_mem_init().
+
+2.1.2 APIs for the PCI Endpoint Function Driver
+
+This section lists the APIs that the PCI Endpoint core provides to be used
+by the PCI endpoint function driver.
+
+*) pci_epc_write_header()
+
+   The PCI endpoint function driver should use pci_epc_write_header() to
+   write the standard configuration header to the endpoint controller.
+
+*) pci_epc_set_bar()
+
+   The PCI endpoint function driver should use pci_epc_set_bar() to configure
+   the Base Address Register in order for the host to assign PCI addr space.
+   Register space of the function driver is usually configured
+   using this API.
+
+*) pci_epc_clear_bar()
+
+   The PCI endpoint function driver should use pci_epc_clear_bar() to reset
+   the BAR.
+
+*) pci_epc_raise_irq()
+
+   The PCI endpoint function driver should use pci_epc_raise_irq() to raise
+   Legacy Interrupt or MSI Interrupt.
+
+*) pci_epc_mem_alloc_addr()
+
+   The PCI endpoint function driver should use pci_epc_mem_alloc_addr(), to
+   allocate memory address from EPC addr space which is required to access
+   RC's buffer
+
+*) pci_epc_mem_free_addr()
+
+   The PCI endpoint function driver should use pci_epc_mem_free_addr() to
+   free the memory space allocated using pci_epc_mem_alloc_addr().
+
+2.1.3 Other APIs
+
+There are other APIs provided by the EPC library. These are used for binding
+the EPF device with EPC device. pci-ep-cfs.c can be used as reference for
+using these APIs.
+
+*) pci_epc_get()
+
+   Get a reference to the PCI endpoint controller based on the device name of
+   the controller.
+
+*) pci_epc_put()
+
+   Release the reference to the PCI endpoint controller obtained using
+   pci_epc_get()
+
+*) pci_epc_add_epf()
+
+   Add a PCI endpoint function to a PCI endpoint controller. A PCIe device
+   can have up to 8 functions according to the specification.
+
+*) pci_epc_remove_epf()
+
+   Remove the PCI endpoint function from PCI endpoint controller.
+
+*) pci_epc_start()
+
+   The PCI endpoint function driver should invoke pci_epc_start() once it
+   has configured the endpoint function and wants to start the PCI link.
+
+*) pci_epc_stop()
+
+   The PCI endpoint function driver should invoke pci_epc_stop() to stop
+   the PCI LINK.
+
+2.2 PCI Endpoint Function(EPF) Library
+
+The EPF library provides APIs to be used by the function driver and the EPC
+library to provide endpoint mode functionality.
+
+2.2.1 APIs for the PCI Endpoint Function Driver
+
+This section lists the APIs that the PCI Endpoint core provides to be used
+by the PCI endpoint function driver.
+
+*) pci_epf_register_driver()
+
+   The PCI Endpoint Function driver should implement the following ops:
+        * bind: ops to perform when a EPC device has been bound to EPF device
+        * unbind: ops to perform when a binding has been lost between a EPC
+          device and EPF device
+        * linkup: ops to perform when the EPC device has established a
+          connection with a host system
+
+  The PCI Function driver can then register the PCI EPF driver by using
+  pci_epf_register_driver().
+
+*) pci_epf_unregister_driver()
+
+  The PCI Function driver can unregister the PCI EPF driver by using
+  pci_epf_unregister_driver().
+
+*) pci_epf_alloc_space()
+
+  The PCI Function driver can allocate space for a particular BAR using
+  pci_epf_alloc_space().
+
+*) pci_epf_free_space()
+
+  The PCI Function driver can free the allocated space
+  (using pci_epf_alloc_space) by invoking pci_epf_free_space().
+
+2.2.2 APIs for the PCI Endpoint Controller Library
+This section lists the APIs that the PCI Endpoint core provides to be used
+by the PCI endpoint controller library.
+
+*) pci_epf_linkup()
+
+   The PCI endpoint controller library invokes pci_epf_linkup() when the
+   EPC device has established the connection to the host.
+
+2.2.2 Other APIs
+There are other APIs provided by the EPF library. These are used to notify
+the function driver when the EPF device is bound to the EPC device.
+pci-ep-cfs.c can be used as reference for using these APIs.
+
+*) pci_epf_create()
+
+   Create a new PCI EPF device by passing the name of the PCI EPF device.
+   This name will be used to bind the the EPF device to a EPF driver.
+
+*) pci_epf_destroy()
+
+   Destroy the created PCI EPF device.
+
+*) pci_epf_bind()
+
+   pci_epf_bind() should be invoked when the EPF device has been bound to
+   a EPC device.
+
+*) pci_epf_unbind()
+
+   pci_epf_unbind() should be invoked when the binding between EPC device
+   and EPF device is lost.
diff --git a/Documentation/PCI/endpoint/pci-test-function.txt b/Documentation/PCI/endpoint/pci-test-function.txt
new file mode 100644 (file)
index 0000000..0c519c9
--- /dev/null
@@ -0,0 +1,66 @@
+                               PCI TEST
+                   Kishon Vijay Abraham I <kishon@ti.com>
+
+Traditionally PCI RC has always been validated by using standard
+PCI cards like ethernet PCI cards or USB PCI cards or SATA PCI cards.
+However with the addition of EP-core in linux kernel, it is possible
+to configure a PCI controller that can operate in EP mode to work as
+a test device.
+
+The PCI endpoint test device is a virtual device (defined in software)
+used to test the endpoint functionality and serve as a sample driver
+for other PCI endpoint devices (to use the EP framework).
+
+The PCI endpoint test device has the following registers:
+
+       1) PCI_ENDPOINT_TEST_MAGIC
+       2) PCI_ENDPOINT_TEST_COMMAND
+       3) PCI_ENDPOINT_TEST_STATUS
+       4) PCI_ENDPOINT_TEST_SRC_ADDR
+       5) PCI_ENDPOINT_TEST_DST_ADDR
+       6) PCI_ENDPOINT_TEST_SIZE
+       7) PCI_ENDPOINT_TEST_CHECKSUM
+
+*) PCI_ENDPOINT_TEST_MAGIC
+
+This register will be used to test BAR0. A known pattern will be written
+and read back from MAGIC register to verify BAR0.
+
+*) PCI_ENDPOINT_TEST_COMMAND:
+
+This register will be used by the host driver to indicate the function
+that the endpoint device must perform.
+
+Bitfield Description:
+  Bit 0                : raise legacy IRQ
+  Bit 1                : raise MSI IRQ
+  Bit 2 - 7    : MSI interrupt number
+  Bit 8                : read command (read data from RC buffer)
+  Bit 9                : write command (write data to RC buffer)
+  Bit 10       : copy command (copy data from one RC buffer to another
+                 RC buffer)
+
+*) PCI_ENDPOINT_TEST_STATUS
+
+This register reflects the status of the PCI endpoint device.
+
+Bitfield Description:
+  Bit 0                : read success
+  Bit 1                : read fail
+  Bit 2                : write success
+  Bit 3                : write fail
+  Bit 4                : copy success
+  Bit 5                : copy fail
+  Bit 6                : IRQ raised
+  Bit 7                : source address is invalid
+  Bit 8                : destination address is invalid
+
+*) PCI_ENDPOINT_TEST_SRC_ADDR
+
+This register contains the source address (RC buffer address) for the
+COPY/READ command.
+
+*) PCI_ENDPOINT_TEST_DST_ADDR
+
+This register contains the destination address (RC buffer address) for
+the COPY/WRITE command.
diff --git a/Documentation/PCI/endpoint/pci-test-howto.txt b/Documentation/PCI/endpoint/pci-test-howto.txt
new file mode 100644 (file)
index 0000000..75f48c3
--- /dev/null
@@ -0,0 +1,179 @@
+                           PCI TEST USERGUIDE
+                   Kishon Vijay Abraham I <kishon@ti.com>
+
+This document is a guide to help users use pci-epf-test function driver
+and pci_endpoint_test host driver for testing PCI. The list of steps to
+be followed in the host side and EP side is given below.
+
+1. Endpoint Device
+
+1.1 Endpoint Controller Devices
+
+To find the list of endpoint controller devices in the system:
+
+       # ls /sys/class/pci_epc/
+         51000000.pcie_ep
+
+If PCI_ENDPOINT_CONFIGFS is enabled
+       # ls /sys/kernel/config/pci_ep/controllers
+         51000000.pcie_ep
+
+1.2 Endpoint Function Drivers
+
+To find the list of endpoint function drivers in the system:
+
+       # ls /sys/bus/pci-epf/drivers
+         pci_epf_test
+
+If PCI_ENDPOINT_CONFIGFS is enabled
+       # ls /sys/kernel/config/pci_ep/functions
+         pci_epf_test
+
+1.3 Creating pci-epf-test Device
+
+PCI endpoint function device can be created using the configfs. To create
+pci-epf-test device, the following commands can be used
+
+       # mount -t configfs none /sys/kernel/config
+       # cd /sys/kernel/config/pci_ep/
+       # mkdir functions/pci_epf_test/func1
+
+The "mkdir func1" above creates the pci-epf-test function device that will
+be probed by pci_epf_test driver.
+
+The PCI endpoint framework populates the directory with the following
+configurable fields.
+
+       # ls functions/pci_epf_test/func1
+         baseclass_code        interrupt_pin   revid           subsys_vendor_id
+         cache_line_size       msi_interrupts  subclass_code   vendorid
+         deviceid              progif_code     subsys_id
+
+The PCI endpoint function driver populates these entries with default values
+when the device is bound to the driver. The pci-epf-test driver populates
+vendorid with 0xffff and interrupt_pin with 0x0001
+
+       # cat functions/pci_epf_test/func1/vendorid
+         0xffff
+       # cat functions/pci_epf_test/func1/interrupt_pin
+         0x0001
+
+1.4 Configuring pci-epf-test Device
+
+The user can configure the pci-epf-test device using configfs entry. In order
+to change the vendorid and the number of MSI interrupts used by the function
+device, the following commands can be used.
+
+       # echo 0x104c > functions/pci_epf_test/func1/vendorid
+       # echo 0xb500 > functions/pci_epf_test/func1/deviceid
+       # echo 16 > functions/pci_epf_test/func1/msi_interrupts
+
+1.5 Binding pci-epf-test Device to EP Controller
+
+In order for the endpoint function device to be useful, it has to be bound to
+a PCI endpoint controller driver. Use the configfs to bind the function
+device to one of the controller driver present in the system.
+
+       # ln -s functions/pci_epf_test/func1 controllers/51000000.pcie_ep/
+
+Once the above step is completed, the PCI endpoint is ready to establish a link
+with the host.
+
+1.6 Start the Link
+
+In order for the endpoint device to establish a link with the host, the _start_
+field should be populated with '1'.
+
+       # echo 1 > controllers/51000000.pcie_ep/start
+
+2. RootComplex Device
+
+2.1 lspci Output
+
+Note that the devices listed here correspond to the value populated in 1.4 above
+
+       00:00.0 PCI bridge: Texas Instruments Device 8888 (rev 01)
+       01:00.0 Unassigned class [ff00]: Texas Instruments Device b500
+
+2.2 Using Endpoint Test function Device
+
+pcitest.sh added in tools/pci/ can be used to run all the default PCI endpoint
+tests. Before pcitest.sh can be used pcitest.c should be compiled using the
+following commands.
+
+       cd <kernel-dir>
+       make headers_install ARCH=arm
+       arm-linux-gnueabihf-gcc -Iusr/include tools/pci/pcitest.c -o pcitest
+       cp pcitest  <rootfs>/usr/sbin/
+       cp tools/pci/pcitest.sh <rootfs>
+
+2.2.1 pcitest.sh Output
+       # ./pcitest.sh
+       BAR tests
+
+       BAR0:           OKAY
+       BAR1:           OKAY
+       BAR2:           OKAY
+       BAR3:           OKAY
+       BAR4:           NOT OKAY
+       BAR5:           NOT OKAY
+
+       Interrupt tests
+
+       LEGACY IRQ:     NOT OKAY
+       MSI1:           OKAY
+       MSI2:           OKAY
+       MSI3:           OKAY
+       MSI4:           OKAY
+       MSI5:           OKAY
+       MSI6:           OKAY
+       MSI7:           OKAY
+       MSI8:           OKAY
+       MSI9:           OKAY
+       MSI10:          OKAY
+       MSI11:          OKAY
+       MSI12:          OKAY
+       MSI13:          OKAY
+       MSI14:          OKAY
+       MSI15:          OKAY
+       MSI16:          OKAY
+       MSI17:          NOT OKAY
+       MSI18:          NOT OKAY
+       MSI19:          NOT OKAY
+       MSI20:          NOT OKAY
+       MSI21:          NOT OKAY
+       MSI22:          NOT OKAY
+       MSI23:          NOT OKAY
+       MSI24:          NOT OKAY
+       MSI25:          NOT OKAY
+       MSI26:          NOT OKAY
+       MSI27:          NOT OKAY
+       MSI28:          NOT OKAY
+       MSI29:          NOT OKAY
+       MSI30:          NOT OKAY
+       MSI31:          NOT OKAY
+       MSI32:          NOT OKAY
+
+       Read Tests
+
+       READ (      1 bytes):           OKAY
+       READ (   1024 bytes):           OKAY
+       READ (   1025 bytes):           OKAY
+       READ (1024000 bytes):           OKAY
+       READ (1024001 bytes):           OKAY
+
+       Write Tests
+
+       WRITE (      1 bytes):          OKAY
+       WRITE (   1024 bytes):          OKAY
+       WRITE (   1025 bytes):          OKAY
+       WRITE (1024000 bytes):          OKAY
+       WRITE (1024001 bytes):          OKAY
+
+       Copy Tests
+
+       COPY (      1 bytes):           OKAY
+       COPY (   1024 bytes):           OKAY
+       COPY (   1025 bytes):           OKAY
+       COPY (1024000 bytes):           OKAY
+       COPY (1024001 bytes):           OKAY
index 2d91ae25198295dc8559d2ef8d00cae1b5314989..d2a84151e99c0a37242d5dd754a3e571ab58ac53 100644 (file)
@@ -68,6 +68,18 @@ To disable SR-IOV capability:
        echo  0 > \
         /sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_numvfs
 
+To enable auto probing VFs by a compatible driver on the host, run
+command below before enabling SR-IOV capabilities. This is the
+default behavior.
+       echo 1 > \
+        /sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_drivers_autoprobe
+
+To disable auto probing VFs by a compatible driver on the host, run
+command below before enabling SR-IOV capabilities. Updating this
+entry will not affect VFs which are already probed.
+       echo  0 > \
+        /sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_drivers_autoprobe
+
 3.2 Usage example
 
 Following piece of code illustrates the usage of the SR-IOV API.
index f773a264ae02918ef6b79f002ff17d0bd4e5df65..1672573b037a73ebe4b169f7044e525b7a4bf246 100644 (file)
@@ -17,7 +17,7 @@ rcu_dereference.txt
 rcubarrier.txt
        - RCU and Unloadable Modules
 rculist_nulls.txt
-       - RCU list primitives for use with SLAB_DESTROY_BY_RCU
+       - RCU list primitives for use with SLAB_TYPESAFE_BY_RCU
 rcuref.txt
        - Reference-count design for elements of lists/arrays protected by RCU
 rcu.txt
index d583c653a703f0645c10c11cd8c1dfe761095cd6..38d6d800761f7cd944c7b290eeea19dbc0d3866e 100644 (file)
@@ -19,6 +19,8 @@ to each other.
        The <tt>rcu_state</tt> Structure</a>
 <li>   <a href="#The rcu_node Structure">
        The <tt>rcu_node</tt> Structure</a>
+<li>   <a href="#The rcu_segcblist Structure">
+       The <tt>rcu_segcblist</tt> Structure</a>
 <li>   <a href="#The rcu_data Structure">
        The <tt>rcu_data</tt> Structure</a>
 <li>   <a href="#The rcu_dynticks Structure">
@@ -841,6 +843,134 @@ for lockdep lock-class names.
 Finally, lines&nbsp;64-66 produce an error if the maximum number of
 CPUs is too large for the specified fanout.
 
+<h3><a name="The rcu_segcblist Structure">
+The <tt>rcu_segcblist</tt> Structure</a></h3>
+
+The <tt>rcu_segcblist</tt> structure maintains a segmented list of
+callbacks as follows:
+
+<pre>
+ 1 #define RCU_DONE_TAIL        0
+ 2 #define RCU_WAIT_TAIL        1
+ 3 #define RCU_NEXT_READY_TAIL  2
+ 4 #define RCU_NEXT_TAIL        3
+ 5 #define RCU_CBLIST_NSEGS     4
+ 6
+ 7 struct rcu_segcblist {
+ 8   struct rcu_head *head;
+ 9   struct rcu_head **tails[RCU_CBLIST_NSEGS];
+10   unsigned long gp_seq[RCU_CBLIST_NSEGS];
+11   long len;
+12   long len_lazy;
+13 };
+</pre>
+
+<p>
+The segments are as follows:
+
+<ol>
+<li>   <tt>RCU_DONE_TAIL</tt>: Callbacks whose grace periods have elapsed.
+       These callbacks are ready to be invoked.
+<li>   <tt>RCU_WAIT_TAIL</tt>: Callbacks that are waiting for the
+       current grace period.
+       Note that different CPUs can have different ideas about which
+       grace period is current, hence the <tt>-&gt;gp_seq</tt> field.
+<li>   <tt>RCU_NEXT_READY_TAIL</tt>: Callbacks waiting for the next
+       grace period to start.
+<li>   <tt>RCU_NEXT_TAIL</tt>: Callbacks that have not yet been
+       associated with a grace period.
+</ol>
+
+<p>
+The <tt>-&gt;head</tt> pointer references the first callback or
+is <tt>NULL</tt> if the list contains no callbacks (which is
+<i>not</i> the same as being empty).
+Each element of the <tt>-&gt;tails[]</tt> array references the
+<tt>-&gt;next</tt> pointer of the last callback in the corresponding
+segment of the list, or the list's <tt>-&gt;head</tt> pointer if
+that segment and all previous segments are empty.
+If the corresponding segment is empty but some previous segment is
+not empty, then the array element is identical to its predecessor.
+Older callbacks are closer to the head of the list, and new callbacks
+are added at the tail.
+This relationship between the <tt>-&gt;head</tt> pointer, the
+<tt>-&gt;tails[]</tt> array, and the callbacks is shown in this
+diagram:
+
+</p><p><img src="nxtlist.svg" alt="nxtlist.svg" width="40%">
+
+</p><p>In this figure, the <tt>-&gt;head</tt> pointer references the
+first
+RCU callback in the list.
+The <tt>-&gt;tails[RCU_DONE_TAIL]</tt> array element references
+the <tt>-&gt;head</tt> pointer itself, indicating that none
+of the callbacks is ready to invoke.
+The <tt>-&gt;tails[RCU_WAIT_TAIL]</tt> array element references callback
+CB&nbsp;2's <tt>-&gt;next</tt> pointer, which indicates that
+CB&nbsp;1 and CB&nbsp;2 are both waiting on the current grace period,
+give or take possible disagreements about exactly which grace period
+is the current one.
+The <tt>-&gt;tails[RCU_NEXT_READY_TAIL]</tt> array element
+references the same RCU callback that <tt>-&gt;tails[RCU_WAIT_TAIL]</tt>
+does, which indicates that there are no callbacks waiting on the next
+RCU grace period.
+The <tt>-&gt;tails[RCU_NEXT_TAIL]</tt> array element references
+CB&nbsp;4's <tt>-&gt;next</tt> pointer, indicating that all the
+remaining RCU callbacks have not yet been assigned to an RCU grace
+period.
+Note that the <tt>-&gt;tails[RCU_NEXT_TAIL]</tt> array element
+always references the last RCU callback's <tt>-&gt;next</tt> pointer
+unless the callback list is empty, in which case it references
+the <tt>-&gt;head</tt> pointer.
+
+<p>
+There is one additional important special case for the
+<tt>-&gt;tails[RCU_NEXT_TAIL]</tt> array element: It can be <tt>NULL</tt>
+when this list is <i>disabled</i>.
+Lists are disabled when the corresponding CPU is offline or when
+the corresponding CPU's callbacks are offloaded to a kthread,
+both of which are described elsewhere.
+
+</p><p>CPUs advance their callbacks from the
+<tt>RCU_NEXT_TAIL</tt> to the <tt>RCU_NEXT_READY_TAIL</tt> to the
+<tt>RCU_WAIT_TAIL</tt> to the <tt>RCU_DONE_TAIL</tt> list segments
+as grace periods advance.
+
+</p><p>The <tt>-&gt;gp_seq[]</tt> array records grace-period
+numbers corresponding to the list segments.
+This is what allows different CPUs to have different ideas as to
+which is the current grace period while still avoiding premature
+invocation of their callbacks.
+In particular, this allows CPUs that go idle for extended periods
+to determine which of their callbacks are ready to be invoked after
+reawakening.
+
+</p><p>The <tt>-&gt;len</tt> counter contains the number of
+callbacks in <tt>-&gt;head</tt>, and the
+<tt>-&gt;len_lazy</tt> contains the number of those callbacks that
+are known to only free memory, and whose invocation can therefore
+be safely deferred.
+
+<p><b>Important note</b>: It is the <tt>-&gt;len</tt> field that
+determines whether or not there are callbacks associated with
+this <tt>rcu_segcblist</tt> structure, <i>not</i> the <tt>-&gt;head</tt>
+pointer.
+The reason for this is that all the ready-to-invoke callbacks
+(that is, those in the <tt>RCU_DONE_TAIL</tt> segment) are extracted
+all at once at callback-invocation time.
+If callback invocation must be postponed, for example, because a
+high-priority process just woke up on this CPU, then the remaining
+callbacks are placed back on the <tt>RCU_DONE_TAIL</tt> segment.
+Either way, the <tt>-&gt;len</tt> and <tt>-&gt;len_lazy</tt> counts
+are adjusted after the corresponding callbacks have been invoked, and so
+again it is the <tt>-&gt;len</tt> count that accurately reflects whether
+or not there are callbacks associated with this <tt>rcu_segcblist</tt>
+structure.
+Of course, off-CPU sampling of the <tt>-&gt;len</tt> count requires
+the use of appropriate synchronization, for example, memory barriers.
+This synchronization can be a bit subtle, particularly in the case
+of <tt>rcu_barrier()</tt>.
+
 <h3><a name="The rcu_data Structure">
 The <tt>rcu_data</tt> Structure</a></h3>
 
@@ -983,62 +1113,18 @@ choice.
 as follows:
 
 <pre>
- 1 struct rcu_head *nxtlist;
- 2 struct rcu_head **nxttail[RCU_NEXT_SIZE];
- 3 unsigned long nxtcompleted[RCU_NEXT_SIZE];
- 4 long qlen_lazy;
- 5 long qlen;
- 6 long qlen_last_fqs_check;
+ 1 struct rcu_segcblist cblist;
+ 2 long qlen_last_fqs_check;
+ 3 unsigned long n_cbs_invoked;
+ 4 unsigned long n_nocbs_invoked;
+ 5 unsigned long n_cbs_orphaned;
+ 6 unsigned long n_cbs_adopted;
  7 unsigned long n_force_qs_snap;
- 8 unsigned long n_cbs_invoked;
- 9 unsigned long n_cbs_orphaned;
-10 unsigned long n_cbs_adopted;
-11 long blimit;
+ 8 long blimit;
 </pre>
 
-<p>The <tt>-&gt;nxtlist</tt> pointer and the
-<tt>-&gt;nxttail[]</tt> array form a four-segment list with
-older callbacks near the head and newer ones near the tail.
-Each segment contains callbacks with the corresponding relationship
-to the current grace period.
-The pointer out of the end of each of the four segments is referenced
-by the element of the <tt>-&gt;nxttail[]</tt> array indexed by
-<tt>RCU_DONE_TAIL</tt> (for callbacks handled by a prior grace period),
-<tt>RCU_WAIT_TAIL</tt> (for callbacks waiting on the current grace period),
-<tt>RCU_NEXT_READY_TAIL</tt> (for callbacks that will wait on the next
-grace period), and
-<tt>RCU_NEXT_TAIL</tt> (for callbacks that are not yet associated
-with a specific grace period)
-respectively, as shown in the following figure.
-
-</p><p><img src="nxtlist.svg" alt="nxtlist.svg" width="40%">
-
-</p><p>In this figure, the <tt>-&gt;nxtlist</tt> pointer references the
-first
-RCU callback in the list.
-The <tt>-&gt;nxttail[RCU_DONE_TAIL]</tt> array element references
-the <tt>-&gt;nxtlist</tt> pointer itself, indicating that none
-of the callbacks is ready to invoke.
-The <tt>-&gt;nxttail[RCU_WAIT_TAIL]</tt> array element references callback
-CB&nbsp;2's <tt>-&gt;next</tt> pointer, which indicates that
-CB&nbsp;1 and CB&nbsp;2 are both waiting on the current grace period.
-The <tt>-&gt;nxttail[RCU_NEXT_READY_TAIL]</tt> array element
-references the same RCU callback that <tt>-&gt;nxttail[RCU_WAIT_TAIL]</tt>
-does, which indicates that there are no callbacks waiting on the next
-RCU grace period.
-The <tt>-&gt;nxttail[RCU_NEXT_TAIL]</tt> array element references
-CB&nbsp;4's <tt>-&gt;next</tt> pointer, indicating that all the
-remaining RCU callbacks have not yet been assigned to an RCU grace
-period.
-Note that the <tt>-&gt;nxttail[RCU_NEXT_TAIL]</tt> array element
-always references the last RCU callback's <tt>-&gt;next</tt> pointer
-unless the callback list is empty, in which case it references
-the <tt>-&gt;nxtlist</tt> pointer.
-
-</p><p>CPUs advance their callbacks from the
-<tt>RCU_NEXT_TAIL</tt> to the <tt>RCU_NEXT_READY_TAIL</tt> to the
-<tt>RCU_WAIT_TAIL</tt> to the <tt>RCU_DONE_TAIL</tt> list segments
-as grace periods advance.
+<p>The <tt>-&gt;cblist</tt> structure is the segmented callback list
+described earlier.
 The CPU advances the callbacks in its <tt>rcu_data</tt> structure
 whenever it notices that another RCU grace period has completed.
 The CPU detects the completion of an RCU grace period by noticing
@@ -1049,16 +1135,7 @@ Recall that each <tt>rcu_node</tt> structure's
 <tt>-&gt;completed</tt> field is updated at the end of each
 grace period.
 
-</p><p>The <tt>-&gt;nxtcompleted[]</tt> array records grace-period
-numbers corresponding to the list segments.
-This allows CPUs that go idle for extended periods to determine
-which of their callbacks are ready to be invoked after reawakening.
-
-</p><p>The <tt>-&gt;qlen</tt> counter contains the number of
-callbacks in <tt>-&gt;nxtlist</tt>, and the
-<tt>-&gt;qlen_lazy</tt> contains the number of those callbacks that
-are known to only free memory, and whose invocation can therefore
-be safely deferred.
+<p>
 The <tt>-&gt;qlen_last_fqs_check</tt> and
 <tt>-&gt;n_force_qs_snap</tt> coordinate the forcing of quiescent
 states from <tt>call_rcu()</tt> and friends when callback
@@ -1069,6 +1146,10 @@ lists grow excessively long.
 fields count the number of callbacks invoked,
 sent to other CPUs when this CPU goes offline,
 and received from other CPUs when those other CPUs go offline.
+The <tt>-&gt;n_nocbs_invoked</tt> is used when the CPU's callbacks
+are offloaded to a kthread.
+
+<p>
 Finally, the <tt>-&gt;blimit</tt> counter is the maximum number of
 RCU callbacks that may be invoked at a given time.
 
@@ -1104,6 +1185,9 @@ Its fields are as follows:
   1   int dynticks_nesting;
   2   int dynticks_nmi_nesting;
   3   atomic_t dynticks;
+  4   bool rcu_need_heavy_qs;
+  5   unsigned long rcu_qs_ctr;
+  6   bool rcu_urgent_qs;
 </pre>
 
 <p>The <tt>-&gt;dynticks_nesting</tt> field counts the
@@ -1117,11 +1201,32 @@ NMIs are counted by the <tt>-&gt;dynticks_nmi_nesting</tt>
 field, except that NMIs that interrupt non-dyntick-idle execution
 are not counted.
 
-</p><p>Finally, the <tt>-&gt;dynticks</tt> field counts the corresponding
+</p><p>The <tt>-&gt;dynticks</tt> field counts the corresponding
 CPU's transitions to and from dyntick-idle mode, so that this counter
 has an even value when the CPU is in dyntick-idle mode and an odd
 value otherwise.
 
+</p><p>The <tt>-&gt;rcu_need_heavy_qs</tt> field is used
+to record the fact that the RCU core code would really like to
+see a quiescent state from the corresponding CPU, so much so that
+it is willing to call for heavy-weight dyntick-counter operations.
+This flag is checked by RCU's context-switch and <tt>cond_resched()</tt>
+code, which provide a momentary idle sojourn in response.
+
+</p><p>The <tt>-&gt;rcu_qs_ctr</tt> field is used to record
+quiescent states from <tt>cond_resched()</tt>.
+Because <tt>cond_resched()</tt> can execute quite frequently, this
+must be quite lightweight, as in a non-atomic increment of this
+per-CPU field.
+
+</p><p>Finally, the <tt>-&gt;rcu_urgent_qs</tt> field is used to record
+the fact that the RCU core code would really like to see a quiescent
+state from the corresponding CPU, with the various other fields indicating
+just how badly RCU wants this quiescent state.
+This flag is checked by RCU's context-switch and <tt>cond_resched()</tt>
+code, which, if nothing else, non-atomically increment <tt>-&gt;rcu_qs_ctr</tt>
+in response.
+
 <table>
 <tr><th>&nbsp;</th></tr>
 <tr><th align="left">Quick Quiz:</th></tr>
index abc4cc73a0977195317d7a0397f1f5e7c52f35b3..0223e79c38e0036373dcfc919b7296bd87fa300e 100644 (file)
@@ -19,7 +19,7 @@
    id="svg2"
    version="1.1"
    inkscape:version="0.48.4 r9939"
-   sodipodi:docname="nxtlist.fig">
+   sodipodi:docname="segcblist.svg">
   <metadata
      id="metadata94">
     <rdf:RDF>
@@ -28,7 +28,7 @@
         <dc:format>image/svg+xml</dc:format>
         <dc:type
            rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
-        <dc:title></dc:title>
+        <dc:title />
       </cc:Work>
     </rdf:RDF>
   </metadata>
        xml:space="preserve"
        x="225"
        y="675"
-       fill="#000000"
-       font-family="Courier"
        font-style="normal"
        font-weight="bold"
        font-size="324"
-       text-anchor="start"
-       id="text64">nxtlist</text>
+       id="text64"
+       style="font-size:324px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;font-family:Courier">-&gt;head</text>
     <!-- Text -->
     <text
        xml:space="preserve"
        x="225"
        y="1800"
-       fill="#000000"
-       font-family="Courier"
        font-style="normal"
        font-weight="bold"
        font-size="324"
-       text-anchor="start"
-       id="text66">nxttail[RCU_DONE_TAIL]</text>
+       id="text66"
+       style="font-size:324px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;font-family:Courier">-&gt;tails[RCU_DONE_TAIL]</text>
     <!-- Text -->
     <text
        xml:space="preserve"
        x="225"
        y="2925"
-       fill="#000000"
-       font-family="Courier"
        font-style="normal"
        font-weight="bold"
        font-size="324"
-       text-anchor="start"
-       id="text68">nxttail[RCU_WAIT_TAIL]</text>
+       id="text68"
+       style="font-size:324px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;font-family:Courier">-&gt;tails[RCU_WAIT_TAIL]</text>
     <!-- Text -->
     <text
        xml:space="preserve"
        x="225"
        y="4050"
-       fill="#000000"
-       font-family="Courier"
        font-style="normal"
        font-weight="bold"
        font-size="324"
-       text-anchor="start"
-       id="text70">nxttail[RCU_NEXT_READY_TAIL]</text>
+       id="text70"
+       style="font-size:324px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;font-family:Courier">-&gt;tails[RCU_NEXT_READY_TAIL]</text>
     <!-- Text -->
     <text
        xml:space="preserve"
        x="225"
        y="5175"
-       fill="#000000"
-       font-family="Courier"
        font-style="normal"
        font-weight="bold"
        font-size="324"
-       text-anchor="start"
-       id="text72">nxttail[RCU_NEXT_TAIL]</text>
+       id="text72"
+       style="font-size:324px;font-style:normal;font-weight:bold;text-anchor:start;fill:#000000;font-family:Courier">-&gt;tails[RCU_NEXT_TAIL]</text>
     <!-- Text -->
     <text
        xml:space="preserve"
index 7a3194c5559a52c5d38994192e61c19ba45cbee2..e5d0bbd0230b4954a8d6aae50f77ce9446640255 100644 (file)
@@ -284,6 +284,7 @@ Expedited Grace Period Refinements</a></h2>
        Funnel locking and wait/wakeup</a>.
 <li>   <a href="#Use of Workqueues">Use of Workqueues</a>.
 <li>   <a href="#Stall Warnings">Stall warnings</a>.
+<li>   <a href="#Mid-Boot Operation">Mid-boot operation</a>.
 </ol>
 
 <h3><a name="Idle-CPU Checks">Idle-CPU Checks</a></h3>
@@ -524,7 +525,7 @@ their grace periods and carrying out their wakeups.
 In earlier implementations, the task requesting the expedited
 grace period also drove it to completion.
 This straightforward approach had the disadvantage of needing to
-account for signals sent to user tasks,
+account for POSIX signals sent to user tasks,
 so more recent implemementations use the Linux kernel's
 <a href="https://www.kernel.org/doc/Documentation/workqueue.txt">workqueues</a>.
 
@@ -533,8 +534,8 @@ The requesting task still does counter snapshotting and funnel-lock
 processing, but the task reaching the top of the funnel lock
 does a <tt>schedule_work()</tt> (from <tt>_synchronize_rcu_expedited()</tt>
 so that a workqueue kthread does the actual grace-period processing.
-Because workqueue kthreads do not accept signals, grace-period-wait
-processing need not allow for signals.
+Because workqueue kthreads do not accept POSIX signals, grace-period-wait
+processing need not allow for POSIX signals.
 
 In addition, this approach allows wakeups for the previous expedited
 grace period to be overlapped with processing for the next expedited
@@ -586,6 +587,46 @@ blocking the current grace period are printed.
 Each stall warning results in another pass through the loop, but the
 second and subsequent passes use longer stall times.
 
+<h3><a name="Mid-Boot Operation">Mid-boot operation</a></h3>
+
+<p>
+The use of workqueues has the advantage that the expedited
+grace-period code need not worry about POSIX signals.
+Unfortunately, it has the
+corresponding disadvantage that workqueues cannot be used until
+they are initialized, which does not happen until some time after
+the scheduler spawns the first task.
+Given that there are parts of the kernel that really do want to
+execute grace periods during this mid-boot &ldquo;dead zone&rdquo;,
+expedited grace periods must do something else during thie time.
+
+<p>
+What they do is to fall back to the old practice of requiring that the
+requesting task drive the expedited grace period, as was the case
+before the use of workqueues.
+However, the requesting task is only required to drive the grace period
+during the mid-boot dead zone.
+Before mid-boot, a synchronous grace period is a no-op.
+Some time after mid-boot, workqueues are used.
+
+<p>
+Non-expedited non-SRCU synchronous grace periods must also operate
+normally during mid-boot.
+This is handled by causing non-expedited grace periods to take the
+expedited code path during mid-boot.
+
+<p>
+The current code assumes that there are no POSIX signals during
+the mid-boot dead zone.
+However, if an overwhelming need for POSIX signals somehow arises,
+appropriate adjustments can be made to the expedited stall-warning code.
+One such adjustment would reinstate the pre-workqueue stall-warning
+checks, but only during the mid-boot dead zone.
+
+<p>
+With this refinement, synchronous grace periods can now be used from
+task context pretty much any time during the life of the kernel.
+
 <h3><a name="Summary">
 Summary</a></h3>
 
index 21593496aca6f617957b667f4f3aa5d627e86c4d..f60adf112663aad038e928e7b7cce04a65752277 100644 (file)
@@ -659,8 +659,9 @@ systems with more than one CPU:
        In other words, a given instance of <tt>synchronize_rcu()</tt>
        can avoid waiting on a given RCU read-side critical section only
        if it can prove that <tt>synchronize_rcu()</tt> started first.
+       </font>
 
-       <p>
+       <p><font color="ffffff">
        A related question is &ldquo;When <tt>rcu_read_lock()</tt>
        doesn't generate any code, why does it matter how it relates
        to a grace period?&rdquo;
@@ -675,8 +676,9 @@ systems with more than one CPU:
        within the critical section, in which case none of the accesses
        within the critical section may observe the effects of any
        access following the grace period.
+       </font>
 
-       <p>
+       <p><font color="ffffff">
        As of late 2016, mathematical models of RCU take this
        viewpoint, for example, see slides&nbsp;62 and&nbsp;63
        of the
@@ -1616,8 +1618,8 @@ CPUs should at least make reasonable forward progress.
 In return for its shorter latencies, <tt>synchronize_rcu_expedited()</tt>
 is permitted to impose modest degradation of real-time latency
 on non-idle online CPUs.
-That said, it will likely be necessary to take further steps to reduce this
-degradation, hopefully to roughly that of a scheduling-clock interrupt.
+Here, &ldquo;modest&rdquo; means roughly the same latency
+degradation as a scheduling-clock interrupt.
 
 <p>
 There are a number of situations where even
@@ -1913,12 +1915,9 @@ This requirement is another factor driving batching of grace periods,
 but it is also the driving force behind the checks for large numbers
 of queued RCU callbacks in the <tt>call_rcu()</tt> code path.
 Finally, high update rates should not delay RCU read-side critical
-sections, although some read-side delays can occur when using
+sections, although some small read-side delays can occur when using
 <tt>synchronize_rcu_expedited()</tt>, courtesy of this function's use
-of <tt>try_stop_cpus()</tt>.
-(In the future, <tt>synchronize_rcu_expedited()</tt> will be
-converted to use lighter-weight inter-processor interrupts (IPIs),
-but this will still disturb readers, though to a much smaller degree.)
+of <tt>smp_call_function_single()</tt>.
 
 <p>
 Although all three of these corner cases were understood in the early
@@ -2154,7 +2153,8 @@ as will <tt>rcu_assign_pointer()</tt>.
 <p>
 Although <tt>call_rcu()</tt> may be invoked at any
 time during boot, callbacks are not guaranteed to be invoked until after
-the scheduler is fully up and running.
+all of RCU's kthreads have been spawned, which occurs at
+<tt>early_initcall()</tt> time.
 This delay in callback invocation is due to the fact that RCU does not
 invoke callbacks until it is fully initialized, and this full initialization
 cannot occur until after the scheduler has initialized itself to the
@@ -2167,8 +2167,10 @@ on what operations those callbacks could invoke.
 Perhaps surprisingly, <tt>synchronize_rcu()</tt>,
 <a href="#Bottom-Half Flavor"><tt>synchronize_rcu_bh()</tt></a>
 (<a href="#Bottom-Half Flavor">discussed below</a>),
-and
-<a href="#Sched Flavor"><tt>synchronize_sched()</tt></a>
+<a href="#Sched Flavor"><tt>synchronize_sched()</tt></a>,
+<tt>synchronize_rcu_expedited()</tt>,
+<tt>synchronize_rcu_bh_expedited()</tt>, and
+<tt>synchronize_sched_expedited()</tt>
 will all operate normally
 during very early boot, the reason being that there is only one CPU
 and preemption is disabled.
@@ -2178,45 +2180,59 @@ state and thus a grace period, so the early-boot implementation can
 be a no-op.
 
 <p>
-Both <tt>synchronize_rcu_bh()</tt> and <tt>synchronize_sched()</tt>
-continue to operate normally through the remainder of boot, courtesy
-of the fact that preemption is disabled across their RCU read-side
-critical sections and also courtesy of the fact that there is still
-only one CPU.
-However, once the scheduler starts initializing, preemption is enabled.
-There is still only a single CPU, but the fact that preemption is enabled
-means that the no-op implementation of <tt>synchronize_rcu()</tt> no
-longer works in <tt>CONFIG_PREEMPT=y</tt> kernels.
-Therefore, as soon as the scheduler starts initializing, the early-boot
-fastpath is disabled.
-This means that <tt>synchronize_rcu()</tt> switches to its runtime
-mode of operation where it posts callbacks, which in turn means that
-any call to <tt>synchronize_rcu()</tt> will block until the corresponding
-callback is invoked.
-Unfortunately, the callback cannot be invoked until RCU's runtime
-grace-period machinery is up and running, which cannot happen until
-the scheduler has initialized itself sufficiently to allow RCU's
-kthreads to be spawned.
-Therefore, invoking <tt>synchronize_rcu()</tt> during scheduler
-initialization can result in deadlock.
+However, once the scheduler has spawned its first kthread, this early
+boot trick fails for <tt>synchronize_rcu()</tt> (as well as for
+<tt>synchronize_rcu_expedited()</tt>) in <tt>CONFIG_PREEMPT=y</tt>
+kernels.
+The reason is that an RCU read-side critical section might be preempted,
+which means that a subsequent <tt>synchronize_rcu()</tt> really does have
+to wait for something, as opposed to simply returning immediately.
+Unfortunately, <tt>synchronize_rcu()</tt> can't do this until all of
+its kthreads are spawned, which doesn't happen until some time during
+<tt>early_initcalls()</tt> time.
+But this is no excuse:  RCU is nevertheless required to correctly handle
+synchronous grace periods during this time period.
+Once all of its kthreads are up and running, RCU starts running
+normally.
 
 <table>
 <tr><th>&nbsp;</th></tr>
 <tr><th align="left">Quick Quiz:</th></tr>
 <tr><td>
-       So what happens with <tt>synchronize_rcu()</tt> during
-       scheduler initialization for <tt>CONFIG_PREEMPT=n</tt>
-       kernels?
+       How can RCU possibly handle grace periods before all of its
+       kthreads have been spawned???
 </td></tr>
 <tr><th align="left">Answer:</th></tr>
 <tr><td bgcolor="#ffffff"><font color="ffffff">
-       In <tt>CONFIG_PREEMPT=n</tt> kernel, <tt>synchronize_rcu()</tt>
-       maps directly to <tt>synchronize_sched()</tt>.
-       Therefore, <tt>synchronize_rcu()</tt> works normally throughout
-       boot in <tt>CONFIG_PREEMPT=n</tt> kernels.
-       However, your code must also work in <tt>CONFIG_PREEMPT=y</tt> kernels,
-       so it is still necessary to avoid invoking <tt>synchronize_rcu()</tt>
-       during scheduler initialization.
+       Very carefully!
+       </font>
+
+       <p><font color="ffffff">
+       During the &ldquo;dead zone&rdquo; between the time that the
+       scheduler spawns the first task and the time that all of RCU's
+       kthreads have been spawned, all synchronous grace periods are
+       handled by the expedited grace-period mechanism.
+       At runtime, this expedited mechanism relies on workqueues, but
+       during the dead zone the requesting task itself drives the
+       desired expedited grace period.
+       Because dead-zone execution takes place within task context,
+       everything works.
+       Once the dead zone ends, expedited grace periods go back to
+       using workqueues, as is required to avoid problems that would
+       otherwise occur when a user task received a POSIX signal while
+       driving an expedited grace period.
+       </font>
+
+       <p><font color="ffffff">
+       And yes, this does mean that it is unhelpful to send POSIX
+       signals to random tasks between the time that the scheduler
+       spawns its first kthread and the time that RCU's kthreads
+       have all been spawned.
+       If there ever turns out to be a good reason for sending POSIX
+       signals during that time, appropriate adjustments will be made.
+       (If it turns out that POSIX signals are sent during this time for
+       no good reason, other adjustments will be made, appropriate
+       or otherwise.)
 </font></td></tr>
 <tr><td>&nbsp;</td></tr>
 </table>
@@ -2295,12 +2311,61 @@ situation, and Dipankar Sarma incorporated <tt>rcu_barrier()</tt> into RCU.
 The need for <tt>rcu_barrier()</tt> for module unloading became
 apparent later.
 
+<p>
+<b>Important note</b>: The <tt>rcu_barrier()</tt> function is not,
+repeat, <i>not</i>, obligated to wait for a grace period.
+It is instead only required to wait for RCU callbacks that have
+already been posted.
+Therefore, if there are no RCU callbacks posted anywhere in the system,
+<tt>rcu_barrier()</tt> is within its rights to return immediately.
+Even if there are callbacks posted, <tt>rcu_barrier()</tt> does not
+necessarily need to wait for a grace period.
+
+<table>
+<tr><th>&nbsp;</th></tr>
+<tr><th align="left">Quick Quiz:</th></tr>
+<tr><td>
+       Wait a minute!
+       Each RCU callbacks must wait for a grace period to complete,
+       and <tt>rcu_barrier()</tt> must wait for each pre-existing
+       callback to be invoked.
+       Doesn't <tt>rcu_barrier()</tt> therefore need to wait for
+       a full grace period if there is even one callback posted anywhere
+       in the system?
+</td></tr>
+<tr><th align="left">Answer:</th></tr>
+<tr><td bgcolor="#ffffff"><font color="ffffff">
+       Absolutely not!!!
+       </font>
+
+       <p><font color="ffffff">
+       Yes, each RCU callbacks must wait for a grace period to complete,
+       but it might well be partly (or even completely) finished waiting
+       by the time <tt>rcu_barrier()</tt> is invoked.
+       In that case, <tt>rcu_barrier()</tt> need only wait for the
+       remaining portion of the grace period to elapse.
+       So even if there are quite a few callbacks posted,
+       <tt>rcu_barrier()</tt> might well return quite quickly.
+       </font>
+
+       <p><font color="ffffff">
+       So if you need to wait for a grace period as well as for all
+       pre-existing callbacks, you will need to invoke both
+       <tt>synchronize_rcu()</tt> and <tt>rcu_barrier()</tt>.
+       If latency is a concern, you can always use workqueues
+       to invoke them concurrently.
+</font></td></tr>
+<tr><td>&nbsp;</td></tr>
+</table>
+
 <h3><a name="Hotplug CPU">Hotplug CPU</a></h3>
 
 <p>
 The Linux kernel supports CPU hotplug, which means that CPUs
 can come and go.
-It is of course illegal to use any RCU API member from an offline CPU.
+It is of course illegal to use any RCU API member from an offline CPU,
+with the exception of <a href="#Sleepable RCU">SRCU</a> read-side
+critical sections.
 This requirement was present from day one in DYNIX/ptx, but
 on the other hand, the Linux kernel's CPU-hotplug implementation
 is &ldquo;interesting.&rdquo;
@@ -2310,19 +2375,18 @@ The Linux-kernel CPU-hotplug implementation has notifiers that
 are used to allow the various kernel subsystems (including RCU)
 to respond appropriately to a given CPU-hotplug operation.
 Most RCU operations may be invoked from CPU-hotplug notifiers,
-including even normal synchronous grace-period operations
-such as <tt>synchronize_rcu()</tt>.
-However, expedited grace-period operations such as
-<tt>synchronize_rcu_expedited()</tt> are not supported,
-due to the fact that current implementations block CPU-hotplug
-operations, which could result in deadlock.
+including even synchronous grace-period operations such as
+<tt>synchronize_rcu()</tt> and <tt>synchronize_rcu_expedited()</tt>.
 
 <p>
-In addition, all-callback-wait operations such as
+However, all-callback-wait operations such as
 <tt>rcu_barrier()</tt> are also not supported, due to the
 fact that there are phases of CPU-hotplug operations where
 the outgoing CPU's callbacks will not be invoked until after
 the CPU-hotplug operation ends, which could also result in deadlock.
+Furthermore, <tt>rcu_barrier()</tt> blocks CPU-hotplug operations
+during its execution, which results in another type of deadlock
+when invoked from a CPU-hotplug notifier.
 
 <h3><a name="Scheduler and RCU">Scheduler and RCU</a></h3>
 
@@ -2863,6 +2927,27 @@ It also motivates the <tt>smp_mb__after_srcu_read_unlock()</tt>
 API, which, in combination with <tt>srcu_read_unlock()</tt>,
 guarantees a full memory barrier.
 
+<p>
+Also unlike other RCU flavors, SRCU's callbacks-wait function
+<tt>srcu_barrier()</tt> may be invoked from CPU-hotplug notifiers,
+though this is not necessarily a good idea.
+The reason that this is possible is that SRCU is insensitive
+to whether or not a CPU is online, which means that <tt>srcu_barrier()</tt>
+need not exclude CPU-hotplug operations.
+
+<p>
+As of v4.12, SRCU's callbacks are maintained per-CPU, eliminating
+a locking bottleneck present in prior kernel versions.
+Although this will allow users to put much heavier stress on
+<tt>call_srcu()</tt>, it is important to note that SRCU does not
+yet take any special steps to deal with callback flooding.
+So if you are posting (say) 10,000 SRCU callbacks per second per CPU,
+you are probably totally OK, but if you intend to post (say) 1,000,000
+SRCU callbacks per second per CPU, please run some tests first.
+SRCU just might need a few adjustment to deal with that sort of load.
+Of course, your mileage may vary based on the speed of your CPUs and
+the size of your memory.
+
 <p>
 The
 <a href="https://lwn.net/Articles/609973/#RCU Per-Flavor API Table">SRCU API</a>
@@ -3021,8 +3106,8 @@ to do some redesign to avoid this scalability problem.
 
 <p>
 RCU disables CPU hotplug in a few places, perhaps most notably in the
-expedited grace-period and <tt>rcu_barrier()</tt> operations.
-If there is a strong reason to use expedited grace periods in CPU-hotplug
+<tt>rcu_barrier()</tt> operations.
+If there is a strong reason to use <tt>rcu_barrier()</tt> in CPU-hotplug
 notifiers, it will be necessary to avoid disabling CPU hotplug.
 This would introduce some complexity, so there had better be a <i>very</i>
 good reason.
@@ -3096,9 +3181,5 @@ Andy Lutomirski for their help in rendering
 this article human readable, and to Michelle Rankin for her support
 of this effort.
 Other contributions are acknowledged in the Linux kernel's git archive.
-The cartoon is copyright (c) 2013 by Melissa Broussard,
-and is provided
-under the terms of the Creative Commons Attribution-Share Alike 3.0
-United States license.
 
 </body></html>
index c0bf2441a2baf5f254ed64d6e4c117dda808fd2c..b2a613f16d747828e35fd182a0c9fe06c1107d0f 100644 (file)
@@ -138,6 +138,15 @@ o  Be very careful about comparing pointers obtained from
                This sort of comparison occurs frequently when scanning
                RCU-protected circular linked lists.
 
+               Note that if checks for being within an RCU read-side
+               critical section are not required and the pointer is never
+               dereferenced, rcu_access_pointer() should be used in place
+               of rcu_dereference(). The rcu_access_pointer() primitive
+               does not require an enclosing read-side critical section,
+               and also omits the smp_read_barrier_depends() included in
+               rcu_dereference(), which in turn should provide a small
+               performance gain in some CPUs (e.g., the DEC Alpha).
+
        o       The comparison is against a pointer that references memory
                that was initialized "a long time ago."  The reason
                this is safe is that even if misordering occurs, the
index 18f9651ff23d411e96737ec070d4fc6bc29c50fe..8151f0195f7688386e8057ad34fdc9cc153b7fb8 100644 (file)
@@ -1,5 +1,5 @@
 Using hlist_nulls to protect read-mostly linked lists and
-objects using SLAB_DESTROY_BY_RCU allocations.
+objects using SLAB_TYPESAFE_BY_RCU allocations.
 
 Please read the basics in Documentation/RCU/listRCU.txt
 
@@ -7,7 +7,7 @@ Using special makers (called 'nulls') is a convenient way
 to solve following problem :
 
 A typical RCU linked list managing objects which are
-allocated with SLAB_DESTROY_BY_RCU kmem_cache can
+allocated with SLAB_TYPESAFE_BY_RCU kmem_cache can
 use following algos :
 
 1) Lookup algo
@@ -96,7 +96,7 @@ unlock_chain(); // typically a spin_unlock()
 3) Remove algo
 --------------
 Nothing special here, we can use a standard RCU hlist deletion.
-But thanks to SLAB_DESTROY_BY_RCU, beware a deleted object can be reused
+But thanks to SLAB_TYPESAFE_BY_RCU, beware a deleted object can be reused
 very very fast (before the end of RCU grace period)
 
 if (put_last_reference_on(obj) {
index e93d04133fe7ae58cfb6c3da3e0717b0640f3b9a..96a3d81837e1b120098eccfd1b95b0bfc4947be9 100644 (file)
@@ -1,9 +1,102 @@
 Using RCU's CPU Stall Detector
 
-The rcu_cpu_stall_suppress module parameter enables RCU's CPU stall
-detector, which detects conditions that unduly delay RCU grace periods.
-This module parameter enables CPU stall detection by default, but
-may be overridden via boot-time parameter or at runtime via sysfs.
+This document first discusses what sorts of issues RCU's CPU stall
+detector can locate, and then discusses kernel parameters and Kconfig
+options that can be used to fine-tune the detector's operation.  Finally,
+this document explains the stall detector's "splat" format.
+
+
+What Causes RCU CPU Stall Warnings?
+
+So your kernel printed an RCU CPU stall warning.  The next question is
+"What caused it?"  The following problems can result in RCU CPU stall
+warnings:
+
+o      A CPU looping in an RCU read-side critical section.
+
+o      A CPU looping with interrupts disabled.
+
+o      A CPU looping with preemption disabled.  This condition can
+       result in RCU-sched stalls and, if ksoftirqd is in use, RCU-bh
+       stalls.
+
+o      A CPU looping with bottom halves disabled.  This condition can
+       result in RCU-sched and RCU-bh stalls.
+
+o      For !CONFIG_PREEMPT kernels, a CPU looping anywhere in the
+       kernel without invoking schedule().  Note that cond_resched()
+       does not necessarily prevent RCU CPU stall warnings.  Therefore,
+       if the looping in the kernel is really expected and desirable
+       behavior, you might need to replace some of the cond_resched()
+       calls with calls to cond_resched_rcu_qs().
+
+o      Booting Linux using a console connection that is too slow to
+       keep up with the boot-time console-message rate.  For example,
+       a 115Kbaud serial console can be -way- too slow to keep up
+       with boot-time message rates, and will frequently result in
+       RCU CPU stall warning messages.  Especially if you have added
+       debug printk()s.
+
+o      Anything that prevents RCU's grace-period kthreads from running.
+       This can result in the "All QSes seen" console-log message.
+       This message will include information on when the kthread last
+       ran and how often it should be expected to run.
+
+o      A CPU-bound real-time task in a CONFIG_PREEMPT kernel, which might
+       happen to preempt a low-priority task in the middle of an RCU
+       read-side critical section.   This is especially damaging if
+       that low-priority task is not permitted to run on any other CPU,
+       in which case the next RCU grace period can never complete, which
+       will eventually cause the system to run out of memory and hang.
+       While the system is in the process of running itself out of
+       memory, you might see stall-warning messages.
+
+o      A CPU-bound real-time task in a CONFIG_PREEMPT_RT kernel that
+       is running at a higher priority than the RCU softirq threads.
+       This will prevent RCU callbacks from ever being invoked,
+       and in a CONFIG_PREEMPT_RCU kernel will further prevent
+       RCU grace periods from ever completing.  Either way, the
+       system will eventually run out of memory and hang.  In the
+       CONFIG_PREEMPT_RCU case, you might see stall-warning
+       messages.
+
+o      A hardware or software issue shuts off the scheduler-clock
+       interrupt on a CPU that is not in dyntick-idle mode.  This
+       problem really has happened, and seems to be most likely to
+       result in RCU CPU stall warnings for CONFIG_NO_HZ_COMMON=n kernels.
+
+o      A bug in the RCU implementation.
+
+o      A hardware failure.  This is quite unlikely, but has occurred
+       at least once in real life.  A CPU failed in a running system,
+       becoming unresponsive, but not causing an immediate crash.
+       This resulted in a series of RCU CPU stall warnings, eventually
+       leading the realization that the CPU had failed.
+
+The RCU, RCU-sched, RCU-bh, and RCU-tasks implementations have CPU stall
+warning.  Note that SRCU does -not- have CPU stall warnings.  Please note
+that RCU only detects CPU stalls when there is a grace period in progress.
+No grace period, no CPU stall warnings.
+
+To diagnose the cause of the stall, inspect the stack traces.
+The offending function will usually be near the top of the stack.
+If you have a series of stall warnings from a single extended stall,
+comparing the stack traces can often help determine where the stall
+is occurring, which will usually be in the function nearest the top of
+that portion of the stack which remains the same from trace to trace.
+If you can reliably trigger the stall, ftrace can be quite helpful.
+
+RCU bugs can often be debugged with the help of CONFIG_RCU_TRACE
+and with RCU's event tracing.  For information on RCU's event tracing,
+see include/trace/events/rcu.h.
+
+
+Fine-Tuning the RCU CPU Stall Detector
+
+The rcuupdate.rcu_cpu_stall_suppress module parameter disables RCU's
+CPU stall detector, which detects conditions that unduly delay RCU grace
+periods.  This module parameter enables CPU stall detection by default,
+but may be overridden via boot-time parameter or at runtime via sysfs.
 The stall detector's idea of what constitutes "unduly delayed" is
 controlled by a set of kernel configuration variables and cpp macros:
 
@@ -56,6 +149,9 @@ rcupdate.rcu_task_stall_timeout
        And continues with the output of sched_show_task() for each
        task stalling the current RCU-tasks grace period.
 
+
+Interpreting RCU's CPU Stall-Detector "Splats"
+
 For non-RCU-tasks flavors of RCU, when a CPU detects that it is stalling,
 it will print a message similar to the following:
 
@@ -178,89 +274,3 @@ grace period is in flight.
 
 It is entirely possible to see stall warnings from normal and from
 expedited grace periods at about the same time from the same run.
-
-
-What Causes RCU CPU Stall Warnings?
-
-So your kernel printed an RCU CPU stall warning.  The next question is
-"What caused it?"  The following problems can result in RCU CPU stall
-warnings:
-
-o      A CPU looping in an RCU read-side critical section.
-       
-o      A CPU looping with interrupts disabled.  This condition can
-       result in RCU-sched and RCU-bh stalls.
-
-o      A CPU looping with preemption disabled.  This condition can
-       result in RCU-sched stalls and, if ksoftirqd is in use, RCU-bh
-       stalls.
-
-o      A CPU looping with bottom halves disabled.  This condition can
-       result in RCU-sched and RCU-bh stalls.
-
-o      For !CONFIG_PREEMPT kernels, a CPU looping anywhere in the
-       kernel without invoking schedule().  Note that cond_resched()
-       does not necessarily prevent RCU CPU stall warnings.  Therefore,
-       if the looping in the kernel is really expected and desirable
-       behavior, you might need to replace some of the cond_resched()
-       calls with calls to cond_resched_rcu_qs().
-
-o      Booting Linux using a console connection that is too slow to
-       keep up with the boot-time console-message rate.  For example,
-       a 115Kbaud serial console can be -way- too slow to keep up
-       with boot-time message rates, and will frequently result in
-       RCU CPU stall warning messages.  Especially if you have added
-       debug printk()s.
-
-o      Anything that prevents RCU's grace-period kthreads from running.
-       This can result in the "All QSes seen" console-log message.
-       This message will include information on when the kthread last
-       ran and how often it should be expected to run.
-
-o      A CPU-bound real-time task in a CONFIG_PREEMPT kernel, which might
-       happen to preempt a low-priority task in the middle of an RCU
-       read-side critical section.   This is especially damaging if
-       that low-priority task is not permitted to run on any other CPU,
-       in which case the next RCU grace period can never complete, which
-       will eventually cause the system to run out of memory and hang.
-       While the system is in the process of running itself out of
-       memory, you might see stall-warning messages.
-
-o      A CPU-bound real-time task in a CONFIG_PREEMPT_RT kernel that
-       is running at a higher priority than the RCU softirq threads.
-       This will prevent RCU callbacks from ever being invoked,
-       and in a CONFIG_PREEMPT_RCU kernel will further prevent
-       RCU grace periods from ever completing.  Either way, the
-       system will eventually run out of memory and hang.  In the
-       CONFIG_PREEMPT_RCU case, you might see stall-warning
-       messages.
-
-o      A hardware or software issue shuts off the scheduler-clock
-       interrupt on a CPU that is not in dyntick-idle mode.  This
-       problem really has happened, and seems to be most likely to
-       result in RCU CPU stall warnings for CONFIG_NO_HZ_COMMON=n kernels.
-
-o      A bug in the RCU implementation.
-
-o      A hardware failure.  This is quite unlikely, but has occurred
-       at least once in real life.  A CPU failed in a running system,
-       becoming unresponsive, but not causing an immediate crash.
-       This resulted in a series of RCU CPU stall warnings, eventually
-       leading the realization that the CPU had failed.
-
-The RCU, RCU-sched, RCU-bh, and RCU-tasks implementations have CPU stall
-warning.  Note that SRCU does -not- have CPU stall warnings.  Please note
-that RCU only detects CPU stalls when there is a grace period in progress.
-No grace period, no CPU stall warnings.
-
-To diagnose the cause of the stall, inspect the stack traces.
-The offending function will usually be near the top of the stack.
-If you have a series of stall warnings from a single extended stall,
-comparing the stack traces can often help determine where the stall
-is occurring, which will usually be in the function nearest the top of
-that portion of the stack which remains the same from trace to trace.
-If you can reliably trigger the stall, ftrace can be quite helpful.
-
-RCU bugs can often be debugged with the help of CONFIG_RCU_TRACE
-and with RCU's event tracing.  For information on RCU's event tracing,
-see include/trace/events/rcu.h.
index 5cbd8b2395b811489c68acb7da4616b4a1ef9523..8ed6c9f6133c45a54c442d04ed0814dc2dcd1a45 100644 (file)
@@ -562,7 +562,9 @@ This section presents a "toy" RCU implementation that is based on
 familiar locking primitives.  Its overhead makes it a non-starter for
 real-life use, as does its lack of scalability.  It is also unsuitable
 for realtime use, since it allows scheduling latency to "bleed" from
-one read-side critical section to another.
+one read-side critical section to another.  It also assumes recursive
+reader-writer locks:  If you try this with non-recursive locks, and
+you allow nested rcu_read_lock() calls, you can deadlock.
 
 However, it is probably the easiest implementation to relate to, so is
 a good starting point.
@@ -587,20 +589,21 @@ It is extremely simple:
                write_unlock(&rcu_gp_mutex);
        }
 
-[You can ignore rcu_assign_pointer() and rcu_dereference() without
-missing much.  But here they are anyway.  And whatever you do, don't
-forget about them when submitting patches making use of RCU!]
+[You can ignore rcu_assign_pointer() and rcu_dereference() without missing
+much.  But here are simplified versions anyway.  And whatever you do,
+don't forget about them when submitting patches making use of RCU!]
 
-       #define rcu_assign_pointer(p, v)        ({ \
-                                                       smp_wmb(); \
-                                                       (p) = (v); \
-                                               })
+       #define rcu_assign_pointer(p, v) \
+       ({ \
+               smp_store_release(&(p), (v)); \
+       })
 
-       #define rcu_dereference(p)     ({ \
-                                       typeof(p) _________p1 = p; \
-                                       smp_read_barrier_depends(); \
-                                       (_________p1); \
-                                       })
+       #define rcu_dereference(p) \
+       ({ \
+               typeof(p) _________p1 = p; \
+               smp_read_barrier_depends(); \
+               (_________p1); \
+       })
 
 
 The rcu_read_lock() and rcu_read_unlock() primitive read-acquire
@@ -925,7 +928,8 @@ d.  Do you need RCU grace periods to complete even in the face
 
 e.     Is your workload too update-intensive for normal use of
        RCU, but inappropriate for other synchronization mechanisms?
-       If so, consider SLAB_DESTROY_BY_RCU.  But please be careful!
+       If so, consider SLAB_TYPESAFE_BY_RCU (which was originally
+       named SLAB_DESTROY_BY_RCU).  But please be careful!
 
 f.     Do you need read-side critical sections that are respected
        even though they are in the middle of the idle loop, during
index 02f639aab06eb17a4e82f7a97e6ab847d3b20394..b96e80f79e853109abdb0d73a6a688453f9689cc 100644 (file)
@@ -362,7 +362,7 @@ If something goes wrong
    as is, otherwise you will have to use the ``ksymoops`` program to make
    sense of the dump (but compiling with CONFIG_KALLSYMS is usually preferred).
    This utility can be downloaded from
-   ftp://ftp.<country>.kernel.org/pub/linux/utils/kernel/ksymoops/ .
+   https://www.kernel.org/pub/linux/utils/kernel/ksymoops/ .
    Alternatively, you can do the dump lookup by hand:
 
  - In debugging dumps like the above, it helps enormously if you can
index e4c9e0e46b9586796a037ee3dc624d6ce1017817..15f79c27748df1611b1643b77ca68e2a5e7cfaab 100644 (file)
                        A valid base address must be provided, and the serial
                        port must already be setup and configured.
 
-               armada3700_uart,<addr>
+               ar3700_uart,<addr>
                        Start an early, polled-mode console on the
                        Armada 3700 serial port at the specified
                        address. The serial port must already be setup
                        extended tables themselves, and also PASID support. With
                        this option set, extended tables will not be used even
                        on hardware which claims to support them.
+               tboot_noforce [Default Off]
+                       Do not force the Intel IOMMU enabled under tboot.
+                       By default, tboot will force Intel IOMMU on, which
+                       could harm performance of some high-throughput
+                       devices like 40GBit network cards, even if identity
+                       mapping is enabled.
+                       Note that using this option lowers the security
+                       provided by tboot because it makes the system
+                       vulnerable to DMA attacks.
 
        intel_idle.max_cstate=  [KNL,HW,ACPI,X86]
                        0       disables intel_idle and fall back on acpi_idle.
                nobypass        [PPC/POWERNV]
                        Disable IOMMU bypass, using IOMMU for PCI devices.
 
+       iommu.passthrough=
+                       [ARM64] Configure DMA to bypass the IOMMU by default.
+                       Format: { "0" | "1" }
+                       0 - Use IOMMU translation for DMA.
+                       1 - Bypass the IOMMU for DMA.
+                       unset - Use IOMMU translation for DMA.
 
        io7=            [HW] IO7 for Marvel based alpha systems
                        See comment before marvel_specify_io7 in
                        and gids from such clients.  This is intended to ease
                        migration from NFSv2/v3.
 
-       objlayoutdriver.osd_login_prog=
-                       [NFS] [OBJLAYOUT] sets the pathname to the program which
-                       is used to automatically discover and login into new
-                       osd-targets. Please see:
-                       Documentation/filesystems/pnfs.txt for more explanations
-
        nmi_debug=      [KNL,SH] Specify one or more actions to take
                        when a NMI is triggered.
                        Format: [state][,regs][,debounce][,die]
        spia_pedr=
        spia_peddr=
 
+       srcutree.exp_holdoff [KNL]
+                       Specifies how many nanoseconds must elapse
+                       since the end of the last SRCU grace period for
+                       a given srcu_struct until the next normal SRCU
+                       grace period will be considered for automatic
+                       expediting.  Set to zero to disable automatic
+                       expediting.
+
        stacktrace      [FTRACE]
                        Enabled the stack tracer on boot up.
 
diff --git a/Documentation/arm/stm32/stm32h743-overview.txt b/Documentation/arm/stm32/stm32h743-overview.txt
new file mode 100644 (file)
index 0000000..3031cba
--- /dev/null
@@ -0,0 +1,30 @@
+                       STM32H743 Overview
+                       ==================
+
+  Introduction
+  ------------
+       The STM32H743 is a Cortex-M7 MCU aimed at various applications.
+       It features:
+       - Cortex-M7 core running up to @400MHz
+       - 2MB internal flash, 1MBytes internal RAM
+       - FMC controller to connect SDRAM, NOR and NAND memories
+       - Dual mode QSPI
+       - SD/MMC/SDIO support
+       - Ethernet controller
+       - USB OTFG FS & HS controllers
+       - I2C, SPI, CAN busses support
+       - Several 16 & 32 bits general purpose timers
+       - Serial Audio interface
+       - LCD controller
+       - HDMI-CEC
+       - SPDIFRX
+       - DFSDM
+
+  Resources
+  ---------
+       Datasheet and reference manual are publicly available on ST website:
+       - http://www.st.com/en/microcontrollers/stm32h7x3.html?querycriteria=productId=LN2033
+
+  Document Author
+  ---------------
+       Alexandre Torgue <alexandre.torgue@st.com>
index d9995f1f51b3eb9e678a557a471e4d387db49ca8..a25a99e82bb1c9811ee3e8cb111d356fa53fc979 100644 (file)
@@ -11,24 +11,56 @@ in AArch64 Linux.
 The kernel configures the translation tables so that translations made
 via TTBR0 (i.e. userspace mappings) have the top byte (bits 63:56) of
 the virtual address ignored by the translation hardware. This frees up
-this byte for application use, with the following caveats:
+this byte for application use.
 
-       (1) The kernel requires that all user addresses passed to EL1
-           are tagged with tag 0x00. This means that any syscall
-           parameters containing user virtual addresses *must* have
-           their top byte cleared before trapping to the kernel.
 
-       (2) Non-zero tags are not preserved when delivering signals.
-           This means that signal handlers in applications making use
-           of tags cannot rely on the tag information for user virtual
-           addresses being maintained for fields inside siginfo_t.
-           One exception to this rule is for signals raised in response
-           to watchpoint debug exceptions, where the tag information
-           will be preserved.
+Passing tagged addresses to the kernel
+--------------------------------------
 
-       (3) Special care should be taken when using tagged pointers,
-           since it is likely that C compilers will not hazard two
-           virtual addresses differing only in the upper byte.
+All interpretation of userspace memory addresses by the kernel assumes
+an address tag of 0x00.
+
+This includes, but is not limited to, addresses found in:
+
+ - pointer arguments to system calls, including pointers in structures
+   passed to system calls,
+
+ - the stack pointer (sp), e.g. when interpreting it to deliver a
+   signal,
+
+ - the frame pointer (x29) and frame records, e.g. when interpreting
+   them to generate a backtrace or call graph.
+
+Using non-zero address tags in any of these locations may result in an
+error code being returned, a (fatal) signal being raised, or other modes
+of failure.
+
+For these reasons, passing non-zero address tags to the kernel via
+system calls is forbidden, and using a non-zero address tag for sp is
+strongly discouraged.
+
+Programs maintaining a frame pointer and frame records that use non-zero
+address tags may suffer impaired or inaccurate debug and profiling
+visibility.
+
+
+Preserving tags
+---------------
+
+Non-zero tags are not preserved when delivering signals. This means that
+signal handlers in applications making use of tags cannot rely on the
+tag information for user virtual addresses being maintained for fields
+inside siginfo_t. One exception to this rule is for signals raised in
+response to watchpoint debug exceptions, where the tag information will
+be preserved.
 
 The architecture prevents the use of a tagged PC, so the upper byte will
 be set to a sign-extension of bit 55 on exception return.
+
+
+Other considerations
+--------------------
+
+Special care should be taken when using tagged pointers, since it is
+likely that C compilers will not hazard two virtual addresses differing
+only in the upper byte.
index 1b87df6cd4761ab0e548d0cc0611c2c5b74725eb..05e2822a80b34d0f31649cfb486ade2b4679f9e8 100644 (file)
@@ -11,6 +11,13 @@ controllers), BFQ's main features are:
   groups (switching back to time distribution when needed to keep
   throughput high).
 
+In its default configuration, BFQ privileges latency over
+throughput. So, when needed for achieving a lower latency, BFQ builds
+schedules that may lead to a lower throughput. If your main or only
+goal, for a given device, is to achieve the maximum-possible
+throughput at all times, then do switch off all low-latency heuristics
+for that device, by setting low_latency to 0. Full details in Section 3.
+
 On average CPUs, the current version of BFQ can handle devices
 performing at most ~30K IOPS; at most ~50 KIOPS on faster CPUs. As a
 reference, 30-50 KIOPS correspond to very high bandwidths with
@@ -375,11 +382,19 @@ default, low latency mode is enabled. If enabled, interactive and soft
 real-time applications are privileged and experience a lower latency,
 as explained in more detail in the description of how BFQ works.
 
-DO NOT enable this mode if you need full control on bandwidth
+DISABLE this mode if you need full control on bandwidth
 distribution. In fact, if it is enabled, then BFQ automatically
 increases the bandwidth share of privileged applications, as the main
 means to guarantee a lower latency to them.
 
+In addition, as already highlighted at the beginning of this document,
+DISABLE this mode if your only goal is to achieve a high throughput.
+In fact, privileging the I/O of some application over the rest may
+entail a lower throughput. To achieve the highest-possible throughput
+on a non-rotational device, setting slice_idle to 0 may be needed too
+(at the cost of giving up any strong guarantee on fairness and low
+latency).
+
 timeout_sync
 ------------
 
index e50b95c25868f15f101e97176a8665391b9e71da..dc5e2dcdbef40b344f373614220460ebe079f768 100644 (file)
@@ -918,6 +918,18 @@ PAGE_SIZE multiple when read back.
 
                Number of major page faults incurred
 
+         workingset_refault
+
+               Number of refaults of previously evicted pages
+
+         workingset_activate
+
+               Number of refaulted pages that were immediately activated
+
+         workingset_nodereclaim
+
+               Number of times a shadow node has been reclaimed
+
   memory.swap.current
 
        A read-only single value file which exists on non-root
index c246cd2730d90669787e0bb5a0f0f50ed5ad3376..bfd5b558477d95bd1c2fe42d47861d791313872e 100644 (file)
@@ -43,8 +43,11 @@ Board compatible values:
   - "wetek,hub" (Meson gxbb)
   - "wetek,play2" (Meson gxbb)
   - "amlogic,p212" (Meson gxl s905x)
+  - "khadas,vim" (Meson gxl s905x)
+
   - "amlogic,p230" (Meson gxl s905d)
   - "amlogic,p231" (Meson gxl s905d)
+  - "hwacom,amazetv" (Meson gxl s905x)
   - "amlogic,q200" (Meson gxm s912)
   - "amlogic,q201" (Meson gxm s912)
   - "nexbox,a95x" (Meson gxbb or Meson gxl s905x)
index 29737b9b616e46920a6df2a6c9327499eda8b69e..799af90dd75b09b4c28e85bbcf36db0604d63bd2 100644 (file)
@@ -217,7 +217,8 @@ memory, bridge implementations, processor and other functionality not controlled
 elsewhere.
 
 required properties:
-- compatible: Should be "atmel,<chip>-sfr", "syscon".
+- compatible: Should be "atmel,<chip>-sfr", "syscon" or
+       "atmel,<chip>-sfrbu", "syscon"
   <chip> can be "sama5d3", "sama5d4" or "sama5d2".
 - reg: Should contain registers location and length
 
diff --git a/Documentation/devicetree/bindings/arm/cavium-thunder2.txt b/Documentation/devicetree/bindings/arm/cavium-thunder2.txt
new file mode 100644 (file)
index 0000000..dc5dd65
--- /dev/null
@@ -0,0 +1,8 @@
+Cavium ThunderX2 CN99XX platform tree bindings
+----------------------------------------------
+
+Boards with Cavium ThunderX2 CN99XX SoC shall have the root property:
+  compatible = "cavium,thunderx2-cn9900", "brcm,vulcan-soc";
+
+These SoC uses the "cavium,thunder2" core which will be compatible
+with "brcm,vulcan".
index 698ad1f097fa34c835478a84a7ad9bddfc86e9b6..1030f5f50207f22baa245e9df9ca69df286c128e 100644 (file)
@@ -170,6 +170,7 @@ nodes to be present and contain the properties described below.
                            "brcm,brahma-b15"
                            "brcm,vulcan"
                            "cavium,thunder"
+                           "cavium,thunder2"
                            "faraday,fa526"
                            "intel,sa110"
                            "intel,sa1100"
diff --git a/Documentation/devicetree/bindings/arm/firmware/linaro,optee-tz.txt b/Documentation/devicetree/bindings/arm/firmware/linaro,optee-tz.txt
new file mode 100644 (file)
index 0000000..d38834c
--- /dev/null
@@ -0,0 +1,31 @@
+OP-TEE Device Tree Bindings
+
+OP-TEE is a piece of software using hardware features to provide a Trusted
+Execution Environment. The security can be provided with ARM TrustZone, but
+also by virtualization or a separate chip.
+
+We're using "linaro" as the first part of the compatible property for
+the reference implementation maintained by Linaro.
+
+* OP-TEE based on ARM TrustZone required properties:
+
+- compatible     : should contain "linaro,optee-tz"
+
+- method         : The method of calling the OP-TEE Trusted OS. Permitted
+                   values are:
+
+                   "smc" : SMC #0, with the register assignments specified
+                          in drivers/tee/optee/optee_smc.h
+
+                   "hvc" : HVC #0, with the register assignments specified
+                          in drivers/tee/optee/optee_smc.h
+
+
+
+Example:
+       firmware {
+               optee {
+                       compatible = "linaro,optee-tz";
+                       method = "smc";
+               };
+       };
index c9c567ae227f7a3f948ddc3a2ad66ba7d3664f05..cdb9dd705754a82928ffb90b7d67faf493104a24 100644 (file)
@@ -179,6 +179,18 @@ LS1046A ARMv8 based RDB Board
 Required root node properties:
     - compatible = "fsl,ls1046a-rdb", "fsl,ls1046a";
 
+LS1088A SoC
+Required root node properties:
+    - compatible = "fsl,ls1088a";
+
+LS1088A ARMv8 based QDS Board
+Required root node properties:
+    - compatible = "fsl,ls1088a-qds", "fsl,ls1088a";
+
+LS1088A ARMv8 based RDB Board
+Required root node properties:
+    - compatible = "fsl,ls1088a-rdb", "fsl,ls1088a";
+
 LS2080A SoC
 Required root node properties:
     - compatible = "fsl,ls2080a";
@@ -195,3 +207,14 @@ LS2080A ARMv8 based RDB Board
 Required root node properties:
     - compatible = "fsl,ls2080a-rdb", "fsl,ls2080a";
 
+LS2088A SoC
+Required root node properties:
+    - compatible = "fsl,ls2088a";
+
+LS2088A ARMv8 based QDS Board
+Required root node properties:
+    - compatible = "fsl,ls2088a-qds", "fsl,ls2088a";
+
+LS2088A ARMv8 based RDB Board
+Required root node properties:
+    - compatible = "fsl,ls2088a-rdb", "fsl,ls2088a";
diff --git a/Documentation/devicetree/bindings/arm/gemini.txt b/Documentation/devicetree/bindings/arm/gemini.txt
new file mode 100644 (file)
index 0000000..0041eb0
--- /dev/null
@@ -0,0 +1,86 @@
+Cortina systems Gemini platforms
+
+The Gemini SoC is the project name for an ARMv4 FA525-based SoC originally
+produced by Storlink Semiconductor around 2005. The company was renamed
+later renamed Storm Semiconductor. The chip product name is Storlink SL3516.
+It was derived from earlier products from Storm named SL3316 (Centroid) and
+SL3512 (Bulverde).
+
+Storm Semiconductor was acquired by Cortina Systems in 2008 and the SoC was
+produced and used for NAS and similar usecases. In 2014 Cortina Systems was
+in turn acquired by Inphi, who seem to have discontinued this product family.
+
+Many of the IP blocks used in the SoC comes from Faraday Technology.
+
+Required properties (in root node):
+       compatible = "cortina,gemini";
+
+Required nodes:
+
+- soc: the SoC should be represented by a simple bus encompassing all the
+  onchip devices, this is referred to as the soc bus node.
+
+- syscon: the soc bus node must have a system controller node pointing to the
+  global control registers, with the compatible string
+  "cortina,gemini-syscon", "syscon";
+
+- timer: the soc bus node must have a timer node pointing to the SoC timer
+  block, with the compatible string "cortina,gemini-timer"
+  See: clocksource/cortina,gemini-timer.txt
+
+- interrupt-controller: the sob bus node must have an interrupt controller
+  node pointing to the SoC interrupt controller block, with the compatible
+  string "cortina,gemini-interrupt-controller"
+  See interrupt-controller/cortina,gemini-interrupt-controller.txt
+
+Example:
+
+/ {
+       model = "Foo Gemini Machine";
+       compatible = "cortina,gemini";
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       memory {
+               device_type = "memory";
+               reg = <0x00000000 0x8000000>;
+       };
+
+       soc {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+               compatible = "simple-bus";
+               interrupt-parent = <&intcon>;
+
+               syscon: syscon@40000000 {
+                       compatible = "cortina,gemini-syscon", "syscon";
+                       reg = <0x40000000 0x1000>;
+               };
+
+               uart0: serial@42000000 {
+                       compatible = "ns16550a";
+                       reg = <0x42000000 0x100>;
+                       clock-frequency = <48000000>;
+                       interrupts = <18 IRQ_TYPE_LEVEL_HIGH>;
+                       reg-shift = <2>;
+               };
+
+               timer@43000000 {
+                       compatible = "cortina,gemini-timer";
+                       reg = <0x43000000 0x1000>;
+                       interrupt-parent = <&intcon>;
+                       interrupts = <14 IRQ_TYPE_EDGE_FALLING>, /* Timer 1 */
+                                    <15 IRQ_TYPE_EDGE_FALLING>, /* Timer 2 */
+                                    <16 IRQ_TYPE_EDGE_FALLING>; /* Timer 3 */
+                       syscon = <&syscon>;
+               };
+
+               intcon: interrupt-controller@48000000 {
+                       compatible = "cortina,gemini-interrupt-controller";
+                       reg = <0x48000000 0x1000>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+       };
+};
index f1c1e21a811099ddd980a566f064d2284729cfcd..2e732152064b5ae51ae33f38dd9f90e3c9fc90a1 100644 (file)
@@ -4,6 +4,14 @@ Hi3660 SoC
 Required root node properties:
        - compatible = "hisilicon,hi3660";
 
+Hi3798cv200 SoC
+Required root node properties:
+       - compatible = "hisilicon,hi3798cv200";
+
+Hi3798cv200 Poplar Board
+Required root node properties:
+       - compatible = "hisilicon,hi3798cv200-poplar", "hisilicon,hi3798cv200";
+
 Hi4511 Board
 Required root node properties:
        - compatible = "hisilicon,hi3620-hi4511";
diff --git a/Documentation/devicetree/bindings/arm/i2se.txt b/Documentation/devicetree/bindings/arm/i2se.txt
new file mode 100644 (file)
index 0000000..dbd54a3
--- /dev/null
@@ -0,0 +1,22 @@
+I2SE Device Tree Bindings
+-------------------------
+
+Duckbill Board
+Required root node properties:
+    - compatible = "i2se,duckbill", "fsl,imx28";
+
+Duckbill 2 Board
+Required root node properties:
+    - compatible = "i2se,duckbill-2", "fsl,imx28";
+
+Duckbill 2 485 Board
+Required root node properties:
+    - compatible = "i2se,duckbill-2-485", "i2se,duckbill-2", "fsl,imx28";
+
+Duckbill 2 EnOcean Board
+Required root node properties:
+    - compatible = "i2se,duckbill-2-enocean", "i2se,duckbill-2", "fsl,imx28";
+
+Duckbill 2 SPI Board
+Required root node properties:
+    - compatible = "i2se,duckbill-2-spi", "i2se,duckbill-2", "fsl,imx28";
index cb0054ac7121e54a747f147844b3f698c380c0e1..cd977db7630c50a6e118e60edd96256efa138ac9 100644 (file)
@@ -7,6 +7,7 @@ Required Properties:
 
 - compatible: Should be one of:
        - "mediatek,mt2701-apmixedsys"
+       - "mediatek,mt6797-apmixedsys"
        - "mediatek,mt8135-apmixedsys"
        - "mediatek,mt8173-apmixedsys"
 - #clock-cells: Must be 1
index f6a916686f4c4a94515d703ebcca0506343a4ba9..047b11ae5f45c0a7e020a231a4e87ce656b3842e 100644 (file)
@@ -7,6 +7,7 @@ Required Properties:
 
 - compatible: Should be one of:
        - "mediatek,mt2701-imgsys", "syscon"
+       - "mediatek,mt6797-imgsys", "syscon"
        - "mediatek,mt8173-imgsys", "syscon"
 - #clock-cells: Must be 1
 
index 1620ec2a5a3f12872d828d18fa04e02a9eafd315..58d58e2006b83324502d3d39739ab6537552649b 100644 (file)
@@ -8,6 +8,7 @@ Required Properties:
 
 - compatible: Should be one of:
        - "mediatek,mt2701-infracfg", "syscon"
+       - "mediatek,mt6797-infracfg", "syscon"
        - "mediatek,mt8135-infracfg", "syscon"
        - "mediatek,mt8173-infracfg", "syscon"
 - #clock-cells: Must be 1
index 67dd2e473d25fbe7189d788f47edfb3f09d19dcd..70529e0b58e9a15927a552ada8106434c1627100 100644 (file)
@@ -7,6 +7,7 @@ Required Properties:
 
 - compatible: Should be one of:
        - "mediatek,mt2701-mmsys", "syscon"
+       - "mediatek,mt6797-mmsys", "syscon"
        - "mediatek,mt8173-mmsys", "syscon"
 - #clock-cells: Must be 1
 
index 9f2fe7860114d65cb1a07ed70a6ec3242b57303f..ec93ecbb9f3c2fb72bf461d8d57275d8c57ac79a 100644 (file)
@@ -7,6 +7,7 @@ Required Properties:
 
 - compatible: Should be one of:
        - "mediatek,mt2701-topckgen"
+       - "mediatek,mt6797-topckgen"
        - "mediatek,mt8135-topckgen"
        - "mediatek,mt8173-topckgen"
 - #clock-cells: Must be 1
index 2440f73450c365895a0ec62e6f87c21281d1b0ef..d150104f928a4f7c023a724a3e646eb11b49d83a 100644 (file)
@@ -7,6 +7,7 @@ Required Properties:
 
 - compatible: Should be one of:
        - "mediatek,mt2701-vdecsys", "syscon"
+       - "mediatek,mt6797-vdecsys", "syscon"
        - "mediatek,mt8173-vdecsys", "syscon"
 - #clock-cells: Must be 1
 
index 5bb2866a2b50acebabf714868386aa9223186542..8a93be643647d429c39ba3c978e6e1a02f94d1c4 100644 (file)
@@ -5,7 +5,8 @@ The Mediatek vencsys controller provides various clocks to the system.
 
 Required Properties:
 
-- compatible: Should be:
+- compatible: Should be one of:
+       - "mediatek,mt6797-vencsys", "syscon"
        - "mediatek,mt8173-vencsys", "syscon"
 - #clock-cells: Must be 1
 
index cc4ace6397abda9ffa0a7aa02a0fce76eff5c6e0..c965d99e86c2b8413c5b5463d2bbc46966f53005 100644 (file)
@@ -1,5 +1,8 @@
 Rockchip platforms device tree bindings
 ---------------------------------------
+- Asus Tinker board
+    Required root node properties:
+      - compatible = "asus,rk3288-tinker", "rockchip,rk3288";
 
 - Kylin RK3036 board:
     Required root node properties:
@@ -56,6 +59,17 @@ Rockchip platforms device tree bindings
       - compatible = "google,veyron-brain-rev0", "google,veyron-brain",
                     "google,veyron", "rockchip,rk3288";
 
+- Google Gru (dev-board):
+    Required root node properties:
+      - compatible = "google,gru-rev15", "google,gru-rev14",
+                    "google,gru-rev13", "google,gru-rev12",
+                    "google,gru-rev11", "google,gru-rev10",
+                    "google,gru-rev9", "google,gru-rev8",
+                    "google,gru-rev7", "google,gru-rev6",
+                    "google,gru-rev5", "google,gru-rev4",
+                    "google,gru-rev3", "google,gru-rev2",
+                    "google,gru", "rockchip,rk3399";
+
 - Google Jaq (Haier Chromebook 11 and more):
     Required root node properties:
       - compatible = "google,veyron-jaq-rev5", "google,veyron-jaq-rev4",
@@ -70,6 +84,15 @@ Rockchip platforms device tree bindings
                     "google,veyron-jerry-rev3", "google,veyron-jerry",
                     "google,veyron", "rockchip,rk3288";
 
+- Google Kevin (Samsung Chromebook Plus):
+    Required root node properties:
+      - compatible = "google,kevin-rev15", "google,kevin-rev14",
+                    "google,kevin-rev13", "google,kevin-rev12",
+                    "google,kevin-rev11", "google,kevin-rev10",
+                    "google,kevin-rev9", "google,kevin-rev8",
+                    "google,kevin-rev7", "google,kevin-rev6",
+                    "google,kevin", "google,gru", "rockchip,rk3399";
+
 - Google Mickey (Asus Chromebit CS10):
     Required root node properties:
       - compatible = "google,veyron-mickey-rev8", "google,veyron-mickey-rev7",
@@ -103,6 +126,10 @@ Rockchip platforms device tree bindings
     Required root node properties:
       - compatible = "mqmaker,miqi", "rockchip,rk3288";
 
+- Phytec phyCORE-RK3288: Rapid Development Kit
+    Required root node properties:
+     - compatible = "phytec,rk3288-pcm-947", "phytec,rk3288-phycore-som", "rockchip,rk3288";
+
 - Rockchip PX3 Evaluation board:
     Required root node properties:
       - compatible = "rockchip,px3-evb", "rockchip,px3", "rockchip,rk3188";
@@ -134,6 +161,10 @@ Rockchip platforms device tree bindings
     Required root node properties:
      - compatible = "rockchip,rk3288-fennec", "rockchip,rk3288";
 
+- Rockchip RK3328 evb:
+    Required root node properties:
+      - compatible = "rockchip,rk3328-evb", "rockchip,rk3328";
+
 - Rockchip RK3399 evb:
     Required root node properties:
       - compatible = "rockchip,rk3399-evb", "rockchip,rk3399";
index c9502634316da3b184e883463973a64962fa252d..170fe0562c637eabb738978b909e930ba4fee87a 100644 (file)
@@ -13,8 +13,12 @@ SoCs:
     compatible = "renesas,r8a73a4"
   - R-Mobile A1 (R8A77400)
     compatible = "renesas,r8a7740"
+  - RZ/G1H (R8A77420)
+    compatible = "renesas,r8a7742"
   - RZ/G1M (R8A77430)
     compatible = "renesas,r8a7743"
+  - RZ/G1N (R8A77440)
+    compatible = "renesas,r8a7744"
   - RZ/G1E (R8A77450)
     compatible = "renesas,r8a7745"
   - R-Car M1A (R8A77781)
index 31a629dc75b8a959a3ad937a60364fa8dddccff0..3df034b13e284338df88af478101b4c4cd1542d0 100644 (file)
@@ -1,11 +1,14 @@
 Spreadtrum SoC Platforms Device Tree Bindings
 ----------------------------------------------------
 
-Sharkl64 is a Spreadtrum's SoC Platform which is based
-on ARM 64-bit processor.
+SC9836 openphone Board
+Required root node properties:
+       - compatible = "sprd,sc9836-openphone", "sprd,sc9836";
 
-SC9836 openphone board with SC9836 SoC based on the
-Sharkl64 Platform shall have the following properties.
+SC9860 SoC
+Required root node properties:
+       - compatible = "sprd,sc9860"
 
+SP9860G 3GFHD Board
 Required root node properties:
-        - compatible = "sprd,sc9836-openphone", "sprd,sc9836";
+       - compatible = "sprd,sp9860g-1h10", "sprd,sc9860";
diff --git a/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt b/Documentation/devicetree/bindings/arm/tegra/nvidia,tegra186-pmc.txt
new file mode 100644 (file)
index 0000000..078a58b
--- /dev/null
@@ -0,0 +1,34 @@
+NVIDIA Tegra Power Management Controller (PMC)
+
+Required properties:
+- compatible: Should contain one of the following:
+  - "nvidia,tegra186-pmc": for Tegra186
+- reg: Must contain an (offset, length) pair of the register set for each
+  entry in reg-names.
+- reg-names: Must include the following entries:
+  - "pmc"
+  - "wake"
+  - "aotag"
+  - "scratch"
+
+Optional properties:
+- nvidia,invert-interrupt: If present, inverts the PMU interrupt signal.
+
+Example:
+
+SoC DTSI:
+
+       pmc@c3600000 {
+               compatible = "nvidia,tegra186-pmc";
+               reg = <0 0x0c360000 0 0x10000>,
+                     <0 0x0c370000 0 0x10000>,
+                     <0 0x0c380000 0 0x10000>,
+                     <0 0x0c390000 0 0x10000>;
+               reg-names = "pmc", "wake", "aotag", "scratch";
+       };
+
+Board DTS:
+
+       pmc@c360000 {
+               nvidia,invert-interrupt;
+       };
index ccf0adddc8205e3f47df8ff99af43271f7792a99..a855c1bffc0f6695d5c0cd3f032019ea32d9d5e8 100644 (file)
@@ -1,7 +1,13 @@
 NVIDIA Tegra Flow Controller
 
 Required properties:
-- compatible: Should be "nvidia,tegra<chip>-flowctrl"
+- compatible: Should contain one of the following:
+  - "nvidia,tegra20-flowctrl": for Tegra20
+  - "nvidia,tegra30-flowctrl": for Tegra30
+  - "nvidia,tegra114-flowctrl": for Tegra114
+  - "nvidia,tegra124-flowctrl": for Tegra124
+  - "nvidia,tegra132-flowctrl", "nvidia,tegra124-flowctrl": for Tegra132
+  - "nvidia,tegra210-flowctrl": for Tegra210
 - reg: Should contain one register range (address and length)
 
 Example:
index ce06435d28ed9a036cdb2283f159acd6b3ac8b4c..a09d627b5508a2f8c9905dc9c02c09387acfe9e6 100644 (file)
@@ -5,7 +5,8 @@ controllers within the SoC.
 
 Required Properties:
 
-- compatible: should be "amlogic,gxbb-clkc"
+- compatible: should be "amlogic,gxbb-clkc" for GXBB SoC,
+             or "amlogic,gxl-clkc" for GXL and GXM SoC.
 - reg: physical base address of the clock controller and length of memory
        mapped region.
 
index 87e9c47a89a399fc3d8ef30623697d58cd956741..53d7e50ed875ae0db438af18f9f3354c2548c705 100644 (file)
@@ -6,18 +6,21 @@ from 3 to 12 output clocks.
 ==I2C device node==
 
 Required properties:
-- compatible:  shall be one of "idt,5p49v5923" , "idt,5p49v5933".
+- compatible:  shall be one of "idt,5p49v5923" , "idt,5p49v5933" ,
+               "idt,5p49v5935".
 - reg:         i2c device address, shall be 0x68 or 0x6a.
 - #clock-cells:        from common clock binding; shall be set to 1.
 - clocks:      from common clock binding; list of parent clock handles,
                - 5p49v5923: (required) either or both of XTAL or CLKIN
                                        reference clock.
-               - 5p49v5933: (optional) property not present (internal
+               - 5p49v5933 and
+               - 5p49v5935: (optional) property not present (internal
                                        Xtal used) or CLKIN reference
                                        clock.
 - clock-names: from common clock binding; clock input names, can be
                - 5p49v5923: (required) either or both of "xin", "clkin".
-               - 5p49v5933: (optional) property not present or "clkin".
+               - 5p49v5933 and
+               - 5p49v5935: (optional) property not present or "clkin".
 
 ==Mapping between clock specifier and physical pins==
 
@@ -34,6 +37,13 @@ clock specifier, the following mapping applies:
        1 -- OUT1
        2 -- OUT4
 
+5P49V5935:
+       0 -- OUT0_SEL_I2CB
+       1 -- OUT1
+       2 -- OUT2
+       3 -- OUT3
+       4 -- OUT4
+
 ==Example==
 
 /* 25MHz reference crystal */
index eb985a633d595b98fe3d861e06b4efe468e25d9c..796c260c183d6af6d202752d453beb6363109c97 100644 (file)
@@ -31,6 +31,12 @@ The following is a list of provided IDs and clock names on Armada 39x:
  4 = dclk    (SDRAM Interface Clock)
  5 = refclk  (Reference Clock)
 
+The following is a list of provided IDs and clock names on 98dx3236:
+ 0 = tclk    (Internal Bus clock)
+ 1 = cpuclk  (CPU clock)
+ 2 = ddrclk   (DDR clock)
+ 3 = mpll    (MPLL Clock)
+
 The following is a list of provided IDs and clock names on Kirkwood and Dove:
  0 = tclk   (Internal Bus clock)
  1 = cpuclk (CPU0 clock)
@@ -49,6 +55,7 @@ Required properties:
        "marvell,armada-380-core-clock" - For Armada 380/385 SoC core clocks
        "marvell,armada-390-core-clock" - For Armada 39x SoC core clocks
        "marvell,armada-xp-core-clock" - For Armada XP SoC core clocks
+       "marvell,mv98dx3236-core-clock" - For 98dx3236 family SoC core clocks
        "marvell,dove-core-clock" - for Dove SoC core clocks
        "marvell,kirkwood-core-clock" - for Kirkwood SoC (except mv88f6180)
        "marvell,mv88f6180-core-clock" - for Kirkwood MV88f6180 SoC
index 5142efc8099d24c927859cac7ca4d317853bfbdf..de562da2ae77db48639d1a775ca5efd489e5de04 100644 (file)
@@ -119,6 +119,16 @@ ID Clock   Peripheral
 29     sata1lnk
 30     sata1   SATA Host 1
 
+The following is a list of provided IDs for 98dx3236:
+ID     Clock   Peripheral
+-----------------------------------
+3      ge1     Gigabit Ethernet 1
+4      ge0     Gigabit Ethernet 0
+5      pex0    PCIe Cntrl 0
+17     sdio    SDHCI Host
+18     usb0    USB Host 0
+22     xor0    XOR DMA 0
+
 The following is a list of provided IDs for Dove:
 ID     Clock   Peripheral
 -----------------------------------
@@ -169,6 +179,7 @@ Required properties:
        "marvell,armada-380-gating-clock" - for Armada 380/385 SoC clock gating
        "marvell,armada-390-gating-clock" - for Armada 39x SoC clock gating
        "marvell,armada-xp-gating-clock" - for Armada XP SoC clock gating
+       "marvell,mv98dx3236-gating-clock" - for 98dx3236 SoC clock gating
        "marvell,dove-gating-clock" - for Dove SoC clock gating
        "marvell,kirkwood-gating-clock" - for Kirkwood SoC clock gating
 - reg : shall be the register address of the Clock Gating Control register
index aa3526f229a721435766bb7ac3d6a82dd14feaa9..6ed469c66b32f42c4bfb62849ce5451618d5067e 100644 (file)
@@ -35,6 +35,7 @@ Required properties:
        * "fsl,ls1021a-clockgen"
        * "fsl,ls1043a-clockgen"
        * "fsl,ls1046a-clockgen"
+       * "fsl,ls1088a-clockgen"
        * "fsl,ls2080a-clockgen"
        Chassis-version clock strings include:
        * "fsl,qoriq-clockgen-1.0": for chassis 1.0 clocks
similarity index 83%
rename from Documentation/devicetree/bindings/clock/rockchip,rk1108-cru.txt
rename to Documentation/devicetree/bindings/clock/rockchip,rv1108-cru.txt
index 4da126116cf007602bee3107c3222a537f7af856..161326a4f9c1feebe41d0ee38e8089c769043dd1 100644 (file)
@@ -1,12 +1,12 @@
-* Rockchip RK1108 Clock and Reset Unit
+* Rockchip RV1108 Clock and Reset Unit
 
-The RK1108 clock controller generates and supplies clock to various
+The RV1108 clock controller generates and supplies clock to various
 controllers within the SoC and also implements a reset controller for SoC
 peripherals.
 
 Required Properties:
 
-- compatible: should be "rockchip,rk1108-cru"
+- compatible: should be "rockchip,rv1108-cru"
 - reg: physical base address of the controller and length of memory mapped
   region.
 - #clock-cells: should be 1.
@@ -19,7 +19,7 @@ Optional Properties:
 
 Each clock is assigned an identifier and client nodes can use this identifier
 to specify the clock which they consume. All available clocks are defined as
-preprocessor macros in the dt-bindings/clock/rk1108-cru.h headers and can be
+preprocessor macros in the dt-bindings/clock/rv1108-cru.h headers and can be
 used in device tree sources. Similar macros exist for the reset sources in
 these files.
 
@@ -38,7 +38,7 @@ clock-output-names:
 Example: Clock controller node:
 
        cru: cru@20200000 {
-               compatible = "rockchip,rk1108-cru";
+               compatible = "rockchip,rv1108-cru";
                reg = <0x20200000 0x1000>;
                rockchip,grf = <&grf>;
 
@@ -50,7 +50,7 @@ Example: UART controller node that consumes the clock generated by the clock
   controller:
 
        uart0: serial@10230000 {
-               compatible = "rockchip,rk1108-uart", "snps,dw-apb-uart";
+               compatible = "rockchip,rv1108-uart", "snps,dw-apb-uart";
                reg = <0x10230000 0x100>;
                interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
                reg-shift = <2>;
index bae5668cf427836642a81ebe2e1d9b8b386bee71..e9c5a1d9834af600de55821bc0077e6235ff0bff 100644 (file)
@@ -7,9 +7,12 @@ Required properties :
                - "allwinner,sun8i-a23-ccu"
                - "allwinner,sun8i-a33-ccu"
                - "allwinner,sun8i-h3-ccu"
+               - "allwinner,sun8i-h3-r-ccu"
                - "allwinner,sun8i-v3s-ccu"
                - "allwinner,sun9i-a80-ccu"
                - "allwinner,sun50i-a64-ccu"
+               - "allwinner,sun50i-a64-r-ccu"
+               - "allwinner,sun50i-h5-ccu"
 
 - reg: Must contain the registers base address and length
 - clocks: phandle to the oscillators feeding the CCU. Two are needed:
@@ -19,7 +22,10 @@ Required properties :
 - #clock-cells : must contain 1
 - #reset-cells : must contain 1
 
-Example:
+For the PRCM CCUs on H3/A64, one more clock is needed:
+- "iosc": the SoC's internal frequency oscillator
+
+Example for generic CCU:
 ccu: clock@01c20000 {
        compatible = "allwinner,sun8i-h3-ccu";
        reg = <0x01c20000 0x400>;
@@ -28,3 +34,13 @@ ccu: clock@01c20000 {
        #clock-cells = <1>;
        #reset-cells = <1>;
 };
+
+Example for PRCM CCU:
+r_ccu: clock@01f01400 {
+       compatible = "allwinner,sun50i-a64-r-ccu";
+       reg = <0x01f01400 0x100>;
+       clocks = <&osc24M>, <&osc32k>, <&iosc>;
+       clock-names = "hosc", "losc", "iosc";
+       #clock-cells = <1>;
+       #reset-cells = <1>;
+};
index d085ef90d27c1f8b82645177169f71c3eb42d00f..f8e946471a58d7bb6ac07d22cf6a876d8c509410 100644 (file)
@@ -202,23 +202,23 @@ Example2 :
                compatible = "operating-points-v2";
                opp-shared;
 
-               opp@50000000 {
+               opp-50000000 {
                        opp-hz = /bits/ 64 <50000000>;
                        opp-microvolt = <800000>;
                };
-               opp@100000000 {
+               opp-100000000 {
                        opp-hz = /bits/ 64 <100000000>;
                        opp-microvolt = <800000>;
                };
-               opp@134000000 {
+               opp-134000000 {
                        opp-hz = /bits/ 64 <134000000>;
                        opp-microvolt = <800000>;
                };
-               opp@200000000 {
+               opp-200000000 {
                        opp-hz = /bits/ 64 <200000000>;
                        opp-microvolt = <825000>;
                };
-               opp@400000000 {
+               opp-400000000 {
                        opp-hz = /bits/ 64 <400000000>;
                        opp-microvolt = <875000>;
                };
@@ -292,23 +292,23 @@ Example2 :
                compatible = "operating-points-v2";
                opp-shared;
 
-               opp@50000000 {
+               opp-50000000 {
                        opp-hz = /bits/ 64 <50000000>;
                        opp-microvolt = <900000>;
                };
-               opp@80000000 {
+               opp-80000000 {
                        opp-hz = /bits/ 64 <80000000>;
                        opp-microvolt = <900000>;
                };
-               opp@100000000 {
+               opp-100000000 {
                        opp-hz = /bits/ 64 <100000000>;
                        opp-microvolt = <1000000>;
                };
-               opp@134000000 {
+               opp-134000000 {
                        opp-hz = /bits/ 64 <134000000>;
                        opp-microvolt = <1000000>;
                };
-               opp@200000000 {
+               opp-200000000 {
                        opp-hz = /bits/ 64 <200000000>;
                        opp-microvolt = <1000000>;
                };
@@ -318,19 +318,19 @@ Example2 :
                compatible = "operating-points-v2";
                opp-shared;
 
-               opp@50000000 {
+               opp-50000000 {
                        opp-hz = /bits/ 64 <50000000>;
                };
-               opp@80000000 {
+               opp-80000000 {
                        opp-hz = /bits/ 64 <80000000>;
                };
-               opp@100000000 {
+               opp-100000000 {
                        opp-hz = /bits/ 64 <100000000>;
                };
-               opp@200000000 {
+               opp-200000000 {
                        opp-hz = /bits/ 64 <200000000>;
                };
-               opp@400000000 {
+               opp-400000000 {
                        opp-hz = /bits/ 64 <400000000>;
                };
        };
@@ -339,19 +339,19 @@ Example2 :
                compatible = "operating-points-v2";
                opp-shared;
 
-               opp@50000000 {
+               opp-50000000 {
                        opp-hz = /bits/ 64 <50000000>;
                };
-               opp@80000000 {
+               opp-80000000 {
                        opp-hz = /bits/ 64 <80000000>;
                };
-               opp@100000000 {
+               opp-100000000 {
                        opp-hz = /bits/ 64 <100000000>;
                };
-               opp@200000000 {
+               opp-200000000 {
                        opp-hz = /bits/ 64 <200000000>;
                };
-               opp@300000000 {
+               opp-300000000 {
                        opp-hz = /bits/ 64 <300000000>;
                };
        };
@@ -360,13 +360,13 @@ Example2 :
                compatible = "operating-points-v2";
                opp-shared;
 
-               opp@50000000 {
+               opp-50000000 {
                        opp-hz = /bits/ 64 <50000000>;
                };
-               opp@80000000 {
+               opp-80000000 {
                        opp-hz = /bits/ 64 <80000000>;
                };
-               opp@100000000 {
+               opp-100000000 {
                        opp-hz = /bits/ 64 <100000000>;
                };
        };
index 7a5c0e204c8edf031c263a4129966445fdd9d0f9..e5a8b363d82972dc64133b69be7cc190f4470f56 100644 (file)
@@ -13,6 +13,8 @@ Required nodes:
        Additional, the display node has to define properties:
        - bits-per-pixel: Bits per pixel
        - fsl,pcr: LCDC PCR value
+       A display node may optionally define
+       - fsl,aus-mode: boolean to enable AUS mode (only for imx21)
 
 Optional properties:
 - lcd-supply: Regulator for LCD supply voltage.
index b82c004494681341bdef251e9323bb1df4773581..57a8d061006276730b07ff1ebf9867f52841e673 100644 (file)
@@ -94,6 +94,7 @@ Required properties:
     * allwinner,sun6i-a31-display-backend
     * allwinner,sun8i-a33-display-backend
   - reg: base address and size of the memory-mapped region.
+  - interrupts: interrupt associated to this IP
   - clocks: phandles to the clocks feeding the frontend and backend
     * ahb: the backend interface clock
     * mod: the backend module clock
@@ -265,6 +266,7 @@ fe0: display-frontend@1e00000 {
 be0: display-backend@1e60000 {
        compatible = "allwinner,sun5i-a13-display-backend";
        reg = <0x01e60000 0x10000>;
+       interrupts = <47>;
        clocks = <&ahb_gates 44>, <&de_be_clk>,
                 <&dram_gates 26>;
        clock-names = "ahb", "mod",
index 476f5ea6c6276a15c52ffc87a7a1033c6d173a26..2b6243e730f690f9bbf2f0c50295b91c0699129f 100644 (file)
@@ -35,6 +35,14 @@ Optional properties:
   - interrupt-names and interrupts:
     * pmu: Power Management Unit interrupt, if implemented in hardware
 
+  - memory-region:
+    Memory region to allocate from, as defined in
+    Documentation/devicetree/bindi/reserved-memory/reserved-memory.txt
+
+  - operating-points-v2:
+    Operating Points for the GPU, as defined in
+    Documentation/devicetree/bindings/opp/opp.txt
+
 Vendor-specific bindings
 ------------------------
 
index ff3db65e50def8224096107eaf05827df884ca25..b7e4c74445108dcd2c966529a85a4a930b40e831 100644 (file)
@@ -5,6 +5,7 @@ Required properties:
   Currently recognized values:
   - nvidia,gk20a
   - nvidia,gm20b
+  - nvidia,gp10b
 - reg: Physical base address and length of the controller's registers.
   Must contain two entries:
   - first entry for bar0
@@ -14,7 +15,8 @@ Required properties:
 - interrupt-names: Must include the following entries:
   - stall
   - nonstall
-- vdd-supply: regulator for supply voltage.
+- vdd-supply: regulator for supply voltage. Only required for GPUs not using
+  power domains.
 - clocks: Must contain an entry for each entry in clock-names.
   See ../clocks/clock-bindings.txt for details.
 - clock-names: Must include the following entries:
@@ -27,6 +29,8 @@ is also required:
   See ../reset/reset.txt for details.
 - reset-names: Must include the following entries:
   - gpu
+- power-domains: GPUs that make use of power domains can define this property
+  instead of vdd-supply. Currently "nvidia,gp10b" makes use of this.
 
 Optional properties:
 - iommus: A reference to the IOMMU. See ../iommu/iommu.txt for details.
@@ -68,3 +72,22 @@ Example for GM20B:
                iommus = <&mc TEGRA_SWGROUP_GPU>;
                status = "disabled";
        };
+
+Example for GP10B:
+
+       gpu@17000000 {
+               compatible = "nvidia,gp10b";
+               reg = <0x0 0x17000000 0x0 0x1000000>,
+                     <0x0 0x18000000 0x0 0x1000000>;
+               interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH
+                             GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "stall", "nonstall";
+               clocks = <&bpmp TEGRA186_CLK_GPCCLK>,
+                        <&bpmp TEGRA186_CLK_GPU>;
+               clock-names = "gpu", "pwr";
+               resets = <&bpmp TEGRA186_RESET_GPU>;
+               reset-names = "gpu";
+               power-domains = <&bpmp TEGRA186_POWER_DOMAIN_GPU>;
+               iommus = <&smmu TEGRA186_SID_GPU>;
+               status = "disabled";
+       };
index 6cdf32d037fcbedc1a25d7f283026ff89f73b361..8a6ffce12af5305e8c630724fa86f735c1884f4d 100644 (file)
@@ -60,6 +60,17 @@ conditions.
                   aliases of secure registers have to be used during
                   SMMU configuration.
 
+- stream-match-mask : For SMMUs supporting stream matching and using
+                  #iommu-cells = <1>, specifies a mask of bits to ignore
+                 when matching stream IDs (e.g. this may be programmed
+                 into the SMRn.MASK field of every stream match register
+                 used). For cases where it is desirable to ignore some
+                  portion of every Stream ID (e.g. for certain MMU-500
+                  configurations given globally unique input IDs). This
+                  property is not valid for SMMUs using stream indexing,
+                  or using stream matching with #iommu-cells = <2>, and
+                  may be ignored if present in such cases.
+
 ** Deprecated properties:
 
 - mmu-masters (deprecated in favour of the generic "iommus" binding) :
@@ -109,3 +120,20 @@ conditions.
         master3 {
                 iommus = <&smmu2 1 0x30>;
         };
+
+
+        /* ARM MMU-500 with 10-bit stream ID input configuration */
+        smmu3: iommu {
+                compatible = "arm,mmu-500", "arm,smmu-v2";
+                ...
+                #iommu-cells = <1>;
+                /* always ignore appended 5-bit TBU number */
+                stream-match-mask = 0x7c00;
+        };
+
+        bus {
+                /* bus whose child devices emit one unique 10-bit stream
+                   ID each, but may master through multiple SMMU TBUs */
+                iommu-map = <0 &smmu3 0 0x400>;
+                ...
+        };
index 3e7ee99d3949ab07b5515e3afff350aebc2e0e71..f6bee57e453aa6dcb9114a188538e1c69860b4b2 100644 (file)
@@ -1,4 +1,109 @@
-Atmel NAND flash
+Atmel NAND flash controller bindings
+
+The NAND flash controller node should be defined under the EBI bus (see
+Documentation/devicetree/bindings/memory-controllers/atmel,ebi.txt).
+One or several NAND devices can be defined under this NAND controller.
+The NAND controller might be connected to an ECC engine.
+
+* NAND controller bindings:
+
+Required properties:
+- compatible: should be one of the following
+       "atmel,at91rm9200-nand-controller"
+       "atmel,at91sam9260-nand-controller"
+       "atmel,at91sam9261-nand-controller"
+       "atmel,at91sam9g45-nand-controller"
+       "atmel,sama5d3-nand-controller"
+- ranges: empty ranges property to forward EBI ranges definitions.
+- #address-cells: should be set to 2.
+- #size-cells: should be set to 1.
+- atmel,nfc-io: phandle to the NFC IO block. Only required for sama5d3
+               controllers.
+- atmel,nfc-sram: phandle to the NFC SRAM block. Only required for sama5d3
+                 controllers.
+
+Optional properties:
+- ecc-engine: phandle to the PMECC block. Only meaningful if the SoC embeds
+             a PMECC engine.
+
+* NAND device/chip bindings:
+
+Required properties:
+- reg: describes the CS lines assigned to the NAND device. If the NAND device
+       exposes multiple CS lines (multi-dies chips), your reg property will
+       contain X tuples of 3 entries.
+       1st entry: the CS line this NAND chip is connected to
+       2nd entry: the base offset of the memory region assigned to this
+                 device (always 0)
+       3rd entry: the memory region size (always 0x800000)
+
+Optional properties:
+- rb-gpios: the GPIO(s) used to check the Ready/Busy status of the NAND.
+- cs-gpios: the GPIO(s) used to control the CS line.
+- det-gpios: the GPIO used to detect if a Smartmedia Card is present.
+- atmel,rb: an integer identifying the native Ready/Busy pin. Only meaningful
+           on sama5 SoCs.
+
+All generic properties described in
+Documentation/devicetree/bindings/mtd/{common,nand}.txt also apply to the NAND
+device node, and NAND partitions should be defined under the NAND node as
+described in Documentation/devicetree/bindings/mtd/partition.txt.
+
+* ECC engine (PMECC) bindings:
+
+Required properties:
+- compatible: should be one of the following
+       "atmel,at91sam9g45-pmecc"
+       "atmel,sama5d4-pmecc"
+       "atmel,sama5d2-pmecc"
+- reg: should contain 2 register ranges. The first one is pointing to the PMECC
+       block, and the second one to the PMECC_ERRLOC block.
+
+Example:
+
+       pmecc: ecc-engine@ffffc070 {
+               compatible = "atmel,at91sam9g45-pmecc";
+                reg = <0xffffc070 0x490>,
+                      <0xffffc500 0x100>;
+       };
+
+       ebi: ebi@10000000 {
+               compatible = "atmel,sama5d3-ebi";
+               #address-cells = <2>;
+               #size-cells = <1>;
+               atmel,smc = <&hsmc>;
+               reg = <0x10000000 0x10000000
+                      0x40000000 0x30000000>;
+               ranges = <0x0 0x0 0x10000000 0x10000000
+                         0x1 0x0 0x40000000 0x10000000
+                         0x2 0x0 0x50000000 0x10000000
+                         0x3 0x0 0x60000000 0x10000000>;
+               clocks = <&mck>;
+
+                nand_controller: nand-controller {
+                       compatible = "atmel,sama5d3-nand-controller";
+                       atmel,nfc-sram = <&nfc_sram>;
+                       atmel,nfc-io = <&nfc_io>;
+                       ecc-engine = <&pmecc>;
+                       #address-cells = <2>;
+                       #size-cells = <1>;
+                       ranges;
+
+                       nand@3 {
+                               reg = <0x3 0x0 0x800000>;
+                               atmel,rb = <0>;
+
+                               /*
+                                * Put generic NAND/MTD properties and
+                                * subnodes here.
+                                */
+                       };
+               };
+       };
+
+-----------------------------------------------------------------------
+
+Deprecated bindings (should not be used in new device trees):
 
 Required properties:
 - compatible: The possible values are:
index b04d03a1d49951a0fe6fbecde446fb523919f811..e593bbeb2115deb92966d593c18f002e5f269e41 100644 (file)
@@ -1,11 +1,11 @@
 * Denali NAND controller
 
 Required properties:
-  - compatible : should be "denali,denali-nand-dt"
+  - compatible : should be one of the following:
+      "altr,socfpga-denali-nand"            - for Altera SOCFPGA
   - reg : should contain registers location and length for data and reg.
   - reg-names: Should contain the reg names "nand_data" and "denali_reg"
   - interrupts : The interrupt number.
-  - dm-mask : DMA bit mask
 
 The device tree may optionally contain sub-nodes describing partitions of the
 address space. See partition.txt for more detail.
@@ -15,9 +15,8 @@ Examples:
 nand: nand@ff900000 {
        #address-cells = <1>;
        #size-cells = <1>;
-       compatible = "denali,denali-nand-dt";
+       compatible = "altr,socfpga-denali-nand";
        reg = <0xff900000 0x100000>, <0xffb80000 0x10000>;
        reg-names = "nand_data", "denali_reg";
        interrupts = <0 144 4>;
-       dma-mask = <0xffffffff>;
 };
index af8915b41ccf4962f9aa3a232b5bd268910ae3b7..486a17d533d7a33cce0ac8814a51979ebc7bc0ca 100644 (file)
@@ -12,7 +12,7 @@ Required properties:
 - #address-cells, #size-cells : Must be present if the device has sub-nodes
   representing partitions.
 - gpios : Specifies the GPIO pins to control the NAND device.  The order of
-  GPIO references is:  RDY, nCE, ALE, CLE, and an optional nWP.
+  GPIO references is:  RDY, nCE, ALE, CLE, and nWP. nCE and nWP are optional.
 
 Optional properties:
 - bank-width : Width (in bytes) of the device.  If not present, the width
@@ -36,7 +36,7 @@ gpio-nand@1,0 {
        #address-cells = <1>;
        #size-cells = <1>;
        gpios = <&banka 1 0>,   /* RDY */
-               <&banka 2 0>,   /* nCE */
+               <0>,            /* nCE */
                <&banka 3 0>,   /* ALE */
                <&banka 4 0>,   /* CLE */
                <0>;            /* nWP */
index 3e920ec5c4d36d48148e069ccb9de617dbee2326..9ce35af8507c1da0a208fc1823b5d1d487909114 100644 (file)
@@ -40,6 +40,7 @@ Required properties:
                  w25x80
                  w25x32
                  w25q32
+                 w25q64
                  w25q32dw
                  w25q80bl
                  w25q128
diff --git a/Documentation/devicetree/bindings/mtd/stm32-quadspi.txt b/Documentation/devicetree/bindings/mtd/stm32-quadspi.txt
new file mode 100644 (file)
index 0000000..ddd18c1
--- /dev/null
@@ -0,0 +1,43 @@
+* STMicroelectronics Quad Serial Peripheral Interface(QuadSPI)
+
+Required properties:
+- compatible: should be "st,stm32f469-qspi"
+- reg: the first contains the register location and length.
+       the second contains the memory mapping address and length
+- reg-names: should contain the reg names "qspi" "qspi_mm"
+- interrupts: should contain the interrupt for the device
+- clocks: the phandle of the clock needed by the QSPI controller
+- A pinctrl must be defined to set pins in mode of operation for QSPI transfer
+
+Optional properties:
+- resets: must contain the phandle to the reset controller.
+
+A spi flash must be a child of the nor_flash node and could have some
+properties. Also see jedec,spi-nor.txt.
+
+Required properties:
+- reg: chip-Select number (QSPI controller may connect 2 nor flashes)
+- spi-max-frequency: max frequency of spi bus
+
+Optional property:
+- spi-rx-bus-width: see ../spi/spi-bus.txt for the description
+
+Example:
+
+qspi: spi@a0001000 {
+       compatible = "st,stm32f469-qspi";
+       reg = <0xa0001000 0x1000>, <0x90000000 0x10000000>;
+       reg-names = "qspi", "qspi_mm";
+       interrupts = <91>;
+       resets = <&rcc STM32F4_AHB3_RESET(QSPI)>;
+       clocks = <&rcc 0 STM32F4_AHB3_CLOCK(QSPI)>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_qspi0>;
+
+       flash@0 {
+               reg = <0>;
+               spi-rx-bus-width = <4>;
+               spi-max-frequency = <108000000>;
+               ...
+       };
+};
index 5fbab29718e8ee087ffd2a3d6dc13e973d1bf48d..c329608fa887b1fad655f7c778ca539b4c5d36c6 100644 (file)
@@ -32,19 +32,16 @@ DFX Server bindings
 -------------------
 
 Required properties:
-- compatible: must be "marvell,dfx-server"
+- compatible: must be "marvell,dfx-server", "simple-bus"
+- ranges: describes the address mapping of a memory-mapped bus.
 - reg: address and length of the register set for the device.
 
 Example:
 
-dfx-registers {
-       compatible = "simple-bus";
+dfx-server {
+       compatible = "marvell,dfx-server", "simple-bus";
        #address-cells = <1>;
        #size-cells = <1>;
        ranges = <0 MBUS_ID(0x08, 0x00) 0 0x100000>;
-
-       dfx: dfx@0 {
-               compatible = "marvell,dfx-server";
-               reg = <0 0x100000>;
-       };
+       reg = <MBUS_ID(0x08, 0x00) 0 0x100000>;
 };
index 1392c705cecae84c1bdbd601e27d91d78dc60980..b2480dd38c1135747c6bcceb5153df94a6a36326 100644 (file)
@@ -6,30 +6,40 @@ Required properties:
 - reg-names: Must be "config" for the PCIe configuration space.
     (The old way of getting the configuration address space from "ranges"
     is deprecated and should be avoided.)
+- num-lanes: number of lanes to use
+RC mode:
 - #address-cells: set to <3>
 - #size-cells: set to <2>
 - device_type: set to "pci"
 - ranges: ranges for the PCI memory and I/O regions
 - #interrupt-cells: set to <1>
-- interrupt-map-mask and interrupt-map: standard PCI properties
-       to define the mapping of the PCIe interface to interrupt
+- interrupt-map-mask and interrupt-map: standard PCI
+       properties to define the mapping of the PCIe interface to interrupt
        numbers.
-- num-lanes: number of lanes to use
+EP mode:
+- num-ib-windows: number of inbound address translation
+        windows
+- num-ob-windows: number of outbound address translation
+        windows
 
 Optional properties:
-- num-viewport: number of view ports configured in hardware.  If a platform
-  does not specify it, the driver assumes 2.
 - num-lanes: number of lanes to use (this property should be specified unless
   the link is brought already up in BIOS)
 - reset-gpio: gpio pin number of power good signal
-- bus-range: PCI bus numbers covered (it is recommended for new devicetrees to
-  specify this property, to keep backwards compatibility a range of 0x00-0xff
-  is assumed if not present)
 - clocks: Must contain an entry for each entry in clock-names.
        See ../clocks/clock-bindings.txt for details.
 - clock-names: Must include the following entries:
        - "pcie"
        - "pcie_bus"
+RC mode:
+- num-viewport: number of view ports configured in
+  hardware. If a platform does not specify it, the driver assumes 2.
+- bus-range: PCI bus numbers covered (it is recommended
+  for new devicetrees to specify this property, to keep backwards
+  compatibility a range of 0x00-0xff is assumed if not present)
+EP mode:
+- max-functions: maximum number of functions that can be
+  configured
 
 Example configuration:
 
diff --git a/Documentation/devicetree/bindings/pci/faraday,ftpci100.txt b/Documentation/devicetree/bindings/pci/faraday,ftpci100.txt
new file mode 100644 (file)
index 0000000..35d4a97
--- /dev/null
@@ -0,0 +1,129 @@
+Faraday Technology FTPCI100 PCI Host Bridge
+
+This PCI bridge is found inside that Cortina Systems Gemini SoC platform and
+is a generic IP block from Faraday Technology. It exists in two variants:
+plain and dual PCI. The plain version embeds a cascading interrupt controller
+into the host bridge. The dual version routes the interrupts to the host
+chips interrupt controller.
+
+The host controller appear on the PCI bus with vendor ID 0x159b (Faraday
+Technology) and product ID 0x4321.
+
+Mandatory properties:
+
+- compatible: ranging from specific to generic, should be one of
+  "cortina,gemini-pci", "faraday,ftpci100"
+  "cortina,gemini-pci-dual", "faraday,ftpci100-dual"
+  "faraday,ftpci100"
+  "faraday,ftpci100-dual"
+- reg: memory base and size for the host bridge
+- #address-cells: set to <3>
+- #size-cells: set to <2>
+- #interrupt-cells: set to <1>
+- bus-range: set to <0x00 0xff>
+- device_type, set to "pci"
+- ranges: see pci.txt
+- interrupt-map-mask: see pci.txt
+- interrupt-map: see pci.txt
+- dma-ranges: three ranges for the inbound memory region. The ranges must
+  be aligned to a 1MB boundary, and may be 1MB, 2MB, 4MB, 8MB, 16MB, 32MB, 64MB,
+  128MB, 256MB, 512MB, 1GB or 2GB in size. The memory should be marked as
+  pre-fetchable.
+
+Mandatory subnodes:
+- For "faraday,ftpci100" a node representing the interrupt-controller inside the
+  host bridge is mandatory. It has the following mandatory properties:
+  - interrupt: see interrupt-controller/interrupts.txt
+  - interrupt-parent: see interrupt-controller/interrupts.txt
+  - interrupt-controller: see interrupt-controller/interrupts.txt
+  - #address-cells: set to <0>
+  - #interrupt-cells: set to <1>
+
+I/O space considerations:
+
+The plain variant has 128MiB of non-prefetchable memory space, whereas the
+"dual" variant has 64MiB. Take this into account when describing the ranges.
+
+Interrupt map considerations:
+
+The "dual" variant will get INT A, B, C, D from the system interrupt controller
+and should point to respective interrupt in that controller in its
+interrupt-map.
+
+The code which is the only documentation of how the Faraday PCI (the non-dual
+variant) interrupts assigns the default interrupt mapping/swizzling has
+typically been like this, doing the swizzling on the interrupt controller side
+rather than in the interconnect:
+
+interrupt-map-mask = <0xf800 0 0 7>;
+interrupt-map =
+       <0x4800 0 0 1 &pci_intc 0>, /* Slot 9 */
+       <0x4800 0 0 2 &pci_intc 1>,
+       <0x4800 0 0 3 &pci_intc 2>,
+       <0x4800 0 0 4 &pci_intc 3>,
+       <0x5000 0 0 1 &pci_intc 1>, /* Slot 10 */
+       <0x5000 0 0 2 &pci_intc 2>,
+       <0x5000 0 0 3 &pci_intc 3>,
+       <0x5000 0 0 4 &pci_intc 0>,
+       <0x5800 0 0 1 &pci_intc 2>, /* Slot 11 */
+       <0x5800 0 0 2 &pci_intc 3>,
+       <0x5800 0 0 3 &pci_intc 0>,
+       <0x5800 0 0 4 &pci_intc 1>,
+       <0x6000 0 0 1 &pci_intc 3>, /* Slot 12 */
+       <0x6000 0 0 2 &pci_intc 0>,
+       <0x6000 0 0 3 &pci_intc 1>,
+       <0x6000 0 0 4 &pci_intc 2>;
+
+Example:
+
+pci@50000000 {
+       compatible = "cortina,gemini-pci", "faraday,ftpci100";
+       reg = <0x50000000 0x100>;
+       interrupts = <8 IRQ_TYPE_LEVEL_HIGH>, /* PCI A */
+                       <26 IRQ_TYPE_LEVEL_HIGH>, /* PCI B */
+                       <27 IRQ_TYPE_LEVEL_HIGH>, /* PCI C */
+                       <28 IRQ_TYPE_LEVEL_HIGH>; /* PCI D */
+       #address-cells = <3>;
+       #size-cells = <2>;
+       #interrupt-cells = <1>;
+
+       bus-range = <0x00 0xff>;
+       ranges = /* 1MiB I/O space 0x50000000-0x500fffff */
+                <0x01000000 0 0          0x50000000 0 0x00100000>,
+                /* 128MiB non-prefetchable memory 0x58000000-0x5fffffff */
+                <0x02000000 0 0x58000000 0x58000000 0 0x08000000>;
+
+       /* DMA ranges */
+       dma-ranges =
+       /* 128MiB at 0x00000000-0x07ffffff */
+       <0x02000000 0 0x00000000 0x00000000 0 0x08000000>,
+       /* 64MiB at 0x00000000-0x03ffffff */
+       <0x02000000 0 0x00000000 0x00000000 0 0x04000000>,
+       /* 64MiB at 0x00000000-0x03ffffff */
+       <0x02000000 0 0x00000000 0x00000000 0 0x04000000>;
+
+       interrupt-map-mask = <0xf800 0 0 7>;
+       interrupt-map =
+               <0x4800 0 0 1 &pci_intc 0>, /* Slot 9 */
+               <0x4800 0 0 2 &pci_intc 1>,
+               <0x4800 0 0 3 &pci_intc 2>,
+               <0x4800 0 0 4 &pci_intc 3>,
+               <0x5000 0 0 1 &pci_intc 1>, /* Slot 10 */
+               <0x5000 0 0 2 &pci_intc 2>,
+               <0x5000 0 0 3 &pci_intc 3>,
+               <0x5000 0 0 4 &pci_intc 0>,
+               <0x5800 0 0 1 &pci_intc 2>, /* Slot 11 */
+               <0x5800 0 0 2 &pci_intc 3>,
+               <0x5800 0 0 3 &pci_intc 0>,
+               <0x5800 0 0 4 &pci_intc 1>,
+               <0x6000 0 0 1 &pci_intc 3>, /* Slot 12 */
+               <0x6000 0 0 2 &pci_intc 0>,
+               <0x6000 0 0 3 &pci_intc 0>,
+               <0x6000 0 0 4 &pci_intc 0>;
+       pci_intc: interrupt-controller {
+               interrupt-parent = <&intcon>;
+               interrupt-controller;
+               #address-cells = <0>;
+               #interrupt-cells = <1>;
+       };
+};
index 83aeb1f5a645ce2fe494e14dedce27dc7085155f..e3d5680875b123326c7cc5527c8f85d7219fe691 100644 (file)
@@ -4,7 +4,11 @@ This PCIe host controller is based on the Synopsis Designware PCIe IP
 and thus inherits all the common properties defined in designware-pcie.txt.
 
 Required properties:
-- compatible: "fsl,imx6q-pcie", "fsl,imx6sx-pcie", "fsl,imx6qp-pcie"
+- compatible:
+       - "fsl,imx6q-pcie"
+       - "fsl,imx6sx-pcie",
+       - "fsl,imx6qp-pcie"
+       - "fsl,imx7d-pcie"
 - reg: base address and length of the PCIe controller
 - interrupts: A list of interrupt outputs of the controller. Must contain an
   entry for each entry in the interrupt-names property.
@@ -34,6 +38,14 @@ Additional required properties for imx6sx-pcie:
 - clock names: Must include the following additional entries:
        - "pcie_inbound_axi"
 
+Additional required properties for imx7d-pcie:
+- power-domains: Must be set to a phandle pointing to PCIE_PHY power domain
+- resets: Must contain phandles to PCIe-related reset lines exposed by SRC
+  IP block
+- reset-names: Must contain the following entires:
+              - "pciephy"
+              - "apps"
+
 Example:
 
        pcie@0x01000000 {
index 60e25161f35181bfd026b48519f43666d33f091e..6a07c96227e0a0a9bd96530c2833df195657e7dc 100644 (file)
@@ -1,17 +1,22 @@
 TI PCI Controllers
 
 PCIe Designware Controller
- - compatible: Should be "ti,dra7-pcie""
- - reg : Two register ranges as listed in the reg-names property
- - reg-names : The first entry must be "ti-conf" for the TI specific registers
-              The second entry must be "rc-dbics" for the designware pcie
-              registers
-              The third entry must be "config" for the PCIe configuration space
+ - compatible: Should be "ti,dra7-pcie" for RC
+              Should be "ti,dra7-pcie-ep" for EP
  - phys : list of PHY specifiers (used by generic PHY framework)
  - phy-names : must be "pcie-phy0", "pcie-phy1", "pcie-phyN".. based on the
               number of PHYs as specified in *phys* property.
  - ti,hwmods : Name of the hwmod associated to the pcie, "pcie<X>",
               where <X> is the instance number of the pcie from the HW spec.
+ - num-lanes as specified in ../designware-pcie.txt
+
+HOST MODE
+=========
+ - reg : Two register ranges as listed in the reg-names property
+ - reg-names : The first entry must be "ti-conf" for the TI specific registers
+              The second entry must be "rc-dbics" for the DesignWare PCIe
+              registers
+              The third entry must be "config" for the PCIe configuration space
  - interrupts : Two interrupt entries must be specified. The first one is for
                main interrupt line and the second for MSI interrupt line.
  - #address-cells,
@@ -19,13 +24,36 @@ PCIe Designware Controller
    #interrupt-cells,
    device_type,
    ranges,
-   num-lanes,
    interrupt-map-mask,
    interrupt-map : as specified in ../designware-pcie.txt
 
+DEVICE MODE
+===========
+ - reg : Four register ranges as listed in the reg-names property
+ - reg-names : "ti-conf" for the TI specific registers
+              "ep_dbics" for the standard configuration registers as
+               they are locally accessed within the DIF CS space
+              "ep_dbics2" for the standard configuration registers as
+               they are locally accessed within the DIF CS2 space
+              "addr_space" used to map remote RC address space
+ - interrupts : one interrupt entries must be specified for main interrupt.
+ - num-ib-windows : number of inbound address translation windows
+ - num-ob-windows : number of outbound address translation windows
+ - ti,syscon-unaligned-access: phandle to the syscon DT node. The 1st argument
+                              should contain the register offset within syscon
+                              and the 2nd argument should contain the bit field
+                              for setting the bit to enable unaligned
+                              access.
+
 Optional Property:
  - gpios : Should be added if a gpio line is required to drive PERST# line
 
+NOTE: Two DT nodes may be added for each PCI controller; one for host
+mode and another for device mode. So in order for PCI to
+work in host mode, EP mode DT node should be disabled and in order to PCI to
+work in EP mode, host mode DT node should be disabled. Host mode and EP
+mode are mutually exclusive.
+
 Example:
 axi {
        compatible = "simple-bus";
index 65cc0345747d73f540d6c5a4e8b18acc1618953b..6c1498958d48c0221ff2d7731051f5f82ea5fe85 100644 (file)
@@ -1,22 +1,42 @@
 Freescale i.MX General Power Controller
 =======================================
 
-The i.MX6Q General Power Control (GPC) block contains DVFS load tracking
-counters and Power Gating Control (PGC) for the CPU and PU (GPU/VPU) power
-domains.
+The i.MX6 General Power Control (GPC) block contains DVFS load tracking
+counters and Power Gating Control (PGC).
 
 Required properties:
-- compatible: Should be "fsl,imx6q-gpc" or "fsl,imx6sl-gpc"
+- compatible: Should be one of the following:
+  - fsl,imx6q-gpc
+  - fsl,imx6qp-gpc
+  - fsl,imx6sl-gpc
 - reg: should be register base and length as documented in the
   datasheet
-- interrupts: Should contain GPC interrupt request 1
-- pu-supply: Link to the LDO regulator powering the PU power domain
-- clocks: Clock phandles to devices in the PU power domain that need
-         to be enabled during domain power-up for reset propagation.
-- #power-domain-cells: Should be 1, see below:
+- interrupts: Should contain one interrupt specifier for the GPC interrupt
+- clocks: Must contain an entry for each entry in clock-names.
+  See Documentation/devicetree/bindings/clocks/clock-bindings.txt for details.
+- clock-names: Must include the following entries:
+  - ipg
 
-The gpc node is a power-controller as documented by the generic power domain
-bindings in Documentation/devicetree/bindings/power/power_domain.txt.
+The power domains are generic power domain providers as documented in
+Documentation/devicetree/bindings/power/power_domain.txt. They are described as
+subnodes of the power gating controller 'pgc' node of the GPC and should
+contain the following:
+
+Required properties:
+- reg: Must contain the DOMAIN_INDEX of this power domain
+  The following DOMAIN_INDEX values are valid for i.MX6Q:
+  ARM_DOMAIN     0
+  PU_DOMAIN      1
+  The following additional DOMAIN_INDEX value is valid for i.MX6SL:
+  DISPLAY_DOMAIN 2
+
+- #power-domain-cells: Should be 0
+
+Optional properties:
+- clocks: a number of phandles to clocks that need to be enabled during domain
+  power-up sequencing to ensure reset propagation into devices located inside
+  this power domain
+- power-supply: a phandle to the regulator powering this domain
 
 Example:
 
@@ -25,14 +45,30 @@ Example:
                reg = <0x020dc000 0x4000>;
                interrupts = <0 89 IRQ_TYPE_LEVEL_HIGH>,
                             <0 90 IRQ_TYPE_LEVEL_HIGH>;
-               pu-supply = <&reg_pu>;
-               clocks = <&clks IMX6QDL_CLK_GPU3D_CORE>,
-                        <&clks IMX6QDL_CLK_GPU3D_SHADER>,
-                        <&clks IMX6QDL_CLK_GPU2D_CORE>,
-                        <&clks IMX6QDL_CLK_GPU2D_AXI>,
-                        <&clks IMX6QDL_CLK_OPENVG_AXI>,
-                        <&clks IMX6QDL_CLK_VPU_AXI>;
-               #power-domain-cells = <1>;
+               clocks = <&clks IMX6QDL_CLK_IPG>;
+               clock-names = "ipg";
+
+               pgc {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       power-domain@0 {
+                               reg = <0>;
+                               #power-domain-cells = <0>;
+                       };
+
+                       pd_pu: power-domain@1 {
+                               reg = <1>;
+                               #power-domain-cells = <0>;
+                               power-supply = <&reg_pu>;
+                               clocks = <&clks IMX6QDL_CLK_GPU3D_CORE>,
+                                        <&clks IMX6QDL_CLK_GPU3D_SHADER>,
+                                        <&clks IMX6QDL_CLK_GPU2D_CORE>,
+                                        <&clks IMX6QDL_CLK_GPU2D_AXI>,
+                                        <&clks IMX6QDL_CLK_OPENVG_AXI>,
+                                        <&clks IMX6QDL_CLK_VPU_AXI>;
+                       };
+               };
        };
 
 
@@ -40,20 +76,13 @@ Specifying power domain for IP modules
 ======================================
 
 IP cores belonging to a power domain should contain a 'power-domains' property
-that is a phandle pointing to the gpc device node and a DOMAIN_INDEX specifying
-the power domain the device belongs to.
+that is a phandle pointing to the power domain the device belongs to.
 
 Example of a device that is part of the PU power domain:
 
        vpu: vpu@02040000 {
                reg = <0x02040000 0x3c000>;
                /* ... */
-               power-domains = <&gpc 1>;
+               power-domains = <&pd_pu>;
                /* ... */
        };
-
-The following DOMAIN_INDEX values are valid for i.MX6Q:
-ARM_DOMAIN     0
-PU_DOMAIN      1
-The following additional DOMAIN_INDEX value is valid for i.MX6SL:
-DISPLAY_DOMAIN 2
diff --git a/Documentation/devicetree/bindings/power/fsl,imx-gpcv2.txt b/Documentation/devicetree/bindings/power/fsl,imx-gpcv2.txt
new file mode 100644 (file)
index 0000000..02f45c6
--- /dev/null
@@ -0,0 +1,71 @@
+Freescale i.MX General Power Controller v2
+==========================================
+
+The i.MX7S/D General Power Control (GPC) block contains Power Gating
+Control (PGC) for various power domains.
+
+Required properties:
+
+- compatible: Should be "fsl,imx7d-gpc"
+
+- reg: should be register base and length as documented in the
+  datasheet
+
+- interrupts: Should contain GPC interrupt request 1
+
+Power domains contained within GPC node are generic power domain
+providers, documented in
+Documentation/devicetree/bindings/power/power_domain.txt, which are
+described as subnodes of the power gating controller 'pgc' node,
+which, in turn, is expected to contain the following:
+
+Required properties:
+
+- reg: Power domain index. Valid values are defined in
+  include/dt-bindings/power/imx7-power.h
+
+- #power-domain-cells: Should be 0
+
+Optional properties:
+
+- power-supply: Power supply used to power the domain
+
+Example:
+
+       gpc: gpc@303a0000 {
+               compatible = "fsl,imx7d-gpc";
+               reg = <0x303a0000 0x1000>;
+               interrupt-controller;
+               interrupts = <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
+               #interrupt-cells = <3>;
+               interrupt-parent = <&intc>;
+
+               pgc {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       pgc_pcie_phy: power-domain@3 {
+                               #power-domain-cells = <0>;
+
+                               reg = <IMX7_POWER_DOMAIN_PCIE_PHY>;
+                               power-supply = <&reg_1p0d>;
+                       };
+               };
+       };
+
+
+Specifying power domain for IP modules
+======================================
+
+IP cores belonging to a power domain should contain a 'power-domains'
+property that is a phandle for PGC node representing the domain.
+
+Example of a device that is part of the PCIE_PHY power domain:
+
+       pcie: pcie@33800000 {
+             reg = <0x33800000 0x4000>,
+                   <0x4ff00000 0x80000>;
+               /* ... */
+               power-domains = <&pgc_pcie_phy>;
+               /* ... */
+       };
index 940707d095ccc8459ebe376f5ee5c2b8761f7f8e..14bd9e945ff6453f3290d628b083a13e645e9967 100644 (file)
@@ -81,7 +81,7 @@ Example 3:
        child: power-controller@12341000 {
                compatible = "foo,power-controller";
                reg = <0x12341000 0x1000>;
-               power-domains = <&parent 0>;
+               power-domains = <&parent>;
                #power-domain-cells = <0>;
                domain-idle-states = <&DOMAIN_PWR_DN>;
        };
diff --git a/Documentation/devicetree/bindings/power/supply/axp20x_battery.txt b/Documentation/devicetree/bindings/power/supply/axp20x_battery.txt
new file mode 100644 (file)
index 0000000..c248866
--- /dev/null
@@ -0,0 +1,20 @@
+AXP20x and AXP22x battery power supply
+
+Required Properties:
+ - compatible, one of:
+                       "x-powers,axp209-battery-power-supply"
+                       "x-powers,axp221-battery-power-supply"
+
+This node is a subnode of the axp20x/axp22x PMIC.
+
+The AXP20X and AXP22X can read the battery voltage, charge and discharge
+currents of the battery by reading ADC channels from the AXP20X/AXP22X
+ADC.
+
+Example:
+
+&axp209 {
+       battery_power_supply: battery-power-supply {
+               compatible = "x-powers,axp209-battery-power-supply";
+       }
+};
diff --git a/Documentation/devicetree/bindings/powerpc/ibm,powerpc-cpu-features.txt b/Documentation/devicetree/bindings/powerpc/ibm,powerpc-cpu-features.txt
new file mode 100644 (file)
index 0000000..5af426e
--- /dev/null
@@ -0,0 +1,248 @@
+*** NOTE ***
+This document is copied from OPAL firmware
+(skiboot/doc/device-tree/ibm,powerpc-cpu-features/binding.txt)
+
+There is more complete overview and documentation of features in that
+source tree.  All patches and modifications should go there.
+************
+
+ibm,powerpc-cpu-features binding
+================================
+
+This device tree binding describes CPU features available to software, with
+enablement, privilege, and compatibility metadata.
+
+More general description of design and implementation of this binding is
+found in design.txt, which also points to documentation of specific features.
+
+
+/cpus/ibm,powerpc-cpu-features node binding
+-------------------------------------------
+
+Node: ibm,powerpc-cpu-features
+
+Description: Container of CPU feature nodes.
+
+The node name must be "ibm,powerpc-cpu-features".
+
+It is implemented as a child of the node "/cpus", but this must not be
+assumed by parsers.
+
+The node is optional but should be provided by new OPAL firmware.
+
+Properties:
+
+- compatible
+  Usage: required
+  Value type: string
+  Definition: "ibm,powerpc-cpu-features"
+
+  This compatibility refers to backwards compatibility of the overall
+  design with parsers that behave according to these guidelines. This can
+  be extended in a backward compatible manner which would not warrant a
+  revision of the compatible property.
+
+- isa
+  Usage: required
+  Value type: <u32>
+  Definition:
+
+  isa that the CPU is currently running in. This provides instruction set
+  compatibility, less the individual feature nodes. For example, an ISA v3.0
+  implementation that lacks the "transactional-memory" cpufeature node
+  should not use transactional memory facilities.
+
+  Value corresponds to the "Power ISA Version" multiplied by 1000.
+  For example, <3000> corresponds to Version 3.0, <2070> to Version 2.07.
+  The minor digit is available for revisions.
+
+- display-name
+  Usage: optional
+  Value type: string
+  Definition:
+
+  A human readable name for the CPU.
+
+/cpus/ibm,powerpc-cpu-features/example-feature node bindings
+----------------------------------------------------------------
+
+Each child node of cpu-features represents a CPU feature / capability.
+
+Node: A string describing an architected CPU feature, e.g., "floating-point".
+
+Description: A feature or capability supported by the CPUs.
+
+The name of the node is a human readable string that forms the interface
+used to describe features to software. Features are currently documented
+in the code where they are implemented in skiboot/core/cpufeatures.c
+
+Presence of the node indicates the feature is available.
+
+Properties:
+
+- isa
+  Usage: required
+  Value type: <u32>
+  Definition:
+
+  First level of the Power ISA that the feature appears in.
+  Software should filter out features when constraining the
+  environment to a particular ISA version.
+
+  Value is defined similarly to /cpus/features/isa
+
+- usable-privilege
+  Usage: required
+  Value type: <u32> bit mask
+  Definition:
+              Bit numbers are LSB0
+              bit 0 - PR (problem state / user mode)
+              bit 1 - OS (privileged state)
+              bit 2 - HV (hypervisor state)
+              All other bits reserved and should be zero.
+
+  This property describes the privilege levels and/or software components
+  that can use the feature.
+
+  If bit 0 is set, then the hwcap-bit-nr property will exist.
+
+
+- hv-support
+  Usage: optional
+  Value type: <u32> bit mask
+  Definition:
+              Bit numbers are LSB0
+              bit 0 -  HFSCR
+              All other bits reserved and should be zero.
+
+  This property describes the HV privilege support required to enable the
+  feature to lesser privilege levels. If the property does not exist then no
+  support is required.
+
+  If no bits are set, the hypervisor must have explicit/custom support for
+  this feature.
+
+  If the HFSCR bit is set, then the hfscr-bit-nr property will exist and
+  the feature may be enabled by setting this bit in the HFSCR register.
+
+
+- os-support
+  Usage: optional
+  Value type: <u32> bit mask
+  Definition:
+              Bit numbers are LSB0
+              bit 0 -  FSCR
+              All other bits reserved and should be zero.
+
+  This property describes the OS privilege support required to enable the
+  feature to lesser privilege levels. If the property does not exist then no
+  support is required.
+
+  If no bits are set, the operating system must have explicit/custom support
+  for this feature.
+
+  If the FSCR bit is set, then the fscr-bit-nr property will exist and
+  the feature may be enabled by setting this bit in the FSCR register.
+
+
+- hfscr-bit-nr
+  Usage: optional
+  Value type: <u32>
+  Definition: HFSCR bit position (LSB0)
+
+  This property exists when the hv-support property HFSCR bit is set. This
+  property describes the bit number in the HFSCR register that the
+  hypervisor must set in order to enable this feature.
+
+  This property also exists if an HFSCR bit corresponds with this feature.
+  This makes CPU feature parsing slightly simpler.
+
+
+- fscr-bit-nr
+  Usage: optional
+  Value type: <u32>
+  Definition: FSCR bit position (LSB0)
+
+  This property exists when the os-support property FSCR bit is set. This
+  property describes the bit number in the FSCR register that the
+  operating system must set in order to enable this feature.
+
+  This property also exists if an FSCR bit corresponds with this feature.
+  This makes CPU feature parsing slightly simpler.
+
+
+- hwcap-bit-nr
+  Usage: optional
+  Value type: <u32>
+  Definition: Linux ELF AUX vector bit position (LSB0)
+
+  This property may exist when the usable-privilege property value has PR bit set.
+  This property describes the bit number that should be set in the ELF AUX
+  hardware capability vectors in order to advertise this feature to userspace.
+  Bits 0-31 correspond to bits 0-31 in AT_HWCAP vector. Bits 32-63 correspond
+  to 0-31 in AT_HWCAP2 vector, and so on.  Missing AT_HWCAPx vectors implies
+  that the feature is not enabled or can not be advertised. Operating systems
+  may provide a number of unassigned hardware capability bits to allow for new
+  features to be advertised.
+
+  Some properties representing features created before this binding are
+  advertised to userspace without a one-to-one hwcap bit number may not specify
+  this bit. Operating system will handle those bits specifically.  All new
+  features usable by userspace will have a hwcap-bit-nr property.
+
+
+- dependencies
+  Usage: optional
+  Value type: <prop-encoded-array>
+  Definition:
+
+  If this property exists then it is a list of phandles to cpu feature
+  nodes that must be enabled for this feature to be enabled.
+
+
+Example
+-------
+
+       /cpus/ibm,powerpc-cpu-features {
+               compatible = "ibm,powerpc-cpu-features";
+
+               isa = <3020>;
+
+               darn {
+                       isa = <3000>;
+                       usable-privilege = <1 | 2 | 4>;
+                       hwcap-bit-nr = <xx>;
+               };
+
+               scv {
+                       isa = <3000>;
+                       usable-privilege = <1 | 2>;
+                       os-support = <0>;
+                       hwcap-bit-nr = <xx>;
+               };
+
+               stop {
+                       isa = <3000>;
+                       usable-privilege = <2 | 4>;
+                       hv-support = <0>;
+                       os-support = <0>;
+               };
+
+               vsx2 (hypothetical) {
+                       isa = <3010>;
+                       usable-privilege = <1 | 2 | 4>;
+                       hv-support = <0>;
+                       os-support = <0>;
+                       hwcap-bit-nr = <xx>;
+               };
+
+               vsx2-newinsns {
+                       isa = <3020>;
+                       usable-privilege = <1 | 2 | 4>;
+                       os-support = <1>;
+                       fscr-bit-nr = <xx>;
+                       hwcap-bit-nr = <xx>;
+                       dependencies = <&vsx2>;
+               };
+
+       };
index 02331b904d4e73780da1999f807068915545ebb9..c8c831d7b0d1bb9d90cfc9b3022b57b9e6a2f74d 100644 (file)
@@ -4,6 +4,7 @@ Required properties:
   - compatible: should be one of:
     - "atmel,at91sam9rl-pwm"
     - "atmel,sama5d3-pwm"
+    - "atmel,sama5d2-pwm"
   - reg: physical base address and length of the controller's registers
   - #pwm-cells: Should be 3. See pwm.txt in this directory for a
     description of the cells format.
index b4e73778dda3a2e211ec210869d4d78807066122..c57e11b8d9375b85b882407a3477f7ff2ac58553 100644 (file)
@@ -19,6 +19,19 @@ Required properties:
 - reset-names: Must include the following entries:
   - pwm
 
+Optional properties:
+============================
+In some of the interface like PWM based regulator device, it is required
+to configure the pins differently in different states, especially in suspend
+state of the system. The configuration of pin is provided via the pinctrl
+DT node as detailed in the pinctrl DT binding document
+       Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt
+
+The PWM node will have following optional properties.
+pinctrl-names: Pin state names. Must be "default" and "sleep".
+pinctrl-0:     phandle for the default/active state of pin configurations.
+pinctrl-1:     phandle for the sleep state of pin configurations.
+
 Example:
 
        pwm: pwm@7000a000 {
@@ -29,3 +42,35 @@ Example:
                resets = <&tegra_car 17>;
                reset-names = "pwm";
        };
+
+
+Example with the pin configuration for suspend and resume:
+=========================================================
+Suppose pin PE7 (On Tegra210) interfaced with the regulator device and
+it requires PWM output to be tristated when system enters suspend.
+Following will be DT binding to achieve this:
+
+#include <dt-bindings/pinctrl/pinctrl-tegra.h>
+
+       pinmux@700008d4 {
+               pwm_active_state: pwm_active_state {
+                        pe7 {
+                                nvidia,pins = "pe7";
+                                nvidia,tristate = <TEGRA_PIN_DISABLE>;
+                       };
+               };
+
+               pwm_sleep_state: pwm_sleep_state {
+                        pe7 {
+                                nvidia,pins = "pe7";
+                                nvidia,tristate = <TEGRA_PIN_ENABLE>;
+                       };
+               };
+       };
+
+       pwm@7000a000 {
+               /* Mandatory PWM properties */
+               pinctrl-names = "default", "sleep";
+               pinctrl-0 = <&pwm_active_state>;
+               pinctrl-1 = <&pwm_sleep_state>;
+       };
diff --git a/Documentation/devicetree/bindings/pwm/pwm-mediatek.txt b/Documentation/devicetree/bindings/pwm/pwm-mediatek.txt
new file mode 100644 (file)
index 0000000..54c59b0
--- /dev/null
@@ -0,0 +1,34 @@
+MediaTek PWM controller
+
+Required properties:
+ - compatible: should be "mediatek,<name>-pwm":
+   - "mediatek,mt7623-pwm": found on mt7623 SoC.
+ - reg: physical base address and length of the controller's registers.
+ - #pwm-cells: must be 2. See pwm.txt in this directory for a description of
+   the cell format.
+ - clocks: phandle and clock specifier of the PWM reference clock.
+ - clock-names: must contain the following:
+   - "top": the top clock generator
+   - "main": clock used by the PWM core
+   - "pwm1-5": the five per PWM clocks
+ - pinctrl-names: Must contain a "default" entry.
+ - pinctrl-0: One property must exist for each entry in pinctrl-names.
+   See pinctrl/pinctrl-bindings.txt for details of the property values.
+
+Example:
+       pwm0: pwm@11006000 {
+               compatible = "mediatek,mt7623-pwm";
+               reg = <0 0x11006000 0 0x1000>;
+               #pwm-cells = <2>;
+               clocks = <&topckgen CLK_TOP_PWM_SEL>,
+                        <&pericfg CLK_PERI_PWM>,
+                        <&pericfg CLK_PERI_PWM1>,
+                        <&pericfg CLK_PERI_PWM2>,
+                        <&pericfg CLK_PERI_PWM3>,
+                        <&pericfg CLK_PERI_PWM4>,
+                        <&pericfg CLK_PERI_PWM5>;
+               clock-names = "top", "main", "pwm1", "pwm2",
+                             "pwm3", "pwm4", "pwm5";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pwm0_pins>;
+       };
diff --git a/Documentation/devicetree/bindings/reset/fsl,imx7-src.txt b/Documentation/devicetree/bindings/reset/fsl,imx7-src.txt
new file mode 100644 (file)
index 0000000..5e1afc3
--- /dev/null
@@ -0,0 +1,47 @@
+Freescale i.MX7 System Reset Controller
+======================================
+
+Please also refer to reset.txt in this directory for common reset
+controller binding usage.
+
+Required properties:
+- compatible: Should be "fsl,imx7-src", "syscon"
+- reg: should be register base and length as documented in the
+  datasheet
+- interrupts: Should contain SRC interrupt
+- #reset-cells: 1, see below
+
+example:
+
+src: reset-controller@30390000 {
+     compatible = "fsl,imx7d-src", "syscon";
+     reg = <0x30390000 0x2000>;
+     interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
+     #reset-cells = <1>;
+};
+
+
+Specifying reset lines connected to IP modules
+==============================================
+
+The system reset controller can be used to reset various set of
+peripherals. Device nodes that need access to reset lines should
+specify them as a reset phandle in their corresponding node as
+specified in reset.txt.
+
+Example:
+
+       pcie: pcie@33800000 {
+
+               ...
+
+               resets = <&src IMX7_RESET_PCIEPHY>,
+                        <&src IMX7_RESET_PCIE_CTRL_APPS_EN>;
+               reset-names = "pciephy", "apps";
+
+               ...
+        };
+
+
+For list of all valid reset indicies see
+<dt-bindings/reset/imx7-reset.h>
diff --git a/Documentation/devicetree/bindings/rtc/cpcap-rtc.txt b/Documentation/devicetree/bindings/rtc/cpcap-rtc.txt
new file mode 100644 (file)
index 0000000..45750ff
--- /dev/null
@@ -0,0 +1,18 @@
+Motorola CPCAP PMIC RTC
+-----------------------
+
+This module is part of the CPCAP. For more details about the whole
+chip see Documentation/devicetree/bindings/mfd/motorola-cpcap.txt.
+
+Requires node properties:
+- compatible: should contain "motorola,cpcap-rtc"
+- interrupts: An interrupt specifier for alarm and 1 Hz irq
+
+Example:
+
+&cpcap {
+       cpcap_rtc: rtc {
+               compatible = "motorola,cpcap-rtc";
+               interrupts = <39 IRQ_TYPE_NONE>, <26 IRQ_TYPE_NONE>;
+       };
+};
diff --git a/Documentation/devicetree/bindings/rtc/rtc-sh.txt b/Documentation/devicetree/bindings/rtc/rtc-sh.txt
new file mode 100644 (file)
index 0000000..7676c7d
--- /dev/null
@@ -0,0 +1,28 @@
+* Real Time Clock for Renesas SH and ARM SoCs
+
+Required properties:
+- compatible: Should be "renesas,r7s72100-rtc" and "renesas,sh-rtc" as a
+  fallback.
+- reg: physical base address and length of memory mapped region.
+- interrupts: 3 interrupts for alarm, period, and carry.
+- interrupt-names: The interrupts should be labeled as "alarm", "period", and
+  "carry".
+- clocks: The functional clock source for the RTC controller must be listed
+  first (if exists). Additionally, potential clock counting sources are to be
+  listed.
+- clock-names: The functional clock must be labeled as "fck". Other clocks
+  may be named in accordance to the SoC hardware manuals.
+
+
+Example:
+rtc: rtc@fcff1000 {
+       compatible = "renesas,r7s72100-rtc", "renesas,sh-rtc";
+       reg = <0xfcff1000 0x2e>;
+       interrupts = <GIC_SPI 276 IRQ_TYPE_EDGE_RISING
+                     GIC_SPI 277 IRQ_TYPE_EDGE_RISING
+                     GIC_SPI 278 IRQ_TYPE_EDGE_RISING>;
+       interrupt-names = "alarm", "period", "carry";
+       clocks = <&mstp6_clks R7S72100_CLK_RTC>, <&rtc_x1_clk>,
+                <&rtc_x3_clk>, <&extal_clk>;
+       clock-names = "fck", "rtc_x1", "rtc_x3", "extal";
+};
index 2aff0f22c9fa31837b9f49cd6d4213d14186f9e4..cab40f0f6f497ab7bc0b3ab9640bcc0563a8cddb 100644 (file)
@@ -1,7 +1,19 @@
 * Spreadtrum serial UART
 
 Required properties:
-- compatible: must be "sprd,sc9836-uart"
+- compatible: must be one of:
+  * "sprd,sc9836-uart"
+  * "sprd,sc9860-uart", "sprd,sc9836-uart"
+
 - reg: offset and length of the register set for the device
 - interrupts: exactly one interrupt specifier
 - clocks: phandles to input clocks.
+
+Example:
+       uart0: serial@0 {
+               compatible = "sprd,sc9860-uart",
+                            "sprd,sc9836-uart";
+               reg = <0x0 0x100>;
+               interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&ext_26m>;
+       };
index 349f79fd7076a63b3ad373e0d473f7e00f484c14..626e1afa64a6eb729f89e311ec67716167b45408 100644 (file)
@@ -13,8 +13,17 @@ Required properties:
 - #gpio-cells : Should be two. The first cell is the pin number and the
   second cell is used to specify optional parameters (currently unused).
 - gpio-controller : Marks the port as GPIO controller.
+Optional properties:
+- fsl,cpm1-gpio-irq-mask : For banks having interrupt capability (like port C
+  on CPM1), this item tells which ports have an associated interrupt (ports are
+  listed in the same order as in PCINT register)
+- interrupts : This property provides the list of interrupt for each GPIO having
+  one as described by the fsl,cpm1-gpio-irq-mask property. There should be as
+  many interrupts as number of ones in the mask property. The first interrupt in
+  the list corresponds to the most significant bit of the mask.
+- interrupt-parent : Parent for the above interrupt property.
 
-Example of three SOC GPIO banks defined as gpio-controller nodes:
+Example of four SOC GPIO banks defined as gpio-controller nodes:
 
        CPM1_PIO_A: gpio-controller@950 {
                #gpio-cells = <2>;
@@ -30,6 +39,16 @@ Example of three SOC GPIO banks defined as gpio-controller nodes:
                gpio-controller;
        };
 
+       CPM1_PIO_C: gpio-controller@960 {
+               #gpio-cells = <2>;
+               compatible = "fsl,cpm1-pario-bank-c";
+               reg = <0x960 0x10>;
+               fsl,cpm1-gpio-irq-mask = <0x0fff>;
+               interrupts = <1 2 6 9 10 11 14 15 23 24 26 31>;
+               interrupt-parent = <&CPM_PIC>;
+               gpio-controller;
+       };
+
        CPM1_PIO_E: gpio-controller@ac8 {
                #gpio-cells = <2>;
                compatible = "fsl,cpm1-pario-bank-e";
index 13ec0992de0f097184afb9dece9f2962dd16573b..cc9f05d3cbc1a0b08a2a278364332b8114b027a3 100644 (file)
@@ -18,6 +18,7 @@ Required Properties:
    - "rockchip,rk3188-grf", "syscon": for rk3188
    - "rockchip,rk3228-grf", "syscon": for rk3228
    - "rockchip,rk3288-grf", "syscon": for rk3288
+   - "rockchip,rk3328-grf", "syscon": for rk3328
    - "rockchip,rk3368-grf", "syscon": for rk3368
    - "rockchip,rk3399-grf", "syscon": for rk3399
 - compatible: PMUGRF should be one of the following:
diff --git a/Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt b/Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt
new file mode 100644 (file)
index 0000000..c705db0
--- /dev/null
@@ -0,0 +1,57 @@
+Texas Instruments TI-SCI Generic Power Domain
+---------------------------------------------
+
+Some TI SoCs contain a system controller (like the PMMC, etc...) that is
+responsible for controlling the state of the IPs that are present.
+Communication between the host processor running an OS and the system
+controller happens through a protocol known as TI-SCI [1].
+
+[1] Documentation/devicetree/bindings/arm/keystone/ti,sci.txt
+
+PM Domain Node
+==============
+The PM domain node represents the global PM domain managed by the PMMC, which
+in this case is the implementation as documented by the generic PM domain
+bindings in Documentation/devicetree/bindings/power/power_domain.txt.  Because
+this relies on the TI SCI protocol to communicate with the PMMC it must be a
+child of the pmmc node.
+
+Required Properties:
+--------------------
+- compatible: should be "ti,sci-pm-domain"
+- #power-domain-cells: Must be 1 so that an id can be provided in each
+                      device node.
+
+Example (K2G):
+-------------
+       pmmc: pmmc {
+               compatible = "ti,k2g-sci";
+               ...
+
+               k2g_pds: power-controller {
+                       compatible = "ti,sci-pm-domain";
+                       #power-domain-cells = <1>;
+               };
+       };
+
+PM Domain Consumers
+===================
+Hardware blocks belonging to a PM domain should contain a "power-domains"
+property that is a phandle pointing to the corresponding PM domain node
+along with an index representing the device id to be passed to the PMMC
+for device control.
+
+Required Properties:
+--------------------
+- power-domains: phandle pointing to the corresponding PM domain node
+                and an ID representing the device.
+
+See dt-bindings/genpd/k2g.h for the list of valid identifiers for k2g.
+
+Example (K2G):
+--------------------
+       uart0: serial@02530c00 {
+               compatible = "ns16550a";
+               ...
+               power-domains = <&k2g_pds K2G_DEV_UART0>;
+       };
index 474531d2b2c5fc746d625a5725e9a09f3ec19b8a..da8c5b73ad105a5fa5bf1510f5ec1f2d1ab462f9 100644 (file)
@@ -3,15 +3,39 @@ Binding for Thermal Sensor driver for BCM2835 SoCs.
 Required parameters:
 -------------------
 
-compatible:    should be one of: "brcm,bcm2835-thermal",
-               "brcm,bcm2836-thermal" or "brcm,bcm2837-thermal"
-reg:           Address range of the thermal registers.
-clocks:        Phandle of the clock used by the thermal sensor.
+compatible:            should be one of: "brcm,bcm2835-thermal",
+                       "brcm,bcm2836-thermal" or "brcm,bcm2837-thermal"
+reg:                   Address range of the thermal registers.
+clocks:                Phandle of the clock used by the thermal sensor.
+#thermal-sensor-cells: should be 0 (see thermal.txt)
 
 Example:
 
+thermal-zones {
+       cpu_thermal: cpu-thermal {
+               polling-delay-passive = <0>;
+               polling-delay = <1000>;
+
+               thermal-sensors = <&thermal>;
+
+               trips {
+                       cpu-crit {
+                               temperature     = <80000>;
+                               hysteresis      = <0>;
+                               type            = "critical";
+                       };
+               };
+
+               coefficients = <(-538)  407000>;
+
+               cooling-maps {
+               };
+       };
+};
+
 thermal: thermal@7e212000 {
        compatible = "brcm,bcm2835-thermal";
        reg = <0x7e212000 0x8>;
        clocks = <&clocks BCM2835_CLOCK_TSENS>;
+       #thermal-sensor-cells = <0>;
 };
diff --git a/Documentation/devicetree/bindings/thermal/brcm,ns-thermal b/Documentation/devicetree/bindings/thermal/brcm,ns-thermal
new file mode 100644 (file)
index 0000000..68e0471
--- /dev/null
@@ -0,0 +1,37 @@
+* Broadcom Northstar Thermal
+
+This binding describes thermal sensor that is part of Northstar's DMU (Device
+Management Unit).
+
+Required properties:
+- compatible : Must be "brcm,ns-thermal"
+- reg : iomem address range of PVTMON registers
+- #thermal-sensor-cells : Should be <0>
+
+Example:
+
+thermal: thermal@1800c2c0 {
+       compatible = "brcm,ns-thermal";
+       reg = <0x1800c2c0 0x10>;
+       #thermal-sensor-cells = <0>;
+};
+
+thermal-zones {
+       cpu_thermal: cpu-thermal {
+               polling-delay-passive = <0>;
+               polling-delay = <1000>;
+               coefficients = <(-556) 418000>;
+               thermal-sensors = <&thermal>;
+
+               trips {
+                       cpu-crit {
+                               temperature     = <125000>;
+                               hysteresis      = <0>;
+                               type            = "critical";
+                       };
+               };
+
+               cooling-maps {
+               };
+       };
+};
diff --git a/Documentation/devicetree/bindings/thermal/da9062-thermal.txt b/Documentation/devicetree/bindings/thermal/da9062-thermal.txt
new file mode 100644 (file)
index 0000000..e241bb5
--- /dev/null
@@ -0,0 +1,36 @@
+* Dialog DA9062/61 TJUNC Thermal Module
+
+This module is part of the DA9061/DA9062. For more details about entire
+DA9062 and DA9061 chips see Documentation/devicetree/bindings/mfd/da9062.txt
+
+Junction temperature thermal module uses an interrupt signal to identify
+high THERMAL_TRIP_HOT temperatures for the PMIC device.
+
+Required properties:
+
+- compatible: should be one of the following valid compatible string lines:
+        "dlg,da9061-thermal", "dlg,da9062-thermal"
+        "dlg,da9062-thermal"
+
+Optional properties:
+
+- polling-delay-passive : Specify the polling period, measured in
+    milliseconds, between thermal zone device update checks.
+
+Example: DA9062
+
+       pmic0: da9062@58 {
+               thermal {
+                       compatible = "dlg,da9062-thermal";
+                       polling-delay-passive = <3000>;
+               };
+       };
+
+Example: DA9061 using a fall-back compatible for the DA9062 onkey driver
+
+       pmic0: da9061@58 {
+               thermal {
+                       compatible = "dlg,da9061-thermal", "dlg,da9062-thermal";
+                       polling-delay-passive = <3000>;
+               };
+       };
index ad10fbe61562506015c93e3e6fe52dba751665a3..3e0a34c88e07759bdd076e98d43a4c988e1de4cc 100644 (file)
@@ -160,6 +160,7 @@ sii,s35390a         2-wire CMOS real-time clock
 silabs,si7020          Relative Humidity and Temperature Sensors
 skyworks,sky81452      Skyworks SKY81452: Six-Channel White LED Driver with Touch Panel Bias Supply
 st,24c256              i2c serial eeprom  (24cxx)
+st,m41t0               Serial real-time clock (RTC)
 st,m41t00              Serial real-time clock (RTC)
 st,m41t62              Serial real-time clock (RTC) with alarm
 st,m41t80              M41T80 - SERIAL ACCESS RTC WITH ALARMS
index ccb844aba7d4b4d241affaba6d216c4494e0971c..717c5f6562373decc6eb91e7963d445b59739f59 100644 (file)
@@ -18,10 +18,26 @@ Required properties:
 
  - phy-names: Should be "usb-phy"
 
+ - dmas: specifies the dma channels
+
+ - dma-names: specifies the names of the channels. Use "rxN" for receive
+   and "txN" for transmit endpoints. N specifies the endpoint number.
+
 Optional properties:
 ~~~~~~~~~~~~~~~~~~~~
  - vbus-supply: Phandle to a regulator providing the USB bus power.
 
+DMA
+~~~
+- compatible: ti,da830-cppi41
+- reg: offset and length of the following register spaces: CPPI DMA Controller,
+  CPPI DMA Scheduler, Queue Manager
+- reg-names: "controller", "scheduler", "queuemgr"
+- #dma-cells: should be set to 2. The first number represents the
+  channel number (0 … 3 for endpoints 1 … 4).
+  The second number is 0 for RX and 1 for TX transfers.
+- #dma-channels: should be set to 4 representing the 4 endpoints.
+
 Example:
        usb_phy: usb-phy {
                compatible = "ti,da830-usb-phy";
@@ -30,7 +46,10 @@ Example:
        };
        usb0: usb@200000 {
                compatible = "ti,da830-musb";
-               reg =   <0x00200000 0x10000>;
+               reg = <0x00200000 0x1000>;
+               ranges;
+               #address-cells = <1>;
+               #size-cells = <1>;
                interrupts = <58>;
                interrupt-names = "mc";
 
@@ -39,5 +58,25 @@ Example:
                phys = <&usb_phy 0>;
                phy-names = "usb-phy";
 
+               dmas = <&cppi41dma 0 0 &cppi41dma 1 0
+                       &cppi41dma 2 0 &cppi41dma 3 0
+                       &cppi41dma 0 1 &cppi41dma 1 1
+                       &cppi41dma 2 1 &cppi41dma 3 1>;
+               dma-names =
+                       "rx1", "rx2", "rx3", "rx4",
+                       "tx1", "tx2", "tx3", "tx4";
+
                status = "okay";
+
+               cppi41dma: dma-controller@201000 {
+                       compatible = "ti,da830-cppi41";
+                       reg =  <0x201000 0x1000
+                               0x202000 0x1000
+                               0x204000 0x4000>;
+                       reg-names = "controller", "scheduler", "queuemgr";
+                       interrupts = <58>;
+                       #dma-cells = <2>;
+                       #dma-channels = <4>;
+               };
+
        };
index 6c7c2bce6d0c3c2b59c8726da4a40a9a1a4a345d..00bea038639e4ea341735c875040ea55a12e8be3 100644 (file)
@@ -14,6 +14,10 @@ Required properties:
   - "amlogic,meson-gxbb-usb": The DWC2 USB controller instance in Amlogic S905 SoCs;
   - "amcc,dwc-otg": The DWC2 USB controller instance in AMCC Canyonlands 460EX SoCs;
   - snps,dwc2: A generic DWC2 USB controller with default parameters.
+  - "st,stm32f4x9-fsotg": The DWC2 USB FS/HS controller instance in STM32F4x9 SoCs
+  configured in FS mode;
+  - "st,stm32f4x9-hsotg": The DWC2 USB HS controller instance in STM32F4x9 SoCs
+  configured in HS mode;
 - reg : Should contain 1 register range (address and length)
 - interrupts : Should contain 1 interrupt
 - clocks: clock provider specifier
index ee558477e1642503f2fa194e0b5ca81345130d41..c03d201403661926164f1f9ba45ecd381a77b544 100644 (file)
@@ -139,6 +139,7 @@ holt        Holt Integrated Circuits, Inc.
 honeywell      Honeywell
 hp     Hewlett Packard
 holtek Holtek Semiconductor, Inc.
+hwacom HwaCom Systems Inc.
 i2se   I2SE GmbH
 ibm    International Business Machines (IBM)
 idt    Integrated Device Technologies, Inc.
@@ -162,6 +163,7 @@ jedec       JEDEC Solid State Technology Association
 karo   Ka-Ro electronics GmbH
 keithkoep      Keith & Koep GmbH
 keymile        Keymile GmbH
+khadas Khadas
 kinetic Kinetic Technologies
 kosagi Sutajio Ko-Usagi PTE Ltd.
 kyo    Kyocera Corporation
@@ -171,6 +173,7 @@ lego        LEGO Systems A/S
 lenovo Lenovo Group Ltd.
 lg     LG Corporation
 licheepi       Lichee Pi
+linaro Linaro Limited
 linux  Linux-specific binding
 lltc   Linear Technology Corporation
 lsi    LSI Corp. (LSI Logic)
@@ -194,6 +197,7 @@ minix       MINIX Technology Ltd.
 miramems       MiraMEMS Sensing Technology Co., Ltd.
 mitsubishi     Mitsubishi Electric Corporation
 mosaixtech     Mosaix Technologies, Inc.
+motorola       Motorola, Inc.
 moxa   Moxa
 mpl    MPL AG
 mqmaker        mqmaker Inc.
diff --git a/Documentation/devicetree/bindings/watchdog/cortina,gemini-watchdog.txt b/Documentation/devicetree/bindings/watchdog/cortina,gemini-watchdog.txt
new file mode 100644 (file)
index 0000000..bc4b865
--- /dev/null
@@ -0,0 +1,17 @@
+Cortina Systems Gemini SoC Watchdog
+
+Required properties:
+- compatible : must be "cortina,gemini-watchdog"
+- reg : shall contain base register location and length
+- interrupts : shall contain the interrupt for the watchdog
+
+Optional properties:
+- timeout-sec : the default watchdog timeout in seconds.
+
+Example:
+
+watchdog@41000000 {
+       compatible = "cortina,gemini-watchdog";
+       reg = <0x41000000 0x1000>;
+       interrupts = <3 IRQ_TYPE_LEVEL_HIGH>;
+};
index bf34d5b3a7330e5c26f9c6eebe977ed853804959..e72587fe477d5f1ad958e9810f1e5c46cbccc786 100644 (file)
@@ -342,8 +342,10 @@ PER-CPU MEM
   devm_free_percpu()
 
 PCI
-  pcim_enable_device() : after success, all PCI ops become managed
-  pcim_pin_device()    : keep PCI device enabled after release
+  devm_pci_remap_cfgspace()    : ioremap PCI configuration space
+  devm_pci_remap_cfg_resource()        : ioremap PCI configuration space resource
+  pcim_enable_device()         : after success, all PCI ops become managed
+  pcim_pin_device()            : keep PCI device enabled after release
 
 PHY
   devm_usb_get_phy()
index 78043d5a8fc35f01c343ced6f956aadee03e1026..843ce91a2e40504beaedf9c159c36d271700071b 100644 (file)
@@ -54,4 +54,4 @@ The first 4 bytes should be 0x1badface.
 If you have any patches, questions or suggestions regarding this BFS
 implementation please contact the author:
 
-Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
+Tigran Aivazian <aivazian.tigran@gmail.com>
index 8de578a98222784ebab5e930586a019dd6cd67aa..80dc0bdc302a6ae86db68657efddc7aba8fec498 100644 (file)
@@ -64,46 +64,9 @@ table which are called by the nfs-client pnfs-core to implement the
 different layout types.
 
 Files-layout-driver code is in: fs/nfs/filelayout/.. directory
-Objects-layout-driver code is in: fs/nfs/objlayout/.. directory
 Blocks-layout-driver code is in: fs/nfs/blocklayout/.. directory
 Flexfiles-layout-driver code is in: fs/nfs/flexfilelayout/.. directory
 
-objects-layout setup
---------------------
-
-As part of the full STD implementation the objlayoutdriver.ko needs, at times,
-to automatically login to yet undiscovered iscsi/osd devices. For this the
-driver makes up-calles to a user-mode script called *osd_login*
-
-The path_name of the script to use is by default:
-       /sbin/osd_login.
-This name can be overridden by the Kernel module parameter:
-       objlayoutdriver.osd_login_prog
-
-If Kernel does not find the osd_login_prog path it will zero it out
-and will not attempt farther logins. An admin can then write new value
-to the objlayoutdriver.osd_login_prog Kernel parameter to re-enable it.
-
-The /sbin/osd_login is part of the nfs-utils package, and should usually
-be installed on distributions that support this Kernel version.
-
-The API to the login script is as follows:
-       Usage: $0 -u <URI> -o <OSDNAME> -s <SYSTEMID>
-       Options:
-               -u              target uri e.g. iscsi://<ip>:<port>
-                               (always exists)
-                               (More protocols can be defined in the future.
-                                The client does not interpret this string it is
-                                passed unchanged as received from the Server)
-               -o              osdname of the requested target OSD
-                               (Might be empty)
-                               (A string which denotes the OSD name, there is a
-                                limit of 64 chars on this string)
-               -s              systemid of the requested target OSD
-                               (Might be empty)
-                               (This string, if not empty is always an hex
-                                representation of the 20 bytes osd_system_id)
-
 blocks-layout setup
 -------------------
 
index 634d03e20c2d9154c926b7db51061c69a6d32cd9..c9e884b52698020f88fdab12588687c10f16004e 100644 (file)
@@ -21,12 +21,19 @@ from accessing the corresponding object from the original filesystem.
 This is most obvious from the 'st_dev' field returned by stat(2).
 
 While directories will report an st_dev from the overlay-filesystem,
-all non-directory objects will report an st_dev from the lower or
+non-directory objects may report an st_dev from the lower filesystem or
 upper filesystem that is providing the object.  Similarly st_ino will
 only be unique when combined with st_dev, and both of these can change
 over the lifetime of a non-directory object.  Many applications and
 tools ignore these values and will not be affected.
 
+In the special case of all overlay layers on the same underlying
+filesystem, all objects will report an st_dev from the overlay
+filesystem and st_ino from the underlying filesystem.  This will
+make the overlay mount more compliant with filesystem scanners and
+overlay objects will be distinguishable from the corresponding
+objects in the original filesystem.
+
 Upper and Lower
 ---------------
 
index 6ea1ceda6f5235ea18458b7aa70f1fe51866fcf5..06f1d64c6f702fa2507b748b6feb5a6bddf20975 100644 (file)
@@ -113,9 +113,18 @@ Supporting PCI access on new platforms
 --------------------------------------
 
 In order to support PCI resource mapping as described above, Linux platform
-code must define HAVE_PCI_MMAP and provide a pci_mmap_page_range function.
-Platforms are free to only support subsets of the mmap functionality, but
-useful return codes should be provided.
+code should ideally define ARCH_GENERIC_PCI_MMAP_RESOURCE and use the generic
+implementation of that functionality. To support the historical interface of
+mmap() through files in /proc/bus/pci, platforms may also set HAVE_PCI_MMAP.
+
+Alternatively, platforms which set HAVE_PCI_MMAP may provide their own
+implementation of pci_mmap_page_range() instead of defining
+ARCH_GENERIC_PCI_MMAP_RESOURCE.
+
+Platforms which support write-combining maps of PCI resources must define
+arch_can_pci_mmap_wc() which shall evaluate to non-zero at runtime when
+write-combining is permitted. Platforms which support maps of I/O resources
+define arch_can_pci_mmap_io() similarly.
 
 Legacy resources are protected by the HAVE_PCI_LEGACY define.  Platforms
 wishing to support legacy functionality should define it and provide
index 94dd27ef4a766ca5414146fab1b76ea5aacb67de..f42b90687d406b73b4a24b2d92c9116540cc8ca1 100644 (file)
@@ -694,8 +694,7 @@ struct address_space_operations {
 
   write_end: After a successful write_begin, and data copy, write_end must
         be called. len is the original len passed to write_begin, and copied
-        is the amount that was able to be copied (copied == len is always true
-       if write_begin was called with the AOP_FLAG_UNINTERRUPTIBLE flag).
+        is the amount that was able to be copied.
 
         The filesystem must take care of unlocking the page and releasing it
         refcount, and updating i_size.
index 61306a22888d137b67982a062370f66c826860ea..bc67dbf76eb041c5dbd66813d873ce74420a0da5 100644 (file)
@@ -67,6 +67,7 @@ needed).
    driver-api/index
    core-api/index
    media/index
+   input/index
    gpu/index
    security/index
    sound/index
index 6a265a6934e68173a0ac79263d6edb60c450d1d7..26d461998e08974f1e47e54f33cfc630c0a9879d 100644 (file)
@@ -130,11 +130,11 @@ See <uapi/linux/input.h> for a description of the ff_effect struct.  You
 should also find help in a few sketches, contained in files shape.svg
 and interactive.svg:
 
-.. figure:: shape.svg
+.. kernel-figure:: shape.svg
 
     Shape
 
-.. figure:: interactive.svg
+.. kernel-figure:: interactive.svg
 
     Interactive
 
index a77ead911956be7f5902b9f53da0c526119aaaf1..1e9fcb4d0ec83ed4eaf2330f16775769ac366aa3 100644 (file)
@@ -191,6 +191,7 @@ Code  Seq#(hex)     Include File            Comments
 'W'    00-1F   linux/watchdog.h        conflict!
 'W'    00-1F   linux/wanrouter.h       conflict!               (pre 3.9)
 'W'    00-3F   sound/asound.h          conflict!
+'W'    40-5F   drivers/pci/switch/switchtec.c
 'X'    all     fs/xfs/xfs_fs.h         conflict!
                and fs/xfs/linux-2.6/xfs_ioctl32.h
                and include/linux/falloc.h
@@ -308,6 +309,7 @@ Code  Seq#(hex)     Include File            Comments
 0xA3   80-8F   Port ACL                in development:
                                        <mailto:tlewis@mindspring.com>
 0xA3   90-9F   linux/dtlk.h
+0xA4   00-1F   uapi/linux/tee.h        Generic TEE subsystem
 0xAA   00-3F   linux/uapi/linux/userfaultfd.h
 0xAB   00-1F   linux/nbd.h
 0xAC   00-1F   linux/raw.h
index 9b9c4797fc55653dec668d82ae8c43ccdab58e4b..e18daca65ccd2add180e5e74f97d0cc4743677cb 100644 (file)
@@ -44,11 +44,11 @@ This document describes the Linux kernel Makefiles.
           --- 6.11 Post-link pass
 
        === 7 Kbuild syntax for exported headers
-               --- 7.1 header-y
+               --- 7.1 no-export-headers
                --- 7.2 genhdr-y
-               --- 7.3 destination-y
-               --- 7.4 generic-y
-               --- 7.5 generated-y
+               --- 7.3 generic-y
+               --- 7.4 generated-y
+               --- 7.5 mandatory-y
 
        === 8 Kbuild Variables
        === 9 Makefile language
@@ -1236,7 +1236,7 @@ When kbuild executes, the following steps are followed (roughly):
        that may be shared between individual architectures.
        The recommended approach how to use a generic header file is
        to list the file in the Kbuild file.
-       See "7.4 generic-y" for further info on syntax etc.
+       See "7.3 generic-y" for further info on syntax etc.
 
 --- 6.11 Post-link pass
 
@@ -1263,53 +1263,32 @@ The pre-processing does:
 - drop include of compiler.h
 - drop all sections that are kernel internal (guarded by ifdef __KERNEL__)
 
-Each relevant directory contains a file name "Kbuild" which specifies the
-headers to be exported.
-See subsequent chapter for the syntax of the Kbuild file.
-
-       --- 7.1 header-y
-
-       header-y specifies header files to be exported.
-
-               Example:
-                       #include/linux/Kbuild
-                       header-y += usb/
-                       header-y += aio_abi.h
+All headers under include/uapi/, include/generated/uapi/,
+arch/<arch>/include/uapi/ and arch/<arch>/include/generated/uapi/
+are exported.
 
-       The convention is to list one file per line and
-       preferably in alphabetic order.
+A Kbuild file may be defined under arch/<arch>/include/uapi/asm/ and
+arch/<arch>/include/asm/ to list asm files coming from asm-generic.
+See subsequent chapter for the syntax of the Kbuild file.
 
-       header-y also specifies which subdirectories to visit.
-       A subdirectory is identified by a trailing '/' which
-       can be seen in the example above for the usb subdirectory.
+       --- 7.1 no-export-headers
 
-       Subdirectories are visited before their parent directories.
+       no-export-headers is essentially used by include/uapi/linux/Kbuild to
+       avoid exporting specific headers (e.g. kvm.h) on architectures that do
+       not support it. It should be avoided as much as possible.
 
        --- 7.2 genhdr-y
 
-       genhdr-y specifies generated files to be exported.
-       Generated files are special as they need to be looked
-       up in another directory when doing 'make O=...' builds.
+       genhdr-y specifies asm files to be generated.
 
                Example:
-                       #include/linux/Kbuild
-                       genhdr-y += version.h
+                       #arch/x86/include/uapi/asm/Kbuild
+                       genhdr-y += unistd_32.h
+                       genhdr-y += unistd_64.h
+                       genhdr-y += unistd_x32.h
 
-       --- 7.3 destination-y
 
-       When an architecture has a set of exported headers that needs to be
-       exported to a different directory destination-y is used.
-       destination-y specifies the destination directory for all exported
-       headers in the file where it is present.
-
-               Example:
-                       #arch/xtensa/platforms/s6105/include/platform/Kbuild
-                       destination-y := include/linux
-
-       In the example above all exported headers in the Kbuild file
-       will be located in the directory "include/linux" when exported.
-
-       --- 7.4 generic-y
+       --- 7.3 generic-y
 
        If an architecture uses a verbatim copy of a header from
        include/asm-generic then this is listed in the file
@@ -1336,7 +1315,7 @@ See subsequent chapter for the syntax of the Kbuild file.
                Example: termios.h
                        #include <asm-generic/termios.h>
 
-       --- 7.5 generated-y
+       --- 7.4 generated-y
 
        If an architecture generates other header files alongside generic-y
        wrappers, and not included in genhdr-y, then generated-y specifies
@@ -1349,6 +1328,15 @@ See subsequent chapter for the syntax of the Kbuild file.
                        #arch/x86/include/asm/Kbuild
                        generated-y += syscalls_32.h
 
+       --- 7.5 mandatory-y
+
+       mandatory-y is essentially used by include/uapi/asm-generic/Kbuild.asm
+       to define the minimun set of headers that must be exported in
+       include/asm.
+
+       The convention is to list one subdir per line and
+       preferably in alphabetic order.
+
 === 8 Kbuild Variables
 
 The top Makefile exports the following variables:
index d2b0a8d81258b43cc1bc97350b9fa4f713101b58..732f10ea382e8e54ab78355934ec63669f59b285 100644 (file)
@@ -768,7 +768,7 @@ equal to zero, in which case the compiler is within its rights to
 transform the above code into the following:
 
        q = READ_ONCE(a);
-       WRITE_ONCE(b, 1);
+       WRITE_ONCE(b, 2);
        do_something_else();
 
 Given this transformation, the CPU is not required to respect the ordering
@@ -2373,7 +2373,7 @@ is performed:
                                        spin_unlock(Q);
 
 
-See Documentation/DocBook/deviceiobook.tmpl for more information.
+See Documentation/driver-api/device-io.rst for more information.
 
 
 =================================
@@ -2614,7 +2614,7 @@ might be needed:
      relaxed memory access properties, then _mandatory_ memory barriers are
      required to enforce ordering.
 
-See Documentation/DocBook/deviceiobook.tmpl for more information.
+See Documentation/driver-api/device-io.rst for more information.
 
 
 INTERRUPTS
diff --git a/Documentation/misc-devices/pci-endpoint-test.txt b/Documentation/misc-devices/pci-endpoint-test.txt
new file mode 100644 (file)
index 0000000..4ebc359
--- /dev/null
@@ -0,0 +1,35 @@
+Driver for PCI Endpoint Test Function
+
+This driver should be used as a host side driver if the root complex is
+connected to a configurable PCI endpoint running *pci_epf_test* function
+driver configured according to [1].
+
+The "pci_endpoint_test" driver can be used to perform the following tests.
+
+The PCI driver for the test device performs the following tests
+       *) verifying addresses programmed in BAR
+       *) raise legacy IRQ
+       *) raise MSI IRQ
+       *) read data
+       *) write data
+       *) copy data
+
+This misc driver creates /dev/pci-endpoint-test.<num> for every
+*pci_epf_test* function connected to the root complex and "ioctls"
+should be used to perform the above tests.
+
+ioctl
+-----
+ PCITEST_BAR: Tests the BAR. The number of the BAR to be tested
+             should be passed as argument.
+ PCITEST_LEGACY_IRQ: Tests legacy IRQ
+ PCITEST_MSI: Tests message signalled interrupts. The MSI number
+             to be tested should be passed as argument.
+ PCITEST_WRITE: Perform write tests. The size of the buffer should be passed
+               as argument.
+ PCITEST_READ: Perform read tests. The size of the buffer should be passed
+              as argument.
+ PCITEST_COPY: Perform read tests. The size of the buffer should be passed
+              as argument.
+
+[1] -> Documentation/PCI/endpoint/function/binding/pci-test.txt
index 19b1e3d09a19b629b622323bbed3e43b5257b5a5..9cabaf8a207e2c945293932cf33a12c9eedb0558 100644 (file)
@@ -55,10 +55,14 @@ as follows:
          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 'fadump_reserve_mem=' which will
-         override the default calculated size. Use this option
-         if default boot memory size is not sufficient for second
-         kernel to boot successfully.
+         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/kdump/kdump.txt. If any offset is
+         provided in crashkernel= parameter, it will be ignored
+         as fadump reserves memory at end of RAM 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
@@ -158,13 +162,16 @@ 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.
-3. Optionally, user can also set 'fadump_reserve_mem=' kernel cmdline
+3. Optionally, user can also set 'crashkernel=' kernel cmdline
    to specify size of the memory to reserve for boot memory dump
    preservation.
 
-NOTE: If firmware-assisted dump fails to reserve memory then it will
-   fallback to existing kdump mechanism if 'crashkernel=' option
-   is set at kernel cmdline.
+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.
 
 Sysfs/debugfs files:
 ------------
diff --git a/Documentation/switchtec.txt b/Documentation/switchtec.txt
new file mode 100644 (file)
index 0000000..a0a9c7b
--- /dev/null
@@ -0,0 +1,80 @@
+========================
+Linux Switchtec Support
+========================
+
+Microsemi's "Switchtec" line of PCI switch devices is already
+supported by the kernel with standard PCI switch drivers. However, the
+Switchtec device advertises a special management endpoint which
+enables some additional functionality. This includes:
+
+* Packet and Byte Counters
+* Firmware Upgrades
+* Event and Error logs
+* Querying port link status
+* Custom user firmware commands
+
+The switchtec kernel module implements this functionality.
+
+
+Interface
+=========
+
+The primary means of communicating with the Switchtec management firmware is
+through the Memory-mapped Remote Procedure Call (MRPC) interface.
+Commands are submitted to the interface with a 4-byte command
+identifier and up to 1KB of command specific data. The firmware will
+respond with a 4 bytes return code and up to 1KB of command specific
+data. The interface only processes a single command at a time.
+
+
+Userspace Interface
+===================
+
+The MRPC interface will be exposed to userspace through a simple char
+device: /dev/switchtec#, one for each management endpoint in the system.
+
+The char device has the following semantics:
+
+* A write must consist of at least 4 bytes and no more than 1028 bytes.
+  The first four bytes will be interpreted as the command to run and
+  the remainder will be used as the input data. A write will send the
+  command to the firmware to begin processing.
+
+* Each write must be followed by exactly one read. Any double write will
+  produce an error and any read that doesn't follow a write will
+  produce an error.
+
+* A read will block until the firmware completes the command and return
+  the four bytes of status plus up to 1024 bytes of output data. (The
+  length will be specified by the size parameter of the read call --
+  reading less than 4 bytes will produce an error.
+
+* The poll call will also be supported for userspace applications that
+  need to do other things while waiting for the command to complete.
+
+The following IOCTLs are also supported by the device:
+
+* SWITCHTEC_IOCTL_FLASH_INFO - Retrieve firmware length and number
+  of partitions in the device.
+
+* SWITCHTEC_IOCTL_FLASH_PART_INFO - Retrieve address and lengeth for
+  any specified partition in flash.
+
+* SWITCHTEC_IOCTL_EVENT_SUMMARY - Read a structure of bitmaps
+  indicating all uncleared events.
+
+* SWITCHTEC_IOCTL_EVENT_CTL - Get the current count, clear and set flags
+  for any event. This ioctl takes in a switchtec_ioctl_event_ctl struct
+  with the event_id, index and flags set (index being the partition or PFF
+  number for non-global events). It returns whether the event has
+  occurred, the number of times and any event specific data. The flags
+  can be used to clear the count or enable and disable actions to
+  happen when the event occurs.
+  By using the SWITCHTEC_IOCTL_EVENT_FLAG_EN_POLL flag,
+  you can set an event to trigger a poll command to return with
+  POLLPRI. In this way, userspace can wait for events to occur.
+
+* SWITCHTEC_IOCTL_PFF_TO_PORT and SWITCHTEC_IOCTL_PORT_TO_PFF convert
+  between PCI Function Framework number (used by the event system)
+  and Switchtec Logic Port ID and Partition number (which is more
+  user friendly).
diff --git a/Documentation/target/target-export-device b/Documentation/target/target-export-device
new file mode 100755 (executable)
index 0000000..b803f4f
--- /dev/null
@@ -0,0 +1,80 @@
+#!/bin/sh
+#
+# This script illustrates the sequence of operations in configfs to
+# create a very simple LIO iSCSI target with a file or block device
+# backstore.
+#
+# (C) Copyright 2014 Christophe Vu-Brugier <cvubrugier@fastmail.fm>
+#
+
+print_usage() {
+    cat <<EOF
+Usage: $(basename $0) [-p PORTAL] DEVICE|FILE
+Export a block device or a file as an iSCSI target with a single LUN
+EOF
+}
+
+die() {
+    echo $1
+    exit 1
+}
+
+while getopts "hp:" arg; do
+    case $arg in
+        h) print_usage; exit 0;;
+        p) PORTAL=${OPTARG};;
+    esac
+done
+shift $(($OPTIND - 1))
+
+DEVICE=$1
+[ -n "$DEVICE" ] || die "Missing device or file argument"
+[ -b $DEVICE -o -f $DEVICE ] || die "Invalid device or file: ${DEVICE}"
+IQN="iqn.2003-01.org.linux-iscsi.$(hostname):$(basename $DEVICE)"
+[ -n "$PORTAL" ] || PORTAL="0.0.0.0:3260"
+
+CONFIGFS=/sys/kernel/config
+CORE_DIR=$CONFIGFS/target/core
+ISCSI_DIR=$CONFIGFS/target/iscsi
+
+# Load the target modules and mount the config file system
+lsmod | grep -q configfs || modprobe configfs
+lsmod | grep -q target_core_mod || modprobe target_core_mod
+mount | grep -q ^configfs || mount -t configfs none $CONFIGFS
+mkdir -p $ISCSI_DIR
+
+# Create a backstore
+if [ -b $DEVICE ]; then
+    BACKSTORE_DIR=$CORE_DIR/iblock_0/data
+    mkdir -p $BACKSTORE_DIR
+    echo "udev_path=${DEVICE}" > $BACKSTORE_DIR/control
+else
+    BACKSTORE_DIR=$CORE_DIR/fileio_0/data
+    mkdir -p $BACKSTORE_DIR
+    DEVICE_SIZE=$(du -b $DEVICE | cut -f1)
+    echo "fd_dev_name=${DEVICE}" > $BACKSTORE_DIR/control
+    echo "fd_dev_size=${DEVICE_SIZE}" > $BACKSTORE_DIR/control
+    echo 1 > $BACKSTORE_DIR/attrib/emulate_write_cache
+fi
+echo 1 > $BACKSTORE_DIR/enable
+
+# Create an iSCSI target and a target portal group (TPG)
+mkdir $ISCSI_DIR/$IQN
+mkdir $ISCSI_DIR/$IQN/tpgt_1/
+
+# Create a LUN
+mkdir $ISCSI_DIR/$IQN/tpgt_1/lun/lun_0
+ln -s $BACKSTORE_DIR $ISCSI_DIR/$IQN/tpgt_1/lun/lun_0/data
+echo 1 > $ISCSI_DIR/$IQN/tpgt_1/enable
+
+# Create a network portal
+mkdir $ISCSI_DIR/$IQN/tpgt_1/np/$PORTAL
+
+# Disable authentication
+echo 0 > $ISCSI_DIR/$IQN/tpgt_1/attrib/authentication
+echo 1 > $ISCSI_DIR/$IQN/tpgt_1/attrib/generate_node_acls
+
+# Allow write access for non authenticated initiators
+echo 0 > $ISCSI_DIR/$IQN/tpgt_1/attrib/demo_mode_write_protect
+
+echo "Target ${IQN}, portal ${PORTAL} has been created"
diff --git a/Documentation/tee.txt b/Documentation/tee.txt
new file mode 100644 (file)
index 0000000..7185993
--- /dev/null
@@ -0,0 +1,118 @@
+TEE subsystem
+This document describes the TEE subsystem in Linux.
+
+A TEE (Trusted Execution Environment) is a trusted OS running in some
+secure environment, for example, TrustZone on ARM CPUs, or a separate
+secure co-processor etc. A TEE driver handles the details needed to
+communicate with the TEE.
+
+This subsystem deals with:
+
+- Registration of TEE drivers
+
+- Managing shared memory between Linux and the TEE
+
+- Providing a generic API to the TEE
+
+The TEE interface
+=================
+
+include/uapi/linux/tee.h defines the generic interface to a TEE.
+
+User space (the client) connects to the driver by opening /dev/tee[0-9]* or
+/dev/teepriv[0-9]*.
+
+- TEE_IOC_SHM_ALLOC allocates shared memory and returns a file descriptor
+  which user space can mmap. When user space doesn't need the file
+  descriptor any more, it should be closed. When shared memory isn't needed
+  any longer it should be unmapped with munmap() to allow the reuse of
+  memory.
+
+- TEE_IOC_VERSION lets user space know which TEE this driver handles and
+  the its capabilities.
+
+- TEE_IOC_OPEN_SESSION opens a new session to a Trusted Application.
+
+- TEE_IOC_INVOKE invokes a function in a Trusted Application.
+
+- TEE_IOC_CANCEL may cancel an ongoing TEE_IOC_OPEN_SESSION or TEE_IOC_INVOKE.
+
+- TEE_IOC_CLOSE_SESSION closes a session to a Trusted Application.
+
+There are two classes of clients, normal clients and supplicants. The latter is
+a helper process for the TEE to access resources in Linux, for example file
+system access. A normal client opens /dev/tee[0-9]* and a supplicant opens
+/dev/teepriv[0-9].
+
+Much of the communication between clients and the TEE is opaque to the
+driver. The main job for the driver is to receive requests from the
+clients, forward them to the TEE and send back the results. In the case of
+supplicants the communication goes in the other direction, the TEE sends
+requests to the supplicant which then sends back the result.
+
+OP-TEE driver
+=============
+
+The OP-TEE driver handles OP-TEE [1] based TEEs. Currently it is only the ARM
+TrustZone based OP-TEE solution that is supported.
+
+Lowest level of communication with OP-TEE builds on ARM SMC Calling
+Convention (SMCCC) [2], which is the foundation for OP-TEE's SMC interface
+[3] used internally by the driver. Stacked on top of that is OP-TEE Message
+Protocol [4].
+
+OP-TEE SMC interface provides the basic functions required by SMCCC and some
+additional functions specific for OP-TEE. The most interesting functions are:
+
+- OPTEE_SMC_FUNCID_CALLS_UID (part of SMCCC) returns the version information
+  which is then returned by TEE_IOC_VERSION
+
+- OPTEE_SMC_CALL_GET_OS_UUID returns the particular OP-TEE implementation, used
+  to tell, for instance, a TrustZone OP-TEE apart from an OP-TEE running on a
+  separate secure co-processor.
+
+- OPTEE_SMC_CALL_WITH_ARG drives the OP-TEE message protocol
+
+- OPTEE_SMC_GET_SHM_CONFIG lets the driver and OP-TEE agree on which memory
+  range to used for shared memory between Linux and OP-TEE.
+
+The GlobalPlatform TEE Client API [5] is implemented on top of the generic
+TEE API.
+
+Picture of the relationship between the different components in the
+OP-TEE architecture.
+
+    User space                  Kernel                   Secure world
+    ~~~~~~~~~~                  ~~~~~~                   ~~~~~~~~~~~~
+ +--------+                                             +-------------+
+ | Client |                                             | Trusted     |
+ +--------+                                             | Application |
+    /\                                                  +-------------+
+    || +----------+                                           /\
+    || |tee-      |                                           ||
+    || |supplicant|                                           \/
+    || +----------+                                     +-------------+
+    \/      /\                                          | TEE Internal|
+ +-------+  ||                                          | API         |
+ + TEE   |  ||            +--------+--------+           +-------------+
+ | Client|  ||            | TEE    | OP-TEE |           | OP-TEE      |
+ | API   |  \/            | subsys | driver |           | Trusted OS  |
+ +-------+----------------+----+-------+----+-----------+-------------+
+ |      Generic TEE API        |       |     OP-TEE MSG               |
+ |      IOCTL (TEE_IOC_*)      |       |     SMCCC (OPTEE_SMC_CALL_*) |
+ +-----------------------------+       +------------------------------+
+
+RPC (Remote Procedure Call) are requests from secure world to kernel driver
+or tee-supplicant. An RPC is identified by a special range of SMCCC return
+values from OPTEE_SMC_CALL_WITH_ARG. RPC messages which are intended for the
+kernel are handled by the kernel driver. Other RPC messages will be forwarded to
+tee-supplicant without further involvement of the driver, except switching
+shared memory buffer representation.
+
+References:
+[1] https://github.com/OP-TEE/optee_os
+[2] http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html
+[3] drivers/tee/optee/optee_smc.h
+[4] drivers/tee/optee/optee_msg.h
+[5] http://www.globalplatform.org/specificationsdevice.asp look for
+    "TEE Client API Specification v1.0" and click download.
index ef473dc7f55edd445abe23dd7d3866a873d490e1..bb9a0a53e76b0f22905862848b6950d598c600c4 100644 (file)
@@ -582,3 +582,24 @@ platform data is provided, this uses the step_wise throttling policy.
 This function serves as an arbitrator to set the state of a cooling
 device. It sets the cooling device to the deepest cooling state if
 possible.
+
+6. thermal_emergency_poweroff:
+
+On an event of critical trip temperature crossing. Thermal framework
+allows the system to shutdown gracefully by calling orderly_poweroff().
+In the event of a failure of orderly_poweroff() to shut down the system
+we are in danger of keeping the system alive at undesirably high
+temperatures. To mitigate this high risk scenario we program a work
+queue to fire after a pre-determined number of seconds to start
+an emergency shutdown of the device using the kernel_power_off()
+function. In case kernel_power_off() fails then finally
+emergency_restart() is called in the worst case.
+
+The delay should be carefully profiled so as to give adequate time for
+orderly_poweroff(). In case of failure of an orderly_poweroff() the
+emergency poweroff kicks in after the delay has elapsed and shuts down
+the system.
+
+If set to 0 emergency poweroff will not be supported. So a carefully
+profiled non-zero positive value is a must for emergerncy poweroff to be
+triggered.
index ce0b48d69eaae96b7e819431dc7864983827b50c..d05d4c54e8f79c8d8ee09898211b629e62d254a4 100644 (file)
@@ -2343,7 +2343,7 @@ ACQUIRE VS I/O 액세스
                                        spin_unlock(Q);
 
 
-더 많은 정보를 위해선 Documenataion/DocBook/deviceiobook.tmpl 을 참고하세요.
+더 많은 정보를 위해선 Documentation/driver-api/device-io.rst 를 참고하세요.
 
 
 =========================
@@ -2578,7 +2578,7 @@ CPU 에서는 사용되는 어토믹 인스트럭션 자체에 메모리 배리
  (2) 만약 액세스 함수들이 완화된 메모리 액세스 속성을 갖는 I/O 메모리 윈도우를
      사용한다면, 순서를 강제하기 위해선 _mandatory_ 메모리 배리어가 필요합니다.
 
-더 많은 정보를 위해선 Documentation/DocBook/deviceiobook.tmpl 을 참고하십시오.
+더 많은 정보를 위해선 Documentation/driver-api/device-io.rst 를 참고하십시오.
 
 
 인터럽트
index 6081a5b7fc1ed93c3dbdb32599a53c8165697447..eb06beb759601f1fa7c96a12ebda6a774f7d877f 100644 (file)
@@ -32,7 +32,128 @@ Groups:
     KVM_DEV_ARM_VGIC_CTRL_INIT
       request the initialization of the ITS, no additional parameter in
       kvm_device_attr.addr.
+
+    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
+
+  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
index c1a24612c198e051e8cd82ebc95fa13f7ddf3bc2..9293b45abdb99578724c995676addd0c50967c57 100644 (file)
@@ -167,11 +167,17 @@ Groups:
     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
index cd28d5ee52732308a171356e466571400192f31a..4dde03b44ad1b2b5b2d091f134d43ec48565f3ab 100644 (file)
@@ -266,7 +266,7 @@ for each mapping.
 
 The number of file transparent huge pages mapped to userspace is available
 by reading ShmemPmdMapped and ShmemHugePages fields in /proc/meminfo.
-To identify what applications are mapping file  transparent huge pages, it
+To identify what applications are mapping file transparent huge pages, it
 is necessary to read /proc/PID/smaps and count the FileHugeMapped fields
 for each mapping.
 
@@ -292,7 +292,7 @@ thp_collapse_alloc_failed is incremented if khugepaged found a range
        the allocation.
 
 thp_file_alloc is incremented every time a file huge page is successfully
-i      allocated.
+       allocated.
 
 thp_file_mapped is incremented every time a file huge page is mapped into
        user address space.
@@ -501,7 +501,7 @@ scanner can get reference to a page is get_page_unless_zero().
 
 All tail pages have zero ->_refcount until atomic_add(). This prevents the
 scanner from getting a reference to the tail page up to that point. After the
-atomic_add() we don't care about the ->_refcount value.  We already known how
+atomic_add() we don't care about the ->_refcount value. We already known how
 many references should be uncharged from the head page.
 
 For head page get_page_unless_zero() will succeed and we don't mind. It's
@@ -519,8 +519,8 @@ comes. Splitting will free up unused subpages.
 
 Splitting the page right away is not an option due to locking context in
 the place where we can detect partial unmap. It's also might be
-counterproductive since in many cases partial unmap unmap happens during
-exit(2) if an THP crosses VMA boundary.
+counterproductive since in many cases partial unmap happens during exit(2) if
+a THP crosses a VMA boundary.
 
 Function deferred_split_huge_page() is used to queue page for splitting.
 The splitting itself will happen when we get memory pressure via shrinker
index 0f6d8477b66c393ed27fbd0be3e175078ced68a5..c491a1b82de22a74d9559a418023fb8c312ffed4 100644 (file)
@@ -295,7 +295,7 @@ kernel and the tasks running there get 50% of the cache. They should
 also get 50% of memory bandwidth assuming that the cores 4-7 are SMT
 siblings and only the real time threads are scheduled on the cores 4-7.
 
-# echo C0 > p0/cpus
+# echo F0 > p0/cpus
 
 4) Locking between applications
 
diff --git a/Kbuild b/Kbuild
index 3d0ae152af7c6271d2b6bf85acef2025e25d8cc5..94c752762bc26530f8024162140c9da9d08b5167 100644 (file)
--- a/Kbuild
+++ b/Kbuild
@@ -7,31 +7,6 @@
 # 4) Check for missing system calls
 # 5) Generate constants.py (may need bounds.h)
 
-# Default sed regexp - multiline due to syntax constraints
-define sed-y
-       "/^->/{s:->#\(.*\):/* \1 */:; \
-       s:^->\([^ ]*\) [\$$#]*\([-0-9]*\) \(.*\):#define \1 \2 /* \3 */:; \
-       s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \
-       s:->::; p;}"
-endef
-
-# Use filechk to avoid rebuilds when a header changes, but the resulting file
-# does not
-define filechk_offsets
-       (set -e; \
-        echo "#ifndef $2"; \
-        echo "#define $2"; \
-        echo "/*"; \
-        echo " * DO NOT MODIFY."; \
-        echo " *"; \
-        echo " * This file was generated by Kbuild"; \
-        echo " */"; \
-        echo ""; \
-        sed -ne $(sed-y); \
-        echo ""; \
-        echo "#endif" )
-endef
-
 #####
 # 1) Generate bounds.h
 
index 0e174d4b86a36fa2009ca8ff6a42e216b99531cb..503bcf4e3e8ffd09750bf6ee1b9cce43c7351be6 100644 (file)
@@ -653,7 +653,9 @@ M:  Thor Thayer <thor.thayer@linux.intel.com>
 S:     Maintained
 F:     drivers/gpio/gpio-altera-a10sr.c
 F:     drivers/mfd/altera-a10sr.c
+F:     drivers/reset/reset-a10sr.c
 F:     include/linux/mfd/altera-a10sr.h
+F:     include/dt-bindings/reset/altr,rst-mgr-a10sr.h
 
 ALTERA TRIPLE SPEED ETHERNET DRIVER
 M:     Vince Bridgers <vbridger@opensource.altera.com>
@@ -1056,8 +1058,13 @@ M:       Chen-Yu Tsai <wens@csie.org>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
 N:     sun[x456789]i
-F:     arch/arm/boot/dts/ntc-gr8*
+N:     sun50i
+F:     arch/arm/mach-sunxi/
 F:     arch/arm64/boot/dts/allwinner/
+F:     drivers/clk/sunxi-ng/
+F:     drivers/pinctrl/sunxi/
+F:     drivers/soc/sunxi/
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/sunxi/linux.git
 
 ARM/Allwinner SoC Clock Support
 M:     Emilio López <emilio@elopez.com.ar>
@@ -1078,6 +1085,16 @@ F:       drivers/pinctrl/meson/
 F:     drivers/mmc/host/meson*
 N:     meson
 
+ARM/Amlogic Meson SoC CLOCK FRAMEWORK
+M:     Neil Armstrong <narmstrong@baylibre.com>
+M:     Jerome Brunet <jbrunet@baylibre.com>
+L:     linux-amlogic@lists.infradead.org
+S:     Maintained
+F:     drivers/clk/meson/
+F:     include/dt-bindings/clock/meson*
+F:     include/dt-bindings/clock/gxbb*
+F:     Documentation/devicetree/bindings/clock/amlogic*
+
 ARM/Annapurna Labs ALPINE ARCHITECTURE
 M:     Tsahee Zidenberg <tsahee@annapurnalabs.com>
 M:     Antoine Tenart <antoine.tenart@free-electrons.com>
@@ -1110,7 +1127,6 @@ F:        drivers/*/*aspeed*
 ARM/ATMEL AT91RM9200, AT91SAM9 AND SAMA5 SOC SUPPORT
 M:     Nicolas Ferre <nicolas.ferre@microchip.com>
 M:     Alexandre Belloni <alexandre.belloni@free-electrons.com>
-M:     Jean-Christophe Plagniol-Villard <plagnioj@jcrosoft.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 W:     http://www.linux4sam.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/nferre/linux-at91.git
@@ -1122,6 +1138,7 @@ F:        arch/arm/boot/dts/at91*.dtsi
 F:     arch/arm/boot/dts/sama*.dts
 F:     arch/arm/boot/dts/sama*.dtsi
 F:     arch/arm/include/debug/at91.S
+F:     drivers/memory/atmel*
 
 ARM/ATMEL AT91 Clock Support
 M:     Boris Brezillon <boris.brezillon@free-electrons.com>
@@ -1277,6 +1294,7 @@ F:        arch/arm/mach-mxs/
 F:     arch/arm/boot/dts/imx*
 F:     arch/arm/configs/imx*_defconfig
 F:     drivers/clk/imx/
+F:     drivers/soc/imx/
 F:     include/soc/imx/
 
 ARM/FREESCALE VYBRID ARM ARCHITECTURE
@@ -1497,6 +1515,7 @@ M:        Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
 M:     Gregory Clement <gregory.clement@free-electrons.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
+F:     Documentation/devicetree/bindings/soc/dove/
 F:     arch/arm/mach-dove/
 F:     arch/arm/mach-mv78xx0/
 F:     arch/arm/mach-orion5x/
@@ -2255,7 +2274,7 @@ M:        Wenyou Yang <wenyou.yang@atmel.com>
 M:     Josh Wu <rainyfeeling@outlook.com>
 L:     linux-mtd@lists.infradead.org
 S:     Supported
-F:     drivers/mtd/nand/atmel_nand*
+F:     drivers/mtd/nand/atmel/*
 
 ATMEL SDMMC DRIVER
 M:     Ludovic Desroches <ludovic.desroches@microchip.com>
@@ -2464,7 +2483,7 @@ S:        Maintained
 F:     drivers/net/ethernet/ec_bhf.c
 
 BFS FILE SYSTEM
-M:     "Tigran A. Aivazian" <tigran@aivazian.fsnet.co.uk>
+M:     "Tigran A. Aivazian" <aivazian.tigran@gmail.com>
 S:     Maintained
 F:     Documentation/filesystems/bfs.txt
 F:     fs/bfs/
@@ -2667,9 +2686,9 @@ N:        kona
 F:     arch/arm/mach-bcm/
 
 BROADCOM BCM2835 ARM ARCHITECTURE
-M:     Stephen Warren <swarren@wwwdotorg.org>
 M:     Lee Jones <lee@kernel.org>
 M:     Eric Anholt <eric@anholt.net>
+M:     Stefan Wahren <stefan.wahren@i2se.com>
 L:     linux-rpi-kernel@lists.infradead.org (moderated for non-subscribers)
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 T:     git git://github.com/anholt/linux
@@ -2689,12 +2708,14 @@ F:      arch/mips/include/asm/mach-bcm47xx/*
 BROADCOM BCM5301X ARM ARCHITECTURE
 M:     Hauke Mehrtens <hauke@hauke-m.de>
 M:     Rafał Miłecki <zajec5@gmail.com>
+M:     Jon Mason <jonmason@broadcom.com>
 M:     bcm-kernel-feedback-list@broadcom.com
 L:     linux-arm-kernel@lists.infradead.org
 S:     Maintained
 F:     arch/arm/mach-bcm/bcm_5301x.c
 F:     arch/arm/boot/dts/bcm5301x*.dtsi
 F:     arch/arm/boot/dts/bcm470*
+F:     arch/arm/boot/dts/bcm953012*
 
 BROADCOM BCM53573 ARM ARCHITECTURE
 M:     Rafał Miłecki <rafal@milecki.pl>
@@ -2856,13 +2877,6 @@ L:       netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/broadcom/bcmsysport.*
 
-BROADCOM VULCAN ARM64 SOC
-M:     Jayachandran C. <c.jayachandran@gmail.com>
-M:     bcm-kernel-feedback-list@broadcom.com
-L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-S:     Maintained
-F:     arch/arm64/boot/dts/broadcom/vulcan*
-
 BROADCOM NETXTREME-E ROCE DRIVER
 M:     Selvin Xavier <selvin.xavier@broadcom.com>
 M:     Devesh Sharma <devesh.sharma@broadcom.com>
@@ -2922,6 +2936,8 @@ T:        git git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs.git
 S:     Maintained
 F:     Documentation/filesystems/btrfs.txt
 F:     fs/btrfs/
+F:     include/linux/btrfs*
+F:     include/uapi/linux/btrfs*
 
 BTTV VIDEO4LINUX DRIVER
 M:     Mauro Carvalho Chehab <mchehab@s-opensource.com>
@@ -3056,7 +3072,7 @@ CAVIUM THUNDERX2 ARM64 SOC
 M:     Jayachandran C <jnair@caviumnetworks.com>
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
-F:     arch/arm64/boot/dts/cavium/thunder-99xx*
+F:     arch/arm64/boot/dts/cavium/thunder2-99xx*
 F:     Documentation/devicetree/bindings/arm/cavium-thunder2.txt
 
 CAVIUM I2C DRIVER
@@ -5584,6 +5600,7 @@ L:        linux-pm@vger.kernel.org
 S:     Supported
 F:     drivers/base/power/domain*.c
 F:     include/linux/pm_domain.h
+F:     Documentation/devicetree/bindings/power/power_domain.txt
 
 GENERIC UIO DRIVER FOR PCI DEVICES
 M:     "Michael S. Tsirkin" <mst@redhat.com>
@@ -7906,7 +7923,7 @@ L:        linux-man@vger.kernel.org
 S:     Maintained
 
 MARDUK (CREATOR CI40) DEVICE TREE SUPPORT
-M:     Rahul Bedarkar <rahul.bedarkar@imgtec.com>
+M:     Rahul Bedarkar <rahulbedarkar89@gmail.com>
 L:     linux-mips@linux-mips.org
 S:     Maintained
 F:     arch/mips/boot/dts/img/pistachio_marduk.dts
@@ -8359,12 +8376,12 @@ M:      Brian Norris <computersforpeace@gmail.com>
 M:     Boris Brezillon <boris.brezillon@free-electrons.com>
 M:     Marek Vasut <marek.vasut@gmail.com>
 M:     Richard Weinberger <richard@nod.at>
-M:     Cyrille Pitchen <cyrille.pitchen@atmel.com>
+M:     Cyrille Pitchen <cyrille.pitchen@wedev4u.fr>
 L:     linux-mtd@lists.infradead.org
 W:     http://www.linux-mtd.infradead.org/
 Q:     http://patchwork.ozlabs.org/project/linux-mtd/list/
-T:     git git://git.infradead.org/linux-mtd.git
-T:     git git://git.infradead.org/l2-mtd.git
+T:     git git://git.infradead.org/linux-mtd.git master
+T:     git git://git.infradead.org/l2-mtd.git master
 S:     Maintained
 F:     Documentation/devicetree/bindings/mtd/
 F:     drivers/mtd/
@@ -8418,7 +8435,7 @@ MICROCHIP / ATMEL AT91 / AT32 SERIAL DRIVER
 M:     Richard Genoud <richard.genoud@gmail.com>
 S:     Maintained
 F:     drivers/tty/serial/atmel_serial.c
-F:     include/linux/atmel_serial.h
+F:     drivers/tty/serial/atmel_serial.h
 
 MICROCHIP / ATMEL DMA DRIVER
 M:     Ludovic Desroches <ludovic.desroches@microchip.com>
@@ -8739,7 +8756,8 @@ R:        Richard Weinberger <richard@nod.at>
 L:     linux-mtd@lists.infradead.org
 W:     http://www.linux-mtd.infradead.org/
 Q:     http://patchwork.ozlabs.org/project/linux-mtd/list/
-T:     git git://github.com/linux-nand/linux.git
+T:     git git://git.infradead.org/linux-mtd.git nand/fixes
+T:     git git://git.infradead.org/l2-mtd.git nand/next
 S:     Maintained
 F:     drivers/mtd/nand/
 F:     include/linux/mtd/nand*.h
@@ -9511,6 +9529,11 @@ F:       arch/*/oprofile/
 F:     drivers/oprofile/
 F:     include/linux/oprofile.h
 
+OP-TEE DRIVER
+M:     Jens Wiklander <jens.wiklander@linaro.org>
+S:     Maintained
+F:     drivers/tee/optee/
+
 ORACLE CLUSTER FILESYSTEM 2 (OCFS2)
 M:     Mark Fasheh <mfasheh@versity.com>
 M:     Joel Becker <jlbec@evilplan.org>
@@ -9719,6 +9742,15 @@ F:       include/linux/pci*
 F:     arch/x86/pci/
 F:     arch/x86/kernel/quirks.c
 
+PCI ENDPOINT SUBSYSTEM
+M:     Kishon Vijay Abraham I <kishon@ti.com>
+L:     linux-pci@vger.kernel.org
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/kishon/pci-endpoint.git
+S:     Supported
+F:     drivers/pci/endpoint/
+F:     drivers/misc/pci_endpoint_test.c
+F:     tools/pci/
+
 PCI DRIVER FOR ALTERA PCIE IP
 M:     Ley Foon Tan <lftan@altera.com>
 L:     rfi@lists.rocketboards.org (moderated for non-subscribers)
@@ -9793,6 +9825,17 @@ S:       Maintained
 F:     Documentation/devicetree/bindings/pci/aardvark-pci.txt
 F:     drivers/pci/host/pci-aardvark.c
 
+PCI DRIVER FOR MICROSEMI SWITCHTEC
+M:     Kurt Schwemmer <kurt.schwemmer@microsemi.com>
+M:     Stephen Bates <stephen.bates@microsemi.com>
+M:     Logan Gunthorpe <logang@deltatee.com>
+L:     linux-pci@vger.kernel.org
+S:     Maintained
+F:     Documentation/switchtec.txt
+F:     Documentation/ABI/testing/sysfs-class-switchtec
+F:     drivers/pci/switch/switchtec*
+F:     include/uapi/linux/switchtec_ioctl.h
+
 PCI DRIVER FOR NVIDIA TEGRA
 M:     Thierry Reding <thierry.reding@gmail.com>
 L:     linux-tegra@vger.kernel.org
@@ -11268,6 +11311,14 @@ F:     drivers/hwtracing/stm/
 F:     include/linux/stm.h
 F:     include/uapi/linux/stm.h
 
+TEE SUBSYSTEM
+M:     Jens Wiklander <jens.wiklander@linaro.org>
+S:     Maintained
+F:     include/linux/tee_drv.h
+F:     include/uapi/linux/tee.h
+F:     drivers/tee/
+F:     Documentation/tee.txt
+
 THUNDERBOLT DRIVER
 M:     Andreas Noever <andreas.noever@gmail.com>
 S:     Maintained
@@ -12059,7 +12110,7 @@ S:      Maintained
 F:     drivers/clk/spear/
 
 SPI NOR SUBSYSTEM
-M:     Cyrille Pitchen <cyrille.pitchen@atmel.com>
+M:     Cyrille Pitchen <cyrille.pitchen@wedev4u.fr>
 M:     Marek Vasut <marek.vasut@gmail.com>
 L:     linux-mtd@lists.infradead.org
 W:     http://www.linux-mtd.infradead.org/
@@ -12492,9 +12543,8 @@ S:      Maintained
 F:     drivers/media/rc/ttusbir.c
 
 TEGRA ARCHITECTURE SUPPORT
-M:     Stephen Warren <swarren@wwwdotorg.org>
 M:     Thierry Reding <thierry.reding@gmail.com>
-M:     Alexandre Courbot <gnurou@gmail.com>
+M:     Jonathan Hunter <jonathanh@nvidia.com>
 L:     linux-tegra@vger.kernel.org
 Q:     http://patchwork.ozlabs.org/project/linux-tegra/list/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tegra/linux.git
@@ -12573,6 +12623,9 @@ S:      Maintained
 F:     Documentation/devicetree/bindings/arm/keystone/ti,sci.txt
 F:     drivers/firmware/ti_sci*
 F:     include/linux/soc/ti/ti_sci_protocol.h
+F:     Documentation/devicetree/bindings/soc/ti/sci-pm-domain.txt
+F:     include/dt-bindings/genpd/k2g.h
+F:     drivers/soc/ti/ti_sci_pm_domains.c
 
 THANKO'S RAREMONO AM/FM/SW RADIO RECEIVER USB DRIVER
 M:     Hans Verkuil <hverkuil@xs4all.nl>
@@ -13510,8 +13563,8 @@ F:      include/uapi/linux/virtio_*.h
 F:     drivers/crypto/virtio/
 
 VIRTIO DRIVERS FOR S390
-M:     Christian Borntraeger <borntraeger@de.ibm.com>
 M:     Cornelia Huck <cornelia.huck@de.ibm.com>
+M:     Halil Pasic <pasic@linux.vnet.ibm.com>
 L:     linux-s390@vger.kernel.org
 L:     virtualization@lists.linux-foundation.org
 L:     kvm@vger.kernel.org
index 43534cca1de92262a68cb8aebe686c45067a0330..b1ee4a49efa27c2ce774b28b1bdcefc694b272d5 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 4
-PATCHLEVEL = 11
+PATCHLEVEL = 12
 SUBLEVEL = 0
-EXTRAVERSION =
+EXTRAVERSION = -rc1
 NAME = Fearless Coyote
 
 # *DOCUMENTATION*
@@ -632,13 +632,9 @@ include arch/$(SRCARCH)/Makefile
 KBUILD_CFLAGS  += $(call cc-option,-fno-delete-null-pointer-checks,)
 KBUILD_CFLAGS  += $(call cc-disable-warning,frame-address,)
 
-ifdef CONFIG_LD_DEAD_CODE_DATA_ELIMINATION
-KBUILD_CFLAGS  += $(call cc-option,-ffunction-sections,)
-KBUILD_CFLAGS  += $(call cc-option,-fdata-sections,)
-endif
-
 ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE
-KBUILD_CFLAGS  += -Os $(call cc-disable-warning,maybe-uninitialized,)
+KBUILD_CFLAGS  += $(call cc-option,-Oz,-Os)
+KBUILD_CFLAGS  += $(call cc-disable-warning,maybe-uninitialized,)
 else
 ifdef CONFIG_PROFILE_ALL_BRANCHES
 KBUILD_CFLAGS  += -O2 $(call cc-disable-warning,maybe-uninitialized,)
@@ -698,8 +694,16 @@ endif
 KBUILD_CFLAGS += $(stackp-flag)
 
 ifeq ($(cc-name),clang)
+ifneq ($(CROSS_COMPILE),)
+CLANG_TARGET   := -target $(notdir $(CROSS_COMPILE:%-=%))
+GCC_TOOLCHAIN  := $(realpath $(dir $(shell which $(LD)))/..)
+endif
+ifneq ($(GCC_TOOLCHAIN),)
+CLANG_GCC_TC   := -gcc-toolchain $(GCC_TOOLCHAIN)
+endif
+KBUILD_CFLAGS += $(CLANG_TARGET) $(CLANG_GCC_TC)
+KBUILD_AFLAGS += $(CLANG_TARGET) $(CLANG_GCC_TC)
 KBUILD_CPPFLAGS += $(call cc-option,-Qunused-arguments,)
-KBUILD_CPPFLAGS += $(call cc-option,-Wno-unknown-warning-option,)
 KBUILD_CFLAGS += $(call cc-disable-warning, unused-variable)
 KBUILD_CFLAGS += $(call cc-disable-warning, format-invalid-specifier)
 KBUILD_CFLAGS += $(call cc-disable-warning, gnu)
@@ -710,10 +714,12 @@ KBUILD_CFLAGS += $(call cc-disable-warning, tautological-compare)
 # See modpost pattern 2
 KBUILD_CFLAGS += $(call cc-option, -mno-global-merge,)
 KBUILD_CFLAGS += $(call cc-option, -fcatch-undefined-behavior)
+KBUILD_CFLAGS += $(call cc-option, -no-integrated-as)
+KBUILD_AFLAGS += $(call cc-option, -no-integrated-as)
 else
 
 # These warnings generated too much noise in a regular build.
-# Use make W=1 to enable them (see scripts/Makefile.build)
+# Use make W=1 to enable them (see scripts/Makefile.extrawarn)
 KBUILD_CFLAGS += $(call cc-disable-warning, unused-but-set-variable)
 KBUILD_CFLAGS += $(call cc-disable-warning, unused-const-variable)
 endif
@@ -773,6 +779,11 @@ ifdef CONFIG_DEBUG_SECTION_MISMATCH
 KBUILD_CFLAGS += $(call cc-option, -fno-inline-functions-called-once)
 endif
 
+ifdef CONFIG_LD_DEAD_CODE_DATA_ELIMINATION
+KBUILD_CFLAGS  += $(call cc-option,-ffunction-sections,)
+KBUILD_CFLAGS  += $(call cc-option,-fdata-sections,)
+endif
+
 # arch Makefile may override CC so keep this after arch Makefile is included
 NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
 CHECKFLAGS     += $(NOSTDINC_FLAGS)
@@ -801,6 +812,9 @@ KBUILD_CFLAGS   += $(call cc-option,-Werror=date-time)
 # enforce correct pointer usage
 KBUILD_CFLAGS   += $(call cc-option,-Werror=incompatible-pointer-types)
 
+# Require designated initializers for all marked structures
+KBUILD_CFLAGS   += $(call cc-option,-Werror=designated-init)
+
 # use the deterministic mode of AR if available
 KBUILD_ARFLAGS := $(call ar-option,D)
 
@@ -815,7 +829,7 @@ KBUILD_AFLAGS   += $(ARCH_AFLAGS)   $(KAFLAGS)
 KBUILD_CFLAGS   += $(ARCH_CFLAGS)   $(KCFLAGS)
 
 # Use --build-id when available.
-LDFLAGS_BUILD_ID = $(patsubst -Wl$(comma)%,%,\
+LDFLAGS_BUILD_ID := $(patsubst -Wl$(comma)%,%,\
                              $(call cc-ldoption, -Wl$(comma)--build-id,))
 KBUILD_LDFLAGS_MODULE += $(LDFLAGS_BUILD_ID)
 LDFLAGS_vmlinux += $(LDFLAGS_BUILD_ID)
@@ -1128,7 +1142,7 @@ firmware_install:
 export INSTALL_HDR_PATH = $(objtree)/usr
 
 # If we do an all arch process set dst to asm-$(hdr-arch)
-hdr-dst = $(if $(KBUILD_HEADERS), dst=include/asm-$(hdr-arch), dst=include/asm)
+hdr-dst = $(if $(KBUILD_HEADERS), dst=include/arch-$(hdr-arch), dst=include)
 
 PHONY += archheaders
 archheaders:
@@ -1149,7 +1163,7 @@ headers_install: __headers
        $(if $(wildcard $(srctree)/arch/$(hdr-arch)/include/uapi/asm/Kbuild),, \
          $(error Headers not exportable for the $(SRCARCH) architecture))
        $(Q)$(MAKE) $(hdr-inst)=include/uapi
-       $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/uapi/asm $(hdr-dst)
+       $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/uapi $(hdr-dst)
 
 PHONY += headers_check_all
 headers_check_all: headers_install_all
@@ -1158,7 +1172,7 @@ headers_check_all: headers_install_all
 PHONY += headers_check
 headers_check: headers_install
        $(Q)$(MAKE) $(hdr-inst)=include/uapi HDRCHECK=1
-       $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/uapi/asm $(hdr-dst) HDRCHECK=1
+       $(Q)$(MAKE) $(hdr-inst)=arch/$(hdr-arch)/include/uapi $(hdr-dst) HDRCHECK=1
 
 # ---------------------------------------------------------------------------
 # Kernel selftest
@@ -1315,8 +1329,8 @@ PHONY += distclean
 distclean: mrproper
        @find $(srctree) $(RCS_FIND_IGNORE) \
                \( -name '*.orig' -o -name '*.rej' -o -name '*~' \
-               -o -name '*.bak' -o -name '#*#' -o -name '.*.orig' \
-               -o -name '.*.rej' -o -name '*%'  -o -name 'core' \) \
+               -o -name '*.bak' -o -name '#*#' -o -name '*%' \
+               -o -name 'core' \) \
                -type f -print | xargs rm -f
 
 
@@ -1361,6 +1375,8 @@ help:
        @echo  '                    (default: $$(INSTALL_MOD_PATH)/lib/firmware)'
        @echo  '  dir/            - Build all files in dir and below'
        @echo  '  dir/file.[ois]  - Build specified target only'
+       @echo  '  dir/file.ll     - Build the LLVM assembly file'
+       @echo  '                    (requires compiler support for LLVM assembly generation)'
        @echo  '  dir/file.lst    - Build specified mixed source/assembly target only'
        @echo  '                    (requires a recent binutils and recent build (System.map))'
        @echo  '  dir/file.ko     - Build module including final link'
@@ -1374,7 +1390,7 @@ help:
        @echo  '  headers_install - Install sanitised kernel headers to INSTALL_HDR_PATH'; \
         echo  '                    (default: $(INSTALL_HDR_PATH))'; \
         echo  ''
-       @echo  'Static analysers'
+       @echo  'Static analysers:'
        @echo  '  checkstack      - Generate a list of stack hogs'
        @echo  '  namespacecheck  - Name space analysis on compiled kernel'
        @echo  '  versioncheck    - Sanity check on version.h usage'
@@ -1384,7 +1400,7 @@ help:
        @echo  '  headerdep       - Detect inclusion cycles in headers'
        @$(MAKE) -f $(srctree)/scripts/Makefile.help checker-help
        @echo  ''
-       @echo  'Kernel selftest'
+       @echo  'Kernel selftest:'
        @echo  '  kselftest       - Build and run kernel selftest (run as root)'
        @echo  '                    Build, install, and boot kernel before'
        @echo  '                    running kselftest on it'
@@ -1392,6 +1408,10 @@ help:
        @echo  '  kselftest-merge - Merge all the config dependencies of kselftest to existed'
        @echo  '                    .config.'
        @echo  ''
+       @echo 'Userspace tools targets:'
+       @echo '  use "make tools/help"'
+       @echo '  or  "cd tools; make help"'
+       @echo  ''
        @echo  'Kernel packaging:'
        @$(MAKE) $(build)=$(package-dir) help
        @echo  ''
@@ -1545,6 +1565,7 @@ clean: $(clean-dirs)
                -o -name '*.symtypes' -o -name 'modules.order' \
                -o -name modules.builtin -o -name '.tmp_*.o.*' \
                -o -name '*.c.[012]*.*' \
+               -o -name '*.ll' \
                -o -name '*.gcno' \) -type f -print | xargs rm -f
 
 # Generate tags for editors
@@ -1648,6 +1669,8 @@ endif
        $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
 %.symtypes: %.c prepare scripts FORCE
        $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
+%.ll: %.c prepare scripts FORCE
+       $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
 
 # Modules
 /: prepare scripts FORCE
index 640999412d11450c2a60635b142cb41f58b6e62e..6c00e5b00f8bd6ac4127b80fed79070843826069 100644 (file)
@@ -2,7 +2,11 @@
 # General architecture dependent options
 #
 
+config CRASH_CORE
+       bool
+
 config KEXEC_CORE
+       select CRASH_CORE
        bool
 
 config HAVE_IMA_KEXEC
@@ -320,6 +324,9 @@ config HAVE_CMPXCHG_LOCAL
 config HAVE_CMPXCHG_DOUBLE
        bool
 
+config ARCH_WEAK_RELEASE_ACQUIRE
+       bool
+
 config ARCH_WANT_IPC_PARSE_VERSION
        bool
 
index d96f2ef5b639c33bd70f13cc3b48a162072a90c7..b15bf6bc0e94f46f035e8781ffa921060341fe91 100644 (file)
@@ -1,43 +1,2 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
-
-header-y += a.out.h
-header-y += auxvec.h
-header-y += bitsperlong.h
-header-y += byteorder.h
-header-y += compiler.h
-header-y += console.h
-header-y += errno.h
-header-y += fcntl.h
-header-y += fpu.h
-header-y += gentrap.h
-header-y += ioctl.h
-header-y += ioctls.h
-header-y += ipcbuf.h
-header-y += kvm_para.h
-header-y += mman.h
-header-y += msgbuf.h
-header-y += pal.h
-header-y += param.h
-header-y += poll.h
-header-y += posix_types.h
-header-y += ptrace.h
-header-y += reg.h
-header-y += regdef.h
-header-y += resource.h
-header-y += sembuf.h
-header-y += setup.h
-header-y += shmbuf.h
-header-y += sigcontext.h
-header-y += siginfo.h
-header-y += signal.h
-header-y += socket.h
-header-y += sockios.h
-header-y += stat.h
-header-y += statfs.h
-header-y += swab.h
-header-y += sysinfo.h
-header-y += termbits.h
-header-y += termios.h
-header-y += types.h
-header-y += unistd.h
index 59660743237cc489b4e4eef405e92ab66f7b25e8..7083434dd2419b7b3ef6ef8e74c204522d4a3257 100644 (file)
@@ -46,11 +46,6 @@ AFLAGS___remqu.o =       -DREM
 AFLAGS___divlu.o = -DDIV       -DINTSIZE
 AFLAGS___remlu.o =       -DREM -DINTSIZE
 
-$(obj)/__divqu.o: $(obj)/$(ev6-y)divide.S
-       $(cmd_as_o_S)
-$(obj)/__remqu.o: $(obj)/$(ev6-y)divide.S
-       $(cmd_as_o_S)
-$(obj)/__divlu.o: $(obj)/$(ev6-y)divide.S
-       $(cmd_as_o_S)
-$(obj)/__remlu.o: $(obj)/$(ev6-y)divide.S
-       $(cmd_as_o_S)
+$(addprefix $(obj)/,__divqu.o __remqu.o __divlu.o __remlu.o): \
+                                               $(src)/$(ev6-y)divide.S FORCE
+       $(call if_changed_rule,as_o_S)
index 5d7fb3e7cb97159012d49e6cee745ada293949a6..a5459698f0ee3762917c82c8cbf133e34643f021 100644 (file)
@@ -444,6 +444,7 @@ config ARC_HAS_PAE40
        bool "Support for the 40-bit Physical Address Extension"
        default n
        depends on ISA_ARCV2
+       select HIGHMEM
        help
          Enable access to physical memory beyond 4G, only supported on
          ARC cores with 40 bit Physical Addressing support
index 19cce226d1a830793b54b98fba6f56c6a5a6a88d..44ef35d339564623b2beb4a380a81da6a7790087 100644 (file)
@@ -123,9 +123,9 @@ libs-y              += arch/arc/lib/ $(LIBGCC)
 boot           := arch/arc/boot
 
 #default target for make without any arguments.
-KBUILD_IMAGE   := bootpImage
+KBUILD_IMAGE   := $(boot)/bootpImage
 
-all:   $(KBUILD_IMAGE)
+all:   bootpImage
 bootpImage: vmlinux
 
 boot_targets += uImage uImage.bin uImage.gz
index d6c1bbc98ac3b40caa94e60420996081bdafe44c..41cfb29b62c142ca48193359e8fedf20151cc9bf 100644 (file)
@@ -51,7 +51,7 @@
                        pguclk: pguclk {
                                #clock-cells = <0>;
                                compatible = "fixed-clock";
-                               clock-frequency = <74440000>;
+                               clock-frequency = <74250000>;
                        };
                };
 
                        interrupts = <14>;
                };
 
-               i2c@0x1e000 {
-                       compatible = "snps,designware-i2c";
+               i2s: i2s@1e000 {
+                       compatible = "snps,designware-i2s";
                        reg = <0x1e000 0x100>;
-                       clock-frequency = <400000>;
-                       clocks = <&i2cclk>;
+                       clocks = <&i2sclk 0>;
+                       clock-names = "i2sclk";
                        interrupts = <15>;
+                       #sound-dai-cells = <0>;
                };
 
                i2c@0x1f000 {
                                adi,input-colorspace = "rgb";
                                adi,input-clock = "1x";
                                adi,clock-delay = <0x03>;
+                               #sound-dai-cells = <0>;
 
                                ports {
                                        #address-cells = <1>;
                                };
                        };
                };
+
+               sound_playback {
+                       compatible = "simple-audio-card";
+                       simple-audio-card,name = "AXS10x HDMI Audio";
+                       simple-audio-card,format = "i2s";
+                       simple-audio-card,cpu {
+                               sound-dai = <&i2s>;
+                       };
+                       simple-audio-card,codec {
+                               sound-dai = <&adv7511>;
+                       };
+               };
        };
 };
index 5008021fba9894c0ba44251ddfd41a716d6c6cca..19ebddffb279db05ca8e53e2c4753665376cc9ad 100644 (file)
@@ -62,6 +62,8 @@ extern unsigned long perip_base, perip_end;
 #define ARC_REG_IC_BCR         0x77    /* Build Config reg */
 #define ARC_REG_IC_IVIC                0x10
 #define ARC_REG_IC_CTRL                0x11
+#define ARC_REG_IC_IVIR                0x16
+#define ARC_REG_IC_ENDR                0x17
 #define ARC_REG_IC_IVIL                0x19
 #define ARC_REG_IC_PTAG                0x1E
 #define ARC_REG_IC_PTAG_HI     0x1F
@@ -76,6 +78,8 @@ extern unsigned long perip_base, perip_end;
 #define ARC_REG_DC_IVDL                0x4A
 #define ARC_REG_DC_FLSH                0x4B
 #define ARC_REG_DC_FLDL                0x4C
+#define ARC_REG_DC_STARTR      0x4D
+#define ARC_REG_DC_ENDR                0x4E
 #define ARC_REG_DC_PTAG                0x5C
 #define ARC_REG_DC_PTAG_HI     0x5F
 
@@ -83,6 +87,8 @@ extern unsigned long perip_base, perip_end;
 #define DC_CTRL_DIS            0x001
 #define DC_CTRL_INV_MODE_FLUSH 0x040
 #define DC_CTRL_FLUSH_STATUS   0x100
+#define DC_CTRL_RGN_OP_INV     0x200
+#define DC_CTRL_RGN_OP_MSK     0x200
 
 /*System-level cache (L2 cache) related Auxiliary registers */
 #define ARC_REG_SLC_CFG                0x901
index b144d7ca7d2076d7f5a41b9bfa179f0f64d21d83..db7319e9b506e9ece826fde788aba60adada59cb 100644 (file)
@@ -9,6 +9,10 @@
 #ifndef _ASM_ARC_MMU_H
 #define _ASM_ARC_MMU_H
 
+#ifndef __ASSEMBLY__
+#include <linux/threads.h>     /* NR_CPUS */
+#endif
+
 #if defined(CONFIG_ARC_MMU_V1)
 #define CONFIG_ARC_MMU_VER 1
 #elif defined(CONFIG_ARC_MMU_V2)
index ee22d40afef43b37dec7d93f0f1ee87060607f93..08fe33830d4b17337757d548399c897aa240de36 100644 (file)
 #ifndef _ASM_ARC_PGTABLE_H
 #define _ASM_ARC_PGTABLE_H
 
-#include <asm/page.h>
-#include <asm/mmu.h>
+#include <linux/const.h>
 #define __ARCH_USE_5LEVEL_HACK
 #include <asm-generic/pgtable-nopmd.h>
-#include <linux/const.h>
+#include <asm/page.h>
+#include <asm/mmu.h>   /* to propagate CONFIG_ARC_MMU_VER <n> */
 
 /**************************************************************************
  * Page Table Flags
index f50d02df78d5ec94a9fc15bed9b44096fcbca5b1..b15bf6bc0e94f46f035e8781ffa921060341fe91 100644 (file)
@@ -1,5 +1,2 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
-header-y += elf.h
-header-y += page.h
-header-y += cachectl.h
index 0037a587320d51c4262e7c3b7b504a8dafb34ddc..06d95e611616a3f6ab884848f19cd065fb6a8680 100644 (file)
@@ -27,6 +27,7 @@ typedef unsigned long elf_greg_t;
 typedef unsigned long elf_fpregset_t;
 
 #define ELF_NGREG      (sizeof(struct user_regs_struct) / sizeof(elf_greg_t))
+#define ELF_ARCV2REG   (sizeof(struct user_regs_arcv2) / sizeof(elf_greg_t))
 
 typedef elf_greg_t elf_gregset_t[ELF_NGREG];
 
index 0b3ef63d4a03b3ef2ff119535ee3c020641e1888..dd206e6b482c11b2f605be711eb1ac8f9b2f9e47 100644 (file)
@@ -47,6 +47,11 @@ struct user_regs_struct {
        unsigned long efa;      /* break pt addr, for break points in delay slots */
        unsigned long stop_pc;  /* give dbg stop_pc after ensuring brkpt trap */
 };
+
+struct user_regs_arcv2 {
+       unsigned long r30, r58, r59;
+};
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* _UAPI__ASM_ARC_PTRACE_H */
index 31150060d38b41cf8191a3b8740c489a572d0fbc..5ee4676f135dee1d0bbc39d467e18281eb9cd1fe 100644 (file)
@@ -184,19 +184,75 @@ static int genregs_set(struct task_struct *target,
        return ret;
 }
 
+#ifdef CONFIG_ISA_ARCV2
+static int arcv2regs_get(struct task_struct *target,
+                      const struct user_regset *regset,
+                      unsigned int pos, unsigned int count,
+                      void *kbuf, void __user *ubuf)
+{
+       const struct pt_regs *regs = task_pt_regs(target);
+       int ret, copy_sz;
+
+       if (IS_ENABLED(CONFIG_ARC_HAS_ACCL_REGS))
+               copy_sz = sizeof(struct user_regs_arcv2);
+       else
+               copy_sz = 4;    /* r30 only */
+
+       /*
+        * itemized copy not needed like above as layout of regs (r30,r58,r59)
+        * is exactly same in kernel (pt_regs) and userspace (user_regs_arcv2)
+        */
+       ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, &regs->r30,
+                                 0, copy_sz);
+
+       return ret;
+}
+
+static int arcv2regs_set(struct task_struct *target,
+                      const struct user_regset *regset,
+                      unsigned int pos, unsigned int count,
+                      const void *kbuf, const void __user *ubuf)
+{
+       const struct pt_regs *regs = task_pt_regs(target);
+       int ret, copy_sz;
+
+       if (IS_ENABLED(CONFIG_ARC_HAS_ACCL_REGS))
+               copy_sz = sizeof(struct user_regs_arcv2);
+       else
+               copy_sz = 4;    /* r30 only */
+
+       ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, (void *)&regs->r30,
+                                 0, copy_sz);
+
+       return ret;
+}
+
+#endif
+
 enum arc_getset {
-       REGSET_GENERAL,
+       REGSET_CMN,
+       REGSET_ARCV2,
 };
 
 static const struct user_regset arc_regsets[] = {
-       [REGSET_GENERAL] = {
+       [REGSET_CMN] = {
               .core_note_type = NT_PRSTATUS,
               .n = ELF_NGREG,
               .size = sizeof(unsigned long),
               .align = sizeof(unsigned long),
               .get = genregs_get,
               .set = genregs_set,
-       }
+       },
+#ifdef CONFIG_ISA_ARCV2
+       [REGSET_ARCV2] = {
+              .core_note_type = NT_ARC_V2,
+              .n = ELF_ARCV2REG,
+              .size = sizeof(unsigned long),
+              .align = sizeof(unsigned long),
+              .get = arcv2regs_get,
+              .set = arcv2regs_set,
+       },
+#endif
 };
 
 static const struct user_regset_view user_arc_view = {
index b6e4f7a7419b3215d8b24103ee5a035ee50c96c7..333daab7def028761478b4215bf7f50335d4f05d 100644 (file)
@@ -845,7 +845,7 @@ static int processCFI(const u8 *start, const u8 *end, unsigned long targetLoc,
                                    * state->dataAlign;
                                break;
                        case DW_CFA_def_cfa_register:
-                               unw_debug("cfa_def_cfa_regsiter: ");
+                               unw_debug("cfa_def_cfa_register: ");
                                state->cfa.reg = get_uleb128(&ptr.p8, end);
                                break;
                                /*todo case DW_CFA_def_cfa_expression: */
index 928562967f3cd02fee4a5de34e687d442d64a4e0..a867575a758b9845c09a84fb4515f17f08f1272b 100644 (file)
 #include <asm/cachectl.h>
 #include <asm/setup.h>
 
+#ifdef CONFIG_ISA_ARCV2
+#define USE_RGN_FLSH   1
+#endif
+
 static int l2_line_sz;
 static int ioc_exists;
 int slc_enable = 1, ioc_enable = 1;
@@ -28,7 +32,7 @@ unsigned long perip_base = ARC_UNCACHED_ADDR_SPACE; /* legacy value for boot */
 unsigned long perip_end = 0xFFFFFFFF; /* legacy value */
 
 void (*_cache_line_loop_ic_fn)(phys_addr_t paddr, unsigned long vaddr,
-                              unsigned long sz, const int cacheop);
+                              unsigned long sz, const int op, const int full_page);
 
 void (*__dma_cache_wback_inv)(phys_addr_t start, unsigned long sz);
 void (*__dma_cache_inv)(phys_addr_t start, unsigned long sz);
@@ -233,11 +237,10 @@ slc_chk:
 
 static inline
 void __cache_line_loop_v2(phys_addr_t paddr, unsigned long vaddr,
-                         unsigned long sz, const int op)
+                         unsigned long sz, const int op, const int full_page)
 {
        unsigned int aux_cmd;
        int num_lines;
-       const int full_page = __builtin_constant_p(sz) && sz == PAGE_SIZE;
 
        if (op == OP_INV_IC) {
                aux_cmd = ARC_REG_IC_IVIL;
@@ -279,11 +282,10 @@ void __cache_line_loop_v2(phys_addr_t paddr, unsigned long vaddr,
  */
 static inline
 void __cache_line_loop_v3(phys_addr_t paddr, unsigned long vaddr,
-                         unsigned long sz, const int op)
+                         unsigned long sz, const int op, const int full_page)
 {
        unsigned int aux_cmd, aux_tag;
        int num_lines;
-       const int full_page = __builtin_constant_p(sz) && sz == PAGE_SIZE;
 
        if (op == OP_INV_IC) {
                aux_cmd = ARC_REG_IC_IVIL;
@@ -334,6 +336,8 @@ void __cache_line_loop_v3(phys_addr_t paddr, unsigned long vaddr,
        }
 }
 
+#ifndef USE_RGN_FLSH
+
 /*
  * In HS38x (MMU v4), I-cache is VIPT (can alias), D-cache is PIPT
  * Here's how cache ops are implemented
@@ -349,17 +353,16 @@ void __cache_line_loop_v3(phys_addr_t paddr, unsigned long vaddr,
  */
 static inline
 void __cache_line_loop_v4(phys_addr_t paddr, unsigned long vaddr,
-                         unsigned long sz, const int cacheop)
+                         unsigned long sz, const int op, const int full_page)
 {
        unsigned int aux_cmd;
        int num_lines;
-       const int full_page_op = __builtin_constant_p(sz) && sz == PAGE_SIZE;
 
-       if (cacheop == OP_INV_IC) {
+       if (op == OP_INV_IC) {
                aux_cmd = ARC_REG_IC_IVIL;
        } else {
                /* d$ cmd: INV (discard or wback-n-discard) OR FLUSH (wback) */
-               aux_cmd = cacheop & OP_INV ? ARC_REG_DC_IVDL : ARC_REG_DC_FLDL;
+               aux_cmd = op & OP_INV ? ARC_REG_DC_IVDL : ARC_REG_DC_FLDL;
        }
 
        /* Ensure we properly floor/ceil the non-line aligned/sized requests
@@ -368,7 +371,7 @@ void __cache_line_loop_v4(phys_addr_t paddr, unsigned long vaddr,
         *  -@paddr will be cache-line aligned already (being page aligned)
         *  -@sz will be integral multiple of line size (being page sized).
         */
-       if (!full_page_op) {
+       if (!full_page) {
                sz += paddr & ~CACHE_LINE_MASK;
                paddr &= CACHE_LINE_MASK;
        }
@@ -381,7 +384,7 @@ void __cache_line_loop_v4(phys_addr_t paddr, unsigned long vaddr,
         *   - (and needs to be written before the lower 32 bits)
         */
        if (is_pae40_enabled()) {
-               if (cacheop == OP_INV_IC)
+               if (op == OP_INV_IC)
                        /*
                         * Non aliasing I-cache in HS38,
                         * aliasing I-cache handled in __cache_line_loop_v3()
@@ -397,6 +400,55 @@ void __cache_line_loop_v4(phys_addr_t paddr, unsigned long vaddr,
        }
 }
 
+#else
+
+/*
+ * optimized flush operation which takes a region as opposed to iterating per line
+ */
+static inline
+void __cache_line_loop_v4(phys_addr_t paddr, unsigned long vaddr,
+                         unsigned long sz, const int op, const int full_page)
+{
+       unsigned int s, e;
+
+       /* Only for Non aliasing I-cache in HS38 */
+       if (op == OP_INV_IC) {
+               s = ARC_REG_IC_IVIR;
+               e = ARC_REG_IC_ENDR;
+       } else {
+               s = ARC_REG_DC_STARTR;
+               e = ARC_REG_DC_ENDR;
+       }
+
+       if (!full_page) {
+               /* for any leading gap between @paddr and start of cache line */
+               sz += paddr & ~CACHE_LINE_MASK;
+               paddr &= CACHE_LINE_MASK;
+
+               /*
+                *  account for any trailing gap to end of cache line
+                *  this is equivalent to DIV_ROUND_UP() in line ops above
+                */
+               sz += L1_CACHE_BYTES - 1;
+       }
+
+       if (is_pae40_enabled()) {
+               /* TBD: check if crossing 4TB boundary */
+               if (op == OP_INV_IC)
+                       write_aux_reg(ARC_REG_IC_PTAG_HI, (u64)paddr >> 32);
+               else
+                       write_aux_reg(ARC_REG_DC_PTAG_HI, (u64)paddr >> 32);
+       }
+
+       /* ENDR needs to be set ahead of START */
+       write_aux_reg(e, paddr + sz);   /* ENDR is exclusive */
+       write_aux_reg(s, paddr);
+
+       /* caller waits on DC_CTRL.FS */
+}
+
+#endif
+
 #if (CONFIG_ARC_MMU_VER < 3)
 #define __cache_line_loop      __cache_line_loop_v2
 #elif (CONFIG_ARC_MMU_VER == 3)
@@ -411,6 +463,11 @@ void __cache_line_loop_v4(phys_addr_t paddr, unsigned long vaddr,
  * Machine specific helpers for Entire D-Cache or Per Line ops
  */
 
+#ifndef USE_RGN_FLSH
+/*
+ * this version avoids extra read/write of DC_CTRL for flush or invalid ops
+ * in the non region flush regime (such as for ARCompact)
+ */
 static inline void __before_dc_op(const int op)
 {
        if (op == OP_FLUSH_N_INV) {
@@ -424,6 +481,32 @@ static inline void __before_dc_op(const int op)
        }
 }
 
+#else
+
+static inline void __before_dc_op(const int op)
+{
+       const unsigned int ctl = ARC_REG_DC_CTRL;
+       unsigned int val = read_aux_reg(ctl);
+
+       if (op == OP_FLUSH_N_INV) {
+               val |= DC_CTRL_INV_MODE_FLUSH;
+       }
+
+       if (op != OP_INV_IC) {
+               /*
+                * Flush / Invalidate is provided by DC_CTRL.RNG_OP 0 or 1
+                * combined Flush-n-invalidate uses DC_CTRL.IM = 1 set above
+                */
+               val &= ~DC_CTRL_RGN_OP_MSK;
+               if (op & OP_INV)
+                       val |= DC_CTRL_RGN_OP_INV;
+       }
+       write_aux_reg(ctl, val);
+}
+
+#endif
+
+
 static inline void __after_dc_op(const int op)
 {
        if (op & OP_FLUSH) {
@@ -486,13 +569,14 @@ static void __dc_enable(void)
 static inline void __dc_line_op(phys_addr_t paddr, unsigned long vaddr,
                                unsigned long sz, const int op)
 {
+       const int full_page = __builtin_constant_p(sz) && sz == PAGE_SIZE;
        unsigned long flags;
 
        local_irq_save(flags);
 
        __before_dc_op(op);
 
-       __cache_line_loop(paddr, vaddr, sz, op);
+       __cache_line_loop(paddr, vaddr, sz, op, full_page);
 
        __after_dc_op(op);
 
@@ -521,10 +605,11 @@ static inline void
 __ic_line_inv_vaddr_local(phys_addr_t paddr, unsigned long vaddr,
                          unsigned long sz)
 {
+       const int full_page = __builtin_constant_p(sz) && sz == PAGE_SIZE;
        unsigned long flags;
 
        local_irq_save(flags);
-       (*_cache_line_loop_ic_fn)(paddr, vaddr, sz, OP_INV_IC);
+       (*_cache_line_loop_ic_fn)(paddr, vaddr, sz, OP_INV_IC, full_page);
        local_irq_restore(flags);
 }
 
index 4c6816be23a923ac1ad23b7769851da3f2f2bb5e..4c1a35f1583872d2ce39db5c1cacce28be48ccb1 100644 (file)
@@ -359,15 +359,6 @@ config ARM_SINGLE_ARMV7M
        select SPARSE_IRQ
        select USE_OF
 
-config ARCH_GEMINI
-       bool "Cortina Systems Gemini"
-       select CLKSRC_MMIO
-       select CPU_FA526
-       select GENERIC_CLOCKEVENTS
-       select GPIOLIB
-       help
-         Support for the Cortina Systems Gemini family SoCs
-
 config ARCH_EBSA110
        bool "EBSA-110"
        select ARCH_USES_GETTIMEOFFSET
@@ -819,6 +810,8 @@ source "arch/arm/mach-spear/Kconfig"
 
 source "arch/arm/mach-sti/Kconfig"
 
+source "arch/arm/mach-stm32/Kconfig"
+
 source "arch/arm/mach-s3c24xx/Kconfig"
 
 source "arch/arm/mach-s3c64xx/Kconfig"
@@ -877,28 +870,6 @@ config ARCH_LPC18XX
          Support for NXP's LPC18xx Cortex-M3 and LPC43xx Cortex-M4
          high performance microcontrollers.
 
-config ARCH_STM32
-       bool "STMicrolectronics STM32"
-       depends on ARM_SINGLE_ARMV7M
-       select ARCH_HAS_RESET_CONTROLLER
-       select ARMV7M_SYSTICK
-       select CLKSRC_STM32
-       select PINCTRL
-       select RESET_CONTROLLER
-       select STM32_EXTI
-       help
-         Support for STMicroelectronics STM32 processors.
-
-config MACH_STM32F429
-       bool "STMicrolectronics STM32F429"
-       depends on ARCH_STM32
-       default y
-
-config MACH_STM32F746
-       bool "STMicrolectronics STM32F746"
-       depends on ARCH_STM32
-       default y
-
 config ARCH_MPS2
        bool "ARM MPS2 platform"
        depends on ARM_SINGLE_ARMV7M
index ab30cc634d024fdb17b379adac2f2d9fe049f1ff..65f4e2a4eb94df1351f0e8e746440b1867c4ae2c 100644 (file)
@@ -297,10 +297,11 @@ drivers-$(CONFIG_OPROFILE)      += arch/arm/oprofile/
 libs-y                         := arch/arm/lib/ $(libs-y)
 
 # Default target when executing plain make
+boot := arch/arm/boot
 ifeq ($(CONFIG_XIP_KERNEL),y)
-KBUILD_IMAGE := xipImage
+KBUILD_IMAGE := $(boot)/xipImage
 else
-KBUILD_IMAGE := zImage
+KBUILD_IMAGE := $(boot)/zImage
 endif
 
 # Build the DT binary blobs if we have OF configured
@@ -308,9 +309,8 @@ ifeq ($(CONFIG_USE_OF),y)
 KBUILD_DTBS := dtbs
 endif
 
-all:   $(KBUILD_IMAGE) $(KBUILD_DTBS)
+all:   $(notdir $(KBUILD_IMAGE)) $(KBUILD_DTBS)
 
-boot := arch/arm/boot
 
 archheaders:
        $(Q)$(MAKE) $(build)=arch/arm/tools uapi
index 011808490fed73ee3bc676f96449411119983b0d..9c5e1d944d1c714f0fcd49cfd1614e7957f0bd52 100644 (file)
@@ -77,6 +77,7 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \
        bcm4708-asus-rt-ac56u.dtb \
        bcm4708-asus-rt-ac68u.dtb \
        bcm4708-buffalo-wzr-1750dhp.dtb \
+       bcm4708-linksys-ea6300-v1.dtb \
        bcm4708-luxul-xap-1510.dtb \
        bcm4708-luxul-xwc-1000.dtb \
        bcm4708-netgear-r6250.dtb \
@@ -87,17 +88,21 @@ dtb-$(CONFIG_ARCH_BCM_5301X) += \
        bcm47081-buffalo-wzr-900dhp.dtb \
        bcm47081-luxul-xap-1410.dtb \
        bcm47081-luxul-xwr-1200.dtb \
+       bcm47081-tplink-archer-c5-v2.dtb \
        bcm4709-asus-rt-ac87u.dtb \
        bcm4709-buffalo-wxr-1900dhp.dtb \
+       bcm4709-linksys-ea9200.dtb \
        bcm4709-netgear-r7000.dtb \
        bcm4709-netgear-r8000.dtb \
        bcm4709-tplink-archer-c9-v1.dtb \
        bcm47094-dlink-dir-885l.dtb \
+       bcm47094-linksys-panamera.dtb \
        bcm47094-luxul-xwr-3100.dtb \
        bcm47094-netgear-r8500.dtb \
        bcm94708.dtb \
        bcm94709.dtb \
        bcm953012er.dtb \
+       bcm953012hr.dtb \
        bcm953012k.dtb
 dtb-$(CONFIG_ARCH_BCM_53573) += \
        bcm47189-tenda-ac9.dtb
@@ -173,6 +178,12 @@ dtb-$(CONFIG_ARCH_EXYNOS5) += \
        exynos5440-sd5v1.dtb \
        exynos5440-ssdk5440.dtb \
        exynos5800-peach-pi.dtb
+dtb-$(CONFIG_ARCH_GEMINI) += \
+       gemini-nas4220b.dtb \
+       gemini-rut1xx.dtb \
+       gemini-sq201.dtb \
+       gemini-wbd111.dtb \
+       gemini-wbd222.dtb
 dtb-$(CONFIG_ARCH_HI3xxx) += \
        hi3620-hi4511.dtb
 dtb-$(CONFIG_ARCH_HIGHBANK) += \
@@ -352,6 +363,8 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
        imx6dl-gw551x.dtb \
        imx6dl-gw552x.dtb \
        imx6dl-gw553x.dtb \
+       imx6dl-gw5903.dtb \
+       imx6dl-gw5904.dtb \
        imx6dl-hummingboard.dtb \
        imx6dl-icore.dtb \
        imx6dl-icore-rqs.dtb \
@@ -395,9 +408,13 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
        imx6q-gw551x.dtb \
        imx6q-gw552x.dtb \
        imx6q-gw553x.dtb \
+       imx6q-gw5903.dtb \
+       imx6q-gw5904.dtb \
        imx6q-h100.dtb \
        imx6q-hummingboard.dtb \
        imx6q-icore.dtb \
+       imx6q-icore-ofcap10.dtb \
+       imx6q-icore-ofcap12.dtb \
        imx6q-icore-rqs.dtb \
        imx6q-marsboard.dtb \
        imx6q-mccmon6.dtb \
@@ -425,9 +442,12 @@ dtb-$(CONFIG_SOC_IMX6Q) += \
        imx6q-utilite-pro.dtb \
        imx6q-wandboard.dtb \
        imx6q-wandboard-revb1.dtb \
+       imx6q-zii-rdu2.dtb \
        imx6qp-nitrogen6_max.dtb \
+       imx6qp-nitrogen6_som2.dtb \
        imx6qp-sabreauto.dtb \
-       imx6qp-sabresd.dtb
+       imx6qp-sabresd.dtb \
+       imx6qp-zii-rdu2.dtb
 dtb-$(CONFIG_SOC_IMX6SL) += \
        imx6sl-evk.dtb \
        imx6sl-warp.dtb
@@ -458,6 +478,7 @@ dtb-$(CONFIG_SOC_IMX7D) += \
        imx7d-nitrogen7.dtb \
        imx7d-sbc-imx7.dtb \
        imx7d-sdb.dtb \
+       imx7d-sdb-sht11.dtb \
        imx7s-colibri-eval-v3.dtb \
        imx7s-warp.dtb
 dtb-$(CONFIG_SOC_LS1021A) += \
@@ -488,6 +509,10 @@ dtb-$(CONFIG_ARCH_MXS) += \
        imx28-cfa10056.dtb \
        imx28-cfa10057.dtb \
        imx28-cfa10058.dtb \
+       imx28-duckbill-2-485.dtb \
+       imx28-duckbill-2.dtb \
+       imx28-duckbill-2-enocean.dtb \
+       imx28-duckbill-2-spi.dtb \
        imx28-duckbill.dtb \
        imx28-eukrea-mbmx283lc.dtb \
        imx28-eukrea-mbmx287lc.dtb \
@@ -673,6 +698,25 @@ dtb-$(CONFIG_ARCH_REALVIEW) += \
        arm-realview-eb-a9mp-bbrevd.dtb \
        arm-realview-pba8.dtb \
        arm-realview-pbx-a9.dtb
+dtb-$(CONFIG_ARCH_RENESAS) += \
+       emev2-kzm9d.dtb \
+       r7s72100-genmai.dtb \
+       r7s72100-rskrza1.dtb \
+       r8a73a4-ape6evm.dtb \
+       r8a7740-armadillo800eva.dtb \
+       r8a7743-sk-rzg1m.dtb \
+       r8a7745-sk-rzg1e.dtb \
+       r8a7778-bockw.dtb \
+       r8a7779-marzen.dtb \
+       r8a7790-lager.dtb \
+       r8a7791-koelsch.dtb \
+       r8a7791-porter.dtb \
+       r8a7792-blanche.dtb \
+       r8a7792-wheat.dtb \
+       r8a7793-gose.dtb \
+       r8a7794-alt.dtb \
+       r8a7794-silk.dtb \
+       sh73a0-kzm9g.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += \
        rk1108-evb.dtb \
        rk3036-evb.dtb \
@@ -692,9 +736,11 @@ dtb-$(CONFIG_ARCH_ROCKCHIP) += \
        rk3288-firefly.dtb \
        rk3288-firefly-reload.dtb \
        rk3288-miqi.dtb \
+       rk3288-phycore-rdk.dtb \
        rk3288-popmetal.dtb \
        rk3288-r89.dtb \
        rk3288-rock2-square.dtb \
+       rk3288-tinker.dtb \
        rk3288-veyron-brain.dtb \
        rk3288-veyron-jaq.dtb \
        rk3288-veyron-jerry.dtb \
@@ -713,25 +759,6 @@ dtb-$(CONFIG_ARCH_S5PV210) += \
        s5pv210-smdkc110.dtb \
        s5pv210-smdkv210.dtb \
        s5pv210-torbreck.dtb
-dtb-$(CONFIG_ARCH_SHMOBILE_MULTI) += \
-       emev2-kzm9d.dtb \
-       r7s72100-genmai.dtb \
-       r7s72100-rskrza1.dtb \
-       r8a73a4-ape6evm.dtb \
-       r8a7740-armadillo800eva.dtb \
-       r8a7743-sk-rzg1m.dtb \
-       r8a7745-sk-rzg1e.dtb \
-       r8a7778-bockw.dtb \
-       r8a7779-marzen.dtb \
-       r8a7790-lager.dtb \
-       r8a7791-koelsch.dtb \
-       r8a7791-porter.dtb \
-       r8a7792-blanche.dtb \
-       r8a7792-wheat.dtb \
-       r8a7793-gose.dtb \
-       r8a7794-alt.dtb \
-       r8a7794-silk.dtb \
-       sh73a0-kzm9g.dtb
 dtb-$(CONFIG_ARCH_SOCFPGA) += \
        socfpga_arria5_socdk.dtb \
        socfpga_arria10_socdk_nand.dtb \
@@ -764,7 +791,8 @@ dtb-$(CONFIG_ARCH_STM32)+= \
        stm32f429-disco.dtb \
        stm32f469-disco.dtb \
        stm32429i-eval.dtb \
-       stm32746g-eval.dtb
+       stm32746g-eval.dtb \
+       stm32h743i-eval.dtb
 dtb-$(CONFIG_MACH_SUN4I) += \
        sun4i-a10-a1000.dtb \
        sun4i-a10-ba10-tvbox.dtb \
@@ -868,6 +896,7 @@ dtb-$(CONFIG_MACH_SUN8I) += \
        sun8i-h3-beelink-x2.dtb \
        sun8i-h3-nanopi-m1.dtb  \
        sun8i-h3-nanopi-neo.dtb \
+       sun8i-h3-nanopi-neo-air.dtb \
        sun8i-h3-orangepi-2.dtb \
        sun8i-h3-orangepi-lite.dtb \
        sun8i-h3-orangepi-one.dtb \
@@ -970,6 +999,8 @@ dtb-$(CONFIG_MACH_ARMADA_38X) += \
        armada-385-db-ap.dtb \
        armada-385-linksys-caiman.dtb \
        armada-385-linksys-cobra.dtb \
+       armada-385-linksys-shelby.dtb \
+       armada-385-synology-ds116.dtb \
        armada-385-turris-omnia.dtb \
        armada-388-clearfog.dtb \
        armada-388-clearfog-base.dtb \
index d0eefc3b886c2a55ff2664b917499cefc2653aaf..731df7a8c4e618ba1b7a37502515876180da82a8 100644 (file)
                        compatible = "arm,cortex-a15";
                        device_type = "cpu";
                        reg = <0>;
-                       clock-frequency = <0>; /* Filled by loader */
+                       clock-frequency = <1700000000>;
                };
 
                cpu@1 {
                        compatible = "arm,cortex-a15";
                        device_type = "cpu";
                        reg = <1>;
-                       clock-frequency = <0>; /* Filled by loader */
+                       clock-frequency = <1700000000>;
                };
 
                cpu@2 {
                        compatible = "arm,cortex-a15";
                        device_type = "cpu";
                        reg = <2>;
-                       clock-frequency = <0>; /* Filled by loader */
+                       clock-frequency = <1700000000>;
                };
 
                cpu@3 {
                        compatible = "arm,cortex-a15";
                        device_type = "cpu";
                        reg = <3>;
-                       clock-frequency = <0>; /* Filled by loader */
+                       clock-frequency = <1700000000>;
                };
        };
 
@@ -81,7 +81,7 @@
                                <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
                                <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
                                <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
-                       clock-frequency = <0>; /* Filled by loader */
+                       clock-frequency = <50000000>;
                };
 
                /* Interrupt Controller */
                                     <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
                };
 
-               uart0:uart@fd883000 {
+               uart0: uart@fd883000 {
                        compatible = "ns16550a";
                        reg = <0x0 0xfd883000 0x0 0x1000>;
-                       clock-frequency = <0>; /* Filled by loader */
+                       clock-frequency = <375000000>;
                        interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
                };
 
-               uart1:uart@0xfd884000 {
+               uart1: uart@fd884000 {
                        compatible = "ns16550a";
                        reg = <0x0 0xfd884000 0x0 0x1000>;
-                       clock-frequency = <0>; /* Filled by loader */
+                       clock-frequency = <375000000>;
                        interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
                };
 
                /* Internal PCIe Controller */
-               pcie-internal@0xfbc00000 {
+               pcie@fbc00000 {
                        compatible = "pci-host-ecam-generic";
                        device_type = "pci";
                        #size-cells = <2>;
index 501c7527121b284d46883a3eab88e7085496745d..75de1e723303752eedccedd24fe0da637f0d2e37 100644 (file)
@@ -14,6 +14,7 @@
 /dts-v1/;
 
 #include "am335x-baltos.dtsi"
+#include "am335x-baltos-leds.dtsi"
 
 / {
        model = "OnRISC Baltos iR 2110";
index 19f53b8569e1c9411dc43b7639d61e080ec40438..46df1b22022c75d811fe7d3af920a3fef95f6af6 100644 (file)
@@ -14,6 +14,7 @@
 /dts-v1/;
 
 #include "am335x-baltos.dtsi"
+#include "am335x-baltos-leds.dtsi"
 
 / {
        model = "OnRISC Baltos iR 3220";
index 2b9d7f4db23f0fa44c14e867f197db5034ae9261..5d56355ba04067acb1f772f3e79048fb21cd87f3 100644 (file)
@@ -14,6 +14,7 @@
 /dts-v1/;
 
 #include "am335x-baltos.dtsi"
+#include "am335x-baltos-leds.dtsi"
 
 / {
        model = "OnRISC Baltos iR 5221";
diff --git a/arch/arm/boot/dts/am335x-baltos-leds.dtsi b/arch/arm/boot/dts/am335x-baltos-leds.dtsi
new file mode 100644 (file)
index 0000000..3ab1767
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/*
+ * VScom OnRISC
+ * http://www.vscom.de
+ */
+
+/*#include "am33xx.dtsi"*/
+
+/ {
+       leds {
+               pinctrl-names = "default";
+               pinctrl-0 = <&user_leds>;
+
+               compatible = "gpio-leds";
+
+               power {
+                       label = "onrisc:red:power";
+                       linux,default-trigger = "default-on";
+                       gpios = <&gpio3 0 GPIO_ACTIVE_LOW>;
+                       default-state = "on";
+               };
+               wlan {
+                       label = "onrisc:blue:wlan";
+                       gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>;
+                       default-state = "off";
+               };
+               app {
+                       label = "onrisc:green:app";
+                       gpios = <&gpio0 17 GPIO_ACTIVE_HIGH>;
+                       default-state = "off";
+               };
+       };
+};
+
+&am33xx_pinmux {
+       user_leds: pinmux_user_leds {
+               pinctrl-single,pins = <
+                       AM33XX_IOPAD(0x908, PIN_OUTPUT_PULLDOWN | MUX_MODE7)    /* mii1_col.gpio3_0 PWR LED */
+                       AM33XX_IOPAD(0x91c, PIN_OUTPUT_PULLDOWN | MUX_MODE7)    /* mii1_txd3.gpio0_16 WLAN LED */
+                       AM33XX_IOPAD(0x920, PIN_OUTPUT_PULLDOWN | MUX_MODE7)    /* mii1_txd2.gpio0_17 APP LED */
+               >;
+       };
+};
index 77273df1a02814ba55a889b1cccbd1e51ba2b2c2..935ed17d22e4624c767ae42394d3ebbe21a8076c 100644 (file)
        model = "TI AM335x BeagleBone Black";
        compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
 };
+
+&cpu0_opp_table {
+       /*
+        * All PG 2.0 silicon may not support 1GHz but some of the early
+        * BeagleBone Blacks have PG 2.0 silicon which is guaranteed
+        * to support 1GHz OPP so enable it for PG 2.0 on this board.
+        */
+       oppnitro@1000000000 {
+               opp-supported-hw = <0x06 0x0100>;
+       };
+};
index a2ad076822db8b54cd03c6f94a20d5419dafa1f2..f2005ecca74fb545ced3e438eb53cb8ea5733a9b 100644 (file)
                        AM33XX_IOPAD(0x938, PIN_OUTPUT_PULLUP | MUX_MODE1) /* (L16) gmii1_rxd2.uart3_txd */
                >;
        };
+
+       cpsw_default: cpsw_default {
+               pinctrl-single,pins = <
+                       /* Slave 1, RMII mode */
+                       AM33XX_IOPAD(0x90c, (PIN_INPUT_PULLUP | MUX_MODE1))     /* mii1_crs.rmii1_crs_dv */
+                       AM33XX_IOPAD(0x944, (PIN_INPUT_PULLUP | MUX_MODE0))     /* rmii1_refclk.rmii1_refclk */
+                       AM33XX_IOPAD(0x940, (PIN_INPUT_PULLUP | MUX_MODE1))     /* mii1_rxd0.rmii1_rxd0 */
+                       AM33XX_IOPAD(0x93c, (PIN_INPUT_PULLUP | MUX_MODE1))     /* mii1_rxd1.rmii1_rxd1 */
+                       AM33XX_IOPAD(0x910, (PIN_INPUT_PULLUP | MUX_MODE1))     /* mii1_rxerr.rmii1_rxerr */
+                       AM33XX_IOPAD(0x928, (PIN_OUTPUT_PULLDOWN | MUX_MODE1))  /* mii1_txd0.rmii1_txd0 */
+                       AM33XX_IOPAD(0x924, (PIN_OUTPUT_PULLDOWN | MUX_MODE1))  /* mii1_txd1.rmii1_txd1 */
+                       AM33XX_IOPAD(0x914, (PIN_OUTPUT_PULLDOWN | MUX_MODE1))  /* mii1_txen.rmii1_txen */
+                       /* Slave 2, RMII mode */
+                       AM33XX_IOPAD(0x870, (PIN_INPUT_PULLUP | MUX_MODE3))     /* gpmc_wait0.rmii2_crs_dv */
+                       AM33XX_IOPAD(0x908, (PIN_INPUT_PULLUP | MUX_MODE1))     /* mii1_col.rmii2_refclk */
+                       AM33XX_IOPAD(0x86c, (PIN_INPUT_PULLUP | MUX_MODE3))     /* gpmc_a11.rmii2_rxd0 */
+                       AM33XX_IOPAD(0x868, (PIN_INPUT_PULLUP | MUX_MODE3))     /* gpmc_a10.rmii2_rxd1 */
+                       AM33XX_IOPAD(0x874, (PIN_INPUT_PULLUP | MUX_MODE3))     /* gpmc_wpn.rmii2_rxerr */
+                       AM33XX_IOPAD(0x854, (PIN_OUTPUT_PULLDOWN | MUX_MODE3))  /* gpmc_a5.rmii2_txd0 */
+                       AM33XX_IOPAD(0x850, (PIN_OUTPUT_PULLDOWN | MUX_MODE3))  /* gpmc_a4.rmii2_txd1 */
+                       AM33XX_IOPAD(0x840, (PIN_OUTPUT_PULLDOWN | MUX_MODE3))  /* gpmc_a0.rmii2_txen */
+               >;
+       };
+
+       cpsw_sleep: cpsw_sleep {
+               pinctrl-single,pins = <
+                       /* Slave 1 reset value */
+                       AM33XX_IOPAD(0x90c, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+                       AM33XX_IOPAD(0x944, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+                       AM33XX_IOPAD(0x940, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+                       AM33XX_IOPAD(0x93c, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+                       AM33XX_IOPAD(0x910, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+                       AM33XX_IOPAD(0x928, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+                       AM33XX_IOPAD(0x924, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+                       AM33XX_IOPAD(0x914, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+
+                       /* Slave 2 reset value */
+                       AM33XX_IOPAD(0x870, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+                       AM33XX_IOPAD(0x908, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+                       AM33XX_IOPAD(0x86c, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+                       AM33XX_IOPAD(0x868, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+                       AM33XX_IOPAD(0x874, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+                       AM33XX_IOPAD(0x854, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+                       AM33XX_IOPAD(0x850, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+                       AM33XX_IOPAD(0x840, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+               >;
+       };
+
+       davinci_mdio_default: davinci_mdio_default {
+               pinctrl-single,pins = <
+                       /* MDIO */
+                       AM33XX_IOPAD(0x948, (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0))     /* mdio_data.mdio_data */
+                       AM33XX_IOPAD(0x94c, (PIN_OUTPUT_PULLUP | MUX_MODE0))                    /* mdio_clk.mdio_clk */
+               >;
+       };
+
+       davinci_mdio_sleep: davinci_mdio_sleep {
+               pinctrl-single,pins = <
+                       /* MDIO reset value */
+                       AM33XX_IOPAD(0x948, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+                       AM33XX_IOPAD(0x94c, (PIN_INPUT_PULLDOWN | MUX_MODE7))
+               >;
+       };
 };
 
 &i2c0 {
                spi-max-frequency = <1000000>;
                spi-cpol;
        };
+
+       spi_nor: flash@0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "winbond,w25q64", "jedec,spi-nor";
+               spi-max-frequency = <80000000>;
+               m25p,fast-read;
+               reg = <0>;
+
+               partition@0 {
+                       label = "u-boot-spl";
+                       reg = <0x0 0x80000>;
+                       read-only;
+               };
+
+               partition@1 {
+                       label = "u-boot";
+                       reg = <0x80000 0x100000>;
+                       read-only;
+               };
+
+               partition@2 {
+                       label = "u-boot-env";
+                       reg = <0x180000 0x20000>;
+                       read-only;
+               };
+
+               partition@3 {
+                       label = "misc";
+                       reg = <0x1A0000 0x660000>;
+               };
+       };
+
 };
 
 &tscadc {
        pinctrl-0 = <&uart3_pins_default>;
        status = "okay";
 };
+
+&gpio3 {
+       p4 {
+               gpio-hog;
+               gpios = <4 GPIO_ACTIVE_HIGH>;
+               output-high;
+               line-name = "PR1_MII_CTRL";
+       };
+
+       p10 {
+               gpio-hog;
+               gpios = <10 GPIO_ACTIVE_HIGH>;
+               /* ETH1 mux: Low for MII-PRU, high for RMII-CPSW */
+               output-high;
+               line-name = "MUX_MII_CTL1";
+       };
+};
+
+&cpsw_emac0 {
+       phy-handle = <&ethphy0>;
+       phy-mode = "rmii";
+       dual_emac_res_vlan = <1>;
+};
+
+&cpsw_emac1 {
+       phy-handle = <&ethphy1>;
+       phy-mode = "rmii";
+       dual_emac_res_vlan = <2>;
+};
+
+&mac {
+       pinctrl-names = "default", "sleep";
+       pinctrl-0 = <&cpsw_default>;
+       pinctrl-1 = <&cpsw_sleep>;
+       status = "okay";
+       dual_emac;
+};
+
+&phy_sel {
+       rmii-clock-ext;
+};
+
+&davinci_mdio {
+       pinctrl-names = "default", "sleep";
+       pinctrl-0 = <&davinci_mdio_default>;
+       pinctrl-1 = <&davinci_mdio_sleep>;
+       status = "okay";
+       reset-gpios = <&gpio2 5 GPIO_ACTIVE_LOW>;
+       reset-delay-us = <2>;   /* PHY datasheet states 1uS min */
+
+       ethphy0: ethernet-phy@1 {
+               reg = <1>;
+       };
+
+       ethphy1: ethernet-phy@3 {
+               reg = <3>;
+       };
+};
index 9e96d60976b77a2b80056ec05cf6d75068a146fa..9e242943dcecf1664a3dfadfbdca6d32e33db2fb 100644 (file)
                        device_type = "cpu";
                        reg = <0>;
 
-                       /*
-                        * To consider voltage drop between PMIC and SoC,
-                        * tolerance value is reduced to 2% from 4% and
-                        * voltage value is increased as a precaution.
-                        */
-                       operating-points = <
-                               /* kHz    uV */
-                               720000  1285000
-                               600000  1225000
-                               500000  1125000
-                               275000  1125000
-                       >;
-                       voltage-tolerance = <2>; /* 2 percentage */
+                       operating-points-v2 = <&cpu0_opp_table>;
 
                        clocks = <&dpll_mpu_ck>;
                        clock-names = "cpu";
                };
        };
 
+       cpu0_opp_table: opp-table {
+               compatible = "operating-points-v2-ti-cpu";
+               syscon = <&scm_conf>;
+
+               /*
+                * The three following nodes are marked with opp-suspend
+                * because the can not be enabled simultaneously on a
+                * single SoC.
+                */
+               opp50@300000000 {
+                       opp-hz = /bits/ 64 <300000000>;
+                       opp-microvolt = <950000 931000 969000>;
+                       opp-supported-hw = <0x06 0x0010>;
+                       opp-suspend;
+               };
+
+               opp100@275000000 {
+                       opp-hz = /bits/ 64 <275000000>;
+                       opp-microvolt = <1100000 1078000 1122000>;
+                       opp-supported-hw = <0x01 0x00FF>;
+                       opp-suspend;
+               };
+
+               opp100@300000000 {
+                       opp-hz = /bits/ 64 <300000000>;
+                       opp-microvolt = <1100000 1078000 1122000>;
+                       opp-supported-hw = <0x06 0x0020>;
+                       opp-suspend;
+               };
+
+               opp100@500000000 {
+                       opp-hz = /bits/ 64 <500000000>;
+                       opp-microvolt = <1100000 1078000 1122000>;
+                       opp-supported-hw = <0x01 0xFFFF>;
+               };
+
+               opp100@600000000 {
+                       opp-hz = /bits/ 64 <600000000>;
+                       opp-microvolt = <1100000 1078000 1122000>;
+                       opp-supported-hw = <0x06 0x0040>;
+               };
+
+               opp120@600000000 {
+                       opp-hz = /bits/ 64 <600000000>;
+                       opp-microvolt = <1200000 1176000 1224000>;
+                       opp-supported-hw = <0x01 0xFFFF>;
+               };
+
+               opp120@720000000 {
+                       opp-hz = /bits/ 64 <720000000>;
+                       opp-microvolt = <1200000 1176000 1224000>;
+                       opp-supported-hw = <0x06 0x0080>;
+               };
+
+               oppturbo@720000000 {
+                       opp-hz = /bits/ 64 <720000000>;
+                       opp-microvolt = <1260000 1234800 1285200>;
+                       opp-supported-hw = <0x01 0xFFFF>;
+               };
+
+               oppturbo@800000000 {
+                       opp-hz = /bits/ 64 <800000000>;
+                       opp-microvolt = <1260000 1234800 1285200>;
+                       opp-supported-hw = <0x06 0x0100>;
+               };
+
+               oppnitro@1000000000 {
+                       opp-hz = /bits/ 64 <1000000000>;
+                       opp-microvolt = <1325000 1298500 1351500>;
+                       opp-supported-hw = <0x04 0x0200>;
+               };
+       };
+
        pmu {
                compatible = "arm,cortex-a8-pmu";
                interrupts = <3>;
index 9fe545dbfa89bb446b553506eb16bd51c4cc0f5f..00da3f2c4072d4d6a3a370e88b1acfa046b58efd 100644 (file)
@@ -13,6 +13,7 @@
 / {
        aliases {
                serial3 = &uart4;
+               can = &hecc;
        };
 
        ocp@68000000 {
                        pinctrl-single,register-width = <16>;
                        pinctrl-single,function-mask = <0xff1f>;
                };
+
+               hecc: can@5c050000 {
+                       compatible = "ti,am3517-hecc";
+                       status = "disabled";
+                       reg = <0x5c050000 0x80>,
+                             <0x5c053000 0x180>,
+                             <0x5c052000 0x200>;
+                       reg-names = "hecc", "hecc-ram", "mbx";
+                       interrupts = <24>;
+                       clocks = <&hecc_ck>;
+               };
        };
 };
 
index 97fcaf415de1858267cf57c1f60c07638b4c7129..176e09e9a45eef97e5512608d95f30545bc7b84d 100644 (file)
                        clock-names = "cpu";
 
                        operating-points-v2 = <&cpu0_opp_table>;
-                       ti,syscon-efuse = <&scm_conf 0x610 0x3f 0>;
-                       ti,syscon-rev = <&scm_conf 0x600>;
 
                        clock-latency = <300000>; /* From omap-cpufreq driver */
                };
        };
 
-       cpu0_opp_table: opp_table0 {
-               compatible = "operating-points-v2";
+       cpu0_opp_table: opp-table {
+               compatible = "operating-points-v2-ti-cpu";
+               syscon = <&scm_conf>;
 
                opp50@300000000 {
                        opp-hz = /bits/ 64 <300000000>;
index a4f31739057f3640153f9d6d977204762322aba4..397e98b7e246ae0a45a280a867583c35f064020f 100644 (file)
                        AM4372_IOPAD(0x884, PIN_INPUT_PULLDOWN | MUX_MODE7) /* gpmc_csn2.gpio1_31 */
                >;
        };
+
+       uart0_pins_default: uart0_pins_default {
+               pinctrl-single,pins = <
+                       AM4372_IOPAD(0x968, PIN_INPUT | MUX_MODE0)              /* uart0_ctsn.uart0_ctsn */
+                       AM4372_IOPAD(0x96C, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* uart0_rtsn.uart0_rtsn */
+                       AM4372_IOPAD(0x970, PIN_INPUT_PULLUP | MUX_MODE0)       /* uart0_rxd.uart0_rxd */
+                       AM4372_IOPAD(0x974, PIN_OUTPUT_PULLDOWN | MUX_MODE0)    /* uart0_txd.uart0_txd */
+               >;
+       };
+};
+
+&uart0 {
+       status = "okay";
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_pins_default>;
 };
 
 &i2c0 {
index e5ac1d81d15c9e482ab06b41830e5230a0187e69..c536b2f5389f2786930a48eb0f7446311c622121 100644 (file)
        };
 };
 
+&dra7_pmx_core {
+       dcan1_pins_default: dcan1_pins_default {
+               pinctrl-single,pins = <
+                       DRA7XX_CORE_IOPAD(0x37d0, PIN_OUTPUT_PULLUP | MUX_MODE0)        /* dcan1_tx */
+                       DRA7XX_CORE_IOPAD(0x37d4, PIN_INPUT_PULLUP | MUX_MODE0)         /* dcan1_rx */
+               >;
+       };
+
+       dcan1_pins_sleep: dcan1_pins_sleep {
+               pinctrl-single,pins = <
+                       DRA7XX_CORE_IOPAD(0x37d0, MUX_MODE15 | PULL_UP) /* dcan1_tx.off */
+                       DRA7XX_CORE_IOPAD(0x37d4, MUX_MODE15 | PULL_UP) /* dcan1_rx.off */
+               >;
+       };
+};
+
 &i2c1 {
        status = "okay";
        clock-frequency = <400000>;
        max-frequency = <96000000>;
 };
 
+&dcan1 {
+       status = "okay";
+       pinctrl-names = "default", "sleep", "active";
+       pinctrl-0 = <&dcan1_pins_sleep>;
+       pinctrl-1 = <&dcan1_pins_sleep>;
+       pinctrl-2 = <&dcan1_pins_default>;
+};
+
 &qspi {
        status = "okay";
 
diff --git a/arch/arm/boot/dts/armada-385-linksys-shelby.dts b/arch/arm/boot/dts/armada-385-linksys-shelby.dts
new file mode 100644 (file)
index 0000000..c7a8ddd
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Device Tree file for the Linksys WRT1900ACS (Shelby)
+ *
+ * Copyright (C) 2015 Imre Kaloz <kaloz@openwrt.org>
+ *
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is licensed under the terms of the GNU General Public
+ *     License version 2.  This program is licensed "as is" without
+ *     any warranty of any kind, whether express or implied.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "armada-385-linksys.dtsi"
+
+/ {
+       model = "Linksys WRT1900ACS";
+       compatible = "linksys,shelby", "linksys,armada385", "marvell,armada385",
+                    "marvell,armada380";
+
+       soc {
+               internal-regs{
+                       i2c@11000 {
+
+                               pca9635@68 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                                       wan_amber@0 {
+                                               label = "shelby:amber:wan";
+                                               reg = <0x0>;
+                                       };
+
+                                       wan_white@1 {
+                                               label = "shelby:white:wan";
+                                               reg = <0x1>;
+                                       };
+
+                                       wlan_2g@2 {
+                                               label = "shelby:white:wlan_2g";
+                                               reg = <0x2>;
+                                       };
+
+                                       wlan_5g@3 {
+                                               label = "shelby:white:wlan_5g";
+                                               reg = <0x3>;
+                                       };
+
+                                       usb2@5 {
+                                               label = "shelby:white:usb2";
+                                               reg = <0x5>;
+                                       };
+
+                                       usb3_1@6 {
+                                               label = "shelby:white:usb3_1";
+                                               reg = <0x6>;
+                                       };
+
+                                       usb3_2@7 {
+                                               label = "shelby:white:usb3_2";
+                                               reg = <0x7>;
+                                       };
+
+                                       wps_white@8 {
+                                               label = "shelby:white:wps";
+                                               reg = <0x8>;
+                                       };
+
+                                       wps_amber@9 {
+                                               label = "shelby:amber:wps";
+                                               reg = <0x9>;
+                                       };
+                               };
+                       };
+               };
+       };
+
+       gpio-leds {
+               power {
+                       label = "shelby:white:power";
+               };
+
+               sata {
+                       label = "shelby:white:sata";
+               };
+       };
+};
index df47bf1ea5eb4fbbac7559eb5b6bad47a1de47cd..2306c45685b1f14788e4e5f3e0927a7724ca554d 100644 (file)
@@ -59,7 +59,8 @@
                ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000
                          MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000
                          MBUS_ID(0x09, 0x19) 0 0xf1100000 0x10000
-                         MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000>;
+                         MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000
+                         MBUS_ID(0x0c, 0x04) 0 0xf1200000 0x100000>;
 
                internal-regs {
                        i2c@11000 {
@@ -88,6 +89,9 @@
                        ethernet@70000 {
                                status = "okay";
                                phy-mode = "rgmii-id";
+                               buffer-manager = <&bm>;
+                               bm,pool-long = <2>;
+                               bm,pool-short = <3>;
                                fixed-link {
                                        speed = <1000>;
                                        full-duplex;
                        ethernet@34000 {
                                status = "okay";
                                phy-mode = "sgmii";
+                               buffer-manager = <&bm>;
+                               bm,pool-long = <0>;
+                               bm,pool-short = <1>;
                                fixed-link {
                                        speed = <1000>;
                                        full-duplex;
                                status = "okay";
                        };
 
+                       bm@c8000 {
+                               status = "okay";
+                       };
+
                        /* USB part of the eSATA/USB 2.0 port */
                        usb@58000 {
                                status = "okay";
                        };
                };
 
+               bm-bppi {
+                       status = "okay";
+               };
+
                pcie-controller {
                        status = "okay";
 
                sata {
                        gpios = <&gpio1 22 GPIO_ACTIVE_LOW>;
                        default-state = "off";
+                       linux,default-trigger = "disk-activity";
                };
        };
 
diff --git a/arch/arm/boot/dts/armada-385-synology-ds116.dts b/arch/arm/boot/dts/armada-385-synology-ds116.dts
new file mode 100644 (file)
index 0000000..31510eb
--- /dev/null
@@ -0,0 +1,321 @@
+/*
+ * Device Tree file for Synology DS116 NAS
+ *
+ * Copyright (C) 2017 Willy Tarreau <w@1wt.eu>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is licensed under the terms of the GNU General Public
+ *     License version 2.  This program is licensed "as is" without
+ *     any warranty of any kind, whether express or implied.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "armada-385.dtsi"
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+       model = "Synology DS116";
+       compatible = "marvell,a385-gp", "marvell,armada385", "marvell,armada380";
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+
+       memory {
+               device_type = "memory";
+               reg = <0x00000000 0x40000000>; /* 1 GB */
+       };
+
+       soc {
+               ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000
+                         MBUS_ID(0x01, 0x1d) 0 0xfff00000 0x100000
+                         MBUS_ID(0x09, 0x19) 0 0xf1100000 0x10000
+                         MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000
+                         MBUS_ID(0x0c, 0x04) 0 0xf1200000 0x100000>;
+
+               internal-regs {
+                       i2c@11000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&i2c0_pins>;
+                               status = "okay";
+                               clock-frequency = <100000>;
+
+                               eeprom@57 {
+                                       compatible = "atmel,24c64";
+                                       reg = <0x57>;
+                               };
+                       };
+
+                       serial@12000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&uart0_pins>;
+                               status = "okay";
+                       };
+
+                       serial@12100 {
+                               /* A PIC16F1829 is connected to uart1 at 9600 bps,
+                                * and takes single-character orders :
+                                *   "1" : power off // already handled by the poweroff node
+                                *   "2" : short beep
+                                *   "3" : long beep
+                                *   "4" : turn the power LED ON
+                                *   "5" : flash the power LED
+                                *   "6" : turn the power LED OFF
+                                *   "7" : turn the status LED OFF
+                                *   "8" : turn the status LED ON
+                                *   "9" : flash the status LED
+                                *   "A" : flash the motherboard LED (D8)
+                                *   "B" : turn the motherboard LED OFF
+                                *   "C" : hard reset
+                                */
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&uart1_pins>;
+                               status = "okay";
+                       };
+
+                       poweroff@12100 {
+                               compatible = "synology,power-off";
+                               reg = <0x12100 0x100>;
+                               clocks = <&coreclk 0>;
+                       };
+
+                       ethernet@70000 {
+                               pinctrl-names = "default";
+                               phy = <&phy0>;
+                               phy-mode = "sgmii";
+                               buffer-manager = <&bm>;
+                               bm,pool-long = <0>;
+                               status = "okay";
+                       };
+
+
+                       mdio@72004 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&mdio_pins>;
+
+                               phy0: ethernet-phy@1 {
+                                       reg = <1>;
+                               };
+                       };
+
+                       sata@a8000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&sata0_pins>;
+                               status = "okay";
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               sata0: sata-port@0 {
+                                       reg = <0>;
+                                       target-supply = <&reg_5v_sata0>;
+                               };
+                       };
+
+                       bm@c8000 {
+                               status = "okay";
+                       };
+
+                       usb3@f0000 {
+                               usb-phy = <&usb3_0_phy>;
+                               status = "okay";
+                       };
+
+                       usb3@f8000 {
+                               usb-phy = <&usb3_1_phy>;
+                               status = "okay";
+                       };
+               };
+
+               bm-bppi {
+                       status = "okay";
+               };
+
+               gpio-fan {
+                       compatible = "gpio-fan";
+                       gpios = <&gpio1 18 GPIO_ACTIVE_HIGH>,
+                               <&gpio1 17 GPIO_ACTIVE_HIGH>,
+                               <&gpio1 16 GPIO_ACTIVE_HIGH>;
+                       gpio-fan,speed-map = <   0 0
+                                             1500 1
+                                             2500 2
+                                             3000 3
+                                             3400 4
+                                             3700 5
+                                             3900 6
+                                             4000 7>;
+                       cooling-cells = <2>;
+               };
+
+               gpio-leds {
+                       compatible = "gpio-leds";
+
+                       /* The green part is on gpio0.20 which is also used by
+                        * sata0, and accesses to SATA disk 0 make it blink so it
+                        * doesn't need to be declared here.
+                        */
+                       orange {
+                               gpios = <&gpio0 13 GPIO_ACTIVE_HIGH>;
+                               label = "ds116:orange:disk";
+                               default-state = "off";
+                       };
+               };
+       };
+
+       usb3_0_phy: usb3_0_phy {
+               compatible = "usb-nop-xceiv";
+               vcc-supply = <&reg_usb3_0_vbus>;
+       };
+
+       usb3_1_phy: usb3_1_phy {
+               compatible = "usb-nop-xceiv";
+               vcc-supply = <&reg_usb3_1_vbus>;
+       };
+
+       reg_usb3_0_vbus: usb3-vbus0 {
+               compatible = "regulator-fixed";
+               regulator-name = "usb3-vbus0";
+               pinctrl-names = "default";
+               pinctrl-0 = <&xhci0_vbus_pins>;
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               enable-active-high;
+               gpio = <&gpio1 26 GPIO_ACTIVE_HIGH>;
+       };
+
+       reg_usb3_1_vbus: usb3-vbus1 {
+               compatible = "regulator-fixed";
+               regulator-name = "usb3-vbus1";
+               pinctrl-names = "default";
+               pinctrl-0 = <&xhci1_vbus_pins>;
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               enable-active-high;
+               gpio = <&gpio1 27 GPIO_ACTIVE_HIGH>;
+       };
+
+       reg_sata0: pwr-sata0 {
+               compatible = "regulator-fixed";
+               regulator-name = "pwr_en_sata0";
+               regulator-min-microvolt = <12000000>;
+               regulator-max-microvolt = <12000000>;
+               enable-active-high;
+               regulator-boot-on;
+               gpio = <&gpio0 15 GPIO_ACTIVE_HIGH>;
+       };
+
+       reg_5v_sata0: v5-sata0 {
+               compatible = "regulator-fixed";
+               regulator-name = "v5.0-sata0";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               vin-supply = <&reg_sata0>;
+       };
+
+       reg_12v_sata0: v12-sata0 {
+               compatible = "regulator-fixed";
+               regulator-name = "v12.0-sata0";
+               regulator-min-microvolt = <12000000>;
+               regulator-max-microvolt = <12000000>;
+               vin-supply = <&reg_sata0>;
+       };
+};
+
+&spi0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&spi0_pins>;
+       status = "okay";
+
+       spi-flash@0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "macronix,mx25l6405d", "jedec,spi-nor";
+               reg = <0>; /* Chip select 0 */
+               spi-max-frequency = <50000000>;
+               m25p,fast-read;
+
+               /* Note: there is a redboot partition table despite u-boot
+                * being used. The names presented here are the same as those
+                * found in the FIS directory. There is also a small device
+                * tree in the last 64kB of the RedBoot partition which is not
+                * enumerated. The MAC address and the serial number are listed
+                * in the "vendor" partition.
+                */
+               partition@00000000 {
+                       label = "RedBoot";
+                       reg = <0x00000000 0x000f0000>;
+                       read-only;
+               };
+
+               partition@000c0000 {
+                       label = "zImage";
+                       reg = <0x000f0000 0x002d0000>;
+               };
+
+               partition@00390000 {
+                       label = "rd.gz";
+                       reg = <0x003c0000 0x00410000>;
+               };
+
+               partition@007d0000 {
+                       label = "vendor";
+                       reg = <0x007d0000 0x00010000>;
+                       read-only;
+               };
+
+               partition@007e0000 {
+                       label = "RedBoot config";
+                       reg = <0x007e0000 0x00010000>;
+                       read-only;
+               };
+
+               partition@007f0000 {
+                       label = "FIS directory";
+                       reg = <0x007f0000 0x00010000>;
+                       read-only;
+               };
+       };
+};
+
+&pinctrl {
+       /* use only one pin for UART1, as mpp20 is used by sata0 */
+       uart1_pins: uart-pins-1 {
+               marvell,pins = "mpp19";
+               marvell,function = "ua1";
+       };
+
+       xhci0_vbus_pins: xhci0_vbus_pins {
+               marvell,pins = "mpp58";
+               marvell,function = "gpio";
+       };
+       xhci1_vbus_pins: xhci1_vbus_pins {
+               marvell,pins = "mpp59";
+               marvell,function = "gpio";
+       };
+};
index 8e63be33472e05d058a055c84fe2ebac56250f81..7fcc4c4885cffa9b51fe8c1c9911e4ea3cfcc138 100644 (file)
        };
 
        soc {
-               internal-regs {
-                       pinctrl@18000 {
-                               compatible = "marvell,mv88f6820-pinctrl";
-                       };
-               };
-
-               pcie-controller {
+               pciec: pcie-controller {
                        compatible = "marvell,armada-370-pcie";
                        status = "disabled";
                        device_type = "pci";
                         * configured in x4 by the bootloader, then
                         * pcie@4,0 is not available.
                         */
-                       pcie@1,0 {
+                       pcie1: pcie@1,0 {
                                device_type = "pci";
                                assigned-addresses = <0x82000800 0 0x80000 0 0x2000>;
                                reg = <0x0800 0 0 0 0>;
                        };
 
                        /* x1 port */
-                       pcie@2,0 {
+                       pcie2: pcie@2,0 {
                                device_type = "pci";
                                assigned-addresses = <0x82000800 0 0x40000 0 0x2000>;
                                reg = <0x1000 0 0 0 0>;
                        };
 
                        /* x1 port */
-                       pcie@3,0 {
+                       pcie3: pcie@3,0 {
                                device_type = "pci";
                                assigned-addresses = <0x82000800 0 0x44000 0 0x2000>;
                                reg = <0x1800 0 0 0 0>;
                         * x1 port only available when pcie@1,0 is
                         * configured as a x1 port
                         */
-                       pcie@4,0 {
+                       pcie4: pcie@4,0 {
                                device_type = "pci";
                                assigned-addresses = <0x82000800 0 0x48000 0 0x2000>;
                                reg = <0x2000 0 0 0 0>;
                };
        };
 };
+
+&pinctrl {
+       compatible = "marvell,mv88f6820-pinctrl";
+};
index 2745b741631339b5afb865b9dedc5a0629714052..0d5f1f06227568389c072194bf7da8ae6957012d 100644 (file)
        };
 };
 
-&pinctrl {
-       clearfog_dsa0_clk_pins: clearfog-dsa0-clk-pins {
-               marvell,pins = "mpp46";
-               marvell,function = "ref";
-       };
-       clearfog_dsa0_pins: clearfog-dsa0-pins {
-               marvell,pins = "mpp23", "mpp41";
-               marvell,function = "gpio";
-       };
-       clearfog_spi1_cs_pins: spi1-cs-pins {
-               marvell,pins = "mpp55";
-               marvell,function = "spi1";
-       };
-       rear_button_pins: rear-button-pins {
-               marvell,pins = "mpp34";
-               marvell,function = "gpio";
-       };
-};
-
 &mdio {
        status = "okay";
 
        };
 };
 
+&pinctrl {
+       clearfog_dsa0_clk_pins: clearfog-dsa0-clk-pins {
+               marvell,pins = "mpp46";
+               marvell,function = "ref";
+       };
+       clearfog_dsa0_pins: clearfog-dsa0-pins {
+               marvell,pins = "mpp23", "mpp41";
+               marvell,function = "gpio";
+       };
+       clearfog_spi1_cs_pins: spi1-cs-pins {
+               marvell,pins = "mpp55";
+               marvell,function = "spi1";
+       };
+       rear_button_pins: rear-button-pins {
+               marvell,pins = "mpp34";
+               marvell,function = "gpio";
+       };
+};
+
 &spi1 {
        /*
         * Add SPI CS pins for clearfog:
index 564fa5937e258f96a0cdfb82b3eed94877e07879..1c0d151b2aaa6d1e5f808b702c688edb06440dd0 100644 (file)
        model = "Marvell Armada 388 family SoC";
        compatible = "marvell,armada388", "marvell,armada385",
                "marvell,armada380";
-
        soc {
                internal-regs {
-                       pinctrl@18000 {
-                               compatible = "marvell,mv88f6828-pinctrl";
-                       };
-
                        sata@e0000 {
                                compatible = "marvell,armada-380-ahci";
                                reg = <0xe0000 0x2000>;
@@ -68,3 +63,7 @@
                };
        };
 };
+
+&pinctrl {
+       compatible = "marvell,mv88f6828-pinctrl";
+};
index 79b767507eab62d9897480c30b48b278d71bd13a..8b165c31de1efb432e15d2cb63fd7bd69b1af89b 100644 (file)
@@ -82,7 +82,7 @@
                        reg = <MBUS_ID(0x01, 0x1d) 0 0x200000>;
                };
 
-               devbus-bootcs {
+               devbus_bootcs: devbus-bootcs {
                        compatible = "marvell,mvebu-devbus";
                        reg = <MBUS_ID(0xf0, 0x01) 0x10400 0x8>;
                        ranges = <0 MBUS_ID(0x01, 0x2f) 0 0xffffffff>;
@@ -92,7 +92,7 @@
                        status = "disabled";
                };
 
-               devbus-cs0 {
+               devbus_cs0: devbus-cs0 {
                        compatible = "marvell,mvebu-devbus";
                        reg = <MBUS_ID(0xf0, 0x01) 0x10408 0x8>;
                        ranges = <0 MBUS_ID(0x01, 0x3e) 0 0xffffffff>;
                        status = "disabled";
                };
 
-               devbus-cs1 {
+               devbus_cs1: devbus-cs1 {
                        compatible = "marvell,mvebu-devbus";
                        reg = <MBUS_ID(0xf0, 0x01) 0x10410 0x8>;
                        ranges = <0 MBUS_ID(0x01, 0x3d) 0 0xffffffff>;
                        status = "disabled";
                };
 
-               devbus-cs2 {
+               devbus_cs2: devbus-cs2 {
                        compatible = "marvell,mvebu-devbus";
                        reg = <MBUS_ID(0xf0, 0x01) 0x10418 0x8>;
                        ranges = <0 MBUS_ID(0x01, 0x3b) 0 0xffffffff>;
                        status = "disabled";
                };
 
-               devbus-cs3 {
+               devbus_cs3: devbus-cs3 {
                        compatible = "marvell,mvebu-devbus";
                        reg = <MBUS_ID(0xf0, 0x01) 0x10420 0x8>;
                        ranges = <0 MBUS_ID(0x01, 0x37) 0 0xffffffff>;
                                             <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
                        };
 
-                       system-controller@18200 {
+                       systemc: system-controller@18200 {
                                compatible = "marvell,armada-380-system-controller",
                                             "marvell,armada-370-xp-system-controller";
                                reg = <0x18200 0x100>;
 
                        mbusc: mbus-controller@20000 {
                                compatible = "marvell,mbus-controller";
-                               reg = <0x20000 0x100>, <0x20180 0x20>;
+                               reg = <0x20000 0x100>, <0x20180 0x20>,
+                                     <0x20250 0x8>;
                        };
 
                        mpic: interrupt-controller@20a00 {
                                interrupts = <GIC_PPI 15 IRQ_TYPE_LEVEL_HIGH>;
                        };
 
-                       timer@20300 {
+                       timer: timer@20300 {
                                compatible = "marvell,armada-380-timer",
                                             "marvell,armada-xp-timer";
                                reg = <0x20300 0x30>, <0x21040 0x30>;
                                clock-names = "nbclk", "fixed";
                        };
 
-                       watchdog@20300 {
+                       watchdog: watchdog@20300 {
                                compatible = "marvell,armada-380-wdt";
                                reg = <0x20300 0x34>, <0x20704 0x4>, <0x18260 0x4>;
                                clocks = <&coreclk 2>, <&refclk>;
                                clock-names = "nbclk", "fixed";
                        };
 
-                       cpurst@20800 {
+                       cpurst: cpurst@20800 {
                                compatible = "marvell,armada-370-cpu-reset";
                                reg = <0x20800 0x10>;
                        };
                                reg = <0x20d20 0x6c>;
                        };
 
-                       coherency-fabric@21010 {
+                       coherencyfab: coherency-fabric@21010 {
                                compatible = "marvell,armada-380-coherency-fabric";
                                reg = <0x21010 0x1c>;
                        };
 
-                       pmsu@22000 {
+                       pmsu: pmsu@22000 {
                                compatible = "marvell,armada-380-pmsu";
                                reg = <0x22000 0x1000>;
                        };
                                status = "disabled";
                        };
 
-                       usb@58000 {
+                       usb0: usb@58000 {
                                compatible = "marvell,orion-ehci";
                                reg = <0x58000 0x500>;
                                interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
                                status = "disabled";
                        };
 
-                       xor@60800 {
+                       xor0: xor@60800 {
                                compatible = "marvell,armada-380-xor", "marvell,orion-xor";
                                reg = <0x60800 0x100
                                       0x60a00 0x100>;
                                };
                        };
 
-                       xor@60900 {
+                       xor1: xor@60900 {
                                compatible = "marvell,armada-380-xor", "marvell,orion-xor";
                                reg = <0x60900 0x100
                                       0x60b00 0x100>;
                                clocks = <&gateclk 4>;
                        };
 
-                       crypto@90000 {
+                       cesa: crypto@90000 {
                                compatible = "marvell,armada-38x-crypto";
                                reg = <0x90000 0x10000>;
                                reg-names = "regs";
                                marvell,crypto-sram-size = <0x800>;
                        };
 
-                       rtc@a3800 {
+                       rtc: rtc@a3800 {
                                compatible = "marvell,armada-380-rtc";
                                reg = <0xa3800 0x20>, <0x184a0 0x0c>;
                                reg-names = "rtc", "rtc-soc";
                                interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
                        };
 
-                       sata@a8000 {
+                       ahci0: sata@a8000 {
                                compatible = "marvell,armada-380-ahci";
                                reg = <0xa8000 0x2000>;
                                interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
                                status = "disabled";
                        };
 
-                       sata@e0000 {
+                       ahci1: sata@e0000 {
                                compatible = "marvell,armada-380-ahci";
                                reg = <0xe0000 0x2000>;
                                interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
                                clock-output-names = "nand";
                        };
 
-                       thermal@e8078 {
+                       thermal: thermal@e8078 {
                                compatible = "marvell,armada380-thermal";
                                reg = <0xe4078 0x4>, <0xe4074 0x4>;
                                status = "okay";
                        };
 
-                       flash@d0000 {
+                       nand: flash@d0000 {
                                compatible = "marvell,armada370-nand";
                                reg = <0xd0000 0x54>;
                                #address-cells = <1>;
                                status = "disabled";
                        };
 
-                       sdhci@d8000 {
+                       sdhci: sdhci@d8000 {
                                compatible = "marvell,armada-380-sdhci";
                                reg-names = "sdhci", "mbus", "conf-sdio3";
                                reg = <0xd8000 0x1000>,
                                status = "disabled";
                        };
 
-                       usb3@f0000 {
+                       usb3_0: usb3@f0000 {
                                compatible = "marvell,armada-380-xhci";
                                reg = <0xf0000 0x4000>,<0xf4000 0x4000>;
                                interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
                                status = "disabled";
                        };
 
-                       usb3@f8000 {
+                       usb3_1: usb3@f8000 {
                                compatible = "marvell,armada-380-xhci";
                                reg = <0xf8000 0x4000>,<0xfc000 0x4000>;
                                interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
index f6a03dcee5efc4b1e3eb6eeb2641c0b36f719bae..84cc232a29e9e3c00f779da43174fa637e52ca4f 100644 (file)
  * common to all Armada XP SoCs.
  */
 
-#include "armada-xp.dtsi"
+#include "armada-370-xp.dtsi"
 
 / {
+       #address-cells = <2>;
+       #size-cells = <2>;
+
        model = "Marvell 98DX3236 SoC";
-       compatible = "marvell,armadaxp-98dx3236", "marvell,armadaxp", "marvell,armada-370-xp";
+       compatible = "marvell,armadaxp-98dx3236", "marvell,armada-370-xp";
 
        aliases {
                gpio0 = &gpio0;
        };
 
        soc {
+               compatible = "marvell,armadaxp-mbus", "simple-bus";
+
                ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000
                          MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000
                          MBUS_ID(0x01, 0x2f) 0 0 0xf0000000 0x1000000
                          MBUS_ID(0x03, 0x00) 0 0 0xa8000000 0x4000000
                          MBUS_ID(0x08, 0x00) 0 0 0xac000000 0x100000>;
 
+               bootrom {
+                       compatible = "marvell,bootrom";
+                       reg = <MBUS_ID(0x01, 0x1d) 0 0x100000>;
+               };
+
                /*
                 * 98DX3236 has 1 x1 PCIe unit Gen2.0
                 */
                        ranges =
                               <0x82000000 0 0x40000 MBUS_ID(0xf0, 0x01) 0x40000 0 0x00002000   /* Port 0.0 registers */
                                0x82000000 0x1 0       MBUS_ID(0x04, 0xe8) 0 1 0 /* Port 0.0 MEM */
-                               0x81000000 0x1 0       MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 0.0 IO  */
-                               0x82000000 0x2 0       MBUS_ID(0x04, 0xd8) 0 1 0 /* Port 0.1 MEM */>;
+                               0x81000000 0x1 0       MBUS_ID(0x04, 0xe0) 0 1 0 /* Port 0.0 IO  */>;
 
                        pcie1: pcie@1,0 {
                                device_type = "pci";
                };
 
                internal-regs {
-                       coreclk: mvebu-sar@18230 {
-                               compatible = "marvell,mv98dx3236-core-clock";
+                       sdramc@1400 {
+                               compatible = "marvell,armada-xp-sdram-controller";
+                               reg = <0x1400 0x500>;
+                       };
+
+                       L2: l2-cache@8000 {
+                               compatible = "marvell,aurora-system-cache";
+                               reg = <0x08000 0x1000>;
+                               cache-id-part = <0x100>;
+                               cache-level = <2>;
+                               cache-unified;
+                               wt-override;
+                       };
+
+                       gpio0: gpio@18100 {
+                               compatible = "marvell,orion-gpio";
+                               reg = <0x18100 0x40>;
+                               ngpios = <32>;
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               interrupts = <82>, <83>, <84>, <85>;
+                       };
+
+                       /* does not exist */
+                       gpio1: gpio@18140 {
+                               compatible = "marvell,orion-gpio";
+                               reg = <0x18140 0x40>;
+                               status = "disabled";
+                       };
+
+                       gpio2: gpio@18180 { /* rework some properties */
+                               compatible = "marvell,orion-gpio";
+                               reg = <0x18180 0x40>;
+                               ngpios = <1>; /* only gpio #32 */
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                               interrupts = <87>;
+                       };
+
+                       systemc: system-controller@18200 {
+                               compatible = "marvell,armada-370-xp-system-controller";
+                               reg = <0x18200 0x500>;
+                       };
+
+                       gateclk: clock-gating-control@18220 {
+                               compatible = "marvell,mv98dx3236-gating-clock";
+                               reg = <0x18220 0x4>;
+                               clocks = <&coreclk 0>;
+                               #clock-cells = <1>;
                        };
 
                        cpuclk: clock-complex@18700 {
+                               #clock-cells = <1>;
                                compatible = "marvell,mv98dx3236-cpu-clock";
+                               reg = <0x18700 0x24>, <0x1c054 0x10>;
+                               clocks = <&coreclk 1>;
                        };
 
                        corediv-clock@18740 {
                                status = "disabled";
                        };
 
-                       xor@60900 {
-                               status = "disabled";
+                       cpu-config@21000 {
+                               compatible = "marvell,armada-xp-cpu-config";
+                               reg = <0x21000 0x8>;
                        };
 
-                       crypto@90000 {
-                               status = "disabled";
+                       ethernet@70000 {
+                               compatible = "marvell,armada-xp-neta";
                        };
 
-                       xor@f0900 {
-                               status = "disabled";
+                       ethernet@74000 {
+                               compatible = "marvell,armada-xp-neta";
                        };
 
-                       xor@f0800 {
+                       xor1: xor@f0800 {
                                compatible = "marvell,orion-xor";
                                reg = <0xf0800 0x100
                                       0xf0a00 0x100>;
                                };
                        };
 
-                       gpio0: gpio@18100 {
-                               compatible = "marvell,orion-gpio";
-                               reg = <0x18100 0x40>;
-                               ngpios = <32>;
-                               gpio-controller;
-                               #gpio-cells = <2>;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                               interrupts = <82>, <83>, <84>, <85>;
-                       };
-
-                       /* does not exist */
-                       gpio1: gpio@18140 {
-                               compatible = "marvell,orion-gpio";
-                               reg = <0x18140 0x40>;
-                               status = "disabled";
+                       nand: nand@d0000 {
+                               clocks = <&dfx_coredivclk 0>;
                        };
 
-                       gpio2: gpio@18180 { /* rework some properties */
-                               compatible = "marvell,orion-gpio";
-                               reg = <0x18180 0x40>;
-                               ngpios = <1>; /* only gpio #32 */
-                               gpio-controller;
-                               #gpio-cells = <2>;
-                               interrupt-controller;
-                               #interrupt-cells = <2>;
-                               interrupts = <87>;
-                       };
+                       xor0: xor@f0900 {
+                               compatible = "marvell,orion-xor";
+                               reg = <0xF0900 0x100
+                                      0xF0B00 0x100>;
+                               clocks = <&gateclk 28>;
+                               status = "okay";
 
-                       nand: nand@d0000 {
-                               clocks = <&dfx_coredivclk 0>;
+                               xor00 {
+                                       interrupts = <94>;
+                                       dmacap,memcpy;
+                                       dmacap,xor;
+                               };
+                               xor01 {
+                                       interrupts = <95>;
+                                       dmacap,memcpy;
+                                       dmacap,xor;
+                                       dmacap,memset;
+                               };
                        };
                };
 
-               dfxr: dfx-registers@ac000000 {
-                       compatible = "simple-bus";
+               dfx: dfx-server@ac000000 {
+                       compatible = "marvell,dfx-server", "simple-bus";
                        #address-cells = <1>;
                        #size-cells = <1>;
                        ranges = <0 MBUS_ID(0x08, 0x00) 0 0x100000>;
+                       reg = <MBUS_ID(0x08, 0x00) 0 0x100000>;
+
+                       coreclk: mvebu-sar@f8204 {
+                               compatible = "marvell,mv98dx3236-core-clock";
+                               reg = <0xf8204 0x4>;
+                               #clock-cells = <1>;
+                       };
 
                        dfx_coredivclk: corediv-clock@f8268 {
                                compatible = "marvell,mv98dx3236-corediv-clock";
                                clocks = <&mainpll>;
                                clock-output-names = "nand";
                        };
-
-                       dfx: dfx@0 {
-                               compatible = "marvell,dfx-server";
-                               reg = <0 0x100000>;
-                       };
                };
 
                switch: switch@a8000000 {
                        };
                };
        };
+
+       clocks {
+               /* 25 MHz reference crystal */
+               refclk: oscillator {
+                       compatible = "fixed-clock";
+                       #clock-cells = <0>;
+                       clock-frequency = <25000000>;
+               };
+       };
+};
+
+&i2c0 {
+       compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c";
+       reg = <0x11000 0x100>;
+};
+
+&i2c1 {
+       compatible = "marvell,mv78230-i2c", "marvell,mv64xxx-i2c";
+       reg = <0x11100 0x100>;
+};
+
+&mpic {
+       reg = <0x20a00 0x2d0>, <0x21070 0x58>;
+};
+
+&timer {
+       compatible = "marvell,armada-xp-timer";
+       clocks = <&coreclk 2>, <&refclk>;
+       clock-names = "nbclk", "fixed";
+};
+
+&watchdog {
+       compatible = "marvell,armada-xp-wdt";
+       clocks = <&coreclk 2>, <&refclk>;
+       clock-names = "nbclk", "fixed";
+};
+
+&cpurst {
+       reg = <0x20800 0x20>;
+};
+
+&usb0 {
+       clocks = <&gateclk 18>;
+};
+
+&usb1 {
+       clocks = <&gateclk 19>;
 };
 
 &pinctrl {
        };
 };
 
-&sdio {
-       status = "disabled";
+&spi0 {
+       compatible = "marvell,armada-xp-spi", "marvell,orion-spi";
+       pinctrl-0 = <&spi0_pins>;
+       pinctrl-names = "default";
 };
 
-&crypto_sram0 {
+&sdio {
        status = "disabled";
 };
 
-&crypto_sram1 {
-       status = "disabled";
-};
index e1580afdc260f3a0783771c993793f8f9c1b5016..a0d81bd7312bee135d6de98b5ee519dba2e914b5 100644 (file)
@@ -49,7 +49,7 @@
 
 / {
        model = "Marvell 98DX3336 SoC";
-       compatible = "marvell,armadaxp-98dx3336", "marvell,armadaxp-98dx3236", "marvell,armadaxp", "marvell,armada-370-xp";
+       compatible = "marvell,armadaxp-98dx3336", "marvell,armadaxp-98dx3236", "marvell,armada-370-xp";
 
        cpus {
                cpu@1 {
index b9d9b269efb49ff7f1612894cb8ec26c6cbf1e72..51de91b31a9d22e6ac259a57dc7971bfa1af5bc1 100644 (file)
@@ -49,7 +49,7 @@
 
 / {
        model = "Marvell 98DX4251 SoC";
-       compatible = "marvell,armadaxp-98dx4251", "marvell,armadaxp-98dx3236", "marvell,armadaxp", "marvell,armada-370-xp";
+       compatible = "marvell,armadaxp-98dx4251", "marvell,armadaxp-98dx3236", "marvell,armada-370-xp";
 
        cpus {
                cpu@1 {
index a8130805074ede73485bec88f8dd9ae9039bf59b..1b1ff17fdd9cf86973163bcb335300e1faf24341 100644 (file)
@@ -58,7 +58,7 @@
 
 / {
        model = "Marvell Bobcat2 Evaluation Board";
-       compatible = "marvell,db-dxbc2", "marvell,armadaxp-98dx4251", "marvell,armadaxp", "marvell,armada-370-xp";
+       compatible = "marvell,db-dxbc2", "marvell,armadaxp-98dx4251", "marvell,armada-370-xp";
 
        chosen {
                bootargs = "console=ttyS0,115200 earlyprintk";
index 4e07cb6ed800eb2b5f073a59c9a7ee3e2fe3611c..06fce35d7491c3062116f5713779664c83fed61e 100644 (file)
@@ -58,7 +58,7 @@
 
 / {
        model = "DB-XC3-24G4XG";
-       compatible = "marvell,db-xc3-24g4xg", "marvell,armadaxp-98dx3336", "marvell,armadaxp", "marvell,armada-370-xp";
+       compatible = "marvell,db-xc3-24g4xg", "marvell,armadaxp-98dx3336", "marvell,armada-370-xp";
 
        chosen {
                bootargs = "console=ttyS0,115200 earlyprintk";
index 42ea8764814cfb5278245ea608b4a39fb86000cb..9efcf59c9b442e957ebddd7fabb9d38113dbf56f 100644 (file)
@@ -71,7 +71,8 @@
                ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000
                          MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000
                          MBUS_ID(0x09, 0x09) 0 0 0xf1100000 0x10000
-                         MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000>;
+                         MBUS_ID(0x09, 0x05) 0 0 0xf1110000 0x10000
+                         MBUS_ID(0x0c, 0x04) 0 0 0xf1200000 0x100000>;
 
                internal-regs {
 
@@ -95,6 +96,9 @@
                                pinctrl-names = "default";
                                status = "okay";
                                phy-mode = "rgmii-id";
+                               buffer-manager = <&bm>;
+                               bm,pool-long = <0>;
+                               bm,pool-short = <1>;
                                fixed-link {
                                        speed = <1000>;
                                        full-duplex;
                                pinctrl-names = "default";
                                status = "okay";
                                phy-mode = "rgmii-id";
+                               buffer-manager = <&bm>;
+                               bm,pool-long = <2>;
+                               bm,pool-short = <3>;
                                fixed-link {
                                        speed = <1000>;
                                        full-duplex;
                                        esata@4 {
                                                label = "mamba:white:esata";
                                                reg = <0x4>;
+                                               linux,default-trigger = "disk-activity";
                                        };
 
                                        usb2@5 {
                                };
                        };
 
+                       bm@c8000 {
+                               status = "okay";
+                       };
+
                        nand@d0000 {
                                status = "okay";
                                num-cs = <1>;
                                };
                        };
                };
+
+               bm-bppi {
+                       status = "okay";
+               };
        };
 
        gpio_keys {
index d967603dade8f20ab4bbdbde2b808a615ee78646..7c90dac9982236b75e6a9a9e197291f1864830e4 100644 (file)
        };
 };
 
+&fmc {
+       status = "okay";
+       flash@0 {
+               status = "okay";
+               m25p,fast-read;
+               label = "bmc";
+       };
+};
+
+&spi1 {
+       status = "okay";
+       flash@0 {
+               status = "okay";
+               m25p,fast-read;
+               label = "pnor";
+       };
+};
+
+&spi2 {
+       status = "okay";
+};
+
 &uart5 {
        status = "okay";
 };
index 1d2fc1e1dc291547bdbbe94cde3a1bf524aac3c8..112551766275c38cfc5831e48d88a5369a05d42b 100644 (file)
        };
 };
 
+&fmc {
+       status = "okay";
+       flash@0 {
+               status = "okay";
+               m25p,fast-read;
+               label = "bmc";
+       };
+};
+
+&spi {
+       status = "okay";
+       flash@0 {
+               status = "okay";
+               m25p,fast-read;
+               label = "pnor";
+       };
+};
+
 &uart5 {
        status = "okay";
 };
index 7a3b2b50c884fa73a06937caec86515ec4246994..1190fec1b5d023d44039439da04c53afd56cc1bf 100644 (file)
        };
 };
 
+&fmc {
+       status = "okay";
+       flash@0 {
+               status = "okay";
+               m25p,fast-read;
+               label = "bmc";
+       };
+};
+
+&spi1 {
+       status = "okay";
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_spi1_default>;
+
+       flash@0 {
+               status = "okay";
+               m25p,fast-read;
+               label = "pnor";
+       };
+};
+
+&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>;
+};
+
 &uart5 {
        status = "okay";
 };
index c79c937b0a8aab92f2227deb8bf2d756542b57e8..8c6bc29eb7f695e0c43a1e6a242c20ea11ea177e 100644 (file)
                };
        };
 
-       clocks {
-               clk_clkin: clk_clkin {
-                       #clock-cells = <0>;
-                       compatible = "fixed-clock";
-                       clock-frequency = <48000000>;
-               };
-
-       };
-
        ahb {
                compatible = "simple-bus";
                #address-cells = <1>;
                #size-cells = <1>;
                ranges;
 
+               fmc: flash-controller@1e620000 {
+                       reg = < 0x1e620000 0x94
+                               0x20000000 0x02000000 >;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "aspeed,ast2400-fmc";
+                       status = "disabled";
+                       interrupts = <19>;
+                       flash@0 {
+                               reg = < 0 >;
+                               compatible = "jedec,spi-nor";
+                               status = "disabled";
+                       };
+               };
+
+               spi: flash-controller@1e630000 {
+                       reg = < 0x1e630000 0x18
+                               0x30000000 0x02000000 >;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "aspeed,ast2400-spi";
+                       status = "disabled";
+                       flash@0 {
+                               reg = < 0 >;
+                               compatible = "jedec,spi-nor";
+                               status = "disabled";
+                       };
+               };
+
                vic: interrupt-controller@1e6c0080 {
                        compatible = "aspeed,ast2400-vic";
                        interrupt-controller;
                        #size-cells = <1>;
                        ranges;
 
-                       clk_hpll: clk_hpll@1e6e2070 {
-                               #clock-cells = <0>;
-                               compatible = "aspeed,g4-hpll-clock";
-                               reg = <0x1e6e2070 0x4>;
-                               clocks = <&clk_clkin>;
-                       };
-
                        syscon: syscon@1e6e2000 {
                                compatible = "aspeed,g4-scu", "syscon", "simple-mfd";
                                reg = <0x1e6e2000 0x1a8>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                                clk_clkin: clk_clkin {
+                                        #clock-cells = <0>;
+                                        compatible = "fixed-clock";
+                                        clock-frequency = <48000000>;
+                                };
+
+                                clk_hpll: clk_hpll@70 {
+                                        #clock-cells = <0>;
+                                        compatible = "aspeed,g4-hpll-clock", "fixed-clock";
+                                        reg = <0x70>;
+                                        clocks = <&clk_clkin>;
+                                        clock-frequency = <384000000>;
+                                };
+
+                                clk_ahb: clk_ahb@70 {
+                                        #clock-cells = <0>;
+                                        compatible = "aspeed,g4-ahb-clock", "fixed-clock";
+                                        reg = <0x70>;
+                                        clocks = <&clk_hpll>;
+                                        clock-frequency = <192000000>;
+                                };
+
+                                clk_apb: clk_apb@08 {
+                                        #clock-cells = <0>;
+                                        compatible = "aspeed,g4-apb-clock", "fixed-clock";
+                                        reg = <0x08>;
+                                        clocks = <&clk_hpll>;
+                                        clock-frequency = <48000000>;
+                                };
+
+                                clk_uart: clk_uart@2c{
+                                        #clock-cells = <0>;
+                                        compatible = "aspeed,g4-uart-clock", "fixed-clock";
+                                        reg = <0x2c>;
+                                        clock-frequency = <24000000>;
+                                };
 
                                pinctrl: pinctrl {
                                        compatible = "aspeed,g4-pinctrl";
                                };
                        };
 
-                       clk_apb: clk_apb@1e6e2008 {
-                               #clock-cells = <0>;
-                               compatible = "aspeed,g4-apb-clock";
-                               reg = <0x1e6e2008 0x4>;
-                               clocks = <&clk_hpll>;
-                       };
-
-                       clk_uart: clk_uart@1e6e2008 {
-                               #clock-cells = <0>;
-                               compatible = "aspeed,uart-clock";
-                               reg = <0x1e6e202c 0x4>;
-                       };
-
                        sram@1e720000 {
                                compatible = "mmio-sram";
                                reg = <0x1e720000 0x8000>;      // 32K
                        };
 
                        wdt1: wdt@1e785000 {
-                               compatible = "aspeed,wdt";
+                               compatible = "aspeed,ast2400-wdt";
                                reg = <0x1e785000 0x1c>;
                                interrupts = <27>;
                        };
 
                        wdt2: wdt@1e785020 {
-                               compatible = "aspeed,wdt";
+                               compatible = "aspeed,ast2400-wdt";
                                reg = <0x1e785020 0x1c>;
                                interrupts = <27>;
                                clocks = <&clk_apb>;
                                no-loopback-test;
                                status = "disabled";
                        };
+
+                       adc: adc@1e6e9000 {
+                               compatible = "aspeed,ast2400-adc";
+                               reg = <0x1e6e9000 0xb0>;
+                               clocks = <&clk_apb>;
+                               #io-channel-cells = <1>;
+                               status = "disabled";
+                       };
                };
        };
 };
index b6596633036cd3a66c29e0c4c28663980fa7c200..a0bea4a6ec7764141e1a62cb8716a1cba5ad6e2e 100644 (file)
                #size-cells = <1>;
                ranges;
 
+               fmc: flash-controller@1e620000 {
+                       reg = < 0x1e620000 0xc4
+                               0x20000000 0x10000000 >;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "aspeed,ast2500-fmc";
+                       status = "disabled";
+                       interrupts = <19>;
+                       flash@0 {
+                               reg = < 0 >;
+                               compatible = "jedec,spi-nor";
+                               status = "disabled";
+                       };
+                       flash@1 {
+                               reg = < 1 >;
+                               compatible = "jedec,spi-nor";
+                               status = "disabled";
+                       };
+                       flash@2 {
+                               reg = < 2 >;
+                               compatible = "jedec,spi-nor";
+                               status = "disabled";
+                       };
+               };
+
+               spi1: flash-controller@1e630000 {
+                       reg = < 0x1e630000 0xc4
+                               0x30000000 0x08000000 >;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "aspeed,ast2500-spi";
+                       status = "disabled";
+                       flash@0 {
+                               reg = < 0 >;
+                               compatible = "jedec,spi-nor";
+                               status = "disabled";
+                       };
+                       flash@1 {
+                               reg = < 1 >;
+                               compatible = "jedec,spi-nor";
+                               status = "disabled";
+                       };
+               };
+
+               spi2: flash-controller@1e631000 {
+                       reg = < 0x1e631000 0xc4
+                               0x38000000 0x08000000 >;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "aspeed,ast2500-spi";
+                       status = "disabled";
+                       flash@0 {
+                               reg = < 0 >;
+                               compatible = "jedec,spi-nor";
+                               status = "disabled";
+                       };
+                       flash@1 {
+                               reg = < 1 >;
+                               compatible = "jedec,spi-nor";
+                               status = "disabled";
+                       };
+               };
+
                vic: interrupt-controller@1e6c0080 {
                        compatible = "aspeed,ast2400-vic";
                        interrupt-controller;
                        #size-cells = <1>;
                        ranges;
 
-                       clk_clkin: clk_clkin@1e6e2070 {
-                               #clock-cells = <0>;
-                               compatible = "aspeed,g5-clkin-clock";
-                               reg = <0x1e6e2070 0x04>;
-                       };
-
                        syscon: syscon@1e6e2000 {
                                compatible = "aspeed,g5-scu", "syscon", "simple-mfd";
                                reg = <0x1e6e2000 0x1a8>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               clk_clkin: clk_clkin@70 {
+                                       #clock-cells = <0>;
+                                       compatible = "aspeed,g5-clkin-clock", "fixed-clock";
+                                       reg = <0x70>;
+                                       clock-frequency = <24000000>;
+                               };
+
+                               clk_hpll: clk_hpll@24 {
+                                       #clock-cells = <0>;
+                                       compatible = "aspeed,g5-hpll-clock", "fixed-clock";
+                                       reg = <0x24>;
+                                       clocks = <&clk_clkin>;
+                                       clock-frequency = <792000000>;
+                               };
+
+                               clk_ahb: clk_ahb@70 {
+                                       #clock-cells = <0>;
+                                       compatible = "aspeed,g5-ahb-clock", "fixed-clock";
+                                       reg = <0x70>;
+                                       clocks = <&clk_hpll>;
+                                       clock-frequency = <198000000>;
+                               };
+
+                               clk_apb: clk_apb@08 {
+                                       #clock-cells = <0>;
+                                       compatible = "aspeed,g5-apb-clock", "fixed-clock";
+                                       reg = <0x08>;
+                                       clocks = <&clk_hpll>;
+                                       clock-frequency = <24750000>;
+                               };
+
+                               clk_uart: clk_uart@2c {
+                                       #clock-cells = <0>;
+                                       compatible = "aspeed,uart-clock", "fixed-clock";
+                                       reg = <0x2c>;
+                                       clock-frequency = <24000000>;
+                               };
 
                                pinctrl: pinctrl {
                                        compatible = "aspeed,g5-pinctrl";
                                                function = "LAD0";
                                                groups = "LAD0";
                                        };
-
                                        pinctrl_lad1_default: lad1_default {
                                                function = "LAD1";
                                                groups = "LAD1";
                                        };
 
                                };
-                       };
-
-                       clk_hpll: clk_hpll@1e6e2024 {
-                               #clock-cells = <0>;
-                               compatible = "aspeed,g5-hpll-clock";
-                               reg = <0x1e6e2024 0x4>;
-                               clocks = <&clk_clkin>;
-                       };
-
-                       clk_ahb: clk_ahb@1e6e2070 {
-                               #clock-cells = <0>;
-                               compatible = "aspeed,g5-ahb-clock";
-                               reg = <0x1e6e2070 0x4>;
-                               clocks = <&clk_hpll>;
-                       };
 
-                       clk_apb: clk_apb@1e6e2008 {
-                               #clock-cells = <0>;
-                               compatible = "aspeed,g5-apb-clock";
-                               reg = <0x1e6e2008 0x4>;
-                               clocks = <&clk_hpll>;
-                       };
-
-                       clk_uart: clk_uart@1e6e2008 {
-                               #clock-cells = <0>;
-                               compatible = "aspeed,uart-clock";
-                               reg = <0x1e6e202c 0x4>;
                        };
 
                        gfx: display@1e6e6000 {
 
 
                        wdt1: wdt@1e785000 {
-                               compatible = "aspeed,wdt";
-                               reg = <0x1e785000 0x1c>;
+                               compatible = "aspeed,ast2500-wdt";
+                               reg = <0x1e785000 0x20>;
                                interrupts = <27>;
                        };
 
                        wdt2: wdt@1e785020 {
-                               compatible = "aspeed,wdt";
-                               reg = <0x1e785020 0x1c>;
+                               compatible = "aspeed,ast2500-wdt";
+                               reg = <0x1e785020 0x20>;
                                interrupts = <27>;
                                status = "disabled";
                        };
 
                        wdt3: wdt@1e785040 {
-                               compatible = "aspeed,wdt";
-                               reg = <0x1e785074 0x1c>;
+                               compatible = "aspeed,ast2500-wdt";
+                               reg = <0x1e785040 0x20>;
                                status = "disabled";
                        };
 
                                no-loopback-test;
                                status = "disabled";
                        };
+
+                       adc: adc@1e6e9000 {
+                               compatible = "aspeed,ast2500-adc";
+                               reg = <0x1e6e9000 0xb0>;
+                               clocks = <&clk_apb>;
+                               #io-channel-cells = <1>;
+                               status = "disabled";
+                       };
                };
        };
 };
index 9f7f8a7d8ff9702443a4a3439fa77fb41ab0f630..0bef9e0b89c608fde1669cd524598bf411054a72 100644 (file)
 
                        shdwc@f8048010 {
                                atmel,shdwc-debouncer = <976>;
+                               atmel,wakeup-rtc-timer;
 
                                input@0 {
                                        reg = <0>;
index c51fc652f6c72639654150919ab7f03b3b7fecbc..5a53fcf542abb980d4cf18e0da4e9e790dddf0e2 100644 (file)
                        };
 
                        adc0: adc@f8018000 {
+                               atmel,adc-vref = <3300>;
+                               atmel,adc-channels-used = <0xfe>;
                                pinctrl-0 = <
                                        &pinctrl_adc0_adtrg
-                                       &pinctrl_adc0_ad0
                                        &pinctrl_adc0_ad1
                                        &pinctrl_adc0_ad2
                                        &pinctrl_adc0_ad3
                                        &pinctrl_adc0_ad5
                                        &pinctrl_adc0_ad6
                                        &pinctrl_adc0_ad7
-                                       &pinctrl_adc0_ad8
-                                       &pinctrl_adc0_ad9
                                        >;
                                status = "okay";
                        };
index 669a2c6bdefca2e0b9e70f18e282b59616c6d2d5..498fba3e52b58bb0918b4cd7e89d8049da3c1a69 100644 (file)
                #io-channel-cells = <1>;
        };
 
-       envelope-detector {
+       env_det: envelope-detector {
                compatible = "axentia,tse850-envelope-detector";
                io-channels = <&dac 0>;
                io-channel-names = "dac";
+               #io-channel-cells = <1>;
 
                interrupt-parent = <&pioA>;
                interrupts = <3 IRQ_TYPE_EDGE_RISING>;
                interrupt-names = "comp";
        };
 
+       mux: mux-controller {
+               compatible = "gpio-mux";
+               #mux-control-cells = <0>;
+
+               mux-gpios = <&pioA 0 GPIO_ACTIVE_HIGH>,
+                           <&pioA 1 GPIO_ACTIVE_HIGH>,
+                           <&pioA 2 GPIO_ACTIVE_HIGH>;
+               idle-state = <0>;
+       };
+
+       envelope-detector-mux {
+               compatible = "io-channel-mux";
+               io-channels = <&env_det 0>;
+               io-channel-names = "parent";
+
+               mux-controls = <&mux>;
+
+               channels = "", "",
+                        "sync-1",
+                        "in",
+                        "out",
+                        "sync-2",
+                        "sys-reg",
+                        "ana-reg";
+       };
+
        leds {
                compatible = "gpio-leds";
 
index 3fe77c38bd0db6940c2d6b5c97de020185535b43..7e80acda8f69d4fb1a1c3ed6de21361f3291ba09 100644 (file)
                        };
 
                        matrix: matrix@ffffee00 {
-                               compatible = "atmel,at91sam9260-bus-matrix", "syscon";
+                               compatible = "atmel,at91sam9261-matrix", "syscon";
                                reg = <0xffffee00 0x200>;
                        };
 
index 696b8ba064a679a7b15eb01d58fa98726241d4b6..9d2bbc41a7b0812d2460da3688090a58bd1f1b9d 100644 (file)
                        };
 
                        spi0: spi@f0000000 {
-                               status = "okay";
+                               status = "disabled"; /* conflicts with mmc1 */
                                cs-gpios = <&pioA 14 0>, <0>, <0>, <0>;
                                m25p80@0 {
                                        compatible = "atmel,at25df321a";
index 675bb0f30825b44abf72581aecb4fdd024964eee..9677dd5cf6b659a4eeb60b27ecfad2ff6305ec5f 100644 (file)
        interrupt-controller;
        #interrupt-cells = <1>;
 
+       ac_power_supply: ac-power-supply {
+               compatible = "x-powers,axp202-ac-power-supply";
+               status = "disabled";
+       };
+
        axp_gpio: gpio {
                compatible = "x-powers,axp209-gpio";
                gpio-controller;
index 458b6681e3ec54b37845b6245464e5385454c087..67331c5f171478056b9f7d937c2d22200af8296c 100644 (file)
        interrupt-controller;
        #interrupt-cells = <1>;
 
+       ac_power_supply: ac-power-supply {
+               compatible = "x-powers,axp221-ac-power-supply";
+               status = "disabled";
+       };
+
        regulators {
                /* Default work frequency for buck regulators */
                x-powers,dcdc-freq = <3000>;
index 8833a4c3cd9695a7a6a14159bd0a3ad4578a8e9f..9644fddb5e3c3d6250f304dfee7c4ffa3bd90071 100644 (file)
                        status = "disabled";
 
                        msi-parent = <&msi0>;
-                       msi0: msi@18012000 {
+                       msi0: msi-controller {
                                compatible = "brcm,iproc-msi";
                                msi-controller;
                                interrupt-parent = <&gic>;
                        status = "disabled";
 
                        msi-parent = <&msi1>;
-                       msi1: msi@18013000 {
+                       msi1: msi-controller {
                                compatible = "brcm,iproc-msi";
                                msi-controller;
                                interrupt-parent = <&gic>;
index 832795b0fd0ff8ad167433af83688813c2952341..fe6cba994a97df53b42cb7bef77e89cf18d280c9 100644 (file)
                        status = "disabled";
                };
 
+               mailbox: mailbox@25000 {
+                       compatible = "brcm,iproc-fa2-mbox";
+                       reg = <0x25000 0x445>;
+                       interrupts = <GIC_SPI 150 IRQ_TYPE_LEVEL_HIGH>;
+                       #mbox-cells = <1>;
+                       brcm,rx-status-len = <32>;
+                       brcm,use-bcm-hdr;
+               };
+
                nand: nand@26000 {
                        compatible = "brcm,nand-iproc", "brcm,brcmnand-v6.1";
                        reg = <0x026000 0x600>,
                        #size-cells = <0>;
                };
 
+               crypto@2f000 {
+                       compatible = "brcm,spum-nsp-crypto";
+                       reg = <0x2f000 0x900>;
+                       mboxes = <&mailbox 0>;
+               };
+
                gpiob: gpio@30000 {
                        compatible = "brcm,iproc-nsp-gpio", "brcm,iproc-gpio";
                        reg = <0x30000 0x50>;
                        status = "disabled";
                };
 
+               ehci0: usb@2a000 {
+                       compatible = "generic-ehci";
+                       reg = <0x2a000 0x100>;
+                       interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
+                       status = "disabled";
+               };
+
+               ohci0: usb@2b000 {
+                       compatible = "generic-ohci";
+                       reg = <0x2b000 0x100>;
+                       interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
+                       status = "disabled";
+               };
+
                rng: rng@33000 {
                        compatible = "brcm,bcm-nsp-rng";
                        reg = <0x33000 0x14>;
                        #size-cells = <0>;
                        interrupts = <GIC_SPI 89 IRQ_TYPE_NONE>;
                        clock-frequency = <100000>;
+                       status = "disabled";
                };
 
                watchdog@39000 {
                status = "disabled";
 
                msi-parent = <&msi0>;
-               msi0: msi@18012000 {
+               msi0: msi-controller {
                        compatible = "brcm,iproc-msi";
                        msi-controller;
                        interrupt-parent = <&gic>;
                status = "disabled";
 
                msi-parent = <&msi1>;
-               msi1: msi@18013000 {
+               msi1: msi-controller {
                        compatible = "brcm,iproc-msi";
                        msi-controller;
                        interrupt-parent = <&gic>;
                status = "disabled";
 
                msi-parent = <&msi2>;
-               msi2: msi@18014000 {
+               msi2: msi-controller {
                        compatible = "brcm,iproc-msi";
                        msi-controller;
                        interrupt-parent = <&gic>;
index 38e6050035bcdc1dd9efb1f88581a9f58f226bd1..a7b5ce133784f12bee9ff2199d9e85c757fd4e17 100644 (file)
        bus-width = <4>;
 };
 
+&sdhost {
+       pinctrl-names = "default";
+       pinctrl-0 = <&sdhost_gpio48>;
+       bus-width = <4>;
+};
+
 &pwm {
        pinctrl-names = "default";
        pinctrl-0 = <&pwm0_gpio40 &pwm1_gpio45>;
        power-domains = <&power RPI_POWER_DOMAIN_VEC>;
        status = "okay";
 };
+
+&dsi0 {
+       power-domains = <&power RPI_POWER_DOMAIN_DSI0>;
+};
+
+&dsi1 {
+       power-domains = <&power RPI_POWER_DOMAIN_DSI1>;
+};
index 12c981e5113489ea785d8f4d8b0a5b9f99d61beb..9a0599f711ff3382a7b908bb72e9f0392db5e1bf 100644 (file)
@@ -1,6 +1,6 @@
 / {
        aliases {
-               ethernet = &ethernet;
+               ethernet0 = &ethernet;
        };
 };
 
index 3f0a56ebcf1f64692cbdd311752ce8d1fd36a5f1..dc7ae776db5fc0ca54e91ef6369fbaee71162d22 100644 (file)
@@ -1,6 +1,6 @@
 / {
        aliases {
-               ethernet = &ethernet;
+               ethernet0 = &ethernet;
        };
 };
 
index a3106aa446c6906108c90952cd39520ff195ef79..561f27d8d92224fe8f4f8c3224a5441f2d41175a 100644 (file)
                        #clock-cells = <1>;
                        reg = <0x7e101000 0x2000>;
 
-                       /* CPRMAN derives everything from the platform's
-                        * oscillator.
+                       /* CPRMAN derives almost everything from the
+                        * platform's oscillator.  However, the DSI
+                        * pixel clocks come from the DSI analog PHY.
                         */
-                       clocks = <&clk_osc>;
+                       clocks = <&clk_osc>,
+                               <&dsi0 0>, <&dsi0 1>, <&dsi0 2>,
+                               <&dsi1 0>, <&dsi1 1>, <&dsi1 2>;
                };
 
                rng@7e104000 {
                                brcm,pins = <0 1>;
                                brcm,function = <BCM2835_FSEL_ALT0>;
                        };
-                       i2c0_gpio32: i2c0_gpio32 {
-                               brcm,pins = <32 34>;
+                       i2c0_gpio28: i2c0_gpio28 {
+                               brcm,pins = <28 29>;
                                brcm,function = <BCM2835_FSEL_ALT0>;
                        };
                        i2c0_gpio44: i2c0_gpio44 {
                        /* Separate from the uart0_gpio14 group
                         * because it conflicts with spi1_gpio16, and
                         * people often run uart0 on the two pins
-                        * without flow contrl.
+                        * without flow control.
                         */
                        uart0_ctsrts_gpio16: uart0_ctsrts_gpio16 {
                                brcm,pins = <16 17>;
                                brcm,function = <BCM2835_FSEL_ALT3>;
                        };
-                       uart0_gpio30: uart0_gpio30 {
+                       uart0_ctsrts_gpio30: uart0_ctsrts_gpio30 {
                                brcm,pins = <30 31>;
                                brcm,function = <BCM2835_FSEL_ALT3>;
                        };
-                       uart0_ctsrts_gpio32: uart0_ctsrts_gpio32 {
+                       uart0_gpio32: uart0_gpio32 {
                                brcm,pins = <32 33>;
                                brcm,function = <BCM2835_FSEL_ALT3>;
                        };
+                       uart0_gpio36: uart0_gpio36 {
+                               brcm,pins = <36 37>;
+                               brcm,function = <BCM2835_FSEL_ALT2>;
+                       };
+                       uart0_ctsrts_gpio38: uart0_ctsrts_gpio38 {
+                               brcm,pins = <38 39>;
+                               brcm,function = <BCM2835_FSEL_ALT2>;
+                       };
 
                        uart1_gpio14: uart1_gpio14 {
                                brcm,pins = <14 15>;
                                brcm,pins = <30 31>;
                                brcm,function = <BCM2835_FSEL_ALT5>;
                        };
-                       uart1_gpio36: uart1_gpio36 {
-                               brcm,pins = <36 37 38 39>;
-                               brcm,function = <BCM2835_FSEL_ALT2>;
-                       };
                        uart1_gpio40: uart1_gpio40 {
                                brcm,pins = <40 41>;
                                brcm,function = <BCM2835_FSEL_ALT5>;
                        arm,primecell-periphid = <0x00241011>;
                };
 
+               sdhost: mmc@7e202000 {
+                       compatible = "brcm,bcm2835-sdhost";
+                       reg = <0x7e202000 0x100>;
+                       interrupts = <2 24>;
+                       clocks = <&clocks BCM2835_CLOCK_VPU>;
+                       dmas = <&dma 13>;
+                       dma-names = "rx-tx";
+                       status = "disabled";
+               };
+
                i2s: i2s@7e203000 {
                        compatible = "brcm,bcm2835-i2s";
                        reg = <0x7e203000 0x20>,
                        interrupts = <2 14>; /* pwa1 */
                };
 
+               dsi0: dsi@7e209000 {
+                       compatible = "brcm,bcm2835-dsi0";
+                       reg = <0x7e209000 0x78>;
+                       interrupts = <2 4>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       #clock-cells = <1>;
+
+                       clocks = <&clocks BCM2835_PLLA_DSI0>,
+                                <&clocks BCM2835_CLOCK_DSI0E>,
+                                <&clocks BCM2835_CLOCK_DSI0P>;
+                       clock-names = "phy", "escape", "pixel";
+
+                       clock-output-names = "dsi0_byte",
+                                            "dsi0_ddr2",
+                                            "dsi0_ddr";
+
+               };
+
                thermal: thermal@7e212000 {
                        compatible = "brcm,bcm2835-thermal";
                        reg = <0x7e212000 0x8>;
                        interrupts = <2 1>;
                };
 
+               dsi1: dsi@7e700000 {
+                       compatible = "brcm,bcm2835-dsi1";
+                       reg = <0x7e700000 0x8c>;
+                       interrupts = <2 12>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       #clock-cells = <1>;
+
+                       clocks = <&clocks BCM2835_PLLD_DSI1>,
+                                <&clocks BCM2835_CLOCK_DSI1E>,
+                                <&clocks BCM2835_CLOCK_DSI1P>;
+                       clock-names = "phy", "escape", "pixel";
+
+                       clock-output-names = "dsi1_byte",
+                                            "dsi1_ddr2",
+                                            "dsi1_ddr";
+
+                       status = "disabled";
+               };
+
                i2c1: i2c@7e804000 {
                        compatible = "brcm,bcm2835-i2c";
                        reg = <0x7e804000 0x1000>;
                        clocks = <&clocks BCM2835_PLLH_PIX>,
                                 <&clocks BCM2835_CLOCK_HSM>;
                        clock-names = "pixel", "hdmi";
+                       dmas = <&dma 17>;
+                       dma-names = "audio-rx";
                        status = "disabled";
                };
 
index d241cee4bfcca92451721a1217fe4c446ef69aba..4175174e589a50ec388e795cc4bdc2ea1f0f31f6 100644 (file)
@@ -4,7 +4,17 @@
  *
  * Copyright (C) 2015 Rafał Miłecki <zajec5@gmail.com>
  *
- * Licensed under the GNU/GPL. See COPYING for details.
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
  */
 
 /dts-v1/;
                usb3 {
                        label = "bcm53xx:blue:usb3";
                        gpios = <&chipcommon 0 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                wan {
                        label = "bcm53xx:blue:wan";
                        gpios = <&chipcommon 1 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                lan {
                        label = "bcm53xx:blue:lan";
                        gpios = <&chipcommon 2 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                power {
                2ghz {
                        label = "bcm53xx:blue:2ghz";
                        gpios = <&chipcommon 6 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
 
                usb2 {
                        label = "bcm53xx:blue:usb2";
                        gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
        };
 
index b0e62042f62fe2427729866fe52825cc2099e84c..8fa033fea95905ca0e0bb241efad9bfd3a756f8b 100644 (file)
@@ -4,7 +4,17 @@
  *
  * Copyright (C) 2015 Rafał Miłecki <zajec5@gmail.com>
  *
- * Licensed under the GNU/GPL. See COPYING for details.
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
  */
 
 /dts-v1/;
@@ -31,7 +41,6 @@
                usb2 {
                        label = "bcm53xx:blue:usb2";
                        gpios = <&chipcommon 0 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                power {
@@ -49,7 +58,6 @@
                usb3 {
                        label = "bcm53xx:blue:usb3";
                        gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
        };
 
index c9ba6b964b3853941961ca6f22c1cd207fb366fa..62e1427b3f1076072301e14b6c26aead71235bd4 100644 (file)
                usb {
                        label = "bcm53xx:blue:usb";
                        gpios = <&hc595 0 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                power0 {
                        label = "bcm53xx:red:power";
                        gpios = <&hc595 1 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                power1 {
@@ -76,7 +74,6 @@
                router1 {
                        label = "bcm53xx:amber:router";
                        gpios = <&hc595 4 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                wan {
                wireless0 {
                        label = "bcm53xx:blue:wireless";
                        gpios = <&hc595 6 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                wireless1 {
                        label = "bcm53xx:amber:wireless";
                        gpios = <&hc595 7 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
        };
 
diff --git a/arch/arm/boot/dts/bcm4708-linksys-ea6300-v1.dts b/arch/arm/boot/dts/bcm4708-linksys-ea6300-v1.dts
new file mode 100644 (file)
index 0000000..126ab58
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2017 Rafał Miłecki <rafal@milecki.pl>
+ *
+ * Licensed under the ISC license.
+ */
+
+/dts-v1/;
+
+#include "bcm4708.dtsi"
+#include "bcm5301x-nand-cs0-bch8.dtsi"
+
+/ {
+       compatible = "linksys,ea6300-v1", "brcm,bcm4708";
+       model = "Linksys EA6300 V1";
+
+       chosen {
+               bootargs = "console=ttyS0,115200";
+       };
+
+       memory {
+               reg = <0x00000000 0x08000000>;
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               wps {
+                       label = "WPS";
+                       linux,code = <KEY_WPS_BUTTON>;
+                       gpios = <&chipcommon 7 GPIO_ACTIVE_LOW>;
+               };
+
+               restart {
+                       label = "Reset";
+                       linux,code = <KEY_RESTART>;
+                       gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>;
+               };
+       };
+};
index b9f66c0fae27246229543b63cc8081a1f34d8e32..a5647efe41187eaa2e0dc70d9bfc125856562f45 100644 (file)
                power1 {
                        label = "bcm53xx:amber:power";
                        gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                usb {
                        label = "bcm53xx:blue:usb";
                        gpios = <&chipcommon 8 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                wireless {
                        label = "bcm53xx:blue:wireless";
                        gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
        };
 
index ae0199f6c7a231cef44891234f3c2446b9325ad4..bb66cebe0bd89279647080ca9196cbc2f205211e 100644 (file)
@@ -4,7 +4,17 @@
  *
  * Copyright (C) 2014 Rafał Miłecki <zajec5@gmail.com>
  *
- * Licensed under the GNU/GPL. See COPYING for details.
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
  */
 
 /dts-v1/;
@@ -37,7 +47,6 @@
                power0 {
                        label = "bcm53xx:green:power";
                        gpios = <&chipcommon 2 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                power1 {
                usb {
                        label = "bcm53xx:blue:usb";
                        gpios = <&chipcommon 8 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                wireless {
                        label = "bcm53xx:blue:wireless";
                        gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
        };
 
index 36b628b190d7d098e7d1c1ca97242d62a61ad1cf..19ee924d7d53fa0c1b86bbbbf0d3787ea8a0bbfa 100644 (file)
                power-amber {
                        label = "bcm53xx:amber:power";
                        gpios = <&chipcommon 2 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                usb2 {
                        label = "bcm53xx:white:usb2";
                        gpios = <&chipcommon 3 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                usb3-white {
                        label = "bcm53xx:white:usb3";
                        gpios = <&chipcommon 4 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                usb3-green {
                        label = "bcm53xx:green:usb3";
                        gpios = <&chipcommon 5 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                wps {
                        label = "bcm53xx:white:wps";
                        gpios = <&chipcommon 6 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                status-red {
                        label = "bcm53xx:red:status";
                        gpios = <&chipcommon 8 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                status-green {
                        label = "bcm53xx:green:status";
                        gpios = <&chipcommon 9 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                status-blue {
                        label = "bcm53xx:blue:status";
                        gpios = <&chipcommon 10 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                wan-white {
                        label = "bcm53xx:white:wan";
                        gpios = <&chipcommon 12 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                wan-red {
                        label = "bcm53xx:red:wan";
                        gpios = <&chipcommon 13 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
        };
 
index d0eec099f1f8cda749315e8e29b1a95ca295fa09..1a19e97a987db95a72da47cda58f22a84d682b09 100644 (file)
 / {
        compatible = "brcm,bcm4708";
 
+       aliases {
+               serial0 = &uart0;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
index db8608be0ee7ebac7ec951900163cfd4f1213ff2..0800a964f2fea5d55efa6f004f168f6155b6b7b6 100644 (file)
@@ -4,7 +4,17 @@
  *
  * Copyright (C) 2014 Rafał Miłecki <zajec5@gmail.com>
  *
- * Licensed under the GNU/GPL. See COPYING for details.
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
  */
 
 /dts-v1/;
@@ -37,7 +47,6 @@
                usb2 {
                        label = "bcm53xx:blue:usb2";
                        gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                wan {
@@ -55,7 +64,6 @@
                usb3 {
                        label = "bcm53xx:blue:usb3";
                        gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
        };
 
index d51586d95b9a0cb1dba7745793a8ba01dd17cc6f..c2af33eb47de0ea1981acc54b969eece18bf1424 100644 (file)
@@ -4,7 +4,17 @@
  *
  * Copyright (C) 2014 Rafał Miłecki <zajec5@gmail.com>
  *
- * Licensed under the GNU/GPL. See COPYING for details.
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
  */
 
 /dts-v1/;
@@ -58,7 +68,6 @@
                power1 {
                        label = "bcm53xx:red:power";
                        gpios = <&hc595 2 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                router0 {
@@ -70,7 +79,6 @@
                router1 {
                        label = "bcm53xx:amber:router";
                        gpios = <&hc595 4 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                wan {
                wireless0 {
                        label = "bcm53xx:green:wireless";
                        gpios = <&hc595 6 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                wireless1 {
                        label = "bcm53xx:amber:wireless";
                        gpios = <&hc595 7 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
        };
 
index de041b8c3342d4aec5f11cfb2c34e2545dcb04ae..8bef6429feeeb81a5bf23a0d1328d4cacfeb58f7 100644 (file)
@@ -4,7 +4,17 @@
  *
  * Copyright (C) 2015 Rafał Miłecki <zajec5@gmail.com>
  *
- * Licensed under the GNU/GPL. See COPYING for details.
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
  */
 
 /dts-v1/;
diff --git a/arch/arm/boot/dts/bcm47081-tplink-archer-c5-v2.dts b/arch/arm/boot/dts/bcm47081-tplink-archer-c5-v2.dts
new file mode 100644 (file)
index 0000000..a854a51
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2017 Rafał Miłecki <rafal@milecki.pl>
+ *
+ * Licensed under the ISC license.
+ */
+
+/dts-v1/;
+
+#include "bcm47081.dtsi"
+
+/ {
+       compatible = "tplink,archer-c5-v2", "brcm,bcm47081", "brcm,bcm4708";
+       model = "TP-LINK Archer C5 V2";
+
+       chosen {
+               bootargs = "earlycon";
+       };
+
+       memory {
+               reg = <0x00000000 0x08000000>;
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               2ghz {
+                       label = "bcm53xx:green:2ghz";
+                       gpios = <&chipcommon 0 GPIO_ACTIVE_HIGH>;
+               };
+
+               lan {
+                       label = "bcm53xx:green:lan";
+                       gpios = <&chipcommon 1 GPIO_ACTIVE_HIGH>;
+               };
+
+               usb2-port1 {
+                       label = "bcm53xx:green:usb2-port1";
+                       gpios = <&chipcommon 2 GPIO_ACTIVE_HIGH>;
+               };
+
+               power {
+                       label = "bcm53xx:green:power";
+                       gpios = <&chipcommon 4 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "default-on";
+               };
+
+               wan-green {
+                       label = "bcm53xx:green:wan";
+                       gpios = <&chipcommon 5 GPIO_ACTIVE_HIGH>;
+               };
+
+               wps {
+                       label = "bcm53xx:green:wps";
+                       gpios = <&chipcommon 6 GPIO_ACTIVE_HIGH>;
+               };
+
+               wan-amber {
+                       label = "bcm53xx:amber:wan";
+                       gpios = <&chipcommon 8 GPIO_ACTIVE_HIGH>;
+               };
+
+               5ghz {
+                       label = "bcm53xx:green:5ghz";
+                       gpios = <&chipcommon 12 GPIO_ACTIVE_HIGH>;
+               };
+
+               usb2-port2 {
+                       label = "bcm53xx:green:usb2-port2";
+                       gpios = <&chipcommon 13 GPIO_ACTIVE_HIGH>;
+               };
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               rfkill {
+                       label = "WiFi";
+                       linux,code = <KEY_RFKILL>;
+                       gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
+               };
+
+               restart {
+                       label = "Reset";
+                       linux,code = <KEY_RESTART>;
+                       gpios = <&chipcommon 7 GPIO_ACTIVE_LOW>;
+               };
+       };
+};
+
+&spi_nor {
+       status = "okay";
+};
+
+&usb2 {
+       vcc-gpio = <&chipcommon 9 GPIO_ACTIVE_HIGH>;
+};
index c5f7619af4a651b53761ec5ec4aa0cd5134d13af..9829d044aaf44a6b4cc2f65dca508b9e3195d44a 100644 (file)
@@ -4,7 +4,17 @@
  *
  * Copyright © 2014 Rafał Miłecki <zajec5@gmail.com>
  *
- * Licensed under the GNU/GPL. See COPYING for details.
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
  */
 
 #include "bcm5301x.dtsi"
 / {
        compatible = "brcm,bcm47081";
 
+       aliases {
+               serial0 = &uart0;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
index eaca6876db0f22395bfde65c2527d05bce6747f9..df473cc41572932722d7a9de14b5711df5df976f 100644 (file)
@@ -4,7 +4,17 @@
  *
  * Copyright (C) 2015 Rafał Miłecki <zajec5@gmail.com>
  *
- * Licensed under the GNU/GPL. See COPYING for details.
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
  */
 
 /dts-v1/;
@@ -31,7 +41,6 @@
                wps {
                        label = "bcm53xx:blue:wps";
                        gpios = <&chipcommon 1 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                power {
@@ -43,7 +52,6 @@
                wan {
                        label = "bcm53xx:red:wan";
                        gpios = <&chipcommon 5 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
        };
 
index b32957ca9443f250ee1e868ebb1cebc96f9a2dcd..92058c73ee59548e48766cbb0475ddb75cf75594 100644 (file)
                usb {
                        label = "bcm53xx:green:usb";
                        gpios = <&chipcommon 4 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                power-amber {
                        label = "bcm53xx:amber:power";
                        gpios = <&chipcommon 5 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                power-white {
                router-amber {
                        label = "bcm53xx:amber:router";
                        gpios = <&chipcommon 7 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                router-white {
                        label = "bcm53xx:white:router";
                        gpios = <&chipcommon 8 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                wan-amber {
                        label = "bcm53xx:amber:wan";
                        gpios = <&chipcommon 9 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                wan-white {
                        label = "bcm53xx:white:wan";
                        gpios = <&chipcommon 10 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                wireless-amber {
                        label = "bcm53xx:amber:wireless";
                        gpios = <&chipcommon 11 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                wireless-white {
                        label = "bcm53xx:white:wireless";
                        gpios = <&chipcommon 12 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
        };
 
diff --git a/arch/arm/boot/dts/bcm4709-linksys-ea9200.dts b/arch/arm/boot/dts/bcm4709-linksys-ea9200.dts
new file mode 100644 (file)
index 0000000..3d1d9c2
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2017 Rafał Miłecki <rafal@milecki.pl>
+ *
+ * Licensed under the ISC license.
+ */
+
+/dts-v1/;
+
+#include "bcm4709.dtsi"
+#include "bcm5301x-nand-cs0-bch8.dtsi"
+
+/ {
+       compatible = "linksys,ea9200", "brcm,bcm4709", "brcm,bcm4708";
+       model = "Linksys EA9200";
+
+       chosen {
+               bootargs = "console=ttyS0,115200";
+       };
+
+       memory {
+               reg = <0x00000000 0x08000000
+                      0x88000000 0x08000000>;
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               wps {
+                       label = "WPS";
+                       linux,code = <KEY_WPS_BUTTON>;
+                       gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
+               };
+
+               restart {
+                       label = "Reset";
+                       linux,code = <KEY_RESTART>;
+                       gpios = <&chipcommon 17 GPIO_ACTIVE_LOW>;
+               };
+       };
+};
index f459a98a72c671a0729cab3a061357940bff7167..f43ab47214561ea82d52553b874528c4d92e7ed5 100644 (file)
@@ -4,7 +4,17 @@
  *
  * Copyright (C) 2015 Rafał Miłecki <zajec5@gmail.com>
  *
- * Licensed under the GNU/GPL. See COPYING for details.
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
  */
 
 /dts-v1/;
                power-amber {
                        label = "bcm53xx:amber:power";
                        gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                5ghz {
                        label = "bcm53xx:white:5ghz";
                        gpios = <&chipcommon 12 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                2ghz {
                        label = "bcm53xx:white:2ghz";
                        gpios = <&chipcommon 13 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                wps {
                        label = "bcm53xx:white:wps";
                        gpios = <&chipcommon 14 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                wireless {
                        label = "bcm53xx:white:wireless";
                        gpios = <&chipcommon 15 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                usb3 {
                        label = "bcm53xx:white:usb3";
                        gpios = <&chipcommon 17 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                usb2 {
                        label = "bcm53xx:white:usb2";
                        gpios = <&chipcommon 18 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
        };
 
index 8e39a84e5bf9eb23ca0f0fc0efd9cfd5f5ba410e..d266131652addd105eb8750255a2f825a6c724a6 100644 (file)
@@ -4,7 +4,17 @@
  *
  * Copyright (C) 2015 Rafał Miłecki <zajec5@gmail.com>
  *
- * Licensed under the GNU/GPL. See COPYING for details.
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
  */
 
 /dts-v1/;
        leds {
                compatible = "gpio-leds";
 
-               power0 {
+               power-white {
                        label = "bcm53xx:white:power";
                        gpios = <&chipcommon 2 GPIO_ACTIVE_LOW>;
                        linux,default-trigger = "default-on";
                };
 
-               power1 {
+               power-amber {
                        label = "bcm53xx:amber:power";
                        gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
+               };
+
+               wan-white {
+                       label = "bcm53xx:white:wan";
+                       gpios = <&chipcommon 8 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "default-on";
+               };
+
+               wan-amber {
+                       label = "bcm53xx:amber:wan";
+                       gpios = <&chipcommon 9 GPIO_ACTIVE_HIGH>;
                };
 
                5ghz-1 {
                        label = "bcm53xx:white:5ghz-1";
                        gpios = <&chipcommon 12 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                2ghz {
                        label = "bcm53xx:white:2ghz";
                        gpios = <&chipcommon 13 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                wireless {
                        label = "bcm53xx:white:wireless";
                        gpios = <&chipcommon 14 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                wps {
                        label = "bcm53xx:white:wps";
                        gpios = <&chipcommon 15 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                5ghz-2 {
                        label = "bcm53xx:white:5ghz-2";
                        gpios = <&chipcommon 16 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                usb3 {
                        label = "bcm53xx:white:usb3";
                        gpios = <&chipcommon 17 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                usb2 {
                        label = "bcm53xx:white:usb2";
                        gpios = <&chipcommon 18 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
        };
 
                        linux,code = <KEY_RESTART>;
                        gpios = <&chipcommon 6 GPIO_ACTIVE_LOW>;
                };
+
+               brightness {
+                       label = "Backlight";
+                       linux,code = <KEY_BRIGHTNESS_ZERO>;
+                       gpios = <&chipcommon 19 GPIO_ACTIVE_LOW>;
+               };
        };
 };
 
index c67bfaa0c8e824bda8e6da609ff893cd3f054e1a..97aa5d59a1d805f155846fad9fec15deaf6765b0 100644 (file)
                lan {
                        label = "bcm53xx:blue:lan";
                        gpios = <&chipcommon 1 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                wps {
                        label = "bcm53xx:blue:wps";
                        gpios = <&chipcommon 2 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                2ghz {
                        label = "bcm53xx:blue:2ghz";
                        gpios = <&chipcommon 4 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                5ghz {
                        label = "bcm53xx:blue:5ghz";
                        gpios = <&chipcommon 5 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                usb3 {
                        label = "bcm53xx:blue:usb3";
                        gpios = <&chipcommon 6 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                usb2 {
                        label = "bcm53xx:blue:usb2";
                        gpios = <&chipcommon 7 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                wan-blue {
                        label = "bcm53xx:blue:wan";
                        gpios = <&chipcommon 14 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                wan-amber {
                        label = "bcm53xx:amber:wan";
                        gpios = <&chipcommon 15 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                power {
index 64ded7643e9f3fcf41d49870947357a097769fa0..51b0641b5f79c9f0a2cff8e1a9b94233d2fc4dac 100644 (file)
@@ -4,7 +4,17 @@
  *
  * Copyright (C) 2016 Rafał Miłecki <zajec5@gmail.com>
  *
- * Licensed under the GNU/GPL. See COPYING for details.
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
  */
 
 /dts-v1/;
                wan-white {
                        label = "bcm53xx:white:wan";
                        gpios = <&chipcommon 1 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                power-amber {
                        label = "bcm53xx:amber:power";
                        gpios = <&chipcommon 2 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                wan-amber {
                        label = "bcm53xx:amber:wan";
                        gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                usb3-white {
                        label = "bcm53xx:white:usb3";
                        gpios = <&chipcommon 8 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                2ghz {
                        label = "bcm53xx:white:2ghz";
                        gpios = <&chipcommon 13 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                5ghz {
                        label = "bcm53xx:white:5ghz";
                        gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
        };
 
diff --git a/arch/arm/boot/dts/bcm47094-linksys-panamera.dts b/arch/arm/boot/dts/bcm47094-linksys-panamera.dts
new file mode 100644 (file)
index 0000000..b6750f7
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2017 Rafał Miłecki <rafal@milecki.pl>
+ *
+ * Licensed under the ISC license.
+ */
+
+/dts-v1/;
+
+#include "bcm47094.dtsi"
+#include "bcm5301x-nand-cs0-bch8.dtsi"
+
+/ {
+       compatible = "linksys,panamera", "brcm,bcm47094", "brcm,bcm4708";
+       model = "Linksys EA9500";
+
+       chosen {
+               bootargs = "console=ttyS0,115200";
+       };
+
+       memory {
+               reg = <0x00000000 0x08000000
+                      0x88000000 0x08000000>;
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               wps {
+                       label = "WPS";
+                       linux,code = <KEY_WPS_BUTTON>;
+                       gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
+               };
+       };
+};
index 5cf4ab1ebe851e19c9e8133bd7a891415cdf4ea0..5f8621d00c5003282eaf68608ab24d3c02d5b94e 100644 (file)
                lan3    {
                        label = "bcm53xx:green:lan3";
                        gpios = <&chipcommon 1 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                lan4    {
                        label = "bcm53xx:green:lan4";
                        gpios = <&chipcommon 2 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                wan     {
                        label = "bcm53xx:green:wan";
                        gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                lan1    {
                        label = "bcm53xx:green:lan1";
                        gpios = <&chipcommon 4 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                lan2    {
                        label = "bcm53xx:green:lan2";
                        gpios = <&chipcommon 6 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                usb3    {
                        label = "bcm53xx:green:usb3";
                        gpios = <&chipcommon 8 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                status  {
                2ghz {
                        label = "bcm53xx:green:2ghz";
                        gpios = <&chipcommon 13 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                5ghz {
                        label = "bcm53xx:green:5ghz";
                        gpios = <&chipcommon 14 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
        };
 
index 600795ee1aed3a3da9c6b01590183ba004ea4068..859929973158fed4c71c7c8819ffc55657c6f7b2 100644 (file)
                power1 {
                        label = "bcm53xx:amber:power";
                        gpios = <&chipcommon 3 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                5ghz-1 {
                        label = "bcm53xx:white:5ghz-1";
                        gpios = <&chipcommon 11 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                5ghz-2 {
                        label = "bcm53xx:white:5ghz-2";
                        gpios = <&chipcommon 12 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                2ghz {
                        label = "bcm53xx:white:2ghz";
                        gpios = <&chipcommon 13 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                usb2 {
                        label = "bcm53xx:white:usb2";
                        gpios = <&chipcommon 17 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
 
                usb3 {
                        label = "bcm53xx:white:usb3";
                        gpios = <&chipcommon 18 GPIO_ACTIVE_LOW>;
-                       linux,default-trigger = "default-off";
                };
        };
 
index 4403ae8790c2e5d04eb8afbf9bb2663b4812ddc0..34417dac1cd0937292469da3b86b54f2e8cfff1c 100644 (file)
                usb {
                        label = "bcm53xx:blue:usb";
                        gpios = <&chipcommon 1 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                wps {
                        label = "bcm53xx:blue:wps";
                        gpios = <&chipcommon 10 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                5ghz {
                        label = "bcm53xx:blue:5ghz";
                        gpios = <&chipcommon 11 GPIO_ACTIVE_HIGH>;
-                       linux,default-trigger = "default-off";
                };
 
                system {
                };
        };
 
+       pcie0_leds {
+               compatible = "gpio-leds";
+
+               2ghz {
+                       label = "bcm53xx:blue:2ghz";
+                       gpios = <&pcie0_chipcommon 3 GPIO_ACTIVE_HIGH>;
+               };
+       };
+
        gpio-keys {
                compatible = "gpio-keys";
                #address-cells = <1>;
                };
        };
 };
+
+&pcie0 {
+       ranges = <0x00000000 0 0 0 0 0x00100000>;
+       #address-cells = <3>;
+       #size-cells = <2>;
+
+       bridge@0,0,0 {
+               reg = <0x0000 0 0 0 0>;
+               ranges = <0x00000000 0 0 0 0 0 0 0x00100000>;
+               #address-cells = <3>;
+               #size-cells = <2>;
+
+               wifi@0,1,0 {
+                       reg = <0x0000 0 0 0 0>;
+                       ranges = <0x00000000 0 0 0 0x00100000>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+
+                       pcie0_chipcommon: chipcommon@0 {
+                               reg = <0 0x1000>;
+
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                       };
+               };
+       };
+};
index 00de62dc0042f1445851d1cb84c2cbea3e28d25f..acee36a610047f69383990ebc980508ea6e47fd8 100644 (file)
 / {
        interrupt-parent = <&gic>;
 
-       chosen {
-               stdout-path = &uart0;
-       };
-
        chipcommonA {
                compatible = "simple-bus";
                ranges = <0x00000000 0x18000000 0x00001000>;
                        clocks = <&periph_clk>;
                };
 
-               local-timer@20600 {
+               timer@20600 {
                        compatible = "arm,cortex-a9-twd-timer";
-                       reg = <0x20600 0x100>;
-                       interrupts = <GIC_PPI 13 IRQ_TYPE_EDGE_RISING>;
+                       reg = <0x20600 0x20>;
+                       interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) |
+                                                 IRQ_TYPE_EDGE_RISING)>;
+                       clocks = <&periph_clk>;
+               };
+
+               watchdog@20620 {
+                       compatible = "arm,cortex-a9-twd-wdt";
+                       reg = <0x20620 0x20>;
+                       interrupts = <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(2) |
+                                                 IRQ_TYPE_EDGE_RISING)>;
                        clocks = <&periph_clk>;
                };
 
                        };
                };
 
-               spi@29000 {
-                       reg = <0x00029000 0x1000>;
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-
-                       spi_nor: spi-nor@0 {
-                               compatible = "jedec,spi-nor";
-                               reg = <0>;
-                               spi-max-frequency = <20000000>;
-                               linux,part-probe = "ofpart", "bcm47xxpart";
-                               status = "disabled";
-                       };
-               };
-
                gmac0: ethernet@24000 {
                        reg = <0x24000 0x800>;
                };
                };
        };
 
+       i2c0: i2c@18009000 {
+               compatible = "brcm,iproc-i2c";
+               reg = <0x18009000 0x50>;
+               interrupts = <GIC_SPI 121 IRQ_TYPE_NONE>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               clock-frequency = <100000>;
+               status = "disabled";
+       };
+
        lcpll0: lcpll0@1800c100 {
                #clock-cells = <1>;
                compatible = "brcm,nsp-lcpll0";
 
                brcm,nand-has-wp;
        };
+
+       spi@18029200 {
+               compatible = "brcm,spi-bcm-qspi", "brcm,spi-nsp-qspi";
+               reg = <0x18029200 0x184>,
+                     <0x18029000 0x124>,
+                     <0x1811b408 0x004>,
+                     <0x180293a0 0x01c>;
+               reg-names = "mspi", "bspi", "intr_regs", "intr_status_reg";
+               interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "spi_lr_fullness_reached",
+                                 "spi_lr_session_aborted",
+                                 "spi_lr_impatient",
+                                 "spi_lr_session_done",
+                                 "spi_lr_overhead",
+                                 "mspi_done",
+                                 "mspi_halted";
+               clocks = <&iprocmed>;
+               clock-names = "iprocmed";
+               num-cs = <2>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               spi_nor: spi-nor@0 {
+                       compatible = "jedec,spi-nor";
+                       reg = <0>;
+                       spi-max-frequency = <20000000>;
+                       linux,part-probe = "ofpart", "bcm47xxpart";
+                       status = "disabled";
+               };
+       };
 };
index 2da04d0a734892d66bc8bb9ec7209b16623627dc..eae623f7640138abb794f52cfc2604321947308e 100644 (file)
 / {
        interrupt-parent = <&gic>;
 
+       aliases {
+               serial0 = &uart0;
+       };
+
        chosen {
-               stdout-path = &uart0;
+               stdout-path = "serial0:115200n8";
        };
 
        cpus {
                        };
                };
 
+               pcie0: pcie@2000 {
+                       reg = <0x00002000 0x1000>;
+               };
+
                usb2: usb2@4000 {
                        reg = <0x4000 0x1000>;
                        ranges;
index 42855a7c1bfa6ca07bb08383107a20fc84c07e1a..2e08c895f2818cefbb799a5011190bfd724c0225 100644 (file)
        model = "NorthStar SVK (BCM94708)";
        compatible = "brcm,bcm94708", "brcm,bcm4708";
 
-       aliases {
-               serial0 = &uart0;
-       };
-
-       chosen {
-               stdout-path = "serial0:115200n8";
-       };
-
        memory {
                reg = <0x00000000 0x08000000>;
        };
index 95e8be65f2f14039ee4d04bfbcb1425fe1ce15f0..c37616c67edcc0810d46c93bfcb78eacdf05c5ed 100644 (file)
        model = "NorthStar SVK (BCM94709)";
        compatible = "brcm,bcm94709", "brcm,bcm4709", "brcm,bcm4708";
 
-       aliases {
-               serial0 = &uart0;
-       };
-
-       chosen {
-               stdout-path = "serial0:115200n8";
-       };
-
        memory {
                reg = <0x00000000 0x08000000>;
        };
index decd86bae901c0296a07cff8cf59b32006e972c9..40e694bfe5cabedfbda67e6632fc388214ccad2e 100644 (file)
        model = "NorthStar Enterprise Router (BCM953012ER)";
        compatible = "brcm,bcm953012er", "brcm,brcm53012", "brcm,bcm4708";
 
-       aliases {
-               serial0 = &uart0;
-       };
-
-       chosen {
-               stdout-path = "serial0:115200n8";
-       };
-
        memory {
                reg = <0x00000000 0x8000000>;
        };
diff --git a/arch/arm/boot/dts/bcm953012hr.dts b/arch/arm/boot/dts/bcm953012hr.dts
new file mode 100644 (file)
index 0000000..3076e81
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ *  SPDX-License-Identifier: BSD-3-Clause
+ *
+ *  Copyright(c) 2017 Broadcom
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in
+ *      the documentation and/or other materials provided with the
+ *      distribution.
+ *    * Neither the name of Broadcom nor the names of its contributors
+ *      may be used to endorse or promote products derived from this
+ *      software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/dts-v1/;
+
+#include "bcm4708.dtsi"
+#include "bcm5301x-nand-cs0-bch4.dtsi"
+
+/ {
+       model = "NorthStar HR (BCM953012HR)";
+       compatible = "brcm,bcm953012hr", "brcm,brcm53012", "brcm,bcm4708";
+
+       aliases {
+               ethernet0 = &gmac0;
+               ethernet1 = &gmac1;
+               ethernet2 = &gmac2;
+       };
+
+       memory@80000000 {
+               reg = <0x80000000 0x10000000>;
+       };
+};
+
+&nandcs {
+       partition@0 {
+               label = "nboot";
+               reg = <0x00000000 0x00200000>;
+               read-only;
+       };
+       partition@200000 {
+               label = "nenv";
+               reg = <0x00200000 0x00400000>;
+       };
+       partition@600000 {
+               label = "nsystem";
+               reg = <0x00600000 0x00a00000>;
+       };
+       partition@1000000 {
+               label = "nrootfs";
+               reg = <0x01000000 0x07000000>;
+       };
+};
+
+&spi_nor {
+       status = "okay";
+       spi-max-frequency = <62500000>;
+       m25p,default-addr-width = <3>;
+
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       partition@0 {
+               label = "boot";
+               reg = <0x00000000 0x000d0000>;
+       };
+       partition@d000 {
+               label = "env";
+               reg = <0x000d0000 0x00030000>;
+       };
+       partition@100000 {
+               label = "system";
+               reg = <0x00100000 0x00600000>;
+       };
+       partition@700000 {
+               label = "rootfs";
+               reg = <0x00700000 0x00900000>;
+       };
+};
index ae31a5826e918ec58fc1948df0f9998664b7064f..79c168e2714b7e6c3c4490f180d1c44ebd38f0ea 100644 (file)
                serial1 = &uart1;
        };
 
-       chosen {
-               stdout-path = "serial0:115200n8";
-       };
-
        memory {
                reg = <0x80000000 0x10000000>;
        };
 };
 
+&nand {
+       nandcs@0 {
+               compatible = "brcm,nandcs";
+               reg = <0>;
+               nand-on-flash-bbt;
+
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               nand-ecc-strength = <4>;
+               nand-ecc-step-size = <512>;
+
+               partition@0 {
+                       label = "nboot";
+                       reg = <0x00000000 0x00200000>;
+                       read-only;
+               };
+               partition@200000 {
+                       label = "nenv";
+                       reg = <0x00200000 0x00400000>;
+               };
+               partition@600000 {
+                       label = "nsystem";
+                       reg = <0x00600000 0x00a00000>;
+               };
+               partition@1000000 {
+                       label = "nrootfs";
+                       reg = <0x01000000 0x07000000>;
+               };
+       };
+};
+
+&spi_nor {
+       status = "okay";
+       spi-max-frequency = <62500000>;
+       m25p,default-addr-width = <3>;
+
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       partition@0 {
+               label = "boot";
+               reg = <0x00000000 0x000d0000>;
+       };
+       partition@d000 {
+               label = "env";
+               reg = <0x000d0000 0x00030000>;
+       };
+       partition@100000 {
+               label = "system";
+               reg = <0x00100000 0x00600000>;
+       };
+       partition@700000 {
+               label = "rootfs";
+               reg = <0x00700000 0x00900000>;
+       };
+};
+
 &uart0 {
        status = "okay";
 };
index df05e7f568af3e36bb2aa703d39fdbec37a6cece..f5c42962c20131dcb1c3bdeef6614c5a36456c36 100644 (file)
@@ -60,7 +60,7 @@
        };
 };
 
-/* USB 2/3 support needed to be complete */
+/* USB 3 support needed to be complete */
 
 &amac0 {
        status = "okay";
        status = "okay";
 };
 
+&ehci0 {
+       status = "okay";
+};
+
 &nand {
        nandcs@0 {
                compatible = "brcm,nandcs";
        };
 };
 
+&ohci0 {
+       status = "okay";
+};
+
 &pcie0 {
        status = "okay";
 };
index 4a3ab19c62819fb8c57d9ccf406100b64b15c598..efcb1f67bdadf7abcb71f625ec7a12aec56e4d9d 100644 (file)
@@ -60,7 +60,7 @@
        };
 };
 
-/* USB 2/3 support needed to be complete */
+/* USB 3 support needed to be complete */
 
 &amac0 {
        status = "okay";
        status = "okay";
 };
 
+&ehci0 {
+       status = "okay";
+};
+
 &nand {
        nandcs@0 {
                compatible = "brcm,nandcs";
        };
 };
 
+&ohci0 {
+       status = "okay";
+};
+
 &pcie0 {
        status = "okay";
 };
index 81f78435d8c76cca38cb777d86e139c7d3751151..b335ce02e32f9cdda5282cd5180121daa33ea457 100644 (file)
        status = "okay";
 };
 
+&ehci0 {
+       status = "okay";
+};
+
 &i2c0 {
+       status = "okay";
+
        temperature-sensor@4c {
                compatible = "adi,adt7461a";
                reg = <0x4c>;
        };
 };
 
+&ohci0 {
+       status = "okay";
+};
+
 &pcie0 {
        status = "okay";
 };
index c88b8fefcb2f13e3c9bd98321948c8988d8e428d..16ab2d82a14ba63bf98577786b844795e8a02ed9 100644 (file)
@@ -60,7 +60,7 @@
        };
 };
 
-/* USB 2/3 and SLIC support needed to be complete */
+/* USB 3 and SLIC support needed to be complete */
 
 &amac0 {
        status = "okay";
        status = "okay";
 };
 
+&ehci0 {
+       status = "okay";
+};
+
 &nand {
        nandcs@0 {
                compatible = "brcm,nandcs";
        };
 };
 
+&ohci0 {
+       status = "okay";
+};
+
 &pcie0 {
        status = "okay";
 };
index d503fa0dde310ff7597aeb7d3bfc757bcca32291..9b921c6aa8f8de19807c9a29d8f72eb404af6a49 100644 (file)
@@ -60,7 +60,7 @@
        };
 };
 
-/* USB 2/3 and SLIC support needed to be complete */
+/* USB 3 and SLIC support needed to be complete */
 
 &amac0 {
        status = "okay";
        status = "okay";
 };
 
+&ehci0 {
+       status = "okay";
+};
+
 &nand {
        nandcs@0 {
                compatible = "brcm,nandcs";
        };
 };
 
+&ohci0 {
+       status = "okay";
+};
+
 &pcie0 {
        status = "okay";
 };
index cc0363b843c1a0ae777efa40a6f2e25b34cf1f4c..006b08e41a3ba0187412c99108e707df11380dd5 100644 (file)
        status = "okay";
 };
 
+&ehci0 {
+       status = "okay";
+};
+
 &nand {
        nandcs@0 {
                compatible = "brcm,nandcs";
        };
 };
 
+&ohci0 {
+       status = "okay";
+};
+
 &pcie0 {
        status = "okay";
 };
index f8d47e517e18ceaa28abc6a43f115d31fa9e71a9..64740f85cf4c906a9ea1d9397087c1515e3024db 100644 (file)
        status = "okay";
 };
 
+&ehci0 {
+       status = "okay";
+};
+
 &nand {
        nandcs@0 {
                compatible = "brcm,nandcs";
        };
 };
 
+&ohci0 {
+       status = "okay";
+};
+
 &pcie0 {
        status = "okay";
 };
index 74e15a3cd9f8efb6a65238054824ba7e22df0bc2..bce251a6859163ed13745992f8b4607c1cb24a5e 100644 (file)
@@ -60,7 +60,7 @@
        };
 };
 
-/* USB 2/3 support needed to be complete */
+/* USB 3 support needed to be complete */
 
 &amac0 {
        status = "okay";
        status = "okay";
 };
 
+&ehci0 {
+       status = "okay";
+};
+
 &nand {
        nandcs@0 {
                compatible = "brcm,nandcs";
        };
 };
 
+&ohci0 {
+       status = "okay";
+};
+
 &pcie0 {
        status = "okay";
 };
index d15107cba765dc2585f0199591947ea5d2984ea1..8d244cd76c36a3efccf08f779343dbbb99efa4a5 100644 (file)
@@ -9,6 +9,7 @@
  */
 /dts-v1/;
 #include "da850.dtsi"
+#include <dt-bindings/gpio/gpio.h>
 
 / {
        compatible = "ti,da850-evm", "ti,da850";
                                DRVDD-supply = <&vbat>;
                                DVDD-supply = <&vbat>;
                        };
-
+                       tca6416: gpio@20 {
+                               compatible = "ti,tca6416";
+                               reg = <0x20>;
+                       };
                };
                wdt: wdt@21000 {
                        status = "okay";
 
 &vpif {
        pinctrl-names = "default";
-       pinctrl-0 = <&vpif_capture_pins>;
+       pinctrl-0 = <&vpif_capture_pins>, <&vpif_display_pins>;
        status = "okay";
 
        /* VPIF capture port */
-       port {
-               vpif_ch0: endpoint@0 {
-                         reg = <0>;
-                         bus-width = <8>;
+       port@0 {
+               vpif_input_ch0: endpoint@0 {
+                       reg = <0>;
+                       bus-width = <8>;
                };
 
-               vpif_ch1: endpoint@1 {
-                         reg = <1>;
-                         bus-width = <8>;
-                         data-shift = <8>;
+               vpif_input_ch1: endpoint@1 {
+                       reg = <1>;
+                       bus-width = <8>;
+                       data-shift = <8>;
+               };
+       };
+
+       /* VPIF display port */
+       port@1 {
+               vpif_output_ch0: endpoint {
+                       bus-width = <8>;
                };
        };
 };
index 112ec92064cea56732a783eabbbafe26983989ba..512604ad8b717e8141657252bad4ba864a102df7 100644 (file)
                pinctrl-0 = <&system_power_pin>;
        };
 
+       sound {
+               compatible = "pwm-beeper";
+               pinctrl-names = "default";
+               pinctrl-0 = <&ehrpwm0b_pins>;
+               pwms = <&ehrpwm0 1 1000000 0>;
+               amp-supply = <&amp>;
+       };
+
        /*
         * This is a 5V current limiting regulator that is shared by USB,
         * the sensor (input) ports, the motor (output) ports and the A/DC.
                enable-active-high;
                regulator-boot-on;
        };
+
+       /*
+        * This is a simple voltage divider on VCC5V to provide a 2.5V
+        * reference signal to the ADC.
+        */
+       adc_ref: regulator2 {
+               compatible = "regulator-fixed";
+               regulator-name = "adc ref";
+               regulator-min-microvolt = <2500000>;
+               regulator-max-microvolt = <2500000>;
+               regulator-boot-on;
+               vin-supply = <&vcc5v>;
+       };
+
+       /*
+        * This is the amplifier for the speaker.
+        */
+       amp: regulator3 {
+               pinctrl-names = "default";
+               pinctrl-0 = <&amp_pins>;
+               compatible = "regulator-fixed";
+               regulator-name = "amp";
+               gpio = <&gpio 111 GPIO_ACTIVE_HIGH>;
+               enable-active-high;
+       };
 };
 
 &pmx_core {
        status = "okay";
 
-       spi0_cs3_pin: pinmux_spi0_cs3_pin {
-               pinctrl-single,bits = <
-                       /* CS3 */
-                       0xc 0x01000000 0x0f000000
-               >;
-       };
-
        mmc0_cd_pin: pinmux_mmc0_cd {
                pinctrl-single,bits = <
                        /* GP5[14] */
                        0x4c 0x00008000 0x0000f000
                >;
        };
+
+       amp_pins: pinmux_amp_pins {
+               pinctrl-single,bits = <
+                       /* GP6[15] */
+                       0x34 0x00000008 0x0000000f
+               >;
+       };
 };
 
 &pinconf {
                        };
                };
        };
+
+       adc: adc@3 {
+               compatible = "ti,ads7957";
+               reg = <3>;
+               #io-channel-cells = <1>;
+               spi-max-frequency = <10000000>;
+               vref-supply = <&adc_ref>;
+       };
+};
+
+&ehrpwm0 {
+       status = "okay";
 };
 
 &gpio {
index 92d633d1da6841cc53300ae246871705acc9caf9..941d455000a75dae91c351d431f827efb7b163c8 100644 (file)
                                        0x10 0x00000010 0x000000f0
                                >;
                        };
+                       spi0_cs3_pin: pinmux_spi0_cs3_pin {
+                               pinctrl-single,bits = <
+                                       /* CS3 */
+                                       0xc 0x01000000 0x0f000000
+                               >;
+                       };
                        spi1_pins: pinmux_spi1_pins {
                                pinctrl-single,bits = <
                                        /* SIMO, SOMI, CLK */
                                        0x3c 0x11111111 0xffffffff
                                        /* VP_DIN[8..9] */
                                        0x40 0x00000011 0x000000ff
-                                       /* VP_CLKIN3, VP_CLKIN2 */
-                                       0x4c 0x00010100 0x000f0f00
+                               >;
+                       };
+                       vpif_display_pins: vpif_display_pins {
+                               pinctrl-single,bits = <
+                                       /* VP_DOUT[2..7] */
+                                       0x40 0x11111100 0xffffff00
+                                       /* VP_DOUT[10..15,0..1] */
+                                       0x44 0x11111111 0xffffffff
+                                       /*  VP_DOUT[8..9] */
+                                       0x48 0x00000011 0x000000ff
+                                       /*
+                                        * VP_CLKOUT3, VP_CLKIN3,
+                                        * VP_CLKOUT2, VP_CLKIN2
+                                        */
+                                       0x4c 0x00111100 0x00ffff00
                                >;
                        };
                };
                        status = "disabled";
 
                        /* VPIF capture port */
-                       port {
+                       port@0 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                       };
+
+                       /* VPIF display port */
+                       port@1 {
                                #address-cells = <1>;
                                #size-cells = <0>;
                        };
index 0bf55fa72dea87d2652ed16239e91aca46f46dda..1865976db5f9a3e11aad03cdd951d2f3af83c78d 100644 (file)
                regulator-min-microvolt = <3300000>;
                regulator-max-microvolt = <3300000>;
        };
+
+       sata_refclk: fixedclock0 {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <100000000>;
+       };
 };
 
 &dm816x_pinmux {
        pinctrl-0 = <&usb1_pins>;
        mentor,multipoint = <0>;
 };
+
+&sata {
+       clocks = <&sysclk5_ck>, <&sata_refclk>;
+};
index 276211e1ee533af0fe345047ab6d006a785f84a8..59cbf958fcc3178c4b56aad647c340e40a63c098 100644 (file)
                        phy-handle = <&phy1>;
                };
 
+               sata: sata@4a140000 {
+                       compatible = "ti,dm816-ahci";
+                       reg = <0x4a140000 0x10000>;
+                       interrupts = <16>;
+                       ti,hwmods = "sata";
+               };
+
                mcspi1: spi@48030000 {
                        compatible = "ti,omap4-mcspi";
                        reg = <0x48030000 0x1000>;
index 4bc4b575c99bd43da80115cf4d8ee74845f3cc22..31a9e061ddd0d0f76b115890aab09dbd2ae340d9 100644 (file)
        tps659038: tps659038@58 {
                compatible = "ti,tps659038";
                reg = <0x58>;
+               ti,palmas-override-powerhold;
+               ti,system-power-controller;
 
                tps659038_pmic {
                        compatible = "ti,tps659038-pmic";
index bbfb9d5a70a98116d303844a91c6a65dd42cfb39..e7144662af45cc98974e648f2b6e2226e214df29 100644 (file)
                        compatible = "arm,cortex-a15";
                        reg = <0>;
 
-                       operating-points = <
-                               /* kHz    uV */
-                               1000000 1060000
-                               1176000 1160000
-                               >;
+                       operating-points-v2 = <&cpu0_opp_table>;
 
                        clocks = <&dpll_mpu_ck>;
                        clock-names = "cpu";
                };
        };
 
+       cpu0_opp_table: opp-table {
+               compatible = "operating-points-v2-ti-cpu";
+               syscon = <&scm_wkup>;
+
+               opp_nom@1000000000 {
+                       opp-hz = /bits/ 64 <1000000000>;
+                       opp-microvolt = <1060000 850000 1150000>;
+                       opp-supported-hw = <0xFF 0x01>;
+                       opp-suspend;
+               };
+
+               opp_od@1176000000 {
+                       opp-hz = /bits/ 64 <1176000000>;
+                       opp-microvolt = <1160000 885000 1160000>;
+                       opp-supported-hw = <0xFF 0x02>;
+               };
+       };
+
        /*
         * The soc node represents the soc top level view. It is used for IPs
         * that are not memory mapped in the MPU view or for the MPU itself.
 
 &cpu_thermal {
        polling-delay = <500>; /* milliseconds */
+       coefficients = <0 2000>;
+};
+
+&gpu_thermal {
+       coefficients = <0 2000>;
+};
+
+&core_thermal {
+       coefficients = <0 2000>;
+};
+
+&dspeve_thermal {
+       coefficients = <0 2000>;
+};
+
+&iva_thermal {
+       coefficients = <0 2000>;
+};
+
+&cpu_crit {
+       temperature = <120000>; /* milli Celsius */
 };
 
 /include/ "dra7xx-clocks.dtsi"
index 0a78347e6615651b16bf0b50bff32c50f55103b8..24e6746c5b262602ac70f4935d23842ba8454fbe 100644 (file)
@@ -17,6 +17,7 @@
                        device_type = "cpu";
                        compatible = "arm,cortex-a15";
                        reg = <1>;
+                       operating-points-v2 = <&cpu0_opp_table>;
                };
        };
 
        };
 };
 
+&cpu0_opp_table {
+       opp-shared;
+};
+
 &dss {
        reg = <0x58000000 0x80>,
              <0x58004054 0x4>,
index 548413e23c4727950c8e1fb1dce9489cf2414213..c9f191ca7b9ccea04da9890aef08836388ab0549 100644 (file)
 &dsi_0 {
        vddcore-supply = <&ldo6_reg>;
        vddio-supply = <&ldo6_reg>;
+       samsung,burst-clock-frequency = <250000000>;
+       samsung,esc-clock-frequency = <20000000>;
        samsung,pll-clock-frequency = <24000000>;
        status = "okay";
 
index 9c28ef4508e0d5a2f1d56a0a9b5b1849d6516c62..590ee442d0ae1bde4ebe2e067f968cf54c2348d5 100644 (file)
                        compatible = "operating-points-v2";
                        opp-shared;
 
-                       opp@50000000 {
+                       opp-50000000 {
                                opp-hz = /bits/ 64 <50000000>;
                                opp-microvolt = <800000>;
                        };
-                       opp@100000000 {
+                       opp-100000000 {
                                opp-hz = /bits/ 64 <100000000>;
                                opp-microvolt = <800000>;
                        };
-                       opp@134000000 {
+                       opp-134000000 {
                                opp-hz = /bits/ 64 <134000000>;
                                opp-microvolt = <800000>;
                        };
-                       opp@200000000 {
+                       opp-200000000 {
                                opp-hz = /bits/ 64 <200000000>;
                                opp-microvolt = <825000>;
                        };
-                       opp@400000000 {
+                       opp-400000000 {
                                opp-hz = /bits/ 64 <400000000>;
                                opp-microvolt = <875000>;
                        };
                        compatible = "operating-points-v2";
                        opp-shared;
 
-                       opp@50000000 {
+                       opp-50000000 {
                                opp-hz = /bits/ 64 <50000000>;
                                opp-microvolt = <900000>;
                        };
-                       opp@80000000 {
+                       opp-80000000 {
                                opp-hz = /bits/ 64 <80000000>;
                                opp-microvolt = <900000>;
                        };
-                       opp@100000000 {
+                       opp-100000000 {
                                opp-hz = /bits/ 64 <100000000>;
                                opp-microvolt = <1000000>;
                        };
-                       opp@134000000 {
+                       opp-134000000 {
                                opp-hz = /bits/ 64 <134000000>;
                                opp-microvolt = <1000000>;
                        };
-                       opp@200000000 {
+                       opp-200000000 {
                                opp-hz = /bits/ 64 <200000000>;
                                opp-microvolt = <1000000>;
                        };
                        compatible = "operating-points-v2";
                        opp-shared;
 
-                       opp@50000000 {
+                       opp-50000000 {
                                opp-hz = /bits/ 64 <50000000>;
                        };
-                       opp@80000000 {
+                       opp-80000000 {
                                opp-hz = /bits/ 64 <80000000>;
                        };
-                       opp@100000000 {
+                       opp-100000000 {
                                opp-hz = /bits/ 64 <100000000>;
                        };
-                       opp@200000000 {
+                       opp-200000000 {
                                opp-hz = /bits/ 64 <200000000>;
                        };
-                       opp@400000000 {
+                       opp-400000000 {
                                opp-hz = /bits/ 64 <400000000>;
                        };
                };
                        compatible = "operating-points-v2";
                        opp-shared;
 
-                       opp@50000000 {
+                       opp-50000000 {
                                opp-hz = /bits/ 64 <50000000>;
                        };
-                       opp@80000000 {
+                       opp-80000000 {
                                opp-hz = /bits/ 64 <80000000>;
                        };
-                       opp@100000000 {
+                       opp-100000000 {
                                opp-hz = /bits/ 64 <100000000>;
                        };
-                       opp@200000000 {
+                       opp-200000000 {
                                opp-hz = /bits/ 64 <200000000>;
                        };
-                       opp@300000000 {
+                       opp-300000000 {
                                opp-hz = /bits/ 64 <300000000>;
                        };
                };
                        compatible = "operating-points-v2";
                        opp-shared;
 
-                       opp@50000000 {
+                       opp-50000000 {
                                opp-hz = /bits/ 64 <50000000>;
                        };
-                       opp@80000000 {
+                       opp-80000000 {
                                opp-hz = /bits/ 64 <80000000>;
                        };
-                       opp@100000000 {
+                       opp-100000000 {
                                opp-hz = /bits/ 64 <100000000>;
                        };
                };
index 84fcdff140aebbf87edb3aef834247a2f5abce42..497a9470c8881bca6e49800f90c0f5d20dd3d84a 100644 (file)
                };
        };
 
-       watchdog: watchdog@10060000 {
-               compatible = "samsung,s3c2410-wdt";
-               reg = <0x10060000 0x100>;
-               interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
-               clocks = <&clock CLK_WDT>;
-               clock-names = "watchdog";
-               status = "disabled";
-       };
-
        rtc: rtc@10070000 {
                compatible = "samsung,s3c6410-rtc";
                reg = <0x10070000 0x100>;
index a2c6a13fe67bb69bac6465346fa32f6ffd0bb88a..312650e2450fbefbe2d1d07cf6b7f22fe696e942 100644 (file)
 &tmu {
        status = "okay";
 };
-
-&watchdog {
-       status = "okay";
-};
index 0ca1b4d355f2c0cf7eb4bd117cce83514bea902b..1743ca850070969aac2571fefcbdacc735809d19 100644 (file)
 &dsi_0 {
        vddcore-supply = <&vusb_reg>;
        vddio-supply = <&vmipi_reg>;
+       samsung,burst-clock-frequency = <500000000>;
+       samsung,esc-clock-frequency = <20000000>;
        samsung,pll-clock-frequency = <24000000>;
        status = "okay";
 
index f9408188f97f21e621e61e00e7cf3e34d86637aa..768fb075b1fd1b520b17f908e7797267200a1bde 100644 (file)
                };
        };
 
+       watchdog: watchdog@10060000 {
+               compatible = "samsung,s3c6410-wdt";
+               reg = <0x10060000 0x100>;
+               interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&clock CLK_WDT>;
+               clock-names = "watchdog";
+       };
+
        clock: clock-controller@10030000 {
                compatible = "samsung,exynos4210-clock";
                reg = <0x10030000 0x20000>;
                compatible = "operating-points-v2";
                opp-shared;
 
-               opp@134000000 {
+               opp-134000000 {
                        opp-hz = /bits/ 64 <134000000>;
                        opp-microvolt = <1025000>;
                };
-               opp@267000000 {
+               opp-267000000 {
                        opp-hz = /bits/ 64 <267000000>;
                        opp-microvolt = <1050000>;
                };
-               opp@400000000 {
+               opp-400000000 {
                        opp-hz = /bits/ 64 <400000000>;
                        opp-microvolt = <1150000>;
                };
                compatible = "operating-points-v2";
                opp-shared;
 
-               opp@134000000 {
+               opp-134000000 {
                        opp-hz = /bits/ 64 <134000000>;
                };
-               opp@160000000 {
+               opp-160000000 {
                        opp-hz = /bits/ 64 <160000000>;
                };
-               opp@200000000 {
+               opp-200000000 {
                        opp-hz = /bits/ 64 <200000000>;
                };
        };
                compatible = "operating-points-v2";
                opp-shared;
 
-               opp@5000000 {
+               opp-5000000 {
                        opp-hz = /bits/ 64 <5000000>;
                };
-               opp@100000000 {
+               opp-100000000 {
                        opp-hz = /bits/ 64 <100000000>;
                };
        };
                compatible = "operating-points-v2";
                opp-shared;
 
-               opp@10000000 {
+               opp-10000000 {
                        opp-hz = /bits/ 64 <10000000>;
                };
-               opp@134000000 {
+               opp-134000000 {
                        opp-hz = /bits/ 64 <134000000>;
                };
        };
                compatible = "operating-points-v2";
                opp-shared;
 
-               opp@100000000 {
+               opp-100000000 {
                        opp-hz = /bits/ 64 <100000000>;
                };
-               opp@134000000 {
+               opp-134000000 {
                        opp-hz = /bits/ 64 <134000000>;
                };
-               opp@160000000 {
+               opp-160000000 {
                        opp-hz = /bits/ 64 <160000000>;
                };
        };
                compatible = "operating-points-v2";
                opp-shared;
 
-               opp@100000000 {
+               opp-100000000 {
                        opp-hz = /bits/ 64 <100000000>;
                };
-               opp@160000000 {
+               opp-160000000 {
                        opp-hz = /bits/ 64 <160000000>;
                };
-               opp@200000000 {
+               opp-200000000 {
                        opp-hz = /bits/ 64 <200000000>;
                };
        };
index a36cd36a26b8056a7bfa287b361cbbc70d109c0e..4cd62487bb16f28a2b1303ac4ce3486a552a7214 100644 (file)
        vtmu-supply = <&ldo16_reg>;
        status = "okay";
 };
-
-&watchdog {
-       status = "okay";
-};
index 78f118cb73d4c81a2dfe3c07db0b885d26552c37..0f1ff792fe44e62ceab0b1668d2de0fed55fabd4 100644 (file)
        vtmu-supply = <&ldo10_reg>;
        status = "okay";
 };
-
-&watchdog {
-       status = "okay";
-};
index a1ab6f94bb64dbae91664907441563c8a0f6000d..7a83e2df18a606a8247859647aa0fa5f7e172236 100644 (file)
 &serial_3 {
        status = "okay";
 };
-
-&watchdog {
-       status = "okay";
-};
index e75bc170c89c89ecbfd001fa07904d823d745f04..a67bd953d754aa11847aa4fa66b2249fefcd0838 100644 (file)
 };
 
 &cpu0_opp_table {
-       opp@1600000000 {
+       opp-1600000000 {
                opp-hz = /bits/ 64 <1600000000>;
                opp-microvolt = <1350000>;
                clock-latency-ns = <200000>;
        };
-       opp@1704000000 {
+       opp-1704000000 {
                opp-hz = /bits/ 64 <1704000000>;
                opp-microvolt = <1350000>;
                clock-latency-ns = <200000>;
index 41ecd6d465a77b8f3ae6ae4ee3e5ae03c6247de6..82221a00444d0859744525c2cc4cbc7ced10e05c 100644 (file)
 &dsi_0 {
        vddcore-supply = <&ldo8_reg>;
        vddio-supply = <&ldo10_reg>;
+       samsung,burst-clock-frequency = <500000000>;
+       samsung,esc-clock-frequency = <20000000>;
        samsung,pll-clock-frequency = <24000000>;
        status = "okay";
 
index 235bbb69ad7c859a0449a757dca7bd2a7dd3af41..7ff03a7e8fb93e9cfcdeb89c1bd39e85e12f5bd8 100644 (file)
                compatible = "operating-points-v2";
                opp-shared;
 
-               opp@200000000 {
+               opp-200000000 {
                        opp-hz = /bits/ 64 <200000000>;
                        opp-microvolt = <900000>;
                        clock-latency-ns = <200000>;
                };
-               opp@300000000 {
+               opp-300000000 {
                        opp-hz = /bits/ 64 <300000000>;
                        opp-microvolt = <900000>;
                        clock-latency-ns = <200000>;
                };
-               opp@400000000 {
+               opp-400000000 {
                        opp-hz = /bits/ 64 <400000000>;
                        opp-microvolt = <925000>;
                        clock-latency-ns = <200000>;
                };
-               opp@500000000 {
+               opp-500000000 {
                        opp-hz = /bits/ 64 <500000000>;
                        opp-microvolt = <950000>;
                        clock-latency-ns = <200000>;
                };
-               opp@600000000 {
+               opp-600000000 {
                        opp-hz = /bits/ 64 <600000000>;
                        opp-microvolt = <975000>;
                        clock-latency-ns = <200000>;
                };
-               opp@700000000 {
+               opp-700000000 {
                        opp-hz = /bits/ 64 <700000000>;
                        opp-microvolt = <987500>;
                        clock-latency-ns = <200000>;
                };
-               opp@800000000 {
+               opp-800000000 {
                        opp-hz = /bits/ 64 <800000000>;
                        opp-microvolt = <1000000>;
                        clock-latency-ns = <200000>;
                        opp-suspend;
                };
-               opp@900000000 {
+               opp-900000000 {
                        opp-hz = /bits/ 64 <900000000>;
                        opp-microvolt = <1037500>;
                        clock-latency-ns = <200000>;
                };
-               opp@1000000000 {
+               opp-1000000000 {
                        opp-hz = /bits/ 64 <1000000000>;
                        opp-microvolt = <1087500>;
                        clock-latency-ns = <200000>;
                };
-               opp@1100000000 {
+               opp-1100000000 {
                        opp-hz = /bits/ 64 <1100000000>;
                        opp-microvolt = <1137500>;
                        clock-latency-ns = <200000>;
                };
-               opp@1200000000 {
+               opp-1200000000 {
                        opp-hz = /bits/ 64 <1200000000>;
                        opp-microvolt = <1187500>;
                        clock-latency-ns = <200000>;
                };
-               opp@1300000000 {
+               opp-1300000000 {
                        opp-hz = /bits/ 64 <1300000000>;
                        opp-microvolt = <1250000>;
                        clock-latency-ns = <200000>;
                };
-               opp@1400000000 {
+               opp-1400000000 {
                        opp-hz = /bits/ 64 <1400000000>;
                        opp-microvolt = <1287500>;
                        clock-latency-ns = <200000>;
                };
-               cpu0_opp_1500: opp@1500000000 {
+               cpu0_opp_1500: opp-1500000000 {
                        opp-hz = /bits/ 64 <1500000000>;
                        opp-microvolt = <1350000>;
                        clock-latency-ns = <200000>;
                };
        };
 
+       watchdog: watchdog@10060000 {
+               compatible = "samsung,exynos5250-wdt";
+               reg = <0x10060000 0x100>;
+               interrupts = <GIC_SPI 43 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&clock CLK_WDT>;
+               clock-names = "watchdog";
+               samsung,syscon-phandle = <&pmu_system_controller>;
+       };
+
        adc: adc@126C0000 {
                compatible = "samsung,exynos-adc-v1";
                reg = <0x126C0000 0x100>;
                compatible = "operating-points-v2";
                opp-shared;
 
-               opp@100000000 {
+               opp-100000000 {
                        opp-hz = /bits/ 64 <100000000>;
                        opp-microvolt = <900000>;
                };
-               opp@134000000 {
+               opp-134000000 {
                        opp-hz = /bits/ 64 <134000000>;
                        opp-microvolt = <900000>;
                };
-               opp@160000000 {
+               opp-160000000 {
                        opp-hz = /bits/ 64 <160000000>;
                        opp-microvolt = <900000>;
                };
-               opp@267000000 {
+               opp-267000000 {
                        opp-hz = /bits/ 64 <267000000>;
                        opp-microvolt = <950000>;
                };
-               opp@400000000 {
+               opp-400000000 {
                        opp-hz = /bits/ 64 <400000000>;
                        opp-microvolt = <1050000>;
                };
                compatible = "operating-points-v2";
                opp-shared;
 
-               opp@100000000 {
+               opp-100000000 {
                        opp-hz = /bits/ 64 <100000000>;
                };
-               opp@134000000 {
+               opp-134000000 {
                        opp-hz = /bits/ 64 <134000000>;
                };
-               opp@160000000 {
+               opp-160000000 {
                        opp-hz = /bits/ 64 <160000000>;
                };
-               opp@267000000 {
+               opp-267000000 {
                        opp-hz = /bits/ 64 <267000000>;
                };
        };
                compatible = "operating-points-v2";
                opp-shared;
 
-               opp@100000000 {
+               opp-100000000 {
                        opp-hz = /bits/ 64 <100000000>;
                        opp-microvolt = <900000>;
                };
-               opp@134000000 {
+               opp-134000000 {
                        opp-hz = /bits/ 64 <134000000>;
                        opp-microvolt = <925000>;
                };
-               opp@160000000 {
+               opp-160000000 {
                        opp-hz = /bits/ 64 <160000000>;
                        opp-microvolt = <950000>;
                };
-               opp@200000000 {
+               opp-200000000 {
                        opp-hz = /bits/ 64 <200000000>;
                        opp-microvolt = <1000000>;
                };
                compatible = "operating-points-v2";
                opp-shared;
 
-               opp@160000000 {
+               opp-160000000 {
                        opp-hz = /bits/ 64 <160000000>;
                };
-               opp@200000000 {
+               opp-200000000 {
                        opp-hz = /bits/ 64 <200000000>;
                };
        };
                compatible = "operating-points-v2";
                opp-shared;
 
-               opp@100000000 {
+               opp-100000000 {
                        opp-hz = /bits/ 64 <100000000>;
                };
-               opp@134000000 {
+               opp-134000000 {
                        opp-hz = /bits/ 64 <134000000>;
                };
        };
                compatible = "operating-points-v2";
                opp-shared;
 
-               opp@50000000 {
+               opp-50000000 {
                        opp-hz = /bits/ 64 <50000000>;
                };
-               opp@100000000 {
+               opp-100000000 {
                        opp-hz = /bits/ 64 <100000000>;
                };
        };
diff --git a/arch/arm/boot/dts/exynos5420-tmu-sensor-conf.dtsi b/arch/arm/boot/dts/exynos5420-tmu-sensor-conf.dtsi
new file mode 100644 (file)
index 0000000..c8771c6
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Device tree sources for Exynos5420 TMU sensor configuration
+ *
+ * Copyright (c) 2014 Lukasz Majewski <l.majewski@samsung.com>
+ * Copyright (c) 2017 Krzysztof Kozlowski <krzk@kernel.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <dt-bindings/thermal/thermal_exynos.h>
+
+#thermal-sensor-cells = <0>;
+samsung,tmu_gain = <8>;
+samsung,tmu_reference_voltage = <16>;
+samsung,tmu_noise_cancel_mode = <4>;
+samsung,tmu_efuse_value = <55>;
+samsung,tmu_min_efuse_value = <0>;
+samsung,tmu_max_efuse_value = <100>;
+samsung,tmu_first_point_trim = <25>;
+samsung,tmu_second_point_trim = <85>;
+samsung,tmu_default_temp_offset = <50>;
+samsung,tmu_cal_type = <TYPE_ONE_POINT_TRIMMING>;
index 7dc9dc82afd87edb22cc3f0411a64a6c9a2d064a..0db0bcf8da3652a3cf5662b38cfcfb89118732c7 100644 (file)
                cluster_a15_opp_table: opp_table0 {
                        compatible = "operating-points-v2";
                        opp-shared;
-                       opp@1800000000 {
+                       opp-1800000000 {
                                opp-hz = /bits/ 64 <1800000000>;
                                opp-microvolt = <1250000>;
                                clock-latency-ns = <140000>;
                        };
-                       opp@1700000000 {
+                       opp-1700000000 {
                                opp-hz = /bits/ 64 <1700000000>;
                                opp-microvolt = <1212500>;
                                clock-latency-ns = <140000>;
                        };
-                       opp@1600000000 {
+                       opp-1600000000 {
                                opp-hz = /bits/ 64 <1600000000>;
                                opp-microvolt = <1175000>;
                                clock-latency-ns = <140000>;
                        };
-                       opp@1500000000 {
+                       opp-1500000000 {
                                opp-hz = /bits/ 64 <1500000000>;
                                opp-microvolt = <1137500>;
                                clock-latency-ns = <140000>;
                        };
-                       opp@1400000000 {
+                       opp-1400000000 {
                                opp-hz = /bits/ 64 <1400000000>;
                                opp-microvolt = <1112500>;
                                clock-latency-ns = <140000>;
                        };
-                       opp@1300000000 {
+                       opp-1300000000 {
                                opp-hz = /bits/ 64 <1300000000>;
                                opp-microvolt = <1062500>;
                                clock-latency-ns = <140000>;
                        };
-                       opp@1200000000 {
+                       opp-1200000000 {
                                opp-hz = /bits/ 64 <1200000000>;
                                opp-microvolt = <1037500>;
                                clock-latency-ns = <140000>;
                        };
-                       opp@1100000000 {
+                       opp-1100000000 {
                                opp-hz = /bits/ 64 <1100000000>;
                                opp-microvolt = <1012500>;
                                clock-latency-ns = <140000>;
                        };
-                       opp@1000000000 {
+                       opp-1000000000 {
                                opp-hz = /bits/ 64 <1000000000>;
                                opp-microvolt = < 987500>;
                                clock-latency-ns = <140000>;
                        };
-                       opp@900000000 {
+                       opp-900000000 {
                                opp-hz = /bits/ 64 <900000000>;
                                opp-microvolt = < 962500>;
                                clock-latency-ns = <140000>;
                        };
-                       opp@800000000 {
+                       opp-800000000 {
                                opp-hz = /bits/ 64 <800000000>;
                                opp-microvolt = < 937500>;
                                clock-latency-ns = <140000>;
                        };
-                       opp@700000000 {
+                       opp-700000000 {
                                opp-hz = /bits/ 64 <700000000>;
                                opp-microvolt = < 912500>;
                                clock-latency-ns = <140000>;
                cluster_a7_opp_table: opp_table1 {
                        compatible = "operating-points-v2";
                        opp-shared;
-                       opp@1300000000 {
+                       opp-1300000000 {
                                opp-hz = /bits/ 64 <1300000000>;
                                opp-microvolt = <1275000>;
                                clock-latency-ns = <140000>;
                        };
-                       opp@1200000000 {
+                       opp-1200000000 {
                                opp-hz = /bits/ 64 <1200000000>;
                                opp-microvolt = <1212500>;
                                clock-latency-ns = <140000>;
                        };
-                       opp@1100000000 {
+                       opp-1100000000 {
                                opp-hz = /bits/ 64 <1100000000>;
                                opp-microvolt = <1162500>;
                                clock-latency-ns = <140000>;
                        };
-                       opp@1000000000 {
+                       opp-1000000000 {
                                opp-hz = /bits/ 64 <1000000000>;
                                opp-microvolt = <1112500>;
                                clock-latency-ns = <140000>;
                        };
-                       opp@900000000 {
+                       opp-900000000 {
                                opp-hz = /bits/ 64 <900000000>;
                                opp-microvolt = <1062500>;
                                clock-latency-ns = <140000>;
                        };
-                       opp@800000000 {
+                       opp-800000000 {
                                opp-hz = /bits/ 64 <800000000>;
                                opp-microvolt = <1025000>;
                                clock-latency-ns = <140000>;
                        };
-                       opp@700000000 {
+                       opp-700000000 {
                                opp-hz = /bits/ 64 <700000000>;
                                opp-microvolt = <975000>;
                                clock-latency-ns = <140000>;
                        };
-                       opp@600000000 {
+                       opp-600000000 {
                                opp-hz = /bits/ 64 <600000000>;
                                opp-microvolt = <937500>;
                                clock-latency-ns = <140000>;
                        interrupts = <0 65 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&clock CLK_TMU>;
                        clock-names = "tmu_apbif";
-                       #include "exynos4412-tmu-sensor-conf.dtsi"
+                       #include "exynos5420-tmu-sensor-conf.dtsi"
                };
 
                tmu_cpu1: tmu@10064000 {
                        interrupts = <0 183 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&clock CLK_TMU>;
                        clock-names = "tmu_apbif";
-                       #include "exynos4412-tmu-sensor-conf.dtsi"
+                       #include "exynos5420-tmu-sensor-conf.dtsi"
                };
 
                tmu_cpu2: tmu@10068000 {
                        interrupts = <0 184 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&clock CLK_TMU>, <&clock CLK_TMU>;
                        clock-names = "tmu_apbif", "tmu_triminfo_apbif";
-                       #include "exynos4412-tmu-sensor-conf.dtsi"
+                       #include "exynos5420-tmu-sensor-conf.dtsi"
                };
 
                tmu_cpu3: tmu@1006c000 {
                        interrupts = <0 185 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&clock CLK_TMU>, <&clock CLK_TMU_GPU>;
                        clock-names = "tmu_apbif", "tmu_triminfo_apbif";
-                       #include "exynos4412-tmu-sensor-conf.dtsi"
+                       #include "exynos5420-tmu-sensor-conf.dtsi"
                };
 
                tmu_gpu: tmu@100a0000 {
                        interrupts = <0 215 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&clock CLK_TMU_GPU>, <&clock CLK_TMU>;
                        clock-names = "tmu_apbif", "tmu_triminfo_apbif";
-                       #include "exynos4412-tmu-sensor-conf.dtsi"
+                       #include "exynos5420-tmu-sensor-conf.dtsi"
                };
 
                sysmmu_g2dr: sysmmu@0x10A60000 {
index 77d35bb92950f1be08188858b106490769a2d89b..a4ea018464fc5d80c1c4b43dfc2545cc92be3345 100644 (file)
        };
 
        watchdog@110000 {
-               compatible = "samsung,s3c2410-wdt";
+               compatible = "samsung,s3c6410-wdt";
                reg = <0x110000 0x1000>;
                interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&clock CLK_B_125>;
                clock-names = "usbhost";
        };
 
+       pcie_phy0: pcie-phy@270000 {
+               #phy-cells = <0>;
+               compatible = "samsung,exynos5440-pcie-phy";
+               reg = <0x270000 0x1000>, <0x271000 0x40>;
+       };
+
+       pcie_phy1: pcie-phy@272000 {
+               #phy-cells = <0>;
+               compatible = "samsung,exynos5440-pcie-phy";
+               reg = <0x272000 0x1000>, <0x271040 0x40>;
+       };
+
        pcie_0: pcie@290000 {
                compatible = "samsung,exynos5440-pcie", "snps,dw-pcie";
-               reg = <0x290000 0x1000
-                       0x270000 0x1000
-                       0x271000 0x40>;
+               reg = <0x290000 0x1000>, <0x40000000 0x1000>;
+               reg-names = "elbi", "config";
                interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>,
                             <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>,
                             <GIC_SPI 22 IRQ_TYPE_LEVEL_HIGH>;
                #address-cells = <3>;
                #size-cells = <2>;
                device_type = "pci";
-               ranges = <0x00000800 0 0x40000000 0x40000000 0 0x00001000   /* configuration space */
-                         0x81000000 0 0          0x40001000 0 0x00010000   /* downstream I/O */
+               phys = <&pcie_phy0>;
+               ranges = <0x81000000 0 0          0x40001000 0 0x00010000   /* downstream I/O */
                          0x82000000 0 0x40011000 0x40011000 0 0x1ffef000>; /* non-prefetchable memory */
                #interrupt-cells = <1>;
                interrupt-map-mask = <0 0 0 0>;
 
        pcie_1: pcie@2a0000 {
                compatible = "samsung,exynos5440-pcie", "snps,dw-pcie";
-               reg = <0x2a0000 0x1000
-                       0x272000 0x1000
-                       0x271040 0x40>;
+               reg = <0x2a0000 0x1000>, <0x60000000 0x1000>;
+               reg-names = "elbi", "config";
                interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>,
                             <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>,
                             <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
                #address-cells = <3>;
                #size-cells = <2>;
                device_type = "pci";
-               ranges = <0x00000800 0 0x60000000 0x60000000 0 0x00001000   /* configuration space */
-                         0x81000000 0 0          0x60001000 0 0x00010000   /* downstream I/O */
+               phys = <&pcie_phy1>;
+               ranges = <0x81000000 0 0          0x60001000 0 0x00010000   /* downstream I/O */
                          0x82000000 0 0x60011000 0x60011000 0 0x1ffef000>; /* non-prefetchable memory */
                #interrupt-cells = <1>;
                interrupt-map-mask = <0 0 0 0>;
index 8213016803e5d4b1465e7c6742926c6734de10b8..9ddb6bacac5ac8ea7b8feb1e21566f545f1cd67c 100644 (file)
 };
 
 &cluster_a15_opp_table {
-       opp@1700000000 {
+       opp-1700000000 {
                opp-microvolt = <1250000>;
        };
-       opp@1600000000 {
+       opp-1600000000 {
                opp-microvolt = <1250000>;
        };
-       opp@1500000000 {
+       opp-1500000000 {
                opp-microvolt = <1100000>;
        };
-       opp@1400000000 {
+       opp-1400000000 {
                opp-microvolt = <1100000>;
        };
-       opp@1300000000 {
+       opp-1300000000 {
                opp-microvolt = <1100000>;
        };
-       opp@1200000000 {
+       opp-1200000000 {
                opp-microvolt = <1000000>;
        };
-       opp@1100000000 {
+       opp-1100000000 {
                opp-microvolt = <1000000>;
        };
-       opp@1000000000 {
+       opp-1000000000 {
                opp-microvolt = <1000000>;
        };
-       opp@900000000 {
+       opp-900000000 {
                opp-microvolt = <1000000>;
        };
-       opp@800000000 {
+       opp-800000000 {
                opp-microvolt = <900000>;
        };
-       opp@700000000 {
+       opp-700000000 {
                opp-microvolt = <900000>;
        };
-       opp@600000000 {
+       opp-600000000 {
                opp-hz = /bits/ 64 <600000000>;
                opp-microvolt = <900000>;
                clock-latency-ns = <140000>;
        };
-       opp@500000000 {
+       opp-500000000 {
                opp-hz = /bits/ 64 <500000000>;
                opp-microvolt = <900000>;
                clock-latency-ns = <140000>;
        };
-       opp@400000000 {
+       opp-400000000 {
                opp-hz = /bits/ 64 <400000000>;
                opp-microvolt = <900000>;
                clock-latency-ns = <140000>;
        };
-       opp@300000000 {
+       opp-300000000 {
                opp-hz = /bits/ 64 <300000000>;
                opp-microvolt = <900000>;
                clock-latency-ns = <140000>;
        };
-       opp@200000000 {
+       opp-200000000 {
                opp-hz = /bits/ 64 <200000000>;
                opp-microvolt = <900000>;
                clock-latency-ns = <140000>;
 };
 
 &cluster_a7_opp_table {
-       opp@1300000000 {
+       opp-1300000000 {
                opp-microvolt = <1250000>;
        };
-       opp@1200000000 {
+       opp-1200000000 {
                opp-microvolt = <1250000>;
        };
-       opp@1100000000 {
+       opp-1100000000 {
                opp-microvolt = <1250000>;
        };
-       opp@1000000000 {
+       opp-1000000000 {
                opp-microvolt = <1100000>;
        };
-       opp@900000000 {
+       opp-900000000 {
                opp-microvolt = <1100000>;
        };
-       opp@800000000 {
+       opp-800000000 {
                opp-microvolt = <1100000>;
        };
-       opp@700000000 {
+       opp-700000000 {
                opp-microvolt = <1000000>;
        };
-       opp@600000000 {
+       opp-600000000 {
                opp-microvolt = <1000000>;
        };
-       opp@500000000 {
+       opp-500000000 {
                opp-hz = /bits/ 64 <500000000>;
                opp-microvolt = <1000000>;
                clock-latency-ns = <140000>;
        };
-       opp@400000000 {
+       opp-400000000 {
                opp-hz = /bits/ 64 <400000000>;
                opp-microvolt = <1000000>;
                clock-latency-ns = <140000>;
        };
-       opp@300000000 {
+       opp-300000000 {
                opp-hz = /bits/ 64 <300000000>;
                opp-microvolt = <900000>;
                clock-latency-ns = <140000>;
        };
-       opp@200000000 {
+       opp-200000000 {
                opp-hz = /bits/ 64 <200000000>;
                opp-microvolt = <900000>;
                clock-latency-ns = <140000>;
diff --git a/arch/arm/boot/dts/gemini-nas4220b.dts b/arch/arm/boot/dts/gemini-nas4220b.dts
new file mode 100644 (file)
index 0000000..7668ba5
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Device Tree file for the Gemini-based Raidsonic NAS IB-4220-B
+ */
+
+/dts-v1/;
+
+#include "gemini.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+       model = "Raidsonic NAS IB-4220-B";
+       compatible = "raidsonic,ib-4220-b", "cortina,gemini";
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       memory { /* 128 MB */
+               device_type = "memory";
+               reg = <0x00000000 0x8000000>;
+       };
+
+       chosen {
+               bootargs = "console=ttyS0,19200n8";
+               stdout-path = &uart0;
+       };
+
+       gpio_keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               button@29 {
+                       debounce_interval = <50>;
+                       wakeup-source;
+                       linux,code = <KEY_SETUP>;
+                       label = "Backup button";
+                       gpios = <&gpio1 29 GPIO_ACTIVE_LOW>;
+               };
+               button@31 {
+                       debounce_interval = <50>;
+                       wakeup-source;
+                       linux,code = <KEY_RESTART>;
+                       label = "Softreset button";
+                       gpios = <&gpio1 31 GPIO_ACTIVE_LOW>;
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+               led@28 {
+                       label = "nas4220b:orange:hdd";
+                       gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>;
+                       default-state = "on";
+               };
+               led@30 {
+                       label = "nas4220b:green:os";
+                       gpios = <&gpio1 30 GPIO_ACTIVE_HIGH>;
+                       default-state = "on";
+                       linux,default-trigger = "heartbeat";
+               };
+       };
+
+       soc {
+               flash@30000000 {
+                       status = "okay";
+                       /* 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;
+                       };
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/gemini-rut1xx.dts b/arch/arm/boot/dts/gemini-rut1xx.dts
new file mode 100644 (file)
index 0000000..7b920bf
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Device Tree file for Teltonika RUT1xx
+ */
+
+/dts-v1/;
+
+#include "gemini.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+       model = "Teltonika RUT1xx";
+       compatible = "teltonika,rut1xx", "cortina,gemini";
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       memory { /* 128 MB */
+               device_type = "memory";
+               reg = <0x00000000 0x8000000>;
+       };
+
+       chosen {
+               bootargs = "console=ttyS0,115200n8";
+               stdout-path = &uart0;
+       };
+
+       gpio_keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               button@28 {
+                       debounce_interval = <50>;
+                       wakeup-source;
+                       linux,code = <KEY_SETUP>;
+                       label = "Reset to defaults";
+                       gpios = <&gpio1 28 GPIO_ACTIVE_LOW>;
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+               led@7 {
+                       /* FIXME: add the LED color */
+                       label = "rut1xx::gsm";
+                       gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>;
+                       default-state = "on";
+               };
+               led@31 {
+                       /* FIXME: add the LED color */
+                       label = "rut1xx::power";
+                       gpios = <&gpio0 17 GPIO_ACTIVE_HIGH>;
+                       default-state = "off";
+                       linux,default-trigger = "heartbeat";
+               };
+       };
+
+       soc {
+               flash@30000000 {
+                       status = "okay";
+                       /* 8MB of flash */
+                       reg = <0x30000000 0x00800000>;
+                       /* TODO: add flash partitions here */
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/gemini-sq201.dts b/arch/arm/boot/dts/gemini-sq201.dts
new file mode 100644 (file)
index 0000000..46309e7
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Device Tree file for ITian Square One SQ201 NAS
+ */
+
+/dts-v1/;
+
+#include "gemini.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+       model = "ITian Square One SQ201";
+       compatible = "itian,sq201", "cortina,gemini";
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       memory { /* 128 MB */
+               device_type = "memory";
+               reg = <0x00000000 0x8000000>;
+       };
+
+       chosen {
+               bootargs = "console=ttyS0,115200n8";
+               stdout-path = &uart0;
+       };
+
+       gpio_keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               button@18 {
+                       debounce_interval = <50>;
+                       wakeup-source;
+                       linux,code = <KEY_SETUP>;
+                       label = "factory reset";
+                       gpios = <&gpio0 18 GPIO_ACTIVE_LOW>;
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+               led@20 {
+                       label = "sq201:green:info";
+                       gpios = <&gpio0 20 GPIO_ACTIVE_HIGH>;
+                       default-state = "on";
+                       linux,default-trigger = "heartbeat";
+               };
+               led@31 {
+                       label = "sq201:green:usb";
+                       gpios = <&gpio0 31 GPIO_ACTIVE_HIGH>;
+                       default-state = "off";
+                       linux,default-trigger = "usb-host";
+               };
+       };
+
+       soc {
+               flash@30000000 {
+                       status = "okay";
+                       /* 16MB of flash */
+                       reg = <0x30000000 0x01000000>;
+
+                       partition@0 {
+                               label = "RedBoot";
+                               reg = <0x00000000 0x00120000>;
+                               read-only;
+                       };
+                       partition@120000 {
+                               label = "Kernel";
+                               reg = <0x00120000 0x00200000>;
+                       };
+                       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;
+                       };
+               };
+
+               pci@50000000 {
+                       status = "okay";
+                       interrupt-map-mask = <0xf800 0 0 7>;
+                       interrupt-map =
+                               <0x4800 0 0 1 &pci_intc 0>, /* Slot 9 */
+                               <0x4800 0 0 2 &pci_intc 1>,
+                               <0x4800 0 0 3 &pci_intc 2>,
+                               <0x4800 0 0 4 &pci_intc 3>,
+                               <0x5000 0 0 1 &pci_intc 1>, /* Slot 10 */
+                               <0x5000 0 0 2 &pci_intc 2>,
+                               <0x5000 0 0 3 &pci_intc 3>,
+                               <0x5000 0 0 4 &pci_intc 0>,
+                               <0x5800 0 0 1 &pci_intc 2>, /* Slot 11 */
+                               <0x5800 0 0 2 &pci_intc 3>,
+                               <0x5800 0 0 3 &pci_intc 0>,
+                               <0x5800 0 0 4 &pci_intc 1>,
+                               <0x6000 0 0 1 &pci_intc 3>, /* Slot 12 */
+                               <0x6000 0 0 2 &pci_intc 0>,
+                               <0x6000 0 0 3 &pci_intc 1>,
+                               <0x6000 0 0 4 &pci_intc 2>;
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/gemini-wbd111.dts b/arch/arm/boot/dts/gemini-wbd111.dts
new file mode 100644 (file)
index 0000000..63b756e
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Device Tree file for Wiliboard WBD-111
+ */
+
+/dts-v1/;
+
+#include "gemini.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+       model = "Wiliboard WBD-111";
+       compatible = "wiliboard,wbd111", "cortina,gemini";
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       memory { /* 128 MB */
+               device_type = "memory";
+               reg = <0x00000000 0x8000000>;
+       };
+
+       chosen {
+               bootargs = "console=ttyS0,115200n8";
+               stdout-path = &uart0;
+       };
+
+       gpio_keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               button@5 {
+                       debounce_interval = <50>;
+                       wakeup-source;
+                       linux,code = <KEY_SETUP>;
+                       label = "reset";
+                       gpios = <&gpio0 5 GPIO_ACTIVE_LOW>;
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               led@1 {
+                       label = "wbd111:red:L3";
+                       gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>;
+                       default-state = "off";
+               };
+               led@2 {
+                       label = "wbd111:green:L4";
+                       gpios = <&gpio0 2 GPIO_ACTIVE_HIGH>;
+                       default-state = "off";
+               };
+               led@3 {
+                       label = "wbd111:red:L4";
+                       gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>;
+                       default-state = "off";
+               };
+               led@5 {
+                       label = "wbd111:green:L3";
+                       gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>;
+                       default-state = "on";
+                       linux,default-trigger = "heartbeat";
+               };
+       };
+
+       soc {
+               flash@30000000 {
+                       status = "okay";
+                       /* 8MB of flash */
+                       reg = <0x30000000 0x00800000>;
+
+                       partition@0 {
+                               label = "RedBoot";
+                               reg = <0x00000000 0x00020000>;
+                               read-only;
+                       };
+                       partition@20000 {
+                               label = "kernel";
+                               reg = <0x00020000 0x00100000>;
+                       };
+                       partition@120000 {
+                               label = "rootfs";
+                               reg = <0x00120000 0x006a0000>;
+                       };
+                       partition@7c0000 {
+                               label = "VCTL";
+                               reg = <0x007c0000 0x00010000>;
+                               read-only;
+                       };
+                       partition@7d0000 {
+                               label = "cfg";
+                               reg = <0x007d0000 0x00010000>;
+                               read-only;
+                       };
+                       partition@7e0000 {
+                               label = "FIS";
+                               reg = <0x007e0000 0x00010000>;
+                               read-only;
+                       };
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/gemini-wbd222.dts b/arch/arm/boot/dts/gemini-wbd222.dts
new file mode 100644 (file)
index 0000000..9747f5a
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Device Tree file for Wiliboard WBD-222
+ */
+
+/dts-v1/;
+
+#include "gemini.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+       model = "Wiliboard WBD-222";
+       compatible = "wiliboard,wbd222", "cortina,gemini";
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       memory { /* 128 MB */
+               device_type = "memory";
+               reg = <0x00000000 0x8000000>;
+       };
+
+       chosen {
+               bootargs = "console=ttyS0,115200n8";
+               stdout-path = &uart0;
+       };
+
+       gpio_keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               button@5 {
+                       debounce_interval = <50>;
+                       wakeup-source;
+                       linux,code = <KEY_SETUP>;
+                       label = "reset";
+                       gpios = <&gpio0 5 GPIO_ACTIVE_LOW>;
+               };
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               led@1 {
+                       label = "wbd111:red:L3";
+                       gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>;
+                       default-state = "off";
+               };
+               led@2 {
+                       label = "wbd111:green:L4";
+                       gpios = <&gpio0 2 GPIO_ACTIVE_HIGH>;
+                       default-state = "off";
+               };
+               led@3 {
+                       label = "wbd111:red:L4";
+                       gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>;
+                       default-state = "off";
+               };
+               led@5 {
+                       label = "wbd111:green:L3";
+                       gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>;
+                       default-state = "on";
+                       linux,default-trigger = "heartbeat";
+               };
+       };
+
+       soc {
+               flash@30000000 {
+                       status = "okay";
+                       /* 8MB of flash */
+                       reg = <0x30000000 0x00800000>;
+
+                       partition@0 {
+                               label = "RedBoot";
+                               reg = <0x00000000 0x00020000>;
+                               read-only;
+                       };
+                       partition@20000 {
+                               label = "kernel";
+                               reg = <0x00020000 0x00100000>;
+                       };
+                       partition@120000 {
+                               label = "rootfs";
+                               reg = <0x00120000 0x006a0000>;
+                       };
+                       partition@7c0000 {
+                               label = "VCTL";
+                               reg = <0x007c0000 0x00010000>;
+                               read-only;
+                       };
+                       partition@7d0000 {
+                               label = "cfg";
+                               reg = <0x007d0000 0x00010000>;
+                               read-only;
+                       };
+                       partition@7e0000 {
+                               label = "FIS";
+                               reg = <0x007e0000 0x00010000>;
+                               read-only;
+                       };
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/gemini.dtsi b/arch/arm/boot/dts/gemini.dtsi
new file mode 100644 (file)
index 0000000..b8d011b
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Device Tree file for Cortina systems Gemini SoC
+ */
+
+/include/ "skeleton.dtsi"
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+       soc {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+               compatible = "simple-bus";
+               interrupt-parent = <&intcon>;
+
+               flash@30000000 {
+                       compatible = "cortina,gemini-flash", "cfi-flash";
+                       syscon = <&syscon>;
+                       bank-width = <2>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       status = "disabled";
+               };
+
+               syscon: syscon@40000000 {
+                       compatible = "cortina,gemini-syscon", "syscon", "simple-mfd";
+                       reg = <0x40000000 0x1000>;
+
+                       syscon-reboot {
+                               compatible = "syscon-reboot";
+                               regmap = <&syscon>;
+                               /* GLOBAL_RESET register */
+                               offset = <0x0c>;
+                               /* RESET_GLOBAL | RESET_CPU1 */
+                               mask = <0xC0000000>;
+                       };
+               };
+
+               watchdog@41000000 {
+                       compatible = "cortina,gemini-watchdog";
+                       reg = <0x41000000 0x1000>;
+                       interrupts = <3 IRQ_TYPE_LEVEL_HIGH>;
+               };
+
+               uart0: serial@42000000 {
+                       compatible = "ns16550a";
+                       reg = <0x42000000 0x100>;
+                       clock-frequency = <48000000>;
+                       interrupts = <18 IRQ_TYPE_LEVEL_HIGH>;
+                       reg-shift = <2>;
+               };
+
+               timer@43000000 {
+                       compatible = "cortina,gemini-timer";
+                       reg = <0x43000000 0x1000>;
+                       interrupt-parent = <&intcon>;
+                       interrupts = <14 IRQ_TYPE_EDGE_FALLING>, /* Timer 1 */
+                                    <15 IRQ_TYPE_EDGE_FALLING>, /* Timer 2 */
+                                    <16 IRQ_TYPE_EDGE_FALLING>; /* Timer 3 */
+                       syscon = <&syscon>;
+               };
+
+               rtc@45000000 {
+                       compatible = "cortina,gemini-rtc";
+                       reg = <0x45000000 0x100>;
+                       interrupts = <17 IRQ_TYPE_LEVEL_HIGH>;
+               };
+
+               intcon: interrupt-controller@48000000 {
+                       compatible = "faraday,ftintc010";
+                       reg = <0x48000000 0x1000>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               power-controller@4b000000 {
+                       compatible = "cortina,gemini-power-controller";
+                       reg = <0x4b000000 0x100>;
+                       interrupts = <26 IRQ_TYPE_EDGE_RISING>;
+               };
+
+               gpio0: gpio@4d000000 {
+                       compatible = "cortina,gemini-gpio", "faraday,ftgpio010";
+                       reg = <0x4d000000 0x100>;
+                       interrupts = <22 IRQ_TYPE_LEVEL_HIGH>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpio1: gpio@4e000000 {
+                       compatible = "cortina,gemini-gpio", "faraday,ftgpio010";
+                       reg = <0x4e000000 0x100>;
+                       interrupts = <23 IRQ_TYPE_LEVEL_HIGH>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpio2: gpio@4f000000 {
+                       compatible = "cortina,gemini-gpio", "faraday,ftgpio010";
+                       reg = <0x4f000000 0x100>;
+                       interrupts = <24 IRQ_TYPE_LEVEL_HIGH>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               pci@50000000 {
+                       compatible = "cortina,gemini-pci", "faraday,ftpci100";
+                       /*
+                        * The first 256 bytes in the IO range is actually used
+                        * to configure the host bridge.
+                        */
+                       reg = <0x50000000 0x100>;
+                       #address-cells = <3>;
+                       #size-cells = <2>;
+                       #interrupt-cells = <1>;
+                       status = "disabled";
+
+                       bus-range = <0x00 0xff>;
+                       /* PCI ranges mappings */
+                       ranges =
+                       /* 1MiB I/O space 0x50000000-0x500fffff */
+                       <0x01000000 0 0          0x50000000 0 0x00100000>,
+                       /* 128MiB non-prefetchable memory 0x58000000-0x5fffffff */
+                       <0x02000000 0 0x58000000 0x58000000 0 0x08000000>;
+
+                       /* DMA ranges */
+                       dma-ranges =
+                       /* 128MiB at 0x00000000-0x07ffffff */
+                       <0x02000000 0 0x00000000 0x00000000 0 0x08000000>,
+                       /* 64MiB at 0x00000000-0x03ffffff */
+                       <0x02000000 0 0x00000000 0x00000000 0 0x04000000>,
+                       /* 64MiB at 0x00000000-0x03ffffff */
+                       <0x02000000 0 0x00000000 0x00000000 0 0x04000000>;
+
+                       /*
+                        * This PCI host bridge variant has a cascaded interrupt
+                        * controller embedded in the host bridge.
+                        */
+                       pci_intc: interrupt-controller {
+                               interrupt-parent = <&intcon>;
+                               interrupts = <8 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-controller;
+                               #address-cells = <0>;
+                               #interrupt-cells = <1>;
+                       };
+               };
+       };
+};
index 9300711f1ea379a346c2055c1bac9d89c06ce205..db39bd6b8e0062ae1cae8b97b743a7ebc577f759 100644 (file)
 };
 
 &usbotg {
-       phy_type = "utmi";
-       dr_mode = "otg";
        external-vbus-divider;
        status = "okay";
 };
index 70292101ba038b7122e3cac312f0794cddb4ff42..d921dd2ed6761370ac9250c3ea9f6ce26af86ec1 100644 (file)
 };
 
 &usbotg {
-       phy_type = "utmi";
-       dr_mode = "otg";
        external-vbus-divider;
        status = "okay";
 };
index f840f03ad1719ba7dabbb18bc53652a96189fe09..6c63dca1b9b8fcc3229f03ae7571e8df3922913e 100644 (file)
@@ -17,8 +17,6 @@
  * <mux_reg conf_reg input_reg mux_mode input_val>
  */
 
-#define MX25_PAD_TDO__TDO                      0x000 0x3e8 0x000 0x00 0x000
-
 #define MX25_PAD_A10__A10                      0x008 0x000 0x000 0x00 0x000
 #define MX25_PAD_A10__GPIO_4_0                 0x008 0x000 0x000 0x05 0x000
 
@@ -68,7 +66,6 @@
 
 #define MX25_PAD_A22__A22                      0x030 0x000 0x000 0x00 0x000
 #define MX25_PAD_A22__GPIO_2_8                 0x030 0x000 0x000 0x05 0x000
-#define MX25_PAD_A22__FEC_TDATA2               0x030 0x000 0x000 0x07 0x000
 #define MX25_PAD_A22__SIM2_VEN1                        0x030 0x000 0x000 0x06 0x000
 #define MX25_PAD_A22__FEC_TDATA2               0x030 0x000 0x000 0x07 0x000
 
 #define MX25_PAD_RTCK__OWIRE                   0x1ec 0x3e4 0x000 0x01 0x000
 #define MX25_PAD_RTCK__GPIO_3_14               0x1ec 0x3e4 0x000 0x05 0x000
 
+#define MX25_PAD_TDO__TDO                      0x000 0x3e8 0x000 0x00 0x000
+
 #define MX25_PAD_DE_B__DE_B                    0x1f0 0x3ec 0x000 0x00 0x000
 #define MX25_PAD_DE_B__GPIO_2_20               0x1f0 0x3ec 0x000 0x05 0x000
 
index e0ba55016a04ad0e0a102336447f479416ef40b2..0cdf333336cde8e5276e9de8475a9776618f099d 100644 (file)
                        reg = <0x43f00000 0x100000>;
                        ranges;
 
+                       aips1: bridge@43f00000 {
+                               compatible = "fsl,imx25-aips";
+                               reg = <0x43f00000 0x4000>;
+                       };
+
                        i2c1: i2c@43f80000 {
                                #address-cells = <1>;
                                #size-cells = <0>;
                        reg = <0x53f00000 0x100000>;
                        ranges;
 
+                       aips2: bridge@53f00000 {
+                               compatible = "fsl,imx25-aips";
+                               reg = <0x53f00000 0x4000>;
+                       };
+
                        clks: ccm@53f80000 {
                                compatible = "fsl,imx25-ccm";
                                reg = <0x53f80000 0x4000>;
                                clock-names = "ipg", "ahb", "per";
                                fsl,usbmisc = <&usbmisc 0>;
                                fsl,usbphy = <&usbphy0>;
+                               phy_type = "utmi";
+                               dr_mode = "otg";
                                status = "disabled";
                        };
 
diff --git a/arch/arm/boot/dts/imx28-duckbill-2-485.dts b/arch/arm/boot/dts/imx28-duckbill-2-485.dts
new file mode 100644 (file)
index 0000000..bd3fd47
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2015-2017 I2SE GmbH <info@i2se.com>
+ * Copyright (C) 2016 Michael Heimpold <mhei@heimpold.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/gpio/gpio.h>
+#include "imx28.dtsi"
+
+/ {
+       model = "I2SE Duckbill 2 485";
+       compatible = "i2se,duckbill-2-485", "i2se,duckbill-2", "fsl,imx28";
+
+       memory {
+               reg = <0x40000000 0x08000000>;
+       };
+
+       apb@80000000 {
+               apbh@80000000 {
+                       ssp0: ssp@80010000 {
+                               compatible = "fsl,imx28-mmc";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&mmc0_8bit_pins_a
+                                       &mmc0_cd_cfg &mmc0_sck_cfg>;
+                               bus-width = <8>;
+                               vmmc-supply = <&reg_3p3v>;
+                               status = "okay";
+                               non-removable;
+                       };
+
+                       ssp2: ssp@80014000 {
+                               compatible = "fsl,imx28-mmc";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&mmc2_4bit_pins_b
+                                       &mmc2_cd_cfg &mmc2_sck_cfg_b>;
+                               bus-width = <4>;
+                               vmmc-supply = <&reg_3p3v>;
+                               status = "okay";
+                       };
+
+                       pinctrl@80018000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&hog_pins_a>;
+
+                               hog_pins_a: hog@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               MX28_PAD_LCD_D17__GPIO_1_17    /* Revision detection */
+                                       >;
+                                       fsl,drive-strength = <MXS_DRIVE_4mA>;
+                                       fsl,voltage = <MXS_VOLTAGE_HIGH>;
+                                       fsl,pull-up = <MXS_PULL_DISABLE>;
+                               };
+
+                               mac0_phy_reset_pin: mac0-phy-reset@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               MX28_PAD_GPMI_ALE__GPIO_0_26    /* PHY Reset */
+                                       >;
+                                       fsl,drive-strength = <MXS_DRIVE_4mA>;
+                                       fsl,voltage = <MXS_VOLTAGE_HIGH>;
+                                       fsl,pull-up = <MXS_PULL_DISABLE>;
+                               };
+
+                               mac0_phy_int_pin: mac0-phy-int@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               MX28_PAD_GPMI_D07__GPIO_0_7    /* PHY Interrupt */
+                                       >;
+                                       fsl,drive-strength = <MXS_DRIVE_4mA>;
+                                       fsl,voltage = <MXS_VOLTAGE_HIGH>;
+                                       fsl,pull-up = <MXS_PULL_DISABLE>;
+                               };
+
+                               led_pins: leds@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               MX28_PAD_SAIF0_MCLK__GPIO_3_20
+                                               MX28_PAD_SAIF0_LRCLK__GPIO_3_21
+                                               MX28_PAD_I2C0_SCL__GPIO_3_24
+                                               MX28_PAD_I2C0_SDA__GPIO_3_25
+                                       >;
+                                       fsl,drive-strength = <MXS_DRIVE_4mA>;
+                                       fsl,voltage = <MXS_VOLTAGE_HIGH>;
+                                       fsl,pull-up = <MXS_PULL_DISABLE>;
+                               };
+                       };
+               };
+
+               apbx@80040000 {
+                       lradc@80050000 {
+                               status = "okay";
+                       };
+
+                       auart0: serial@8006a000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&auart0_2pins_a>;
+                               status = "okay";
+                       };
+
+                       duart: serial@80074000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&duart_pins_a>;
+                               status = "okay";
+                       };
+
+                       usbphy0: usbphy@8007c000 {
+                               status = "okay";
+                       };
+               };
+       };
+
+       ahb@80080000 {
+               usb0: usb@80080000 {
+                       status = "okay";
+                       dr_mode = "peripheral";
+               };
+
+               mac0: ethernet@800f0000 {
+                       phy-mode = "rmii";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&mac0_pins_a>, <&mac0_phy_reset_pin>;
+                       phy-supply = <&reg_3p3v>;
+                       phy-reset-gpios = <&gpio0 26 GPIO_ACTIVE_LOW>;
+                       phy-reset-duration = <25>;
+                       phy-handle = <&ethphy>;
+                       status = "okay";
+
+                       mdio {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               ethphy: ethernet-phy@0 {
+                                       compatible = "ethernet-phy-ieee802.3-c22";
+                                       reg = <0>;
+                                       pinctrl-names = "default";
+                                       pinctrl-0 = <&mac0_phy_int_pin>;
+                                       interrupt-parent = <&gpio0>;
+                                       interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
+                                       max-speed = <100>;
+                               };
+                       };
+               };
+       };
+
+       reg_3p3v: regulator-3p3v {
+               compatible = "regulator-fixed";
+               regulator-name = "3P3V";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-always-on;
+       };
+
+       leds {
+               compatible = "gpio-leds";
+               pinctrl-names = "default";
+               pinctrl-0 = <&led_pins>;
+
+               status-red {
+                       label = "duckbill:red:status";
+                       gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "default-on";
+               };
+
+               status-green {
+                       label = "duckbill:green:status";
+                       gpios = <&gpio3 20 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "heartbeat";
+               };
+
+               rs485-red {
+                       label = "duckbill:red:rs485";
+                       gpios = <&gpio3 24 GPIO_ACTIVE_LOW>;
+               };
+
+               rs485-green {
+                       label = "duckbill:green:rs485";
+                       gpios = <&gpio3 25 GPIO_ACTIVE_LOW>;
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/imx28-duckbill-2-enocean.dts b/arch/arm/boot/dts/imx28-duckbill-2-enocean.dts
new file mode 100644 (file)
index 0000000..4450047
--- /dev/null
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2015-2017 I2SE GmbH <info@i2se.com>
+ * Copyright (C) 2016 Michael Heimpold <mhei@heimpold.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/gpio/gpio.h>
+#include "imx28.dtsi"
+
+/ {
+       model = "I2SE Duckbill 2 EnOcean";
+       compatible = "i2se,duckbill-2-enocean", "i2se,duckbill-2", "fsl,imx28";
+
+       memory {
+               reg = <0x40000000 0x08000000>;
+       };
+
+       apb@80000000 {
+               apbh@80000000 {
+                       ssp0: ssp@80010000 {
+                               compatible = "fsl,imx28-mmc";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&mmc0_8bit_pins_a
+                                       &mmc0_cd_cfg &mmc0_sck_cfg>;
+                               bus-width = <8>;
+                               vmmc-supply = <&reg_3p3v>;
+                               status = "okay";
+                               non-removable;
+                       };
+
+                       ssp2: ssp@80014000 {
+                               compatible = "fsl,imx28-mmc";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&mmc2_4bit_pins_b
+                                       &mmc2_cd_cfg &mmc2_sck_cfg_b>;
+                               bus-width = <4>;
+                               vmmc-supply = <&reg_3p3v>;
+                               status = "okay";
+                       };
+
+                       pinctrl@80018000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&hog_pins_a>;
+
+                               hog_pins_a: hog@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               MX28_PAD_LCD_D17__GPIO_1_17    /* Revision detection */
+                                       >;
+                                       fsl,drive-strength = <MXS_DRIVE_4mA>;
+                                       fsl,voltage = <MXS_VOLTAGE_HIGH>;
+                                       fsl,pull-up = <MXS_PULL_DISABLE>;
+                               };
+
+                               mac0_phy_reset_pin: mac0-phy-reset@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               MX28_PAD_GPMI_ALE__GPIO_0_26    /* PHY Reset */
+                                       >;
+                                       fsl,drive-strength = <MXS_DRIVE_4mA>;
+                                       fsl,voltage = <MXS_VOLTAGE_HIGH>;
+                                       fsl,pull-up = <MXS_PULL_DISABLE>;
+                               };
+
+                               mac0_phy_int_pin: mac0-phy-int@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               MX28_PAD_GPMI_D07__GPIO_0_7    /* PHY Interrupt */
+                                       >;
+                                       fsl,drive-strength = <MXS_DRIVE_4mA>;
+                                       fsl,voltage = <MXS_VOLTAGE_HIGH>;
+                                       fsl,pull-up = <MXS_PULL_DISABLE>;
+                               };
+
+                               led_pins: leds@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               MX28_PAD_SAIF0_MCLK__GPIO_3_20
+                                               MX28_PAD_SAIF0_LRCLK__GPIO_3_21
+                                               MX28_PAD_AUART0_CTS__GPIO_3_2
+                                               MX28_PAD_I2C0_SCL__GPIO_3_24
+                                               MX28_PAD_I2C0_SDA__GPIO_3_25
+                                       >;
+                                       fsl,drive-strength = <MXS_DRIVE_4mA>;
+                                       fsl,voltage = <MXS_VOLTAGE_HIGH>;
+                                       fsl,pull-up = <MXS_PULL_DISABLE>;
+                               };
+
+                               enocean_button: enocean-button@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               MX28_PAD_AUART0_RTS__GPIO_3_3
+                                       >;
+                                       fsl,drive-strength = <MXS_DRIVE_4mA>;
+                                       fsl,voltage = <MXS_VOLTAGE_HIGH>;
+                                       fsl,pull-up = <MXS_PULL_DISABLE>;
+                               };
+                       };
+               };
+
+               apbx@80040000 {
+                       lradc@80050000 {
+                               status = "okay";
+                       };
+
+                       auart0: serial@8006a000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&auart0_2pins_a>;
+                               status = "okay";
+                       };
+
+                       duart: serial@80074000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&duart_pins_a>;
+                               status = "okay";
+                       };
+
+                       usbphy0: usbphy@8007c000 {
+                               status = "okay";
+                       };
+               };
+       };
+
+       ahb@80080000 {
+               usb0: usb@80080000 {
+                       status = "okay";
+                       dr_mode = "peripheral";
+               };
+
+               mac0: ethernet@800f0000 {
+                       phy-mode = "rmii";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&mac0_pins_a>, <&mac0_phy_reset_pin>;
+                       phy-supply = <&reg_3p3v>;
+                       phy-reset-gpios = <&gpio0 26 GPIO_ACTIVE_LOW>;
+                       phy-reset-duration = <25>;
+                       phy-handle = <&ethphy>;
+                       status = "okay";
+
+                       mdio {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               ethphy: ethernet-phy@0 {
+                                       compatible = "ethernet-phy-ieee802.3-c22";
+                                       reg = <0>;
+                                       pinctrl-names = "default";
+                                       pinctrl-0 = <&mac0_phy_int_pin>;
+                                       interrupt-parent = <&gpio0>;
+                                       interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
+                                       max-speed = <100>;
+                               };
+                       };
+               };
+       };
+
+       reg_3p3v: regulator-3p3v {
+               compatible = "regulator-fixed";
+               regulator-name = "3P3V";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-always-on;
+       };
+
+       leds {
+               compatible = "gpio-leds";
+               pinctrl-names = "default";
+               pinctrl-0 = <&led_pins>;
+
+               status-red {
+                       label = "duckbill:red:status";
+                       gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "default-on";
+               };
+
+               status-green {
+                       label = "duckbill:green:status";
+                       gpios = <&gpio3 20 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "heartbeat";
+               };
+
+               enocean-blue {
+                       label = "duckbill:blue:enocean";
+                       gpios = <&gpio3 24 GPIO_ACTIVE_LOW>;
+               };
+
+               enocean-red {
+                       label = "duckbill:red:enocean";
+                       gpios = <&gpio3 25 GPIO_ACTIVE_LOW>;
+               };
+
+               enocean-green {
+                       label = "duckbill:green:enocean";
+                       gpios = <&gpio3 2 GPIO_ACTIVE_LOW>;
+               };
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&enocean_button>;
+
+               enocean {
+                       label = "EnOcean";
+                       linux,code = <KEY_NEW>;
+                       gpios = <&gpio3 3 GPIO_ACTIVE_HIGH>;
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/imx28-duckbill-2-spi.dts b/arch/arm/boot/dts/imx28-duckbill-2-spi.dts
new file mode 100644 (file)
index 0000000..927732e
--- /dev/null
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2015-2017 I2SE GmbH <info@i2se.com>
+ * Copyright (C) 2016 Michael Heimpold <mhei@heimpold.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/gpio/gpio.h>
+#include "imx28.dtsi"
+
+/ {
+       model = "I2SE Duckbill 2 SPI";
+       compatible = "i2se,duckbill-2-spi", "i2se,duckbill-2", "fsl,imx28";
+
+       aliases {
+               ethernet1 = &qca7000;
+       };
+
+       memory {
+               reg = <0x40000000 0x08000000>;
+       };
+
+       apb@80000000 {
+               apbh@80000000 {
+                       ssp0: ssp@80010000 {
+                               compatible = "fsl,imx28-mmc";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&mmc0_8bit_pins_a
+                                       &mmc0_cd_cfg &mmc0_sck_cfg>;
+                               bus-width = <8>;
+                               vmmc-supply = <&reg_3p3v>;
+                               status = "okay";
+                               non-removable;
+                       };
+
+                       ssp2: ssp@80014000 {
+                               compatible = "fsl,imx28-spi";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&spi2_pins_a>;
+                               status = "okay";
+
+                               qca7000: ethernet@0 {
+                                       reg = <0>;
+                                       compatible = "qca,qca7000";
+                                       pinctrl-names = "default";
+                                       pinctrl-0 = <&qca7000_pins>;
+                                       interrupt-parent = <&gpio3>;
+                                       interrupts = <3 IRQ_TYPE_EDGE_RISING>;
+                                       spi-cpha;
+                                       spi-cpol;
+                                       spi-max-frequency = <8000000>;
+                               };
+                       };
+
+                       pinctrl@80018000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&hog_pins_a>;
+
+                               hog_pins_a: hog@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               MX28_PAD_LCD_D17__GPIO_1_17    /* Revision detection */
+                                       >;
+                                       fsl,drive-strength = <MXS_DRIVE_4mA>;
+                                       fsl,voltage = <MXS_VOLTAGE_HIGH>;
+                                       fsl,pull-up = <MXS_PULL_DISABLE>;
+                               };
+
+                               mac0_phy_reset_pin: mac0-phy-reset@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               MX28_PAD_GPMI_ALE__GPIO_0_26    /* PHY Reset */
+                                       >;
+                                       fsl,drive-strength = <MXS_DRIVE_4mA>;
+                                       fsl,voltage = <MXS_VOLTAGE_HIGH>;
+                                       fsl,pull-up = <MXS_PULL_DISABLE>;
+                               };
+
+                               mac0_phy_int_pin: mac0-phy-int@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               MX28_PAD_GPMI_D07__GPIO_0_7    /* PHY Interrupt */
+                                       >;
+                                       fsl,drive-strength = <MXS_DRIVE_4mA>;
+                                       fsl,voltage = <MXS_VOLTAGE_HIGH>;
+                                       fsl,pull-up = <MXS_PULL_DISABLE>;
+                               };
+
+                               led_pins: led@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               MX28_PAD_SAIF0_MCLK__GPIO_3_20
+                                               MX28_PAD_SAIF0_LRCLK__GPIO_3_21
+                                       >;
+                                       fsl,drive-strength = <MXS_DRIVE_4mA>;
+                                       fsl,voltage = <MXS_VOLTAGE_HIGH>;
+                                       fsl,pull-up = <MXS_PULL_DISABLE>;
+                               };
+
+                               qca7000_pins: qca7000@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               MX28_PAD_AUART0_RTS__GPIO_3_3    /* Interrupt */
+                                               MX28_PAD_LCD_D13__GPIO_1_13      /* QCA7K reset */
+                                               MX28_PAD_LCD_D14__GPIO_1_14      /* GPIO 0 */
+                                               MX28_PAD_LCD_D15__GPIO_1_15      /* GPIO 1 */
+                                               MX28_PAD_LCD_D18__GPIO_1_18      /* GPIO 2 */
+                                               MX28_PAD_LCD_D21__GPIO_1_21      /* GPIO 3 */
+                                       >;
+                                       fsl,drive-strength = <MXS_DRIVE_4mA>;
+                                       fsl,voltage = <MXS_VOLTAGE_HIGH>;
+                                       fsl,pull-up = <MXS_PULL_DISABLE>;
+                               };
+                       };
+               };
+
+               apbx@80040000 {
+                       lradc@80050000 {
+                               status = "okay";
+                       };
+
+                       duart: serial@80074000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&duart_pins_a>;
+                               status = "okay";
+                       };
+
+                       usbphy0: usbphy@8007c000 {
+                               status = "okay";
+                       };
+               };
+       };
+
+       ahb@80080000 {
+               usb0: usb@80080000 {
+                       status = "okay";
+                       dr_mode = "peripheral";
+               };
+
+               mac0: ethernet@800f0000 {
+                       phy-mode = "rmii";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&mac0_pins_a>, <&mac0_phy_reset_pin>;
+                       phy-supply = <&reg_3p3v>;
+                       phy-reset-gpios = <&gpio0 26 GPIO_ACTIVE_LOW>;
+                       phy-reset-duration = <25>;
+                       phy-handle = <&ethphy>;
+                       status = "okay";
+
+                       mdio {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               ethphy: ethernet-phy@0 {
+                                       compatible = "ethernet-phy-ieee802.3-c22";
+                                       reg = <0>;
+                                       pinctrl-names = "default";
+                                       pinctrl-0 = <&mac0_phy_int_pin>;
+                                       interrupt-parent = <&gpio0>;
+                                       interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
+                                       max-speed = <100>;
+                               };
+                       };
+               };
+       };
+
+       reg_3p3v: regulator-3p3v {
+               compatible = "regulator-fixed";
+               regulator-name = "3P3V";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-always-on;
+       };
+
+       leds {
+               compatible = "gpio-leds";
+               pinctrl-names = "default";
+               pinctrl-0 = <&led_pins>;
+
+               status-red {
+                       label = "duckbill:red:status";
+                       gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "default-on";
+               };
+
+               status-green {
+                       label = "duckbill:green:status";
+                       gpios = <&gpio3 20 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "heartbeat";
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/imx28-duckbill-2.dts b/arch/arm/boot/dts/imx28-duckbill-2.dts
new file mode 100644 (file)
index 0000000..7fa3d75
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2015-2017 I2SE GmbH <info@i2se.com>
+ * Copyright (C) 2016 Michael Heimpold <mhei@heimpold.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/gpio/gpio.h>
+#include "imx28.dtsi"
+
+/ {
+       model = "I2SE Duckbill 2";
+       compatible = "i2se,duckbill-2", "fsl,imx28";
+
+       memory {
+               reg = <0x40000000 0x08000000>;
+       };
+
+       apb@80000000 {
+               apbh@80000000 {
+                       ssp0: ssp@80010000 {
+                               compatible = "fsl,imx28-mmc";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&mmc0_8bit_pins_a
+                                       &mmc0_cd_cfg &mmc0_sck_cfg>;
+                               bus-width = <8>;
+                               vmmc-supply = <&reg_3p3v>;
+                               status = "okay";
+                               non-removable;
+                       };
+
+                       ssp2: ssp@80014000 {
+                               compatible = "fsl,imx28-mmc";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&mmc2_4bit_pins_b
+                                       &mmc2_cd_cfg &mmc2_sck_cfg_b>;
+                               bus-width = <4>;
+                               vmmc-supply = <&reg_3p3v>;
+                               status = "okay";
+                       };
+
+                       pinctrl@80018000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&hog_pins_a>;
+
+                               hog_pins_a: hog@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               MX28_PAD_LCD_D17__GPIO_1_17    /* Revision detection */
+                                       >;
+                                       fsl,drive-strength = <MXS_DRIVE_4mA>;
+                                       fsl,voltage = <MXS_VOLTAGE_HIGH>;
+                                       fsl,pull-up = <MXS_PULL_DISABLE>;
+                               };
+
+                               mac0_phy_reset_pin: mac0-phy-reset@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               MX28_PAD_GPMI_ALE__GPIO_0_26    /* PHY Reset */
+                                       >;
+                                       fsl,drive-strength = <MXS_DRIVE_4mA>;
+                                       fsl,voltage = <MXS_VOLTAGE_HIGH>;
+                                       fsl,pull-up = <MXS_PULL_DISABLE>;
+                               };
+
+                               mac0_phy_int_pin: mac0-phy-int@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               MX28_PAD_GPMI_D07__GPIO_0_7    /* PHY Interrupt */
+                                       >;
+                                       fsl,drive-strength = <MXS_DRIVE_4mA>;
+                                       fsl,voltage = <MXS_VOLTAGE_HIGH>;
+                                       fsl,pull-up = <MXS_PULL_DISABLE>;
+                               };
+
+                               led_pins: leds@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               MX28_PAD_SAIF0_MCLK__GPIO_3_20
+                                               MX28_PAD_SAIF0_LRCLK__GPIO_3_21
+                                       >;
+                                       fsl,drive-strength = <MXS_DRIVE_4mA>;
+                                       fsl,voltage = <MXS_VOLTAGE_HIGH>;
+                                       fsl,pull-up = <MXS_PULL_DISABLE>;
+                               };
+                       };
+               };
+
+               apbx@80040000 {
+                       lradc@80050000 {
+                               status = "okay";
+                       };
+
+                       i2c0: i2c@80058000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&i2c0_pins_a>;
+                               status = "okay";
+                       };
+
+                       auart0: serial@8006a000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&auart0_2pins_a>;
+                               status = "okay";
+                       };
+
+                       duart: serial@80074000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&duart_pins_a>;
+                               status = "okay";
+                       };
+
+                       usbphy0: usbphy@8007c000 {
+                               status = "okay";
+                       };
+               };
+       };
+
+       ahb@80080000 {
+               usb0: usb@80080000 {
+                       status = "okay";
+                       dr_mode = "peripheral";
+               };
+
+               mac0: ethernet@800f0000 {
+                       phy-mode = "rmii";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&mac0_pins_a>, <&mac0_phy_reset_pin>;
+                       phy-supply = <&reg_3p3v>;
+                       phy-reset-gpios = <&gpio0 26 GPIO_ACTIVE_LOW>;
+                       phy-reset-duration = <25>;
+                       phy-handle = <&ethphy>;
+                       status = "okay";
+
+                       mdio {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               ethphy: ethernet-phy@0 {
+                                       compatible = "ethernet-phy-ieee802.3-c22";
+                                       reg = <0>;
+                                       pinctrl-names = "default";
+                                       pinctrl-0 = <&mac0_phy_int_pin>;
+                                       interrupt-parent = <&gpio0>;
+                                       interrupts = <7 IRQ_TYPE_EDGE_FALLING>;
+                                       max-speed = <100>;
+                               };
+                       };
+               };
+       };
+
+       reg_3p3v: regulator-3p3v {
+               compatible = "regulator-fixed";
+               regulator-name = "3P3V";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-always-on;
+       };
+
+       leds {
+               compatible = "gpio-leds";
+               pinctrl-names = "default";
+               pinctrl-0 = <&led_pins>;
+
+               status-red {
+                       label = "duckbill:red:status";
+                       gpios = <&gpio3 21 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "default-on";
+               };
+
+               status-green {
+                       label = "duckbill:green:status";
+                       gpios = <&gpio3 20 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "heartbeat";
+               };
+       };
+};
index ce1a7effba3770ce8708cfb44ecae6e781d6a79f..3e4385d4ed78dee6e0259ea0749dfe04ab535995 100644 (file)
@@ -1,5 +1,6 @@
 /*
- * Copyright (C) 2013 Michael Heimpold <mhei@heimpold.de>
+ * Copyright (C) 2013-2014,2016 Michael Heimpold <mhei@heimpold.de>
+ * Copyright (C) 2015-2017 I2SE GmbH <info@i2se.com>
  *
  * The code contained herein is licensed under the GNU General Public
  * License. You may obtain a copy of the GNU General Public License
@@ -10,6 +11,7 @@
  */
 
 /dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
 #include "imx28.dtsi"
 
 / {
                                status = "okay";
                        };
 
+                       ssp2: ssp@80014000 {
+                               compatible = "fsl,imx28-spi";
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&spi2_pins_a>;
+                               status = "okay";
+                       };
+
                        pinctrl@80018000 {
                                pinctrl-names = "default";
                                pinctrl-0 = <&hog_pins_a>;
                                hog_pins_a: hog@0 {
                                        reg = <0>;
                                        fsl,pinmux-ids = <
-                                               MX28_PAD_SSP0_DATA7__GPIO_2_7 /* PHY Reset */
+                                               MX28_PAD_LCD_D17__GPIO_1_17    /* Revision detection */
+                                       >;
+                                       fsl,drive-strength = <MXS_DRIVE_4mA>;
+                                       fsl,voltage = <MXS_VOLTAGE_HIGH>;
+                                       fsl,pull-up = <MXS_PULL_DISABLE>;
+                               };
+
+                               mac0_phy_reset_pin: mac0-phy-reset@0 {
+                                       reg = <0>;
+                                       fsl,pinmux-ids = <
+                                               MX28_PAD_SSP0_DATA7__GPIO_2_7    /* PHY Reset */
                                        >;
                                        fsl,drive-strength = <MXS_DRIVE_4mA>;
                                        fsl,voltage = <MXS_VOLTAGE_HIGH>;
                                        fsl,pull-up = <MXS_PULL_DISABLE>;
                                };
 
-                               led_pins_a: led_gpio@0 {
+                               led_pins: leds@0 {
                                        reg = <0>;
                                        fsl,pinmux-ids = <
                                                MX28_PAD_AUART1_RX__GPIO_3_4
                };
 
                apbx@80040000 {
+                       lradc@80050000 {
+                               status = "okay";
+                       };
+
+                       i2c0: i2c@80058000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&i2c0_pins_a>;
+                               status = "okay";
+                       };
+
+                       auart0: serial@8006a000 {
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&auart0_2pins_a>;
+                               status = "okay";
+                       };
+
                        duart: serial@80074000 {
                                pinctrl-names = "default";
                                pinctrl-0 = <&duart_pins_a>;
        ahb@80080000 {
                usb0: usb@80080000 {
                        status = "okay";
+                       dr_mode = "peripheral";
                };
 
                mac0: ethernet@800f0000 {
                        phy-mode = "rmii";
                        pinctrl-names = "default";
-                       pinctrl-0 = <&mac0_pins_a>;
+                       pinctrl-0 = <&mac0_pins_a>, <&mac0_phy_reset_pin>;
                        phy-supply = <&reg_3p3v>;
                        phy-reset-gpios = <&gpio2 7 GPIO_ACTIVE_LOW>;
-                       phy-reset-duration = <100>;
+                       phy-reset-duration = <25>;
                        status = "okay";
                };
        };
 
-       regulators {
-               compatible = "simple-bus";
-               #address-cells = <1>;
-               #size-cells = <0>;
-
-               reg_3p3v: regulator@0 {
-                       compatible = "regulator-fixed";
-                       reg = <0>;
-                       regulator-name = "3P3V";
-                       regulator-min-microvolt = <3300000>;
-                       regulator-max-microvolt = <3300000>;
-                       regulator-always-on;
-               };
+       reg_3p3v: regulator-3p3v {
+               compatible = "regulator-fixed";
+               regulator-name = "3P3V";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-always-on;
        };
 
        leds {
                compatible = "gpio-leds";
                pinctrl-names = "default";
-               pinctrl-0 = <&led_pins_a>;
+               pinctrl-0 = <&led_pins>;
 
-               status {
-                       label = "duckbill:green:status";
-                       gpios = <&gpio3 5 GPIO_ACTIVE_HIGH>;
-               };
-
-               failure {
+               status-red {
                        label = "duckbill:red:status";
                        gpios = <&gpio3 4 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "default-on";
+               };
+
+               status-green {
+                       label = "duckbill:green:status";
+                       gpios = <&gpio3 5 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "heartbeat";
                };
        };
 };
index 2df63bee6f4e1a5df65a00fd9620951dac3e9e5e..bb5329479c62fd471d35c57ebc1233f0ca3e9119 100644 (file)
@@ -57,7 +57,7 @@
                                pinctrl-names = "default";
                                pinctrl-0 = <&mmc2_4bit_pins_a
                                             &mmc2_cd_cfg
-                                            &mmc2_sck_cfg>;
+                                            &mmc2_sck_cfg_a>;
                                bus-width = <4>;
                                vmmc-supply = <&reg_vddio_sd1>;
                                status = "okay";
index 148fcf4d3b98a217a1b6e9d4ce8fb1ce3b60fcb8..2f4ebe0318d32cfa18c7a02f55dc59654d77ff99 100644 (file)
                                        fsl,pull-up = <MXS_PULL_ENABLE>;
                                };
 
+                               mmc2_4bit_pins_b: mmc2-4bit@1 {
+                                       reg = <1>;
+                                       fsl,pinmux-ids = <
+                                               MX28_PAD_SSP2_SCK__SSP2_SCK
+                                               MX28_PAD_SSP2_MOSI__SSP2_CMD
+                                               MX28_PAD_SSP2_MISO__SSP2_D0
+                                               MX28_PAD_SSP2_SS0__SSP2_D3
+                                               MX28_PAD_SSP2_SS1__SSP2_D1
+                                               MX28_PAD_SSP2_SS2__SSP2_D2
+                                               MX28_PAD_AUART1_RX__SSP2_CARD_DETECT
+                                       >;
+                                       fsl,drive-strength = <MXS_DRIVE_8mA>;
+                                       fsl,voltage = <MXS_VOLTAGE_HIGH>;
+                                       fsl,pull-up = <MXS_PULL_ENABLE>;
+                               };
+
                                mmc2_cd_cfg: mmc2-cd-cfg {
                                        fsl,pinmux-ids = <
                                                MX28_PAD_AUART1_RX__SSP2_CARD_DETECT
                                        fsl,pull-up = <MXS_PULL_DISABLE>;
                                };
 
-                               mmc2_sck_cfg: mmc2-sck-cfg {
+                               mmc2_sck_cfg_a: mmc2-sck-cfg@0 {
+                                       reg = <0>;
                                        fsl,pinmux-ids = <
                                                MX28_PAD_SSP0_DATA7__SSP2_SCK
                                        >;
                                        fsl,pull-up = <MXS_PULL_DISABLE>;
                                };
 
+                               mmc2_sck_cfg_b: mmc2-sck-cfg@1 {
+                                       reg = <1>;
+                                       fsl,pinmux-ids = <
+                                               MX28_PAD_SSP2_SCK__SSP2_SCK
+                                       >;
+                                       fsl,drive-strength = <MXS_DRIVE_12mA>;
+                                       fsl,pull-up = <MXS_PULL_DISABLE>;
+                               };
+
                                i2c0_pins_a: i2c0@0 {
                                        reg = <0>;
                                        fsl,pinmux-ids = <
index ceae909e2201f729e8ed64a2f9baaa3103d3d968..2a98afcd8a4e302834596ab40655646c097b3ccc 100644 (file)
                                ranges;
 
                                esdhc1: esdhc@50004000 {
-                                       compatible = "fsl,imx50-esdhc";
+                                       compatible = "fsl,imx50-esdhc", "fsl,imx53-esdhc";
                                        reg = <0x50004000 0x4000>;
                                        interrupts = <1>;
                                        clocks = <&clks IMX5_CLK_ESDHC1_IPG_GATE>,
                                };
 
                                esdhc2: esdhc@50008000 {
-                                       compatible = "fsl,imx50-esdhc";
+                                       compatible = "fsl,imx50-esdhc", "fsl,imx53-esdhc";
                                        reg = <0x50008000 0x4000>;
                                        interrupts = <2>;
                                        clocks = <&clks IMX5_CLK_ESDHC2_IPG_GATE>,
                                };
 
                                esdhc3: esdhc@50020000 {
-                                       compatible = "fsl,imx50-esdhc";
+                                       compatible = "fsl,imx50-esdhc", "fsl,imx53-esdhc";
                                        reg = <0x50020000 0x4000>;
                                        interrupts = <3>;
                                        clocks = <&clks IMX5_CLK_ESDHC3_IPG_GATE>,
                                };
 
                                esdhc4: esdhc@50024000 {
-                                       compatible = "fsl,imx50-esdhc";
+                                       compatible = "fsl,imx50-esdhc", "fsl,imx53-esdhc";
                                        reg = <0x50024000 0x4000>;
                                        interrupts = <4>;
                                        clocks = <&clks IMX5_CLK_ESDHC4_IPG_GATE>,
index f4c158cce908e9fd77ec78c1e79ffa0b18cd0a45..d3d662e376772182e13f24df1152bca84e14df0e 100644 (file)
@@ -88,8 +88,8 @@
                        };
 
                        ldo7_reg: ldo7 {
-                               regulator-min-microvolt = <1200000>;
-                               regulator-max-microvolt = <3600000>;
+                               regulator-min-microvolt = <2750000>;
+                               regulator-max-microvolt = <2750000>;
                        };
 
                        ldo8_reg: ldo8 {
index 479ca4c9e3841671db80573b18a65f709e0a306e..4e103a905dc9c9adb112caba85f2b7cff8f8ef1d 100644 (file)
@@ -23,7 +23,7 @@
        imx53-qsrb {
                pinctrl_pmic: pmicgrp {
                        fsl,pins = <
-                               MX53_PAD_CSI0_DAT5__GPIO5_23    0x1e4 /* IRQ */
+                               MX53_PAD_CSI0_DAT5__GPIO5_23    0x1c4 /* IRQ */
                        >;
                };
        };
 
                        vdac_reg: vdac {
                                regulator-name = "VDAC";
-                               regulator-min-microvolt = <2500000>;
-                               regulator-max-microvolt = <2775000>;
+                               regulator-min-microvolt = <2750000>;
+                               regulator-max-microvolt = <2750000>;
                        };
 
                        vgen1_reg: vgen1 {
diff --git a/arch/arm/boot/dts/imx6dl-gw5903.dts b/arch/arm/boot/dts/imx6dl-gw5903.dts
new file mode 100644 (file)
index 0000000..103261e
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2017 Gateworks Corporation
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this file; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-gw5903.dtsi"
+
+/ {
+       model = "Gateworks Ventana i.MX6 Duallite/Solo GW5903";
+       compatible = "gw,imx6dl-gw5903", "gw,ventana", "fsl,imx6dl";
+};
diff --git a/arch/arm/boot/dts/imx6dl-gw5904.dts b/arch/arm/boot/dts/imx6dl-gw5904.dts
new file mode 100644 (file)
index 0000000..9c6d3cd
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2017 Gateworks Corporation
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this file; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "imx6dl.dtsi"
+#include "imx6qdl-gw5904.dtsi"
+
+/ {
+       model = "Gateworks Ventana i.MX6 DualLite/Solo GW5904";
+       compatible = "gw,imx6dl-gw5904", "gw,ventana", "fsl,imx6dl";
+};
index 116bebb5e4353d229b170b697ca9b0abe51a18fa..404a93d9596ba6ed04510a49dd25a7bd5961f0e1 100644 (file)
                output-low;
                line-name = "PCA9539-P05";
        };
+
+        P07 {
+                gpio-hog;
+                gpios = <7 0>;
+                output-low;
+                line-name = "PCA9539-P07";
+        };
 };
index 33f5c436c09f65878213126af440546ddbd81b00..7f9f176901d4c5842fbf35ed33cf61e7192222ca 100644 (file)
                output-low;
                line-name = "PCA9539-P05";
        };
+
+        P07 {
+                gpio-hog;
+                gpios = <7 0>;
+                output-low;
+                line-name = "PCA9539-P07";
+        };
 };
 
 &usbphy1 {
index d78514c9234952048e15dda288e481e06a30b1e3..2c1e98e0cf7bf469593f0d28f9a830b73deb35bb 100644 (file)
                fsl,data-mapping = "spwg";
                fsl,data-width = <24>;
                status = "okay";
+
+               port@4 {
+                       reg = <4>;
+
+                       lvds0_out: endpoint {
+                               remote-endpoint = <&stdp4028_in>;
+                       };
+               };
        };
 };
 
                reg = <0x4a>;
        };
 };
+
+&mux2_i2c2 {
+       clock-frequency = <100000>;
+
+       stdp2690@72 {
+               compatible = "megachips,stdp2690-ge-b850v3-fw";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               reg = <0x72>;
+
+               ports {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       port@0 {
+                               reg = <0>;
+
+                               stdp2690_in: endpoint {
+                                       remote-endpoint = <&stdp4028_out>;
+                               };
+                       };
+
+                       port@1 {
+                               reg = <1>;
+
+                               stdp2690_out: endpoint {
+                                       /* Connector for external display */
+                               };
+                       };
+               };
+       };
+
+       stdp4028@73 {
+               compatible = "megachips,stdp4028-ge-b850v3-fw";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               reg = <0x73>;
+               interrupt-parent = <&gpio2>;
+               interrupts = <0 IRQ_TYPE_LEVEL_HIGH>;
+
+               ports {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       port@0 {
+                               reg = <0>;
+
+                               stdp4028_in: endpoint {
+                                       remote-endpoint = <&lvds0_out>;
+                               };
+                       };
+
+                       port@1 {
+                               reg = <1>;
+
+                               stdp4028_out: endpoint {
+                                       remote-endpoint = <&stdp2690_in>;
+                               };
+                       };
+               };
+       };
+};
index 36d6bb39593a005b20723d1c5517c51ef9bfd2d8..c90b26f00e24c8395b3ebd2d0d20f1a2481e0a33 100644 (file)
 
        m25_eeprom: m25p80@0 {
                compatible = "atmel,at25";
-               spi-max-frequency = <20000000>;
+               spi-max-frequency = <10000000>;
                size = <0x8000>;
                pagesize = <64>;
                reg = <0>;
                                interrupt-parent = <&gpio2>;
                                interrupts = <3 IRQ_TYPE_LEVEL_LOW>;
 
-                               P06 {
-                                       gpio-hog;
-                                       gpios = <6 0>;
-                                       output-low;
-                                       line-name = "PCA9539-P06";
-                               };
-
-                               P07 {
-                                       gpio-hog;
-                                       gpios = <7 0>;
-                                       output-low;
-                                       line-name = "PCA9539-P07";
-                               };
-
                                P10 {
                                        gpio-hog;
                                        gpios = <8 0>;
index d8a5789a4bc809a67ef3c7f2d6cd715e4193f0b9..66cac5328b86ba8fcc61c5d9013224f8457f2611 100644 (file)
@@ -43,6 +43,7 @@
 
 /dts-v1/;
 #include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/sound/fsl-imx-audmux.h>
 #include "imx6q.dtsi"
 
 / {
                enable-active-high;
        };
 
+       sound-analog {
+               compatible = "simple-audio-card";
+               simple-audio-card,name = "On-board analog audio";
+               simple-audio-card,widgets =
+                       "Headphone", "Headphone Jack",
+                       "Line", "Line Out",
+                       "Microphone", "Mic Jack",
+                       "Line", "Line In";
+               simple-audio-card,routing =
+                       "Headphone Jack", "RHPOUT",
+                       "Headphone Jack", "LHPOUT",
+                       "MICIN", "Mic Bias",
+                       "Mic Bias", "Mic Jack";
+               simple-audio-card,format = "i2s";
+               simple-audio-card,bitclock-master = <&sound_master>;
+               simple-audio-card,frame-master = <&sound_master>;
+               simple-audio-card,bitclock-inversion;
+
+               sound_master: simple-audio-card,cpu {
+                       sound-dai = <&ssi2>;
+                       system-clock-frequency = <2822400>;
+               };
+
+               simple-audio-card,codec {
+                       sound-dai = <&wm8731>;
+               };
+       };
+
        sound-spdif {
                compatible = "fsl,imx-audio-spdif";
                model = "imx-spdif";
        };
 };
 
+&audmux {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_audmux>;
+       status = "okay";
+
+       ssi2 {
+               fsl,audmux-port = <1>;
+               fsl,port-config = <
+                       (IMX_AUDMUX_V2_PTCR_RCLKDIR |
+                       IMX_AUDMUX_V2_PTCR_RCSEL(3 | 0x8) |
+                       IMX_AUDMUX_V2_PTCR_TCLKDIR |
+                       IMX_AUDMUX_V2_PTCR_TCSEL(3))
+                       IMX_AUDMUX_V2_PDCR_RXDSEL(3)
+               >;
+       };
+
+       audmux4 {
+               fsl,audmux-port = <3>;
+               fsl,port-config = <
+                       (IMX_AUDMUX_V2_PTCR_TFSDIR |
+                       IMX_AUDMUX_V2_PTCR_TFSEL(1) |
+                       IMX_AUDMUX_V2_PTCR_RCLKDIR |
+                       IMX_AUDMUX_V2_PTCR_RCSEL(1 | 0x8) |
+                       IMX_AUDMUX_V2_PTCR_TCLKDIR |
+                       IMX_AUDMUX_V2_PTCR_TCSEL(1))
+                       IMX_AUDMUX_V2_PDCR_RXDSEL(1)
+               >;
+       };
+};
+
 &cpu0 {
        /*
         * Although the imx6q fuse indicates that 1.2GHz operation is possible,
                reg = <0x50>;
                pagesize = <16>;
        };
+
+       wm8731: codec@1a {
+               #sound-dai-cells = <0>;
+               compatible = "wlf,wm8731";
+               reg = <0x1a>;
+       };
 };
 
 &iomuxc {
+       pinctrl_audmux: audmuxgrp {
+               fsl,pins = <
+                       MX6QDL_PAD_SD2_CMD__AUD4_RXC   0x17059
+                       MX6QDL_PAD_SD2_DAT0__AUD4_RXD  0x17059
+                       MX6QDL_PAD_SD2_DAT3__AUD4_TXC  0x17059
+                       MX6QDL_PAD_SD2_DAT2__AUD4_TXD  0x17059
+                       MX6QDL_PAD_SD2_DAT1__AUD4_TXFS 0x17059
+               >;
+       };
+
        pinctrl_ecspi1: ecspi1grp {
                fsl,pins = <
                        MX6QDL_PAD_EIM_D16__ECSPI1_SCLK 0x100b1
        status = "okay";
 };
 
+&ssi2 {
+       assigned-clocks = <&clks IMX6QDL_CLK_SSI2_SEL>,
+                       <&clks IMX6QDL_CLK_PLL4_AUDIO_DIV>;
+       assigned-clock-parents = <&clks IMX6QDL_CLK_PLL4_AUDIO_DIV>;
+       assigned-clock-rates = <0>, <786432000>;
+       status = "okay";
+};
+
 &uart4 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_uart4>;
diff --git a/arch/arm/boot/dts/imx6q-gw5903.dts b/arch/arm/boot/dts/imx6q-gw5903.dts
new file mode 100644 (file)
index 0000000..a182e4c
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2017 Gateworks Corporation
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this file; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-gw5903.dtsi"
+
+/ {
+       model = "Gateworks Ventana i.MX6 Dual/Quad GW5903";
+       compatible = "gw,imx6q-gw5903", "gw,ventana", "fsl,imx6q";
+};
diff --git a/arch/arm/boot/dts/imx6q-gw5904.dts b/arch/arm/boot/dts/imx6q-gw5904.dts
new file mode 100644 (file)
index 0000000..ca1e2ae
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2017 Gateworks Corporation
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this file; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "imx6q.dtsi"
+#include "imx6qdl-gw5904.dtsi"
+
+/ {
+       model = "Gateworks Ventana i.MX6 Dual/Quad GW5904";
+       compatible = "gw,imx6q-gw5904", "gw,ventana", "fsl,imx6q";
+};
+
+&sata {
+       status = "okay";
+};
diff --git a/arch/arm/boot/dts/imx6q-icore-ofcap10.dts b/arch/arm/boot/dts/imx6q-icore-ofcap10.dts
new file mode 100644 (file)
index 0000000..49b60ca
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2016 Amarula Solutions B.V.
+ * Copyright (C) 2016 Engicam S.r.l.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include "imx6q.dtsi"
+#include "imx6qdl-icore.dtsi"
+
+/ {
+       model = "Engicam i.CoreM6 Quad/Dual OpenFrame Capacitive touch 10.1 Kit";
+       compatible = "engicam,imx6-icore", "fsl,imx6q";
+};
+
+&ldb {
+       status = "okay";
+
+       lvds-channel@0 {
+               fsl,data-mapping = "spwg";
+               fsl,data-width = <24>;
+               status = "okay";
+
+               display-timings {
+                       native-mode = <&timing0>;
+                       timing0: timing0 {
+                               clock-frequency = <60000000>;
+                               hactive = <1280>;
+                               vactive = <800>;
+                               hback-porch = <40>;
+                               hfront-porch = <40>;
+                               vback-porch = <10>;
+                               vfront-porch = <3>;
+                               hsync-len = <80>;
+                               vsync-len = <10>;
+                       };
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/imx6q-icore-ofcap12.dts b/arch/arm/boot/dts/imx6q-icore-ofcap12.dts
new file mode 100644 (file)
index 0000000..9e230f5
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2016 Amarula Solutions B.V.
+ * Copyright (C) 2016 Engicam S.r.l.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include "imx6q.dtsi"
+#include "imx6qdl-icore.dtsi"
+
+/ {
+       model = "Engicam i.CoreM6 Quad/Dual OpenFrame Capacitive touch 12 Kit";
+       compatible = "engicam,imx6-icore", "fsl,imx6q";
+};
+
+&ldb {
+       status = "okay";
+
+       lvds-channel@0 {
+               fsl,data-mapping = "spwg";
+               fsl,data-width = <18>;
+               status = "okay";
+
+               display-timings {
+                       native-mode = <&timing0>;
+                       timing0: timing0 {
+                               clock-frequency = <46800000>;
+                               hactive = <1280>;
+                               vactive = <480>;
+                               hback-porch = <353>;
+                               hfront-porch = <47>;
+                               vback-porch = <39>;
+                               vfront-porch = <4>;
+                               hsync-len = <8>;
+                               vsync-len = <2>;
+                       };
+               };
+       };
+};
index 59eb7adc24729e1d8b181375fb1beb508cbd3337..5613dd9dc4693a6638475018b1017ad0bf3cfe38 100644 (file)
 &can2 {
        status = "okay";
 };
+
+&i2c1 {
+       max11801: touchscreen@48 {
+               compatible = "maxim,max11801";
+               reg = <0x48>;
+               interrupt-parent = <&gpio3>;
+               interrupts = <31 IRQ_TYPE_EDGE_FALLING>;
+       };
+};
+
+&ldb {
+       status = "okay";
+
+       lvds-channel@0 {
+               fsl,data-mapping = "spwg";
+               fsl,data-width = <18>;
+               status = "okay";
+
+               display-timings {
+                       native-mode = <&timing0>;
+                       timing0: timing0 {
+                               clock-frequency = <60000000>;
+                               hactive = <800>;
+                               vactive = <480>;
+                               hback-porch = <30>;
+                               hfront-porch = <30>;
+                               vback-porch = <5>;
+                               vfront-porch = <5>;
+                               hsync-len = <64>;
+                               vsync-len = <20>;
+                       };
+               };
+       };
+};
index 69bdd82ce21fc732259aee42a1c80e01025ee1ff..d900ad6ec5f826ff7a2f960d1b66ba1144e40d78 100644 (file)
 
        hdmi-connector {
                compatible = "hdmi-connector";
-
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_hpd>;
                type = "a";
                ddc-i2c-bus = <&i2c_dvi_ddc>;
+               hpd-gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>;
 
                port {
                        hdmi_connector_in: endpoint {
                >;
        };
 
+       pinctrl_hpd: hpdgrp {
+               fsl,pins = <
+                       MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1b0b0
+               >;
+       };
+
        pinctrl_i2c1: i2c1grp {
                fsl,pins = <
                        MX6QDL_PAD_EIM_D21__I2C1_SCL 0x4001b8b1
diff --git a/arch/arm/boot/dts/imx6q-zii-rdu2.dts b/arch/arm/boot/dts/imx6q-zii-rdu2.dts
new file mode 100644 (file)
index 0000000..b2d3466
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016-2017 Zodiac Inflight Innovations
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include <imx6q.dtsi>
+#include <imx6qdl-zii-rdu2.dtsi>
+
+/ {
+       model = "ZII RDU2 Board";
+       compatible = "zii,imx6q-zii-rdu2", "fsl,imx6q";
+};
diff --git a/arch/arm/boot/dts/imx6qdl-gw5903.dtsi b/arch/arm/boot/dts/imx6qdl-gw5903.dtsi
new file mode 100644 (file)
index 0000000..4444251
--- /dev/null
@@ -0,0 +1,654 @@
+/*
+ * Copyright 2017 Gateworks Corporation
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this file; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+       chosen {
+               stdout-path = &uart2;
+       };
+
+       backlight {
+               compatible = "pwm-backlight";
+               pwms = <&pwm1 0 5000000>;
+               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
+                       >;
+               default-brightness-level = <100>;
+       };
+
+       leds {
+               compatible = "gpio-leds";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_gpio_leds>;
+
+               led0: user1 {
+                       label = "user1";
+                       gpios = <&gpio6 14 GPIO_ACTIVE_LOW>; /* MX6_LOCLED# */
+                       default-state = "off";
+               };
+       };
+
+       memory {
+               reg = <0x10000000 0x40000000>;
+       };
+
+       reg_5p0v: regulator-5p0v {
+               compatible = "regulator-fixed";
+               regulator-name = "5P0V";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-always-on;
+       };
+
+       reg_3p3v: regulator-3p3v {
+               compatible = "regulator-fixed";
+               regulator-name = "3P3V";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-always-on;
+       };
+
+       reg_2p5v: regulator-2p5v {
+               compatible = "regulator-fixed";
+               regulator-name = "2P5V";
+               regulator-min-microvolt = <2500000>;
+               regulator-max-microvolt = <2500000>;
+               regulator-always-on;
+       };
+
+       reg_usb_h1_vbus: regulator-usb-h1-vbus {
+               compatible = "regulator-fixed";
+               regulator-name = "usb_h1_vbus";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               gpio = <&gpio3 30 0>;
+               enable-active-high;
+       };
+
+       reg_usb_otg_vbus: regulator-usb-otg-vbus {
+               compatible = "regulator-fixed";
+               regulator-name = "usb_otg_vbus";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               gpio = <&gpio4 15 GPIO_ACTIVE_HIGH>;
+               enable-active-high;
+       };
+
+       reg_12p0: regulator-12p0v {
+               compatible = "regulator-fixed";
+               regulator-name = "12P0V";
+               regulator-min-microvolt = <12000000>;
+               regulator-max-microvolt = <12000000>;
+               gpio = <&gpio1 7 GPIO_ACTIVE_HIGH>;
+               enable-active-high;
+       };
+
+       sound {
+               compatible = "fsl,imx-audio-tlv320";
+               model = "imx-tlv320";
+               ssi-controller = <&ssi1>;
+               audio-codec = <&tlv320aic3105>;
+               /* routing of sink, source */
+               audio-routing =
+                       /* TLV320 LINE1L pin <-> Mic Jack connector */
+                       "LINE1L", "Mic Jack",
+                       /* board Headphone Jack <-> HPOUT */
+                       "Headphone Jack", "HPLOUT",
+                       "Headphone Jack", "HPROUT",
+                       "Mic Jack", "Mic Bias";
+               mux-int-port = <1>;
+               mux-ext-port = <6>;
+       };
+};
+
+&audmux {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_audmux>;
+       status = "okay";
+};
+
+&clks {
+       assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>,
+                         <&clks IMX6QDL_CLK_LDB_DI1_SEL>;
+       assigned-clock-parents = <&clks IMX6QDL_CLK_PLL3_USB_OTG>,
+                                <&clks IMX6QDL_CLK_PLL3_USB_OTG>;
+};
+
+&fec {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_enet>;
+       phy-mode = "rgmii-id";
+       status = "okay";
+};
+
+&i2c1 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c1>;
+       status = "okay";
+
+       pca9555: gpio@23 {
+               compatible = "nxp,pca9555";
+               reg = <0x23>;
+               gpio-controller;
+               #gpio-cells = <2>;
+       };
+
+       eeprom1: eeprom@50 {
+               compatible = "atmel,24c02";
+               reg = <0x50>;
+               pagesize = <16>;
+       };
+
+       eeprom2: eeprom@51 {
+               compatible = "atmel,24c02";
+               reg = <0x51>;
+               pagesize = <16>;
+       };
+
+       eeprom3: eeprom@52 {
+               compatible = "atmel,24c02";
+               reg = <0x52>;
+               pagesize = <16>;
+       };
+
+       eeprom4: eeprom@53 {
+               compatible = "atmel,24c02";
+               reg = <0x53>;
+               pagesize = <16>;
+       };
+
+       dts1672: rtc@68 {
+               compatible = "dallas,ds1672";
+               reg = <0x68>;
+       };
+};
+
+&i2c2 {
+       clock-frequency = <400000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c2>;
+       status = "okay";
+
+       ltc3676: pmic@3c {
+               compatible = "lltc,ltc3676";
+               reg = <0x3c>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <8 IRQ_TYPE_EDGE_FALLING>;
+
+               regulators {
+                       /* VDD_1P8 (1+R1/R2 = 2.505): Aud/eMMC/microSD/Touch */
+                       reg_1p8v: sw1 {
+                               regulator-name = "vdd1p8";
+                               regulator-min-microvolt = <1033310>;
+                               regulator-max-microvolt = <2004000>;
+                               lltc,fb-voltage-divider = <301000 200000>;
+                               regulator-ramp-delay = <7000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       /* VDD_DDR (1+R1/R2 = 2.105) */
+                       reg_vdd_ddr: sw2 {
+                               regulator-name = "vddddr";
+                               regulator-min-microvolt = <868310>;
+                               regulator-max-microvolt = <1684000>;
+                               lltc,fb-voltage-divider = <221000 200000>;
+                               regulator-ramp-delay = <7000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       /* VDD_ARM (1+R1/R2 = 1.635) */
+                       reg_vdd_arm: sw3 {
+                               regulator-name = "vddarm";
+                               regulator-min-microvolt = <674400>;
+                               regulator-max-microvolt = <1308000>;
+                               lltc,fb-voltage-divider = <127000 200000>;
+                               regulator-ramp-delay = <7000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                               linux,phandle = <&reg_vdd_arm>;
+                       };
+
+                       /* VDD_SOC (1+R1/R2 = 1.635) */
+                       reg_vdd_soc: sw4 {
+                               regulator-name = "vddsoc";
+                               regulator-min-microvolt = <674400>;
+                               regulator-max-microvolt = <1308000>;
+                               lltc,fb-voltage-divider = <127000 200000>;
+                               regulator-ramp-delay = <7000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                               linux,phandle = <&reg_vdd_soc>;
+                       };
+
+                       /* VDD_1P0 (1+R1/R2 = 1.38): */
+                       reg_1p0v: ldo2 {
+                               regulator-name = "vdd1p0";
+                               regulator-min-microvolt = <1002777>;
+                               regulator-max-microvolt = <1002777>;
+                               lltc,fb-voltage-divider = <100000 261000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       /* VDD_HIGH (1+R1/R2 = 4.17) */
+                       reg_3p0v: ldo4 {
+                               regulator-name = "vdd3p0";
+                               regulator-min-microvolt = <3023250>;
+                               regulator-max-microvolt = <3023250>;
+                               lltc,fb-voltage-divider = <634000 200000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+               };
+       };
+};
+
+&i2c3 {
+       clock-frequency = <400000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c3>;
+       status = "okay";
+
+       tlv320aic3105: codec@18 {
+               compatible = "ti,tlv320aic3x";
+               reg = <0x18>;
+               gpio-reset = <&gpio5 17 GPIO_ACTIVE_LOW>;
+               clocks = <&clks IMX6QDL_CLK_CKO>;
+               ai3x-micbias-vg = <2>; /* MICBIAS_2_5V */
+               /* Regulators */
+               DRVDD-supply = <&reg_3p3v>;
+               AVDD-supply = <&reg_3p3v>;
+               IOVDD-supply = <&reg_3p3v>;
+               DVDD-supply = <&reg_1p8v>;
+       };
+
+       accelerometer@1d {
+               compatible = "fsl,mma8451";
+               reg = <0x1d>;
+               interrupt-parent = <&gpio7>;
+               interrupts = <11 IRQ_TYPE_EDGE_RISING>;
+               interrupt-names = "INT2";
+       };
+
+       /* headphone detect */
+       ts3a227e@3b {
+               compatible = "ti,ts3a227e";
+               reg = <0x3b>;
+               interrupt-parent = <&gpio5>;
+               interrupts = <15 IRQ_TYPE_LEVEL_LOW>;
+               ti,micbias = <4>; /* 2.5V micbias */
+       };
+};
+
+&ldb {
+       status = "okay";
+
+       lvds-channel@0 {
+               fsl,data-mapping = "spwg";
+               fsl,data-width = <18>;
+               status = "okay";
+
+               display-timings {
+                       native-mode = <&timing0>;
+                       timing0: g101evn010 {
+                               clock-frequency = <68930000>;
+                               hactive = <1280>;
+                               vactive = <800>;
+                               hback-porch = <220>;
+                               hfront-porch = <40>;
+                               vback-porch = <21>;
+                               vfront-porch = <7>;
+                               hsync-len = <60>;
+                               vsync-len = <10>;
+                       };
+               };
+       };
+};
+
+&pwm1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_pwm1>;
+       status = "okay";
+};
+
+&ssi1 {
+       status = "okay";
+};
+
+&uart1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart1>;
+       status = "okay";
+};
+
+&uart2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart2>;
+       status = "okay";
+};
+
+&usbotg {
+       vbus-supply = <&reg_usb_otg_vbus>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usbotg>;
+       disable-over-current;
+       status = "okay";
+};
+
+&usbh1 {
+       vbus-supply = <&reg_usb_h1_vbus>;
+       status = "okay";
+};
+
+&usdhc1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usdhc1_200mhz>;
+       vmmc-supply = <&reg_3p3v>;
+       non-removable;
+       bus-width = <4>;
+       status = "okay";
+};
+
+&usdhc2 {
+       pinctrl-names = "default", "state_100mhz", "state_200mhz";
+       pinctrl-0 = <&pinctrl_usdhc2>;
+       pinctrl-1 = <&pinctrl_usdhc2_100mhz>;
+       pinctrl-2 = <&pinctrl_usdhc2_200mhz>;
+       cd-gpios = <&gpio6 11 GPIO_ACTIVE_LOW>;
+       vmmc-supply = <&reg_3p3v>;
+       max-frequency = <100000000>;
+       status = "okay";
+};
+
+&usdhc3 {
+       pinctrl-names = "default", "state_100mhz", "state_200mhz";
+       pinctrl-0 = <&pinctrl_usdhc3>;
+       pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+       pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
+       non-removable;
+       vmmc-supply = <&reg_3p3v>;
+       keep-power-in-suspend;
+       status = "okay";
+};
+
+&wdog1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_wdog>;
+       fsl,ext-reset-output;
+};
+
+&iomuxc {
+       pinctrl_audmux: audmuxgrp {
+               fsl,pins = <
+                       MX6QDL_PAD_DI0_PIN2__AUD6_TXD           0x130b0
+                       MX6QDL_PAD_DI0_PIN3__AUD6_TXFS          0x130b0
+                       MX6QDL_PAD_DI0_PIN4__AUD6_RXD           0x130b0
+                       MX6QDL_PAD_DI0_PIN15__AUD6_TXC          0x130b0
+                       MX6QDL_PAD_GPIO_0__CCM_CLKO1            0x130b0 /* MCK */
+               >;
+       };
+
+       pinctrl_enet: enetgrp {
+               fsl,pins = <
+                       MX6QDL_PAD_RGMII_RXC__RGMII_RXC         0x1b030
+                       MX6QDL_PAD_RGMII_RD0__RGMII_RD0         0x1b030
+                       MX6QDL_PAD_RGMII_RD1__RGMII_RD1         0x1b030
+                       MX6QDL_PAD_RGMII_RD2__RGMII_RD2         0x1b030
+                       MX6QDL_PAD_RGMII_RD3__RGMII_RD3         0x1b030
+                       MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL   0x1b030
+                       MX6QDL_PAD_RGMII_TXC__RGMII_TXC         0x1b030
+                       MX6QDL_PAD_RGMII_TD0__RGMII_TD0         0x1b030
+                       MX6QDL_PAD_RGMII_TD1__RGMII_TD1         0x1b030
+                       MX6QDL_PAD_RGMII_TD2__RGMII_TD2         0x1b030
+                       MX6QDL_PAD_RGMII_TD3__RGMII_TD3         0x1b030
+                       MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL   0x1b030
+                       MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK    0x1b0b0
+                       MX6QDL_PAD_ENET_MDIO__ENET_MDIO         0x1b0b0
+                       MX6QDL_PAD_ENET_MDC__ENET_MDC           0x1b0b0
+                       MX6QDL_PAD_ENET_TXD0__GPIO1_IO30        0x4001b0b0 /* PHY_RST# */
+                       MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25      0x4001b0b0 /* PHY_EN */
+               >;
+       };
+
+       pinctrl_gpio_leds: gpioledsgrp {
+               fsl,pins = <
+                       MX6QDL_PAD_NANDF_CS1__GPIO6_IO14        0x1b0b0
+               >;
+       };
+
+       pinctrl_i2c1: i2c1grp {
+               fsl,pins = <
+                       MX6QDL_PAD_EIM_D21__I2C1_SCL            0x4001b8b1
+                       MX6QDL_PAD_EIM_D28__I2C1_SDA            0x4001b8b1
+                       MX6QDL_PAD_GPIO_4__GPIO1_IO04           0x0001b0b0 /* GSC_IRQ# */
+               >;
+       };
+
+       pinctrl_i2c2: i2c2grp {
+               fsl,pins = <
+                       MX6QDL_PAD_KEY_COL3__I2C2_SCL           0x4001b8b1
+                       MX6QDL_PAD_KEY_ROW3__I2C2_SDA           0x4001b8b1
+                       MX6QDL_PAD_GPIO_8__GPIO1_IO08           0x0001b0b0 /* PMIC_IRQ# */
+               >;
+       };
+
+       pinctrl_i2c3: i2c3grp {
+               fsl,pins = <
+                       /* I2C3 */
+                       MX6QDL_PAD_GPIO_3__I2C3_SCL             0x4001b8b1
+                       MX6QDL_PAD_GPIO_6__I2C3_SDA             0x4001b8b1
+
+                       /* Headphone Detect */
+                       MX6QDL_PAD_DISP0_DAT21__GPIO5_IO15      0x0001b0b0 /* HPDET_IRQ# */
+                       MX6QDL_PAD_DISP0_DAT22__GPIO5_IO16      0x0001b0b0 /* HPDET_MIC# */
+
+                       /* Codec */
+                       MX6QDL_PAD_DISP0_DAT23__GPIO5_IO17      0x0001b0b0 /* CODEC_RST# */
+
+                       /* Touch Controller */
+                       MX6QDL_PAD_KEY_COL0__GPIO4_IO06         0x0001b0b0 /* TOUCH_IRQ# */
+                       MX6QDL_PAD_KEY_COL1__GPIO4_IO08         0x0001b0b0 /* TOUCH_RST */
+
+                       /* Stow Sensor */
+                       MX6QDL_PAD_GPIO_16__GPIO7_IO11          0x0001b0b0 /* ACCEL_IRQ2 */
+                       MX6QDL_PAD_GPIO_18__GPIO7_IO13          0x0001b0b0 /* ACCEL_IRQ1 */
+               >;
+       };
+
+       pinctrl_pwm1: pwm1grp {
+               fsl,pins = <
+                       MX6QDL_PAD_GPIO_9__PWM1_OUT             0x1b0b1
+               >;
+       };
+
+       pinctrl_uart1: uart1grp {
+               fsl,pins = <
+                       MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA    0x1b0b1
+                       MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA    0x1b0b1
+                       MX6QDL_PAD_CSI0_DAT12__GPIO5_IO30       0x1b0b1 /* TXEN */
+               >;
+       };
+
+       pinctrl_uart2: uart2grp {
+               fsl,pins = <
+                       MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA      0x1b0b1
+                       MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA      0x1b0b1
+               >;
+       };
+
+       pinctrl_usbotg: usbotggrp {
+               fsl,pins = <
+                       MX6QDL_PAD_GPIO_1__USB_OTG_ID           0x13059
+                       MX6QDL_PAD_KEY_ROW4__GPIO4_IO15         0x4001b0b0 /* PWR_EN */
+                       MX6QDL_PAD_KEY_COL4__GPIO4_IO14         0x1b0b0 /* OC */
+               >;
+       };
+
+       pinctrl_usdhc1_200mhz: usdhc1grp200mhz {
+               fsl,pins = <
+                       MX6QDL_PAD_NANDF_D3__GPIO2_IO03         0x4001b0b0 /* EMMY_EN */
+                       MX6QDL_PAD_NANDF_D4__GPIO2_IO04         0x4001b0b0 /* EMMY_CFG1# */
+                       MX6QDL_PAD_NANDF_D5__GPIO2_IO05         0x4001b0b0 /* EMMY_CFG2# */
+                       MX6QDL_PAD_NANDF_D6__GPIO2_IO06         0x0001b0b0 /* EMMY_BTWAKE# */
+                       MX6QDL_PAD_NANDF_D7__GPIO2_IO07         0x0001b0b0 /* EMMY_WFWAKE# */
+
+                       MX6QDL_PAD_SD1_CLK__SD1_CLK             0x100f9
+                       MX6QDL_PAD_SD1_CMD__SD1_CMD             0x100f9
+                       MX6QDL_PAD_SD1_DAT0__SD1_DATA0          0x170f9
+                       MX6QDL_PAD_SD1_DAT1__SD1_DATA1          0x170f9
+                       MX6QDL_PAD_SD1_DAT2__SD1_DATA2          0x170f9
+                       MX6QDL_PAD_SD1_DAT3__SD1_DATA3          0x170f9
+               >;
+       };
+
+       pinctrl_usdhc2: usdhc2grp {
+               fsl,pins = <
+                       MX6QDL_PAD_SD2_CMD__SD2_CMD             0x17059
+                       MX6QDL_PAD_SD2_CLK__SD2_CLK             0x10059
+                       MX6QDL_PAD_SD2_DAT0__SD2_DATA0          0x17059
+                       MX6QDL_PAD_SD2_DAT1__SD2_DATA1          0x17059
+                       MX6QDL_PAD_SD2_DAT2__SD2_DATA2          0x17059
+                       MX6QDL_PAD_SD2_DAT3__SD2_DATA3          0x17059
+                       MX6QDL_PAD_NANDF_CS0__GPIO6_IO11        0x17059 /* CD */
+                       MX6QDL_PAD_KEY_ROW1__SD2_VSELECT        0x17059
+               >;
+       };
+
+       pinctrl_usdhc2_100mhz: usdhc2grp100mhz {
+               fsl,pins = <
+                       MX6QDL_PAD_SD2_CMD__SD2_CMD             0x170b9
+                       MX6QDL_PAD_SD2_CLK__SD2_CLK             0x100b9
+                       MX6QDL_PAD_SD2_DAT0__SD2_DATA0          0x170b9
+                       MX6QDL_PAD_SD2_DAT1__SD2_DATA1          0x170b9
+                       MX6QDL_PAD_SD2_DAT2__SD2_DATA2          0x170b9
+                       MX6QDL_PAD_SD2_DAT3__SD2_DATA3          0x170b9
+                       MX6QDL_PAD_NANDF_CS0__GPIO6_IO11        0x170b9 /* CD */
+                       MX6QDL_PAD_KEY_ROW1__SD2_VSELECT        0x170b9
+               >;
+       };
+
+       pinctrl_usdhc2_200mhz: usdhc2grp200mhz {
+               fsl,pins = <
+                       MX6QDL_PAD_SD2_CMD__SD2_CMD             0x170f9
+                       MX6QDL_PAD_SD2_CLK__SD2_CLK             0x100f9
+                       MX6QDL_PAD_SD2_DAT0__SD2_DATA0          0x170f9
+                       MX6QDL_PAD_SD2_DAT1__SD2_DATA1          0x170f9
+                       MX6QDL_PAD_SD2_DAT2__SD2_DATA2          0x170f9
+                       MX6QDL_PAD_SD2_DAT3__SD2_DATA3          0x170f9
+                       MX6QDL_PAD_NANDF_CS0__GPIO6_IO11        0x170f9 /* CD */
+                       MX6QDL_PAD_KEY_ROW1__SD2_VSELECT        0x170f9
+               >;
+       };
+
+       pinctrl_usdhc3: usdhc3grp {
+               fsl,pins = <
+                       MX6QDL_PAD_SD3_CMD__SD3_CMD             0x17059
+                       MX6QDL_PAD_SD3_CLK__SD3_CLK             0x10059
+                       MX6QDL_PAD_SD3_RST__SD3_RESET           0x10059
+                       MX6QDL_PAD_SD3_DAT0__SD3_DATA0          0x17059
+                       MX6QDL_PAD_SD3_DAT1__SD3_DATA1          0x17059
+                       MX6QDL_PAD_SD3_DAT2__SD3_DATA2          0x17059
+                       MX6QDL_PAD_SD3_DAT3__SD3_DATA3          0x17059
+                       MX6QDL_PAD_SD3_DAT4__SD3_DATA4          0x17059
+                       MX6QDL_PAD_SD3_DAT5__SD3_DATA5          0x17059
+                       MX6QDL_PAD_SD3_DAT6__SD3_DATA6          0x17059
+                       MX6QDL_PAD_SD3_DAT7__SD3_DATA7          0x17059
+               >;
+       };
+
+       pinctrl_usdhc3_100mhz: usdhc3grp100mhz {
+               fsl,pins = <
+                       MX6QDL_PAD_SD3_CMD__SD3_CMD             0x170b9
+                       MX6QDL_PAD_SD3_CLK__SD3_CLK             0x100b9
+                       MX6QDL_PAD_SD3_RST__SD3_RESET           0x100b9
+                       MX6QDL_PAD_SD3_DAT0__SD3_DATA0          0x170b9
+                       MX6QDL_PAD_SD3_DAT1__SD3_DATA1          0x170b9
+                       MX6QDL_PAD_SD3_DAT2__SD3_DATA2          0x170b9
+                       MX6QDL_PAD_SD3_DAT3__SD3_DATA3          0x170b9
+                       MX6QDL_PAD_SD3_DAT4__SD3_DATA4          0x170b9
+                       MX6QDL_PAD_SD3_DAT5__SD3_DATA5          0x170b9
+                       MX6QDL_PAD_SD3_DAT6__SD3_DATA6          0x170b9
+                       MX6QDL_PAD_SD3_DAT7__SD3_DATA7          0x170b9
+               >;
+       };
+
+       pinctrl_usdhc3_200mhz: usdhc3grp200mhz {
+               fsl,pins = <
+                       MX6QDL_PAD_SD3_CMD__SD3_CMD             0x170f9
+                       MX6QDL_PAD_SD3_CLK__SD3_CLK             0x100f9
+                       MX6QDL_PAD_SD3_RST__SD3_RESET           0x100f9
+                       MX6QDL_PAD_SD3_DAT0__SD3_DATA0          0x170f9
+                       MX6QDL_PAD_SD3_DAT1__SD3_DATA1          0x170f9
+                       MX6QDL_PAD_SD3_DAT2__SD3_DATA2          0x170f9
+                       MX6QDL_PAD_SD3_DAT3__SD3_DATA3          0x170f9
+                       MX6QDL_PAD_SD3_DAT4__SD3_DATA4          0x170f9
+                       MX6QDL_PAD_SD3_DAT5__SD3_DATA5          0x170f9
+                       MX6QDL_PAD_SD3_DAT6__SD3_DATA6          0x170f9
+                       MX6QDL_PAD_SD3_DAT7__SD3_DATA7          0x170f9
+               >;
+       };
+
+       pinctrl_wdog: wdoggrp {
+               fsl,pins = <
+                       MX6QDL_PAD_DISP0_DAT8__WDOG1_B          0x1b0b0
+               >;
+       };
+};
diff --git a/arch/arm/boot/dts/imx6qdl-gw5904.dtsi b/arch/arm/boot/dts/imx6qdl-gw5904.dtsi
new file mode 100644 (file)
index 0000000..fd4b68b
--- /dev/null
@@ -0,0 +1,641 @@
+/*
+ * Copyright 2017 Gateworks Corporation
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of
+ *     the License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *     You should have received a copy of the GNU General Public
+ *     License along with this file; if not, write to the Free
+ *     Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ *     MA 02110-1301 USA
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+       /* these are used by bootloader for disabling nodes */
+       aliases {
+               led0 = &led0;
+               led1 = &led1;
+               led2 = &led2;
+               usb0 = &usbh1;
+               usb1 = &usbotg;
+       };
+
+       chosen {
+               stdout-path = &uart2;
+       };
+
+       backlight {
+               compatible = "pwm-backlight";
+               pwms = <&pwm4 0 5000000>;
+               brightness-levels = <0 4 8 16 32 64 128 255>;
+               default-brightness-level = <7>;
+       };
+
+       leds {
+               compatible = "gpio-leds";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_gpio_leds>;
+
+               led0: user1 {
+                       label = "user1";
+                       gpios = <&gpio4 6 GPIO_ACTIVE_HIGH>; /* MX6_PANLEDG */
+                       default-state = "on";
+                       linux,default-trigger = "heartbeat";
+               };
+
+               led1: user2 {
+                       label = "user2";
+                       gpios = <&gpio4 7 GPIO_ACTIVE_HIGH>; /* MX6_PANLEDR */
+                       default-state = "off";
+               };
+
+               led2: user3 {
+                       label = "user3";
+                       gpios = <&gpio4 15 GPIO_ACTIVE_LOW>; /* MX6_LOCLED# */
+                       default-state = "off";
+               };
+       };
+
+       memory {
+               reg = <0x10000000 0x40000000>;
+       };
+
+       pps {
+               compatible = "pps-gpio";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_pps>;
+               gpios = <&gpio1 26 GPIO_ACTIVE_HIGH>;
+       };
+
+       reg_1p0v: regulator-1p0v {
+               compatible = "regulator-fixed";
+               regulator-name = "1P0V";
+               regulator-min-microvolt = <1000000>;
+               regulator-max-microvolt = <1000000>;
+               regulator-always-on;
+       };
+
+       reg_3p3v: regulator-3p3v {
+               compatible = "regulator-fixed";
+               regulator-name = "3P3V";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-always-on;
+       };
+
+       reg_usb_h1_vbus: regulator-usb-h1-vbus {
+               compatible = "regulator-fixed";
+               regulator-name = "usb_h1_vbus";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-always-on;
+       };
+
+       reg_usb_otg_vbus: regulator-usb-otg-vbus {
+               compatible = "regulator-fixed";
+               regulator-name = "usb_otg_vbus";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               gpio = <&gpio3 22 GPIO_ACTIVE_HIGH>;
+               enable-active-high;
+       };
+};
+
+&clks {
+       assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>,
+                         <&clks IMX6QDL_CLK_LDB_DI1_SEL>;
+       assigned-clock-parents = <&clks IMX6QDL_CLK_PLL3_USB_OTG>,
+                                <&clks IMX6QDL_CLK_PLL3_USB_OTG>;
+};
+
+&fec {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_enet>;
+       phy-mode = "rgmii-id";
+       status = "okay";
+
+       fixed-link {
+               speed = <1000>;
+               full-duplex;
+       };
+
+       mdio {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               switch@0 {
+                       compatible = "marvell,mv88e6085";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0>;
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               port@0 {
+                                       reg = <0>;
+                                       label = "lan4";
+                               };
+
+                               port@1 {
+                                       reg = <1>;
+                                       label = "lan3";
+                               };
+
+                               port@2 {
+                                       reg = <2>;
+                                       label = "lan2";
+                               };
+
+                               port@3 {
+                                       reg = <3>;
+                                       label = "lan1";
+                               };
+
+                               port@5 {
+                                       reg = <5>;
+                                       label = "cpu";
+                                       ethernet = <&fec>;
+                               };
+                       };
+               };
+       };
+};
+
+&i2c1 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c1>;
+       status = "okay";
+
+       pca9555: gpio@23 {
+               compatible = "nxp,pca9555";
+               reg = <0x23>;
+               gpio-controller;
+               #gpio-cells = <2>;
+       };
+
+       eeprom1: eeprom@50 {
+               compatible = "atmel,24c02";
+               reg = <0x50>;
+               pagesize = <16>;
+       };
+
+       eeprom2: eeprom@51 {
+               compatible = "atmel,24c02";
+               reg = <0x51>;
+               pagesize = <16>;
+       };
+
+       eeprom3: eeprom@52 {
+               compatible = "atmel,24c02";
+               reg = <0x52>;
+               pagesize = <16>;
+       };
+
+       eeprom4: eeprom@53 {
+               compatible = "atmel,24c02";
+               reg = <0x53>;
+               pagesize = <16>;
+       };
+
+       dts1672: rtc@68 {
+               compatible = "dallas,ds1672";
+               reg = <0x68>;
+       };
+};
+
+&i2c2 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c2>;
+       status = "okay";
+
+       ltc3676: pmic@3c {
+               compatible = "lltc,ltc3676";
+               reg = <0x3c>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <8 IRQ_TYPE_EDGE_FALLING>;
+
+               regulators {
+                       /* VDD_SOC (1+R1/R2 = 1.635) */
+                       reg_vdd_soc: sw1 {
+                               regulator-name = "vddsoc";
+                               regulator-min-microvolt = <674400>;
+                               regulator-max-microvolt = <1308000>;
+                               lltc,fb-voltage-divider = <127000 200000>;
+                               regulator-ramp-delay = <7000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       /* VDD_1P8 (1+R1/R2 = 2.505): GbE switch */
+                       reg_1p8v: sw2 {
+                               regulator-name = "vdd1p8";
+                               regulator-min-microvolt = <1033310>;
+                               regulator-max-microvolt = <2004000>;
+                               lltc,fb-voltage-divider = <301000 200000>;
+                               regulator-ramp-delay = <7000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       /* VDD_ARM (1+R1/R2 = 1.635) */
+                       reg_vdd_arm: sw3 {
+                               regulator-name = "vddarm";
+                               regulator-min-microvolt = <674400>;
+                               regulator-max-microvolt = <1308000>;
+                               lltc,fb-voltage-divider = <127000 200000>;
+                               regulator-ramp-delay = <7000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       /* VDD_DDR (1+R1/R2 = 2.105) */
+                       reg_vdd_ddr: sw4 {
+                               regulator-name = "vddddr";
+                               regulator-min-microvolt = <868310>;
+                               regulator-max-microvolt = <1684000>;
+                               lltc,fb-voltage-divider = <221000 200000>;
+                               regulator-ramp-delay = <7000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       /* VDD_2P5 (1+R1/R2 = 3.435): PCIe/ENET-PHY */
+                       reg_2p5v: ldo2 {
+                               regulator-name = "vdd2p5";
+                               regulator-min-microvolt = <2490375>;
+                               regulator-max-microvolt = <2490375>;
+                               lltc,fb-voltage-divider = <487000 200000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       /* VDD_HIGH (1+R1/R2 = 4.17) */
+                       reg_3p0v: ldo4 {
+                               regulator-name = "vdd3p0";
+                               regulator-min-microvolt = <3023250>;
+                               regulator-max-microvolt = <3023250>;
+                               lltc,fb-voltage-divider = <634000 200000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+               };
+       };
+};
+
+&i2c3 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c3>;
+       status = "okay";
+
+       egalax_ts: touchscreen@4 {
+               compatible = "eeti,egalax_ts";
+               reg = <0x04>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <11 IRQ_TYPE_EDGE_FALLING>;
+               wakeup-gpios = <&gpio1 11 GPIO_ACTIVE_LOW>;
+       };
+};
+
+&ldb {
+       status = "okay";
+
+       lvds-channel@0 {
+               fsl,data-mapping = "spwg";
+               fsl,data-width = <18>;
+               status = "okay";
+
+               display-timings {
+                       native-mode = <&timing0>;
+                       timing0: hsd100pxn1 {
+                               clock-frequency = <65000000>;
+                               hactive = <1024>;
+                               vactive = <768>;
+                               hback-porch = <220>;
+                               hfront-porch = <40>;
+                               vback-porch = <21>;
+                               vfront-porch = <7>;
+                               hsync-len = <60>;
+                               vsync-len = <10>;
+                       };
+               };
+       };
+};
+
+&pcie {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_pcie>;
+       reset-gpio = <&gpio1 0 GPIO_ACTIVE_LOW>;
+       status = "okay";
+};
+
+&pwm2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_pwm2>; /* MX6_DIO1 */
+       status = "disabled";
+};
+
+&pwm3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_pwm3>; /* MX6_DIO2 */
+       status = "disabled";
+};
+
+&pwm4 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_pwm4>;
+       status = "okay";
+};
+
+&uart1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart1>;
+       status = "okay";
+};
+
+&uart2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart2>;
+       status = "okay";
+};
+
+&uart3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart3>;
+       uart-has-rtscts;
+       status = "okay";
+};
+
+&uart4 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart4>;
+       uart-has-rtscts;
+       status = "okay";
+};
+
+&uart5 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart5>;
+       status = "okay";
+};
+
+&usbotg {
+       vbus-supply = <&reg_usb_otg_vbus>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usbotg>;
+       disable-over-current;
+       status = "okay";
+};
+
+&usbh1 {
+       vbus-supply = <&reg_usb_h1_vbus>;
+       status = "okay";
+};
+
+&usdhc3 {
+       pinctrl-names = "default", "state_100mhz", "state_200mhz";
+       pinctrl-0 = <&pinctrl_usdhc3>;
+       pinctrl-1 = <&pinctrl_usdhc3_100mhz>;
+       pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
+       non-removable;
+       vmmc-supply = <&reg_3p3v>;
+       keep-power-in-suspend;
+       status = "okay";
+};
+
+&wdog1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_wdog>;
+       fsl,ext-reset-output;
+};
+
+&iomuxc {
+       pinctrl_enet: enetgrp {
+               fsl,pins = <
+                       MX6QDL_PAD_RGMII_RXC__RGMII_RXC         0x1b030
+                       MX6QDL_PAD_RGMII_RD0__RGMII_RD0         0x1b030
+                       MX6QDL_PAD_RGMII_RD1__RGMII_RD1         0x1b030
+                       MX6QDL_PAD_RGMII_RD2__RGMII_RD2         0x1b030
+                       MX6QDL_PAD_RGMII_RD3__RGMII_RD3         0x1b030
+                       MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL   0x1b030
+                       MX6QDL_PAD_RGMII_TXC__RGMII_TXC         0x1b030
+                       MX6QDL_PAD_RGMII_TD0__RGMII_TD0         0x1b030
+                       MX6QDL_PAD_RGMII_TD1__RGMII_TD1         0x1b030
+                       MX6QDL_PAD_RGMII_TD2__RGMII_TD2         0x1b030
+                       MX6QDL_PAD_RGMII_TD3__RGMII_TD3         0x1b030
+                       MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL   0x1b030
+                       MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK    0x1b0b0
+                       MX6QDL_PAD_ENET_MDIO__ENET_MDIO         0x1b0b0
+                       MX6QDL_PAD_ENET_MDC__ENET_MDC           0x1b0b0
+                       MX6QDL_PAD_GPIO_16__ENET_REF_CLK        0x4001b0a8
+                       MX6QDL_PAD_ENET_TXD0__GPIO1_IO30        0x4001b0b0 /* PHY_RST# */
+               >;
+       };
+
+       pinctrl_gpio_leds: gpioledsgrp {
+               fsl,pins = <
+                       MX6QDL_PAD_KEY_COL0__GPIO4_IO06         0x1b0b0
+                       MX6QDL_PAD_KEY_ROW0__GPIO4_IO07         0x1b0b0
+                       MX6QDL_PAD_KEY_ROW4__GPIO4_IO15         0x1b0b0
+               >;
+       };
+
+       pinctrl_i2c1: i2c1grp {
+               fsl,pins = <
+                       MX6QDL_PAD_EIM_D21__I2C1_SCL            0x4001b8b1
+                       MX6QDL_PAD_EIM_D28__I2C1_SDA            0x4001b8b1
+               >;
+       };
+
+       pinctrl_i2c2: i2c2grp {
+               fsl,pins = <
+                       MX6QDL_PAD_KEY_COL3__I2C2_SCL           0x4001b8b1
+                       MX6QDL_PAD_KEY_ROW3__I2C2_SDA           0x4001b8b1
+               >;
+       };
+
+       pinctrl_i2c3: i2c3grp {
+               fsl,pins = <
+                       MX6QDL_PAD_GPIO_3__I2C3_SCL             0x4001b8b1
+                       MX6QDL_PAD_GPIO_6__I2C3_SDA             0x4001b8b1
+               >;
+       };
+
+       pinctrl_pcie: pciegrp {
+               fsl,pins = <
+                       MX6QDL_PAD_GPIO_0__GPIO1_IO00   0x1b0b0 /* PCIE RST */
+               >;
+       };
+
+       pinctrl_pmic: pmicgrp {
+               fsl,pins = <
+                       MX6QDL_PAD_GPIO_8__GPIO1_IO08   0x1b0b0 /* PMIC_IRQ# */
+               >;
+       };
+
+       pinctrl_pps: ppsgrp {
+               fsl,pins = <
+                       MX6QDL_PAD_ENET_RXD1__GPIO1_IO26        0x1b0b1
+               >;
+       };
+
+       pinctrl_pwm2: pwm2grp {
+               fsl,pins = <
+                       MX6QDL_PAD_SD1_DAT2__PWM2_OUT           0x1b0b1
+               >;
+       };
+
+       pinctrl_pwm3: pwm3grp {
+               fsl,pins = <
+                       MX6QDL_PAD_SD1_DAT1__PWM3_OUT           0x1b0b1
+               >;
+       };
+
+       pinctrl_pwm4: pwm4grp {
+               fsl,pins = <
+                       MX6QDL_PAD_SD1_CMD__PWM4_OUT            0x1b0b1
+               >;
+       };
+
+       pinctrl_uart1: uart1grp {
+               fsl,pins = <
+                       MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA    0x1b0b1
+                       MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA    0x1b0b1
+               >;
+       };
+
+       pinctrl_uart2: uart2grp {
+               fsl,pins = <
+                       MX6QDL_PAD_SD4_DAT7__UART2_TX_DATA      0x1b0b1
+                       MX6QDL_PAD_SD4_DAT4__UART2_RX_DATA      0x1b0b1
+               >;
+       };
+
+       pinctrl_uart3: uart3grp {
+               fsl,pins = <
+                       MX6QDL_PAD_EIM_D23__UART3_CTS_B         0x1b0b1
+                       MX6QDL_PAD_EIM_D24__UART3_TX_DATA       0x1b0b1
+                       MX6QDL_PAD_EIM_D25__UART3_RX_DATA       0x1b0b1
+                       MX6QDL_PAD_EIM_D31__UART3_RTS_B         0x1b0b1
+               >;
+       };
+
+       pinctrl_uart4: uart4grp {
+               fsl,pins = <
+                       MX6QDL_PAD_CSI0_DAT12__UART4_TX_DATA    0x1b0b1
+                       MX6QDL_PAD_CSI0_DAT13__UART4_RX_DATA    0x1b0b1
+                       MX6QDL_PAD_CSI0_DAT16__UART4_RTS_B      0x1b0b1
+                       MX6QDL_PAD_CSI0_DAT17__UART4_CTS_B      0x1b0b1
+               >;
+       };
+
+       pinctrl_uart5: uart5grp {
+               fsl,pins = <
+                       MX6QDL_PAD_KEY_COL1__UART5_TX_DATA      0x1b0b1
+                       MX6QDL_PAD_KEY_ROW1__UART5_RX_DATA      0x1b0b1
+               >;
+       };
+
+       pinctrl_usbotg: usbotggrp {
+               fsl,pins = <
+                       MX6QDL_PAD_GPIO_1__USB_OTG_ID           0x17059
+                       MX6QDL_PAD_EIM_D22__GPIO3_IO22          0x1b0b0 /* PWR_EN */
+                       MX6QDL_PAD_KEY_COL4__GPIO4_IO14         0x1b0b0 /* OC */
+               >;
+       };
+
+       pinctrl_usdhc3: usdhc3grp {
+               fsl,pins = <
+                       MX6QDL_PAD_SD3_CMD__SD3_CMD             0x17059
+                       MX6QDL_PAD_SD3_CLK__SD3_CLK             0x10059
+                       MX6QDL_PAD_SD3_RST__SD3_RESET           0x10059
+                       MX6QDL_PAD_SD3_DAT0__SD3_DATA0          0x17059
+                       MX6QDL_PAD_SD3_DAT1__SD3_DATA1          0x17059
+                       MX6QDL_PAD_SD3_DAT2__SD3_DATA2          0x17059
+                       MX6QDL_PAD_SD3_DAT3__SD3_DATA3          0x17059
+                       MX6QDL_PAD_SD3_DAT4__SD3_DATA4          0x17059
+                       MX6QDL_PAD_SD3_DAT5__SD3_DATA5          0x17059
+                       MX6QDL_PAD_SD3_DAT6__SD3_DATA6          0x17059
+                       MX6QDL_PAD_SD3_DAT7__SD3_DATA7          0x17059
+               >;
+       };
+
+       pinctrl_usdhc3_100mhz: usdhc3grp100mhz {
+               fsl,pins = <
+                       MX6QDL_PAD_SD3_CMD__SD3_CMD             0x170b9
+                       MX6QDL_PAD_SD3_CLK__SD3_CLK             0x100b9
+                       MX6QDL_PAD_SD3_RST__SD3_RESET           0x100b9
+                       MX6QDL_PAD_SD3_DAT0__SD3_DATA0          0x170b9
+                       MX6QDL_PAD_SD3_DAT1__SD3_DATA1          0x170b9
+                       MX6QDL_PAD_SD3_DAT2__SD3_DATA2          0x170b9
+                       MX6QDL_PAD_SD3_DAT3__SD3_DATA3          0x170b9
+                       MX6QDL_PAD_SD3_DAT4__SD3_DATA4          0x170b9
+                       MX6QDL_PAD_SD3_DAT5__SD3_DATA5          0x170b9
+                       MX6QDL_PAD_SD3_DAT6__SD3_DATA6          0x170b9
+                       MX6QDL_PAD_SD3_DAT7__SD3_DATA7          0x170b9
+               >;
+       };
+
+       pinctrl_usdhc3_200mhz: usdhc3grp200mhz {
+               fsl,pins = <
+                       MX6QDL_PAD_SD3_CMD__SD3_CMD             0x170f9
+                       MX6QDL_PAD_SD3_CLK__SD3_CLK             0x100f9
+                       MX6QDL_PAD_SD3_RST__SD3_RESET           0x100f9
+                       MX6QDL_PAD_SD3_DAT0__SD3_DATA0          0x170f9
+                       MX6QDL_PAD_SD3_DAT1__SD3_DATA1          0x170f9
+                       MX6QDL_PAD_SD3_DAT2__SD3_DATA2          0x170f9
+                       MX6QDL_PAD_SD3_DAT3__SD3_DATA3          0x170f9
+                       MX6QDL_PAD_SD3_DAT4__SD3_DATA4          0x170f9
+                       MX6QDL_PAD_SD3_DAT5__SD3_DATA5          0x170f9
+                       MX6QDL_PAD_SD3_DAT6__SD3_DATA6          0x170f9
+                       MX6QDL_PAD_SD3_DAT7__SD3_DATA7          0x170f9
+               >;
+       };
+
+       pinctrl_wdog: wdoggrp {
+               fsl,pins = <
+                       MX6QDL_PAD_DISP0_DAT8__WDOG1_B          0x1b0b0
+               >;
+       };
+};
index 55bebfc9ad94b4362f11d6c20836e87a27a68b4f..56d0c5d21cd01b528eb09300bf0ba82156c64e83 100644 (file)
                reg = <0x10000000 0x80000000>;
        };
 
+       backlight {
+               compatible = "pwm-backlight";
+               pwms = <&pwm3 0 100000>;
+               brightness-levels = <0 4 8 16 32 64 128 255>;
+               default-brightness-level = <7>;
+       };
+
        reg_3p3v: regulator-3p3v {
                compatible = "regulator-fixed";
                regulator-name = "3P3V";
        status = "okay";
 };
 
+&pwm3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_pwm3>;
+       status = "okay";
+};
+
 &uart4 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_uart4>;
                >;
        };
 
+       pinctrl_pwm3: pwm3grp {
+               fsl,pins = <
+                       MX6QDL_PAD_SD4_DAT1__PWM3_OUT 0x1b0b1
+               >;
+       };
+
        pinctrl_usbotg: usbotggrp {
                fsl,pins = <
                        MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x17059
index 63bf95ed8c88930ccc935f71a236fa02c89243e7..58055ceec6dcf97960a6fe239aa1e1f47b140e60 100644 (file)
        status = "okay";
 };
 
+&reg_arm {
+       vin-supply = <&sw1a_reg>;
+};
+
+&reg_pu {
+       vin-supply = <&sw1c_reg>;
+};
+
+&reg_soc {
+       vin-supply = <&sw1c_reg>;
+};
+
 &snvs_poweroff {
        status = "okay";
 };
diff --git a/arch/arm/boot/dts/imx6qdl-zii-rdu2.dtsi b/arch/arm/boot/dts/imx6qdl-zii-rdu2.dtsi
new file mode 100644 (file)
index 0000000..5d94b5e
--- /dev/null
@@ -0,0 +1,932 @@
+/*
+ * Copyright (C) 2016-2017 Zodiac Inflight Innovations
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/sound/fsl-imx-audmux.h>
+
+/ {
+       chosen {
+               stdout-path = &uart1;
+       };
+
+       aliases {
+               mdio-gpio0 = &mdio1;
+       };
+
+       mdio1: mdio {
+               compatible = "virtual,mdio-gpio";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_mdio1>;
+               gpios = <&gpio6 5 GPIO_ACTIVE_HIGH
+                        &gpio6 4 GPIO_ACTIVE_HIGH>;
+       };
+
+       reg_28p0v: regulator-28p0v {
+               compatible = "regulator-fixed";
+               regulator-name = "28V_IN";
+               regulator-min-microvolt = <28000000>;
+               regulator-max-microvolt = <28000000>;
+               regulator-always-on;
+       };
+
+       reg_12p0v: regulator-12p0v {
+               compatible = "regulator-fixed";
+               vin-supply = <&reg_28p0v>;
+               regulator-name = "12V_MAIN";
+               regulator-min-microvolt = <12000000>;
+               regulator-max-microvolt = <12000000>;
+               regulator-always-on;
+       };
+
+       reg_5p0v_main: regulator-5p0v-main {
+               compatible = "regulator-fixed";
+               vin-supply = <&reg_12p0v>;
+               regulator-name = "5V_MAIN";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-always-on;
+       };
+
+       reg_5p0v_user_usb: regulator-5p0v-user-usb {
+               compatible = "regulator-fixed";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_reg_user_usb>;
+               vin-supply = <&reg_5p0v_main>;
+               regulator-name = "5V_USER_USB";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               gpio = <&gpio3 22 GPIO_ACTIVE_LOW>;
+               startup-delay-us = <1000>;
+       };
+
+       reg_3p3v_pmic: regulator-3p3v-pmic {
+               compatible = "regulator-fixed";
+               vin-supply = <&reg_12p0v>;
+               regulator-name = "PMIC_3V3";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-always-on;
+       };
+
+       reg_3p3v: regulator-3p3v {
+               compatible = "regulator-fixed";
+               vin-supply = <&reg_3p3v_pmic>;
+               regulator-name = "GEN_3V3";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-always-on;
+       };
+
+       reg_3p3v_sd: regulator-3p3v-sd {
+               compatible = "regulator-fixed";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_reg_3p3v_sd>;
+               vin-supply = <&reg_3p3v>;
+               regulator-name = "3V3_SD";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               gpio = <&gpio7 8 GPIO_ACTIVE_HIGH>;
+               startup-delay-us = <1000>;
+               enable-active-high;
+               regulator-always-on;
+       };
+
+       reg_3p3v_display: regulator-3p3v-display {
+               compatible = "regulator-fixed";
+               vin-supply = <&reg_12p0v>;
+               regulator-name = "3V3_DISPLAY";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-always-on;
+       };
+
+       reg_3p3v_ssd: regulator-3p3v-ssd {
+               compatible = "regulator-fixed";
+               vin-supply = <&reg_12p0v>;
+               regulator-name = "3V3_SSD";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-always-on;
+       };
+
+       sound1 {
+               compatible = "simple-audio-card";
+               simple-audio-card,name = "Front";
+               simple-audio-card,format = "i2s";
+               simple-audio-card,bitclock-master = <&sound1_codec>;
+               simple-audio-card,frame-master = <&sound1_codec>;
+               simple-audio-card,widgets =
+                       "Headphone", "Headphone Jack";
+               simple-audio-card,routing =
+                       "Headphone Jack", "HPLEFT",
+                       "Headphone Jack", "HPRIGHT",
+                       "LEFTIN", "HPL",
+                       "RIGHTIN", "HPR";
+               simple-audio-card,aux-devs = <&hpa1>;
+
+               sound1_cpu: simple-audio-card,cpu {
+                       sound-dai = <&ssi2>;
+               };
+
+               sound1_codec: simple-audio-card,codec {
+                       sound-dai = <&codec1>;
+                       clocks = <&cs2000>;
+               };
+       };
+
+       sound2 {
+               compatible = "simple-audio-card";
+               simple-audio-card,name = "Back";
+               simple-audio-card,format = "i2s";
+               simple-audio-card,bitclock-master = <&sound2_codec>;
+               simple-audio-card,frame-master = <&sound2_codec>;
+               simple-audio-card,widgets =
+                       "Headphone", "Headphone Jack";
+               simple-audio-card,routing =
+                       "Headphone Jack", "HPLEFT",
+                       "Headphone Jack", "HPRIGHT",
+                       "LEFTIN", "HPL",
+                       "RIGHTIN", "HPR";
+               simple-audio-card,aux-devs = <&hpa2>;
+
+               sound2_cpu: simple-audio-card,cpu {
+                       sound-dai = <&ssi1>;
+               };
+
+               sound2_codec: simple-audio-card,codec {
+                       sound-dai = <&codec2>;
+                       clocks = <&cs2000>;
+               };
+       };
+
+       panel {
+               power-supply = <&reg_3p3v_display>;
+               status = "disabled";
+
+               port {
+                       panel_in: endpoint {
+                               remote-endpoint = <&lvds0_out>;
+                       };
+               };
+       };
+
+       disp0: disp0 {
+               #address-cells = <1>;
+               #size-cells = <0>;
+               compatible = "fsl,imx-parallel-display";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_disp0>;
+               status = "disabled";
+
+               port@0 {
+                       reg = <0>;
+
+                       disp0_in_0: endpoint {
+                               remote-endpoint = <&ipu1_di0_disp0>;
+                       };
+               };
+
+               port@1 {
+                       reg = <1>;
+
+                       disp0_out: endpoint {
+                               remote-endpoint = <&tc358767_in>;
+                       };
+               };
+       };
+
+       cs2000_ref: cs2000-ref {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <24576000>;
+       };
+
+       cs2000_in_dummy: cs2000-in-dummy {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <0>;
+       };
+
+       edp_refclk: edp-refclk {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <19200000>;
+       };
+};
+
+&reg_arm {
+       vin-supply = <&sw1a_reg>;
+};
+
+&reg_pu {
+       vin-supply = <&sw1c_reg>;
+};
+
+&reg_soc {
+       vin-supply = <&sw1c_reg>;
+};
+
+&ldb {
+       lvds-channel@0 {
+               port@4 {
+                       reg = <4>;
+
+                       lvds0_out: endpoint {
+                               remote-endpoint = <&panel_in>;
+                       };
+               };
+       };
+};
+
+&uart1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart1>;
+       status = "okay";
+};
+
+&uart3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart3>;
+       uart-has-rtscts;
+       linux,rs485-enabled-at-boot-time;
+       status = "okay";
+};
+
+&uart4 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_uart4>;
+       status = "okay";
+};
+
+&ecspi1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_ecspi1>;
+       cs-gpios = <&gpio2 30 GPIO_ACTIVE_HIGH>;
+       status = "okay";
+
+       flash@0 {
+               compatible = "st,m25p128", "jedec,spi-nor";
+               spi-max-frequency = <20000000>;
+               reg = <0>;
+       };
+};
+
+&i2c1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c1>;
+       clock-frequency = <100000>;
+       status = "okay";
+
+       codec2: codec@18 {
+               compatible = "ti,tlv320dac3100";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_codec2>;
+               reg = <0x18>;
+               #sound-dai-cells = <0>;
+               HPVDD-supply = <&reg_3p3v>;
+               SPRVDD-supply = <&reg_3p3v>;
+               SPLVDD-supply = <&reg_3p3v>;
+               AVDD-supply = <&reg_3p3v>;
+               IOVDD-supply = <&reg_3p3v>;
+               DVDD-supply = <&vgen4_reg>;
+               gpio-reset = <&gpio1 2 GPIO_ACTIVE_HIGH>;
+       };
+
+       accel@1c {
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_accel>;
+               compatible = "fsl,mma8451";
+               reg = <0x1c>;
+               interrupt-parent = <&gpio1>;
+               interrupt-names = "int1", "int2";
+               interrupts = <18 IRQ_TYPE_LEVEL_LOW>, <20 IRQ_TYPE_LEVEL_LOW>;
+       };
+
+       hpa2: amp@60 {
+               compatible = "ti,tpa6130a2";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_tpa2>;
+               reg = <0x60>;
+               power-gpio = <&gpio1 5 GPIO_ACTIVE_HIGH>;
+               Vdd-supply = <&reg_5p0v_main>;
+       };
+
+       edp-bridge@68 {
+               compatible = "toshiba,tc358767";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_tc358767>;
+               reg = <0x68>;
+               shutdown-gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+               clock-names = "ref";
+               clocks = <&edp_refclk>;
+               status = "disabled";
+
+               ports {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       port@1 {
+                               reg = <1>;
+
+                               tc358767_in: endpoint {
+                                       remote-endpoint = <&disp0_out>;
+                               };
+                       };
+               };
+       };
+};
+
+&i2c2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c2>;
+       clock-frequency = <100000>;
+       status = "okay";
+
+       pmic@08 {
+               compatible = "fsl,pfuze100";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_pfuze100_irq>;
+               reg = <0x08>;
+               interrupt-parent = <&gpio7>;
+               interrupts = <13 IRQ_TYPE_LEVEL_LOW>;
+
+               regulators {
+                       sw1a_reg: sw1ab {
+                               regulator-min-microvolt = <300000>;
+                               regulator-max-microvolt = <1875000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                               regulator-ramp-delay = <6250>;
+                       };
+
+                       sw1c_reg: sw1c {
+                               regulator-min-microvolt = <300000>;
+                               regulator-max-microvolt = <1875000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                               regulator-ramp-delay = <6250>;
+                       };
+
+                       sw2_reg: sw2 {
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <3000000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       sw3a_reg: sw3a {
+                               regulator-min-microvolt = <400000>;
+                               regulator-max-microvolt = <1500000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       sw3b_reg: sw3b {
+                               regulator-min-microvolt = <400000>;
+                               regulator-max-microvolt = <1500000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       sw4_reg: sw4 {
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-boot-on;
+                               regulator-always-on;
+                       };
+
+                       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;
+                       };
+
+                       vgen2_reg: vgen2 {
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1500000>;
+                               regulator-always-on;
+                       };
+
+                       vgen4_reg: vgen4 {
+                               regulator-min-microvolt = <1200000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-always-on;
+                       };
+
+                       vgen5_reg: vgen5 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <2500000>;
+                               regulator-always-on;
+                       };
+
+                       vgen6_reg: vgen6 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <2800000>;
+                               regulator-always-on;
+                       };
+               };
+       };
+
+       temp-sense@48 {
+               compatible = "national,lm75";
+               reg = <0x48>;
+       };
+
+       cs2000: clkgen@4e {
+               compatible = "cirrus,cs2000-cp";
+               reg = <0x4e>;
+               #clock-cells = <0>;
+               clock-names = "clk_in", "ref_clk";
+               clocks = <&cs2000_in_dummy>, <&cs2000_ref>;
+               assigned-clocks = <&cs2000>;
+               assigned-clock-rates = <24000000>;
+       };
+
+       eeprom@54 {
+               compatible = "at,24c128";
+               reg = <0x54>;
+       };
+
+       rtc@68 {
+               compatible = "dallas,ds1341";
+               reg = <0x68>;
+       };
+};
+
+&i2c3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c3>;
+       clock-frequency = <400000>;
+       status = "okay";
+
+       codec1: codec@18 {
+               compatible = "ti,tlv320dac3100";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_codec1>;
+               reg = <0x18>;
+               #sound-dai-cells = <0>;
+               HPVDD-supply = <&reg_3p3v>;
+               SPRVDD-supply = <&reg_3p3v>;
+               SPLVDD-supply = <&reg_3p3v>;
+               AVDD-supply = <&reg_3p3v>;
+               IOVDD-supply = <&reg_3p3v>;
+               DVDD-supply = <&vgen4_reg>;
+               gpio-reset = <&gpio1 0 GPIO_ACTIVE_HIGH>;
+       };
+
+       touchscreen@20 {
+               compatible = "syna,rmi4-i2c";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_ts>;
+               reg = <0x20>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <8 IRQ_TYPE_LEVEL_LOW>;
+               vdd-supply = <&reg_5p0v_main>;
+               vio-supply = <&reg_3p3v>;
+
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               rmi4-f01@1 {
+                       reg = <0x1>;
+                       syna,nosleep-mode = <1>;
+               };
+
+               rmi4-f11@11 {
+                       reg = <0x11>;
+                       touchscreen-inverted-y;
+                       touchscreen-swapped-x-y;
+                       syna,sensor-type = <1>;
+               };
+
+               rmi4-f12@12 {
+                       reg = <0x12>;
+                       touchscreen-inverted-y;
+                       touchscreen-swapped-x-y;
+                       syna,sensor-type = <1>;
+               };
+       };
+
+       hpa1: amp@60 {
+               compatible = "ti,tpa6130a2";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_tpa1>;
+               reg = <0x60>;
+               power-gpio = <&gpio1 4 GPIO_ACTIVE_HIGH>;
+               Vdd-supply = <&reg_5p0v_main>;
+       };
+};
+
+&ipu1_di0_disp0 {
+       remote-endpoint = <&disp0_in_0>;
+};
+
+&pcie {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_pcie>;
+       reset-gpio = <&gpio7 12 GPIO_ACTIVE_LOW>;
+       status = "okay";
+};
+
+&usdhc2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usdhc2>;
+       bus-width = <4>;
+       cd-gpios = <&gpio2 2 GPIO_ACTIVE_LOW>;
+       wp-gpios = <&gpio2 3 GPIO_ACTIVE_HIGH>;
+       vmmc-supply = <&reg_3p3v_sd>;
+       vqmmc-supply = <&reg_3p3v>;
+       status = "okay";
+};
+
+&usdhc3 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usdhc3>;
+       bus-width = <4>;
+       cd-gpios = <&gpio2 0 GPIO_ACTIVE_LOW>;
+       wp-gpios = <&gpio2 1 GPIO_ACTIVE_HIGH>;
+       vmmc-supply = <&reg_3p3v_sd>;
+       vqmmc-supply = <&reg_3p3v>;
+       status = "okay";
+};
+
+&usdhc4 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_usdhc4>;
+       bus-width = <8>;
+       vmmc-supply = <&reg_3p3v>;
+       vqmmc-supply = <&reg_3p3v>;
+       non-removable;
+       status = "okay";
+};
+
+&sata {
+       target-supply = <&reg_3p3v_ssd>;
+       status = "okay";
+};
+
+&fec {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_enet>;
+       phy-mode = "rmii";
+       phy-reset-gpios = <&gpio1 23 GPIO_ACTIVE_LOW>;
+       phy-reset-duration = <100>;
+       phy-supply = <&reg_3p3v>;
+       status = "okay";
+
+       fixed-link {
+               speed = <100>;
+               full-duplex;
+       };
+};
+
+&usbh1 {
+       vbus-supply = <&reg_5p0v_main>;
+       status = "okay";
+};
+
+&usbotg {
+       vbus-supply = <&reg_5p0v_user_usb>;
+       disable-over-current;
+       dr_mode = "host";
+       status = "okay";
+};
+
+&ssi1 {
+       status = "okay";
+};
+
+&ssi2 {
+       status = "okay";
+};
+
+&audmux {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_audmux>;
+       status = "okay";
+
+       ssi1 {
+               fsl,audmux-port = <0>;
+               fsl,port-config = <
+                       (IMX_AUDMUX_V2_PTCR_SYN |
+                        IMX_AUDMUX_V2_PTCR_TFSEL(2) |
+                        IMX_AUDMUX_V2_PTCR_TCSEL(2) |
+                        IMX_AUDMUX_V2_PTCR_TFSDIR |
+                        IMX_AUDMUX_V2_PTCR_TCLKDIR)
+                       IMX_AUDMUX_V2_PDCR_RXDSEL(2)
+               >;
+       };
+
+       aud3 {
+               fsl,audmux-port = <2>;
+               fsl,port-config = <
+                       IMX_AUDMUX_V2_PTCR_SYN
+                       IMX_AUDMUX_V2_PDCR_RXDSEL(0)
+               >;
+       };
+
+       ssi2 {
+               fsl,audmux-port = <1>;
+               fsl,port-config = <
+                       (IMX_AUDMUX_V2_PTCR_SYN |
+                        IMX_AUDMUX_V2_PTCR_TFSEL(4) |
+                        IMX_AUDMUX_V2_PTCR_TCSEL(4) |
+                        IMX_AUDMUX_V2_PTCR_TFSDIR |
+                        IMX_AUDMUX_V2_PTCR_TCLKDIR)
+                       IMX_AUDMUX_V2_PDCR_RXDSEL(4)
+               >;
+       };
+
+       aud5 {
+               fsl,audmux-port = <4>;
+               fsl,port-config = <
+                       IMX_AUDMUX_V2_PTCR_SYN
+                       IMX_AUDMUX_V2_PDCR_RXDSEL(1)
+               >;
+       };
+};
+
+&iomuxc {
+       pinctrl_accel: accelgrp {
+               fsl,pins = <
+                       MX6QDL_PAD_SD1_CMD__GPIO1_IO18          0x4001b000
+                       MX6QDL_PAD_SD1_CLK__GPIO1_IO20          0x4001b000
+               >;
+       };
+
+       pinctrl_audmux: audmuxgrp {
+               fsl,pins = <
+                       MX6QDL_PAD_KEY_COL0__AUD5_TXC           0x130b0
+                       MX6QDL_PAD_KEY_ROW0__AUD5_TXD           0x130b0
+                       MX6QDL_PAD_KEY_COL1__AUD5_TXFS          0x130b0
+                       MX6QDL_PAD_CSI0_DAT4__AUD3_TXC          0x130b0
+                       MX6QDL_PAD_CSI0_DAT5__AUD3_TXD          0x130b0
+                       MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS         0x130b0
+               >;
+       };
+
+       pinctrl_codec1: dac1grp {
+               fsl,pins = <
+                       MX6QDL_PAD_GPIO_0__GPIO1_IO00           0x40000038
+               >;
+       };
+
+       pinctrl_codec2: dac2grp {
+               fsl,pins = <
+                       MX6QDL_PAD_GPIO_2__GPIO1_IO02           0x40000038
+               >;
+       };
+
+       pinctrl_disp0: disp0grp {
+               fsl,pins = <
+                       MX6QDL_PAD_DI0_DISP_CLK__IPU1_DI0_DISP_CLK 0x100f9
+                       MX6QDL_PAD_DI0_PIN15__IPU1_DI0_PIN15       0x100f9
+                       MX6QDL_PAD_DI0_PIN2__IPU1_DI0_PIN02        0x100f9
+                       MX6QDL_PAD_DI0_PIN3__IPU1_DI0_PIN03        0x100f9
+                       MX6QDL_PAD_DISP0_DAT0__IPU1_DISP0_DATA00   0x100f9
+                       MX6QDL_PAD_DISP0_DAT1__IPU1_DISP0_DATA01   0x100f9
+                       MX6QDL_PAD_DISP0_DAT2__IPU1_DISP0_DATA02   0x100f9
+                       MX6QDL_PAD_DISP0_DAT3__IPU1_DISP0_DATA03   0x100f9
+                       MX6QDL_PAD_DISP0_DAT4__IPU1_DISP0_DATA04   0x100f9
+                       MX6QDL_PAD_DISP0_DAT5__IPU1_DISP0_DATA05   0x100f9
+                       MX6QDL_PAD_DISP0_DAT6__IPU1_DISP0_DATA06   0x100f9
+                       MX6QDL_PAD_DISP0_DAT7__IPU1_DISP0_DATA07   0x100f9
+                       MX6QDL_PAD_DISP0_DAT8__IPU1_DISP0_DATA08   0x100f9
+                       MX6QDL_PAD_DISP0_DAT9__IPU1_DISP0_DATA09   0x100f9
+                       MX6QDL_PAD_DISP0_DAT10__IPU1_DISP0_DATA10  0x100f9
+                       MX6QDL_PAD_DISP0_DAT11__IPU1_DISP0_DATA11  0x100f9
+                       MX6QDL_PAD_DISP0_DAT12__IPU1_DISP0_DATA12  0x100f9
+                       MX6QDL_PAD_DISP0_DAT13__IPU1_DISP0_DATA13  0x100f9
+                       MX6QDL_PAD_DISP0_DAT14__IPU1_DISP0_DATA14  0x100f9
+                       MX6QDL_PAD_DISP0_DAT15__IPU1_DISP0_DATA15  0x100f9
+                       MX6QDL_PAD_DISP0_DAT16__IPU1_DISP0_DATA16  0x100f9
+                       MX6QDL_PAD_DISP0_DAT17__IPU1_DISP0_DATA17  0x100f9
+                       MX6QDL_PAD_DISP0_DAT18__IPU1_DISP0_DATA18  0x100f9
+                       MX6QDL_PAD_DISP0_DAT19__IPU1_DISP0_DATA19  0x100f9
+                       MX6QDL_PAD_DISP0_DAT20__IPU1_DISP0_DATA20  0x100f9
+                       MX6QDL_PAD_DISP0_DAT21__IPU1_DISP0_DATA21  0x100f9
+                       MX6QDL_PAD_DISP0_DAT22__IPU1_DISP0_DATA22  0x100f9
+                       MX6QDL_PAD_DISP0_DAT23__IPU1_DISP0_DATA23  0x100f9
+               >;
+       };
+
+       pinctrl_ecspi1: ecspi1grp {
+               fsl,pins = <
+                       MX6QDL_PAD_EIM_D17__ECSPI1_MISO         0x100b1
+                       MX6QDL_PAD_EIM_D18__ECSPI1_MOSI         0x100b1
+                       MX6QDL_PAD_EIM_D16__ECSPI1_SCLK         0x100b1
+                       MX6QDL_PAD_EIM_EB2__GPIO2_IO30          0x1b0b1
+               >;
+       };
+
+       pinctrl_enet: enetgrp {
+               fsl,pins = <
+                       MX6QDL_PAD_ENET_MDC__ENET_MDC           0x000b1
+                       MX6QDL_PAD_ENET_MDIO__ENET_MDIO         0x100b1
+                       MX6QDL_PAD_ENET_CRS_DV__ENET_RX_EN      0x100f5
+                       MX6QDL_PAD_ENET_TX_EN__ENET_TX_EN       0x100f5
+                       MX6QDL_PAD_ENET_RXD0__ENET_RX_DATA0     0x100c0
+                       MX6QDL_PAD_ENET_RXD1__ENET_RX_DATA1     0x100c0
+                       MX6QDL_PAD_ENET_TXD0__ENET_TX_DATA0     0x100f5
+                       MX6QDL_PAD_ENET_TXD1__ENET_TX_DATA1     0x100f5
+                       MX6QDL_PAD_GPIO_16__ENET_REF_CLK        0x40010040
+                       MX6QDL_PAD_ENET_RX_ER__ENET_RX_ER       0x100b0
+                       MX6QDL_PAD_ENET_REF_CLK__GPIO1_IO23     0x1b0b0
+               >;
+       };
+
+       pinctrl_i2c1: i2c1grp {
+               fsl,pins = <
+                       MX6QDL_PAD_CSI0_DAT8__I2C1_SDA          0x4001b8b1
+                       MX6QDL_PAD_CSI0_DAT9__I2C1_SCL          0x4001b8b1
+               >;
+       };
+
+       pinctrl_i2c2: i2c2grp {
+               fsl,pins = <
+                       MX6QDL_PAD_KEY_COL3__I2C2_SCL           0x4001b8b1
+                       MX6QDL_PAD_KEY_ROW3__I2C2_SDA           0x4001b8b1
+               >;
+       };
+
+       pinctrl_i2c3: i2c3grp {
+               fsl,pins = <
+                       MX6QDL_PAD_GPIO_3__I2C3_SCL             0x4001b8b1
+                       MX6QDL_PAD_GPIO_6__I2C3_SDA             0x4001b8b1
+               >;
+       };
+
+       pinctrl_mdio1: bitbangmdiogrp {
+               fsl,pins = <
+                       /* Bitbang MDIO for DEB Switch */
+                       MX6QDL_PAD_CSI0_DAT19__GPIO6_IO05       0x4001b030
+                       MX6QDL_PAD_CSI0_DAT18__GPIO6_IO04       0x40018830
+               >;
+       };
+
+       pinctrl_pcie: pciegrp {
+               fsl,pins = <
+                       MX6QDL_PAD_GPIO_17__GPIO7_IO12          0x10038
+               >;
+       };
+
+       pinctrl_pfuze100_irq: pfuze100grp {
+               fsl,pins = <
+                       MX6QDL_PAD_GPIO_18__GPIO7_IO13          0x40010000
+               >;
+       };
+
+       pinctrl_reg_3p3v_sd: mmcsupply1grp {
+               fsl,pins = <
+                       MX6QDL_PAD_SD3_RST__GPIO7_IO08          0x858
+               >;
+       };
+
+       pinctrl_reg_user_usb: usbotggrp {
+               fsl,pins = <
+                       MX6QDL_PAD_EIM_D22__GPIO3_IO22          0x40000038
+               >;
+       };
+
+       pinctrl_rmii_phy_irq: phygrp {
+               fsl,pins = <
+                       MX6QDL_PAD_EIM_D30__GPIO3_IO30          0x40010000
+               >;
+       };
+
+       pinctrl_tc358767: tc358767grp {
+               fsl,pins = <
+                       MX6QDL_PAD_GPIO_9__GPIO1_IO09           0x10
+               >;
+       };
+
+       pinctrl_tpa1: tpa6130-1grp {
+               fsl,pins = <
+                       MX6QDL_PAD_GPIO_4__GPIO1_IO04           0x40000038
+               >;
+       };
+
+       pinctrl_tpa2: tpa6130-2grp {
+               fsl,pins = <
+                       MX6QDL_PAD_GPIO_5__GPIO1_IO05           0x40000038
+               >;
+       };
+
+       pinctrl_ts: tsgrp {
+               fsl,pins = <
+                       MX6QDL_PAD_GPIO_8__GPIO1_IO08           0x1b0b0
+                       MX6QDL_PAD_GPIO_7__GPIO1_IO07           0x1b0b0
+               >;
+       };
+
+       pinctrl_uart1: uart1grp {
+               fsl,pins = <
+                       MX6QDL_PAD_CSI0_DAT10__UART1_TX_DATA    0x1b0b1
+                       MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA    0x1b0b1
+               >;
+       };
+
+       pinctrl_uart3: uart3grp {
+               fsl,pins = <
+                       MX6QDL_PAD_EIM_D24__UART3_TX_DATA       0x1b0b1
+                       MX6QDL_PAD_EIM_D25__UART3_RX_DATA       0x1b0b1
+                       MX6QDL_PAD_EIM_D31__UART3_RTS_B         0x1b0b1
+               >;
+       };
+
+       pinctrl_uart4: uart4grp {
+               fsl,pins = <
+                       MX6QDL_PAD_CSI0_DAT12__UART4_TX_DATA    0x1b0b1
+                       MX6QDL_PAD_CSI0_DAT13__UART4_RX_DATA    0x1b0b1
+               >;
+       };
+
+       pinctrl_usdhc2: usdhc2grp {
+               fsl,pins = <
+                       MX6QDL_PAD_SD2_CMD__SD2_CMD             0x10059
+                       MX6QDL_PAD_SD2_CLK__SD2_CLK             0x10069
+                       MX6QDL_PAD_SD2_DAT0__SD2_DATA0          0x17059
+                       MX6QDL_PAD_SD2_DAT1__SD2_DATA1          0x17059
+                       MX6QDL_PAD_SD2_DAT2__SD2_DATA2          0x17059
+                       MX6QDL_PAD_SD2_DAT3__SD2_DATA3          0x17059
+                       MX6QDL_PAD_NANDF_D3__GPIO2_IO03         0x40010040
+                       MX6QDL_PAD_NANDF_D2__GPIO2_IO02         0x40010040
+               >;
+       };
+
+       pinctrl_usdhc3: usdhc3grp {
+               fsl,pins = <
+                       MX6QDL_PAD_SD3_CMD__SD3_CMD             0x10059
+                       MX6QDL_PAD_SD3_CLK__SD3_CLK             0x10069
+                       MX6QDL_PAD_SD3_DAT0__SD3_DATA0          0x17059
+                       MX6QDL_PAD_SD3_DAT1__SD3_DATA1          0x17059
+                       MX6QDL_PAD_SD3_DAT2__SD3_DATA2          0x17059
+                       MX6QDL_PAD_SD3_DAT3__SD3_DATA3          0x17059
+                       MX6QDL_PAD_NANDF_D1__GPIO2_IO01         0x40010040
+                       MX6QDL_PAD_NANDF_D0__GPIO2_IO00         0x40010040
+
+               >;
+       };
+
+       pinctrl_usdhc4: usdhc4grp {
+               fsl,pins = <
+                       MX6QDL_PAD_SD4_CMD__SD4_CMD             0x17059
+                       MX6QDL_PAD_SD4_CLK__SD4_CLK             0x10059
+                       MX6QDL_PAD_SD4_DAT0__SD4_DATA0          0x17059
+                       MX6QDL_PAD_SD4_DAT1__SD4_DATA1          0x17059
+                       MX6QDL_PAD_SD4_DAT2__SD4_DATA2          0x17059
+                       MX6QDL_PAD_SD4_DAT3__SD4_DATA3          0x17059
+                       MX6QDL_PAD_SD4_DAT4__SD4_DATA4          0x17059
+                       MX6QDL_PAD_SD4_DAT5__SD4_DATA5          0x17059
+                       MX6QDL_PAD_SD4_DAT6__SD4_DATA6          0x17059
+                       MX6QDL_PAD_SD4_DAT7__SD4_DATA7          0x17059
+                       MX6QDL_PAD_NANDF_ALE__SD4_RESET         0x1b0b1
+               >;
+       };
+};
index 6d7bf64961170f5e2e23b989e06f5894dfb1b59e..e426faa9c24379bc3b19c3f859c464649c8c220d 100644 (file)
                        arm,shared-override;
                };
 
-               pcie: pcie@0x01000000 {
+               pcie: pcie@1ffc000 {
                        compatible = "fsl,imx6q-pcie", "snps,dw-pcie";
                        reg = <0x01ffc000 0x04000>,
                              <0x01f00000 0x80000>;
                        #address-cells = <3>;
                        #size-cells = <2>;
                        device_type = "pci";
+                       bus-range = <0x00 0xff>;
                        ranges = <0x81000000 0 0          0x01f80000 0 0x00010000 /* downstream I/O */
                                  0x82000000 0 0x01000000 0x01000000 0 0x00f00000>; /* non-prefetchable memory */
                        num-lanes = <1>;
diff --git a/arch/arm/boot/dts/imx6qp-nitrogen6_som2.dts b/arch/arm/boot/dts/imx6qp-nitrogen6_som2.dts
new file mode 100644 (file)
index 0000000..011726c
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2017 Boundary Devices, Inc.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include "imx6qp.dtsi"
+#include "imx6qdl-nitrogen6_som2.dtsi"
+
+/ {
+       model = "Boundary Devices i.MX6 Quad Plus Nitrogen6_SOM2 Board";
+       compatible = "boundary,imx6qp-nitrogen6_som2", "fsl,imx6qp";
+};
+
+&sata {
+       status = "okay";
+};
index b23458062f5e66f231797bf7a02833c8a4aa4792..a8a5004dd9c8615c877a6de92eb06df17ccc9c12 100644 (file)
@@ -50,8 +50,8 @@
        compatible = "fsl,imx6qp-sabresd", "fsl,imx6qp";
 };
 
-&cpu0 {
-       arm-supply = <&sw2_reg>;
+&reg_arm {
+       vin-supply = <&sw2_reg>;
 };
 
 &iomuxc {
diff --git a/arch/arm/boot/dts/imx6qp-zii-rdu2.dts b/arch/arm/boot/dts/imx6qp-zii-rdu2.dts
new file mode 100644 (file)
index 0000000..882b3bd
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016-2017 Zodiac Inflight Innovations
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED , WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include <imx6qp.dtsi>
+#include <imx6qdl-zii-rdu2.dtsi>
+
+/ {
+       model = "ZII RDU2+ Board";
+       compatible = "zii,imx6qp-zii-rdu2", "fsl,imx6qp";
+};
index 24d071f5d9cd2c9b68813f7ef49dfe557f838ff3..59453f2ac4bafeaad4efbb98ab4189c27bb788f8 100644 (file)
                        clocks = <&clks IMX6QDL_CLK_OCRAM>;
                };
 
-               ipu1: ipu@02400000 {
-                       compatible = "fsl,imx6qp-ipu", "fsl,imx6q-ipu";
-                       clocks = <&clks IMX6QDL_CLK_IPU1>,
-                                <&clks IMX6QDL_CLK_IPU1_DI0>, <&clks IMX6QDL_CLK_IPU1_DI1>,
-                                <&clks IMX6QDL_CLK_IPU1_DI0_SEL>, <&clks IMX6QDL_CLK_IPU1_DI1_SEL>,
-                                <&clks IMX6QDL_CLK_LDB_DI0_PODF>, <&clks IMX6QDL_CLK_LDB_DI1_PODF>,
-                                <&clks IMX6QDL_CLK_PRG0_APB>;
-                       clock-names = "bus",
-                                     "di0", "di1",
-                                     "di0_sel", "di1_sel",
-                                     "ldb_di0", "ldb_di1", "prg";
-               };
+               aips-bus@02100000 {
+                       pre1: pre@21c8000 {
+                               compatible = "fsl,imx6qp-pre";
+                               reg = <0x021c8000 0x1000>;
+                               interrupts = <GIC_SPI 90 IRQ_TYPE_EDGE_RISING>;
+                               clocks = <&clks IMX6QDL_CLK_PRE0>;
+                               clock-names = "axi";
+                               fsl,iram = <&ocram2>;
+                       };
 
-               ipu2: ipu@02800000 {
-                       compatible = "fsl,imx6qp-ipu", "fsl,imx6q-ipu";
-                       clocks = <&clks IMX6QDL_CLK_IPU2>,
-                                <&clks IMX6QDL_CLK_IPU2_DI0>, <&clks IMX6QDL_CLK_IPU2_DI1>,
-                                <&clks IMX6QDL_CLK_IPU2_DI0_SEL>, <&clks IMX6QDL_CLK_IPU2_DI1_SEL>,
-                                <&clks IMX6QDL_CLK_LDB_DI0_PODF>, <&clks IMX6QDL_CLK_LDB_DI1_PODF>,
-                                <&clks IMX6QDL_CLK_PRG1_APB>;
-                       clock-names = "bus",
-                                     "di0", "di1",
-                                     "di0_sel", "di1_sel",
-                                     "ldb_di0", "ldb_di1", "prg";
-               };
+                       pre2: pre@21c9000 {
+                               compatible = "fsl,imx6qp-pre";
+                               reg = <0x021c9000 0x1000>;
+                               interrupts = <GIC_SPI 97 IRQ_TYPE_EDGE_RISING>;
+                               clocks = <&clks IMX6QDL_CLK_PRE1>;
+                               clock-names = "axi";
+                               fsl,iram = <&ocram2>;
+                       };
 
-               pcie: pcie@0x01000000 {
-                       compatible = "fsl,imx6qp-pcie", "snps,dw-pcie";
-               };
+                       pre3: pre@21ca000 {
+                               compatible = "fsl,imx6qp-pre";
+                               reg = <0x021ca000 0x1000>;
+                               interrupts = <GIC_SPI 98 IRQ_TYPE_EDGE_RISING>;
+                               clocks = <&clks IMX6QDL_CLK_PRE2>;
+                               clock-names = "axi";
+                               fsl,iram = <&ocram3>;
+                       };
 
-               aips-bus@02100000 {
-                       mmdc0: mmdc@021b0000 { /* MMDC0 */
-                               compatible = "fsl,imx6qp-mmdc", "fsl,imx6q-mmdc";
-                               reg = <0x021b0000 0x4000>;
+                       pre4: pre@21cb000 {
+                               compatible = "fsl,imx6qp-pre";
+                               reg = <0x021cb000 0x1000>;
+                               interrupts = <GIC_SPI 99 IRQ_TYPE_EDGE_RISING>;
+                               clocks = <&clks IMX6QDL_CLK_PRE3>;
+                               clock-names = "axi";
+                               fsl,iram = <&ocram3>;
+                       };
+
+                       prg1: prg@21cc000 {
+                               compatible = "fsl,imx6qp-prg";
+                               reg = <0x021cc000 0x1000>;
+                               clocks = <&clks IMX6QDL_CLK_PRG0_APB>,
+                                        <&clks IMX6QDL_CLK_PRG0_AXI>;
+                               clock-names = "ipg", "axi";
+                               fsl,pres = <&pre1>, <&pre2>, <&pre3>;
+                       };
+
+                       prg2: prg@21cd000 {
+                               compatible = "fsl,imx6qp-prg";
+                               reg = <0x021cd000 0x1000>;
+                               clocks = <&clks IMX6QDL_CLK_PRG1_APB>,
+                                        <&clks IMX6QDL_CLK_PRG1_AXI>;
+                               clock-names = "ipg", "axi";
+                               fsl,pres = <&pre4>, <&pre2>, <&pre3>;
                        };
                };
        };
                     <0 119 IRQ_TYPE_LEVEL_HIGH>;
 };
 
+&ipu1 {
+       compatible = "fsl,imx6qp-ipu", "fsl,imx6q-ipu";
+       fsl,prg = <&prg1>;
+};
+
+&ipu2 {
+       compatible = "fsl,imx6qp-ipu", "fsl,imx6q-ipu";
+       fsl,prg = <&prg2>;
+};
+
 &ldb {
        clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>, <&clks IMX6QDL_CLK_LDB_DI1_SEL>,
                 <&clks IMX6QDL_CLK_IPU1_DI0_SEL>, <&clks IMX6QDL_CLK_IPU1_DI1_SEL>,
                      "di0_sel", "di1_sel", "di2_sel", "di3_sel",
                      "di0", "di1";
 };
+
+&mmdc0 {
+       compatible = "fsl,imx6qp-mmdc", "fsl,imx6q-mmdc";
+};
+
+&pcie {
+       compatible = "fsl,imx6qp-pcie", "snps,dw-pcie";
+};
index 5bb8fd57e7f5a83f6cbae6c2292f33c92446c4f7..d71da30c9cff2347900f9e68715b18d65597d47a 100644 (file)
        model = "Freescale i.MX6 SoloX SDB RevB Board";
 };
 
-&cpu0 {
-       operating-points = <
-               /* kHz    uV */
-               996000  1250000
-               792000  1175000
-               396000  1175000
-               198000  1175000
-               >;
-       fsl,soc-operating-points = <
-               /* ARM kHz      SOC uV */
-               996000  1250000
-               792000  1175000
-               396000  1175000
-               198000  1175000
-       >;
-};
-
 &i2c1 {
        clock-frequency = <100000>;
        pinctrl-names = "default";
index dd4ec85ecbaaff534c2128997da4215e5b0f93bc..3f1416be4c360909bc256000d5d83b0ae385b130 100644 (file)
                                };
 
                                uart1: serial@02020000 {
-                                       compatible = "fsl,imx6sx-uart", "fsl,imx21-uart";
+                                       compatible = "fsl,imx6sx-uart",
+                                                    "fsl,imx6q-uart", "fsl,imx21-uart";
                                        reg = <0x02020000 0x4000>;
                                        interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
                                        clocks = <&clks IMX6SX_CLK_UART_IPG>,
                        };
 
                        uart2: serial@021e8000 {
-                               compatible = "fsl,imx6sx-uart", "fsl,imx21-uart";
+                               compatible = "fsl,imx6sx-uart",
+                                            "fsl,imx6q-uart", "fsl,imx21-uart";
                                reg = <0x021e8000 0x4000>;
                                interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6SX_CLK_UART_IPG>,
                        };
 
                        uart3: serial@021ec000 {
-                               compatible = "fsl,imx6sx-uart", "fsl,imx21-uart";
+                               compatible = "fsl,imx6sx-uart",
+                                            "fsl,imx6q-uart", "fsl,imx21-uart";
                                reg = <0x021ec000 0x4000>;
                                interrupts = <GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6SX_CLK_UART_IPG>,
                        };
 
                        uart4: serial@021f0000 {
-                               compatible = "fsl,imx6sx-uart", "fsl,imx21-uart";
+                               compatible = "fsl,imx6sx-uart",
+                                            "fsl,imx6q-uart", "fsl,imx21-uart";
                                reg = <0x021f0000 0x4000>;
                                interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6SX_CLK_UART_IPG>,
                        };
 
                        uart5: serial@021f4000 {
-                               compatible = "fsl,imx6sx-uart", "fsl,imx21-uart";
+                               compatible = "fsl,imx6sx-uart",
+                                            "fsl,imx6q-uart", "fsl,imx21-uart";
                                reg = <0x021f4000 0x4000>;
                                interrupts = <GIC_SPI 30 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6SX_CLK_UART_IPG>,
                        };
 
                        uart6: serial@022a0000 {
-                               compatible = "fsl,imx6sx-uart", "fsl,imx21-uart";
+                               compatible = "fsl,imx6sx-uart",
+                                            "fsl,imx6q-uart", "fsl,imx21-uart";
                                reg = <0x022a0000 0x4000>;
                                interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6SX_CLK_UART_IPG>,
                        };
                };
 
-               pcie: pcie@0x08000000 {
+               pcie: pcie@8ffc000 {
                        compatible = "fsl,imx6sx-pcie", "snps,dw-pcie";
                        reg = <0x08ffc000 0x4000>; /* DBI */
                        #address-cells = <3>;
                                  0x81000000 0 0          0x08f80000 0 0x00010000
                                  /* non-prefetchable memory */
                                  0x82000000 0 0x08000000 0x08000000 0 0x00f00000>;
+                       bus-range = <0x00 0xff>;
                        num-lanes = <1>;
                        interrupts = <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&clks IMX6SX_CLK_PCIE_REF_125M>,
index 00f98e5bfcaf3196fd8e9f24f439da97e18315b4..f18e1f1d0ce2c6aad83c08b7ad8ac4cfc41e715e 100644 (file)
        assigned-clock-rates = <786432000>;
 };
 
-&cpu0 {
-       arm-supply = <&reg_arm>;
-       soc-supply = <&reg_soc>;
-};
-
 &i2c2 {
        clock_frequency = <100000>;
        pinctrl-names = "default";
index 940aef67313bc12acc858060df5b730eb67721d2..eb94d956808bb21d05d190d11a6a652bb9f84ff9 100644 (file)
                reg = <0x80000000 0x08000000>;
        };
 
+       backlight {
+               compatible = "pwm-backlight";
+               pwms = <&pwm8 0 100000>;
+               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>;
+               default-brightness-level = <100>;
+       };
+
        chosen {
                stdout-path = &uart1;
        };
        display = <&display0>;
 };
 
+&pwm8 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_pwm8>;
+       status = "okay";
+};
+
 &tsc {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_tsc>;
        xnur-gpio = <&gpio1 3 GPIO_ACTIVE_LOW>;
 };
 
+&sai2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_sai2>;
+       status = "okay";
+};
+
 &uart1 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_uart1>;
                >;
        };
 
+       pinctrl_pwm8: pwm8grp {
+               fsl,pins = <
+                       MX6UL_PAD_ENET1_RX_ER__PWM8_OUT   0x110b0
+               >;
+       };
+
        pinctrl_tsc: tscgrp {
                fsl,pin = <
                        MX6UL_PAD_GPIO1_IO01__GPIO1_IO01        0xb0
                >;
        };
 
+       pinctrl_sai2: sai2grp {
+               fsl,pins = <
+                       MX6UL_PAD_JTAG_TCK__SAI2_RX_DATA        0x130b0
+                       MX6UL_PAD_JTAG_TMS__CCM_CLKO1           0x4001b031
+                       MX6UL_PAD_JTAG_TDI__SAI2_TX_BCLK        0x17088
+                       MX6UL_PAD_JTAG_TDO__SAI2_TX_SYNC        0x17088
+                       MX6UL_PAD_JTAG_TRST_B__SAI2_TX_DATA     0x120b0
+               >;
+       };
+
        pinctrl_uart1: uart1grp {
                fsl,pins = <
                        MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x1b0b1
diff --git a/arch/arm/boot/dts/imx6ul-isiot-common.dtsi b/arch/arm/boot/dts/imx6ul-isiot-common.dtsi
new file mode 100644 (file)
index 0000000..2beaab6
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2016 Amarula Solutions B.V.
+ * Copyright (C) 2016 Engicam S.r.l.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     version 2 as published by the Free Software Foundation.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+&i2c1 {
+       stmpe811: gpio-expander@44 {
+               compatible = "st,stmpe811";
+               reg = <0x44>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_stmpe>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <18 IRQ_TYPE_EDGE_FALLING>;
+               interrupt-controller;
+               #interrupt-cells = <2>;
+
+               stmpe: 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>;
+               };
+       };
+};
+
+&lcdif {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_lcdif_dat
+                    &pinctrl_lcdif_ctrl>;
+       display = <&display0>;
+       status = "okay";
+
+       display0: display {
+               bits-per-pixel = <16>;
+               bus-width = <18>;
+
+               display-timings {
+                       native-mode = <&timing0>;
+                       timing0: timing0 {
+                               clock-frequency = <28000000>;
+                               hactive = <800>;
+                               vactive = <480>;
+                               hfront-porch = <30>;
+                               hback-porch = <30>;
+                               hsync-len = <64>;
+                               vback-porch = <5>;
+                               vfront-porch = <5>;
+                               vsync-len = <20>;
+                               hsync-active = <0>;
+                               vsync-active = <0>;
+                               de-active = <1>;
+                               pixelclk-active = <0>;
+                       };
+               };
+       };
+};
+
+&iomuxc {
+       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
+               >;
+       };
+
+       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
+               >;
+       };
+
+       pinctrl_stmpe: stmpegrp  {
+               fsl,pins = <
+                       MX6UL_PAD_UART1_CTS_B__GPIO1_IO18 0x1b0b0
+               >;
+       };
+};
index f5b422898e61dd22ed1c13a3357a62fb2209f8f1..73a1d0f0b9d543b18d498a0c4c38becef68831b9 100644 (file)
@@ -43,6 +43,7 @@
 /dts-v1/;
 
 #include "imx6ul-isiot.dtsi"
+#include "imx6ul-isiot-common.dtsi"
 
 / {
        model = "Engicam Is.IoT MX6UL eMMC Starter kit";
index de15e1c75dd1ddf606976d0f3571fdf6bb1c10e7..da29a86eb6a8f83dc9e3fc64bf50f4b6d0cd2b74 100644 (file)
@@ -43,6 +43,7 @@
 /dts-v1/;
 
 #include "imx6ul-isiot.dtsi"
+#include "imx6ul-isiot-common.dtsi"
 
 / {
        model = "Engicam Is.IoT MX6UL NAND Starter kit";
index 0b43699af3e366cac6b76b35499c9412a99eb38f..ea30380ad7a4bef0e1261bdc7788b9257579b2ec 100644 (file)
        chosen {
                stdout-path = &uart1;
        };
+
+       backlight {
+               compatible = "pwm-backlight";
+               pwms = <&pwm8 0 100000>;
+               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>;
+               default-brightness-level = <100>;
+       };
+};
+
+&i2c1 {
+       clock-frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c1>;
+       status = "okay";
+};
+
+&i2c2 {
+       clock_frequency = <100000>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_i2c2>;
+       status = "okay";
+};
+
+&pwm8 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_pwm8>;
+       status = "okay";
+};
+
+&sai2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&pinctrl_sai2>;
+       status = "okay";
 };
 
 &uart1 {
 };
 
 &iomuxc {
+       pinctrl_i2c1: i2c1grp {
+               fsl,pins = <
+                       MX6UL_PAD_UART4_TX_DATA__I2C1_SCL 0x4001b8b0
+                       MX6UL_PAD_UART4_RX_DATA__I2C1_SDA 0x4001b8b0
+               >;
+       };
+
+       pinctrl_i2c2: i2c2grp {
+               fsl,pins = <
+                       MX6UL_PAD_GPIO1_IO00__I2C2_SCL 0x4001b8b0
+                       MX6UL_PAD_GPIO1_IO01__I2C2_SDA 0x4001b8b0
+               >;
+       };
+
+       pinctrl_pwm8: pwm8grp {
+               fsl,pins = <
+                       MX6UL_PAD_ENET1_RX_ER__PWM8_OUT   0x110b0
+               >;
+       };
+
+       pinctrl_sai2: sai2grp {
+               fsl,pins = <
+                       MX6UL_PAD_JTAG_TCK__SAI2_RX_DATA        0x130b0
+                       MX6UL_PAD_JTAG_TMS__CCM_CLKO1           0x4001b031
+                       MX6UL_PAD_JTAG_TDI__SAI2_TX_BCLK        0x17088
+                       MX6UL_PAD_JTAG_TDO__SAI2_TX_SYNC        0x17088
+                       MX6UL_PAD_JTAG_TRST_B__SAI2_TX_DATA     0x120b0
+               >;
+       };
+
        pinctrl_uart1: uart1grp {
                fsl,pins = <
                        MX6UL_PAD_UART1_TX_DATA__UART1_DCE_TX 0x1b0b1
index 373ee19196a675f51f683ea0a4aa99c6d030cceb..18bebd6d8d4714d2107f2d39903ff8b27b9abcee 100644 (file)
        chosen {
                stdout-path = "serial0:115200n8";
        };
+
+       panel: panel {
+               compatible = "edt,et057090dhu";
+               backlight = <&bl>;
+               power-supply = <&reg_3v3>;
+
+               port {
+                       panel_in: endpoint {
+                               remote-endpoint = <&lcdif_out>;
+                       };
+               };
+       };
+
+       reg_3v3: regulator-3v3 {
+               compatible = "regulator-fixed";
+               regulator-name = "3.3V";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+       };
+
+       reg_5v0: regulator-5v0 {
+               compatible = "regulator-fixed";
+               regulator-name = "5V";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+       };
 };
 
 &bl {
        brightness-levels = <0 4 8 16 32 64 128 255>;
        default-brightness-level = <6>;
+       power-supply = <&reg_3v3>;
+
        status = "okay";
 };
 
 };
 
 &lcdif {
-       display = <&display0>;
        status = "okay";
 
-       display0: lcd-display {
-               bits-per-pixel = <16>;
-               bus-width = <18>;
-
-               display-timings {
-                       native-mode = <&timing_vga>;
-
-                       /* Standard VGA timing */
-                       timing_vga: 640x480 {
-                               clock-frequency = <25175000>;
-                               hactive = <640>;
-                               vactive = <480>;
-                               hback-porch = <40>;
-                               hfront-porch = <24>;
-                               vback-porch = <32>;
-                               vfront-porch = <11>;
-                               hsync-len = <96>;
-                               vsync-len = <2>;
-                               de-active = <1>;
-                               hsync-active = <0>;
-                               vsync-active = <0>;
-                               pixelclk-active = <0>;
-                       };
+       port {
+               lcdif_out: endpoint {
+                       remote-endpoint = <&panel_in>;
                };
        };
 };
index a171545478be6ba6eb855016e78a66a0a61d6875..2d87489f9105cf1aa9e3d6f5f2b55bff37551175 100644 (file)
                regulator-max-microvolt = <3300000>;
        };
 
-       reg_vref_1v8: regulator-vref-1v8 {
-               compatible = "regulator-fixed";
-               regulator-name = "vref-1v8";
-               regulator-min-microvolt = <1800000>;
-               regulator-max-microvolt = <1800000>;
-       };
-
        sound {
                compatible = "simple-audio-card";
                simple-audio-card,name = "imx7-sgtl5000";
 };
 
 &adc1 {
-       vref-supply = <&reg_vref_1v8>;
+       vref-supply = <&reg_DCDC3>;
 };
 
 &adc2 {
-       vref-supply = <&reg_vref_1v8>;
+       vref-supply = <&reg_DCDC3>;
 };
 
 &cpu0 {
 
                regulators {
                        reg_DCDC1: DCDC1 {  /* V1.0_SOC */
-                               regulator-min-microvolt =  <975000>;
-                               regulator-max-microvolt = <1125000>;
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1100000>;
                                regulator-boot-on;
                                regulator-always-on;
                        };
 
                        reg_DCDC2: DCDC2 { /* V1.1_ARM */
-                               regulator-min-microvolt =  <975000>;
-                               regulator-max-microvolt = <1125000>;
+                               regulator-min-microvolt = <975000>;
+                               regulator-max-microvolt = <1100000>;
                                regulator-boot-on;
                                regulator-always-on;
                        };
 
                        reg_DCDC3: DCDC3 { /* V1.8 */
-                               regulator-min-microvolt = <1775000>;
-                               regulator-max-microvolt = <1825000>;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
                                regulator-boot-on;
                                regulator-always-on;
                        };
 
                        reg_DCDC4: DCDC4 { /* V1.35_DRAM */
-                               regulator-min-microvolt = <1325000>;
-                               regulator-max-microvolt = <1375000>;
+                               regulator-min-microvolt = <1350000>;
+                               regulator-max-microvolt = <1350000>;
                                regulator-boot-on;
                                regulator-always-on;
                        };
                        reg_LDO1: LDO1 { /* PWR_EN_+V3.3_ETH */
                                regulator-min-microvolt = <1800000>;
                                regulator-max-microvolt = <3300000>;
-                               regulator-always-on;
+                               regulator-boot-on;
                        };
 
                        reg_LDO2: LDO2 { /* +V1.8_SD */
-                               regulator-min-microvolt = <1775000>;
-                               regulator-max-microvolt = <3325000>;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3300000>;
                                regulator-boot-on;
                                regulator-always-on;
                        };
 
                        reg_LDO3: LDO3 { /* PWR_EN_+V3.3_LPSR */
-                               regulator-min-microvolt = <3275000>;
-                               regulator-max-microvolt = <3325000>;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
                                regulator-boot-on;
                                regulator-always-on;
                        };
 
                        reg_LDO4: LDO4 { /* V1.8_LPSR */
-                               regulator-min-microvolt = <1775000>;
-                               regulator-max-microvolt = <1825000>;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
                                regulator-boot-on;
                                regulator-always-on;
                        };
 
                        reg_LDO5: LDO5 { /* PWR_EN_+V3.3 */
-                               regulator-min-microvolt = <1775000>;
-                               regulator-max-microvolt = <1825000>;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
                                regulator-boot-on;
                                regulator-always-on;
                        };
index bd01d2cc642d8e947896fd881d78e4653587a28c..a608a14d8c8556afbb5f8bf92157250117af82d2 100644 (file)
@@ -57,6 +57,7 @@
                regulator-min-microvolt = <5000000>;
                regulator-max-microvolt = <5000000>;
                gpio = <&gpio4 7 GPIO_ACTIVE_LOW>;
+               vin-supply = <&reg_5v0>;
        };
 };
 
diff --git a/arch/arm/boot/dts/imx7d-sdb-sht11.dts b/arch/arm/boot/dts/imx7d-sdb-sht11.dts
new file mode 100644 (file)
index 0000000..64a20ed
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2015 Freescale Semiconductor, Inc.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "imx7d-sdb.dts"
+
+/ {
+       sensor {
+               pinctrl-names = "default";
+               pinctrl-0 = <&pinctrl_sensor>;
+               compatible = "sensirion,sht15";
+               clk-gpios = <&gpio4 12 0>;
+               data-gpios = <&gpio4 13 0>;
+               vcc-supply = <&reg_sht15>;
+       };
+
+       reg_sht15: regulator-sht15 {
+               compatible = "regulator-fixed";
+               regulator-name = "reg_sht15";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+       };
+};
+
+&i2c3 {
+       status = "disabled";
+};
+
+&iomuxc {
+       pinctrl_sensor: sensorgrp {
+               fsl,pins = <
+                       MX7D_PAD_I2C3_SDA__GPIO4_IO13   0x4000007f
+                       MX7D_PAD_I2C3_SCL__GPIO4_IO12   0x4000007f
+               >;
+       };
+};
index 5d3a43b8de20704fe8d334366d063d7675821f34..c4f12fd2e044e44d325eca5776748288d04d0885 100644 (file)
                        };
 
                        ocotp: ocotp-ctrl@30350000 {
-                               compatible = "syscon";
+                               compatible = "fsl,imx7d-ocotp", "syscon";
                                reg = <0x30350000 0x10000>;
-                               clocks = <&clks IMX7D_CLK_DUMMY>;
-                               status = "disabled";
+                               clocks = <&clks IMX7D_OCOTP_CLK>;
                        };
 
                        anatop: anatop@30360000 {
                        };
 
                        src: src@30390000 {
-                               compatible = "fsl,imx7d-src", "fsl,imx51-src", "syscon";
+                               compatible = "fsl,imx7d-src", "syscon";
                                reg = <0x30390000 0x10000>;
                                interrupts = <GIC_SPI 89 IRQ_TYPE_LEVEL_HIGH>;
                                #reset-cells = <1>;
diff --git a/arch/arm/boot/dts/include/dt-bindings b/arch/arm/boot/dts/include/dt-bindings
deleted file mode 120000 (symlink)
index 08c00e4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../include/dt-bindings
\ No newline at end of file
index 08cce17a25a01f460fd199f5f380bb3c907e20ed..43e9364083de84383a34815c04a6bd1021b3baa0 100644 (file)
                        OMAP3_CORE1_IOPAD(0x2110, PIN_INPUT | MUX_MODE0)   /* cam_xclka.cam_xclka */
                        OMAP3_CORE1_IOPAD(0x2112, PIN_INPUT | MUX_MODE0)   /* cam_pclk.cam_pclk */
 
-                       OMAP3_CORE1_IOPAD(0x2114, PIN_INPUT | MUX_MODE0)   /* cam_d0.cam_d0 */
-                       OMAP3_CORE1_IOPAD(0x2116, PIN_INPUT | MUX_MODE0)   /* cam_d1.cam_d1 */
-                       OMAP3_CORE1_IOPAD(0x2118, PIN_INPUT | MUX_MODE0)   /* cam_d2.cam_d2 */
+                       OMAP3_CORE1_IOPAD(0x2116, PIN_INPUT | MUX_MODE0)   /* cam_d0.cam_d0 */
+                       OMAP3_CORE1_IOPAD(0x2118, PIN_INPUT | MUX_MODE0)   /* cam_d1.cam_d1 */
+                       OMAP3_CORE1_IOPAD(0x211a, PIN_INPUT | MUX_MODE0)   /* cam_d2.cam_d2 */
                        OMAP3_CORE1_IOPAD(0x211c, PIN_INPUT | MUX_MODE0)   /* cam_d3.cam_d3 */
                        OMAP3_CORE1_IOPAD(0x211e, PIN_INPUT | MUX_MODE0)   /* cam_d4.cam_d4 */
                        OMAP3_CORE1_IOPAD(0x2120, PIN_INPUT | MUX_MODE0)   /* cam_d5.cam_d5 */
index 45619f6162c56a6260b7d832678b4cc94b019de0..ebc763eab195a7dcc8307ecfad23b4b238106f8b 100644 (file)
                        reg-names = "mux", "pull", "pull-enable", "gpio";
                        gpio-controller;
                        #gpio-cells = <2>;
+                       gpio-ranges = <&pinctrl_cbus 0 0 120>;
                };
 
                spi_nor_pins: nor {
                        reg-names = "mux", "pull", "gpio";
                        gpio-controller;
                        #gpio-cells = <2>;
+                       gpio-ranges = <&pinctrl_aobus 0 120 16>;
                };
 
                uart_ao_a_pins: uart_ao_a {
index 41fd53671859cd162073fb21b6ec67c8546691bd..828aa49c678cd4bc484648d6dd339b9f515a2f11 100644 (file)
                                reg-names = "mux", "pull", "pull-enable", "gpio";
                                gpio-controller;
                                #gpio-cells = <2>;
+                               gpio-ranges = <&pinctrl_cbus 0 0 130>;
                        };
                };
 
                                reg-names = "mux", "pull", "gpio";
                                gpio-controller;
                                #gpio-cells = <2>;
+                               gpio-ranges = <&pinctrl_aobus 0 130 16>;
                        };
 
                        uart_ao_a_pins: uart_ao_a {
diff --git a/arch/arm/boot/dts/motorola-cpcap-mapphone.dtsi b/arch/arm/boot/dts/motorola-cpcap-mapphone.dtsi
new file mode 100644 (file)
index 0000000..f5aeb39
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * Common CPCAP configuration used on Motorola phones
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+&mcspi1 {
+       cpcap: pmic@0 {
+               compatible = "motorola,cpcap", "st,6556002";
+               reg = <0>;      /* cs0 */
+               interrupt-parent = <&gpio1>;
+               interrupts = <7 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-controller;
+               #interrupt-cells = <2>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               spi-max-frequency = <3000000>;
+               spi-cs-high;
+
+               cpcap_adc: adc {
+                       compatible = "motorola,mapphone-cpcap-adc";
+                       interrupts-extended = <&cpcap 8 0>;
+                       interrupt-names = "adcdone";
+                       #io-channel-cells = <1>;
+               };
+
+               cpcap_charger: charger {
+                       compatible = "motorola,mapphone-cpcap-charger";
+                       interrupts-extended = <
+                               &cpcap 13 0 &cpcap 12 0 &cpcap 29 0 &cpcap 28 0
+                               &cpcap 22 0 &cpcap 20 0 &cpcap 19 0 &cpcap 54 0
+                       >;
+                       interrupt-names =
+                               "chrg_det", "rvrs_chrg", "chrg_se1b", "se0conn",
+                               "rvrs_mode", "chrgcurr1", "vbusvld", "battdetb";
+                       mode-gpios = <&gpio3 29 GPIO_ACTIVE_LOW
+                                     &gpio3 23 GPIO_ACTIVE_LOW>;
+                       io-channels = <&cpcap_adc 0 &cpcap_adc 1
+                                      &cpcap_adc 2 &cpcap_adc 5
+                                      &cpcap_adc 6>;
+                       io-channel-names = "battdetb", "battp",
+                                          "vbus", "chg_isense",
+                                          "batti";
+               };
+
+               cpcap_regulator: regulator {
+                       compatible = "motorola,mapphone-cpcap-regulator";
+
+                       cpcap_regulators: regulators {
+                       };
+               };
+
+               cpcap_rtc: rtc {
+                       compatible = "motorola,cpcap-rtc";
+
+                       interrupt-parent = <&cpcap>;
+                       interrupts = <39 IRQ_TYPE_NONE>, <26 IRQ_TYPE_NONE>;
+               };
+
+               power_button: button {
+                       compatible = "motorola,cpcap-pwrbutton";
+
+                       interrupts = <23 IRQ_TYPE_NONE>;
+               };
+
+               cpcap_usb2_phy: phy {
+                       compatible = "motorola,mapphone-cpcap-usb-phy";
+                       pinctrl-0 = <&usb_gpio_mux_sel1 &usb_gpio_mux_sel2>;
+                       pinctrl-1 = <&usb_ulpi_pins>;
+                       pinctrl-2 = <&usb_utmi_pins>;
+                       pinctrl-3 = <&uart3_pins>;
+                       pinctrl-names = "default", "ulpi", "utmi", "uart";
+                       #phy-cells = <0>;
+                       interrupts-extended = <
+                               &cpcap 15 0 &cpcap 14 0 &cpcap 28 0 &cpcap 19 0
+                               &cpcap 18 0 &cpcap 17 0 &cpcap 16 0 &cpcap 49 0
+                               &cpcap 48 1
+                       >;
+                       interrupt-names =
+                               "id_ground", "id_float", "se0conn", "vbusvld",
+                               "sessvld", "sessend", "se1", "dm", "dp";
+                       mode-gpios = <&gpio2 28 GPIO_ACTIVE_HIGH
+                                     &gpio1 0 GPIO_ACTIVE_HIGH>;
+                       io-channels = <&cpcap_adc 2>, <&cpcap_adc 7>;
+                       io-channel-names = "vbus", "id";
+                       vusb-supply = <&vusb>;
+               };
+
+               led_red: led-red {
+                       compatible = "motorola,cpcap-led-red";
+                       vdd-supply = <&sw5>;
+                       label = "status-led:red";
+               };
+
+               led_green: led-green {
+                       compatible = "motorola,cpcap-led-green";
+                       vdd-supply = <&sw5>;
+                       label = "status-led:green";
+               };
+
+               led_blue: led-blue {
+                       compatible = "motorola,cpcap-led-blue";
+                       vdd-supply = <&sw5>;
+                       label = "status-led:blue";
+               };
+
+               led_adl: led-adl {
+                       compatible = "motorola,cpcap-led-adl";
+                       vdd-supply = <&sw5>;
+                       label = "button-backlight";
+               };
+
+               led_cp: led-cp {
+                       compatible = "motorola,cpcap-led-cp";
+                       vdd-supply = <&sw5>;
+                       label = "shift-key-light";
+               };
+       };
+};
+
+&cpcap_regulators {
+       sw5: SW5 {
+               regulator-min-microvolt = <5050000>;
+               regulator-max-microvolt = <5050000>;
+               regulator-enable-ramp-delay = <50000>;
+               regulator-boot-on;
+       };
+
+       vcam: VCAM {
+               regulator-min-microvolt = <2900000>;
+               regulator-max-microvolt = <2900000>;
+               regulator-enable-ramp-delay = <1000>;
+       };
+
+       /* Used by DSS */
+       vcsi: VCSI {
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               regulator-enable-ramp-delay = <1000>;
+               regulator-boot-on;
+       };
+
+       vdac: VDAC {
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               regulator-enable-ramp-delay = <1000>;
+       };
+
+       vdig: VDIG {
+               regulator-min-microvolt = <1875000>;
+               regulator-max-microvolt = <1875000>;
+               regulator-enable-ramp-delay = <1000>;
+       };
+
+       vfuse: VFUSE {
+               regulator-min-microvolt = <1500000>;
+               regulator-max-microvolt = <3150000>;
+               regulator-enable-ramp-delay = <1000>;
+       };
+
+       vhvio: VHVIO {
+               regulator-min-microvolt = <2775000>;
+               regulator-max-microvolt = <2775000>;
+               regulator-enable-ramp-delay = <1000>;
+               regulator-always-on;
+       };
+
+       /* Used by eMMC at mmc2 */
+       vsdio: VSDIO {
+               regulator-min-microvolt = <2900000>;
+               regulator-max-microvolt = <2900000>;
+               regulator-enable-ramp-delay = <1000>;
+       };
+
+       vpll: VPLL {
+               regulator-min-microvolt = <1200000>;
+               regulator-max-microvolt = <1800000>;
+               regulator-enable-ramp-delay = <100>;
+       };
+
+       vrf1: VRF1 {
+               regulator-min-microvolt = <2775000>;
+               regulator-max-microvolt = <2775000>;
+               regulator-enable-ramp-delay = <1000>;
+       };
+
+       vrf2: VRF2 {
+               regulator-min-microvolt = <2775000>;
+               regulator-max-microvolt = <2775000>;
+               regulator-enable-ramp-delay = <1000>;
+       };
+
+       vrfref: VRFREF {
+               regulator-min-microvolt = <2500000>;
+               regulator-max-microvolt = <2775000>;
+               regulator-enable-ramp-delay = <100>;
+       };
+
+       vwlan1: VWLAN1 {
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1900000>;
+               regulator-enable-ramp-delay = <1000>;
+       };
+
+       /* Used by micro-SDIO at mmc1 */
+       vwlan2: VWLAN2 {
+               regulator-min-microvolt = <3000000>;
+               regulator-max-microvolt = <3000000>;
+               regulator-enable-ramp-delay = <1000>;
+       };
+
+       vsim: VSIM {
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <2900000>;
+               regulator-enable-ramp-delay = <1000>;
+       };
+
+       vsimcard: VSIMCARD {
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <2900000>;
+               regulator-enable-ramp-delay = <1000>;
+       };
+
+       vvib: VVIB {
+               regulator-min-microvolt = <1300000>;
+               regulator-max-microvolt = <3000000>;
+               regulator-enable-ramp-delay = <500>;
+       };
+
+       vusb: VUSB {
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-enable-ramp-delay = <1000>;
+       };
+
+       vaudio: VAUDIO {
+               regulator-min-microvolt = <2775000>;
+               regulator-max-microvolt = <2775000>;
+               regulator-enable-ramp-delay = <1000>;
+       };
+};
index 10d088df0c35177a573bd695337ac1010a2dc138..4a962a26482df2796b1627e304ea743f5ae32680 100644 (file)
@@ -6,7 +6,7 @@
  */
 
 /dts-v1/;
-/include/ "moxart.dtsi"
+#include "moxart.dtsi"
 
 / {
        model = "MOXA UC-7112-LX";
index 1fd27ed65a01fc868d918a2a593534153bd45415..e86f8c905ac57ba1bb01af25ca98e785b640b4b6 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 /include/ "skeleton.dtsi"
+#include <dt-bindings/interrupt-controller/irq.h>
 
 / {
        compatible = "moxa,moxart";
@@ -36,8 +37,8 @@
                ranges;
 
                intc: interrupt-controller@98800000 {
-                       compatible = "moxa,moxart-ic";
-                       reg = <0x98800000 0x38>;
+                       compatible = "moxa,moxart-ic", "faraday,ftintc010";
+                       reg = <0x98800000 0x100>;
                        interrupt-controller;
                        #interrupt-cells = <2>;
                        interrupt-mask = <0x00080000>;
                timer: timer@98400000 {
                        compatible = "moxa,moxart-timer";
                        reg = <0x98400000 0x42>;
-                       interrupts = <19 1>;
+                       interrupts = <19 IRQ_TYPE_EDGE_FALLING>;
                        clocks = <&clk_apb>;
                };
 
                gpio: gpio@98700000 {
                        gpio-controller;
                        #gpio-cells = <2>;
-                       compatible = "moxa,moxart-gpio";
-                       reg = <0x98700000 0xC>;
+                       compatible = "moxa,moxart-gpio", "faraday,ftgpio010";
+                       reg = <0x98700000 0x100>;
                };
 
                rtc: rtc {
@@ -80,7 +81,7 @@
                dma: dma@90500000 {
                        compatible = "moxa,moxart-dma";
                        reg = <0x90500080 0x40>;
-                       interrupts = <24 0>;
+                       interrupts = <24 IRQ_TYPE_LEVEL_HIGH>;
                        #dma-cells = <1>;
                };
 
@@ -93,7 +94,7 @@
                sdhci: sdhci@98e00000 {
                        compatible = "moxa,moxart-sdhci";
                        reg = <0x98e00000 0x5C>;
-                       interrupts = <5 0>;
+                       interrupts = <5 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&clk_apb>;
                        dmas =  <&dma 5>,
                                <&dma 5>;
                mac0: mac@90900000 {
                        compatible = "moxa,moxart-mac";
                        reg = <0x90900000 0x90>;
-                       interrupts = <25 0>;
+                       interrupts = <25 IRQ_TYPE_LEVEL_HIGH>;
                        phy-handle = <&ethphy0>;
                        phy-mode = "mii";
                        status = "disabled";
                mac1: mac@92000000 {
                        compatible = "moxa,moxart-mac";
                        reg = <0x92000000 0x90>;
-                       interrupts = <27 0>;
+                       interrupts = <27 IRQ_TYPE_LEVEL_HIGH>;
                        phy-handle = <&ethphy1>;
                        phy-mode = "mii";
                        status = "disabled";
                uart0: uart@98200000 {
                        compatible = "ns16550a";
                        reg = <0x98200000 0x20>;
-                       interrupts = <31 8>;
+                       interrupts = <31 IRQ_TYPE_LEVEL_HIGH>;
                        reg-shift = <2>;
                        reg-io-width = <4>;
                        clock-frequency = <14745600>;
index 402579ab70d2b94a21f58fd8bea2eeb1885a9072..3a9e9b6aea6892784a3379fd39fb562c0869a0ba 100644 (file)
@@ -72,6 +72,8 @@
                             <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 = <13000000>;
+               arm,cpu-registers-not-fw-configured;
        };
 
        watchdog: watchdog@10007000 {
diff --git a/arch/arm/boot/dts/omap3-cpu-thermal.dtsi b/arch/arm/boot/dts/omap3-cpu-thermal.dtsi
new file mode 100644 (file)
index 0000000..235ecfd
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Device Tree Source for OMAP3 SoC CPU thermal
+ *
+ * Copyright (C) 2017 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2.  This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#include <dt-bindings/thermal/thermal.h>
+
+cpu_thermal: cpu_thermal {
+       polling-delay-passive = <250>; /* milliseconds */
+       polling-delay = <1000>; /* milliseconds */
+       coefficients = <0 20000>;
+
+                       /* sensor       ID */
+       thermal-sensors = <&bandgap     0>;
+};
index b3a8b1f24499afe232d752ba16e15e45e4280d5b..9ec737069369672f6b52b26df840636cce768761 100644 (file)
@@ -55,7 +55,8 @@
                simple-audio-card,bitclock-master = <&telephony_link_master>;
                simple-audio-card,frame-master = <&telephony_link_master>;
                simple-audio-card,format = "i2s";
-
+               simple-audio-card,bitclock-inversion;
+               simple-audio-card,frame-inversion;
                simple-audio-card,cpu {
                        sound-dai = <&mcbsp4>;
                };
index e268efde6c6d36f68ac1a8e5f71a1c0c406b3aff..4ad7d5565906efcb04f29c1c5c795c20f5fa4410 100644 (file)
 };
 
 &omap3_pmx_core {
+       gpmc_pins: pinmux_gpmc_pins {
+               pinctrl-single,pins = <
+                       /* OneNAND seems to require PIN_INPUT on clock. */
+                        OMAP3_CORE1_IOPAD(0x20be, PIN_INPUT | MUX_MODE0)        /* gpmc_clk.gpmc_clk */
+               >;
+       };
+
        uart1_pins: pinmux_uart1_pins {
                pinctrl-single,pins = <
                        OMAP3_CORE1_IOPAD(0x2182, PIN_INPUT | MUX_MODE0)        /* uart1_rx.uart1_rx */
 };
 
 &gpmc {
+       pinctrl-names = "default";
+       pinctrl-0 = <&gpmc_pins>;
+
        nand@0,0 {
                compatible = "ti,omap2-nand";
                reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
 
                #address-cells = <1>;
                #size-cells = <1>;
+
+               status = "okay";
+       };
+
+       onenand@0,0 {
+               compatible = "ti,omap2-onenand";
+               reg = <0 0 0x20000>;    /* CS0, offset 0, IO size 128K */
+
+               gpmc,sync-read;
+               gpmc,sync-write;
+               gpmc,burst-length = <16>;
+               gpmc,burst-read;
+               gpmc,burst-wrap;
+               gpmc,burst-write;
+               gpmc,device-width = <2>; /* GPMC_DEVWIDTH_16BIT */
+               gpmc,mux-add-data = <2>; /* GPMC_MUX_AD */
+               gpmc,cs-on-ns = <0>;
+               gpmc,cs-rd-off-ns = <87>;
+               gpmc,cs-wr-off-ns = <87>;
+               gpmc,adv-on-ns = <0>;
+               gpmc,adv-rd-off-ns = <10>;
+               gpmc,adv-wr-off-ns = <10>;
+               gpmc,oe-on-ns = <15>;
+               gpmc,oe-off-ns = <87>;
+               gpmc,we-on-ns = <0>;
+               gpmc,we-off-ns = <87>;
+               gpmc,rd-cycle-ns = <112>;
+               gpmc,wr-cycle-ns = <112>;
+               gpmc,access-ns = <81>;
+               gpmc,page-burst-access-ns = <15>;
+               gpmc,bus-turnaround-ns = <0>;
+               gpmc,cycle2cycle-delay-ns = <0>;
+               gpmc,wait-monitoring-ns = <0>;
+               gpmc,clk-activation-ns = <5>;
+               gpmc,wr-data-mux-bus-ns = <30>;
+               gpmc,wr-access-ns = <81>;
+               gpmc,sync-clk-ps = <15000>;
+
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               status = "disabled";
        };
 };
 
index b64cfda8dbb73d9518fe72e79427e0a0e90a9a43..49f37084e43507b1f2b87b11d79eecacfe0599dc 100644 (file)
                compatible = "nokia,n900-ir";
                pwms = <&pwm9 0 26316 0>; /* 38000 Hz */
        };
+
+       /* controlled (enabled/disabled) directly by bcm2048 and wl1251 */
+       vctcxo: vctcxo {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <38400000>;
+       };
 };
 
 &omap3_pmx_core {
 
        uart2_pins: pinmux_uart2_pins {
                pinctrl-single,pins = <
-                       OMAP3_CORE1_IOPAD(0x217a, PIN_INPUT | MUX_MODE0)                /* uart2_rx */
+                       OMAP3_CORE1_IOPAD(0x2174, PIN_INPUT_PULLUP | MUX_MODE0)         /* uart2_cts */
+                       OMAP3_CORE1_IOPAD(0x2176, PIN_OUTPUT | MUX_MODE0)               /* uart2_rts */
                        OMAP3_CORE1_IOPAD(0x2178, PIN_OUTPUT | MUX_MODE0)               /* uart2_tx */
+                       OMAP3_CORE1_IOPAD(0x217a, PIN_INPUT | MUX_MODE0)                /* uart2_rx */
                >;
        };
 
 
                interrupt-parent = <&gpio2>;
                interrupts = <10 IRQ_TYPE_NONE>; /* gpio line 42 */
+
+               clocks = <&vctcxo>;
        };
 };
 
 };
 
 &uart2 {
-       interrupts-extended = <&intc 73 &omap3_pmx_core OMAP3_UART2_RX>;
        pinctrl-names = "default";
        pinctrl-0 = <&uart2_pins>;
+
+       bcm2048: bluetooth {
+               compatible = "brcm,bcm2048-nokia", "nokia,h4p-bluetooth";
+               reset-gpios = <&gpio3 27 GPIO_ACTIVE_LOW>; /* 91 */
+               host-wakeup-gpios = <&gpio4 5 GPIO_ACTIVE_HIGH>; /* 101 */
+               bluetooth-wakeup-gpios = <&gpio2 5 GPIO_ACTIVE_HIGH>; /* 37 */
+               clocks = <&vctcxo>;
+               clock-names = "sysclk";
+       };
 };
 
 &uart3 {
index 5d8c4b4a42058023f91ff5e2fb6ed61b8dde89fb..df3366fa5409be2813086f11d757740c47d2491a 100644 (file)
                        pinctrl-0 = <&debug_leds>;
                };
        };
+
+       /* controlled (enabled/disabled) directly by wl1271 */
+       vctcxo: vctcxo {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <38400000>;
+       };
 };
 
 &omap3_pmx_core {
                        OMAP3_CORE1_IOPAD(0x210a, PIN_OUTPUT | MUX_MODE4)            /* gpio_93 (cmt_apeslpx) */
                >;
        };
+
+       uart2_pins: pinmux_uart2_pins {
+               pinctrl-single,pins = <
+                       OMAP3_CORE1_IOPAD(0x2174, PIN_INPUT_PULLUP | MUX_MODE0)         /* uart2_cts */
+                       OMAP3_CORE1_IOPAD(0x2176, PIN_OUTPUT | MUX_MODE0)               /* uart2_rts */
+                       OMAP3_CORE1_IOPAD(0x2178, PIN_OUTPUT | MUX_MODE0)               /* uart2_tx */
+                       OMAP3_CORE1_IOPAD(0x217a, PIN_INPUT | MUX_MODE0)                /* uart2_rx */
+               >;
+       };
 };
 
 &omap3_pmx_core2 {
 &ssi_port2 {
        status = "disabled";
 };
+
+&uart2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart2_pins>;
+
+       bluetooth {
+               compatible = "ti,wl1271-bluetooth-nokia", "nokia,h4p-bluetooth";
+
+               reset-gpios = <&gpio1 26 GPIO_ACTIVE_LOW>; /* 26 */
+               host-wakeup-gpios = <&gpio4 5 GPIO_ACTIVE_HIGH>; /* 101 */
+               bluetooth-wakeup-gpios = <&gpio2 5 GPIO_ACTIVE_HIGH>; /* 37 */
+
+               clocks = <&vctcxo>;
+               clock-names = "sysclk";
+       };
+};
index 834fdf13601feb261a3660491e3f0480f622c85b..ac4f8795b756f597356d5776475d811f93483e62 100644 (file)
@@ -14,7 +14,7 @@
 
 / {
        cpus {
-               cpu@0 {
+               cpu: cpu@0 {
                        /* OMAP343x/OMAP35xx variants OPP1-5 */
                        operating-points = <
                                /* kHz    uV */
                        };
                };
 
-               bandgap@48002524 {
+               bandgap: bandgap@48002524 {
                        reg = <0x48002524 0x4>;
                        compatible = "ti,omap34xx-bandgap";
                        #thermal-sensor-cells = <0>;
                };
        };
+
+       thermal_zones: thermal-zones {
+               #include "omap3-cpu-thermal.dtsi"
+       };
 };
 
 &ssi {
index d1a3e56b50cebf80c64a243e499d648101a34ddf..ade31d74c70c9aaa30e9963625055265658d4cd4 100644 (file)
@@ -19,7 +19,7 @@
 
        cpus {
                /* OMAP3630/OMAP37xx 'standard device' variants OPP50 to OPP130 */
-               cpu@0 {
+               cpu: cpu@0 {
                        operating-points = <
                                /* kHz    uV */
                                300000  1012500
                        };
                };
 
-               bandgap@48002524 {
+               bandgap: bandgap@48002524 {
                        reg = <0x48002524 0x4>;
                        compatible = "ti,omap36xx-bandgap";
                        #thermal-sensor-cells = <0>;
                };
        };
+
+       thermal_zones: thermal-zones {
+               #include "omap3-cpu-thermal.dtsi"
+       };
 };
 
 /* OMAP3630 needs dss_96m_fck for VENC */
index f3ccb4ceed9e3dd8fa9f3f09a10b15187468db4e..89eb607f4a9e1a6afc33571c626bd8d30251b54a 100644 (file)
@@ -5,7 +5,9 @@
  */
 /dts-v1/;
 
+#include <dt-bindings/input/input.h>
 #include "omap443x.dtsi"
+#include "motorola-cpcap-mapphone.dtsi"
 
 / {
        model = "Motorola Droid 4 XT894";
                stdout-path = &uart3;
        };
 
+       aliases {
+               display0 = &lcd0;
+               display1 = &hdmi0;
+       };
+
        /*
         * We seem to have only 1021 MB accessible, 1021 - 1022 is locked,
-        * then 1023 - 1024 seems to contain mbm. For SRAM, see the notes
-        * below about SRAM and L3_ICLK2 being unused by default,
+        * then 1023 - 1024 seems to contain mbm.
         */
        memory {
                device_type = "memory";
                reg = <0x80000000 0x3fd00000>;  /* 1021 MB */
        };
 
-       /* CPCAP really supports 1650000 to 3400000 range */
-       vmmc: regulator-mmc {
+       /* Poweroff GPIO probably connected to CPCAP */
+       gpio-poweroff {
+               compatible = "gpio-poweroff";
+               pinctrl-0 = <&poweroff_gpio>;
+               pinctrl-names = "default";
+               gpios = <&gpio2 18 GPIO_ACTIVE_LOW>;    /* gpio50 */
+       };
+
+       hdmi0: connector {
+               compatible = "hdmi-connector";
+               pinctrl-0 = <&hdmi_hpd_gpio>;
+               pinctrl-names = "default";
+               label = "hdmi";
+               type = "d";
+
+               hpd-gpios = <&gpio2 31 GPIO_ACTIVE_HIGH>;       /* gpio63 */
+
+               port {
+                       hdmi_connector_in: endpoint {
+                               remote-endpoint = <&hdmi_out>;
+                       };
+               };
+       };
+
+       /*
+        * HDMI 5V regulator probably sourced from battery. Let's keep
+        * keep this as always enabled for HDMI to work until we've
+        * figured what the encoder chip is.
+        */
+       hdmi_regulator: regulator-hdmi {
                compatible = "regulator-fixed";
-               regulator-name = "vmmc";
-               regulator-min-microvolt = <3000000>;
-               regulator-max-microvolt = <3000000>;
+               regulator-name = "hdmi";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               gpio = <&gpio2 27 GPIO_ACTIVE_HIGH>;    /* gpio59 */
+               enable-active-high;
                regulator-always-on;
        };
 
-       /* CPCAP really supports 3000000 to 3100000 range */
-       vemmc: regulator-emmc {
+       /* HS USB Host PHY on PORT 1 */
+       hsusb1_phy: hsusb1_phy {
+               compatible = "usb-nop-xceiv";
+       };
+
+       /* LCD regulator from sw5 source */
+       lcd_regulator: regulator-lcd {
                compatible = "regulator-fixed";
-               regulator-name = "vemmc";
-               regulator-min-microvolt = <3000000>;
-               regulator-max-microvolt = <3000000>;
-               regulator-always-on;
+               regulator-name = "lcd";
+               regulator-min-microvolt = <5050000>;
+               regulator-max-microvolt = <5050000>;
+               gpio = <&gpio4 0 GPIO_ACTIVE_HIGH>;     /* gpio96 */
+               enable-active-high;
+               vin-supply = <&sw5>;
        };
 
-       /* CPCAP really supports 1650000 to 1950000 range */
+       /* This is probably coming straight from the battery.. */
        wl12xx_vmmc: regulator-wl12xx {
                compatible = "regulator-fixed";
                regulator-name = "vwl1271";
                startup-delay-us = <70000>;
                enable-active-high;
        };
+
+       gpio_keys {
+               compatible = "gpio-keys";
+
+               volume_down {
+                       label = "Volume Down";
+                       gpios = <&gpio5 26 GPIO_ACTIVE_LOW>; /* gpio154 */
+                       linux,code = <KEY_VOLUMEDOWN>;
+                       linux,can-disable;
+               };
+
+               slider {
+                       label = "Keypad Slide";
+                       gpios = <&gpio4 26 GPIO_ACTIVE_HIGH>; /* gpio122 */
+                       linux,input-type = <EV_SW>;
+                       linux,code = <SW_KEYPAD_SLIDE>;
+                       linux,can-disable;
+
+               };
+       };
+};
+
+&dss {
+       status = "okay";
+};
+
+&gpio6 {
+       touchscreen_reset {
+               gpio-hog;
+               gpios = <13 0>;
+               output-high;
+               line-name = "touchscreen-reset";
+       };
+};
+
+&dsi1 {
+       status = "okay";
+       vdd-supply = <&vcsi>;
+
+       port {
+               dsi1_out_ep: endpoint {
+                       remote-endpoint = <&lcd0_in>;
+                       lanes = <0 1 2 3 4 5>;
+               };
+       };
+
+       lcd0: display {
+               compatible = "panel-dsi-cm";
+               label = "lcd0";
+               vddi-supply = <&lcd_regulator>;
+               reset-gpios = <&gpio4 5 GPIO_ACTIVE_HIGH>;      /* gpio101 */
+
+               panel-timing {
+                       clock-frequency = <0>;          /* Calculated by dsi */
+
+                       hback-porch = <2>;
+                       hactive = <540>;
+                       hfront-porch = <0>;
+                       hsync-len = <2>;
+
+                       vback-porch = <1>;
+                       vactive = <960>;
+                       vfront-porch = <0>;
+                       vsync-len = <1>;
+
+                       hsync-active = <0>;
+                       vsync-active = <0>;
+                       de-active = <1>;
+                       pixelclk-active = <1>;
+               };
+
+               port {
+                       lcd0_in: endpoint {
+                               remote-endpoint = <&dsi1_out_ep>;
+                       };
+               };
+       };
 };
 
-/* L3_2 interconnect is unused, SRAM, GPMC and L3_ICLK2 disabled */
-&gpmc {
-       status = "disabled";
+&hdmi {
+       status = "okay";
+       pinctrl-0 = <&dss_hdmi_pins>;
+       pinctrl-names = "default";
+       vdda-supply = <&vdac>;
+
+       port {
+               hdmi_out: endpoint {
+                       remote-endpoint = <&hdmi_connector_in>;
+                       lanes = <1 0 3 2 5 4 7 6>;
+               };
+       };
+};
+
+&i2c1 {
+       tmp105@48 {
+               compatible = "ti,tmp105";
+               reg = <0x48>;
+               pinctrl-0 = <&tmp105_irq>;
+               pinctrl-names = "default";
+               /* kpd_row0.gpio_178 */
+               interrupts-extended = <&gpio6 18 IRQ_TYPE_EDGE_FALLING
+                                      &omap4_pmx_core 0x14e>;
+               interrupt-names = "irq", "wakeup";
+               wakeup-source;
+       };
+};
+
+&keypad {
+       keypad,num-rows = <8>;
+       keypad,num-columns = <8>;
+       linux,keymap = <
+
+       /* Row 1 */
+       MATRIX_KEY(0, 2, KEY_1)
+       MATRIX_KEY(0, 6, KEY_2)
+       MATRIX_KEY(2, 3, KEY_3)
+       MATRIX_KEY(0, 7, KEY_4)
+       MATRIX_KEY(0, 4, KEY_5)
+       MATRIX_KEY(5, 5, KEY_6)
+       MATRIX_KEY(0, 1, KEY_7)
+       MATRIX_KEY(0, 5, KEY_8)
+       MATRIX_KEY(0, 0, KEY_9)
+       MATRIX_KEY(1, 6, KEY_0)
+
+       /* Row 2 */
+       MATRIX_KEY(3, 4, KEY_APOSTROPHE)
+       MATRIX_KEY(7, 6, KEY_Q)
+       MATRIX_KEY(7, 7, KEY_W)
+       MATRIX_KEY(7, 2, KEY_E)
+       MATRIX_KEY(1, 0, KEY_R)
+       MATRIX_KEY(4, 4, KEY_T)
+       MATRIX_KEY(1, 2, KEY_Y)
+       MATRIX_KEY(6, 7, KEY_U)
+       MATRIX_KEY(2, 2, KEY_I)
+       MATRIX_KEY(5, 6, KEY_O)
+       MATRIX_KEY(3, 7, KEY_P)
+       MATRIX_KEY(6, 5, KEY_BACKSPACE)
+
+       /* Row 3 */
+       MATRIX_KEY(5, 4, KEY_TAB)
+       MATRIX_KEY(5, 7, KEY_A)
+       MATRIX_KEY(2, 7, KEY_S)
+       MATRIX_KEY(7, 0, KEY_D)
+       MATRIX_KEY(2, 6, KEY_F)
+       MATRIX_KEY(6, 2, KEY_G)
+       MATRIX_KEY(6, 6, KEY_H)
+       MATRIX_KEY(1, 4, KEY_J)
+       MATRIX_KEY(3, 1, KEY_K)
+       MATRIX_KEY(2, 1, KEY_L)
+       MATRIX_KEY(4, 6, KEY_ENTER)
+
+       /* Row 4 */
+       MATRIX_KEY(3, 6, KEY_LEFTSHIFT)         /* KEY_CAPSLOCK */
+       MATRIX_KEY(6, 1, KEY_Z)
+       MATRIX_KEY(7, 4, KEY_X)
+       MATRIX_KEY(5, 1, KEY_C)
+       MATRIX_KEY(1, 7, KEY_V)
+       MATRIX_KEY(2, 4, KEY_B)
+       MATRIX_KEY(4, 1, KEY_N)
+       MATRIX_KEY(1, 1, KEY_M)
+       MATRIX_KEY(3, 5, KEY_COMMA)
+       MATRIX_KEY(5, 2, KEY_DOT)
+       MATRIX_KEY(6, 3, KEY_UP)
+       MATRIX_KEY(7, 3, KEY_OK)
+
+       /* Row 5 */
+       MATRIX_KEY(2, 5, KEY_LEFTCTRL)          /* KEY_LEFTSHIFT */
+       MATRIX_KEY(4, 5, KEY_LEFTALT)           /* SYM */
+       MATRIX_KEY(6, 0, KEY_MINUS)
+       MATRIX_KEY(4, 7, KEY_EQUAL)
+       MATRIX_KEY(1, 5, KEY_SPACE)
+       MATRIX_KEY(3, 2, KEY_SLASH)
+       MATRIX_KEY(4, 3, KEY_LEFT)
+       MATRIX_KEY(5, 3, KEY_DOWN)
+       MATRIX_KEY(3, 3, KEY_RIGHT)
+
+       /* Side buttons, KEY_VOLUMEDOWN and KEY_PWER are on CPCAP? */
+       MATRIX_KEY(5, 0, KEY_VOLUMEUP)
+       >;
 };
 
 &mmc1 {
-       vmmc-supply = <&vmmc>;
+       vmmc-supply = <&vwlan2>;
        bus-width = <4>;
-       cd-gpios = <&gpio4 10 GPIO_ACTIVE_LOW>; /* gpio106 */
+       cd-gpios = <&gpio6 16 GPIO_ACTIVE_LOW>; /* gpio176 */
 };
 
 &mmc2 {
-       vmmc-supply = <&vemmc>;
+       vmmc-supply = <&vsdio>;
        bus-width = <8>;
        non-removable;
 };
        };
 };
 
-/* L3_2 interconnect is unused, SRAM, GPMC and L3_ICLK2 disabled */
-&ocmcram {
-       status = "disabled";
+&i2c1 {
+       lm3532@38 {
+               compatible = "ti,lm3532";
+               reg = <0x38>;
+
+               enable-gpios = <&gpio6 12 GPIO_ACTIVE_HIGH>;
+
+               backlight {
+                       compatible = "ti,lm3532-backlight";
+
+                       lcd {
+                               led-sources = <0 1 2>;
+                               ramp-up-msec = <1>;
+                               ramp-down-msec = <0>;
+                       };
+               };
+       };
+};
+
+/*
+ * REVISIT: Add gpio173 reset pin handling to the driver, see gpio-hog above.
+ * If the GPIO reset is used, we probably need to have /lib/firmware/maxtouch.fw
+ * available. See "mxt-app" and "droid4-touchscreen-firmware" tools for more
+ * information.
+ */
+&i2c2 {
+       tsp@4a {
+               compatible = "atmel,maxtouch";
+               reg = <0x4a>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&touchscreen_pins>;
+
+               /* gpio_183 with sys_nirq2 pad as wakeup */
+               interrupts-extended = <&gpio6 23 IRQ_TYPE_EDGE_FALLING
+                                      &omap4_pmx_core 0x160>;
+               interrupt-names = "irq", "wakeup";
+               wakeup-source;
+       };
 };
 
 &omap4_pmx_core {
+
+       /* hdmi_hpd.gpio_63 */
+       hdmi_hpd_gpio: pinmux_hdmi_hpd_pins {
+               pinctrl-single,pins = <
+               OMAP4_IOPAD(0x098, PIN_INPUT | MUX_MODE3)
+               >;
+       };
+
+       /* hdmi_cec.hdmi_cec, hdmi_scl.hdmi_scl, hdmi_sda.hdmi_sda */
+       dss_hdmi_pins: pinmux_dss_hdmi_pins {
+               pinctrl-single,pins = <
+               OMAP4_IOPAD(0x09a, PIN_INPUT_PULLUP | MUX_MODE0)
+               OMAP4_IOPAD(0x09c, PIN_INPUT | MUX_MODE0)
+               OMAP4_IOPAD(0x09e, PIN_INPUT | MUX_MODE0)
+               >;
+       };
+
+       /* gpmc_ncs0.gpio_50 */
+       poweroff_gpio: pinmux_poweroff_pins {
+               pinctrl-single,pins = <
+               OMAP4_IOPAD(0x074, PIN_OUTPUT_PULLUP | MUX_MODE3)
+               >;
+       };
+
+       /* kpd_row0.gpio_178 */
+       tmp105_irq: pinmux_tmp105_irq {
+               pinctrl-single,pins = <
+               OMAP4_IOPAD(0x18e, PIN_INPUT_PULLUP | MUX_MODE3)
+               >;
+       };
+
        usb_gpio_mux_sel1: pinmux_usb_gpio_mux_sel1_pins {
                /* gpio_60 */
                pinctrl-single,pins = <
                >;
        };
 
+       touchscreen_pins: pinmux_touchscreen_pins {
+               pinctrl-single,pins = <
+               OMAP4_IOPAD(0x1a0, PIN_INPUT_PULLUP | MUX_MODE3)
+               >;
+       };
+
        usb_ulpi_pins: pinmux_usb_ulpi_pins {
                pinctrl-single,pins = <
                OMAP4_IOPAD(0x196, MUX_MODE7)
                               &omap4_pmx_core 0x17c>;
 };
 
+&usbhsehci {
+       phys = <&hsusb1_phy>;
+};
+
+&usbhshost {
+       port1-mode = "ohci-phy-4pin-dpdm";
+       port2-mode = "ehci-tll";
+};
+
 /* Internal UTMI+ PHY used for OTG, CPCAP ULPI PHY for detection and charger */
 &usb_otg_hs {
        interface-type = <1>;
        mode = <3>;
        power = <50>;
 };
+
+&i2c4 {
+       ak8975: magnetometer@c {
+               compatible = "asahi-kasei,ak8975";
+               reg = <0x0c>;
+
+               vdd-supply = <&vhvio>;
+
+               interrupt-parent = <&gpio6>;
+               interrupts = <15 IRQ_TYPE_EDGE_RISING>; /* gpio175 */
+
+               rotation-matrix = "-1", "0", "0",
+                                 "0", "1", "0",
+                                 "0", "0", "-1";
+
+       };
+
+       lis3dh: accelerometer@18 {
+               compatible = "st,lis3dh-accel";
+               reg = <0x18>;
+
+               vdd-supply = <&vhvio>;
+
+               interrupt-parent = <&gpio2>;
+               interrupts = <2 IRQ_TYPE_EDGE_BOTH>; /* gpio34 */
+
+               rotation-matrix = "0", "-1", "0",
+                                 "1", "0", "0",
+                                 "0", "0", "1";
+       };
+};
index 78d3631777629b8422deac792a6d2e6f1c655e7c..f1a6476af3716489007c12141d06f208ec2ebc94 100644 (file)
@@ -13,7 +13,7 @@
 /* Pandaboard Rev A4+ have external pullups on SCL & SDA */
 &dss_hdmi_pins {
        pinctrl-single,pins = <
-               OMAP4_IOPAD(0x09a, PIN_INPUT_PULLUP | MUX_MODE0)        /* hdmi_cec.hdmi_cec */
+               OMAP4_IOPAD(0x09a, PIN_INPUT | MUX_MODE0)               /* hdmi_cec.hdmi_cec */
                OMAP4_IOPAD(0x09c, PIN_INPUT | MUX_MODE0)               /* hdmi_scl.hdmi_scl */
                OMAP4_IOPAD(0x09e, PIN_INPUT | MUX_MODE0)               /* hdmi_sda.hdmi_sda */
                >;
index 119f8e657edc9bae37089588968b660c9c3749da..940fe4f7c5f6e148a1e22e7b2daaadc91c627c10 100644 (file)
@@ -34,7 +34,7 @@
 /* PandaboardES has external pullups on SCL & SDA */
 &dss_hdmi_pins {
        pinctrl-single,pins = <
-               OMAP4_IOPAD(0x09a, PIN_INPUT_PULLUP | MUX_MODE0)        /* hdmi_cec.hdmi_cec */
+               OMAP4_IOPAD(0x09a, PIN_INPUT | MUX_MODE0)               /* hdmi_cec.hdmi_cec */
                OMAP4_IOPAD(0x09c, PIN_INPUT | MUX_MODE0)               /* hdmi_scl.hdmi_scl */
                OMAP4_IOPAD(0x09e, PIN_INPUT | MUX_MODE0)               /* hdmi_sda.hdmi_sda */
                >;
index fc6a8610c24c583b34e2a57c025cdbbed5b2e8c5..03c8ad91ddac919932282f6cb5bb681031f5a0d8 100644 (file)
@@ -71,4 +71,8 @@
 
 };
 
+&cpu_thermal {
+       coefficients = <0 20000>;
+};
+
 /include/ "omap443x-clocks.dtsi"
index ef66e12e0a67a281da15df0f99c04700ecf3e5cb..c43f2a2d0a1e26c9b6024a3c5c74b98bdbe92cb6 100644 (file)
@@ -90,4 +90,8 @@
 
 };
 
+&cpu_thermal {
+       coefficients = <348 (-9301)>;
+};
+
 /include/ "omap446x-clocks.dtsi"
index 222155ca8ad7d768af6de5ab71f29f1853f5d116..eaff2a5751ddc11c5b1ec901a60c6f7c671aabac 100644 (file)
 
 &cpu_thermal {
        polling-delay = <500>; /* milliseconds */
+       coefficients = <65 (-1791)>;
 };
 
 /include/ "omap54xx-clocks.dtsi"
+
+&gpu_thermal {
+       coefficients = <117 (-2992)>;
+};
+
+&core_thermal {
+       coefficients = <0 2000>;
+};
index 39d9e6ddefedbbc4d1d82f2bf99ba9c2a785f32f..2da1413f5720bd264e93c5280333de935779b26f 100644 (file)
                                             function = "sdc1";
                                };
                                clk {
-                                       pins = "gpio167"; /* SDC5 CLK */
+                                       pins = "gpio167"; /* SDC1 CLK */
                                        drive-strength = <16>;
                                        bias-disable;
                                };
                                cmd {
-                                       pins = "gpio168"; /* SDC5 CMD */
+                                       pins = "gpio168"; /* SDC1 CMD */
                                        drive-strength = <10>;
                                        bias-pull-up;
                                };
                                data {
-                                       /* SDC5 D0 to D7 */
+                                       /* SDC1 D0 to D7 */
                                        pins = "gpio159", "gpio160", "gpio161", "gpio162",
                                             "gpio163", "gpio164", "gpio165", "gpio166";
                                        drive-strength = <10>;
index 91c9a62ae7250184147c9750e417d39f54915827..747669a62aa82ff9520b9f3d0bb1f9210b7714c5 100644 (file)
                                cap-mmc-highspeed;
                        };
 
+                       sdcc2: sdcc@12140000 {
+                               status          = "disabled";
+                               compatible      = "arm,pl18x", "arm,primecell";
+                               arm,primecell-periphid = <0x00051180>;
+                               reg             = <0x12140000 0x8000>;
+                               interrupts      = <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-names = "cmd_irq";
+                               clocks          = <&gcc SDC2_CLK>, <&gcc SDC2_H_CLK>;
+                               clock-names     = "mclk", "apb_pclk";
+                               bus-width       = <8>;
+                               max-frequency   = <48000000>;
+                               cap-sd-highspeed;
+                               cap-mmc-highspeed;
+                       };
+
                        sdcc3: sdcc@12180000 {
                                compatible      = "arm,pl18x", "arm,primecell";
                                arm,primecell-periphid = <0x00051180>;
                                no-1-8-v;
                        };
 
+                       sdcc4: sdcc@121c0000 {
+                               compatible      = "arm,pl18x", "arm,primecell";
+                               arm,primecell-periphid = <0x00051180>;
+                               status          = "disabled";
+                               reg             = <0x121c0000 0x8000>;
+                               interrupts      = <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-names = "cmd_irq";
+                               clocks          = <&gcc SDC4_CLK>, <&gcc SDC4_H_CLK>;
+                               clock-names     = "mclk", "apb_pclk";
+                               bus-width       = <4>;
+                               max-frequency   = <48000000>;
+                               cap-sd-highspeed;
+                               cap-mmc-highspeed;
+                       };
+
                        sdcc5: sdcc@12200000 {
                                compatible      = "arm,pl18x", "arm,primecell";
                                arm,primecell-periphid = <0x00051180>;
index 96c853bab8babe174169768fba59ce8951d10549..e7c1577d56f4812663afc7bbb4ad262743139bf5 100644 (file)
        dma-controller@f9944000 {
                qcom,controlled-remotely;
        };
-
-       usb-phy@f9a55000 {
-               status = "ok";
-       };
-
-       usb@f9a55000 {
-               status = "ok";
-       };
 };
 
 &spmi_bus {
index d3e1a61b86710ee017adec7c243e5ce2878d0252..307bf6a647b30a423c7c746e493584ea27bbdbb6 100644 (file)
@@ -2,8 +2,8 @@
 
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/clock/qcom,gcc-msm8974.h>
+#include <dt-bindings/clock/qcom,rpmcc.h>
 #include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/reset/qcom,gcc-msm8974.h>
 #include "skeleton.dtsi"
 
 / {
@@ -67,7 +67,7 @@
                #size-cells = <0>;
                interrupts = <1 9 0xf04>;
 
-               cpu@0 {
+               CPU0: cpu@0 {
                        compatible = "qcom,krait";
                        enable-method = "qcom,kpss-acc-v2";
                        device_type = "cpu";
@@ -78,7 +78,7 @@
                        cpu-idle-states = <&CPU_SPC>;
                };
 
-               cpu@1 {
+               CPU1: cpu@1 {
                        compatible = "qcom,krait";
                        enable-method = "qcom,kpss-acc-v2";
                        device_type = "cpu";
@@ -89,7 +89,7 @@
                        cpu-idle-states = <&CPU_SPC>;
                };
 
-               cpu@2 {
+               CPU2: cpu@2 {
                        compatible = "qcom,krait";
                        enable-method = "qcom,kpss-acc-v2";
                        device_type = "cpu";
                        cpu-idle-states = <&CPU_SPC>;
                };
 
-               cpu@3 {
+               CPU3: cpu@3 {
                        compatible = "qcom,krait";
                        enable-method = "qcom,kpss-acc-v2";
                        device_type = "cpu";
 
                cx-supply = <&pm8841_s2>;
 
+               clocks = <&xo_board>;
+               clock-names = "xo";
+
                memory-region = <&adsp_region>;
 
                qcom,smem-states = <&adsp_smp2p_out 0>;
                        qcom,ee = <0>;
                };
 
-               usb1_phy: usb-phy@f9a55000 {
-                       compatible = "qcom,usb-otg-snps";
+               etr@fc322000 {
+                       compatible = "arm,coresight-tmc", "arm,primecell";
+                       reg = <0xfc322000 0x1000>;
 
-                       reg = <0xf9a55000 0x400>;
-                       interrupts-extended = <&intc 0 134 0>, <&intc 0 140 0>,
-                               <&spmi_bus 0 0x9 0 0>;
-                       interrupt-names = "core_irq", "async_irq", "pmic_id_irq";
+                       clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
+                       clock-names = "apb_pclk", "atclk";
 
-                       vddcx-supply = <&pm8841_s2>;
-                       v3p3-supply = <&pm8941_l24>;
-                       v1p8-supply = <&pm8941_l6>;
+                       port {
+                               etr_in: endpoint {
+                                       slave-mode;
+                                       remote-endpoint = <&replicator_out0>;
+                               };
+                       };
+               };
 
-                       dr_mode = "otg";
-                       qcom,phy-init-sequence = <0x63 0x81 0xfffffff>;
-                       qcom,otg-control = <1>;
-                       qcom,phy-num = <0>;
+               tpiu@fc318000 {
+                       compatible = "arm,coresight-tpiu", "arm,primecell";
+                       reg = <0xfc318000 0x1000>;
 
-                       resets = <&gcc GCC_USB2A_PHY_BCR>, <&gcc GCC_USB_HS_BCR>;
-                       reset-names = "phy", "link";
+                       clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
+                       clock-names = "apb_pclk", "atclk";
 
-                       clocks = <&gcc GCC_XO_CLK>, <&gcc GCC_USB_HS_SYSTEM_CLK>,
-                               <&gcc GCC_USB_HS_AHB_CLK>;
-                       clock-names = "phy", "core", "iface";
+                       port {
+                               tpiu_in: endpoint {
+                                        slave-mode;
+                                        remote-endpoint = <&replicator_out1>;
+                                };
+                       };
+               };
 
-                       status = "disabled";
+               replicator@fc31c000 {
+                       compatible = "qcom,coresight-replicator1x", "arm,primecell";
+                       reg = <0xfc31c000 0x1000>;
+
+                       clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
+                       clock-names = "apb_pclk", "atclk";
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               port@0 {
+                                       reg = <0>;
+                                       replicator_out0: endpoint {
+                                               remote-endpoint = <&etr_in>;
+                                       };
+                               };
+                               port@1 {
+                                       reg = <1>;
+                                       replicator_out1: endpoint {
+                                               remote-endpoint = <&tpiu_in>;
+                                       };
+                               };
+                               port@2 {
+                                       reg = <0>;
+                                       replicator_in: endpoint {
+                                               slave-mode;
+                                               remote-endpoint = <&etf_out>;
+                                       };
+                               };
+                       };
                };
 
-               usb@f9a55000 {
-                       compatible = "qcom,ci-hdrc";
-                       reg = <0xf9a55000 0x400>;
-                       dr_mode = "otg";
-                       interrupts = <0 134 0>, <0 140 0>;
-                       interrupt-names = "core_irq", "async_irq";
-                       usb-phy = <&usb1_phy>;
+               etf@fc307000 {
+                       compatible = "arm,coresight-tmc", "arm,primecell";
+                       reg = <0xfc307000 0x1000>;
 
-                       status = "disabled";
+                       clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
+                       clock-names = "apb_pclk", "atclk";
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               port@0 {
+                                       reg = <0>;
+                                       etf_out: endpoint {
+                                               remote-endpoint = <&replicator_in>;
+                                       };
+                               };
+                               port@1 {
+                                       reg = <0>;
+                                       etf_in: endpoint {
+                                               slave-mode;
+                                               remote-endpoint = <&merger_out>;
+                                       };
+                               };
+                       };
+               };
+
+               funnel@fc31b000 {
+                       compatible = "arm,coresight-funnel", "arm,primecell";
+                       reg = <0xfc31b000 0x1000>;
+
+                       clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
+                       clock-names = "apb_pclk", "atclk";
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               /*
+                                * Not described input ports:
+                                * 0 - connected trought funnel to Audio, Modem and
+                                *     Resource and Power Manager CPU's
+                                * 2...7 - not-connected
+                                */
+                               port@1 {
+                                       reg = <1>;
+                                       merger_in1: endpoint {
+                                               slave-mode;
+                                               remote-endpoint = <&funnel1_out>;
+                                       };
+                               };
+                               port@8 {
+                                       reg = <0>;
+                                       merger_out: endpoint {
+                                               remote-endpoint = <&etf_in>;
+                                       };
+                               };
+                       };
+               };
+
+               funnel@fc31a000 {
+                       compatible = "arm,coresight-funnel", "arm,primecell";
+                       reg = <0xfc31a000 0x1000>;
+
+                       clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
+                       clock-names = "apb_pclk", "atclk";
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               /*
+                                * Not described input ports:
+                                * 0 - not-connected
+                                * 1 - connected trought funnel to Multimedia CPU
+                                * 2 - connected to Wireless CPU
+                                * 3 - not-connected
+                                * 4 - not-connected
+                                * 6 - not-connected
+                                * 7 - connected to STM
+                                */
+                               port@5 {
+                                       reg = <5>;
+                                       funnel1_in5: endpoint {
+                                               slave-mode;
+                                               remote-endpoint = <&kpss_out>;
+                                       };
+                               };
+                               port@8 {
+                                       reg = <0>;
+                                       funnel1_out: endpoint {
+                                               remote-endpoint = <&merger_in1>;
+                                       };
+                               };
+                       };
+               };
+
+               funnel@fc345000 { /* KPSS funnel only 4 inputs are used */
+                       compatible = "arm,coresight-funnel", "arm,primecell";
+                       reg = <0xfc345000 0x1000>;
+
+                       clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
+                       clock-names = "apb_pclk", "atclk";
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               port@0 {
+                                       reg = <0>;
+                                       kpss_in0: endpoint {
+                                               slave-mode;
+                                               remote-endpoint = <&etm0_out>;
+                                       };
+                               };
+                               port@1 {
+                                       reg = <1>;
+                                       kpss_in1: endpoint {
+                                               slave-mode;
+                                               remote-endpoint = <&etm1_out>;
+                                       };
+                               };
+                               port@2 {
+                                       reg = <2>;
+                                       kpss_in2: endpoint {
+                                               slave-mode;
+                                               remote-endpoint = <&etm2_out>;
+                                       };
+                               };
+                               port@3 {
+                                       reg = <3>;
+                                       kpss_in3: endpoint {
+                                               slave-mode;
+                                               remote-endpoint = <&etm3_out>;
+                                       };
+                               };
+                               port@8 {
+                                       reg = <0>;
+                                       kpss_out: endpoint {
+                                               remote-endpoint = <&funnel1_in5>;
+                                       };
+                               };
+                       };
+               };
+
+               etm@fc33c000 {
+                       compatible = "arm,coresight-etm4x", "arm,primecell";
+                       reg = <0xfc33c000 0x1000>;
+
+                       clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
+                       clock-names = "apb_pclk", "atclk";
+
+                       cpu = <&CPU0>;
+
+                       port {
+                               etm0_out: endpoint {
+                                       remote-endpoint = <&kpss_in0>;
+                               };
+                       };
+               };
+
+               etm@fc33d000 {
+                       compatible = "arm,coresight-etm4x", "arm,primecell";
+                       reg = <0xfc33d000 0x1000>;
+
+                       clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
+                       clock-names = "apb_pclk", "atclk";
+
+                       cpu = <&CPU1>;
+
+                       port {
+                               etm1_out: endpoint {
+                                       remote-endpoint = <&kpss_in1>;
+                               };
+                       };
+               };
+
+               etm@fc33e000 {
+                       compatible = "arm,coresight-etm4x", "arm,primecell";
+                       reg = <0xfc33e000 0x1000>;
+
+                       clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
+                       clock-names = "apb_pclk", "atclk";
+
+                       cpu = <&CPU2>;
+
+                       port {
+                               etm2_out: endpoint {
+                                       remote-endpoint = <&kpss_in2>;
+                               };
+                       };
+               };
+
+               etm@fc33f000 {
+                       compatible = "arm,coresight-etm4x", "arm,primecell";
+                       reg = <0xfc33f000 0x1000>;
+
+                       clocks = <&rpmcc RPM_SMD_QDSS_CLK>, <&rpmcc RPM_SMD_QDSS_A_CLK>;
+                       clock-names = "apb_pclk", "atclk";
+
+                       cpu = <&CPU3>;
+
+                       port {
+                               etm3_out: endpoint {
+                                       remote-endpoint = <&kpss_in3>;
+                               };
+                       };
                };
        };
 
                                compatible = "qcom,rpm-msm8974";
                                qcom,smd-channels = "rpm_requests";
 
+                               rpmcc: clock-controller {
+                                       compatible = "qcom,rpmcc-msm8974", "qcom,rpmcc";
+                                       #clock-cells = <1>;
+                               };
+
                                pm8841-regulators {
                                        compatible = "qcom,rpm-pm8841-regulators";
 
index 118a8e2b86bdd67293d7360d90f8468604bf381e..52a7b586bac72277f411ccb306fe0c0d719aaa5d 100644 (file)
        clock-frequency = <48000000>;
 };
 
+&rtc_x1_clk {
+       clock-frequency = <32768>;
+};
+
 &mtu2 {
        status = "okay";
 };
        };
 };
 
+&rtc {
+       status = "okay";
+};
+
 &scif2 {
        status = "okay";
 };
index 02b59c5b3c53a6d25a42bf508a1ca631b458f232..72df20a04320e7ac61dccde306f5799bdf1bd78c 100644 (file)
        clock-frequency = <48000000>;
 };
 
+&rtc_x1_clk {
+       clock-frequency = <32768>;
+};
+
 &mtu2 {
        status = "okay";
 };
        status = "okay";
 };
 
+&rtc {
+       status = "okay";
+};
+
 &scif2 {
        status = "okay";
 };
index 1cf2bd0380901d1d6f8ec05cfc38e693defaddfe..0423996e4dccf612a0521546699d17df3ae9c360 100644 (file)
                        clock-frequency = <0>;
                };
 
+               rtc_x1_clk: rtc_x1 {
+                       #clock-cells = <0>;
+                       compatible = "fixed-clock";
+                       /* If clk present, value must be set by board to 32678 */
+                       clock-frequency = <0>;
+               };
+
+               rtc_x3_clk: rtc_x3 {
+                       #clock-cells = <0>;
+                       compatible = "fixed-clock";
+                       /* If clk present, value must be set by board to 4000000 */
+                       clock-frequency = <0>;
+               };
+
                /* Fixed factor clocks */
                b_clk: b {
                        #clock-cells = <0>;
                        clock-output-names = "ostm0", "ostm1";
                };
 
+               mstp6_clks: mstp6_clks@fcfe042c {
+                       #clock-cells = <1>;
+                       compatible = "renesas,r7s72100-mstp-clocks", "renesas,cpg-mstp-clocks";
+                       reg = <0xfcfe042c 4>;
+                       clocks = <&p0_clk>;
+                       clock-indices = <R7S72100_CLK_RTC>;
+                       clock-output-names = "rtc";
+               };
+
                mstp7_clks: mstp7_clks@fcfe0430 {
                        #clock-cells = <1>;
                        compatible = "renesas,r7s72100-mstp-clocks", "renesas,cpg-mstp-clocks";
                        reg = <0xfcfe0430 4>;
-                       clocks = <&p0_clk>;
+                       clocks = <&b_clk>;
                        clock-indices = <R7S72100_CLK_ETHER>;
                        clock-output-names = "ether";
                };
                        #clock-cells = <1>;
                        compatible = "renesas,r7s72100-mstp-clocks", "renesas,cpg-mstp-clocks";
                        reg = <0xfcfe0444 4>;
-                       clocks = <&p1_clk>, <&p1_clk>;
-                       clock-indices = <R7S72100_CLK_SDHI1 R7S72100_CLK_SDHI0>;
-                       clock-output-names = "sdhi1", "sdhi0";
+                       clocks = <&p1_clk>, <&p1_clk>, <&p1_clk>, <&p1_clk>;
+                       clock-indices = <
+                               R7S72100_CLK_SDHI00 R7S72100_CLK_SDHI01
+                               R7S72100_CLK_SDHI10 R7S72100_CLK_SDHI11
+                       >;
+                       clock-output-names = "sdhi00", "sdhi01", "sdhi10", "sdhi11";
                };
        };
 
                cache-level = <2>;
        };
 
+       wdt: watchdog@fcfe0000 {
+               compatible = "renesas,r7s72100-wdt", "renesas,rza-wdt";
+               reg = <0xfcfe0000 0x6>;
+               interrupts = <GIC_SPI 106 IRQ_TYPE_EDGE_RISING>;
+               clocks = <&p0_clk>;
+       };
+
        i2c0: i2c@fcfee000 {
                #address-cells = <1>;
                #size-cells = <0>;
                              GIC_SPI 271 IRQ_TYPE_LEVEL_HIGH
                              GIC_SPI 272 IRQ_TYPE_LEVEL_HIGH>;
 
-               clocks = <&mstp12_clks R7S72100_CLK_SDHI0>;
+               clocks = <&mstp12_clks R7S72100_CLK_SDHI00>,
+                        <&mstp12_clks R7S72100_CLK_SDHI01>;
+               clock-names = "core", "cd";
+               power-domains = <&cpg_clocks>;
                cap-sd-highspeed;
                cap-sdio-irq;
                status = "disabled";
                              GIC_SPI 274 IRQ_TYPE_LEVEL_HIGH
                              GIC_SPI 275 IRQ_TYPE_LEVEL_HIGH>;
 
-               clocks = <&mstp12_clks R7S72100_CLK_SDHI1>;
+               clocks = <&mstp12_clks R7S72100_CLK_SDHI10>,
+                        <&mstp12_clks R7S72100_CLK_SDHI11>;
+               clock-names = "core", "cd";
+               power-domains = <&cpg_clocks>;
                cap-sd-highspeed;
                cap-sdio-irq;
                status = "disabled";
                power-domains = <&cpg_clocks>;
                status = "disabled";
        };
+
+       rtc: rtc@fcff1000 {
+               compatible = "renesas,r7s72100-rtc", "renesas,sh-rtc";
+               reg = <0xfcff1000 0x2e>;
+               interrupts = <GIC_SPI 276 IRQ_TYPE_EDGE_RISING
+                             GIC_SPI 277 IRQ_TYPE_EDGE_RISING
+                             GIC_SPI 278 IRQ_TYPE_EDGE_RISING>;
+               interrupt-names = "alarm", "period", "carry";
+               clocks = <&mstp6_clks R7S72100_CLK_RTC>, <&rtc_x1_clk>,
+                        <&rtc_x3_clk>, <&extal_clk>;
+               clock-names = "fck", "rtc_x1", "rtc_x3", "extal";
+               power-domains = <&cpg_clocks>;
+               status = "disabled";
+       };
 };
index 00eb9a7114dc2621b3bff2a94b1e3e2a4b4c0e6e..1f5c9f6dddba93665febc919309f01090e918f40 100644 (file)
                        next-level-cache = <&L2_CA15>;
                };
 
-               L2_CA15: cache-controller@0 {
+               L2_CA15: cache-controller-0 {
                        compatible = "cache";
-                       reg = <0>;
                        clocks = <&cpg_clocks R8A73A4_CLK_Z>;
                        power-domains = <&pd_a3sm>;
                        cache-unified;
                        cache-level = <2>;
                };
 
-               L2_CA7: cache-controller@100 {
+               L2_CA7: cache-controller-1 {
                        compatible = "cache";
-                       reg = <0x100>;
                        clocks = <&cpg_clocks R8A73A4_CLK_Z2>;
                        power-domains = <&pd_a3km>;
                        cache-unified;
                        <0 0xf1004000 0 0x2000>,
                        <0 0xf1006000 0 0x2000>;
                interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+               clocks = <&mstp4_clks R8A73A4_CLK_INTC_SYS>;
+               clock-names = "clk";
+               power-domains = <&pd_c4>;
        };
 
        bsc: bus@fec10000 {
                mstp4_clks: mstp4_clks@e6150140 {
                        compatible = "renesas,r8a73a4-mstp-clocks", "renesas,cpg-mstp-clocks";
                        reg = <0 0xe6150140 0 4>, <0 0xe615004c 0 4>;
-                       clocks = <&main_div2_clk>, <&main_div2_clk>,
+                       clocks = <&main_div2_clk>, <&cpg_clocks R8A73A4_CLK_ZS>,
+                                <&main_div2_clk>,
                                 <&cpg_clocks R8A73A4_CLK_HP>,
                                 <&cpg_clocks R8A73A4_CLK_HP>;
                        #clock-cells = <1>;
                        clock-indices = <
-                               R8A73A4_CLK_IRQC R8A73A4_CLK_IIC5
-                               R8A73A4_CLK_IIC4 R8A73A4_CLK_IIC3
+                               R8A73A4_CLK_IRQC R8A73A4_CLK_INTC_SYS
+                               R8A73A4_CLK_IIC5 R8A73A4_CLK_IIC4
+                               R8A73A4_CLK_IIC3
                        >;
                        clock-output-names =
-                               "irqc", "iic5", "iic4", "iic3";
+                               "irqc", "intc-sys", "iic5", "iic4", "iic3";
                };
                mstp5_clks: mstp5_clks@e6150144 {
                        compatible = "renesas,r8a73a4-mstp-clocks", "renesas,cpg-mstp-clocks";
index d8393b97768bf8e9a6f53fdc44fe2211b64e3705..0ddac81742e4cdc7dc93be53fd019db00de98faa 100644 (file)
@@ -32,9 +32,8 @@
                        next-level-cache = <&L2_CA15>;
                };
 
-               L2_CA15: cache-controller@0 {
+               L2_CA15: cache-controller-0 {
                        compatible = "cache";
-                       reg = <0>;
                        cache-unified;
                        cache-level = <2>;
                        power-domains = <&sysc R8A7743_PD_CA15_SCU>;
@@ -63,6 +62,7 @@
                        clocks = <&cpg CPG_MOD 408>;
                        clock-names = "clk";
                        power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+                       resets = <&cpg 408>;
                };
 
                irqc: interrupt-controller@e61c0000 {
@@ -82,6 +82,7 @@
                                     <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 407>;
                        power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+                       resets = <&cpg 407>;
                };
 
                timer {
                        clock-names = "extal", "usb_extal";
                        #clock-cells = <2>;
                        #power-domain-cells = <0>;
+                       #reset-cells = <1>;
                };
 
                prr: chipid@ff000044 {
                        clocks = <&cpg CPG_MOD 219>;
                        clock-names = "fck";
                        power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+                       resets = <&cpg 219>;
                        #dma-cells = <1>;
                        dma-channels = <15>;
                };
                        clocks = <&cpg CPG_MOD 218>;
                        clock-names = "fck";
                        power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+                       resets = <&cpg 218>;
                        #dma-cells = <1>;
                        dma-channels = <15>;
                };
                               <&dmac1 0x21>, <&dmac1 0x22>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+                       resets = <&cpg 204>;
                        status = "disabled";
                };
 
                               <&dmac1 0x25>, <&dmac1 0x26>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+                       resets = <&cpg 203>;
                        status = "disabled";
                };
 
                               <&dmac1 0x27>, <&dmac1 0x28>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+                       resets = <&cpg 202>;
                        status = "disabled";
                };
 
                               <&dmac1 0x1b>, <&dmac1 0x1c>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+                       resets = <&cpg 1106>;
                        status = "disabled";
                };
 
                               <&dmac1 0x1f>, <&dmac1 0x20>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+                       resets = <&cpg 1107>;
                        status = "disabled";
                };
 
                               <&dmac1 0x23>, <&dmac1 0x24>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+                       resets = <&cpg 1108>;
                        status = "disabled";
                };
 
                        clocks = <&cpg CPG_MOD 206>;
                        clock-names = "fck";
                        dmas = <&dmac0 0x3d>, <&dmac0 0x3e>,
-                      <&dmac1 0x3d>, <&dmac1 0x3e>;
+                              <&dmac1 0x3d>, <&dmac1 0x3e>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+                       resets = <&cpg 206>;
                        status = "disabled";
                };
 
                               <&dmac1 0x19>, <&dmac1 0x1a>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+                       resets = <&cpg 207>;
                        status = "disabled";
                };
 
                               <&dmac1 0x1d>, <&dmac1 0x1e>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+                       resets = <&cpg 216>;
                        status = "disabled";
                };
 
                               <&dmac1 0x29>, <&dmac1 0x2a>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+                       resets = <&cpg 721>;
                        status = "disabled";
                };
 
                               <&dmac1 0x2d>, <&dmac1 0x2e>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+                       resets = <&cpg 720>;
                        status = "disabled";
                };
 
                               <&dmac1 0x2b>, <&dmac1 0x2c>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+                       resets = <&cpg 719>;
                        status = "disabled";
                };
 
                               <&dmac1 0x2f>, <&dmac1 0x30>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+                       resets = <&cpg 718>;
                        status = "disabled";
                };
 
                               <&dmac1 0xfb>, <&dmac1 0xfc>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+                       resets = <&cpg 715>;
                        status = "disabled";
                };
 
                               <&dmac1 0xfd>, <&dmac1 0xfe>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+                       resets = <&cpg 714>;
                        status = "disabled";
                };
 
                               <&dmac1 0x39>, <&dmac1 0x3a>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+                       resets = <&cpg 717>;
                        status = "disabled";
                };
 
                               <&dmac1 0x4d>, <&dmac1 0x4e>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+                       resets = <&cpg 716>;
                        status = "disabled";
                };
 
                               <&dmac1 0x3b>, <&dmac1 0x3c>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+                       resets = <&cpg 713>;
                        status = "disabled";
                };
 
                        interrupts = <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 813>;
                        power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+                       resets = <&cpg 813>;
                        phy-mode = "rmii";
                        #address-cells = <1>;
                        #size-cells = <0>;
index 1f65ff68a469d9f35cb419726bc67bd4254ab9dd..2feb0084bb3b1b5149afe1efd3f50aeeb6984117 100644 (file)
@@ -32,9 +32,8 @@
                        next-level-cache = <&L2_CA7>;
                };
 
-               L2_CA7: cache-controller@0 {
+               L2_CA7: cache-controller-0 {
                        compatible = "cache";
-                       reg = <0>;
                        cache-unified;
                        cache-level = <2>;
                        power-domains = <&sysc R8A7745_PD_CA7_SCU>;
@@ -63,6 +62,7 @@
                        clocks = <&cpg CPG_MOD 408>;
                        clock-names = "clk";
                        power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+                       resets = <&cpg 408>;
                };
 
                irqc: interrupt-controller@e61c0000 {
@@ -82,6 +82,7 @@
                                     <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 407>;
                        power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+                       resets = <&cpg 407>;
                };
 
                timer {
                        clock-names = "extal", "usb_extal";
                        #clock-cells = <2>;
                        #power-domain-cells = <0>;
+                       #reset-cells = <1>;
                };
 
                prr: chipid@ff000044 {
                        clocks = <&cpg CPG_MOD 219>;
                        clock-names = "fck";
                        power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+                       resets = <&cpg 219>;
                        #dma-cells = <1>;
                        dma-channels = <15>;
                };
                        clocks = <&cpg CPG_MOD 218>;
                        clock-names = "fck";
                        power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+                       resets = <&cpg 218>;
                        #dma-cells = <1>;
                        dma-channels = <15>;
                };
                               <&dmac1 0x21>, <&dmac1 0x22>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+                       resets = <&cpg 204>;
                        status = "disabled";
                };
 
                               <&dmac1 0x25>, <&dmac1 0x26>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+                       resets = <&cpg 203>;
                        status = "disabled";
                };
 
                               <&dmac1 0x27>, <&dmac1 0x28>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+                       resets = <&cpg 202>;
                        status = "disabled";
                };
 
                               <&dmac1 0x1b>, <&dmac1 0x1c>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+                       resets = <&cpg 1106>;
                        status = "disabled";
                };
 
                               <&dmac1 0x1f>, <&dmac1 0x20>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+                       resets = <&cpg 1107>;
                        status = "disabled";
                };
 
                               <&dmac1 0x23>, <&dmac1 0x24>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+                       resets = <&cpg 1108>;
                        status = "disabled";
                };
 
                        clocks = <&cpg CPG_MOD 206>;
                        clock-names = "fck";
                        dmas = <&dmac0 0x3d>, <&dmac0 0x3e>,
-                      <&dmac1 0x3d>, <&dmac1 0x3e>;
+                              <&dmac1 0x3d>, <&dmac1 0x3e>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+                       resets = <&cpg 206>;
                        status = "disabled";
                };
 
                               <&dmac1 0x19>, <&dmac1 0x1a>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+                       resets = <&cpg 207>;
                        status = "disabled";
                };
 
                               <&dmac1 0x1d>, <&dmac1 0x1e>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+                       resets = <&cpg 216>;
                        status = "disabled";
                };
 
                               <&dmac1 0x29>, <&dmac1 0x2a>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+                       resets = <&cpg 721>;
                        status = "disabled";
                };
 
                               <&dmac1 0x2d>, <&dmac1 0x2e>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+                       resets = <&cpg 720>;
                        status = "disabled";
                };
 
                               <&dmac1 0x2b>, <&dmac1 0x2c>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+                       resets = <&cpg 719>;
                        status = "disabled";
                };
 
                               <&dmac1 0x2f>, <&dmac1 0x30>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+                       resets = <&cpg 718>;
                        status = "disabled";
                };
 
                               <&dmac1 0xfb>, <&dmac1 0xfc>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+                       resets = <&cpg 715>;
                        status = "disabled";
                };
 
                               <&dmac1 0xfd>, <&dmac1 0xfe>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+                       resets = <&cpg 714>;
                        status = "disabled";
                };
 
                               <&dmac1 0x39>, <&dmac1 0x3a>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+                       resets = <&cpg 717>;
                        status = "disabled";
                };
 
                               <&dmac1 0x4d>, <&dmac1 0x4e>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+                       resets = <&cpg 716>;
                        status = "disabled";
                };
 
                               <&dmac1 0x3b>, <&dmac1 0x3c>;
                        dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+                       resets = <&cpg 713>;
                        status = "disabled";
                };
 
                        interrupts = <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 813>;
                        power-domains = <&sysc R8A7745_PD_ALWAYS_ON>;
+                       resets = <&cpg 813>;
                        phy-mode = "rmii";
                        #address-cells = <1>;
                        #size-cells = <0>;
index 211d239d9041a8863d2de27f859e600a8d9aea76..c79d55eb43c53fde3d3b0b0a5211c6b6612bdb8f 100644 (file)
 
 &scif_clk {
        clock-frequency = <14745600>;
-       status = "okay";
 };
index 89c5b24a3d03f0492a432532de68f0bc31e87cb5..9412a86f9b300fa7a78fbb0b62ee1affb2ad05e0 100644 (file)
 
 &scif_clk {
        clock-frequency = <14745600>;
-       status = "okay";
 };
 
 &sdhi0 {
index bd512c86e8522233b3c1def53630e69808e2a666..ba100a6f67ca554c1b7068ba60e83090a0338ff4 100644 (file)
 
 &scif_clk {
        clock-frequency = <14745600>;
-       status = "okay";
 };
 
 &msiof1 {
index 6d10450de6d7b97fcd287ba965cd3f331e66dc85..99269aaca6fc953eccc3218cf78487d0a9c156d3 100644 (file)
                        next-level-cache = <&L2_CA7>;
                };
 
-               L2_CA15: cache-controller@0 {
+               L2_CA15: cache-controller-0 {
                        compatible = "cache";
-                       reg = <0>;
                        power-domains = <&sysc R8A7790_PD_CA15_SCU>;
                        cache-unified;
                        cache-level = <2>;
                };
 
-               L2_CA7: cache-controller@100 {
+               L2_CA7: cache-controller-1 {
                        compatible = "cache";
-                       reg = <0x100>;
                        power-domains = <&sysc R8A7790_PD_CA7_SCU>;
                        cache-unified;
                        cache-level = <2>;
                        <0 0xf1004000 0 0x2000>,
                        <0 0xf1006000 0 0x2000>;
                interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+               clocks = <&mstp4_clks R8A7790_CLK_INTC_SYS>;
+               clock-names = "clk";
+               power-domains = <&sysc R8A7790_PD_ALWAYS_ON>;
        };
 
        gpio0: gpio@e6050000 {
                };
 
                /* External CAN clock */
-               can_clk: can_clk {
+               can_clk: can {
                        compatible = "fixed-clock";
                        #clock-cells = <0>;
                        /* This value must be overridden by the board. */
                mstp4_clks: mstp4_clks@e6150140 {
                        compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks";
                        reg = <0 0xe6150140 0 4>, <0 0xe615004c 0 4>;
-                       clocks = <&cp_clk>;
+                       clocks = <&cp_clk>, <&zs_clk>;
                        #clock-cells = <1>;
-                       clock-indices = <R8A7790_CLK_IRQC>;
-                       clock-output-names = "irqc";
+                       clock-indices = <R8A7790_CLK_IRQC R8A7790_CLK_INTC_SYS>;
+                       clock-output-names = "irqc", "intc-sys";
                };
                mstp5_clks: mstp5_clks@e6150144 {
                        compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks";
                        compatible = "renesas,r8a7790-mstp-clocks", "renesas,cpg-mstp-clocks";
                        reg = <0 0xe6150998 0 4>, <0 0xe61509a8 0 4>;
                        clocks = <&p_clk>,
-                               <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>,
-                               <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>,
+                               <&mstp10_clks R8A7790_CLK_SSI_ALL>, <&mstp10_clks R8A7790_CLK_SSI_ALL>,
+                               <&mstp10_clks R8A7790_CLK_SSI_ALL>, <&mstp10_clks R8A7790_CLK_SSI_ALL>,
+                               <&mstp10_clks R8A7790_CLK_SSI_ALL>, <&mstp10_clks R8A7790_CLK_SSI_ALL>,
+                               <&mstp10_clks R8A7790_CLK_SSI_ALL>, <&mstp10_clks R8A7790_CLK_SSI_ALL>,
+                               <&mstp10_clks R8A7790_CLK_SSI_ALL>, <&mstp10_clks R8A7790_CLK_SSI_ALL>,
                                <&p_clk>,
                                <&mstp10_clks R8A7790_CLK_SCU_ALL>, <&mstp10_clks R8A7790_CLK_SCU_ALL>,
                                <&mstp10_clks R8A7790_CLK_SCU_ALL>, <&mstp10_clks R8A7790_CLK_SCU_ALL>,
 
                rcar_sound,dvc {
                        dvc0: dvc-0 {
-                               dmas = <&audma0 0xbc>;
+                               dmas = <&audma1 0xbc>;
                                dma-names = "tx";
                        };
                        dvc1: dvc-1 {
-                               dmas = <&audma0 0xbe>;
+                               dmas = <&audma1 0xbe>;
                                dma-names = "tx";
                        };
                };
index 5405d337d74486659d0b408189f06247123263d9..001e6116c47c7c3bd9a22eb0106e369e47dedcae 100644 (file)
        x2_clk: x2-clock {
                compatible = "fixed-clock";
                #clock-cells = <0>;
-               clock-frequency = <148500000>;
+               clock-frequency = <74250000>;
        };
 
        x13_clk: x13-clock {
 
 &scif_clk {
        clock-frequency = <14745600>;
-       status = "okay";
 };
 
 &sdhi0 {
 
 &pcie_bus_clk {
        clock-frequency = <100000000>;
-       status = "okay";
 };
 
 &pciec {
index 6761d11d3f9e1317fd2d8a21c2e361cd40723823..95da5cb9d37ab8e50fab028bca63782dd422bf7c 100644 (file)
 
        phy-handle = <&phy1>;
        renesas,ether-link-active-low;
-       status = "ok";
+       status = "okay";
 
        phy1: ethernet-phy@1 {
                reg = <1>;
 
 /* composite video input */
 &vin0 {
-       status = "ok";
+       status = "okay";
        pinctrl-0 = <&vin0_pins>;
        pinctrl-names = "default";
 
 
 &pcie_bus_clk {
        clock-frequency = <100000000>;
-       status = "okay";
 };
 
 &pciec {
index 9f9e48511836ddc6c79951d327d10dfc26da7a71..4d0c2ce59900f8115eebb0a38c0c66f83ac447bd 100644 (file)
@@ -74,9 +74,8 @@
                        next-level-cache = <&L2_CA15>;
                };
 
-               L2_CA15: cache-controller@0 {
+               L2_CA15: cache-controller-0 {
                        compatible = "cache";
-                       reg = <0>;
                        power-domains = <&sysc R8A7791_PD_CA15_SCU>;
                        cache-unified;
                        cache-level = <2>;
                        <0 0xf1004000 0 0x2000>,
                        <0 0xf1006000 0 0x2000>;
                interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
+               clocks = <&mstp4_clks R8A7791_CLK_INTC_SYS>;
+               clock-names = "clk";
+               power-domains = <&sysc R8A7791_PD_ALWAYS_ON>;
        };
 
        gpio0: gpio@e6050000 {
                };
 
                /* External CAN clock */
-               can_clk: can_clk {
+               can_clk: can {
                        compatible = "fixed-clock";
                        #clock-cells = <0>;
                        /* This value must be overridden by the board. */
                mstp4_clks: mstp4_clks@e6150140 {
                        compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks";
                        reg = <0 0xe6150140 0 4>, <0 0xe615004c 0 4>;
-                       clocks = <&cp_clk>;
+                       clocks = <&cp_clk>, <&zs_clk>;
                        #clock-cells = <1>;
-                       clock-indices = <R8A7791_CLK_IRQC>;
-                       clock-output-names = "irqc";
+                       clock-indices = <R8A7791_CLK_IRQC R8A7791_CLK_INTC_SYS>;
+                       clock-output-names = "irqc", "intc-sys";
                };
                mstp5_clks: mstp5_clks@e6150144 {
                        compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks";
                        compatible = "renesas,r8a7791-mstp-clocks", "renesas,cpg-mstp-clocks";
                        reg = <0 0xe6150998 0 4>, <0 0xe61509a8 0 4>;
                        clocks = <&p_clk>,
-                               <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>,
-                               <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>,
+                               <&mstp10_clks R8A7791_CLK_SSI_ALL>, <&mstp10_clks R8A7791_CLK_SSI_ALL>,
+                               <&mstp10_clks R8A7791_CLK_SSI_ALL>, <&mstp10_clks R8A7791_CLK_SSI_ALL>,
+                               <&mstp10_clks R8A7791_CLK_SSI_ALL>, <&mstp10_clks R8A7791_CLK_SSI_ALL>,
+                               <&mstp10_clks R8A7791_CLK_SSI_ALL>, <&mstp10_clks R8A7791_CLK_SSI_ALL>,
+                               <&mstp10_clks R8A7791_CLK_SSI_ALL>, <&mstp10_clks R8A7791_CLK_SSI_ALL>,
                                <&p_clk>,
                                <&mstp10_clks R8A7791_CLK_SCU_ALL>, <&mstp10_clks R8A7791_CLK_SCU_ALL>,
                                <&mstp10_clks R8A7791_CLK_SCU_ALL>, <&mstp10_clks R8A7791_CLK_SCU_ALL>,
 
                rcar_sound,dvc {
                        dvc0: dvc-0 {
-                               dmas = <&audma0 0xbc>;
+                               dmas = <&audma1 0xbc>;
                                dma-names = "tx";
                        };
                        dvc1: dvc-1 {
-                               dmas = <&audma0 0xbe>;
+                               dmas = <&audma1 0xbe>;
                                dma-names = "tx";
                        };
                };
index 8ecfda7a004ecb322b63e1fa0c8b3d1aa6851ca9..0efecb232ee52ce0d75c189b1e378fbb274cc836 100644 (file)
@@ -46,7 +46,7 @@
                        compatible = "arm,cortex-a15";
                        reg = <0>;
                        clock-frequency = <1000000000>;
-                       clocks = <&cpg_clocks R8A7792_CLK_Z>;
+                       clocks = <&z_clk>;
                        power-domains = <&sysc R8A7792_PD_CA15_CPU0>;
                        next-level-cache = <&L2_CA15>;
                };
@@ -60,9 +60,8 @@
                        next-level-cache = <&L2_CA15>;
                };
 
-               L2_CA15: cache-controller@0 {
+               L2_CA15: cache-controller-0 {
                        compatible = "cache";
-                       reg = <0>;
                        cache-unified;
                        cache-level = <2>;
                        power-domains = <&sysc R8A7792_PD_CA15_SCU>;
@@ -93,6 +92,9 @@
                              <0 0xf1006000 0 0x2000>;
                        interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(2) |
                                      IRQ_TYPE_LEVEL_HIGH)>;
+                       clocks = <&mstp4_clks R8A7792_CLK_INTC_SYS>;
+                       clock-names = "clk";
+                       power-domains = <&sysc R8A7792_PD_ALWAYS_ON>;
                };
 
                irqc: interrupt-controller@e61c0000 {
                        clocks = <&extal_clk>;
                        #clock-cells = <1>;
                        clock-output-names = "main", "pll0", "pll1", "pll3",
-                                            "lb", "qspi", "z";
+                                            "lb", "qspi";
                        #power-domain-cells = <0>;
                };
 
                        clock-div = <2>;
                        clock-mult = <1>;
                };
+               z_clk: z {
+                       compatible = "fixed-factor-clock";
+                       clocks = <&cpg_clocks R8A7792_CLK_PLL0>;
+                       #clock-cells = <0>;
+                       clock-div = <1>;
+                       clock-mult = <1>;
+               };
                zx_clk: zx {
                        compatible = "fixed-factor-clock";
                        clocks = <&cpg_clocks R8A7792_CLK_PLL1>;
                        compatible = "renesas,r8a7792-mstp-clocks",
                                     "renesas,cpg-mstp-clocks";
                        reg = <0 0xe6150140 0 4>, <0 0xe615004c 0 4>;
-                       clocks = <&cp_clk>;
+                       clocks = <&cp_clk>, <&zs_clk>;
                        #clock-cells = <1>;
-                       clock-indices = <R8A7792_CLK_IRQC>;
-                       clock-output-names = "irqc";
+                       clock-indices = <
+                               R8A7792_CLK_IRQC R8A7792_CLK_INTC_SYS
+                       >;
+                       clock-output-names = "irqc", "intc-sys";
                };
                mstp7_clks: mstp7_clks@e615014c {
                        compatible = "renesas,r8a7792-mstp-clocks",
index 92fff07c5e2bfe13824f6637351040145d251c84..806c93f6ae8b9fdad3c1c1a5c3ce9cc8d8c534ae 100644 (file)
 
 &scif_clk {
        clock-frequency = <14745600>;
-       status = "okay";
 };
 
 &sdhi0 {
index 48ce21c5e8db3c52990026226d85852cfec1e1a6..4de6041d61f9d4ecdb2b476c9ae26a95ff54b96a 100644 (file)
@@ -65,9 +65,8 @@
                        power-domains = <&sysc R8A7793_PD_CA15_CPU1>;
                };
 
-               L2_CA15: cache-controller@0 {
+               L2_CA15: cache-controller-0 {
                        compatible = "cache";
-                       reg = <0>;
                        power-domains = <&sysc R8A7793_PD_CA15_SCU>;
                        cache-unified;
                        cache-level = <2>;
                        <0 0xf1004000 0 0x2000>,
                        <0 0xf1006000 0 0x2000>;
                interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
+               clocks = <&mstp4_clks R8A7793_CLK_INTC_SYS>;
+               clock-names = "clk";
+               power-domains = <&sysc R8A7793_PD_ALWAYS_ON>;
        };
 
        gpio0: gpio@e6050000 {
                mstp4_clks: mstp4_clks@e6150140 {
                        compatible = "renesas,r8a7793-mstp-clocks", "renesas,cpg-mstp-clocks";
                        reg = <0 0xe6150140 0 4>, <0 0xe615004c 0 4>;
-                       clocks = <&cp_clk>;
+                       clocks = <&cp_clk>, <&zs_clk>;
                        #clock-cells = <1>;
-                       clock-indices = <R8A7793_CLK_IRQC>;
-                       clock-output-names = "irqc";
+                       clock-indices = <
+                               R8A7793_CLK_IRQC R8A7793_CLK_INTC_SYS
+                       >;
+                       clock-output-names = "irqc", "intc-sys";
                };
                mstp5_clks: mstp5_clks@e6150144 {
                        compatible = "renesas,r8a7793-mstp-clocks", "renesas,cpg-mstp-clocks";
                        compatible = "renesas,r8a7793-mstp-clocks", "renesas,cpg-mstp-clocks";
                        reg = <0 0xe6150998 0 4>, <0 0xe61509a8 0 4>;
                        clocks = <&p_clk>,
-                               <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>,
-                               <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>,
+                               <&mstp10_clks R8A7793_CLK_SSI_ALL>, <&mstp10_clks R8A7793_CLK_SSI_ALL>,
+                               <&mstp10_clks R8A7793_CLK_SSI_ALL>, <&mstp10_clks R8A7793_CLK_SSI_ALL>,
+                               <&mstp10_clks R8A7793_CLK_SSI_ALL>, <&mstp10_clks R8A7793_CLK_SSI_ALL>,
+                               <&mstp10_clks R8A7793_CLK_SSI_ALL>, <&mstp10_clks R8A7793_CLK_SSI_ALL>,
+                               <&mstp10_clks R8A7793_CLK_SSI_ALL>, <&mstp10_clks R8A7793_CLK_SSI_ALL>,
                                <&p_clk>,
                                <&mstp10_clks R8A7793_CLK_SCU_ALL>, <&mstp10_clks R8A7793_CLK_SCU_ALL>,
                                <&mstp10_clks R8A7793_CLK_SCU_ALL>, <&mstp10_clks R8A7793_CLK_SCU_ALL>,
 
                rcar_sound,dvc {
                        dvc0: dvc-0 {
-                               dmas = <&audma0 0xbc>;
+                               dmas = <&audma1 0xbc>;
                                dma-names = "tx";
                        };
                        dvc1: dvc-1 {
-                               dmas = <&audma0 0xbe>;
+                               dmas = <&audma1 0xbe>;
                                dma-names = "tx";
                        };
                };
index 569e3f0e97a51804bffe7206b2a7e7215e3fea5b..f1eea13cdf44371d84f63695aaf5ff812fc9a45c 100644 (file)
        status = "okay";
 
        clocks = <&mstp7_clks R8A7794_CLK_DU0>,
-                <&mstp7_clks R8A7794_CLK_DU0>,
+                <&mstp7_clks R8A7794_CLK_DU1>,
                 <&x13_clk>, <&x2_clk>;
        clock-names = "du.0", "du.1", "dclkin.0", "dclkin.1";
 
 
 &scif_clk {
        clock-frequency = <14745600>;
-       status = "okay";
 };
 
 &qspi {
index cf880ac06f4b795f6b6458f597ffed4bf35983c4..4cb5278d104dfcb3324c923cdd4346908f8d7586 100644 (file)
 
 &scif_clk {
        clock-frequency = <14745600>;
-       status = "okay";
 };
 
 &ether {
        status = "okay";
 
        clocks = <&mstp7_clks R8A7794_CLK_DU0>,
-                <&mstp7_clks R8A7794_CLK_DU0>,
+                <&mstp7_clks R8A7794_CLK_DU1>,
                 <&x2_clk>, <&x3_clk>;
        clock-names = "du.0", "du.1", "dclkin.0", "dclkin.1";
 
index 319c1069b7eeb722a79dd2efff221e7627907901..a19b884fb25897fc8731feda6ed7e2d909c91403 100644 (file)
@@ -43,6 +43,7 @@
                        compatible = "arm,cortex-a7";
                        reg = <0>;
                        clock-frequency = <1000000000>;
+                       clocks = <&z2_clk>;
                        power-domains = <&sysc R8A7794_PD_CA7_CPU0>;
                        next-level-cache = <&L2_CA7>;
                };
@@ -56,9 +57,8 @@
                        next-level-cache = <&L2_CA7>;
                };
 
-               L2_CA7: cache-controller@0 {
+               L2_CA7: cache-controller-0 {
                        compatible = "cache";
-                       reg = <0>;
                        power-domains = <&sysc R8A7794_PD_CA7_SCU>;
                        cache-unified;
                        cache-level = <2>;
@@ -75,6 +75,9 @@
                        <0 0xf1004000 0 0x2000>,
                        <0 0xf1006000 0 0x2000>;
                interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
+               clocks = <&mstp4_clks R8A7794_CLK_INTC_SYS>;
+               clock-names = "clk";
+               power-domains = <&sysc R8A7794_PD_ALWAYS_ON>;
        };
 
        gpio0: gpio@e6050000 {
                interrupts = <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>,
                             <GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&mstp7_clks R8A7794_CLK_DU0>,
-                        <&mstp7_clks R8A7794_CLK_DU0>;
+                        <&mstp7_clks R8A7794_CLK_DU1>;
                clock-names = "du.0", "du.1";
                status = "disabled";
 
                        clock-div = <2>;
                        clock-mult = <1>;
                };
+               z2_clk: z2 {
+                       compatible = "fixed-factor-clock";
+                       clocks = <&cpg_clocks R8A7794_CLK_PLL0>;
+                       #clock-cells = <0>;
+                       clock-div = <1>;
+                       clock-mult = <1>;
+               };
                zg_clk: zg {
                        compatible = "fixed-factor-clock";
                        clocks = <&cpg_clocks R8A7794_CLK_PLL1>;
                mstp4_clks: mstp4_clks@e6150140 {
                        compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks";
                        reg = <0 0xe6150140 0 4>, <0 0xe615004c 0 4>;
-                       clocks = <&cp_clk>;
+                       clocks = <&cp_clk>, <&zs_clk>;
                        #clock-cells = <1>;
-                       clock-indices = <R8A7794_CLK_IRQC>;
-                       clock-output-names = "irqc";
+                       clock-indices = <R8A7794_CLK_IRQC R8A7794_CLK_INTC_SYS>;
+                       clock-output-names = "irqc", "intc-sys";
                };
                mstp5_clks: mstp5_clks@e6150144 {
                        compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks";
                        clocks = <&mp_clk>, <&hp_clk>,
                                 <&zs_clk>, <&p_clk>, <&p_clk>, <&zs_clk>,
                                 <&zs_clk>, <&p_clk>, <&p_clk>, <&p_clk>, <&p_clk>,
-                                <&zx_clk>;
+                                <&zx_clk>, <&zx_clk>;
                        #clock-cells = <1>;
                        clock-indices = <
                                R8A7794_CLK_EHCI R8A7794_CLK_HSUSB
                                R8A7794_CLK_HSCIF2 R8A7794_CLK_SCIF5
                                R8A7794_CLK_SCIF4 R8A7794_CLK_HSCIF1 R8A7794_CLK_HSCIF0
                                R8A7794_CLK_SCIF3 R8A7794_CLK_SCIF2 R8A7794_CLK_SCIF1
-                               R8A7794_CLK_SCIF0 R8A7794_CLK_DU0
+                               R8A7794_CLK_SCIF0
+                               R8A7794_CLK_DU1 R8A7794_CLK_DU0
                        >;
                        clock-output-names =
                                "ehci", "hsusb",
                                "hscif2", "scif5", "scif4", "hscif1", "hscif0",
-                               "scif3", "scif2", "scif1", "scif0", "du0";
+                               "scif3", "scif2", "scif1", "scif0",
+                               "du1", "du0";
                };
                mstp8_clks: mstp8_clks@e6150990 {
                        compatible = "renesas,r8a7794-mstp-clocks", "renesas,cpg-mstp-clocks";
index 6c8fc19d0ecdfb0cd477394f0d2166537d056868..1297924db6ad00882aa959e72ee445c149368fc9 100644 (file)
@@ -41,7 +41,7 @@
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
-#include <dt-bindings/clock/rk1108-cru.h>
+#include <dt-bindings/clock/rv1108-cru.h>
 #include <dt-bindings/pinctrl/rockchip.h>
 / {
        #address-cells = <1>;
index ff9b90bfaefde4a1ac69b4bea41c8092f67ada52..ec91325d3b6ebeb50da67b44607c600a88cf64bc 100644 (file)
                clock-names = "biu", "ciu";
                fifo-depth = <0x100>;
                interrupts = <GIC_SPI 14 IRQ_TYPE_LEVEL_HIGH>;
+               resets = <&cru SRST_MMC0>;
+               reset-names = "reset";
                status = "disabled";
        };
 
                clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
                fifo-depth = <0x100>;
                interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+               resets = <&cru SRST_SDIO>;
+               reset-names = "reset";
                status = "disabled";
        };
 
                num-slots = <1>;
                pinctrl-names = "default";
                pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>;
+               resets = <&cru SRST_EMMC>;
+               reset-names = "reset";
                status = "disabled";
        };
 
index 1aff4ad22fc41260f446ef54e1811d2f5828ec49..1399bc04ea77fe17fd10472c0ba37ba7d80c8a1a 100644 (file)
 };
 
 &global_timer {
-       interrupts = <GIC_PPI 11 0xf04>;
+       interrupts = <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_EDGE_RISING)>;
        status = "disabled";
 };
 
 &local_timer {
-       interrupts = <GIC_PPI 13 0xf04>;
+       interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_EDGE_RISING)>;
 };
 
 &i2c0 {
index 641607d9ad296156761836ba28a7858b313d7394..48a0c1cf430127bd8e8324cd791661cd1aef43fe 100644 (file)
                fifo-depth = <0x100>;
                pinctrl-names = "default";
                pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_bus8>;
+               resets = <&cru SRST_EMMC>;
+               reset-names = "reset";
                status = "disabled";
        };
 
index 21326f3e8564ab141a8f4a9d0534bd51a3ef3b58..30e93f694ae86699194fb830a45f7d5644d6d23f 100644 (file)
                compatible = "gpio-leds";
 
                work {
-                       gpios = <&gpio7 RK_PA4 GPIO_ACTIVE_LOW>;
+                       gpios = <&gpio7 RK_PA2 GPIO_ACTIVE_HIGH>;
                        label = "miqi:green:user";
-                       linux,default-trigger = "default-on";
-                       pinctrl-names = "default";
-                       pinctrl-0 = <&led_ctl>;
+                       linux,default-trigger = "timer";
                };
        };
 
                };
        };
 
-       leds {
-               led_ctl: led-ctl {
-                       rockchip,pins = <7 4 RK_FUNC_GPIO &pcfg_pull_none>;
-               };
-       };
-
        sdmmc {
                /*
                 * Default drive strength isn't enough to achieve even
diff --git a/arch/arm/boot/dts/rk3288-phycore-rdk.dts b/arch/arm/boot/dts/rk3288-phycore-rdk.dts
new file mode 100644 (file)
index 0000000..3dda795
--- /dev/null
@@ -0,0 +1,298 @@
+/*
+ * Device tree file for Phytec PCM-947 carrier board
+ * Copyright (C) 2017 PHYTEC Messtechnik GmbH
+ * Author: Wadim Egorov <w.egorov@phytec.de>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/leds/leds-pca9532.h>
+#include "rk3288-phycore-som.dtsi"
+
+/ {
+       model = "Phytec RK3288 PCM-947";
+       compatible = "phytec,rk3288-pcm-947", "phytec,rk3288-phycore-som", "rockchip,rk3288";
+
+       user_buttons: user-buttons {
+               compatible = "gpio-keys";
+               pinctrl-names = "default";
+               pinctrl-0 = <&user_button_pins>;
+
+               button@0 {
+                       label = "home";
+                       linux,code = <KEY_HOME>;
+                       gpios = <&gpio8 0 GPIO_ACTIVE_HIGH>;
+                       wakeup-source;
+               };
+
+               button@1 {
+                       label = "menu";
+                       linux,code = <KEY_MENU>;
+                       gpios = <&gpio8 3 GPIO_ACTIVE_HIGH>;
+                       wakeup-source;
+               };
+       };
+
+       vcc_host0_5v: usb-host0-regulator {
+               compatible = "regulator-fixed";
+               gpio = <&gpio2 13 GPIO_ACTIVE_HIGH>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&host0_vbus_drv>;
+               regulator-name = "vcc_host0_5v";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-always-on;
+               vin-supply = <&vdd_in_otg_out>;
+       };
+
+       vcc_host1_5v: usb-host1-regulator {
+               compatible = "regulator-fixed";
+               gpio = <&gpio2 0 GPIO_ACTIVE_HIGH>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&host1_vbus_drv>;
+               regulator-name = "vcc_host1_5v";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-always-on;
+               vin-supply = <&vdd_in_otg_out>;
+       };
+
+       vcc_otg_5v: usb-otg-regulator {
+               compatible = "regulator-fixed";
+               gpio = <&gpio2 12 GPIO_ACTIVE_HIGH>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&otg_vbus_drv>;
+               regulator-name = "vcc_otg_5v";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-always-on;
+               vin-supply = <&vdd_in_otg_out>;
+       };
+};
+
+&gmac {
+       status = "okay";
+};
+
+&hdmi {
+       status = "okay";
+};
+
+&i2c1 {
+       status = "okay";
+
+       touchscreen@44 {
+               compatible = "st,stmpe811";
+               reg = <0x44>;
+       };
+
+       adc@64 {
+               compatible = "maxim,max1037";
+               reg = <0x64>;
+       };
+
+       i2c_rtc: rtc@68 {
+               compatible = "rv4162";
+               reg = <0x68>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&i2c_rtc_int>;
+               interrupt-parent = <&gpio5>;
+               interrupts = <10 0>;
+       };
+};
+
+&i2c3 {
+       status = "okay";
+
+       i2c_eeprom_cb: eeprom@51 {
+               compatible = "atmel,24c32";
+               reg = <0x51>;
+               pagesize = <32>;
+       };
+};
+
+&i2c4 {
+       status = "okay";
+
+       /* PCA9533 - 4-bit LED dimmer */
+       leddim: leddimmer@62 {
+               compatible = "nxp,pca9533";
+               reg = <0x62>;
+
+               led1 {
+                       label = "red:user1";
+                       linux,default-trigger = "none";
+                       type = <PCA9532_TYPE_LED>;
+               };
+
+               led2 {
+                       label = "green:user2";
+                       linux,default-trigger = "none";
+                       type = <PCA9532_TYPE_LED>;
+               };
+
+               led3 {
+                       label = "blue:user3";
+                       linux,default-trigger = "none";
+                       type = <PCA9532_TYPE_LED>;
+               };
+
+               led4 {
+                       label = "red:user4";
+                       linux,default-trigger = "none";
+                       type = <PCA9532_TYPE_LED>;
+               };
+       };
+};
+
+&i2c5 {
+       status = "okay";
+};
+
+&pinctrl {
+       pcfg_pull_up_drv_12ma: pcfg-pull-up-drv-12ma {
+               bias-pull-up;
+               drive-strength = <12>;
+       };
+
+       buttons {
+               user_button_pins: user-button-pins {
+                       /* button 1 */
+                       rockchip,pins = <8 3 RK_FUNC_GPIO &pcfg_pull_up>,
+                       /* button 2 */
+                                       <8 0 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+       };
+
+       rv4162 {
+               i2c_rtc_int: i2c-rtc-int {
+                       rockchip,pins = <5 10 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+       };
+
+       sdmmc {
+               /*
+                * Default drive strength isn't enough to achieve even
+                * high-speed mode on pcm-947 board so bump up to 12 mA.
+                */
+               sdmmc_bus4: sdmmc-bus4 {
+                       rockchip,pins = <6 16 RK_FUNC_1 &pcfg_pull_up_drv_12ma>,
+                                       <6 17 RK_FUNC_1 &pcfg_pull_up_drv_12ma>,
+                                       <6 18 RK_FUNC_1 &pcfg_pull_up_drv_12ma>,
+                                       <6 19 RK_FUNC_1 &pcfg_pull_up_drv_12ma>;
+               };
+
+               sdmmc_clk: sdmmc-clk {
+                       rockchip,pins = <6 20 RK_FUNC_1 &pcfg_pull_none_12ma>;
+               };
+
+               sdmmc_cmd: sdmmc-cmd {
+                       rockchip,pins = <6 21 RK_FUNC_1 &pcfg_pull_up_drv_12ma>;
+               };
+
+               sdmmc_pwr: sdmmc-pwr {
+                       rockchip,pins = <7 11 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       touchscreen {
+               ts_irq_pin: ts-irq-pin {
+                       rockchip,pins = <5 15 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       usb_host {
+               host0_vbus_drv: host0-vbus-drv {
+                       rockchip,pins = <2 13 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+
+               host1_vbus_drv: host1-vbus-drv {
+                       rockchip,pins = <2 0 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       usb_otg {
+               otg_vbus_drv: otg-vbus-drv {
+                       rockchip,pins = <2 12 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+};
+
+&sdmmc {
+       bus-width = <4>;
+       cap-mmc-highspeed;
+       cap-sd-highspeed;
+       card-detect-delay = <200>;
+       disable-wp;
+       num-slots = <1>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_bus4>;
+       vmmc-supply = <&vdd_io_sd>;
+       vqmmc-supply = <&vdd_io_sd>;
+       status = "okay";
+};
+
+&uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_xfer &uart0_cts &uart0_rts>;
+       status = "okay";
+};
+
+&uart2 {
+       status = "okay";
+};
+
+&usbphy {
+       status = "okay";
+};
+
+&usb_host0_ehci {
+       status = "okay";
+};
+
+&usb_host1 {
+       status = "okay";
+};
+
+&usb_otg {
+       status = "okay";
+};
diff --git a/arch/arm/boot/dts/rk3288-phycore-som.dtsi b/arch/arm/boot/dts/rk3288-phycore-som.dtsi
new file mode 100644 (file)
index 0000000..26cd3ad
--- /dev/null
@@ -0,0 +1,497 @@
+/*
+ * Device tree file for Phytec phyCORE-RK3288 SoM
+ * Copyright (C) 2017 PHYTEC Messtechnik GmbH
+ * Author: Wadim Egorov <w.egorov@phytec.de>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <dt-bindings/net/ti-dp83867.h>
+#include "rk3288.dtsi"
+
+/ {
+       model = "Phytec RK3288 phyCORE";
+       compatible = "phytec,rk3288-phycore-som", "rockchip,rk3288";
+
+       /*
+        * Set the minimum memory size here and
+        * let the bootloader set the real size.
+        */
+       memory {
+               device_type = "memory";
+               reg = <0 0x8000000>;
+       };
+
+       aliases {
+               rtc0 = &i2c_rtc;
+               rtc1 = &rk818;
+       };
+
+       ext_gmac: external-gmac-clock {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <125000000>;
+               clock-output-names = "ext_gmac";
+       };
+
+       leds: user-leds {
+               compatible = "gpio-leds";
+               pinctrl-names = "default";
+               pinctrl-0 = <&user_led>;
+
+               user {
+                       label = "green_led";
+                       gpios = <&gpio7 2 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "heartbeat";
+                       default-state = "keep";
+               };
+       };
+
+       vdd_emmc_io: vdd-emmc-io {
+               compatible = "regulator-fixed";
+               regulator-name = "vdd_emmc_io";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               vin-supply = <&vdd_3v3_io>;
+       };
+
+       vdd_in_otg_out: vdd-in-otg-out {
+               compatible = "regulator-fixed";
+               regulator-name = "vdd_in_otg_out";
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+       };
+
+       vdd_misc_1v8: vdd-misc-1v8 {
+               compatible = "regulator-fixed";
+               regulator-name = "vdd_misc_1v8";
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+       };
+};
+
+&cpu0 {
+       cpu0-supply = <&vdd_cpu>;
+       operating-points = <
+               /* KHz    uV */
+               1800000 1400000
+               1608000 1350000
+               1512000 1300000
+               1416000 1200000
+               1200000 1100000
+               1008000 1050000
+                816000 1000000
+                696000  950000
+                600000  900000
+                408000  900000
+                312000  900000
+                216000  900000
+                126000  900000
+       >;
+};
+
+&emmc {
+       status = "okay";
+       bus-width = <8>;
+       cap-mmc-highspeed;
+       disable-wp;
+       non-removable;
+       num-slots = <1>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&emmc_clk &emmc_cmd &emmc_pwr &emmc_bus8>;
+       vmmc-supply = <&vdd_3v3_io>;
+       vqmmc-supply = <&vdd_emmc_io>;
+};
+
+&gmac {
+       assigned-clocks = <&cru SCLK_MAC>;
+       assigned-clock-parents = <&ext_gmac>;
+       clock_in_out = "input";
+       pinctrl-names = "default";
+       pinctrl-0 = <&rgmii_pins &phy_rst &phy_int>;
+       phy-handle = <&phy0>;
+       phy-supply = <&vdd_eth_2v5>;
+       phy-mode = "rgmii-id";
+       snps,reset-active-low;
+       snps,reset-delays-us = <0 10000 1000000>;
+       snps,reset-gpio = <&gpio4 8 GPIO_ACTIVE_HIGH>;
+       tx_delay = <0x0>;
+       rx_delay = <0x0>;
+
+       mdio0 {
+               compatible = "snps,dwmac-mdio";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               phy0: ethernet-phy@0 {
+                       compatible = "ethernet-phy-ieee802.3-c22";
+                       reg = <0>;
+                       interrupt-parent = <&gpio4>;
+                       interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
+                       ti,rx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+                       ti,tx-internal-delay = <DP83867_RGMIIDCTL_2_00_NS>;
+                       ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
+                       enet-phy-lane-no-swap;
+               };
+       };
+};
+
+&hdmi {
+       ddc-i2c-bus = <&i2c5>;
+};
+
+&io_domains {
+       status = "okay";
+       sdcard-supply = <&vdd_io_sd>;
+       flash0-supply = <&vdd_emmc_io>;
+       flash1-supply = <&vdd_misc_1v8>;
+       gpio1830-supply = <&vdd_3v3_io>;
+       gpio30-supply = <&vdd_3v3_io>;
+       bb-supply = <&vdd_3v3_io>;
+       dvp-supply = <&vdd_3v3_io>;
+       lcdc-supply = <&vdd_3v3_io>;
+       wifi-supply = <&vdd_3v3_io>;
+       audio-supply = <&vdd_3v3_io>;
+};
+
+&i2c0 {
+       status = "okay";
+       clock-frequency = <400000>;
+
+       rk818: pmic@1c {
+               compatible = "rockchip,rk818";
+               reg = <0x1c>;
+               interrupt-parent = <&gpio0>;
+               interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pmic_int>;
+               rockchip,system-power-controller;
+               wakeup-source;
+               #clock-cells = <1>;
+
+               vcc1-supply = <&vdd_sys>;
+               vcc2-supply = <&vdd_sys>;
+               vcc3-supply = <&vdd_sys>;
+               vcc4-supply = <&vdd_sys>;
+               boost-supply = <&vdd_in_otg_out>;
+               vcc6-supply = <&vdd_sys>;
+               vcc7-supply = <&vdd_misc_1v8>;
+               vcc8-supply = <&vdd_misc_1v8>;
+               vcc9-supply = <&vdd_3v3_io>;
+               vddio-supply = <&vdd_3v3_io>;
+
+               regulators {
+                       vdd_log: DCDC_REG1 {
+                               regulator-name = "vdd_log";
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <1100000>;
+                               regulator-max-microvolt = <1100000>;
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       vdd_gpu: DCDC_REG2 {
+                               regulator-name = "vdd_gpu";
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <800000>;
+                               regulator-max-microvolt = <1250000>;
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <1000000>;
+                               };
+                       };
+
+                       vcc_ddr: DCDC_REG3 {
+                               regulator-name = "vcc_ddr";
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                               };
+                       };
+
+                       vdd_3v3_io: DCDC_REG4 {
+                               regulator-name = "vdd_3v3_io";
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <3300000>;
+                               };
+                       };
+
+                       vdd_sys: DCDC_BOOST {
+                               regulator-name = "vdd_sys";
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <5000000>;
+                               regulator-max-microvolt = <5000000>;
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <5000000>;
+                               };
+                       };
+
+                       /* vcc9 */
+                       vdd_sd: SWITCH_REG {
+                               regulator-name = "vdd_sd";
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       /* vcc6 */
+                       vdd_eth_2v5: LDO_REG2 {
+                               regulator-name = "vdd_eth_2v5";
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <2500000>;
+                               regulator-max-microvolt = <2500000>;
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <2500000>;
+                               };
+                       };
+
+                       /* vcc7 */
+                       vdd_1v0: LDO_REG3 {
+                               regulator-name = "vdd_1v0";
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <1000000>;
+                               };
+                       };
+
+                       /* vcc8 */
+                       vdd_1v8_lcd_ldo: LDO_REG4 {
+                               regulator-name = "vdd_1v8_lcd_ldo";
+                               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>;
+                               };
+                       };
+
+                       /* vcc8 */
+                       vdd_1v0_lcd: LDO_REG6 {
+                               regulator-name = "vdd_1v0_lcd";
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <1000000>;
+                               };
+                       };
+
+                       /* vcc7 */
+                       vdd_1v8_ldo: LDO_REG7 {
+                               regulator-name = "vdd_1v8_ldo";
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                                       regulator-suspend-microvolt = <1800000>;
+                               };
+                       };
+
+                       /* vcc9 */
+                       vdd_io_sd: LDO_REG9 {
+                               regulator-name = "vdd_io_sd";
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <3300000>;
+                               };
+                       };
+               };
+       };
+
+       /* M24C32-D */
+       i2c_eeprom: eeprom@50 {
+               compatible = "atmel,24c32";
+               reg = <0x50>;
+               pagesize = <32>;
+       };
+
+       vdd_cpu: regulator@60 {
+               compatible = "fcs,fan53555";
+               reg = <0x60>;
+               fcs,suspend-voltage-selector = <1>;
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-enable-ramp-delay = <300>;
+               regulator-name = "vdd_cpu";
+               regulator-min-microvolt = <800000>;
+               regulator-max-microvolt = <1430000>;
+               regulator-ramp-delay = <8000>;
+               vin-supply = <&vdd_sys>;
+       };
+};
+
+&pinctrl {
+       pcfg_output_high: pcfg-output-high {
+               output-high;
+       };
+
+       emmc {
+               /*
+                * We run eMMC at max speed; bump up drive strength.
+                * We also have external pulls, so disable the internal ones.
+                */
+               emmc_clk: emmc-clk {
+                       rockchip,pins = <3 18 RK_FUNC_2 &pcfg_pull_none_12ma>;
+               };
+
+               emmc_cmd: emmc-cmd {
+                       rockchip,pins = <3 16 RK_FUNC_2 &pcfg_pull_none_12ma>;
+               };
+
+               emmc_bus8: emmc-bus8 {
+                       rockchip,pins = <3 0 RK_FUNC_2 &pcfg_pull_none_12ma>,
+                                       <3 1 RK_FUNC_2 &pcfg_pull_none_12ma>,
+                                       <3 2 RK_FUNC_2 &pcfg_pull_none_12ma>,
+                                       <3 3 RK_FUNC_2 &pcfg_pull_none_12ma>,
+                                       <3 4 RK_FUNC_2 &pcfg_pull_none_12ma>,
+                                       <3 5 RK_FUNC_2 &pcfg_pull_none_12ma>,
+                                       <3 6 RK_FUNC_2 &pcfg_pull_none_12ma>,
+                                       <3 7 RK_FUNC_2 &pcfg_pull_none_12ma>;
+               };
+       };
+
+       gmac {
+               phy_int: phy-int {
+                       rockchip,pins = <4 2 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+
+               phy_rst: phy-rst {
+                       rockchip,pins = <4 8 RK_FUNC_GPIO &pcfg_output_high>;
+               };
+       };
+
+       leds {
+               user_led: user-led {
+                       rockchip,pins = <7 2 RK_FUNC_GPIO &pcfg_output_high>;
+               };
+       };
+
+       pmic {
+               pmic_int: pmic-int {
+                       rockchip,pins = <RK_GPIO0 4 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+
+               /* Pin for switching state between sleep and non-sleep state */
+               pmic_sleep: pmic-sleep {
+                       rockchip,pins = <RK_GPIO0 0 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+       };
+};
+
+&pwm1 {
+       status = "okay";
+};
+
+&saradc {
+       status = "okay";
+       vref-supply = <&vdd_1v8_ldo>;
+};
+
+&spi2 {
+       status = "okay";
+
+       serial_flash: flash@0 {
+               compatible = "micron,n25q128a13", "jedec,spi-nor";
+               reg = <0x0>;
+               spi-max-frequency = <50000000>;
+               m25p,fast-read;
+               #address-cells = <1>;
+               #size-cells = <1>;
+               status = "okay";
+       };
+};
+
+&tsadc {
+       status = "okay";
+       rockchip,hw-tshut-mode = <0>;
+       rockchip,hw-tshut-polarity = <0>;
+};
+
+&vopb {
+       status = "okay";
+};
+
+&vopb_mmu {
+       status = "okay";
+};
+
+&vopl {
+       status = "okay";
+};
+
+&vopl_mmu {
+       status = "okay";
+};
+
+&wdt {
+       status = "okay";
+};
index 1c0bbc9b928b1e11b779e2c721967c8ec847bd9b..f0778a46bca9b6edd16fc905a442cb53f651d8e3 100644 (file)
                                regulator-always-on;
                        };
 
-                       vcc_io: REG2 {
+                       vcc_io: vccio_codec: REG2 {
                                regulator-name = "VCC_IO";
                                regulator-min-microvolt = <3300000>;
                                regulator-max-microvolt = <3300000>;
index 96a2e745bb9322a33af765265e4f5554f9d22d2b..a23a94811be8ade1bdc6b8233d875c0483b126d4 100644 (file)
                };
        };
 
+       sata_pwr: sata-prw-regulator {
+               compatible = "regulator-fixed";
+               enable-active-high;
+               gpio = <&gpio0 13 GPIO_ACTIVE_HIGH>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&sata_pwr_en>;
+               /* Always turn on the 5V sata power connector */
+               regulator-always-on;
+               regulator-name = "sata_pwr";
+       };
+
        spdif_out: spdif-out {
                compatible = "linux,spdif-dit";
                #sound-dai-cells = <0>;
        };
 
+       sound-i2s {
+               compatible = "rockchip,rk3288-hdmi-analog";
+               pinctrl-names = "default";
+               pinctrl-0 = <&phone_ctl>, <&hp_det>;
+               rockchip,audio-codec = <&es8388>;
+               rockchip,hp-det-gpios = <&gpio7 7 GPIO_ACTIVE_HIGH>;
+               rockchip,hp-en-gpios = <&gpio8 0 GPIO_ACTIVE_HIGH>;
+               rockchip,i2s-controller = <&i2s>;
+               rockchip,model = "I2S";
+               rockchip,routing = "Analog", "LOUT2",
+                                  "Analog", "ROUT2";
+       };
+
        sdio_pwrseq: sdio-pwrseq {
                compatible = "mmc-pwrseq-simple";
                clocks = <&hym8563>;
        };
 };
 
+&i2c2 {
+       status = "okay";
+
+       es8388: es8388@10 {
+               compatible = "everest,es8388", "everest,es8328";
+               reg = <0x10>;
+               AVDD-supply = <&vccio_codec>;
+               DVDD-supply = <&vccio_codec>;
+               HPVDD-supply = <&vccio_codec>;
+               PVDD-supply = <&vccio_codec>;
+               clocks = <&cru SCLK_I2S0_OUT>;
+       };
+};
+
 &i2c5 {
        status = "okay";
 };
 
+&i2s {
+       status = "okay";
+};
+
 &pinctrl {
        ir {
                ir_int: ir-int {
                };
        };
 
+       headphone {
+               hp_det: hp-det {
+                       rockchip,pins = <7 7 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+
+               phone_ctl: phone-ctl {
+                       rockchip,pins = <8 0 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+       };
+
        usb {
                host_vbus_drv: host-vbus-drv {
                        rockchip,pins = <0 14 RK_FUNC_GPIO &pcfg_pull_none>;
                };
        };
 
+       sata {
+               sata_pwr_en: sata-pwr-en {
+                       rockchip,pins = <0 13 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
        sdmmc {
                sdmmc_pwr: sdmmc-pwr {
                        rockchip,pins = <7 11 RK_FUNC_GPIO &pcfg_pull_none>;
 &usb_host0_ehci {
        status = "okay";
 };
+
+&usb_host1 {
+       status = "okay";
+};
diff --git a/arch/arm/boot/dts/rk3288-tinker.dts b/arch/arm/boot/dts/rk3288-tinker.dts
new file mode 100644 (file)
index 0000000..f601c78
--- /dev/null
@@ -0,0 +1,536 @@
+/*
+ * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include "rk3288.dtsi"
+#include <dt-bindings/input/input.h>
+
+/ {
+       model = "Rockchip RK3288 Tinker Board";
+       compatible = "asus,rk3288-tinker", "rockchip,rk3288";
+
+       memory {
+               reg = <0x0 0x80000000>;
+               device_type = "memory";
+       };
+
+       ext_gmac: external-gmac-clock {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <125000000>;
+               clock-output-names = "ext_gmac";
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               autorepeat;
+
+               pinctrl-names = "default";
+               pinctrl-0 = <&pwrbtn>;
+
+               button@0 {
+                       gpios = <&gpio0 RK_PA5 GPIO_ACTIVE_LOW>;
+                       linux,code = <KEY_POWER>;
+                       label = "GPIO Key Power";
+                       linux,input-type = <1>;
+                       wakeup-source;
+                       debounce-interval = <100>;
+               };
+       };
+
+       gpio-leds {
+               compatible = "gpio-leds";
+
+               act-led {
+                       gpios=<&gpio1 RK_PD0 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger="mmc0";
+               };
+
+               heartbeat-led {
+                       gpios=<&gpio1 RK_PD1 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger="heartbeat";
+               };
+
+               pwr-led {
+                       gpios = <&gpio0 RK_PA3 GPIO_ACTIVE_HIGH>;
+                       linux,default-trigger = "default-on";
+               };
+       };
+
+       sound {
+               compatible = "simple-audio-card";
+               simple-audio-card,format = "i2s";
+               simple-audio-card,name = "rockchip,tinker-codec";
+               simple-audio-card,mclk-fs = <512>;
+
+               simple-audio-card,codec {
+                       sound-dai = <&hdmi>;
+               };
+
+               simple-audio-card,cpu {
+                       sound-dai = <&i2s>;
+               };
+       };
+
+       vcc_sys: vsys-regulator {
+               compatible = "regulator-fixed";
+               regulator-name = "vcc_sys";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-always-on;
+               regulator-boot-on;
+       };
+
+       vcc_sd: sdmmc-regulator {
+               compatible = "regulator-fixed";
+               gpio = <&gpio7 11 GPIO_ACTIVE_LOW>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&sdmmc_pwr>;
+               regulator-name = "vcc_sd";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               startup-delay-us = <100000>;
+               vin-supply = <&vcc_io>;
+       };
+};
+
+&cpu0 {
+       cpu0-supply = <&vdd_cpu>;
+};
+
+&gmac {
+       assigned-clocks = <&cru SCLK_MAC>;
+       assigned-clock-parents = <&ext_gmac>;
+       clock_in_out = "input";
+       phy-mode = "rgmii";
+       phy-supply = <&vcc33_lan>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&rgmii_pins>;
+       snps,reset-gpio = <&gpio4 7 0>;
+       snps,reset-active-low;
+       snps,reset-delays-us = <0 10000 1000000>;
+       tx_delay = <0x30>;
+       rx_delay = <0x10>;
+       status = "ok";
+};
+
+&hdmi {
+       ddc-i2c-bus = <&i2c5>;
+       status = "okay";
+};
+
+&i2c0 {
+       clock-frequency = <400000>;
+       status = "okay";
+
+       rk808: pmic@1b {
+               compatible = "rockchip,rk808";
+               reg = <0x1b>;
+               interrupt-parent = <&gpio0>;
+               interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+               #clock-cells = <1>;
+               clock-output-names = "xin32k", "rk808-clkout2";
+               dvs-gpios = <&gpio0 11 GPIO_ACTIVE_HIGH>,
+                               <&gpio0 12 GPIO_ACTIVE_HIGH>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&pmic_int &global_pwroff &dvs_1 &dvs_2>;
+               rockchip,system-power-controller;
+               wakeup-source;
+
+               vcc1-supply = <&vcc_sys>;
+               vcc2-supply = <&vcc_sys>;
+               vcc3-supply = <&vcc_sys>;
+               vcc4-supply = <&vcc_sys>;
+               vcc6-supply = <&vcc_sys>;
+               vcc7-supply = <&vcc_sys>;
+               vcc8-supply = <&vcc_io>;
+               vcc9-supply = <&vcc_io>;
+               vcc10-supply = <&vcc_io>;
+               vcc11-supply = <&vcc_sys>;
+               vcc12-supply = <&vcc_io>;
+               vddio-supply = <&vcc_io>;
+
+               regulators {
+                       vdd_cpu: DCDC_REG1 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <750000>;
+                               regulator-max-microvolt = <1350000>;
+                               regulator-name = "vdd_arm";
+                               regulator-ramp-delay = <6000>;
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       vdd_gpu: DCDC_REG2 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <850000>;
+                               regulator-max-microvolt = <1250000>;
+                               regulator-name = "vdd_gpu";
+                               regulator-ramp-delay = <6000>;
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <1000000>;
+                               };
+                       };
+
+                       vcc_ddr: DCDC_REG3 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-name = "vcc_ddr";
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                               };
+                       };
+
+                       vcc_io: DCDC_REG4 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc_io";
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <3300000>;
+                               };
+                       };
+
+                       vcc18_ldo1: LDO_REG1 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-name = "vcc18_ldo1";
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <1800000>;
+                               };
+                       };
+
+                       vcc33_mipi: LDO_REG2 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <3300000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vcc33_mipi";
+                               regulator-state-mem {
+                                       regulator-off-in-suspend;
+                               };
+                       };
+
+                       vdd_10: LDO_REG3 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-name = "vdd_10";
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <1000000>;
+                               };
+                       };
+
+                       vcc18_codec: LDO_REG4 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-name = "vcc18_codec";
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <1800000>;
+                               };
+                       };
+
+                       vccio_sd: LDO_REG5 {
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <3300000>;
+                               regulator-name = "vccio_sd";
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <3300000>;
+                               };
+                       };
+
+                       vdd10_lcd: LDO_REG6 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <1000000>;
+                               regulator-max-microvolt = <1000000>;
+                               regulator-name = "vdd10_lcd";
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <1000000>;
+                               };
+                       };
+
+                       vcc_18: LDO_REG7 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-name = "vcc_18";
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <1800000>;
+                               };
+                       };
+
+                       vcc18_lcd: LDO_REG8 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-min-microvolt = <1800000>;
+                               regulator-max-microvolt = <1800000>;
+                               regulator-name = "vcc18_lcd";
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                                       regulator-suspend-microvolt = <1800000>;
+                               };
+                       };
+
+                       vcc33_sd: SWITCH_REG1 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-name = "vcc33_sd";
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                               };
+                       };
+
+                       vcc33_lan: SWITCH_REG2 {
+                               regulator-always-on;
+                               regulator-boot-on;
+                               regulator-name = "vcc33_lan";
+                               regulator-state-mem {
+                                       regulator-on-in-suspend;
+                               };
+                       };
+               };
+       };
+};
+
+&i2c2 {
+       status = "okay";
+};
+
+&i2c5 {
+       status = "okay";
+};
+
+&i2s {
+       #sound-dai-cells = <0>;
+       status = "okay";
+};
+
+&io_domains {
+       status = "okay";
+
+       sdcard-supply = <&vccio_sd>;
+};
+
+&pinctrl {
+       pcfg_pull_none_drv_8ma: pcfg-pull-none-drv-8ma {
+               drive-strength = <8>;
+       };
+
+       pcfg_pull_up_drv_8ma: pcfg-pull-up-drv-8ma {
+               bias-pull-up;
+               drive-strength = <8>;
+       };
+
+       backlight {
+               bl_en: bl-en {
+                       rockchip,pins = <7 2 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       buttons {
+               pwrbtn: pwrbtn {
+                       rockchip,pins = <0 5 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+       };
+
+       eth_phy {
+               eth_phy_pwr: eth-phy-pwr {
+                       rockchip,pins = <0 6 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       pmic {
+               pmic_int: pmic-int {
+                       rockchip,pins = <RK_GPIO0 4 RK_FUNC_GPIO \
+                                       &pcfg_pull_up>;
+               };
+
+               dvs_1: dvs-1 {
+                       rockchip,pins = <RK_GPIO0 11 RK_FUNC_GPIO \
+                                       &pcfg_pull_down>;
+               };
+
+               dvs_2: dvs-2 {
+                       rockchip,pins = <RK_GPIO0 12 RK_FUNC_GPIO \
+                                       &pcfg_pull_down>;
+               };
+       };
+
+       sdmmc {
+               sdmmc_bus4: sdmmc-bus4 {
+                       rockchip,pins = <6 16 RK_FUNC_1 &pcfg_pull_up_drv_8ma>,
+                                       <6 17 RK_FUNC_1 &pcfg_pull_up_drv_8ma>,
+                                       <6 18 RK_FUNC_1 &pcfg_pull_up_drv_8ma>,
+                                       <6 19 RK_FUNC_1 &pcfg_pull_up_drv_8ma>;
+               };
+
+               sdmmc_clk: sdmmc-clk {
+                       rockchip,pins = <6 20 RK_FUNC_1 \
+                                       &pcfg_pull_none_drv_8ma>;
+               };
+
+               sdmmc_cmd: sdmmc-cmd {
+                       rockchip,pins = <6 21 RK_FUNC_1 &pcfg_pull_up_drv_8ma>;
+               };
+
+               sdmmc_pwr: sdmmc-pwr {
+                       rockchip,pins = <7 11 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       usb {
+               host_vbus_drv: host-vbus-drv {
+                       rockchip,pins = <0 14 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+
+               pwr_3g: pwr-3g {
+                       rockchip,pins = <7 8 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+};
+
+&pwm0 {
+       status = "okay";
+};
+
+&saradc {
+       vref-supply = <&vcc18_ldo1>;
+       status ="okay";
+};
+
+&sdmmc {
+       bus-width = <4>;
+       cap-mmc-highspeed;
+       cap-sd-highspeed;
+       card-detect-delay = <200>;
+       disable-wp;                     /* wp not hooked up */
+       num-slots = <1>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_bus4>;
+       status = "okay";
+       vmmc-supply = <&vcc33_sd>;
+       vqmmc-supply = <&vccio_sd>;
+};
+
+&tsadc {
+       rockchip,hw-tshut-mode = <1>; /* tshut mode 0:CRU 1:GPIO */
+       rockchip,hw-tshut-polarity = <1>; /* tshut polarity 0:LOW 1:HIGH */
+       status = "okay";
+};
+
+&uart0 {
+       status = "okay";
+};
+
+&uart1 {
+       status = "okay";
+};
+
+&uart2 {
+       status = "okay";
+};
+
+&uart3 {
+       status = "okay";
+};
+
+&uart4 {
+       status = "okay";
+};
+
+&usbphy {
+       status = "okay";
+};
+
+&usb_host0_ehci {
+       status = "okay";
+};
+
+&usb_host1 {
+       status = "okay";
+};
+
+&usb_otg {
+       status= "okay";
+};
+
+&vopb {
+       status = "okay";
+};
+
+&vopb_mmu {
+       status = "okay";
+};
+
+&vopl {
+       status = "okay";
+};
+
+&vopl_mmu {
+       status = "okay";
+};
+
+&wdt {
+       status = "okay";
+};
index df8a0dbe9d910aa44174bcfb4400aa445859a72e..ad5d6022e95fe58ba1f354473cc53d397f04ebf8 100644 (file)
                fifo-depth = <0x100>;
                interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
                reg = <0xff0c0000 0x4000>;
+               resets = <&cru SRST_MMC0>;
+               reset-names = "reset";
                status = "disabled";
        };
 
                fifo-depth = <0x100>;
                interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
                reg = <0xff0d0000 0x4000>;
+               resets = <&cru SRST_SDIO0>;
+               reset-names = "reset";
                status = "disabled";
        };
 
                fifo-depth = <0x100>;
                interrupts = <GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>;
                reg = <0xff0e0000 0x4000>;
+               resets = <&cru SRST_SDIO1>;
+               reset-names = "reset";
                status = "disabled";
        };
 
                fifo-depth = <0x100>;
                interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
                reg = <0xff0f0000 0x4000>;
+               resets = <&cru SRST_EMMC>;
+               reset-names = "reset";
                status = "disabled";
        };
 
index 0b45811cf28bb246cfad4425c135ca802b0d76ea..4aa6f60d6a22eddf372c34cc18769347e65fa48c 100644 (file)
        global_timer: global-timer@1013c200 {
                compatible = "arm,cortex-a9-global-timer";
                reg = <0x1013c200 0x20>;
-               interrupts = <GIC_PPI 11 0x304>;
+               interrupts = <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_EDGE_RISING)>;
                clocks = <&cru CORE_PERI>;
        };
 
        local_timer: local-timer@1013c600 {
                compatible = "arm,cortex-a9-twd-timer";
                reg = <0x1013c600 0x20>;
-               interrupts = <GIC_PPI 13 0x304>;
+               interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_EDGE_RISING)>;
                clocks = <&cru CORE_PERI>;
        };
 
                interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&cru HCLK_SDMMC>, <&cru SCLK_SDMMC>;
                clock-names = "biu", "ciu";
+               dmas = <&dmac2 1>;
+               dma-names = "rx-tx";
                fifo-depth = <256>;
+               resets = <&cru SRST_SDMMC>;
+               reset-names = "reset";
                status = "disabled";
        };
 
                interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&cru HCLK_SDIO>, <&cru SCLK_SDIO>;
                clock-names = "biu", "ciu";
+               dmas = <&dmac2 3>;
+               dma-names = "rx-tx";
                fifo-depth = <256>;
+               resets = <&cru SRST_SDIO>;
+               reset-names = "reset";
                status = "disabled";
        };
 
                interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
                clocks = <&cru HCLK_EMMC>, <&cru SCLK_EMMC>;
                clock-names = "biu", "ciu";
+               dmas = <&dmac2 4>;
+               dma-names = "rx-tx";
                fifo-depth = <256>;
+               resets = <&cru SRST_EMMC>;
+               reset-names = "reset";
                status = "disabled";
        };
 
index 0ccb414cd2687c9567e492972528db4101d26199..c55cbb3af2c0c1dcded36f055c3b031e80ff32f4 100644 (file)
                };
 
                watchdog: watchdog@7e004000 {
-                       compatible = "samsung,s3c2410-wdt";
+                       compatible = "samsung,s3c6410-wdt";
                        reg = <0x7e004000 0x1000>;
                        interrupt-parent = <&vic0>;
                        interrupts = <26>;
                        clock-names = "watchdog";
                        clocks = <&clocks PCLK_WDT>;
-                       status = "disabled";
                };
 
                i2c0: i2c@7f004000 {
index a853918be43fcf044252f767d0ef419234799e61..726c5d0dbd5bce6451c0c25f510e7ddabee108bf 100644 (file)
                };
 
                watchdog: watchdog@e2700000 {
-                       compatible = "samsung,s3c2410-wdt";
+                       compatible = "samsung,s3c6410-wdt";
                        reg = <0xe2700000 0x1000>;
                        interrupt-parent = <&vic0>;
                        interrupts = <26>;
index 528b4e9c6d3d30928d363ffc6cf1d8d2275a8ce7..8067c71c3a38a956d93ccaaaf53e724715243328 100644 (file)
                                status = "okay";
                        };
 
+                       sfrbu: sfr@fc05c000 {
+                               compatible = "atmel,sama5d2-sfrbu", "syscon";
+                               reg = <0xfc05c000 0x20>;
+                       };
+
                        chipid@fc069000 {
                                compatible = "atmel,sama5d2-chipid";
                                reg = <0xfc069000 0x8>;
index 2c43c4d85deec3e4308c56b038dc5865d1c23874..b2674bdb8e6a9bb477a0c93341cdb58f399131eb 100644 (file)
@@ -15,7 +15,6 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "skeleton.dtsi"
 #include <dt-bindings/reset/altr,rst-mgr.h>
 
 / {
                #size-cells = <0>;
                enable-method = "altr,socfpga-smp";
 
-               cpu@0 {
+               cpu0: cpu@0 {
                        compatible = "arm,cortex-a9";
                        device_type = "cpu";
                        reg = <0>;
                        next-level-cache = <&L2>;
                };
-               cpu@1 {
+               cpu1: cpu@1 {
                        compatible = "arm,cortex-a9";
                        device_type = "cpu";
                        reg = <1>;
                };
        };
 
+       pmu: pmu@ff111000 {
+               compatible = "arm,cortex-a9-pmu";
+               interrupt-parent = <&intc>;
+               interrupts = <0 176 4>, <0 177 4>;
+               interrupt-affinity = <&cpu0>, <&cpu1>;
+               reg = <0xff111000 0x1000>,
+                     <0xff113000 0x1000>;
+       };
+
        intc: intc@fffed000 {
                compatible = "arm,cortex-a9-gic";
                #interrupt-cells = <3>;
                                                compatible = "fixed-clock";
                                        };
 
-                                       main_pll: main_pll {
+                                       main_pll: main_pll@40 {
                                                #address-cells = <1>;
                                                #size-cells = <0>;
                                                #clock-cells = <0>;
                                                clocks = <&osc1>;
                                                reg = <0x40>;
 
-                                               mpuclk: mpuclk {
+                                               mpuclk: mpuclk@48 {
                                                        #clock-cells = <0>;
                                                        compatible = "altr,socfpga-perip-clk";
                                                        clocks = <&main_pll>;
                                                        reg = <0x48>;
                                                };
 
-                                               mainclk: mainclk {
+                                               mainclk: mainclk@4c {
                                                        #clock-cells = <0>;
                                                        compatible = "altr,socfpga-perip-clk";
                                                        clocks = <&main_pll>;
                                                        reg = <0x4C>;
                                                };
 
-                                               dbg_base_clk: dbg_base_clk {
+                                               dbg_base_clk: dbg_base_clk@50 {
                                                        #clock-cells = <0>;
                                                        compatible = "altr,socfpga-perip-clk";
                                                        clocks = <&main_pll>, <&osc1>;
                                                        reg = <0x50>;
                                                };
 
-                                               main_qspi_clk: main_qspi_clk {
+                                               main_qspi_clk: main_qspi_clk@54 {
                                                        #clock-cells = <0>;
                                                        compatible = "altr,socfpga-perip-clk";
                                                        clocks = <&main_pll>;
                                                        reg = <0x54>;
                                                };
 
-                                               main_nand_sdmmc_clk: main_nand_sdmmc_clk {
+                                               main_nand_sdmmc_clk: main_nand_sdmmc_clk@58 {
                                                        #clock-cells = <0>;
                                                        compatible = "altr,socfpga-perip-clk";
                                                        clocks = <&main_pll>;
                                                        reg = <0x58>;
                                                };
 
-                                               cfg_h2f_usr0_clk: cfg_h2f_usr0_clk {
+                                               cfg_h2f_usr0_clk: cfg_h2f_usr0_clk@5c {
                                                        #clock-cells = <0>;
                                                        compatible = "altr,socfpga-perip-clk";
                                                        clocks = <&main_pll>;
                                                };
                                        };
 
-                                       periph_pll: periph_pll {
+                                       periph_pll: periph_pll@80 {
                                                #address-cells = <1>;
                                                #size-cells = <0>;
                                                #clock-cells = <0>;
                                                clocks = <&osc1>, <&osc2>, <&f2s_periph_ref_clk>;
                                                reg = <0x80>;
 
-                                               emac0_clk: emac0_clk {
+                                               emac0_clk: emac0_clk@88 {
                                                        #clock-cells = <0>;
                                                        compatible = "altr,socfpga-perip-clk";
                                                        clocks = <&periph_pll>;
                                                        reg = <0x88>;
                                                };
 
-                                               emac1_clk: emac1_clk {
+                                               emac1_clk: emac1_clk@8c {
                                                        #clock-cells = <0>;
                                                        compatible = "altr,socfpga-perip-clk";
                                                        clocks = <&periph_pll>;
                                                        reg = <0x8C>;
                                                };
 
-                                               per_qspi_clk: per_qsi_clk {
+                                               per_qspi_clk: per_qsi_clk@90 {
                                                        #clock-cells = <0>;
                                                        compatible = "altr,socfpga-perip-clk";
                                                        clocks = <&periph_pll>;
                                                        reg = <0x90>;
                                                };
 
-                                               per_nand_mmc_clk: per_nand_mmc_clk {
+                                               per_nand_mmc_clk: per_nand_mmc_clk@94 {
                                                        #clock-cells = <0>;
                                                        compatible = "altr,socfpga-perip-clk";
                                                        clocks = <&periph_pll>;
                                                        reg = <0x94>;
                                                };
 
-                                               per_base_clk: per_base_clk {
+                                               per_base_clk: per_base_clk@98 {
                                                        #clock-cells = <0>;
                                                        compatible = "altr,socfpga-perip-clk";
                                                        clocks = <&periph_pll>;
                                                        reg = <0x98>;
                                                };
 
-                                               h2f_usr1_clk: h2f_usr1_clk {
+                                               h2f_usr1_clk: h2f_usr1_clk@9c {
                                                        #clock-cells = <0>;
                                                        compatible = "altr,socfpga-perip-clk";
                                                        clocks = <&periph_pll>;
                                                };
                                        };
 
-                                       sdram_pll: sdram_pll {
+                                       sdram_pll: sdram_pll@c0 {
                                                #address-cells = <1>;
                                                #size-cells = <0>;
                                                #clock-cells = <0>;
                                                clocks = <&osc1>, <&osc2>, <&f2s_sdram_ref_clk>;
                                                reg = <0xC0>;
 
-                                               ddr_dqs_clk: ddr_dqs_clk {
+                                               ddr_dqs_clk: ddr_dqs_clk@c8 {
                                                        #clock-cells = <0>;
                                                        compatible = "altr,socfpga-perip-clk";
                                                        clocks = <&sdram_pll>;
                                                        reg = <0xC8>;
                                                };
 
-                                               ddr_2x_dqs_clk: ddr_2x_dqs_clk {
+                                               ddr_2x_dqs_clk: ddr_2x_dqs_clk@cc {
                                                        #clock-cells = <0>;
                                                        compatible = "altr,socfpga-perip-clk";
                                                        clocks = <&sdram_pll>;
                                                        reg = <0xCC>;
                                                };
 
-                                               ddr_dq_clk: ddr_dq_clk {
+                                               ddr_dq_clk: ddr_dq_clk@d0 {
                                                        #clock-cells = <0>;
                                                        compatible = "altr,socfpga-perip-clk";
                                                        clocks = <&sdram_pll>;
                                                        reg = <0xD0>;
                                                };
 
-                                               h2f_usr2_clk: h2f_usr2_clk {
+                                               h2f_usr2_clk: h2f_usr2_clk@d4 {
                                                        #clock-cells = <0>;
                                                        compatible = "altr,socfpga-perip-clk";
                                                        clocks = <&sdram_pll>;
                        status = "disabled";
                };
 
-               eccmgr: eccmgr@ffd08140 {
+               eccmgr: eccmgr {
                        compatible = "altr,socfpga-ecc-manager";
                        #address-cells = <1>;
                        #size-cells = <1>;
                        dma-names = "tx", "rx";
                };
 
-               usbphy0: usbphy@0 {
+               usbphy0: usbphy {
                        #phy-cells = <0>;
                        compatible = "usb-nop-xceiv";
                        status = "okay";
index 6b0b7463f36f8bef0acc65cf2b2d32a12011f20e..bead79e4b2aa2b624b8f7d21cef4751d6536b724 100644 (file)
@@ -14,7 +14,6 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include "skeleton.dtsi"
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/reset/altr,rst-mgr-a10.h>
 
                                                compatible = "fixed-clock";
                                        };
 
-                                       main_pll: main_pll {
+                                       main_pll: main_pll@40 {
                                                #address-cells = <1>;
                                                #size-cells = <0>;
                                                #clock-cells = <0>;
                                                        div-reg = <0x144 0 11>;
                                                };
 
-                                               main_emaca_clk: main_emaca_clk {
+                                               main_emaca_clk: main_emaca_clk@68 {
                                                        #clock-cells = <0>;
                                                        compatible = "altr,socfpga-a10-perip-clk";
                                                        clocks = <&main_pll>;
                                                        reg = <0x68>;
                                                };
 
-                                               main_emacb_clk: main_emacb_clk {
+                                               main_emacb_clk: main_emacb_clk@6c {
                                                        #clock-cells = <0>;
                                                        compatible = "altr,socfpga-a10-perip-clk";
                                                        clocks = <&main_pll>;
                                                        reg = <0x6C>;
                                                };
 
-                                               main_emac_ptp_clk: main_emac_ptp_clk {
+                                               main_emac_ptp_clk: main_emac_ptp_clk@70 {
                                                        #clock-cells = <0>;
                                                        compatible = "altr,socfpga-a10-perip-clk";
                                                        clocks = <&main_pll>;
                                                        reg = <0x70>;
                                                };
 
-                                               main_gpio_db_clk: main_gpio_db_clk {
+                                               main_gpio_db_clk: main_gpio_db_clk@74 {
                                                        #clock-cells = <0>;
                                                        compatible = "altr,socfpga-a10-perip-clk";
                                                        clocks = <&main_pll>;
                                                        reg = <0x74>;
                                                };
 
-                                               main_sdmmc_clk: main_sdmmc_clk {
+                                               main_sdmmc_clk: main_sdmmc_clk@78 {
                                                        #clock-cells = <0>;
                                                        compatible = "altr,socfpga-a10-perip-clk"
 ;
                                                        reg = <0x78>;
                                                };
 
-                                               main_s2f_usr0_clk: main_s2f_usr0_clk {
+                                               main_s2f_usr0_clk: main_s2f_usr0_clk@7c {
                                                        #clock-cells = <0>;
                                                        compatible = "altr,socfpga-a10-perip-clk";
                                                        clocks = <&main_pll>;
                                                        reg = <0x7C>;
                                                };
 
-                                               main_s2f_usr1_clk: main_s2f_usr1_clk {
+                                               main_s2f_usr1_clk: main_s2f_usr1_clk@80 {
                                                        #clock-cells = <0>;
                                                        compatible = "altr,socfpga-a10-perip-clk";
                                                        clocks = <&main_pll>;
                                                        reg = <0x80>;
                                                };
 
-                                               main_hmc_pll_ref_clk: main_hmc_pll_ref_clk {
+                                               main_hmc_pll_ref_clk: main_hmc_pll_ref_clk@84 {
                                                        #clock-cells = <0>;
                                                        compatible = "altr,socfpga-a10-perip-clk";
                                                        clocks = <&main_pll>;
                                                        reg = <0x84>;
                                                };
 
-                                               main_periph_ref_clk: main_periph_ref_clk {
+                                               main_periph_ref_clk: main_periph_ref_clk@9c {
                                                        #clock-cells = <0>;
                                                        compatible = "altr,socfpga-a10-perip-clk";
                                                        clocks = <&main_pll>;
                                                };
                                        };
 
-                                       periph_pll: periph_pll {
+                                       periph_pll: periph_pll@c0 {
                                                #address-cells = <1>;
                                                #size-cells = <0>;
                                                #clock-cells = <0>;
                                                        div-reg = <0x144 16 11>;
                                                };
 
-                                               peri_emaca_clk: peri_emaca_clk {
+                                               peri_emaca_clk: peri_emaca_clk@e8 {
                                                        #clock-cells = <0>;
                                                        compatible = "altr,socfpga-a10-perip-clk";
                                                        clocks = <&periph_pll>;
                                                        reg = <0xE8>;
                                                };
 
-                                               peri_emacb_clk: peri_emacb_clk {
+                                               peri_emacb_clk: peri_emacb_clk@ec {
                                                        #clock-cells = <0>;
                                                        compatible = "altr,socfpga-a10-perip-clk";
                                                        clocks = <&periph_pll>;
                                                        reg = <0xEC>;
                                                };
 
-                                               peri_emac_ptp_clk: peri_emac_ptp_clk {
+                                               peri_emac_ptp_clk: peri_emac_ptp_clk@f0 {
                                                        #clock-cells = <0>;
                                                        compatible = "altr,socfpga-a10-perip-clk";
                                                        clocks = <&periph_pll>;
                                                        reg = <0xF0>;
                                                };
 
-                                               peri_gpio_db_clk: peri_gpio_db_clk {
+                                               peri_gpio_db_clk: peri_gpio_db_clk@f4 {
                                                        #clock-cells = <0>;
                                                        compatible = "altr,socfpga-a10-perip-clk";
                                                        clocks = <&periph_pll>;
                                                        reg = <0xF4>;
                                                };
 
-                                               peri_sdmmc_clk: peri_sdmmc_clk {
+                                               peri_sdmmc_clk: peri_sdmmc_clk@f8 {
                                                        #clock-cells = <0>;
                                                        compatible = "altr,socfpga-a10-perip-clk";
                                                        clocks = <&periph_pll>;
                                                        reg = <0xF8>;
                                                };
 
-                                               peri_s2f_usr0_clk: peri_s2f_usr0_clk {
+                                               peri_s2f_usr0_clk: peri_s2f_usr0_clk@fc {
                                                        #clock-cells = <0>;
                                                        compatible = "altr,socfpga-a10-perip-clk";
                                                        clocks = <&periph_pll>;
                                                        reg = <0xFC>;
                                                };
 
-                                               peri_s2f_usr1_clk: peri_s2f_usr1_clk {
+                                               peri_s2f_usr1_clk: peri_s2f_usr1_clk@100 {
                                                        #clock-cells = <0>;
                                                        compatible = "altr,socfpga-a10-perip-clk";
                                                        clocks = <&periph_pll>;
                                                        reg = <0x100>;
                                                };
 
-                                               peri_hmc_pll_ref_clk: peri_hmc_pll_ref_clk {
+                                               peri_hmc_pll_ref_clk: peri_hmc_pll_ref_clk@104 {
                                                        #clock-cells = <0>;
                                                        compatible = "altr,socfpga-a10-perip-clk";
                                                        clocks = <&periph_pll>;
                                                };
                                        };
 
-                                       mpu_free_clk: mpu_free_clk {
+                                       mpu_free_clk: mpu_free_clk@60 {
                                                #clock-cells = <0>;
                                                compatible = "altr,socfpga-a10-perip-clk";
                                                clocks = <&main_mpu_base_clk>, <&peri_mpu_base_clk>,
                                                reg = <0x60>;
                                        };
 
-                                       noc_free_clk: noc_free_clk {
+                                       noc_free_clk: noc_free_clk@64 {
                                                #clock-cells = <0>;
                                                compatible = "altr,socfpga-a10-perip-clk";
                                                clocks = <&main_noc_base_clk>, <&peri_noc_base_clk>,
                                                reg = <0x64>;
                                        };
 
-                                       s2f_user1_free_clk: s2f_user1_free_clk {
+                                       s2f_user1_free_clk: s2f_user1_free_clk@104 {
                                                #clock-cells = <0>;
                                                compatible = "altr,socfpga-a10-perip-clk";
                                                clocks = <&main_s2f_usr1_clk>, <&peri_s2f_usr1_clk>,
                                                reg = <0x104>;
                                        };
 
-                                       sdmmc_free_clk: sdmmc_free_clk {
+                                       sdmmc_free_clk: sdmmc_free_clk@f8 {
                                                #clock-cells = <0>;
                                                compatible = "altr,socfpga-a10-perip-clk";
                                                clocks = <&main_sdmmc_clk>, <&peri_sdmmc_clk>,
                        reg = <0xffe00000 0x40000>;
                };
 
-               eccmgr: eccmgr@ffd06000 {
+               eccmgr: eccmgr {
                        compatible = "altr,socfpga-a10-ecc-manager";
                        altr,sysmgr-syscon = <&sysmgr>;
                        #address-cells = <1>;
                        status = "disabled";
                };
 
-               usbphy0: usbphy@0 {
+               usbphy0: usbphy {
                        #phy-cells = <0>;
                        compatible = "usb-nop-xceiv";
                        status = "okay";
index c57e6cea0d83dfd8fbef1de65ca6635cbfc2abd8..94e088473823bcc7bc6e0644930cdb4cb1f1bc06 100644 (file)
@@ -30,7 +30,7 @@
                stdout-path = "serial0:115200n8";
        };
 
-       memory {
+       memory@0 {
                name = "memory";
                device_type = "memory";
                reg = <0x0 0x40000000>; /* 1GB */
                        gpio-controller;
                        #gpio-cells = <2>;
                };
+
+               a10sr_rst: reset-controller {
+                       compatible = "altr,a10sr-reset";
+                       #reset-cells = <1>;
+               };
        };
 };
 
index 8672edf9ba4ebccb6c4b131909bccd6d9d8070bb..aac4feea86f38c9d589ad814c6a6c0d0863711e7 100644 (file)
@@ -26,7 +26,7 @@
                stdout-path = "serial0:115200n8";
        };
 
-       memory {
+       memory@0 {
                name = "memory";
                device_type = "memory";
                reg = <0x0 0x40000000>; /* 1GB */
index 5ecd2ef405e315e91abaa6e810c60f752619a2e7..7b49395452b6f0133fcb7e67a52c4b84c0dbaaa4 100644 (file)
@@ -25,7 +25,7 @@
                stdout-path = "serial0:115200n8";
        };
 
-       memory {
+       memory@0 {
                name = "memory";
                device_type = "memory";
                reg = <0x0 0x40000000>; /* 1GB */
index 6ad3b1eb9b86f933b8a23e19684dcac59f621be4..3c03da6b8b1d147bfbbaa850736400c0891e3d68 100644 (file)
@@ -21,7 +21,7 @@
        model = "Aries/DENX MCV";
        compatible = "altr,socfpga-cyclone5", "altr,socfpga";
 
-       memory {
+       memory@0 {
                name = "memory";
                device_type = "memory";
                reg = <0x0 0x40000000>; /* 1 GiB */
index e5a98e5696ca23be228b3a6614b46ddea268ebbb..21e397287e295a082d28528e92e3bc6a0cab82b8 100644 (file)
@@ -71,7 +71,6 @@
 
                stmpe_touchscreen {
                        compatible = "st,stmpe-ts";
-                       reg = <0>;
                        ts,sample-time = <4>;
                        ts,mod-12b = <1>;
                        ts,ref-sel = <0>;
index 7ea32c81e72090a4fe4f175d10f1ee40a1b42a90..155829f9eba16d173fe8b9d958e239dabfb6b5d9 100644 (file)
@@ -26,7 +26,7 @@
                stdout-path = "serial0:115200n8";
        };
 
-       memory {
+       memory@0 {
                name = "memory";
                device_type = "memory";
                reg = <0x0 0x40000000>; /* 1GB */
index a0c90b3bdfd13d537eff4d743137874a5d488641..a4a555c19d94374dbaa29ef30ecc80de1420a45b 100644 (file)
@@ -26,7 +26,7 @@
                stdout-path = "serial0:115200n8";
        };
 
-       memory {
+       memory@0 {
                name = "memory";
                device_type = "memory";
                reg = <0x0 0x40000000>; /* 1GB */
index c3d52f27b21ef9f4d3bf8f378ad27ec13f0851dc..53bf99eef66de70fba4647fb9592750afffee486 100644 (file)
@@ -25,7 +25,7 @@
                bootargs = "console=ttyS0,115200";
        };
 
-       memory {
+       memory@0 {
                name = "memory";
                device_type = "memory";
                reg = <0x0 0x40000000>; /* 1GB */
 &leds {
        compatible = "gpio-leds";
 
-       led@0 {
+       led0 {
                label = "led:green:heartbeat";
                gpios = <&porta 28 1>;
                linux,default-trigger = "heartbeat";
        };
 
-       led@1 {
+       led1 {
                label = "led:green:D7";
                gpios = <&portb 19 1>;
        };
 
-       led@2 {
+       led2 {
                label = "led:green:D8";
                gpios = <&portb 25 1>;
        };
index 5b7e3c27e6e9058948557436bf5f1de5f3ed2321..8860dd2e242c4b62683f7532c0d347bf38ee02db 100644 (file)
@@ -28,7 +28,7 @@
                stdout-path = "serial0:115200n8";
        };
 
-       memory {
+       memory@0 {
                name = "memory";
                device_type = "memory";
                reg = <0x0 0x40000000>;
 &usb1 {
        status = "okay";
 };
+
+&qspi {
+        status = "okay";
+
+        flash0: n25q512a@0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "n25q512a";
+               reg = <0>;
+               spi-max-frequency = <100000000>;
+
+               m25p,fast-read;
+               cdns,page-size = <256>;
+               cdns,block-size = <16>;
+               cdns,read-delay = <4>;
+               cdns,tshsl-ns = <50>;
+               cdns,tsd2d-ns = <50>;
+               cdns,tchsh-ns = <4>;
+               cdns,tslch-ns = <4>;
+       };
+};
index 363ee62457fea072e0cf01b1ef78d216993e33bc..89319804939718632e0f7f890c5e51d0b9298525 100644 (file)
@@ -57,7 +57,7 @@
                bootargs = "console=ttyS0,115200";
        };
 
-       memory {
+       memory@0 {
                name = "memory";
                device_type = "memory";
                reg = <0x0 0x40000000>; /* 1GB */
index f9345e02ca49e069b846563dc474432b77377b45..dfe2193cd4d5b5a657cbb4facbff90a1272fd966 100644 (file)
@@ -26,7 +26,7 @@
                bootargs = "console=ttyS0,57600";
        };
 
-       memory {
+       memory@0 {
                name = "memory";
                device_type = "memory";
                reg = <0x0 0x40000000>; /* 1 GB */
index d865a891776df9cf60d6052bf1cdfc753400ebd9..c67e76c8ba5d5b90a9b875fb689825fbb90bc891 100644 (file)
                device_type = "memory";
                reg = <0 0x10000000>;
        };
+};
 
-       ahb {
-               clcd@fc200000 {
-                       status = "okay";
-               };
+&clcd {
+       status = "okay";
+};
 
-               dma@fc400000 {
-                       status = "okay";
-               };
+&dmac {
+       status = "okay";
+};
 
-               ehci@e1800000 {
-                       status = "okay";
-               };
+&ehci_usb0 {
+       status = "okay";
+};
 
-               ehci@e2000000 {
-                       status = "okay";
-               };
+&ehci_usb1 {
+       status = "okay";
+};
 
-               gmac: ethernet@e0800000 {
-                       phy-mode = "gmii";
-                       status = "okay";
-               };
+&gmac {
+       phy-mode = "gmii";
+       status = "okay";
+};
 
-               ohci@e1900000 {
-                       status = "okay";
-               };
+&ohci_usb0 {
+       status = "okay";
+};
 
-               ohci@e2100000 {
-                       status = "okay";
-               };
+&ohci_usb1 {
+       status = "okay";
+};
 
-               smi: flash@fc000000 {
-                       status = "okay";
-                       clock-rate=<50000000>;
-
-                       flash@f8000000 {
-                               #address-cells = <1>;
-                               #size-cells = <1>;
-                               reg = <0xf8000000 0x800000>;
-                               st,smi-fast-mode;
-
-                               partition@0 {
-                                       label = "xloader";
-                                       reg = <0x0 0x10000>;
-                               };
-                               partition@10000 {
-                                       label = "u-boot";
-                                       reg = <0x10000 0x50000>;
-                               };
-                               partition@60000 {
-                                       label = "environment";
-                                       reg = <0x60000 0x10000>;
-                               };
-                               partition@70000 {
-                                       label = "dtb";
-                                       reg = <0x70000 0x10000>;
-                               };
-                               partition@80000 {
-                                       label = "linux";
-                                       reg = <0x80000 0x310000>;
-                               };
-                               partition@390000 {
-                                       label = "rootfs";
-                                       reg = <0x390000 0x0>;
-                               };
-                       };
-               };
+&smi {
+       status = "okay";
+       clock-rate = <50000000>;
 
-               apb {
-                       serial@d0000000 {
-                               status = "okay";
-                               pinctrl-names = "default";
-                               pinctrl-0 = <>;
-                       };
+       flash@f8000000 {
+               reg = <0xf8000000 0x800000>;
+               st,smi-fast-mode;
 
-                       serial@d0080000 {
-                               status = "okay";
-                               pinctrl-names = "default";
-                               pinctrl-0 = <>;
-                       };
+               partitions {
+                       compatible = "fixed-partitions";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
 
-                       rtc@fc900000 {
-                              status = "okay";
+                       partition@0 {
+                               label = "xloader";
+                               reg = <0x0 0x10000>;
                        };
-
-                       i2c@d0200000 {
-                               clock-frequency = <400000>;
-                               status = "okay";
+                       partition@10000 {
+                               label = "u-boot";
+                               reg = <0x10000 0x50000>;
+                       };
+                       partition@60000 {
+                               label = "environment";
+                               reg = <0x60000 0x10000>;
+                       };
+                       partition@70000 {
+                               label = "dtb";
+                               reg = <0x70000 0x10000>;
+                       };
+                       partition@80000 {
+                               label = "linux";
+                               reg = <0x80000 0x310000>;
+                       };
+                       partition@390000 {
+                               label = "rootfs";
+                               reg = <0x390000 0x0>;
                        };
                };
        };
 };
+
+&uart0 {
+       status = "okay";
+};
+
+&uart1 {
+       status = "okay";
+};
+
+&rtc {
+       status = "okay";
+};
+
+&i2c {
+       clock-frequency = <400000>;
+       status = "okay";
+};
index 9f60a7b6a42bf42e0b84584d94b48b7888ea58a0..6b32d20acc9f4bef1285a51f3045c5ffca6e22b0 100644 (file)
@@ -49,7 +49,7 @@
                        #interrupt-cells = <1>;
                };
 
-               clcd@fc200000 {
+               clcd: clcd@fc200000 {
                        compatible = "arm,pl110", "arm,primecell";
                        reg = <0xfc200000 0x1000>;
                        interrupt-parent = <&vic1>;
@@ -57,7 +57,7 @@
                        status = "disabled";
                };
 
-               dma@fc400000 {
+               dmac: dma@fc400000 {
                        compatible = "arm,pl080", "arm,primecell";
                        reg = <0xfc400000 0x1000>;
                        interrupt-parent = <&vic1>;
@@ -97,7 +97,7 @@
                        status = "disabled";
                };
 
-               ehci@e1800000 {
+               ehci_usb0: ehci@e1800000 {
                        compatible = "st,spear600-ehci", "usb-ehci";
                        reg = <0xe1800000 0x1000>;
                        interrupt-parent = <&vic1>;
                        status = "disabled";
                };
 
-               ehci@e2000000 {
+               ehci_usb1: ehci@e2000000 {
                        compatible = "st,spear600-ehci", "usb-ehci";
                        reg = <0xe2000000 0x1000>;
                        interrupt-parent = <&vic1>;
                        status = "disabled";
                };
 
-               ohci@e1900000 {
+               ohci_usb0: ohci@e1900000 {
                        compatible = "st,spear600-ohci", "usb-ohci";
                        reg = <0xe1900000 0x1000>;
                        interrupt-parent = <&vic1>;
                        status = "disabled";
                };
 
-               ohci@e2100000 {
+               ohci_usb1: ohci@e2100000 {
                        compatible = "st,spear600-ohci", "usb-ohci";
                        reg = <0xe2100000 0x1000>;
                        interrupt-parent = <&vic1>;
                        compatible = "simple-bus";
                        ranges = <0xd0000000 0xd0000000 0x30000000>;
 
-                       serial@d0000000 {
+                       uart0: serial@d0000000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0xd0000000 0x1000>;
                                interrupt-parent = <&vic0>;
                                status = "disabled";
                        };
 
-                       serial@d0080000 {
+                       uart1: serial@d0080000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0xd0080000 0x1000>;
                                interrupt-parent = <&vic0>;
                                interrupts = <4>;
                        };
 
-                       i2c@d0200000 {
+                       i2c: i2c@d0200000 {
                                #address-cells = <1>;
                                #size-cells = <0>;
                                compatible = "snps,designware-i2c";
                                status = "disabled";
                        };
 
-                       rtc@fc900000 {
+                       rtc: rtc@fc900000 {
                                compatible = "st,spear600-rtc";
                                reg = <0xfc900000 0x1000>;
                                interrupts = <10>;
                                interrupt-parent = <&vic0>;
                                interrupts = <16>;
                        };
+
+                       adc: adc@d820b000 {
+                               compatible = "st,spear600-adc";
+                               reg = <0xd820b000 0x1000>;
+                               interrupt-parent = <&vic1>;
+                               interrupts = <6>;
+                               status = "disabled";
+                       };
                };
        };
 };
index 044184580326cab47928977e11232c6d61f38247..12c0757594d7fc305a1aea564419e69bf508c0da 100644 (file)
                        clock-names = "ssc";
                        pinctrl-names = "default";
                        pinctrl-0 = <&pinctrl_spi1_default>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
 
                        status = "disabled";
                };
                        clock-names = "ssc";
                        pinctrl-names = "default";
                        pinctrl-0 = <&pinctrl_spi2_default>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
 
                        status = "disabled";
                };
                        clock-names = "ssc";
                        pinctrl-names = "default";
                        pinctrl-0 = <&pinctrl_spi3_default>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
 
                        status = "disabled";
                };
                        clock-names = "ssc";
                        pinctrl-names = "default";
                        pinctrl-0 = <&pinctrl_spi4_default>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
 
                        status = "disabled";
                };
                        clock-names = "ssc";
                        pinctrl-names = "default";
                        pinctrl-0 = <&pinctrl_spi10_default>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
 
                        status = "disabled";
                };
                        clock-names = "ssc";
                        pinctrl-names = "default";
                        pinctrl-0 = <&pinctrl_spi11_default>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
 
                        status = "disabled";
                };
                        clock-names = "ssc";
                        pinctrl-names = "default";
                        pinctrl-0 = <&pinctrl_spi12_default>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
 
                        status = "disabled";
                };
                        status          = "okay";
                };
 
-               st231_gp0: remote-processor {
+               st231_gp0: st231-gp0@0 {
                        compatible      = "st,st231-rproc";
                        memory-region   = <&gp0_reserved>;
                        resets          = <&softreset STIH407_ST231_GP0_SOFTRESET>;
                        mboxes = <&mailbox0 0 2>, <&mailbox2 0 1>, <&mailbox0 0 3>, <&mailbox2 0 0>;
                };
 
-               st231_delta: remote-processor {
+               st231_delta: st231-delta@0 {
                        compatible      = "st,st231-rproc";
                        memory-region   = <&delta_reserved>;
                        resets          = <&softreset STIH407_ST231_DMU_SOFTRESET>;
index 3c99466989b1c3643f5ce00fd169a5f51272053e..b6331146aa02df166cad3a7a15209b320a37f4cd 100644 (file)
        status = "okay";
 };
 
+&timers1 {
+       status = "okay";
+
+       pwm {
+               pinctrl-0 = <&pwm1_pins>;
+               pinctrl-names = "default";
+               status = "okay";
+       };
+
+       timer@0 {
+               status = "okay";
+       };
+};
+
+&timers3 {
+       status = "okay";
+
+       pwm {
+               pinctrl-0 = <&pwm3_pins>;
+               pinctrl-names = "default";
+               status = "okay";
+       };
+
+       timer@2 {
+               status = "okay";
+       };
+};
+
 &usart1 {
        pinctrl-0 = <&usart1_pins_a>;
        pinctrl-names = "default";
index 0dc18a0f0940e143c1a299103cf58469c00a32af..69a957963fa8c96d1586bdd2a8d7df2732d42904 100644 (file)
        status = "okay";
 };
 
+&rtc {
+       status = "okay";
+};
+
 &usart1 {
        pinctrl-0 = <&usart1_pins_a>;
        pinctrl-names = "default";
index 9222b9f37bc00fefa1d9bb2176192bbb7effbe7e..191fa50e34ebd7c8ab590ecf910ea5d56b7bfe52 100644 (file)
                        gpios = <&gpioa 0 0>;
                };
        };
+
+       /* This turns on vbus for otg for host mode (dwc2) */
+       vcc5v_otg: vcc5v-otg-regulator {
+               compatible = "regulator-fixed";
+               gpio = <&gpioc 4 0>;
+               regulator-name = "vcc5_host1";
+               regulator-always-on;
+       };
 };
 
 &clk_hse {
        pinctrl-names = "default";
        status = "okay";
 };
+
+&usbotg_hs {
+       compatible = "st,stm32f4x9-fsotg";
+       dr_mode = "host";
+       pinctrl-0 = <&usbotg_fs_pins_b>;
+       pinctrl-names = "default";
+       status = "okay";
+};
index ee0da970e8ad7dd3b776bc834c91e8002a84d682..b2a2b5c38caa789012084e70f348b1b9153e212d 100644 (file)
                                clocks = <&rcc 0 STM32F4_APB2_CLOCK(ADC1)>;
                                interrupt-parent = <&adc>;
                                interrupts = <0>;
+                               dmas = <&dma2 0 0 0x400 0x0>;
+                               dma-names = "rx";
                                status = "disabled";
                        };
 
                                clocks = <&rcc 0 STM32F4_APB2_CLOCK(ADC2)>;
                                interrupt-parent = <&adc>;
                                interrupts = <1>;
+                               dmas = <&dma2 3 1 0x400 0x0>;
+                               dma-names = "rx";
                                status = "disabled";
                        };
 
                                clocks = <&rcc 0 STM32F4_APB2_CLOCK(ADC3)>;
                                interrupt-parent = <&adc>;
                                interrupts = <2>;
+                               dmas = <&dma2 1 2 0x400 0x0>;
+                               dma-names = "rx";
                                status = "disabled";
                        };
                };
                                };
                        };
 
+                       usbotg_fs_pins_a: usbotg_fs@0 {
+                               pins {
+                                       pinmux = <STM32F429_PA10_FUNC_OTG_FS_ID>,
+                                                <STM32F429_PA11_FUNC_OTG_FS_DM>,
+                                                <STM32F429_PA12_FUNC_OTG_FS_DP>;
+                                       bias-disable;
+                                       drive-push-pull;
+                                       slew-rate = <2>;
+                               };
+                       };
+
+                       usbotg_fs_pins_b: usbotg_fs@1 {
+                               pins {
+                                       pinmux = <STM32F429_PB12_FUNC_OTG_HS_ID>,
+                                                <STM32F429_PB14_FUNC_OTG_HS_DM>,
+                                                <STM32F429_PB15_FUNC_OTG_HS_DP>;
+                                       bias-disable;
+                                       drive-push-pull;
+                                       slew-rate = <2>;
+                               };
+                       };
+
                        usbotg_hs_pins_a: usbotg_hs@0 {
                                pins {
                                        pinmux = <STM32F429_PH4_FUNC_OTG_HS_ULPI_NXT>,
                        status = "disabled";
                };
 
+               usbotg_fs: usb@50000000 {
+                       compatible = "st,stm32f4x9-fsotg";
+                       reg = <0x50000000 0x40000>;
+                       interrupts = <67>;
+                       clocks = <&rcc 0 39>;
+                       clock-names = "otg";
+                       status = "disabled";
+               };
+
                rng: rng@50060800 {
                        compatible = "st,stm32-rng";
                        reg = <0x50060800 0x400>;
index 0dd56ef574fa23f6fd54a404848e7a6be28db8b9..75470c34b92cb36c5f1f6eb61c3c0f31e94a84bf 100644 (file)
        soc {
                dma-ranges = <0xc0000000 0x0 0x10000000>;
        };
+
+       /* This turns on vbus for otg for host mode (dwc2) */
+       vcc5v_otg: vcc5v-otg-regulator {
+               compatible = "regulator-fixed";
+               enable-active-high;
+               gpio = <&gpiob 2 0>;
+               regulator-name = "vcc5_host1";
+               regulator-always-on;
+       };
 };
 
 &rcc {
        pinctrl-names = "default";
        status = "okay";
 };
+
+&usbotg_fs {
+       dr_mode = "host";
+       pinctrl-0 = <&usbotg_fs_pins_a>;
+       pinctrl-names = "default";
+       status = "okay";
+};
index 755fb923c07baec50b555f9ebad962c0db2efa01..c2765ce12e2e0292c64a77380657ae1756e94520 100644 (file)
@@ -43,6 +43,8 @@
 #include "skeleton.dtsi"
 #include "armv7-m.dtsi"
 #include <dt-bindings/pinctrl/stm32f746-pinfunc.h>
+#include <dt-bindings/clock/stm32fx-clock.h>
+#include <dt-bindings/mfd/stm32f7-rcc.h>
 
 / {
        clocks {
                        compatible = "fixed-clock";
                        clock-frequency = <0>;
                };
+
+               clk-lse {
+                       #clock-cells = <0>;
+                       compatible = "fixed-clock";
+                       clock-frequency = <32768>;
+               };
+
+               clk-lsi {
+                       #clock-cells = <0>;
+                       compatible = "fixed-clock";
+                       clock-frequency = <32000>;
+               };
+
+               clk_i2s_ckin: clk-i2s-ckin {
+                       #clock-cells = <0>;
+                       compatible = "fixed-clock";
+                       clock-frequency = <48000000>;
+               };
        };
 
        soc {
@@ -58,7 +78,7 @@
                        compatible = "st,stm32-timer";
                        reg = <0x40000000 0x400>;
                        interrupts = <28>;
-                       clocks = <&rcc 0 128>;
+                       clocks = <&rcc 0 STM32F7_APB1_CLOCK(TIM2)>;
                        status = "disabled";
                };
 
@@ -66,7 +86,7 @@
                        compatible = "st,stm32-timer";
                        reg = <0x40000400 0x400>;
                        interrupts = <29>;
-                       clocks = <&rcc 0 129>;
+                       clocks = <&rcc 0 STM32F7_APB1_CLOCK(TIM3)>;
                        status = "disabled";
                };
 
@@ -74,7 +94,7 @@
                        compatible = "st,stm32-timer";
                        reg = <0x40000800 0x400>;
                        interrupts = <30>;
-                       clocks = <&rcc 0 130>;
+                       clocks = <&rcc 0 STM32F7_APB1_CLOCK(TIM4)>;
                        status = "disabled";
                };
 
                        compatible = "st,stm32-timer";
                        reg = <0x40000c00 0x400>;
                        interrupts = <50>;
-                       clocks = <&rcc 0 131>;
+                       clocks = <&rcc 0 STM32F7_APB1_CLOCK(TIM5)>;
                };
 
                timer6: timer@40001000 {
                        compatible = "st,stm32-timer";
                        reg = <0x40001000 0x400>;
                        interrupts = <54>;
-                       clocks = <&rcc 0 132>;
+                       clocks = <&rcc 0 STM32F7_APB1_CLOCK(TIM6)>;
                        status = "disabled";
                };
 
                        compatible = "st,stm32-timer";
                        reg = <0x40001400 0x400>;
                        interrupts = <55>;
-                       clocks = <&rcc 0 133>;
+                       clocks = <&rcc 0 STM32F7_APB1_CLOCK(TIM7)>;
+                       status = "disabled";
+               };
+
+               rtc: rtc@40002800 {
+                       compatible = "st,stm32-rtc";
+                       reg = <0x40002800 0x400>;
+                       clocks = <&rcc 1 CLK_RTC>;
+                       clock-names = "ck_rtc";
+                       assigned-clocks = <&rcc 1 CLK_RTC>;
+                       assigned-clock-parents = <&rcc 1 CLK_LSE>;
+                       interrupt-parent = <&exti>;
+                       interrupts = <17 1>;
+                       interrupt-names = "alarm";
+                       st,syscfg = <&pwrcfg>;
                        status = "disabled";
                };
 
                        compatible = "st,stm32f7-usart", "st,stm32f7-uart";
                        reg = <0x40004400 0x400>;
                        interrupts = <38>;
-                       clocks =  <&rcc 0 145>;
+                       clocks = <&rcc 1 CLK_USART2>;
                        status = "disabled";
                };
 
                        compatible = "st,stm32f7-usart", "st,stm32f7-uart";
                        reg = <0x40004800 0x400>;
                        interrupts = <39>;
-                       clocks = <&rcc 0 146>;
+                       clocks = <&rcc 1 CLK_USART3>;
                        status = "disabled";
                };
 
                        compatible = "st,stm32f7-uart";
                        reg = <0x40004c00 0x400>;
                        interrupts = <52>;
-                       clocks = <&rcc 0 147>;
+                       clocks = <&rcc 1 CLK_UART4>;
                        status = "disabled";
                };
 
                        compatible = "st,stm32f7-uart";
                        reg = <0x40005000 0x400>;
                        interrupts = <53>;
-                       clocks = <&rcc 0 148>;
+                       clocks = <&rcc 1 CLK_UART5>;
                        status = "disabled";
                };
 
                        compatible = "st,stm32f7-usart", "st,stm32f7-uart";
                        reg = <0x40007800 0x400>;
                        interrupts = <82>;
-                       clocks = <&rcc 0 158>;
+                       clocks = <&rcc 1 CLK_UART7>;
                        status = "disabled";
                };
 
                        compatible = "st,stm32f7-usart", "st,stm32f7-uart";
                        reg = <0x40007c00 0x400>;
                        interrupts = <83>;
-                       clocks = <&rcc 0 159>;
+                       clocks = <&rcc 1 CLK_UART8>;
                        status = "disabled";
                };
 
                        compatible = "st,stm32f7-usart", "st,stm32f7-uart";
                        reg = <0x40011000 0x400>;
                        interrupts = <37>;
-                       clocks = <&rcc 0 164>;
+                       clocks = <&rcc 1 CLK_USART1>;
                        status = "disabled";
                };
 
                        compatible = "st,stm32f7-usart", "st,stm32f7-uart";
                        reg = <0x40011400 0x400>;
                        interrupts = <71>;
-                       clocks = <&rcc 0 165>;
+                       clocks = <&rcc 1 CLK_USART6>;
                        status = "disabled";
                };
 
                        interrupts = <1>, <2>, <3>, <6>, <7>, <8>, <9>, <10>, <23>, <40>, <41>, <42>, <62>, <76>;
                };
 
+               pwrcfg: power-config@40007000 {
+                       compatible = "syscon";
+                       reg = <0x40007000 0x400>;
+               };
+
                pin-controller {
                        #address-cells = <1>;
                        #size-cells = <1>;
                                gpio-controller;
                                #gpio-cells = <2>;
                                reg = <0x0 0x400>;
-                               clocks = <&rcc 0 256>;
+                               clocks = <&rcc 0 STM32F7_AHB1_CLOCK(GPIOA)>;
                                st,bank-name = "GPIOA";
                        };
 
                                gpio-controller;
                                #gpio-cells = <2>;
                                reg = <0x400 0x400>;
-                               clocks = <&rcc 0 257>;
+                               clocks = <&rcc 0 STM32F7_AHB1_CLOCK(GPIOB)>;
                                st,bank-name = "GPIOB";
                        };
 
                                gpio-controller;
                                #gpio-cells = <2>;
                                reg = <0x800 0x400>;
-                               clocks = <&rcc 0 258>;
+                               clocks = <&rcc 0 STM32F7_AHB1_CLOCK(GPIOC)>;
                                st,bank-name = "GPIOC";
                        };
 
                                gpio-controller;
                                #gpio-cells = <2>;
                                reg = <0xc00 0x400>;
-                               clocks = <&rcc 0 259>;
+                               clocks = <&rcc 0 STM32F7_AHB1_CLOCK(GPIOD)>;
                                st,bank-name = "GPIOD";
                        };
 
                                gpio-controller;
                                #gpio-cells = <2>;
                                reg = <0x1000 0x400>;
-                               clocks = <&rcc 0 260>;
+                               clocks = <&rcc 0 STM32F7_AHB1_CLOCK(GPIOE)>;
                                st,bank-name = "GPIOE";
                        };
 
                                gpio-controller;
                                #gpio-cells = <2>;
                                reg = <0x1400 0x400>;
-                               clocks = <&rcc 0 261>;
+                               clocks = <&rcc 0 STM32F7_AHB1_CLOCK(GPIOF)>;
                                st,bank-name = "GPIOF";
                        };
 
                                gpio-controller;
                                #gpio-cells = <2>;
                                reg = <0x1800 0x400>;
-                               clocks = <&rcc 0 262>;
+                               clocks = <&rcc 0 STM32F7_AHB1_CLOCK(GPIOG)>;
                                st,bank-name = "GPIOG";
                        };
 
                                gpio-controller;
                                #gpio-cells = <2>;
                                reg = <0x1c00 0x400>;
-                               clocks = <&rcc 0 263>;
+                               clocks = <&rcc 0 STM32F7_AHB1_CLOCK(GPIOH)>;
                                st,bank-name = "GPIOH";
                        };
 
                                gpio-controller;
                                #gpio-cells = <2>;
                                reg = <0x2000 0x400>;
-                               clocks = <&rcc 0 264>;
+                               clocks = <&rcc 0 STM32F7_AHB1_CLOCK(GPIOI)>;
                                st,bank-name = "GPIOI";
                        };
 
                                gpio-controller;
                                #gpio-cells = <2>;
                                reg = <0x2400 0x400>;
-                               clocks = <&rcc 0 265>;
+                               clocks = <&rcc 0 STM32F7_AHB1_CLOCK(GPIOJ)>;
                                st,bank-name = "GPIOJ";
                        };
 
                                gpio-controller;
                                #gpio-cells = <2>;
                                reg = <0x2800 0x400>;
-                               clocks = <&rcc 0 266>;
+                               clocks = <&rcc 0 STM32F7_AHB1_CLOCK(GPIOK)>;
                                st,bank-name = "GPIOK";
                        };
 
 
                rcc: rcc@40023800 {
                        #clock-cells = <2>;
-                       compatible = "st,stm32f42xx-rcc", "st,stm32-rcc";
+                       compatible = "st,stm32f746-rcc", "st,stm32-rcc";
                        reg = <0x40023800 0x400>;
-                       clocks = <&clk_hse>;
+                       clocks = <&clk_hse>, <&clk_i2s_ckin>;
+                       st,syscfg = <&pwrcfg>;
+                       assigned-clocks = <&rcc 1 CLK_HSE_RTC>;
+                       assigned-clock-rates = <1000000>;
                };
        };
 };
diff --git a/arch/arm/boot/dts/stm32h743-pinctrl.dtsi b/arch/arm/boot/dts/stm32h743-pinctrl.dtsi
new file mode 100644 (file)
index 0000000..fcc1e06
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright 2017 - Alexandre Torgue <alexandre.torgue@st.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <dt-bindings/pinctrl/stm32h7-pinfunc.h>
+
+/ {
+       soc {
+               pin-controller {
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       compatible = "st,stm32h743-pinctrl";
+                       ranges = <0 0x58020000 0x3000>;
+                       pins-are-numbered;
+
+                       gpioa: gpio@58020000 {
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               reg = <0x0 0x400>;
+                               clocks = <&timer_clk>;
+                               st,bank-name = "GPIOA";
+                       };
+
+                       gpiob: gpio@58020400 {
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               reg = <0x400 0x400>;
+                               clocks = <&timer_clk>;
+                               st,bank-name = "GPIOB";
+                       };
+
+                       gpioc: gpio@58020800 {
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               reg = <0x800 0x400>;
+                               clocks = <&timer_clk>;
+                               st,bank-name = "GPIOC";
+                       };
+
+                       gpiod: gpio@58020c00 {
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               reg = <0xc00 0x400>;
+                               clocks = <&timer_clk>;
+                               st,bank-name = "GPIOD";
+                       };
+
+                       gpioe: gpio@58021000 {
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               reg = <0x1000 0x400>;
+                               clocks = <&timer_clk>;
+                               st,bank-name = "GPIOE";
+                       };
+
+                       gpiof: gpio@58021400 {
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               reg = <0x1400 0x400>;
+                               clocks = <&timer_clk>;
+                               st,bank-name = "GPIOF";
+                       };
+
+                       gpiog: gpio@58021800 {
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               reg = <0x1800 0x400>;
+                               clocks = <&timer_clk>;
+                               st,bank-name = "GPIOG";
+                       };
+
+                       gpioh: gpio@58021c00 {
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               reg = <0x1c00 0x400>;
+                               clocks = <&timer_clk>;
+                               st,bank-name = "GPIOH";
+                       };
+
+                       gpioi: gpio@58022000 {
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               reg = <0x2000 0x400>;
+                               clocks = <&timer_clk>;
+                               st,bank-name = "GPIOI";
+                       };
+
+                       gpioj: gpio@58022400 {
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               reg = <0x2400 0x400>;
+                               clocks = <&timer_clk>;
+                               st,bank-name = "GPIOJ";
+                       };
+
+                       gpiok: gpio@58022800 {
+                               gpio-controller;
+                               #gpio-cells = <2>;
+                               reg = <0x2800 0x400>;
+                               clocks = <&timer_clk>;
+                               st,bank-name = "GPIOK";
+                       };
+
+                       usart1_pins: usart1@0 {
+                               pins1 {
+                                       pinmux = <STM32H7_PB14_FUNC_USART1_TX>;
+                                       bias-disable;
+                                       drive-push-pull;
+                                       slew-rate = <0>;
+                               };
+                               pins2 {
+                                       pinmux = <STM32H7_PB15_FUNC_USART1_RX>;
+                                       bias-disable;
+                               };
+                       };
+               };
+       };
+};
diff --git a/arch/arm/boot/dts/stm32h743.dtsi b/arch/arm/boot/dts/stm32h743.dtsi
new file mode 100644 (file)
index 0000000..4685629
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2017 - Alexandre Torgue <alexandre.torgue@st.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "skeleton.dtsi"
+#include "armv7-m.dtsi"
+
+/ {
+       clocks {
+               clk_hse: clk-hse {
+                       #clock-cells = <0>;
+                       compatible = "fixed-clock";
+                       clock-frequency = <0>;
+               };
+
+               timer_clk: timer-clk {
+                       #clock-cells = <0>;
+                       compatible = "fixed-clock";
+                       clock-frequency = <125000000>;
+               };
+       };
+
+       soc {
+               usart1: serial@40011000 {
+                       compatible = "st,stm32f7-usart", "st,stm32f7-uart";
+                       reg = <0x40011000 0x400>;
+                       interrupts = <37>;
+                       status = "disabled";
+                       clocks = <&timer_clk>;
+
+               };
+
+               timer5: timer@40000c00 {
+                       compatible = "st,stm32-timer";
+                       reg = <0x40000c00 0x400>;
+                       interrupts = <50>;
+                       clocks = <&timer_clk>;
+               };
+       };
+};
+
+&systick {
+       clock-frequency = <250000000>;
+       status = "okay";
+};
diff --git a/arch/arm/boot/dts/stm32h743i-eval.dts b/arch/arm/boot/dts/stm32h743i-eval.dts
new file mode 100644 (file)
index 0000000..c6effbb
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2017 - Alexandre Torgue <alexandre.torgue@st.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "stm32h743.dtsi"
+#include "stm32h743-pinctrl.dtsi"
+
+/ {
+       model = "STMicroelectronics STM32H743i-EVAL board";
+       compatible = "st,stm32h743i-eval", "st,stm32h743";
+
+       chosen {
+               bootargs = "root=/dev/ram";
+               stdout-path = "serial0:115200n8";
+       };
+
+       memory {
+               reg = <0xd0000000 0x2000000>;
+       };
+
+       aliases {
+               serial0 = &usart1;
+       };
+};
+
+&clk_hse {
+       clock-frequency = <125000000>;
+};
+
+&usart1 {
+       pinctrl-0 = <&usart1_pins>;
+       pinctrl-names = "default";
+       status = "okay";
+};
+
index f3fc27412a67f0cbc40225ef462d14903056ff8a..f2a01fe2bebc8ab0a01b93189616508cf87785bd 100644 (file)
@@ -47,7 +47,6 @@
 #include "sunxi-common-regulators.dtsi"
 
 #include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Mele A1000";
index 04e040e6233d081ddd6b04fece52a3cc94551014..d844938e2aa7f56537dd076a92af0f3059a92ca6 100644 (file)
@@ -46,7 +46,6 @@
 #include "sunxi-common-regulators.dtsi"
 
 #include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Cubietech Cubieboard";
index 8317fbfeec4a477a6c84099346421096a73479e1..aad3bec1cb39a6e2d7f4e742aa016530fc6c2cef 100644 (file)
@@ -46,7 +46,6 @@
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 #include <dt-bindings/pwm/pwm.h>
 
 / {
index a48b4647441710e5e41bef064860f7744a103f3a..a1a7282199d52c893813ff2178ffecc16b8694b4 100644 (file)
@@ -47,7 +47,6 @@
 #include "sunxi-common-regulators.dtsi"
 
 #include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Miniand Hackberry";
index f3092703a1a6a6b7e858d9b3a41ecaf63457826e..b8923b92cb36912041f11c6d2f03ac58ffb45229 100644 (file)
@@ -46,7 +46,6 @@
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 #include <dt-bindings/pwm/pwm.h>
 
 / {
index 4ef2a60a8cd49e36265535e36b97371612773f1c..4a27eb9102cda7c39c79225f9c9a9a32d8f3d6ee 100644 (file)
@@ -46,7 +46,6 @@
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "iNet-9F Rev 03";
index fc4d4d49e2e2e2659acf833a54f0d737a6ee3b97..308dc15130417f29b2acdf8e8ccc1d17f7460885 100644 (file)
@@ -47,7 +47,6 @@
 #include "sunxi-common-regulators.dtsi"
 
 #include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Jesurun Q5";
index a2885039d5f1646a0a3c21819ee4aa7ee19e3c46..98a5f7258dca44bf12ccaf3183c4d33783520590 100644 (file)
@@ -46,7 +46,6 @@
 #include "sunxi-common-regulators.dtsi"
 
 #include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "HAOYU Electronics Marsboard A10";
index af42ebb3a97b20811642fcc265ee53b7ffd8ad26..484c57493bd21d90ff4a01f177fc8282b16a724d 100644 (file)
@@ -47,7 +47,6 @@
 #include "sunxi-common-regulators.dtsi"
 
 #include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "PineRiver Mini X-Plus";
index 9c1afd4277d75b69d3ee73f09aac76404c75979b..2b75745cd246a93267a5708d0836c2aa48399f26 100644 (file)
@@ -44,7 +44,6 @@
 #include "sun4i-a10.dtsi"
 #include "sunxi-common-regulators.dtsi"
 #include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "MK802";
index 214a5accfe9302a7025c2acad4c977d402510e06..3a2522a9419ddcb870a7251c1e8f49bddc15812e 100644 (file)
@@ -45,7 +45,6 @@
 #include "sunxi-common-regulators.dtsi"
 
 #include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Olimex A10-OLinuXino-LIME";
index b0365d63ba70ab7ce46a994890bb6035a134191d..83596fd2ccfc385e50f5d35c843db080e36ab19a 100644 (file)
@@ -47,7 +47,6 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "LinkSprite pcDuino";
index bfa6bbdaab276eaaa03b394c5223eb9471c3ace1..a68c7cc53b9450f001b237cb17f36d28df18f2a1 100644 (file)
@@ -46,7 +46,6 @@
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 #include <dt-bindings/pwm/pwm.h>
 
 / {
index ba20b48c07028acd761655e7a5e56d198e01bd4b..b63668ece1513958484294a60da8e11944604628 100644 (file)
@@ -47,7 +47,6 @@
 
 #include <dt-bindings/clock/sun4i-a10-pll2.h>
 #include <dt-bindings/dma/sun4i-a10.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        interrupt-parent = <&intc>;
                        #interrupt-cells = <3>;
                        #gpio-cells = <3>;
 
+                       can0_pins_a: can0@0 {
+                               pins = "PH20", "PH21";
+                               function = "can";
+                       };
+
                        emac_pins_a: emac0@0 {
                                pins = "PA0", "PA1", "PA2",
                                       "PA3", "PA4", "PA5", "PA6",
                        status = "disabled";
                };
 
+               ps20: ps2@01c2a000 {
+                       compatible = "allwinner,sun4i-a10-ps2";
+                       reg = <0x01c2a000 0x400>;
+                       interrupts = <62>;
+                       clocks = <&apb1_gates 6>;
+                       status = "disabled";
+               };
+
+               ps21: ps2@01c2a400 {
+                       compatible = "allwinner,sun4i-a10-ps2";
+                       reg = <0x01c2a400 0x400>;
+                       interrupts = <63>;
+                       clocks = <&apb1_gates 7>;
+                       status = "disabled";
+               };
+
                i2c0: i2c@01c2ac00 {
                        compatible = "allwinner,sun4i-a10-i2c";
                        reg = <0x01c2ac00 0x400>;
                        #size-cells = <0>;
                };
 
-               ps20: ps2@01c2a000 {
-                       compatible = "allwinner,sun4i-a10-ps2";
-                       reg = <0x01c2a000 0x400>;
-                       interrupts = <62>;
-                       clocks = <&apb1_gates 6>;
-                       status = "disabled";
-               };
-
-               ps21: ps2@01c2a400 {
-                       compatible = "allwinner,sun4i-a10-ps2";
-                       reg = <0x01c2a400 0x400>;
-                       interrupts = <63>;
-                       clocks = <&apb1_gates 7>;
+               can0: can@01c2bc00 {
+                       compatible = "allwinner,sun4i-a10-can";
+                       reg = <0x01c2bc00 0x400>;
+                       interrupts = <26>;
+                       clocks = <&apb1_gates 4>;
                        status = "disabled";
                };
        };
index a539b72ce093d0150b2b97e7817a6a57b67f7e32..c6f742a7e69f610ee4e50b7c87ffff93f3b60ac2 100644 (file)
@@ -44,7 +44,6 @@
 #include "sun5i-a10s.dtsi"
 #include "sunxi-common-regulators.dtsi"
 #include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Auxtek t003 A10s hdmi tv-stick";
index e1b5e8a446fecd11baac888f800e9e86633f6bff..a27c3fa587366a19684bb151045a53cfb69d8775 100644 (file)
@@ -44,7 +44,6 @@
 #include "sun5i-a10s.dtsi"
 #include "sunxi-common-regulators.dtsi"
 #include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Auxtek t004 A10s hdmi tv-stick";
index d8245c6314a7e8228e967e6b8014b01468029d45..894f874a5beb32e8643577c48a562d9dddf20e92 100644 (file)
@@ -48,7 +48,6 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Olimex A10s-Olinuxino Micro";
@@ -83,7 +82,7 @@
 
 &emac {
        pinctrl-names = "default";
-       pinctrl-0 = <&emac_pins_a>;
+       pinctrl-0 = <&emac_pins_b>;
        phy = <&phy1>;
        status = "okay";
 };
 
 &uart2 {
        pinctrl-names = "default";
-       pinctrl-0 = <&uart2_pins_a>;
+       pinctrl-0 = <&uart2_pins_b>;
        status = "okay";
 };
 
index 51371f9b1cf0699243a7b4c6f446ff745e28b8ad..262b3669f04d79d1f5b260cfc84c74d9bfb36de7 100644 (file)
@@ -45,7 +45,6 @@
 #include "sunxi-common-regulators.dtsi"
 
 #include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "R7 A10s hdmi tv-stick";
index 2b8adda0dedad1d838db4471e2e03c50483d96c4..ea3e5655a61bdacbcf3eb739848cfcb2f81ba181 100644 (file)
@@ -46,7 +46,6 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "A10s-Wobo i5";
@@ -95,7 +94,7 @@
 
 &emac {
        pinctrl-names = "default";
-       pinctrl-0 = <&emac_pins_b>;
+       pinctrl-0 = <&emac_pins_a>;
        phy = <&phy1>;
        status = "okay";
 };
index 24b0f5f556f8a99ea3bd34fdc70b70213e06baa7..1e38ff80366c677b6ee76a033f134cdc837ec1b5 100644 (file)
@@ -47,7 +47,6 @@
 #include "sun5i.dtsi"
 
 #include <dt-bindings/dma/sun4i-a10.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        interrupt-parent = <&intc>;
@@ -61,7 +60,7 @@
                #size-cells = <1>;
                ranges;
 
-               framebuffer@0 {
+               framebuffer@2 {
                        compatible = "allwinner,simple-framebuffer",
                                     "simple-framebuffer";
                        allwinner,pipeline = "de_be0-lcd0-hdmi";
                                 <&ccu CLK_DE_BE>, <&ccu CLK_HDMI>;
                        status = "disabled";
                };
-
-               framebuffer@1 {
-                       compatible = "allwinner,simple-framebuffer",
-                                    "simple-framebuffer";
-                       allwinner,pipeline = "de_be0-lcd0";
-                       clocks = <&ccu CLK_AHB_LCD>, <&ccu CLK_AHB_DE_BE>, <&ccu CLK_DE_BE>,
-                                <&ccu CLK_TCON_CH0>, <&ccu CLK_DRAM_DE_BE>;
-                       status = "disabled";
-               };
-
-               framebuffer@2 {
-                       compatible = "allwinner,simple-framebuffer",
-                                    "simple-framebuffer";
-                       allwinner,pipeline = "de_be0-lcd0-tve0";
-                       clocks = <&ccu CLK_AHB_TVE>, <&ccu CLK_AHB_LCD>,
-                                <&ccu CLK_AHB_DE_BE>, <&ccu CLK_DE_BE>,
-                                <&ccu CLK_TCON_CH1>, <&ccu CLK_DRAM_DE_BE>;
-                       status = "disabled";
-               };
        };
 
        soc@01c00000 {
-               emac: ethernet@01c0b000 {
-                       compatible = "allwinner,sun4i-a10-emac";
-                       reg = <0x01c0b000 0x1000>;
-                       interrupts = <55>;
-                       clocks = <&ccu CLK_AHB_EMAC>;
-                       allwinner,sram = <&emac_sram 1>;
-                       status = "disabled";
-               };
-
-               mdio: mdio@01c0b080 {
-                       compatible = "allwinner,sun4i-a10-mdio";
-                       reg = <0x01c0b080 0x14>;
-                       status = "disabled";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-               };
-
                pwm: pwm@01c20e00 {
                        compatible = "allwinner,sun5i-a10s-pwm";
                        reg = <0x01c20e00 0xc>;
                        #pwm-cells = <3>;
                        status = "disabled";
                };
-
-               uart0: serial@01c28000 {
-                       compatible = "snps,dw-apb-uart";
-                       reg = <0x01c28000 0x400>;
-                       interrupts = <1>;
-                       reg-shift = <2>;
-                       reg-io-width = <4>;
-                       clocks = <&ccu CLK_APB1_UART0>;
-                       status = "disabled";
-               };
-
-               uart2: serial@01c28800 {
-                       compatible = "snps,dw-apb-uart";
-                       reg = <0x01c28800 0x400>;
-                       interrupts = <3>;
-                       reg-shift = <2>;
-                       reg-io-width = <4>;
-                       clocks = <&ccu CLK_APB1_UART2>;
-                       status = "disabled";
-               };
        };
 };
 
                function = "uart0";
        };
 
-       uart2_pins_a: uart2@0 {
+       uart2_pins_b: uart2@1 {
                pins = "PC18", "PC19";
                function = "uart2";
        };
 
-       emac_pins_a: emac0@0 {
+       emac_pins_b: emac0@1 {
                pins = "PA0", "PA1", "PA2",
                                "PA3", "PA4", "PA5", "PA6",
                                "PA7", "PA8", "PA9", "PA10",
                function = "emac";
        };
 
-       emac_pins_b: emac0@1 {
-               pins = "PD6", "PD7", "PD10",
-                               "PD11", "PD12", "PD13", "PD14",
-                               "PD15", "PD18", "PD19", "PD20",
-                               "PD21", "PD22", "PD23", "PD24",
-                               "PD25", "PD26", "PD27";
-               function = "emac";
-       };
-
        mmc1_pins_a: mmc1@0 {
                pins = "PG3", "PG4", "PG5",
                                 "PG6", "PG7", "PG8";
 };
 
 &sram_a {
-       emac_sram: sram-section@8000 {
-               compatible = "allwinner,sun4i-a10-sram-a3-a4";
-               reg = <0x8000 0x4000>;
-               status = "disabled";
-       };
 };
index 42435454acefe1e5bf211f0fce6d6f0986a3e9f5..34411d27aadfd712f64d189ae81638aabd1a2837 100644 (file)
@@ -46,7 +46,6 @@
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 #include <dt-bindings/pwm/pwm.h>
 
 / {
index 5879a75cf97a3b1982d0c80b5c20b278b9610def..2489c16f7efa528dde0cbfb3b3089f2cf7340f56 100644 (file)
@@ -46,7 +46,6 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "HSG H702";
index 566cda91a66b41e9660294d3763d2ffaec5125d5..bc883893f4a4af87609ae8b1f362832b67c1b387 100644 (file)
@@ -50,7 +50,6 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Lichee Pi One";
index 60e393e287832a1a09dace62e72a20563d3866a9..3a831eaf1dfc4da48ee2a8151a030c27099b4a6c 100644 (file)
@@ -46,7 +46,6 @@
 #include "sunxi-common-regulators.dtsi"
 
 #include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Olimex A13-Olinuxino Micro";
index 940d47e880561289e1ca71c93e3cbabb22613817..95f591bb8ced0bc7d6c479959c9497be8a1bef6f 100644 (file)
@@ -48,7 +48,6 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Olimex A13-Olinuxino";
index fb2ddb9a04c9e8487da6a14975aa9d8ec0c34f70..6436bad94404d21e1edd012992d2983053ae7428 100644 (file)
 
 #include "sun5i.dtsi"
 
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 #include <dt-bindings/thermal/thermal.h>
 
 / {
        interrupt-parent = <&intc>;
 
-       chosen {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               ranges;
-
-               framebuffer@0 {
-                       compatible = "allwinner,simple-framebuffer",
-                                    "simple-framebuffer";
-                       allwinner,pipeline = "de_be0-lcd0";
-                       clocks = <&ccu CLK_AHB_LCD>, <&ccu CLK_AHB_DE_BE>, <&ccu CLK_DE_BE>,
-                                <&ccu CLK_TCON_CH0>, <&ccu CLK_DRAM_DE_BE>;
-                       status = "disabled";
-               };
-       };
-
        thermal-zones {
                cpu_thermal {
                        /* milliseconds */
        };
 
        soc@01c00000 {
-               tcon0: lcd-controller@01c0c000 {
-                       compatible = "allwinner,sun5i-a13-tcon";
-                       reg = <0x01c0c000 0x1000>;
-                       interrupts = <44>;
-                       resets = <&ccu RST_LCD>;
-                       reset-names = "lcd";
-                       clocks = <&ccu CLK_AHB_LCD>,
-                                <&ccu CLK_TCON_CH0>,
-                                <&ccu CLK_TCON_CH1>;
-                       clock-names = "ahb",
-                                     "tcon-ch0",
-                                     "tcon-ch1";
-                       clock-output-names = "tcon-pixel-clock";
-                       status = "disabled";
-
-                       ports {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-
-                               tcon0_in: port@0 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
-                                       reg = <0>;
-
-                                       tcon0_in_be0: endpoint@0 {
-                                               reg = <0>;
-                                               remote-endpoint = <&be0_out_tcon0>;
-                                       };
-                               };
-
-                               tcon0_out: port@1 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
-                                       reg = <1>;
-                               };
-                       };
-               };
-
                pwm: pwm@01c20e00 {
                        compatible = "allwinner,sun5i-a13-pwm";
                        reg = <0x01c20e00 0xc>;
                        status = "disabled";
                };
 
-               fe0: display-frontend@01e00000 {
-                       compatible = "allwinner,sun5i-a13-display-frontend";
-                       reg = <0x01e00000 0x20000>;
-                       interrupts = <47>;
-                       clocks = <&ccu CLK_DE_FE>, <&ccu CLK_DE_FE>,
-                                <&ccu CLK_DRAM_DE_FE>;
-                       clock-names = "ahb", "mod",
-                                     "ram";
-                       resets = <&ccu RST_DE_FE>;
-                       status = "disabled";
-
-                       ports {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-
-                               fe0_out: port@1 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
-                                       reg = <1>;
-
-                                       fe0_out_be0: endpoint@0 {
-                                               reg = <0>;
-                                               remote-endpoint = <&be0_in_fe0>;
-                                       };
-                               };
-                       };
-               };
-
-               be0: display-backend@01e60000 {
-                       compatible = "allwinner,sun5i-a13-display-backend";
-                       reg = <0x01e60000 0x10000>;
-                       clocks = <&ccu CLK_AHB_DE_BE>, <&ccu CLK_DE_BE>,
-                                <&ccu CLK_DRAM_DE_BE>;
-                       clock-names = "ahb", "mod",
-                                     "ram";
-                       resets = <&ccu RST_DE_BE>;
-                       status = "disabled";
-
-                       assigned-clocks = <&ccu CLK_DE_BE>;
-                       assigned-clock-rates = <300000000>;
-
-                       ports {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-
-                               be0_in: port@0 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
-                                       reg = <0>;
-
-                                       be0_in_fe0: endpoint@0 {
-                                               reg = <0>;
-                                               remote-endpoint = <&fe0_out_be0>;
-                                       };
-                               };
-
-                               be0_out: port@1 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
-                                       reg = <1>;
-
-                                       be0_out_tcon0: endpoint@0 {
-                                               reg = <0>;
-                                               remote-endpoint = <&tcon0_in_be0>;
-                                       };
-                               };
-                       };
-               };
        };
 };
 
 
 &pio {
        compatible = "allwinner,sun5i-a13-pinctrl";
-
-       lcd_rgb666_pins: lcd_rgb666@0 {
-               pins = "PD2", "PD3", "PD4", "PD5", "PD6", "PD7",
-                      "PD10", "PD11", "PD12", "PD13", "PD14", "PD15",
-                      "PD18", "PD19", "PD20", "PD21", "PD22", "PD23",
-                      "PD24", "PD25", "PD26", "PD27";
-               function = "lcd0";
-       };
-
-       uart1_pins_a: uart1@0 {
-               pins = "PE10", "PE11";
-               function = "uart1";
-       };
-
-       uart1_pins_b: uart1@1 {
-               pins = "PG3", "PG4";
-               function = "uart1";
-       };
 };
index 0cf0813d363a8a19a884f03bd01cc0ef16163d40..c55b11a4d3c7f59988381a2afc130324a51fb598 100644 (file)
 
 &pwm {
        pinctrl-names = "default";
-       pinctrl-0 = <&pwm0_pins_a>, <&pwm1_pins>;
+       pinctrl-0 = <&pwm0_pins>, <&pwm1_pins>;
        status = "disabled";
 };
 
 
 &uart1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&uart1_pins_a>, <&uart1_cts_rts_pins_a>;
+       pinctrl-0 = <&uart1_pins_b>, <&uart1_cts_rts_pins_a>;
        status = "okay";
 };
 
index 1a845af4d4db7432164ec2c50025996b1acbf207..558c16a30543efa5f23934e50ee4b5410cec9da3 100644 (file)
 
 &pwm {
        pinctrl-names = "default";
-       pinctrl-0 = <&pwm0_pins_a>;
+       pinctrl-0 = <&pwm0_pins>;
        status = "okay";
 };
 
 
 &uart1 {
        pinctrl-names = "default";
-       pinctrl-0 = <&uart1_pins_a>, <&uart1_cts_rts_pins_a>;
+       pinctrl-0 = <&uart1_pins_b>, <&uart1_cts_rts_pins_a>;
        status = "okay";
 };
 
index cb9b2aaf7297ab6cfecdd5620e78631410e1f03c..3eb56cad0ceaa2b44fc218c66103502b25766615 100644 (file)
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
+#include "sun5i.dtsi"
+
 #include <dt-bindings/clock/sun5i-ccu.h>
 #include <dt-bindings/dma/sun4i-a10.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 #include <dt-bindings/reset/sun5i-ccu.h>
 
 / {
-       interrupt-parent = <&intc>;
-       #address-cells = <1>;
-       #size-cells = <1>;
-
-       cpus {
-               #address-cells = <1>;
-               #size-cells = <0>;
-
-               cpu0: cpu@0 {
-                       device_type = "cpu";
-                       compatible = "arm,cortex-a8";
-                       reg = <0x0>;
-                       clocks = <&ccu CLK_CPU>;
-               };
-       };
-
-       clocks {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               ranges;
-
-               osc24M: clk@01c20050 {
-                       #clock-cells = <0>;
-                       compatible = "fixed-clock";
-                       clock-frequency = <24000000>;
-                       clock-output-names = "osc24M";
-               };
-
-               osc32k: clk@0 {
-                       #clock-cells = <0>;
-                       compatible = "fixed-clock";
-                       clock-frequency = <32768>;
-                       clock-output-names = "osc32k";
-               };
-       };
-
        display-engine {
                compatible = "allwinner,sun5i-a13-display-engine";
                allwinner,pipelines = <&fe0>;
        };
 
        soc@01c00000 {
-               compatible = "simple-bus";
-               #address-cells = <1>;
-               #size-cells = <1>;
-               ranges;
-
-               sram-controller@01c00000 {
-                       compatible = "allwinner,sun4i-a10-sram-controller";
-                       reg = <0x01c00000 0x30>;
-                       #address-cells = <1>;
-                       #size-cells = <1>;
-                       ranges;
-
-                       sram_a: sram@00000000 {
-                               compatible = "mmio-sram";
-                               reg = <0x00000000 0xc000>;
-                               #address-cells = <1>;
-                               #size-cells = <1>;
-                               ranges = <0 0x00000000 0xc000>;
-                       };
-
-                       sram_d: sram@00010000 {
-                               compatible = "mmio-sram";
-                               reg = <0x00010000 0x1000>;
-                               #address-cells = <1>;
-                               #size-cells = <1>;
-                               ranges = <0 0x00010000 0x1000>;
-
-                               otg_sram: sram-section@0000 {
-                                       compatible = "allwinner,sun4i-a10-sram-d";
-                                       reg = <0x0000 0x1000>;
-                                       status = "disabled";
-                               };
-                       };
-               };
-
-               dma: dma-controller@01c02000 {
-                       compatible = "allwinner,sun4i-a10-dma";
-                       reg = <0x01c02000 0x1000>;
-                       interrupts = <27>;
-                       clocks = <&ccu CLK_AHB_DMA>;
-                       #dma-cells = <2>;
-               };
-
-               nfc: nand@01c03000 {
-                       compatible = "allwinner,sun4i-a10-nand";
-                       reg = <0x01c03000 0x1000>;
-                       interrupts = <37>;
-                       clocks = <&ccu CLK_AHB_NAND>, <&ccu CLK_NAND>;
-                       clock-names = "ahb", "mod";
-                       dmas = <&dma SUN4I_DMA_DEDICATED 3>;
-                       dma-names = "rxtx";
-                       status = "disabled";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-               };
-
-               spi0: spi@01c05000 {
-                       compatible = "allwinner,sun4i-a10-spi";
-                       reg = <0x01c05000 0x1000>;
-                       interrupts = <10>;
-                       clocks = <&ccu CLK_AHB_SPI0>, <&ccu CLK_SPI0>;
-                       clock-names = "ahb", "mod";
-                       dmas = <&dma SUN4I_DMA_DEDICATED 27>,
-                              <&dma SUN4I_DMA_DEDICATED 26>;
-                       dma-names = "rx", "tx";
-                       status = "disabled";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-               };
-
-               spi1: spi@01c06000 {
-                       compatible = "allwinner,sun4i-a10-spi";
-                       reg = <0x01c06000 0x1000>;
-                       interrupts = <11>;
-                       clocks = <&ccu CLK_AHB_SPI1>, <&ccu CLK_SPI1>;
-                       clock-names = "ahb", "mod";
-                       dmas = <&dma SUN4I_DMA_DEDICATED 9>,
-                              <&dma SUN4I_DMA_DEDICATED 8>;
-                       dma-names = "rx", "tx";
-                       status = "disabled";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-               };
-
-               tve0: tv-encoder@01c0a000 {
-                       compatible = "allwinner,sun4i-a10-tv-encoder";
-                       reg = <0x01c0a000 0x1000>;
-                       clocks = <&ccu CLK_AHB_TVE>;
-                       resets = <&ccu RST_TVE>;
-                       status = "disabled";
-
-                       port {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-
-                               tve0_in_tcon0: endpoint@0 {
-                                       reg = <0>;
-                                       remote-endpoint = <&tcon0_out_tve0>;
-                               };
-                       };
-               };
-
-               tcon0: lcd-controller@01c0c000 {
-                       compatible = "allwinner,sun5i-a13-tcon";
-                       reg = <0x01c0c000 0x1000>;
-                       interrupts = <44>;
-                       resets = <&ccu RST_LCD>;
-                       reset-names = "lcd";
-                       clocks = <&ccu CLK_AHB_LCD>,
-                                <&ccu CLK_TCON_CH0>,
-                                <&ccu CLK_TCON_CH1>;
-                       clock-names = "ahb",
-                                     "tcon-ch0",
-                                     "tcon-ch1";
-                       clock-output-names = "tcon-pixel-clock";
-                       status = "disabled";
-
-                       ports {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-
-                               tcon0_in: port@0 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
-                                       reg = <0>;
-
-                                       tcon0_in_be0: endpoint@0 {
-                                               reg = <0>;
-                                               remote-endpoint = <&be0_out_tcon0>;
-                                       };
-                               };
-
-                               tcon0_out: port@1 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
-                                       reg = <1>;
-
-                                       tcon0_out_tve0: endpoint@1 {
-                                               reg = <1>;
-                                               remote-endpoint = <&tve0_in_tcon0>;
-                                       };
-                               };
-                       };
-               };
-
-               mmc0: mmc@01c0f000 {
-                       compatible = "allwinner,sun5i-a13-mmc";
-                       reg = <0x01c0f000 0x1000>;
-                       clocks = <&ccu CLK_AHB_MMC0>, <&ccu CLK_MMC0>;
-                       clock-names = "ahb", "mmc";
-                       interrupts = <32>;
-                       status = "disabled";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-               };
-
-               mmc1: mmc@01c10000 {
-                       compatible = "allwinner,sun5i-a13-mmc";
-                       reg = <0x01c10000 0x1000>;
-                       clocks = <&ccu CLK_AHB_MMC1>, <&ccu CLK_MMC1>;
-                       clock-names = "ahb", "mmc";
-                       interrupts = <33>;
-                       status = "disabled";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-               };
-
-               mmc2: mmc@01c11000 {
-                       compatible = "allwinner,sun5i-a13-mmc";
-                       reg = <0x01c11000 0x1000>;
-                       clocks = <&ccu CLK_AHB_MMC2>, <&ccu CLK_MMC2>;
-                       clock-names = "ahb", "mmc";
-                       interrupts = <34>;
-                       status = "disabled";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-               };
-
-               usb_otg: usb@01c13000 {
-                       compatible = "allwinner,sun4i-a10-musb";
-                       reg = <0x01c13000 0x0400>;
-                       clocks = <&ccu CLK_AHB_OTG>;
-                       interrupts = <38>;
-                       interrupt-names = "mc";
-                       phys = <&usbphy 0>;
-                       phy-names = "usb";
-                       extcon = <&usbphy 0>;
-                       allwinner,sram = <&otg_sram 1>;
-                       status = "disabled";
-
-                       dr_mode = "otg";
-               };
-
-               usbphy: phy@01c13400 {
-                       #phy-cells = <1>;
-                       compatible = "allwinner,sun5i-a13-usb-phy";
-                       reg = <0x01c13400 0x10 0x01c14800 0x4>;
-                       reg-names = "phy_ctrl", "pmu1";
-                       clocks = <&ccu CLK_USB_PHY0>;
-                       clock-names = "usb_phy";
-                       resets = <&ccu RST_USB_PHY0>, <&ccu RST_USB_PHY1>;
-                       reset-names = "usb0_reset", "usb1_reset";
-                       status = "disabled";
-               };
-
-               ehci0: usb@01c14000 {
-                       compatible = "allwinner,sun5i-a13-ehci", "generic-ehci";
-                       reg = <0x01c14000 0x100>;
-                       interrupts = <39>;
-                       clocks = <&ccu CLK_AHB_EHCI>;
-                       phys = <&usbphy 1>;
-                       phy-names = "usb";
-                       status = "disabled";
-               };
-
-               ohci0: usb@01c14400 {
-                       compatible = "allwinner,sun5i-a13-ohci", "generic-ohci";
-                       reg = <0x01c14400 0x100>;
-                       interrupts = <40>;
-                       clocks = <&ccu CLK_USB_OHCI>, <&ccu CLK_AHB_OHCI>;
-                       phys = <&usbphy 1>;
-                       phy-names = "usb";
-                       status = "disabled";
-               };
-
-               spi2: spi@01c17000 {
-                       compatible = "allwinner,sun4i-a10-spi";
-                       reg = <0x01c17000 0x1000>;
-                       interrupts = <12>;
-                       clocks = <&ccu CLK_AHB_SPI2>, <&ccu CLK_SPI2>;
-                       clock-names = "ahb", "mod";
-                       dmas = <&dma SUN4I_DMA_DEDICATED 29>,
-                              <&dma SUN4I_DMA_DEDICATED 28>;
-                       dma-names = "rx", "tx";
-                       status = "disabled";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-               };
-
-               ccu: clock@01c20000 {
-                       compatible = "nextthing,gr8-ccu";
-                       reg = <0x01c20000 0x400>;
-                       clocks = <&osc24M>, <&osc32k>;
-                       clock-names = "hosc", "losc";
-                       #clock-cells = <1>;
-                       #reset-cells = <1>;
-               };
-
-               intc: interrupt-controller@01c20400 {
-                       compatible = "allwinner,sun4i-a10-ic";
-                       reg = <0x01c20400 0x400>;
-                       interrupt-controller;
-                       #interrupt-cells = <1>;
-               };
-
-               pio: pinctrl@01c20800 {
-                       compatible = "nextthing,gr8-pinctrl";
-                       reg = <0x01c20800 0x400>;
-                       interrupts = <28>;
-                       clocks = <&ccu CLK_APB0_PIO>;
-                       gpio-controller;
-                       interrupt-controller;
-                       #interrupt-cells = <3>;
-                       #gpio-cells = <3>;
-
-                       i2c0_pins_a: i2c0@0 {
-                               pins = "PB0", "PB1";
-                               function = "i2c0";
-                       };
-
-                       i2c1_pins_a: i2c1@0 {
-                               pins = "PB15", "PB16";
-                               function = "i2c1";
-                       };
-
-                       i2c2_pins_a: i2c2@0 {
-                               pins = "PB17", "PB18";
-                               function = "i2c2";
-                       };
-
-                       i2s0_data_pins_a: i2s0-data@0 {
-                               pins = "PB6", "PB7", "PB8", "PB9";
-                               function = "i2s0";
-                       };
-
-                       i2s0_mclk_pins_a: i2s0-mclk@0 {
-                               pins = "PB5";
-                               function = "i2s0";
-                       };
-
-                       ir0_rx_pins_a: ir0@0 {
-                               pins = "PB4";
-                               function = "ir0";
-                       };
-
-                       lcd_rgb666_pins: lcd-rgb666@0 {
-                               pins = "PD2", "PD3", "PD4", "PD5", "PD6", "PD7",
-                                                "PD10", "PD11", "PD12", "PD13", "PD14", "PD15",
-                                                "PD18", "PD19", "PD20", "PD21", "PD22", "PD23",
-                                                "PD24", "PD25", "PD26", "PD27";
-                               function = "lcd0";
-                       };
-
-                       mmc0_pins_a: mmc0@0 {
-                               pins = "PF0", "PF1", "PF2", "PF3",
-                                                "PF4", "PF5";
-                               function = "mmc0";
-                               drive-strength = <30>;
-                       };
-
-                       nand_pins_a: nand-base0@0 {
-                               pins = "PC0", "PC1", "PC2",
-                                               "PC5", "PC8", "PC9", "PC10",
-                                               "PC11", "PC12", "PC13", "PC14",
-                                               "PC15";
-                               function = "nand0";
-                       };
-
-                       nand_cs0_pins_a: nand-cs@0 {
-                               pins = "PC4";
-                               function = "nand0";
-                       };
-
-                       nand_rb0_pins_a: nand-rb@0 {
-                               pins = "PC6";
-                               function = "nand0";
-                       };
-
-                       pwm0_pins_a: pwm0@0 {
-                               pins = "PB2";
-                               function = "pwm0";
-                       };
-
-                       pwm1_pins: pwm1 {
-                               pins = "PG13";
-                               function = "pwm1";
-                       };
-
-                       spdif_tx_pins_a: spdif@0 {
-                               pins = "PB10";
-                               function = "spdif";
-                               bias-pull-up;
-                       };
-
-                       uart1_pins_a: uart1@1 {
-                               pins = "PG3", "PG4";
-                               function = "uart1";
-                       };
-
-                       uart1_cts_rts_pins_a: uart1-cts-rts@0 {
-                               pins = "PG5", "PG6";
-                               function = "uart1";
-                       };
-
-                       uart2_pins_a: uart2@1 {
-                               pins = "PD2", "PD3";
-                               function = "uart2";
-                       };
-
-                       uart2_cts_rts_pins_a: uart2-cts-rts@0 {
-                               pins = "PD4", "PD5";
-                               function = "uart2";
-                       };
-
-                       uart3_pins_a: uart3@1 {
-                               pins = "PG9", "PG10";
-                               function = "uart3";
-                       };
-
-                       uart3_cts_rts_pins_a: uart3-cts-rts@0 {
-                               pins = "PG11", "PG12";
-                               function = "uart3";
-                       };
-               };
-
                pwm: pwm@01c20e00 {
                        compatible = "allwinner,sun5i-a10s-pwm";
                        reg = <0x01c20e00 0xc>;
                        status = "disabled";
                };
 
-               timer@01c20c00 {
-                       compatible = "allwinner,sun4i-a10-timer";
-                       reg = <0x01c20c00 0x90>;
-                       interrupts = <22>;
-                       clocks = <&ccu CLK_HOSC>;
-               };
-
-               wdt: watchdog@01c20c90 {
-                       compatible = "allwinner,sun4i-a10-wdt";
-                       reg = <0x01c20c90 0x10>;
-               };
-
                spdif: spdif@01c21000 {
                        #sound-dai-cells = <0>;
                        compatible = "allwinner,sun4i-a10-spdif";
                        status = "disabled";
                };
 
-               ir0: ir@01c21800 {
-                       compatible = "allwinner,sun4i-a10-ir";
-                       clocks = <&ccu CLK_APB0_IR>, <&ccu CLK_IR>;
-                       clock-names = "apb", "ir";
-                       interrupts = <5>;
-                       reg = <0x01c21800 0x40>;
-                       status = "disabled";
-               };
-
                i2s0: i2s@01c22400 {
                        #sound-dai-cells = <0>;
                        compatible = "allwinner,sun4i-a10-i2s";
                        dma-names = "rx", "tx";
                        status = "disabled";
                };
+       };
+};
 
-               lradc: lradc@01c22800 {
-                       compatible = "allwinner,sun4i-a10-lradc-keys";
-                       reg = <0x01c22800 0x100>;
-                       interrupts = <31>;
-                       status = "disabled";
-               };
-
-               codec: codec@01c22c00 {
-                       #sound-dai-cells = <0>;
-                       compatible = "allwinner,sun4i-a10-codec";
-                       reg = <0x01c22c00 0x40>;
-                       interrupts = <30>;
-                       clocks = <&ccu CLK_APB0_CODEC>, <&ccu CLK_CODEC>;
-                       clock-names = "apb", "codec";
-                       dmas = <&dma SUN4I_DMA_NORMAL 19>,
-                              <&dma SUN4I_DMA_NORMAL 19>;
-                       dma-names = "rx", "tx";
-                       status = "disabled";
-               };
-
-               rtp: rtp@01c25000 {
-                       compatible = "allwinner,sun5i-a13-ts";
-                       reg = <0x01c25000 0x100>;
-                       interrupts = <29>;
-                       #thermal-sensor-cells = <0>;
-               };
-
-               uart1: serial@01c28400 {
-                       compatible = "snps,dw-apb-uart";
-                       reg = <0x01c28400 0x400>;
-                       interrupts = <2>;
-                       reg-shift = <2>;
-                       reg-io-width = <4>;
-                       clocks = <&ccu CLK_APB1_UART1>;
-                       status = "disabled";
-               };
-
-               uart2: serial@01c28800 {
-                       compatible = "snps,dw-apb-uart";
-                       reg = <0x01c28800 0x400>;
-                       interrupts = <3>;
-                       reg-shift = <2>;
-                       reg-io-width = <4>;
-                       clocks = <&ccu CLK_APB1_UART2>;
-                       status = "disabled";
-               };
-
-               uart3: serial@01c28c00 {
-                       compatible = "snps,dw-apb-uart";
-                       reg = <0x01c28c00 0x400>;
-                       interrupts = <4>;
-                       reg-shift = <2>;
-                       reg-io-width = <4>;
-                       clocks = <&ccu CLK_APB1_UART3>;
-                       status = "disabled";
-               };
-
-               i2c0: i2c@01c2ac00 {
-                       compatible = "allwinner,sun4i-a10-i2c";
-                       reg = <0x01c2ac00 0x400>;
-                       interrupts = <7>;
-                       clocks = <&ccu CLK_APB1_I2C0>;
-                       status = "disabled";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-               };
-
-               i2c1: i2c@01c2b000 {
-                       compatible = "allwinner,sun4i-a10-i2c";
-                       reg = <0x01c2b000 0x400>;
-                       interrupts = <8>;
-                       clocks = <&ccu CLK_APB1_I2C1>;
-                       status = "disabled";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-               };
-
-               i2c2: i2c@01c2b400 {
-                       compatible = "allwinner,sun4i-a10-i2c";
-                       reg = <0x01c2b400 0x400>;
-                       interrupts = <9>;
-                       clocks = <&ccu CLK_APB1_I2C2>;
-                       status = "disabled";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-               };
-
-               timer@01c60000 {
-                       compatible = "allwinner,sun5i-a13-hstimer";
-                       reg = <0x01c60000 0x1000>;
-                       interrupts = <82>, <83>;
-                       clocks = <&ccu CLK_AHB_HSTIMER>;
-               };
-
-               fe0: display-frontend@01e00000 {
-                       compatible = "allwinner,sun5i-a13-display-frontend";
-                       reg = <0x01e00000 0x20000>;
-                       interrupts = <47>;
-                       clocks = <&ccu CLK_AHB_DE_FE>, <&ccu CLK_DE_FE>,
-                                <&ccu CLK_DRAM_DE_FE>;
-                       clock-names = "ahb", "mod",
-                                     "ram";
-                       resets = <&ccu RST_DE_FE>;
-                       status = "disabled";
-
-                       ports {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-
-                               fe0_out: port@1 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
-                                       reg = <1>;
-
-                                       fe0_out_be0: endpoint@0 {
-                                               reg = <0>;
-                                               remote-endpoint = <&be0_in_fe0>;
-                                       };
-                               };
-                       };
-               };
-
-               be0: display-backend@01e60000 {
-                       compatible = "allwinner,sun5i-a13-display-backend";
-                       reg = <0x01e60000 0x10000>;
-                       clocks = <&ccu CLK_AHB_DE_BE>, <&ccu CLK_DE_BE>,
-                                <&ccu CLK_DRAM_DE_BE>;
-                       clock-names = "ahb", "mod",
-                                     "ram";
-                       resets = <&ccu RST_DE_BE>;
-                       status = "disabled";
+&ccu {
+       compatible = "nextthing,gr8-ccu";
+};
 
-                       assigned-clocks = <&ccu CLK_DE_BE>;
-                       assigned-clock-rates = <300000000>;
+&pio {
+       compatible = "nextthing,gr8-pinctrl";
 
-                       ports {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
+       i2s0_data_pins_a: i2s0-data@0 {
+               pins = "PB6", "PB7", "PB8", "PB9";
+               function = "i2s0";
+       };
 
-                               be0_in: port@0 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
-                                       reg = <0>;
+       i2s0_mclk_pins_a: i2s0-mclk@0 {
+               pins = "PB5";
+               function = "i2s0";
+       };
 
-                                       be0_in_fe0: endpoint@0 {
-                                               reg = <0>;
-                                               remote-endpoint = <&fe0_out_be0>;
-                                       };
-                               };
+       pwm1_pins: pwm1 {
+               pins = "PG13";
+               function = "pwm1";
+       };
 
-                               be0_out: port@1 {
-                                       #address-cells = <1>;
-                                       #size-cells = <0>;
-                                       reg = <1>;
+       spdif_tx_pins_a: spdif@0 {
+               pins = "PB10";
+               function = "spdif";
+               bias-pull-up;
+       };
 
-                                       be0_out_tcon0: endpoint@0 {
-                                               reg = <0>;
-                                               remote-endpoint = <&tcon0_in_be0>;
-                                       };
-                               };
-                       };
-               };
+       uart1_cts_rts_pins_a: uart1-cts-rts@0 {
+               pins = "PG5", "PG6";
+               function = "uart1";
        };
 };
index e86fa46fdd4553c4afb41a8ef66cd803734457b4..d0785602663ba5e9d09d376604230f49ad2e0c06 100644 (file)
 
 #include "axp209.dtsi"
 
+&ac_power_supply {
+       status = "okay";
+};
+
 &i2c1 {
        pinctrl-names = "default";
        pinctrl-0 = <&i2c1_pins_a>;
 &uart3 {
        pinctrl-names = "default";
        pinctrl-0 = <&uart3_pins_a>,
-                   <&uart3_pins_cts_rts_a>;
+                   <&uart3_cts_rts_pins_a>;
        status = "okay";
 };
 
index 4c1141396c99e8e5dbad67d4a055fc82d77a097d..de35dbcd11916848eab0d7653dae71e786a663a9 100644 (file)
 
 #include "sun5i-a13.dtsi"
 
-/ {
-       chosen {
-               framebuffer@1 {
-                       compatible = "allwinner,simple-framebuffer",
-                                    "simple-framebuffer";
-                       allwinner,pipeline = "de_be0-lcd0-tve0";
-                       clocks = <&ccu CLK_AHB_TVE>, <&ccu CLK_AHB_LCD>,
-                                <&ccu CLK_AHB_DE_BE>, <&ccu CLK_DE_BE>,
-                                <&ccu CLK_TCON_CH1>, <&ccu CLK_DRAM_DE_BE>;
-                       status = "disabled";
-               };
-       };
-
-       soc@01c00000 {
-               tve0: tv-encoder@01c0a000 {
-                       compatible = "allwinner,sun4i-a10-tv-encoder";
-                       reg = <0x01c0a000 0x1000>;
-                       clocks = <&ccu CLK_AHB_TVE>;
-                       resets = <&ccu RST_TVE>;
-                       status = "disabled";
-
-                       port {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-
-                               tve0_in_tcon0: endpoint@0 {
-                                       reg = <0>;
-                                       remote-endpoint = <&tcon0_out_tve0>;
-                               };
-                       };
-               };
-       };
-};
-
-&tcon0_out {
-       tcon0_out_tve0: endpoint@1 {
-               reg = <1>;
-               remote-endpoint = <&tve0_in_tcon0>;
-       };
-};
index a9574a6cd95c6d5fcb84c0e9c66bee5a3fc550ec..5175f9cc9bed0f4f6169c1ef9387ffa74044b0b5 100644 (file)
@@ -46,7 +46,6 @@
 
 #include <dt-bindings/clock/sun5i-ccu.h>
 #include <dt-bindings/dma/sun4i-a10.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 #include <dt-bindings/reset/sun5i-ccu.h>
 
 / {
                };
        };
 
+       chosen {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               framebuffer@0 {
+                       compatible = "allwinner,simple-framebuffer",
+                                    "simple-framebuffer";
+                       allwinner,pipeline = "de_be0-lcd0";
+                       clocks = <&ccu CLK_AHB_LCD>, <&ccu CLK_AHB_DE_BE>, <&ccu CLK_DE_BE>,
+                                <&ccu CLK_TCON_CH0>, <&ccu CLK_DRAM_DE_BE>;
+                       status = "disabled";
+               };
+
+               framebuffer@1 {
+                       compatible = "allwinner,simple-framebuffer",
+                                    "simple-framebuffer";
+                       allwinner,pipeline = "de_be0-lcd0-tve0";
+                       clocks = <&ccu CLK_AHB_TVE>, <&ccu CLK_AHB_LCD>,
+                                <&ccu CLK_AHB_DE_BE>, <&ccu CLK_DE_BE>,
+                                <&ccu CLK_TCON_CH1>, <&ccu CLK_DRAM_DE_BE>;
+                       status = "disabled";
+               };
+       };
+
        clocks {
                #address-cells = <1>;
                #size-cells = <1>;
                                ranges = <0 0x00000000 0xc000>;
                        };
 
+                       emac_sram: sram-section@8000 {
+                               compatible = "allwinner,sun4i-a10-sram-a3-a4";
+                               reg = <0x8000 0x4000>;
+                               status = "disabled";
+                       };
+
                        sram_d: sram@00010000 {
                                compatible = "mmio-sram";
                                reg = <0x00010000 0x1000>;
                        #dma-cells = <2>;
                };
 
+               nfc: nand@01c03000 {
+                       compatible = "allwinner,sun4i-a10-nand";
+                       reg = <0x01c03000 0x1000>;
+                       interrupts = <37>;
+                       clocks = <&ccu CLK_AHB_NAND>, <&ccu CLK_NAND>;
+                       clock-names = "ahb", "mod";
+                       dmas = <&dma SUN4I_DMA_DEDICATED 3>;
+                       dma-names = "rxtx";
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
                spi0: spi@01c05000 {
                        compatible = "allwinner,sun4i-a10-spi";
                        reg = <0x01c05000 0x1000>;
                        #size-cells = <0>;
                };
 
+               tve0: tv-encoder@01c0a000 {
+                       compatible = "allwinner,sun4i-a10-tv-encoder";
+                       reg = <0x01c0a000 0x1000>;
+                       clocks = <&ccu CLK_AHB_TVE>;
+                       resets = <&ccu RST_TVE>;
+                       status = "disabled";
+
+                       port {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               tve0_in_tcon0: endpoint@0 {
+                                       reg = <0>;
+                                       remote-endpoint = <&tcon0_out_tve0>;
+                               };
+                       };
+               };
+
+               emac: ethernet@01c0b000 {
+                       compatible = "allwinner,sun4i-a10-emac";
+                       reg = <0x01c0b000 0x1000>;
+                       interrupts = <55>;
+                       clocks = <&ccu CLK_AHB_EMAC>;
+                       allwinner,sram = <&emac_sram 1>;
+                       status = "disabled";
+               };
+
+               mdio: mdio@01c0b080 {
+                       compatible = "allwinner,sun4i-a10-mdio";
+                       reg = <0x01c0b080 0x14>;
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               tcon0: lcd-controller@01c0c000 {
+                       compatible = "allwinner,sun5i-a13-tcon";
+                       reg = <0x01c0c000 0x1000>;
+                       interrupts = <44>;
+                       resets = <&ccu RST_LCD>;
+                       reset-names = "lcd";
+                       clocks = <&ccu CLK_AHB_LCD>,
+                                <&ccu CLK_TCON_CH0>,
+                                <&ccu CLK_TCON_CH1>;
+                       clock-names = "ahb",
+                                     "tcon-ch0",
+                                     "tcon-ch1";
+                       clock-output-names = "tcon-pixel-clock";
+                       status = "disabled";
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               tcon0_in: port@0 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <0>;
+
+                                       tcon0_in_be0: endpoint@0 {
+                                               reg = <0>;
+                                               remote-endpoint = <&be0_out_tcon0>;
+                                       };
+                               };
+
+                               tcon0_out: port@1 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <1>;
+
+                                       tcon0_out_tve0: endpoint@1 {
+                                               reg = <1>;
+                                               remote-endpoint = <&tve0_in_tcon0>;
+                                       };
+                               };
+                       };
+               };
+
                mmc0: mmc@01c0f000 {
                        compatible = "allwinner,sun5i-a13-mmc";
                        reg = <0x01c0f000 0x1000>;
                        #interrupt-cells = <3>;
                        #gpio-cells = <3>;
 
+                       emac_pins_a: emac0@0 {
+                               pins = "PD6", "PD7", "PD10",
+                                      "PD11", "PD12", "PD13", "PD14",
+                                      "PD15", "PD18", "PD19", "PD20",
+                                      "PD21", "PD22", "PD23", "PD24",
+                                      "PD25", "PD26", "PD27";
+                               function = "emac";
+                       };
+
                        i2c0_pins_a: i2c0@0 {
                                pins = "PB0", "PB1";
                                function = "i2c0";
                                function = "i2c2";
                        };
 
+                       ir0_rx_pins_a: ir0@0 {
+                               pins = "PB4";
+                               function = "ir0";
+                       };
+
                        lcd_rgb565_pins: lcd_rgb565@0 {
                                pins = "PD3", "PD4", "PD5", "PD6", "PD7",
                                                 "PD10", "PD11", "PD12", "PD13", "PD14", "PD15",
                                function = "lcd0";
                        };
 
+                       lcd_rgb666_pins: lcd_rgb666@0 {
+                               pins = "PD2", "PD3", "PD4", "PD5", "PD6", "PD7",
+                                      "PD10", "PD11", "PD12", "PD13", "PD14", "PD15",
+                                      "PD18", "PD19", "PD20", "PD21", "PD22", "PD23",
+                                      "PD24", "PD25", "PD26", "PD27";
+                               function = "lcd0";
+                       };
+
                        mmc0_pins_a: mmc0@0 {
                                pins = "PF0", "PF1", "PF2", "PF3",
                                       "PF4", "PF5";
                                bias-pull-up;
                        };
 
+                       nand_pins_a: nand-base0@0 {
+                               pins = "PC0", "PC1", "PC2",
+                                      "PC5", "PC8", "PC9", "PC10",
+                                      "PC11", "PC12", "PC13", "PC14",
+                                      "PC15";
+                               function = "nand0";
+                       };
+
+                       nand_cs0_pins_a: nand-cs@0 {
+                               pins = "PC4";
+                               function = "nand0";
+                       };
+
+                       nand_rb0_pins_a: nand-rb@0 {
+                               pins = "PC6";
+                               function = "nand0";
+                       };
+
                        spi2_pins_a: spi2@0 {
                                pins = "PE1", "PE2", "PE3";
                                function = "spi2";
                                function = "spi2";
                        };
 
+                       uart1_pins_a: uart1@0 {
+                               pins = "PE10", "PE11";
+                               function = "uart1";
+                       };
+
+                       uart1_pins_b: uart1@1 {
+                               pins = "PG3", "PG4";
+                               function = "uart1";
+                       };
+
+                       uart2_pins_a: uart2@0 {
+                               pins = "PD2", "PD3";
+                               function = "uart2";
+                       };
+
+                       uart2_cts_rts_pins_a: uart2-cts-rts@0 {
+                               pins = "PD4", "PD5";
+                               function = "uart2";
+                       };
+
                        uart3_pins_a: uart3@0 {
                                pins = "PG9", "PG10";
                                function = "uart3";
                        };
 
-                       uart3_pins_cts_rts_a: uart3-cts-rts@0 {
+                       uart3_cts_rts_pins_a: uart3-cts-rts@0 {
                                pins = "PG11", "PG12";
                                function = "uart3";
                        };
                        reg = <0x01c20c90 0x10>;
                };
 
+               ir0: ir@01c21800 {
+                       compatible = "allwinner,sun4i-a10-ir";
+                       clocks = <&ccu CLK_APB0_IR>, <&ccu CLK_IR>;
+                       clock-names = "apb", "ir";
+                       interrupts = <5>;
+                       reg = <0x01c21800 0x40>;
+                       status = "disabled";
+               };
+
                lradc: lradc@01c22800 {
                        compatible = "allwinner,sun4i-a10-lradc-keys";
                        reg = <0x01c22800 0x100>;
                        #thermal-sensor-cells = <0>;
                };
 
+               uart0: serial@01c28000 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x01c28000 0x400>;
+                       interrupts = <1>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       clocks = <&ccu CLK_APB1_UART0>;
+                       status = "disabled";
+               };
+
                uart1: serial@01c28400 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0x01c28400 0x400>;
                        status = "disabled";
                };
 
+               uart2: serial@01c28800 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x01c28800 0x400>;
+                       interrupts = <3>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       clocks = <&ccu CLK_APB1_UART2>;
+                       status = "disabled";
+               };
+
                uart3: serial@01c28c00 {
                        compatible = "snps,dw-apb-uart";
                        reg = <0x01c28c00 0x400>;
                        interrupts = <82>, <83>;
                        clocks = <&ccu CLK_AHB_HSTIMER>;
                };
+
+               fe0: display-frontend@01e00000 {
+                       compatible = "allwinner,sun5i-a13-display-frontend";
+                       reg = <0x01e00000 0x20000>;
+                       interrupts = <47>;
+                       clocks = <&ccu CLK_DE_FE>, <&ccu CLK_DE_FE>,
+                                <&ccu CLK_DRAM_DE_FE>;
+                       clock-names = "ahb", "mod",
+                                     "ram";
+                       resets = <&ccu RST_DE_FE>;
+                       status = "disabled";
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               fe0_out: port@1 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <1>;
+
+                                       fe0_out_be0: endpoint@0 {
+                                               reg = <0>;
+                                               remote-endpoint = <&be0_in_fe0>;
+                                       };
+                               };
+                       };
+               };
+
+               be0: display-backend@01e60000 {
+                       compatible = "allwinner,sun5i-a13-display-backend";
+                       reg = <0x01e60000 0x10000>;
+                       interrupts = <47>;
+                       clocks = <&ccu CLK_AHB_DE_BE>, <&ccu CLK_DE_BE>,
+                                <&ccu CLK_DRAM_DE_BE>;
+                       clock-names = "ahb", "mod",
+                                     "ram";
+                       resets = <&ccu RST_DE_BE>;
+                       status = "disabled";
+
+                       assigned-clocks = <&ccu CLK_DE_BE>;
+                       assigned-clock-rates = <300000000>;
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               be0_in: port@0 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <0>;
+
+                                       be0_in_fe0: endpoint@0 {
+                                               reg = <0>;
+                                               remote-endpoint = <&fe0_out_be0>;
+                                       };
+                               };
+
+                               be0_out: port@1 {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+                                       reg = <1>;
+
+                                       be0_out_tcon0: endpoint@0 {
+                                               reg = <0>;
+                                               remote-endpoint = <&tcon0_in_be0>;
+                                       };
+                               };
+                       };
+               };
        };
 };
index effbdc766938590cae987afbf3ef638d60532ca1..7f34323a668c41b29066aabce9423b31bdb16094 100644 (file)
@@ -47,7 +47,6 @@
 #include "sunxi-common-regulators.dtsi"
 
 #include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Allwinner A31 APP4 EVB1 Evaluation Board";
index f5ececd45bc0333bbbede4bd7acd40673a25d8ea..85eff0307ca4236571846dae8fc47041b58533ae 100644 (file)
@@ -47,7 +47,6 @@
 #include "sunxi-common-regulators.dtsi"
 
 #include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "WITS A31 Colombus Evaluation Board";
index f094eeb6c499fcd3137c38c042a48d409983f5d2..d4f74f476f25e036ba6b0248f2bfcdf429167796 100644 (file)
@@ -47,7 +47,6 @@
 #include "sunxi-common-regulators.dtsi"
 
 #include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Merrii A31 Hummingbird";
index 2bc57d2dcd80f6359bce9a6c1eeaf87d4cca836a..010a84c7c012a141dd32c2961a80c584de4387fc 100644 (file)
@@ -45,7 +45,6 @@
 #include "sunxi-common-regulators.dtsi"
 
 #include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Mele I7 Quad top set box";
index 8af5b667a46d01d9c4efabe3bdc846fdcd22ca84..50605fd4449e4e4c549152dcbc78e4cfc07142b3 100644 (file)
@@ -45,7 +45,6 @@
 #include "sunxi-common-regulators.dtsi"
 
 #include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Mele M9 top set box";
index bf0f5831126f15710348e0dd00012295dbf43d36..5219556e9f73e96adb6d307e002b35d246d8e0b3 100644 (file)
@@ -45,7 +45,6 @@
 #include "sunxi-common-regulators.dtsi"
 
 #include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Mele A1000G Quad top set box";
index a4b96184cac11bf72456aeb6af6ce892969f1222..9c999d3788f6816f81296b40e3e202d98cd22b2f 100644 (file)
@@ -48,7 +48,6 @@
 #include <dt-bindings/thermal/thermal.h>
 
 #include <dt-bindings/clock/sun6i-a31-ccu.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 #include <dt-bindings/reset/sun6i-a31-ccu.h>
 
 / {
index 5e8f8c4f2b302a67ab02f396977a92e174d76ce3..75e578159c3ab35908c998bb854db018f62daac5 100644 (file)
@@ -43,8 +43,6 @@
 /dts-v1/;
 #include "sun6i-a31s.dtsi"
 
-#include <dt-bindings/pinctrl/sun4i-a10.h>
-
 / {
        model = "CSQ CS908 top set box";
        compatible = "csq,cs908", "allwinner,sun6i-a31s";
index 2238eda318f60f060d7c82ad290d3a1271ce1358..f3712753fa425a97178cc71962064cd99737c0d7 100644 (file)
@@ -48,7 +48,6 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "MSI Primo81 tablet";
index 4ec0c8679b2e20b9a15b28160639daf264abd0d6..d7325bc4eeb40d11349d94fca8b0e00943aa7612 100644 (file)
@@ -45,7 +45,6 @@
 #include "sunxi-common-regulators.dtsi"
 
 #include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Sinlinx SinA31s Core Board";
index 7ff68bdd71098afcbc65f713b457d5e9b9744eed..b3d98222bd8134700addbef18b22b57464999e07 100644 (file)
                        gpios = <&pio 7 13 GPIO_ACTIVE_HIGH>; /* PH13 */
                };
        };
+
+       sound {
+               compatible = "simple-audio-card";
+               simple-audio-card,name = "On-board 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";
+       };
 };
 
 &codec {
        regulator-name = "vcc-gmac-phy";
 };
 
+&spdif {
+       pinctrl-names = "default";
+       pinctrl-0 = <&spdif_pins_a>;
+       status = "okay";
+};
+
 &usb_otg {
        dr_mode = "peripheral";
        status = "okay";
index 3bd862bf82a968caebd44f512ae0e0a76866fcea..bdfdce8ca6ba12beedbceb4487cc00c2159d508a 100644 (file)
        };
 };
 
+&cpu0 {
+       cpu-supply = <&reg_dcdc3>;
+};
+
 &ehci0 {
        status = "okay";
 };
        status = "okay";
 };
 
+&p2wi {
+       status = "okay";
+
+       axp22x: pmic@68 {
+               compatible = "x-powers,axp221";
+               reg = <0x68>;
+               interrupt-parent = <&nmi_intc>;
+               interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+       };
+};
+
 &pio {
        gmac_phy_reset_pin_bpi_m2: gmac_phy_reset_pin@0 {
                pins = "PA21";
        };
 };
 
+#include "axp22x.dtsi"
+
+&reg_dc5ldo {
+       regulator-min-microvolt = <700000>;
+       regulator-max-microvolt = <1320000>;
+       regulator-name = "vdd-cpus";
+};
+
+&reg_dcdc1 {
+       regulator-always-on;
+       regulator-min-microvolt = <3000000>;
+       regulator-max-microvolt = <3000000>;
+       regulator-name = "vdd-3v0";
+};
+
+&reg_dcdc2 {
+       regulator-min-microvolt = <700000>;
+       regulator-max-microvolt = <1320000>;
+       regulator-name = "vdd-gpu";
+};
+
+&reg_dcdc3 {
+       regulator-always-on;
+       regulator-min-microvolt = <700000>;
+       regulator-max-microvolt = <1320000>;
+       regulator-name = "vdd-cpu";
+};
+
+&reg_dcdc4 {
+       regulator-always-on;
+       regulator-min-microvolt = <700000>;
+       regulator-max-microvolt = <1320000>;
+       regulator-name = "vdd-sys-dll";
+};
+
+&reg_dcdc5 {
+       regulator-always-on;
+       regulator-min-microvolt = <1500000>;
+       regulator-max-microvolt = <1500000>;
+       regulator-name = "vcc-dram";
+};
+
 &uart0 {
        pinctrl-names = "default";
        pinctrl-0 = <&uart0_pins_a>;
index 154ebf5082ed3543a3d48c48da866dbe71a65034..f3edf9ca435cffe69622499d2997353491f240c4 100644 (file)
@@ -45,7 +45,6 @@
 #include "sunxi-common-regulators.dtsi"
 
 #include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Yones TopTech BS1078 v2 Tablet";
index edaba5f904fd8eccaf518dc9389d183d16c62c56..3cc4046b904a51d30192ccfa49a02b241127cf77 100644 (file)
@@ -44,7 +44,6 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        aliases {
index 91f2e5f9efcbe30219fafc4bca99cdebb9386d41..ed2f35adf5426d630f72c48b7a1276db9b4b3952 100644 (file)
@@ -48,7 +48,6 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "LeMaker Banana Pi";
index 4dc1e10f88c47ba5769757933f22e5d363f6db65..a2eab7aa80e014383ebe69d34fed4d55a4b5bd23 100644 (file)
@@ -48,7 +48,6 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Cubietech Cubieboard2";
index f019aa3fe96d86031000c4cf6ddaa03656669594..102903e83bd216802dbfd6d75d553082d83926d6 100644 (file)
@@ -48,7 +48,6 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Cubietech Cubietruck";
 
 #include "axp209.dtsi"
 
+&ac_power_supply {
+       status = "okay";
+};
+
 &reg_dcdc2 {
        regulator-always-on;
        regulator-min-microvolt = <1000000>;
        status = "okay";
 };
 
+&usb_power_supply {
+       status = "okay";
+};
+
 &usbphy {
        pinctrl-names = "default";
        pinctrl-0 = <&usb0_id_detect_pin>, <&usb0_vbus_detect_pin>;
index e921ba42f1703c11f2c1182d0ae67b6e793ea550..99c00b9a15464f2039760efebbe8d033881415fb 100644 (file)
@@ -48,7 +48,6 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Merrii A20 Hummingbird";
index 385fd8232ae00b83f1b9e14073a3a144cc9b0b66..4da49717da210835bbc99a88701c7febd5de67e6 100644 (file)
@@ -46,7 +46,6 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "I12 / Q5 / QT840A A20 tvbox";
index f5b5325a70e2a19a1c2b12ff8a72e0434a08bb99..28d3abbdc2d4c9c42edc227bc1047489f7a7cdde 100644 (file)
@@ -46,7 +46,6 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "ICnova-A20 SWAC";
index bbf1c8cbaac6aa19a6acd946a0230220e4e11417..96bb0bc198baff67123df539911e7e173b926df1 100644 (file)
@@ -46,7 +46,6 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Lamobo R1";
index 0e074bd0e8c924e6164b92c91c1c6d49bcda7268..86f69813683ec1b41d99c5ab74e48cb4695c914d 100644 (file)
@@ -48,7 +48,6 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Mele M3";
index 97d7a8b65a0313b1167f13aaa45199be4ec388f3..c4ee30709f3a1875d5e5ea2c36677707dd1db9a9 100644 (file)
@@ -53,7 +53,6 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "mk808c";
index a1450c10b08ecefea6f8f165acab65dd282a72f7..1af5b46862cba9d5add598f2cbbbdf8f4ff86b53 100644 (file)
@@ -48,7 +48,6 @@
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Olimex A20-Olimex-SOM-EVB";
index 1297432c28021701cafe96b3080cc61505eec413..dcd0f7a0dffae7716deba7cafac55c532cca8b06 100644 (file)
@@ -49,7 +49,6 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Olimex A20-OLinuXino-LIME";
index 71cca5360728b6bc727fd352b6f6ba26519936d7..e7d45425758ca1e87980f2b52736d9ff0ec780e2 100644 (file)
@@ -46,7 +46,6 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Olimex A20-OLinuXino-LIME2";
index 223fbd9f7c62db31d1f0e72c56664df0159b54f0..def0ad8395bb2c80a6ce173029ca42f8eab34c91 100644 (file)
@@ -49,7 +49,6 @@
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Olimex A20-Olinuxino Micro";
        status = "okay";
 };
 
+&codec {
+       status = "okay";
+};
+
+&cpu0 {
+       cpu-supply = <&reg_dcdc2>;
+};
+
 &ehci0 {
        status = "okay";
 };
        status = "okay";
 
        axp209: pmic@34 {
-               compatible = "x-powers,axp209";
                reg = <0x34>;
                interrupt-parent = <&nmi_intc>;
                interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
-
-               interrupt-controller;
-               #interrupt-cells = <1>;
        };
 };
 
        };
 };
 
+#include "axp209.dtsi"
+
+&reg_dcdc2 {
+       regulator-always-on;
+       regulator-min-microvolt = <1000000>;
+       regulator-max-microvolt = <1400000>;
+       regulator-name = "vdd-cpu";
+};
+
+&reg_dcdc3 {
+       regulator-always-on;
+       regulator-min-microvolt = <1000000>;
+       regulator-max-microvolt = <1400000>;
+       regulator-name = "vdd-int-dll";
+};
+
+&reg_ldo2 {
+       regulator-always-on;
+       regulator-min-microvolt = <3000000>;
+       regulator-max-microvolt = <3000000>;
+       regulator-name = "avcc";
+};
+
 &reg_ahci_5v {
        status = "okay";
 };
index a7426574922781b4801569ad784206ca5ba1e64b..7af4c8fc18656ad11461babba737cce7e2b64d17 100644 (file)
@@ -48,7 +48,6 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Orange Pi Mini";
index 3de980c8f8ff9ab4ebfb8484875d634f7bc72204..0a8d4a05e8a09946ebad9a726eadc62da7b67e68 100644 (file)
@@ -48,7 +48,6 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Orange Pi";
index 4599f98a3aeee60c89f291fcf517a09042644d3f..7c96b53b76bfe0ae4a9a6beac0d93e737aa9b919 100644 (file)
@@ -48,7 +48,6 @@
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
 #include <dt-bindings/interrupt-controller/irq.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "LinkSprite pcDuino3";
index 2db97fc820dd678a6076f6bb78b052dd2af32ffe..93aa55970bd7a28bdede575b6da0a88daa352568 100644 (file)
@@ -49,7 +49,6 @@
 
 #include <dt-bindings/clock/sun4i-a10-pll2.h>
 #include <dt-bindings/dma/sun4i-a10.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        interrupt-parent = <&gic>;
                        #interrupt-cells = <3>;
                        #gpio-cells = <3>;
 
+                       can0_pins_a: can0@0 {
+                               pins = "PH20", "PH21";
+                               function = "can";
+                       };
+
                        clk_out_a_pins_a: clk_out_a@0 {
                                pins = "PI12";
                                function = "clk_out_a";
                        status = "disabled";
                };
 
+               ps20: ps2@01c2a000 {
+                       compatible = "allwinner,sun4i-a10-ps2";
+                       reg = <0x01c2a000 0x400>;
+                       interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&apb1_gates 6>;
+                       status = "disabled";
+               };
+
+               ps21: ps2@01c2a400 {
+                       compatible = "allwinner,sun4i-a10-ps2";
+                       reg = <0x01c2a400 0x400>;
+                       interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&apb1_gates 7>;
+                       status = "disabled";
+               };
+
                i2c0: i2c@01c2ac00 {
                        compatible = "allwinner,sun7i-a20-i2c",
                                     "allwinner,sun4i-a10-i2c";
                        #size-cells = <0>;
                };
 
+               can0: can@01c2bc00 {
+                       compatible = "allwinner,sun7i-a20-can",
+                                    "allwinner,sun4i-a10-can";
+                       reg = <0x01c2bc00 0x400>;
+                       interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&apb1_gates 4>;
+                       status = "disabled";
+               };
+
                i2c4: i2c@01c2c000 {
                        compatible = "allwinner,sun7i-a20-i2c",
                                     "allwinner,sun4i-a10-i2c";
                        interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
                };
 
-               ps20: ps2@01c2a000 {
-                       compatible = "allwinner,sun4i-a10-ps2";
-                       reg = <0x01c2a000 0x400>;
-                       interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&apb1_gates 6>;
-                       status = "disabled";
-               };
-
-               ps21: ps2@01c2a400 {
-                       compatible = "allwinner,sun4i-a10-ps2";
-                       reg = <0x01c2a400 0x400>;
-                       interrupts = <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&apb1_gates 7>;
-                       status = "disabled";
-               };
        };
 };
index 8a3ed21cb7bcfcf4785784bcb66d10aafd2081e7..a8b978d0f35b5f68b6621fa5e4ac71c3e3395dce 100644 (file)
@@ -47,7 +47,6 @@
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 
 #include <dt-bindings/clock/sun8i-a23-a33-ccu.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 #include <dt-bindings/reset/sun8i-a23-a33-ccu.h>
 
 / {
                        clocks = <&ccu CLK_BUS_GPU>, <&ccu CLK_GPU>;
                        clock-names = "bus", "core";
                        resets = <&ccu RST_BUS_GPU>;
+                       #cooling-cells = <2>;
 
                        assigned-clocks = <&ccu CLK_GPU>;
                        assigned-clock-rates = <384000000>;
index c21f5b1b255e27d33b932988ec426bf9032e57f7..87289a60c52021e3ef017d8cbf60ba223d1a7197 100644 (file)
@@ -48,7 +48,6 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Allwinner A23 Evaluation Board";
index 3ab5c0c09d93920aca5ba96be2e16e7f708c1740..b6958e8f2f01ad6a3f9ea49917da1246f9aa3cf8 100644 (file)
@@ -50,7 +50,6 @@
 };
 
 &codec {
-       pinctrl-0 = <&codec_pa_pin>;
        allwinner,pa-gpios = <&pio 7 9 GPIO_ACTIVE_HIGH>; /* PH9 */
        allwinner,audio-routing =
                "Headphone", "HP",
                "Headset Mic", "HBIAS";
        status = "okay";
 };
-
-&pio {
-       codec_pa_pin: codec_pa_pin@0 {
-               allwinner,pins = "PH9";
-               allwinner,function = "gpio_out";
-               allwinner,drive = <SUN4I_PINCTRL_10_MA>;
-               allwinner,pull = <SUN4I_PINCTRL_NO_PULL>;
-       };
-};
index 03b89bdd55ba1e9d60487862df36536cfd8256c0..9b620cc1d5f1323d1abc0fb89cec00ae2f99704d 100644 (file)
@@ -48,7 +48,6 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Sinlinx SinA33";
        status = "okay";
 };
 
+&cpu0 {
+       cpu-supply = <&reg_dcdc3>;
+};
+
+&cpu0_opp_table {
+       opp@1104000000 {
+               opp-hz = /bits/ 64 <1104000000>;
+               opp-microvolt = <1320000>;
+               clock-latency-ns = <244144>; /* 8 32k periods */
+       };
+
+       opp@1200000000 {
+               opp-hz = /bits/ 64 <1200000000>;
+               opp-microvolt = <1320000>;
+               clock-latency-ns = <244144>; /* 8 32k periods */
+       };
+};
+
 &de {
        status = "okay";
 };
 
 #include "axp223.dtsi"
 
+&ac_power_supply {
+       status = "okay";
+};
+
 &reg_aldo1 {
        regulator-always-on;
        regulator-min-microvolt = <3000000>;
index 306af6cadf26033c6102b61c6a6d7693faba30fe..01397825937241221097dd47caef60459e857df3 100644 (file)
  */
 
 #include "sun8i-a23-a33.dtsi"
+#include <dt-bindings/thermal/thermal.h>
 
 / {
        cpu0_opp_table: opp_table0 {
                compatible = "operating-points-v2";
                opp-shared;
 
+               opp@120000000 {
+                       opp-hz = /bits/ 64 <120000000>;
+                       opp-microvolt = <1040000>;
+                       clock-latency-ns = <244144>; /* 8 32k periods */
+               };
+
+               opp@240000000 {
+                       opp-hz = /bits/ 64 <240000000>;
+                       opp-microvolt = <1040000>;
+                       clock-latency-ns = <244144>; /* 8 32k periods */
+               };
+
+               opp@312000000 {
+                       opp-hz = /bits/ 64 <312000000>;
+                       opp-microvolt = <1040000>;
+                       clock-latency-ns = <244144>; /* 8 32k periods */
+               };
+
+               opp@408000000 {
+                       opp-hz = /bits/ 64 <408000000>;
+                       opp-microvolt = <1040000>;
+                       clock-latency-ns = <244144>; /* 8 32k periods */
+               };
+
+               opp@480000000 {
+                       opp-hz = /bits/ 64 <480000000>;
+                       opp-microvolt = <1040000>;
+                       clock-latency-ns = <244144>; /* 8 32k periods */
+               };
+
+               opp@504000000 {
+                       opp-hz = /bits/ 64 <504000000>;
+                       opp-microvolt = <1040000>;
+                       clock-latency-ns = <244144>; /* 8 32k periods */
+               };
+
+               opp@600000000 {
+                       opp-hz = /bits/ 64 <600000000>;
+                       opp-microvolt = <1040000>;
+                       clock-latency-ns = <244144>; /* 8 32k periods */
+               };
+
                opp@648000000 {
                        opp-hz = /bits/ 64 <648000000>;
                        opp-microvolt = <1040000>;
                        clock-latency-ns = <244144>; /* 8 32k periods */
                };
 
+               opp@720000000 {
+                       opp-hz = /bits/ 64 <720000000>;
+                       opp-microvolt = <1100000>;
+                       clock-latency-ns = <244144>; /* 8 32k periods */
+               };
+
                opp@816000000 {
                        opp-hz = /bits/ 64 <816000000>;
                        opp-microvolt = <1100000>;
                        clock-latency-ns = <244144>; /* 8 32k periods */
                };
 
+               opp@912000000 {
+                       opp-hz = /bits/ 64 <912000000>;
+                       opp-microvolt = <1200000>;
+                       clock-latency-ns = <244144>; /* 8 32k periods */
+               };
+
                opp@1008000000 {
                        opp-hz = /bits/ 64 <1008000000>;
                        opp-microvolt = <1200000>;
                        clocks = <&ccu CLK_CPUX>;
                        clock-names = "cpu";
                        operating-points-v2 = <&cpu0_opp_table>;
+                       #cooling-cells = <2>;
                };
 
                cpu@1 {
                status = "disabled";
        };
 
+       iio-hwmon {
+               compatible = "iio-hwmon";
+               io-channels = <&ths>;
+       };
+
+       mali_opp_table: gpu-opp-table {
+               compatible = "operating-points-v2";
+
+               opp@144000000 {
+                       opp-hz = /bits/ 64 <144000000>;
+               };
+
+               opp@240000000 {
+                       opp-hz = /bits/ 64 <240000000>;
+               };
+
+               opp@384000000 {
+                       opp-hz = /bits/ 64 <384000000>;
+               };
+       };
+
        memory {
                reg = <0x40000000 0x80000000>;
        };
                        status = "disabled";
                };
 
+               ths: ths@01c25000 {
+                       compatible = "allwinner,sun8i-a33-ths";
+                       reg = <0x01c25000 0x100>;
+                       #thermal-sensor-cells = <0>;
+                       #io-channel-cells = <0>;
+               };
+
                fe0: display-frontend@01e00000 {
                        compatible = "allwinner,sun8i-a33-display-frontend";
                        reg = <0x01e00000 0x20000>;
                        };
                };
        };
+
+       thermal-zones {
+               cpu_thermal {
+                       /* milliseconds */
+                       polling-delay-passive = <250>;
+                       polling-delay = <1000>;
+                       thermal-sensors = <&ths>;
+
+                       cooling-maps {
+                               map0 {
+                                       trip = <&cpu_alert0>;
+                                       cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+                               };
+                               map1 {
+                                       trip = <&cpu_alert1>;
+                                       cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+                               };
+
+                               map2 {
+                                       trip = <&gpu_alert0>;
+                                       cooling-device = <&mali 1 THERMAL_NO_LIMIT>;
+                               };
+
+                               map3 {
+                                       trip = <&gpu_alert1>;
+                                       cooling-device = <&mali 2 THERMAL_NO_LIMIT>;
+                               };
+                       };
+
+                       trips {
+                               cpu_alert0: cpu_alert0 {
+                                       /* milliCelsius */
+                                       temperature = <75000>;
+                                       hysteresis = <2000>;
+                                       type = "passive";
+                               };
+
+                               gpu_alert0: gpu_alert0 {
+                                       /* milliCelsius */
+                                       temperature = <85000>;
+                                       hysteresis = <2000>;
+                                       type = "passive";
+                               };
+
+                               cpu_alert1: cpu_alert1 {
+                                       /* milliCelsius */
+                                       temperature = <90000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+
+                               gpu_alert1: gpu_alert1 {
+                                       /* milliCelsius */
+                                       temperature = <95000>;
+                                       hysteresis = <2000>;
+                                       type = "hot";
+                               };
+
+                               cpu_crit: cpu_crit {
+                                       /* milliCelsius */
+                                       temperature = <110000>;
+                                       hysteresis = <2000>;
+                                       type = "critical";
+                               };
+                       };
+               };
+       };
 };
 
 &ccu {
        compatible = "allwinner,sun8i-a33-ccu";
 };
 
+&mali {
+       operating-points-v2 = <&mali_opp_table>;
+};
+
 &pio {
        compatible = "allwinner,sun8i-a33-pinctrl";
        interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>,
index a789a7caf2170bb56620d2f39f8709ffa86e5ad0..0ec143773ee9bf8b79df021492a6b23605044a3e 100644 (file)
@@ -47,8 +47,6 @@
 
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 
-#include <dt-bindings/pinctrl/sun4i-a10.h>
-
 / {
        interrupt-parent = <&gic>;
 
index b7ca916d871d723df656f4891973ad9b315c50fc..9e8b082c134f61efede523a916b1e60e382e005c 100644 (file)
@@ -49,7 +49,6 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Xunlong Orange Pi Zero";
        };
 };
 
+&ehci0 {
+       status = "okay";
+};
+
 &ehci1 {
        status = "okay";
 };
        bias-pull-up;
 };
 
+&ohci0 {
+       status = "okay";
+};
+
 &ohci1 {
        status = "okay";
 };
        status = "disabled";
 };
 
+&usb_otg {
+       dr_mode = "peripheral";
+       status = "okay";
+};
+
 &usbphy {
-       /* USB VBUS is always on */
+       /*
+        * USB Type-A port VBUS is always on. However, MicroUSB VBUS can only
+        * power up the board; when it's used as OTG port, this VBUS is
+        * always off even if the board is powered via GPIO pins.
+        */
        status = "okay";
+       usb0_id_det-gpios = <&pio 6 12 GPIO_ACTIVE_HIGH>; /* PG12 */
 };
index c0c49dd4d3b268d88f6347a9ff0104d22bfd6093..52acbe111cade5aa6c81c71d079df731c9f03d8d 100644 (file)
@@ -46,7 +46,6 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Banana Pi BPI-M2-Plus";
index 25b225b7dfd650152c997b8d0b639eb471443ba9..e7fae65eb5d3dd88b478c4e4f81050c1790e5568 100644 (file)
@@ -46,7 +46,6 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Beelink X2";
        };
 };
 
+&mmc2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc2_8bit_pins>;
+       vmmc-supply = <&reg_vcc3v3>;
+       bus-width = <8>;
+       non-removable;
+       cap-mmc-hw-reset;
+       status = "okay";
+};
+
 &ohci1 {
        status = "okay";
 };
diff --git a/arch/arm/boot/dts/sun8i-h3-nanopi-neo-air.dts b/arch/arm/boot/dts/sun8i-h3-nanopi-neo-air.dts
new file mode 100644 (file)
index 0000000..03ff6f8
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2017 Jelle van der Waa <jelle@vdwaa.nl>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "sun8i-h3.dtsi"
+#include "sunxi-common-regulators.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+
+/ {
+       model = "FriendlyARM NanoPi NEO Air";
+       compatible = "friendlyarm,nanopi-neo-air", "allwinner,sun8i-h3";
+
+       aliases {
+               serial0 = &uart0;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               pwr {
+                       label = "nanopi:green:pwr";
+                       gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>; /* PL10 */
+                       default-state = "on";
+               };
+
+               status {
+                       label = "nanopi:blue:status";
+                       gpios = <&pio 0 10 GPIO_ACTIVE_HIGH>; /* PA10 */
+               };
+       };
+};
+
+&mmc0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
+       vmmc-supply = <&reg_vcc3v3>;
+       bus-width = <4>;
+       cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; /* PF6 */
+       cd-inverted;
+       status = "okay";
+};
+
+&uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_pins_a>;
+       status = "okay";
+};
+
+&usbphy {
+       /* USB VBUS is always on */
+       status = "okay";
+};
index 2216e68d1838b2615717f866314d717de161761f..c6decee41a275e4970cf0c538386314f449f914f 100644 (file)
@@ -47,7 +47,6 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        aliases {
index 047e9e1c609326b5a7338c1d50afe5ef35017a54..5b6d14555b7ccb8b537d35ea82a75d01b39e0833 100644 (file)
@@ -46,7 +46,6 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Xunlong Orange Pi 2";
index 22b99b407019b3bb09f8dc1fd623849728fa47f1..9b47a0def740c5ca43af9fd17503c3b2a28eb6c3 100644 (file)
@@ -46,7 +46,6 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Xunlong Orange Pi Lite";
index 34da853ee0372b6b284b72c371eb25c4a2ecb28e..5fea430e0eb1006120dd9b98dd904cdd7af14b67 100644 (file)
@@ -46,7 +46,6 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Xunlong Orange Pi One";
        };
 };
 
+&ehci0 {
+       status = "okay";
+};
+
 &ehci1 {
        status = "okay";
 };
        status = "okay";
 };
 
+&ohci0 {
+       status = "okay";
+};
+
 &ohci1 {
        status = "okay";
 };
        };
 };
 
+&reg_usb0_vbus {
+       gpio = <&r_pio 0 2 GPIO_ACTIVE_HIGH>; /* PL2 */
+       status = "okay";
+};
+
 &uart0 {
        pinctrl-names = "default";
        pinctrl-0 = <&uart0_pins_a>;
        status = "disabled";
 };
 
+&usb_otg {
+       dr_mode = "otg";
+       status = "okay";
+};
+
 &usbphy {
-       /* USB VBUS is always on */
+       /* USB Type-A port's VBUS is always on */
+       usb0_id_det-gpios = <&pio 6 12 GPIO_ACTIVE_HIGH>; /* PG12 */
+       usb0_vbus-supply = <&reg_usb0_vbus>;
        status = "okay";
 };
index d43978d3294e57c6cce1cb97b9d534d8c182e7e2..f148111c326d073674de51ca921ca97525bf28fd 100644 (file)
@@ -46,7 +46,6 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Xunlong Orange Pi PC";
index 27780b97c863e70c3abbbacf3cae7f95854da276..b36f9f423c39d9d872bbbf6dc745473906494a4f 100644 (file)
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#include "skeleton.dtsi"
-
-#include <dt-bindings/clock/sun8i-h3-ccu.h>
-#include <dt-bindings/interrupt-controller/arm-gic.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
-#include <dt-bindings/reset/sun8i-h3-ccu.h>
+#include "sunxi-h3-h5.dtsi"
 
 / {
-       interrupt-parent = <&gic>;
-
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
                             <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
                             <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
        };
+};
 
-       clocks {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               ranges;
-
-               osc24M: osc24M_clk {
-                       #clock-cells = <0>;
-                       compatible = "fixed-clock";
-                       clock-frequency = <24000000>;
-                       clock-output-names = "osc24M";
-               };
-
-               osc32k: osc32k_clk {
-                       #clock-cells = <0>;
-                       compatible = "fixed-clock";
-                       clock-frequency = <32768>;
-                       clock-output-names = "osc32k";
-               };
-
-               apb0: apb0_clk {
-                       compatible = "fixed-factor-clock";
-                       #clock-cells = <0>;
-                       clock-div = <1>;
-                       clock-mult = <1>;
-                       clocks = <&osc24M>;
-                       clock-output-names = "apb0";
-               };
-
-               apb0_gates: clk@01f01428 {
-                       compatible = "allwinner,sun8i-h3-apb0-gates-clk",
-                                    "allwinner,sun4i-a10-gates-clk";
-                       reg = <0x01f01428 0x4>;
-                       #clock-cells = <1>;
-                       clocks = <&apb0>;
-                       clock-indices = <0>, <1>;
-                       clock-output-names = "apb0_pio", "apb0_ir";
-               };
-
-               ir_clk: ir_clk@01f01454 {
-                       compatible = "allwinner,sun4i-a10-mod0-clk";
-                       reg = <0x01f01454 0x4>;
-                       #clock-cells = <0>;
-                       clocks = <&osc32k>, <&osc24M>;
-                       clock-output-names = "ir";
-               };
-       };
-
-       soc {
-               compatible = "simple-bus";
-               #address-cells = <1>;
-               #size-cells = <1>;
-               ranges;
-
-               dma: dma-controller@01c02000 {
-                       compatible = "allwinner,sun8i-h3-dma";
-                       reg = <0x01c02000 0x1000>;
-                       interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&ccu CLK_BUS_DMA>;
-                       resets = <&ccu RST_BUS_DMA>;
-                       #dma-cells = <1>;
-               };
-
-               mmc0: mmc@01c0f000 {
-                       compatible = "allwinner,sun7i-a20-mmc";
-                       reg = <0x01c0f000 0x1000>;
-                       clocks = <&ccu CLK_BUS_MMC0>,
-                                <&ccu CLK_MMC0>,
-                                <&ccu CLK_MMC0_OUTPUT>,
-                                <&ccu CLK_MMC0_SAMPLE>;
-                       clock-names = "ahb",
-                                     "mmc",
-                                     "output",
-                                     "sample";
-                       resets = <&ccu RST_BUS_MMC0>;
-                       reset-names = "ahb";
-                       interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
-                       status = "disabled";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-               };
-
-               mmc1: mmc@01c10000 {
-                       compatible = "allwinner,sun7i-a20-mmc";
-                       reg = <0x01c10000 0x1000>;
-                       clocks = <&ccu CLK_BUS_MMC1>,
-                                <&ccu CLK_MMC1>,
-                                <&ccu CLK_MMC1_OUTPUT>,
-                                <&ccu CLK_MMC1_SAMPLE>;
-                       clock-names = "ahb",
-                                     "mmc",
-                                     "output",
-                                     "sample";
-                       resets = <&ccu RST_BUS_MMC1>;
-                       reset-names = "ahb";
-                       interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
-                       status = "disabled";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-               };
-
-               mmc2: mmc@01c11000 {
-                       compatible = "allwinner,sun7i-a20-mmc";
-                       reg = <0x01c11000 0x1000>;
-                       clocks = <&ccu CLK_BUS_MMC2>,
-                                <&ccu CLK_MMC2>,
-                                <&ccu CLK_MMC2_OUTPUT>,
-                                <&ccu CLK_MMC2_SAMPLE>;
-                       clock-names = "ahb",
-                                     "mmc",
-                                     "output",
-                                     "sample";
-                       resets = <&ccu RST_BUS_MMC2>;
-                       reset-names = "ahb";
-                       interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
-                       status = "disabled";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-               };
-
-               usbphy: phy@01c19400 {
-                       compatible = "allwinner,sun8i-h3-usb-phy";
-                       reg = <0x01c19400 0x2c>,
-                             <0x01c1a800 0x4>,
-                             <0x01c1b800 0x4>,
-                             <0x01c1c800 0x4>,
-                             <0x01c1d800 0x4>;
-                       reg-names = "phy_ctrl",
-                                   "pmu0",
-                                   "pmu1",
-                                   "pmu2",
-                                   "pmu3";
-                       clocks = <&ccu CLK_USB_PHY0>,
-                                <&ccu CLK_USB_PHY1>,
-                                <&ccu CLK_USB_PHY2>,
-                                <&ccu CLK_USB_PHY3>;
-                       clock-names = "usb0_phy",
-                                     "usb1_phy",
-                                     "usb2_phy",
-                                     "usb3_phy";
-                       resets = <&ccu RST_USB_PHY0>,
-                                <&ccu RST_USB_PHY1>,
-                                <&ccu RST_USB_PHY2>,
-                                <&ccu RST_USB_PHY3>;
-                       reset-names = "usb0_reset",
-                                     "usb1_reset",
-                                     "usb2_reset",
-                                     "usb3_reset";
-                       status = "disabled";
-                       #phy-cells = <1>;
-               };
-
-               ehci1: usb@01c1b000 {
-                       compatible = "allwinner,sun8i-h3-ehci", "generic-ehci";
-                       reg = <0x01c1b000 0x100>;
-                       interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&ccu CLK_BUS_EHCI1>, <&ccu CLK_BUS_OHCI1>;
-                       resets = <&ccu RST_BUS_EHCI1>, <&ccu RST_BUS_OHCI1>;
-                       phys = <&usbphy 1>;
-                       phy-names = "usb";
-                       status = "disabled";
-               };
-
-               ohci1: usb@01c1b400 {
-                       compatible = "allwinner,sun8i-h3-ohci", "generic-ohci";
-                       reg = <0x01c1b400 0x100>;
-                       interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&ccu CLK_BUS_EHCI1>, <&ccu CLK_BUS_OHCI1>,
-                                <&ccu CLK_USB_OHCI1>;
-                       resets = <&ccu RST_BUS_EHCI1>, <&ccu RST_BUS_OHCI1>;
-                       phys = <&usbphy 1>;
-                       phy-names = "usb";
-                       status = "disabled";
-               };
-
-               ehci2: usb@01c1c000 {
-                       compatible = "allwinner,sun8i-h3-ehci", "generic-ehci";
-                       reg = <0x01c1c000 0x100>;
-                       interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&ccu CLK_BUS_EHCI2>, <&ccu CLK_BUS_OHCI2>;
-                       resets = <&ccu RST_BUS_EHCI2>, <&ccu RST_BUS_OHCI2>;
-                       phys = <&usbphy 2>;
-                       phy-names = "usb";
-                       status = "disabled";
-               };
-
-               ohci2: usb@01c1c400 {
-                       compatible = "allwinner,sun8i-h3-ohci", "generic-ohci";
-                       reg = <0x01c1c400 0x100>;
-                       interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&ccu CLK_BUS_EHCI2>, <&ccu CLK_BUS_OHCI2>,
-                                <&ccu CLK_USB_OHCI2>;
-                       resets = <&ccu RST_BUS_EHCI2>, <&ccu RST_BUS_OHCI2>;
-                       phys = <&usbphy 2>;
-                       phy-names = "usb";
-                       status = "disabled";
-               };
-
-               ehci3: usb@01c1d000 {
-                       compatible = "allwinner,sun8i-h3-ehci", "generic-ehci";
-                       reg = <0x01c1d000 0x100>;
-                       interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&ccu CLK_BUS_EHCI3>, <&ccu CLK_BUS_OHCI3>;
-                       resets = <&ccu RST_BUS_EHCI3>, <&ccu RST_BUS_OHCI3>;
-                       phys = <&usbphy 3>;
-                       phy-names = "usb";
-                       status = "disabled";
-               };
-
-               ohci3: usb@01c1d400 {
-                       compatible = "allwinner,sun8i-h3-ohci", "generic-ohci";
-                       reg = <0x01c1d400 0x100>;
-                       interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&ccu CLK_BUS_EHCI3>, <&ccu CLK_BUS_OHCI3>,
-                                <&ccu CLK_USB_OHCI3>;
-                       resets = <&ccu RST_BUS_EHCI3>, <&ccu RST_BUS_OHCI3>;
-                       phys = <&usbphy 3>;
-                       phy-names = "usb";
-                       status = "disabled";
-               };
-
-               ccu: clock@01c20000 {
-                       compatible = "allwinner,sun8i-h3-ccu";
-                       reg = <0x01c20000 0x400>;
-                       clocks = <&osc24M>, <&osc32k>;
-                       clock-names = "hosc", "losc";
-                       #clock-cells = <1>;
-                       #reset-cells = <1>;
-               };
-
-               pio: pinctrl@01c20800 {
-                       compatible = "allwinner,sun8i-h3-pinctrl";
-                       reg = <0x01c20800 0x400>;
-                       interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
-                                    <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&ccu CLK_BUS_PIO>, <&osc24M>, <&osc32k>;
-                       clock-names = "apb", "hosc", "losc";
-                       gpio-controller;
-                       #gpio-cells = <3>;
-                       interrupt-controller;
-                       #interrupt-cells = <3>;
-
-                       i2c0_pins: i2c0 {
-                               pins = "PA11", "PA12";
-                               function = "i2c0";
-                       };
-
-                       i2c1_pins: i2c1 {
-                               pins = "PA18", "PA19";
-                               function = "i2c1";
-                       };
-
-                       i2c2_pins: i2c2 {
-                               pins = "PE12", "PE13";
-                               function = "i2c2";
-                       };
-
-                       mmc0_pins_a: mmc0@0 {
-                               pins = "PF0", "PF1", "PF2", "PF3",
-                                      "PF4", "PF5";
-                               function = "mmc0";
-                               drive-strength = <30>;
-                               bias-pull-up;
-                       };
-
-                       mmc0_cd_pin: mmc0_cd_pin@0 {
-                               pins = "PF6";
-                               function = "gpio_in";
-                               bias-pull-up;
-                       };
-
-                       mmc1_pins_a: mmc1@0 {
-                               pins = "PG0", "PG1", "PG2", "PG3",
-                                      "PG4", "PG5";
-                               function = "mmc1";
-                               drive-strength = <30>;
-                               bias-pull-up;
-                       };
-
-                       mmc2_8bit_pins: mmc2_8bit {
-                               pins = "PC5", "PC6", "PC8",
-                                      "PC9", "PC10", "PC11",
-                                      "PC12", "PC13", "PC14",
-                                      "PC15", "PC16";
-                               function = "mmc2";
-                               drive-strength = <30>;
-                               bias-pull-up;
-                       };
-
-                       spdif_tx_pins_a: spdif@0 {
-                               pins = "PA17";
-                               function = "spdif";
-                       };
-
-                       spi0_pins: spi0 {
-                               pins = "PC0", "PC1", "PC2", "PC3";
-                               function = "spi0";
-                       };
-
-                       spi1_pins: spi1 {
-                               pins = "PA15", "PA16", "PA14", "PA13";
-                               function = "spi1";
-                       };
-
-                       uart0_pins_a: uart0@0 {
-                               pins = "PA4", "PA5";
-                               function = "uart0";
-                       };
-
-                       uart1_pins: uart1 {
-                               pins = "PG6", "PG7";
-                               function = "uart1";
-                       };
-
-                       uart1_rts_cts_pins: uart1_rts_cts {
-                               pins = "PG8", "PG9";
-                               function = "uart1";
-                       };
-
-                       uart2_pins: uart2 {
-                               pins = "PA0", "PA1";
-                               function = "uart2";
-                       };
-
-                       uart3_pins: uart3 {
-                               pins = "PA13", "PA14";
-                               function = "uart3";
-                       };
-               };
-
-               timer@01c20c00 {
-                       compatible = "allwinner,sun4i-a10-timer";
-                       reg = <0x01c20c00 0xa0>;
-                       interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
-                                    <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&osc24M>;
-               };
-
-               spi0: spi@01c68000 {
-                       compatible = "allwinner,sun8i-h3-spi";
-                       reg = <0x01c68000 0x1000>;
-                       interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&ccu CLK_BUS_SPI0>, <&ccu CLK_SPI0>;
-                       clock-names = "ahb", "mod";
-                       dmas = <&dma 23>, <&dma 23>;
-                       dma-names = "rx", "tx";
-                       pinctrl-names = "default";
-                       pinctrl-0 = <&spi0_pins>;
-                       resets = <&ccu RST_BUS_SPI0>;
-                       status = "disabled";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-               };
-
-               spi1: spi@01c69000 {
-                       compatible = "allwinner,sun8i-h3-spi";
-                       reg = <0x01c69000 0x1000>;
-                       interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&ccu CLK_BUS_SPI1>, <&ccu CLK_SPI1>;
-                       clock-names = "ahb", "mod";
-                       dmas = <&dma 24>, <&dma 24>;
-                       dma-names = "rx", "tx";
-                       pinctrl-names = "default";
-                       pinctrl-0 = <&spi1_pins>;
-                       resets = <&ccu RST_BUS_SPI1>;
-                       status = "disabled";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-               };
-
-               wdt0: watchdog@01c20ca0 {
-                       compatible = "allwinner,sun6i-a31-wdt";
-                       reg = <0x01c20ca0 0x20>;
-                       interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
-               };
-
-               spdif: spdif@01c21000 {
-                       #sound-dai-cells = <0>;
-                       compatible = "allwinner,sun8i-h3-spdif";
-                       reg = <0x01c21000 0x400>;
-                       interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&ccu CLK_BUS_SPDIF>, <&ccu CLK_SPDIF>;
-                       resets = <&ccu RST_BUS_SPDIF>;
-                       clock-names = "apb", "spdif";
-                       dmas = <&dma 2>;
-                       dma-names = "tx";
-                       status = "disabled";
-               };
-
-               pwm: pwm@01c21400 {
-                       compatible = "allwinner,sun8i-h3-pwm";
-                       reg = <0x01c21400 0x8>;
-                       clocks = <&osc24M>;
-                       #pwm-cells = <3>;
-                       status = "disabled";
-               };
-
-               codec: codec@01c22c00 {
-                       #sound-dai-cells = <0>;
-                       compatible = "allwinner,sun8i-h3-codec";
-                       reg = <0x01c22c00 0x400>;
-                       interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&ccu CLK_BUS_CODEC>, <&ccu CLK_AC_DIG>;
-                       clock-names = "apb", "codec";
-                       resets = <&ccu RST_BUS_CODEC>;
-                       dmas = <&dma 15>, <&dma 15>;
-                       dma-names = "rx", "tx";
-                       allwinner,codec-analog-controls = <&codec_analog>;
-                       status = "disabled";
-               };
-
-               uart0: serial@01c28000 {
-                       compatible = "snps,dw-apb-uart";
-                       reg = <0x01c28000 0x400>;
-                       interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
-                       reg-shift = <2>;
-                       reg-io-width = <4>;
-                       clocks = <&ccu CLK_BUS_UART0>;
-                       resets = <&ccu RST_BUS_UART0>;
-                       dmas = <&dma 6>, <&dma 6>;
-                       dma-names = "rx", "tx";
-                       status = "disabled";
-               };
-
-               uart1: serial@01c28400 {
-                       compatible = "snps,dw-apb-uart";
-                       reg = <0x01c28400 0x400>;
-                       interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
-                       reg-shift = <2>;
-                       reg-io-width = <4>;
-                       clocks = <&ccu CLK_BUS_UART1>;
-                       resets = <&ccu RST_BUS_UART1>;
-                       dmas = <&dma 7>, <&dma 7>;
-                       dma-names = "rx", "tx";
-                       status = "disabled";
-               };
-
-               uart2: serial@01c28800 {
-                       compatible = "snps,dw-apb-uart";
-                       reg = <0x01c28800 0x400>;
-                       interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
-                       reg-shift = <2>;
-                       reg-io-width = <4>;
-                       clocks = <&ccu CLK_BUS_UART2>;
-                       resets = <&ccu RST_BUS_UART2>;
-                       dmas = <&dma 8>, <&dma 8>;
-                       dma-names = "rx", "tx";
-                       status = "disabled";
-               };
-
-               uart3: serial@01c28c00 {
-                       compatible = "snps,dw-apb-uart";
-                       reg = <0x01c28c00 0x400>;
-                       interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
-                       reg-shift = <2>;
-                       reg-io-width = <4>;
-                       clocks = <&ccu CLK_BUS_UART3>;
-                       resets = <&ccu RST_BUS_UART3>;
-                       dmas = <&dma 9>, <&dma 9>;
-                       dma-names = "rx", "tx";
-                       status = "disabled";
-               };
-
-               i2c0: i2c@01c2ac00 {
-                       compatible = "allwinner,sun6i-a31-i2c";
-                       reg = <0x01c2ac00 0x400>;
-                       interrupts = <GIC_SPI 6 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@01c2b000 {
-                       compatible = "allwinner,sun6i-a31-i2c";
-                       reg = <0x01c2b000 0x400>;
-                       interrupts = <GIC_SPI 7 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@01c2b400 {
-                       compatible = "allwinner,sun6i-a31-i2c";
-                       reg = <0x01c2b000 0x400>;
-                       interrupts = <GIC_SPI 8 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>;
-               };
-
-               gic: interrupt-controller@01c81000 {
-                       compatible = "arm,cortex-a7-gic", "arm,cortex-a15-gic";
-                       reg = <0x01c81000 0x1000>,
-                             <0x01c82000 0x2000>,
-                             <0x01c84000 0x2000>,
-                             <0x01c86000 0x2000>;
-                       interrupt-controller;
-                       #interrupt-cells = <3>;
-                       interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
-               };
-
-               rtc: rtc@01f00000 {
-                       compatible = "allwinner,sun6i-a31-rtc";
-                       reg = <0x01f00000 0x54>;
-                       interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
-                                    <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
-               };
-
-               apb0_reset: reset@01f014b0 {
-                       reg = <0x01f014b0 0x4>;
-                       compatible = "allwinner,sun6i-a31-clock-reset";
-                       #reset-cells = <1>;
-               };
+&ccu {
+       compatible = "allwinner,sun8i-h3-ccu";
+};
 
-               codec_analog: codec-analog@01f015c0 {
-                       compatible = "allwinner,sun8i-h3-codec-analog";
-                       reg = <0x01f015c0 0x4>;
-               };
+&mmc0 {
+       compatible = "allwinner,sun7i-a20-mmc";
+       clocks = <&ccu CLK_BUS_MMC0>,
+                <&ccu CLK_MMC0>,
+                <&ccu CLK_MMC0_OUTPUT>,
+                <&ccu CLK_MMC0_SAMPLE>;
+       clock-names = "ahb",
+                     "mmc",
+                     "output",
+                     "sample";
+};
 
-               ir: ir@01f02000 {
-                       compatible = "allwinner,sun5i-a13-ir";
-                       clocks = <&apb0_gates 1>, <&ir_clk>;
-                       clock-names = "apb", "ir";
-                       resets = <&apb0_reset 1>;
-                       interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
-                       reg = <0x01f02000 0x40>;
-                       status = "disabled";
-               };
+&mmc1 {
+       compatible = "allwinner,sun7i-a20-mmc";
+       clocks = <&ccu CLK_BUS_MMC1>,
+                <&ccu CLK_MMC1>,
+                <&ccu CLK_MMC1_OUTPUT>,
+                <&ccu CLK_MMC1_SAMPLE>;
+       clock-names = "ahb",
+                     "mmc",
+                     "output",
+                     "sample";
+};
 
-               r_pio: pinctrl@01f02c00 {
-                       compatible = "allwinner,sun8i-h3-r-pinctrl";
-                       reg = <0x01f02c00 0x400>;
-                       interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
-                       clocks = <&apb0_gates 0>, <&osc24M>, <&osc32k>;
-                       clock-names = "apb", "hosc", "losc";
-                       resets = <&apb0_reset 0>;
-                       gpio-controller;
-                       #gpio-cells = <3>;
-                       interrupt-controller;
-                       #interrupt-cells = <3>;
+&mmc2 {
+       compatible = "allwinner,sun7i-a20-mmc";
+       clocks = <&ccu CLK_BUS_MMC2>,
+                <&ccu CLK_MMC2>,
+                <&ccu CLK_MMC2_OUTPUT>,
+                <&ccu CLK_MMC2_SAMPLE>;
+       clock-names = "ahb",
+                     "mmc",
+                     "output",
+                     "sample";
+};
 
-                       ir_pins_a: ir@0 {
-                               pins = "PL11";
-                               function = "s_cir_rx";
-                       };
-               };
-       };
+&pio {
+       compatible = "allwinner,sun8i-h3-pinctrl";
 };
index 9112a200fd5e5d79d8f44104099b0fdfee6530d6..3741ac71c3d62588b507199b425a44987df52397 100644 (file)
@@ -47,7 +47,6 @@
 #include "sun9i-a80.dtsi"
 
 #include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Cubietech Cubieboard4";
index 0fc3a87f5576146dd21cfae48d4e92f6a1fa3831..85f1ad6703109ff736854532b7242d32281c000a 100644 (file)
@@ -46,7 +46,6 @@
 #include "sun9i-a80.dtsi"
 
 #include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 / {
        model = "Merrii A80 Optimus Board";
index 15b6d122f878ba7f29ec96e8d555fcc2687141fd..759a72317eb8f0b2c98156deadaf6773f4c9cb7e 100644 (file)
@@ -46,8 +46,6 @@
 
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 
-#include <dt-bindings/pinctrl/sun4i-a10.h>
-
 #include <dt-bindings/clock/sun9i-a80-ccu.h>
 #include <dt-bindings/clock/sun9i-a80-de.h>
 #include <dt-bindings/clock/sun9i-a80-usb.h>
index 17c09fed9e84d2b38490c7627b4ef938b135ddc6..ce5c53e4452fcda1357f045783d7ee0a9b343d74 100644 (file)
@@ -43,7 +43,6 @@
  */
 
 #include <dt-bindings/gpio/gpio.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 
 &pio {
        ahci_pwr_pin_a: ahci_pwr_pin@0 {
diff --git a/arch/arm/boot/dts/sunxi-h3-h5.dtsi b/arch/arm/boot/dts/sunxi-h3-h5.dtsi
new file mode 100644 (file)
index 0000000..1aeeacb
--- /dev/null
@@ -0,0 +1,601 @@
+/*
+ * Copyright (C) 2015 Jens Kuske <jenskuske@gmail.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <dt-bindings/clock/sun8i-h3-ccu.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/reset/sun8i-h3-ccu.h>
+
+/ {
+       interrupt-parent = <&gic>;
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       clocks {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               osc24M: osc24M_clk {
+                       #clock-cells = <0>;
+                       compatible = "fixed-clock";
+                       clock-frequency = <24000000>;
+                       clock-output-names = "osc24M";
+               };
+
+               osc32k: osc32k_clk {
+                       #clock-cells = <0>;
+                       compatible = "fixed-clock";
+                       clock-frequency = <32768>;
+                       clock-output-names = "osc32k";
+               };
+
+               iosc: internal-osc-clk {
+                       #clock-cells = <0>;
+                       compatible = "fixed-clock";
+                       clock-frequency = <16000000>;
+                       clock-accuracy = <300000000>;
+                       clock-output-names = "iosc";
+               };
+       };
+
+       soc {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges;
+
+               dma: dma-controller@01c02000 {
+                       compatible = "allwinner,sun8i-h3-dma";
+                       reg = <0x01c02000 0x1000>;
+                       interrupts = <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&ccu CLK_BUS_DMA>;
+                       resets = <&ccu RST_BUS_DMA>;
+                       #dma-cells = <1>;
+               };
+
+               mmc0: mmc@01c0f000 {
+                       /* compatible and clocks are in per SoC .dtsi file */
+                       reg = <0x01c0f000 0x1000>;
+                       resets = <&ccu RST_BUS_MMC0>;
+                       reset-names = "ahb";
+                       interrupts = <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>;
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               mmc1: mmc@01c10000 {
+                       /* compatible and clocks are in per SoC .dtsi file */
+                       reg = <0x01c10000 0x1000>;
+                       resets = <&ccu RST_BUS_MMC1>;
+                       reset-names = "ahb";
+                       interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               mmc2: mmc@01c11000 {
+                       /* compatible and clocks are in per SoC .dtsi file */
+                       reg = <0x01c11000 0x1000>;
+                       resets = <&ccu RST_BUS_MMC2>;
+                       reset-names = "ahb";
+                       interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               usb_otg: usb@01c19000 {
+                       compatible = "allwinner,sun8i-h3-musb";
+                       reg = <0x01c19000 0x400>;
+                       clocks = <&ccu CLK_BUS_OTG>;
+                       resets = <&ccu RST_BUS_OTG>;
+                       interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupt-names = "mc";
+                       phys = <&usbphy 0>;
+                       phy-names = "usb";
+                       extcon = <&usbphy 0>;
+                       status = "disabled";
+               };
+
+               usbphy: phy@01c19400 {
+                       compatible = "allwinner,sun8i-h3-usb-phy";
+                       reg = <0x01c19400 0x2c>,
+                             <0x01c1a800 0x4>,
+                             <0x01c1b800 0x4>,
+                             <0x01c1c800 0x4>,
+                             <0x01c1d800 0x4>;
+                       reg-names = "phy_ctrl",
+                                   "pmu0",
+                                   "pmu1",
+                                   "pmu2",
+                                   "pmu3";
+                       clocks = <&ccu CLK_USB_PHY0>,
+                                <&ccu CLK_USB_PHY1>,
+                                <&ccu CLK_USB_PHY2>,
+                                <&ccu CLK_USB_PHY3>;
+                       clock-names = "usb0_phy",
+                                     "usb1_phy",
+                                     "usb2_phy",
+                                     "usb3_phy";
+                       resets = <&ccu RST_USB_PHY0>,
+                                <&ccu RST_USB_PHY1>,
+                                <&ccu RST_USB_PHY2>,
+                                <&ccu RST_USB_PHY3>;
+                       reset-names = "usb0_reset",
+                                     "usb1_reset",
+                                     "usb2_reset",
+                                     "usb3_reset";
+                       status = "disabled";
+                       #phy-cells = <1>;
+               };
+
+               ehci0: usb@01c1a000 {
+                       compatible = "allwinner,sun8i-h3-ehci", "generic-ehci";
+                       reg = <0x01c1a000 0x100>;
+                       interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&ccu CLK_BUS_EHCI0>, <&ccu CLK_BUS_OHCI0>;
+                       resets = <&ccu RST_BUS_EHCI0>, <&ccu RST_BUS_OHCI0>;
+                       status = "disabled";
+               };
+
+               ohci0: usb@01c1a400 {
+                       compatible = "allwinner,sun8i-h3-ohci", "generic-ohci";
+                       reg = <0x01c1a400 0x100>;
+                       interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&ccu CLK_BUS_EHCI0>, <&ccu CLK_BUS_OHCI0>,
+                                <&ccu CLK_USB_OHCI0>;
+                       resets = <&ccu RST_BUS_EHCI0>, <&ccu RST_BUS_OHCI0>;
+                       status = "disabled";
+               };
+
+               ehci1: usb@01c1b000 {
+                       compatible = "allwinner,sun8i-h3-ehci", "generic-ehci";
+                       reg = <0x01c1b000 0x100>;
+                       interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&ccu CLK_BUS_EHCI1>, <&ccu CLK_BUS_OHCI1>;
+                       resets = <&ccu RST_BUS_EHCI1>, <&ccu RST_BUS_OHCI1>;
+                       phys = <&usbphy 1>;
+                       phy-names = "usb";
+                       status = "disabled";
+               };
+
+               ohci1: usb@01c1b400 {
+                       compatible = "allwinner,sun8i-h3-ohci", "generic-ohci";
+                       reg = <0x01c1b400 0x100>;
+                       interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&ccu CLK_BUS_EHCI1>, <&ccu CLK_BUS_OHCI1>,
+                                <&ccu CLK_USB_OHCI1>;
+                       resets = <&ccu RST_BUS_EHCI1>, <&ccu RST_BUS_OHCI1>;
+                       phys = <&usbphy 1>;
+                       phy-names = "usb";
+                       status = "disabled";
+               };
+
+               ehci2: usb@01c1c000 {
+                       compatible = "allwinner,sun8i-h3-ehci", "generic-ehci";
+                       reg = <0x01c1c000 0x100>;
+                       interrupts = <GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&ccu CLK_BUS_EHCI2>, <&ccu CLK_BUS_OHCI2>;
+                       resets = <&ccu RST_BUS_EHCI2>, <&ccu RST_BUS_OHCI2>;
+                       phys = <&usbphy 2>;
+                       phy-names = "usb";
+                       status = "disabled";
+               };
+
+               ohci2: usb@01c1c400 {
+                       compatible = "allwinner,sun8i-h3-ohci", "generic-ohci";
+                       reg = <0x01c1c400 0x100>;
+                       interrupts = <GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&ccu CLK_BUS_EHCI2>, <&ccu CLK_BUS_OHCI2>,
+                                <&ccu CLK_USB_OHCI2>;
+                       resets = <&ccu RST_BUS_EHCI2>, <&ccu RST_BUS_OHCI2>;
+                       phys = <&usbphy 2>;
+                       phy-names = "usb";
+                       status = "disabled";
+               };
+
+               ehci3: usb@01c1d000 {
+                       compatible = "allwinner,sun8i-h3-ehci", "generic-ehci";
+                       reg = <0x01c1d000 0x100>;
+                       interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&ccu CLK_BUS_EHCI3>, <&ccu CLK_BUS_OHCI3>;
+                       resets = <&ccu RST_BUS_EHCI3>, <&ccu RST_BUS_OHCI3>;
+                       phys = <&usbphy 3>;
+                       phy-names = "usb";
+                       status = "disabled";
+               };
+
+               ohci3: usb@01c1d400 {
+                       compatible = "allwinner,sun8i-h3-ohci", "generic-ohci";
+                       reg = <0x01c1d400 0x100>;
+                       interrupts = <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&ccu CLK_BUS_EHCI3>, <&ccu CLK_BUS_OHCI3>,
+                                <&ccu CLK_USB_OHCI3>;
+                       resets = <&ccu RST_BUS_EHCI3>, <&ccu RST_BUS_OHCI3>;
+                       phys = <&usbphy 3>;
+                       phy-names = "usb";
+                       status = "disabled";
+               };
+
+               ccu: clock@01c20000 {
+                       /* compatible is in per SoC .dtsi file */
+                       reg = <0x01c20000 0x400>;
+                       clocks = <&osc24M>, <&osc32k>;
+                       clock-names = "hosc", "losc";
+                       #clock-cells = <1>;
+                       #reset-cells = <1>;
+               };
+
+               pio: pinctrl@01c20800 {
+                       /* compatible is in per SoC .dtsi file */
+                       reg = <0x01c20800 0x400>;
+                       interrupts = <GIC_SPI 11 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&ccu CLK_BUS_PIO>, <&osc24M>, <&osc32k>;
+                       clock-names = "apb", "hosc", "losc";
+                       gpio-controller;
+                       #gpio-cells = <3>;
+                       interrupt-controller;
+                       #interrupt-cells = <3>;
+
+                       i2c0_pins: i2c0 {
+                               pins = "PA11", "PA12";
+                               function = "i2c0";
+                       };
+
+                       i2c1_pins: i2c1 {
+                               pins = "PA18", "PA19";
+                               function = "i2c1";
+                       };
+
+                       i2c2_pins: i2c2 {
+                               pins = "PE12", "PE13";
+                               function = "i2c2";
+                       };
+
+                       mmc0_pins_a: mmc0@0 {
+                               pins = "PF0", "PF1", "PF2", "PF3",
+                                      "PF4", "PF5";
+                               function = "mmc0";
+                               drive-strength = <30>;
+                               bias-pull-up;
+                       };
+
+                       mmc0_cd_pin: mmc0_cd_pin@0 {
+                               pins = "PF6";
+                               function = "gpio_in";
+                               bias-pull-up;
+                       };
+
+                       mmc1_pins_a: mmc1@0 {
+                               pins = "PG0", "PG1", "PG2", "PG3",
+                                      "PG4", "PG5";
+                               function = "mmc1";
+                               drive-strength = <30>;
+                               bias-pull-up;
+                       };
+
+                       mmc2_8bit_pins: mmc2_8bit {
+                               pins = "PC5", "PC6", "PC8",
+                                      "PC9", "PC10", "PC11",
+                                      "PC12", "PC13", "PC14",
+                                      "PC15", "PC16";
+                               function = "mmc2";
+                               drive-strength = <30>;
+                               bias-pull-up;
+                       };
+
+                       spdif_tx_pins_a: spdif@0 {
+                               pins = "PA17";
+                               function = "spdif";
+                       };
+
+                       spi0_pins: spi0 {
+                               pins = "PC0", "PC1", "PC2", "PC3";
+                               function = "spi0";
+                       };
+
+                       spi1_pins: spi1 {
+                               pins = "PA15", "PA16", "PA14", "PA13";
+                               function = "spi1";
+                       };
+
+                       uart0_pins_a: uart0@0 {
+                               pins = "PA4", "PA5";
+                               function = "uart0";
+                       };
+
+                       uart1_pins: uart1 {
+                               pins = "PG6", "PG7";
+                               function = "uart1";
+                       };
+
+                       uart1_rts_cts_pins: uart1_rts_cts {
+                               pins = "PG8", "PG9";
+                               function = "uart1";
+                       };
+
+                       uart2_pins: uart2 {
+                               pins = "PA0", "PA1";
+                               function = "uart2";
+                       };
+
+                       uart3_pins: uart3 {
+                               pins = "PA13", "PA14";
+                               function = "uart3";
+                       };
+               };
+
+               timer@01c20c00 {
+                       compatible = "allwinner,sun4i-a10-timer";
+                       reg = <0x01c20c00 0xa0>;
+                       interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&osc24M>;
+               };
+
+               spi0: spi@01c68000 {
+                       compatible = "allwinner,sun8i-h3-spi";
+                       reg = <0x01c68000 0x1000>;
+                       interrupts = <GIC_SPI 65 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&ccu CLK_BUS_SPI0>, <&ccu CLK_SPI0>;
+                       clock-names = "ahb", "mod";
+                       dmas = <&dma 23>, <&dma 23>;
+                       dma-names = "rx", "tx";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&spi0_pins>;
+                       resets = <&ccu RST_BUS_SPI0>;
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               spi1: spi@01c69000 {
+                       compatible = "allwinner,sun8i-h3-spi";
+                       reg = <0x01c69000 0x1000>;
+                       interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&ccu CLK_BUS_SPI1>, <&ccu CLK_SPI1>;
+                       clock-names = "ahb", "mod";
+                       dmas = <&dma 24>, <&dma 24>;
+                       dma-names = "rx", "tx";
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&spi1_pins>;
+                       resets = <&ccu RST_BUS_SPI1>;
+                       status = "disabled";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               wdt0: watchdog@01c20ca0 {
+                       compatible = "allwinner,sun6i-a31-wdt";
+                       reg = <0x01c20ca0 0x20>;
+                       interrupts = <GIC_SPI 25 IRQ_TYPE_LEVEL_HIGH>;
+               };
+
+               spdif: spdif@01c21000 {
+                       #sound-dai-cells = <0>;
+                       compatible = "allwinner,sun8i-h3-spdif";
+                       reg = <0x01c21000 0x400>;
+                       interrupts = <GIC_SPI 12 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&ccu CLK_BUS_SPDIF>, <&ccu CLK_SPDIF>;
+                       resets = <&ccu RST_BUS_SPDIF>;
+                       clock-names = "apb", "spdif";
+                       dmas = <&dma 2>;
+                       dma-names = "tx";
+                       status = "disabled";
+               };
+
+               pwm: pwm@01c21400 {
+                       compatible = "allwinner,sun8i-h3-pwm";
+                       reg = <0x01c21400 0x8>;
+                       clocks = <&osc24M>;
+                       #pwm-cells = <3>;
+                       status = "disabled";
+               };
+
+               codec: codec@01c22c00 {
+                       #sound-dai-cells = <0>;
+                       compatible = "allwinner,sun8i-h3-codec";
+                       reg = <0x01c22c00 0x400>;
+                       interrupts = <GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&ccu CLK_BUS_CODEC>, <&ccu CLK_AC_DIG>;
+                       clock-names = "apb", "codec";
+                       resets = <&ccu RST_BUS_CODEC>;
+                       dmas = <&dma 15>, <&dma 15>;
+                       dma-names = "rx", "tx";
+                       allwinner,codec-analog-controls = <&codec_analog>;
+                       status = "disabled";
+               };
+
+               uart0: serial@01c28000 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x01c28000 0x400>;
+                       interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       clocks = <&ccu CLK_BUS_UART0>;
+                       resets = <&ccu RST_BUS_UART0>;
+                       dmas = <&dma 6>, <&dma 6>;
+                       dma-names = "rx", "tx";
+                       status = "disabled";
+               };
+
+               uart1: serial@01c28400 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x01c28400 0x400>;
+                       interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       clocks = <&ccu CLK_BUS_UART1>;
+                       resets = <&ccu RST_BUS_UART1>;
+                       dmas = <&dma 7>, <&dma 7>;
+                       dma-names = "rx", "tx";
+                       status = "disabled";
+               };
+
+               uart2: serial@01c28800 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x01c28800 0x400>;
+                       interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       clocks = <&ccu CLK_BUS_UART2>;
+                       resets = <&ccu RST_BUS_UART2>;
+                       dmas = <&dma 8>, <&dma 8>;
+                       dma-names = "rx", "tx";
+                       status = "disabled";
+               };
+
+               uart3: serial@01c28c00 {
+                       compatible = "snps,dw-apb-uart";
+                       reg = <0x01c28c00 0x400>;
+                       interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+                       reg-shift = <2>;
+                       reg-io-width = <4>;
+                       clocks = <&ccu CLK_BUS_UART3>;
+                       resets = <&ccu RST_BUS_UART3>;
+                       dmas = <&dma 9>, <&dma 9>;
+                       dma-names = "rx", "tx";
+                       status = "disabled";
+               };
+
+               i2c0: i2c@01c2ac00 {
+                       compatible = "allwinner,sun6i-a31-i2c";
+                       reg = <0x01c2ac00 0x400>;
+                       interrupts = <GIC_SPI 6 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@01c2b000 {
+                       compatible = "allwinner,sun6i-a31-i2c";
+                       reg = <0x01c2b000 0x400>;
+                       interrupts = <GIC_SPI 7 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@01c2b400 {
+                       compatible = "allwinner,sun6i-a31-i2c";
+                       reg = <0x01c2b000 0x400>;
+                       interrupts = <GIC_SPI 8 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>;
+               };
+
+               gic: interrupt-controller@01c81000 {
+                       compatible = "arm,gic-400";
+                       reg = <0x01c81000 0x1000>,
+                             <0x01c82000 0x2000>,
+                             <0x01c84000 0x2000>,
+                             <0x01c86000 0x2000>;
+                       interrupt-controller;
+                       #interrupt-cells = <3>;
+                       interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+               };
+
+               rtc: rtc@01f00000 {
+                       compatible = "allwinner,sun6i-a31-rtc";
+                       reg = <0x01f00000 0x54>;
+                       interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+               };
+
+               r_ccu: clock@1f01400 {
+                       compatible = "allwinner,sun50i-a64-r-ccu";
+                       reg = <0x01f01400 0x100>;
+                       clocks = <&osc24M>, <&osc32k>, <&iosc>;
+                       clock-names = "hosc", "losc", "iosc";
+                       #clock-cells = <1>;
+                       #reset-cells = <1>;
+               };
+
+               codec_analog: codec-analog@01f015c0 {
+                       compatible = "allwinner,sun8i-h3-codec-analog";
+                       reg = <0x01f015c0 0x4>;
+               };
+
+               ir: ir@01f02000 {
+                       compatible = "allwinner,sun5i-a13-ir";
+                       clocks = <&r_ccu 4>, <&r_ccu 11>;
+                       clock-names = "apb", "ir";
+                       resets = <&r_ccu 0>;
+                       interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+                       reg = <0x01f02000 0x40>;
+                       status = "disabled";
+               };
+
+               r_pio: pinctrl@01f02c00 {
+                       compatible = "allwinner,sun8i-h3-r-pinctrl";
+                       reg = <0x01f02c00 0x400>;
+                       interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&r_ccu 3>, <&osc24M>, <&osc32k>;
+                       clock-names = "apb", "hosc", "losc";
+                       gpio-controller;
+                       #gpio-cells = <3>;
+                       interrupt-controller;
+                       #interrupt-cells = <3>;
+
+                       ir_pins_a: ir@0 {
+                               pins = "PL11";
+                               function = "s_cir_rx";
+                       };
+               };
+       };
+};
index b8241462fcea56bc5b16955cc4418442b0d70a08..245d0bcde4415ff95061fff37afc92b87533d7f7 100644 (file)
@@ -42,7 +42,6 @@
 
 #include <dt-bindings/gpio/gpio.h>
 #include <dt-bindings/input/input.h>
-#include <dt-bindings/pinctrl/sun4i-a10.h>
 #include "sunxi-common-regulators.dtsi"
 
 &i2c0 {
index 110031bc0e7e39277a5ba896186c54a267a25de6..e0da4ee21c2105c1a92b44951ce7128bc1d7d3ab 100644 (file)
        model = "UniPhier LD4 Reference Board";
        compatible = "socionext,uniphier-ld4-ref", "socionext,uniphier-ld4";
 
-       memory {
-               device_type = "memory";
-               reg = <0x80000000 0x20000000>;
-       };
-
        chosen {
                stdout-path = "serial0:115200n8";
        };
                i2c2 = &i2c2;
                i2c3 = &i2c3;
        };
+
+       memory@80000000 {
+               device_type = "memory";
+               reg = <0x80000000 0x20000000>;
+       };
 };
 
 &ethsc {
index a7c494d7c43a92d66d32fdd950c25ed3d1a12210..4f5fe15eaee2dab859ba3ca66f44e1597c8aea79 100644 (file)
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
-/include/ "skeleton.dtsi"
-
 / {
        compatible = "socionext,uniphier-ld4";
+       #address-cells = <1>;
+       #size-cells = <1>;
 
        cpus {
                #address-cells = <1>;
index c05d631dcf02d12a6542d2af41cfde7b3ddb908e..a397a8811c7882c39556ae11513a7079b01f23a2 100644 (file)
        model = "UniPhier LD6b Reference Board";
        compatible = "socionext,uniphier-ld6b-ref", "socionext,uniphier-ld6b";
 
-       memory {
-               device_type = "memory";
-               reg = <0x80000000 0x80000000>;
-       };
-
        chosen {
                stdout-path = "serial0:115200n8";
        };
                i2c5 = &i2c5;
                i2c6 = &i2c6;
        };
+
+       memory@80000000 {
+               device_type = "memory";
+               reg = <0x80000000 0x80000000>;
+       };
 };
 
 &ethsc {
index 8ee79da9af7c33f6834b2b4542dea20b1ecc2e31..246f35ffb638119fc81c9e159afe870fb7e72a48 100644 (file)
@@ -45,7 +45,7 @@
 
 &pinctrl {
        pinctrl_emmc: emmc_grp {
-               groups = "emmc";
+               groups = "emmc", "emmc_dat8";
                function = "emmc";
        };
 
index 0ab0a40c041ea5022d9dd46796273b9f7afd3327..fefc89149234961b8c9dc441ca11629fe6395ef2 100644 (file)
        model = "UniPhier Pro4 Ace Board";
        compatible = "socionext,uniphier-pro4-ace", "socionext,uniphier-pro4";
 
-       memory {
-               device_type = "memory";
-               reg = <0x80000000 0x40000000>;
-       };
-
        chosen {
                stdout-path = "serial0:115200n8";
        };
                i2c5 = &i2c5;
                i2c6 = &i2c6;
        };
+
+       memory@80000000 {
+               device_type = "memory";
+               reg = <0x80000000 0x40000000>;
+       };
 };
 
 &serial0 {
@@ -90,6 +90,7 @@
        eeprom@54 {
                compatible = "st,24c64";
                reg = <0x54>;
+               pagesize = <32>;
        };
 };
 
index 9e92e60d25cea9c2cd00bcaf7a1603399b858281..6077e634d14aeb324db4154bfc8ae387e12ac541 100644 (file)
        model = "UniPhier Pro4 Reference Board";
        compatible = "socionext,uniphier-pro4-ref", "socionext,uniphier-pro4";
 
-       memory {
-               device_type = "memory";
-               reg = <0x80000000 0x40000000>;
-       };
-
        chosen {
                stdout-path = "serial0:115200n8";
        };
                i2c5 = &i2c5;
                i2c6 = &i2c6;
        };
+
+       memory@80000000 {
+               device_type = "memory";
+               reg = <0x80000000 0x40000000>;
+       };
 };
 
 &ethsc {
index dc4ea8832ce2f0111957855aecb4f9b6753c1b1c..6c63c8bad8254869417dd7d2c6529c7f6d1dfb45 100644 (file)
        model = "UniPhier Pro4 Sanji Board";
        compatible = "socionext,uniphier-pro4-sanji", "socionext,uniphier-pro4";
 
-       memory {
-               device_type = "memory";
-               reg = <0x80000000 0x80000000>;
-       };
-
        chosen {
                stdout-path = "serial0:115200n8";
        };
                i2c5 = &i2c5;
                i2c6 = &i2c6;
        };
+
+       memory@80000000 {
+               device_type = "memory";
+               reg = <0x80000000 0x80000000>;
+       };
 };
 
 &serial0 {
@@ -85,6 +85,7 @@
        eeprom@54 {
                compatible = "st,24c64";
                reg = <0x54>;
+               pagesize = <32>;
        };
 };
 
index e960b09ff01cd91a60df32aebafb81387bbc7286..794a85a7068b8adcecfe5c178804206bf39d94b9 100644 (file)
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
-/include/ "skeleton.dtsi"
-
 / {
        compatible = "socionext,uniphier-pro4";
+       #address-cells = <1>;
+       #size-cells = <1>;
 
        cpus {
                #address-cells = <1>;
index dbc5e53331630f302b1ef47d818d848f7f33b614..df07b555cbed819c9edeef74de89ad9e2c8e8bc2 100644 (file)
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
-/include/ "skeleton.dtsi"
-
 / {
        compatible = "socionext,uniphier-pro5";
+       #address-cells = <1>;
+       #size-cells = <1>;
 
        cpus {
                #address-cells = <1>;
index 373818ace0864a47e77528300625cbb5d13447f1..cccc86658d2027001d6ceb7f978ff513312135e0 100644 (file)
        compatible = "socionext,uniphier-pxs2-gentil",
                     "socionext,uniphier-pxs2";
 
-       memory {
-               device_type = "memory";
-               reg = <0x80000000 0x80000000>;
-       };
-
        chosen {
                stdout-path = "serial0:115200n8";
        };
                i2c5 = &i2c5;
                i2c6 = &i2c6;
        };
+
+       memory@80000000 {
+               device_type = "memory";
+               reg = <0x80000000 0x80000000>;
+       };
 };
 
 &serial2 {
@@ -82,6 +82,7 @@
        eeprom@54 {
                compatible = "st,24c64";
                reg = <0x54>;
+               pagesize = <32>;
        };
 };
 
index 51a3eacddfc6c1fda3935b59cce6b676b9c58939..803a39aa39d0a02373c8138079868e7b6e5731c4 100644 (file)
        model = "UniPhier PXs2 Vodka Board";
        compatible = "socionext,uniphier-pxs2-vodka", "socionext,uniphier-pxs2";
 
-       memory {
-               device_type = "memory";
-               reg = <0x80000000 0x80000000>;
-       };
-
        chosen {
                stdout-path = "serial0:115200n8";
        };
                i2c5 = &i2c5;
                i2c6 = &i2c6;
        };
+
+       memory@80000000 {
+               device_type = "memory";
+               reg = <0x80000000 0x80000000>;
+       };
 };
 
 &serial2 {
index e9e031d63c1ab694bfe5d81ce72ebe4505f18149..58c3e2f357069eaea404bfc8eaf76216b514f9cd 100644 (file)
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
-/include/ "skeleton.dtsi"
-
 / {
        compatible = "socionext,uniphier-pxs2";
+       #address-cells = <1>;
+       #size-cells = <1>;
 
        cpus {
                #address-cells = <1>;
index f7df0881c5e00e32651e965118b73c7ed44d4c84..c62ae1a81f471816b80d9d4104319f0f0fc40170 100644 (file)
@@ -1,7 +1,8 @@
 /*
  * Device Tree Source for UniPhier Reference Daughter Board
  *
- * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2015-2017 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * This file is dual-licensed: you can use it either under the terms
  * of the GPL or the X11 license, at your option. Note that this dual
@@ -46,5 +47,6 @@
        eeprom@50 {
                compatible = "microchip,24lc128";
                reg = <0x50>;
+               pagesize = <64>;
        };
 };
index ac792ae07ae01fce2a40b1dc44772c83a58f214c..eb63dcca92b5efdc2236d00601757fcf84dd968b 100644 (file)
        model = "UniPhier sLD3 Reference Board";
        compatible = "socionext,uniphier-sld3-ref", "socionext,uniphier-sld3";
 
-       memory {
-               device_type = "memory";
-               reg = <0x80000000 0x20000000
-                      0xc0000000 0x20000000>;
-       };
-
        chosen {
                stdout-path = "serial0:115200n8";
        };
                i2c3 = &i2c3;
                i2c4 = &i2c4;
        };
+
+       memory@8000000 {
+               device_type = "memory";
+               reg = <0x80000000 0x20000000
+                      0xc0000000 0x20000000>;
+       };
 };
 
 &ethsc {
index 9fad6bd2db8aa72d3f8c186cfc035326418dbbb8..01d77edac01f681c09001f258238c68dc3f85acf 100644 (file)
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
-/include/ "skeleton.dtsi"
-
 / {
        compatible = "socionext,uniphier-sld3";
+       #address-cells = <1>;
+       #size-cells = <1>;
 
        cpus {
                #address-cells = <1>;
index a8291f988066a906fe5ae09e276e88a0ee025a05..737d276349fd5f91e2aa0a92a5a3aee88d1723db 100644 (file)
        model = "UniPhier sLD8 Reference Board";
        compatible = "socionext,uniphier-sld8-ref", "socionext,uniphier-sld8";
 
-       memory {
-               device_type = "memory";
-               reg = <0x80000000 0x20000000>;
-       };
-
        chosen {
                stdout-path = "serial0:115200n8";
        };
                i2c2 = &i2c2;
                i2c3 = &i2c3;
        };
+
+       memory@80000000 {
+               device_type = "memory";
+               reg = <0x80000000 0x20000000>;
+       };
 };
 
 &ethsc {
index b2c980ead7f082e60bd951b7c8c355a3c94e4020..eb06fdc04b0255df9a184b8ff6869ad3e35931bb 100644 (file)
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
-/include/ "skeleton.dtsi"
-
 / {
        compatible = "socionext,uniphier-sld8";
+       #address-cells = <1>;
+       #size-cells = <1>;
 
        cpus {
                #address-cells = <1>;
index 51ecc9b9c0ceb6072c37173d4b9606645016344e..f61dfec2807fab84fe6d11bf5f31db16bf8d152f 100644 (file)
@@ -1,7 +1,8 @@
 /*
  * Device Tree Source for UniPhier Support Card (Expansion Board)
  *
- * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ * Copyright (C) 2015-2017 Socionext Inc.
+ *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
  *
  * This file is dual-licensed: you can use it either under the terms
  * of the GPL or the X11 license, at your option. Note that this dual
@@ -46,7 +47,7 @@
        status = "okay";
        ranges = <1 0x00000000 0x42000000 0x02000000>;
 
-       support_card: support_card {
+       support_card: support_card@1,1f00000 {
                compatible = "simple-bus";
                #address-cells = <1>;
                #size-cells = <1>;
index 3086efacd00e09ab388078625127af568f62214c..35714ff6f4677dfd6ee80af87c0db546dc360b85 100644 (file)
@@ -71,7 +71,7 @@
                        #size-cells = <1>;
                        ranges = <0 3 0 0x200000>;
 
-                       v2m_sysreg: sysreg@010000 {
+                       v2m_sysreg: sysreg@10000 {
                                compatible = "arm,vexpress-sysreg";
                                reg = <0x010000 0x1000>;
 
@@ -94,7 +94,7 @@
                                };
                        };
 
-                       v2m_sysctl: sysctl@020000 {
+                       v2m_sysctl: sysctl@20000 {
                                compatible = "arm,sp810", "arm,primecell";
                                reg = <0x020000 0x1000>;
                                clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&smbclk>;
                        };
 
                        /* PCI-E I2C bus */
-                       v2m_i2c_pcie: i2c@030000 {
+                       v2m_i2c_pcie: i2c@30000 {
                                compatible = "arm,versatile-i2c";
                                reg = <0x030000 0x1000>;
 
                                };
                        };
 
-                       aaci@040000 {
+                       aaci@40000 {
                                compatible = "arm,pl041", "arm,primecell";
                                reg = <0x040000 0x1000>;
                                interrupts = <11>;
                                clock-names = "apb_pclk";
                        };
 
-                       mmci@050000 {
+                       mmci@50000 {
                                compatible = "arm,pl180", "arm,primecell";
                                reg = <0x050000 0x1000>;
                                interrupts = <9 10>;
                                clock-names = "mclk", "apb_pclk";
                        };
 
-                       kmi@060000 {
+                       kmi@60000 {
                                compatible = "arm,pl050", "arm,primecell";
                                reg = <0x060000 0x1000>;
                                interrupts = <12>;
                                clock-names = "KMIREFCLK", "apb_pclk";
                        };
 
-                       kmi@070000 {
+                       kmi@70000 {
                                compatible = "arm,pl050", "arm,primecell";
                                reg = <0x070000 0x1000>;
                                interrupts = <13>;
                                clock-names = "KMIREFCLK", "apb_pclk";
                        };
 
-                       v2m_serial0: uart@090000 {
+                       v2m_serial0: uart@90000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0x090000 0x1000>;
                                interrupts = <5>;
                                clock-names = "uartclk", "apb_pclk";
                        };
 
-                       v2m_serial1: uart@0a0000 {
+                       v2m_serial1: uart@a0000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0x0a0000 0x1000>;
                                interrupts = <6>;
                                clock-names = "uartclk", "apb_pclk";
                        };
 
-                       v2m_serial2: uart@0b0000 {
+                       v2m_serial2: uart@b0000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0x0b0000 0x1000>;
                                interrupts = <7>;
                                clock-names = "uartclk", "apb_pclk";
                        };
 
-                       v2m_serial3: uart@0c0000 {
+                       v2m_serial3: uart@c0000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0x0c0000 0x1000>;
                                interrupts = <8>;
                                clock-names = "uartclk", "apb_pclk";
                        };
 
-                       wdt@0f0000 {
+                       wdt@f0000 {
                                compatible = "arm,sp805", "arm,primecell";
                                reg = <0x0f0000 0x1000>;
                                interrupts = <0>;
index c6393d3f17191c86eeaedd114fd55239766b4690..1b6f6393be936d1114ea2dd5235eb18d70165cf9 100644 (file)
@@ -70,7 +70,7 @@
                        #size-cells = <1>;
                        ranges = <0 7 0 0x20000>;
 
-                       v2m_sysreg: sysreg@00000 {
+                       v2m_sysreg: sysreg@0 {
                                compatible = "arm,vexpress-sysreg";
                                reg = <0x00000 0x1000>;
 
@@ -93,7 +93,7 @@
                                };
                        };
 
-                       v2m_sysctl: sysctl@01000 {
+                       v2m_sysctl: sysctl@1000 {
                                compatible = "arm,sp810", "arm,primecell";
                                reg = <0x01000 0x1000>;
                                clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&smbclk>;
                        };
 
                        /* PCI-E I2C bus */
-                       v2m_i2c_pcie: i2c@02000 {
+                       v2m_i2c_pcie: i2c@2000 {
                                compatible = "arm,versatile-i2c";
                                reg = <0x02000 0x1000>;
 
                                };
                        };
 
-                       aaci@04000 {
+                       aaci@4000 {
                                compatible = "arm,pl041", "arm,primecell";
                                reg = <0x04000 0x1000>;
                                interrupts = <11>;
                                clock-names = "apb_pclk";
                        };
 
-                       mmci@05000 {
+                       mmci@5000 {
                                compatible = "arm,pl180", "arm,primecell";
                                reg = <0x05000 0x1000>;
                                interrupts = <9 10>;
                                clock-names = "mclk", "apb_pclk";
                        };
 
-                       kmi@06000 {
+                       kmi@6000 {
                                compatible = "arm,pl050", "arm,primecell";
                                reg = <0x06000 0x1000>;
                                interrupts = <12>;
                                clock-names = "KMIREFCLK", "apb_pclk";
                        };
 
-                       kmi@07000 {
+                       kmi@7000 {
                                compatible = "arm,pl050", "arm,primecell";
                                reg = <0x07000 0x1000>;
                                interrupts = <13>;
                                clock-names = "KMIREFCLK", "apb_pclk";
                        };
 
-                       v2m_serial0: uart@09000 {
+                       v2m_serial0: uart@9000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0x09000 0x1000>;
                                interrupts = <5>;
                                clock-names = "uartclk", "apb_pclk";
                        };
 
-                       v2m_serial1: uart@0a000 {
+                       v2m_serial1: uart@a000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0x0a000 0x1000>;
                                interrupts = <6>;
                                clock-names = "uartclk", "apb_pclk";
                        };
 
-                       v2m_serial2: uart@0b000 {
+                       v2m_serial2: uart@b000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0x0b000 0x1000>;
                                interrupts = <7>;
                                clock-names = "uartclk", "apb_pclk";
                        };
 
-                       v2m_serial3: uart@0c000 {
+                       v2m_serial3: uart@c000 {
                                compatible = "arm,pl011", "arm,primecell";
                                reg = <0x0c000 0x1000>;
                                interrupts = <8>;
                                clock-names = "uartclk", "apb_pclk";
                        };
 
-                       wdt@0f000 {
+                       wdt@f000 {
                                compatible = "arm,sp805", "arm,primecell";
                                reg = <0x0f000 0x1000>;
                                interrupts = <0>;
index 15f4fd3f469561caa7fba30fed8c6a10c18c6668..0c8de0ca73ee8a67f1c7c419d8de28590888ebfd 100644 (file)
                };
        };
 
-       smb@08000000 {
+       smb@8000000 {
                compatible = "simple-bus";
 
                #address-cells = <2>;
index bd107c5a02267f33a02e31e0e5fd116672684d73..65ecf206388cc3b4ae1885daa67235b9bcdd1621 100644 (file)
                };
        };
 
-       etb@0,20010000 {
+       etb@20010000 {
                compatible = "arm,coresight-etb10", "arm,primecell";
                reg = <0 0x20010000 0 0x1000>;
 
                };
        };
 
-       tpiu@0,20030000 {
+       tpiu@20030000 {
                compatible = "arm,coresight-tpiu", "arm,primecell";
                reg = <0 0x20030000 0 0x1000>;
 
                };
        };
 
-       funnel@0,20040000 {
+       funnel@20040000 {
                compatible = "arm,coresight-funnel", "arm,primecell";
                reg = <0 0x20040000 0 0x1000>;
 
                };
        };
 
-       ptm@0,2201c000 {
+       ptm@2201c000 {
                compatible = "arm,coresight-etm3x", "arm,primecell";
                reg = <0 0x2201c000 0 0x1000>;
 
                };
        };
 
-       ptm@0,2201d000 {
+       ptm@2201d000 {
                compatible = "arm,coresight-etm3x", "arm,primecell";
                reg = <0 0x2201d000 0 0x1000>;
 
                };
        };
 
-       etm@0,2203c000 {
+       etm@2203c000 {
                compatible = "arm,coresight-etm3x", "arm,primecell";
                reg = <0 0x2203c000 0 0x1000>;
 
                };
        };
 
-       etm@0,2203d000 {
+       etm@2203d000 {
                compatible = "arm,coresight-etm3x", "arm,primecell";
                reg = <0 0x2203d000 0 0x1000>;
 
                };
        };
 
-       etm@0,2203e000 {
+       etm@2203e000 {
                compatible = "arm,coresight-etm3x", "arm,primecell";
                reg = <0 0x2203e000 0 0x1000>;
 
                };
        };
 
-       smb@08000000 {
+       smb@8000000 {
                compatible = "simple-bus";
 
                #address-cells = <2>;
index 1acecaf4b13d8a349616b3e78f7f62c1dc9556c2..6e69b8e6c1a7891af21b5b861128bef18cf89b96 100644 (file)
                };
        };
 
-       smb@08000000 {
+       smb@8000000 {
                compatible = "simple-bus";
 
                #address-cells = <2>;
index b608a03ee02f73f0c8d39ca546e163e9ed6053b2..c9305b58afc23d8733d6d5ee600127b5a8888248 100644 (file)
                };
        };
 
-       smb@04000000 {
+       smb@4000000 {
                compatible = "simple-bus";
 
                #address-cells = <2>;
index 7940408838df6c10e086e1246b8ee944bd42fef9..37f95427616f28697f7bbbedd5ef8ba758d3e514 100644 (file)
                        #size-cells = <0>;
                        reg = <4>;
 
-                       switch2: switch2@0 {
+                       switch2: switch@0 {
                                compatible = "marvell,mv88e6085";
                                #address-cells = <1>;
                                #size-cells = <0>;
                >;
        };
 
-       pinctrl_gpio_switch0: pinctrl-gpio-switch0 {
-               fsl,pins = <
-                       VF610_PAD_PTB5__GPIO_27         0x219d
-               >;
-       };
-
-       pinctrl_gpio_switch1: pinctrl-gpio-switch1 {
-               fsl,pins = <
-                       VF610_PAD_PTB4__GPIO_26         0x219d
-               >;
-       };
-
        pinctrl_mdio_mux: pinctrl-mdio-mux {
                fsl,pins = <
                        VF610_PAD_PTA18__GPIO_8         0x31c2
index 6a45bd24ffe608b085bf534a8165e55dd8537b90..db3b408ea55afee6a96530585fbda8a3c6f3fad2 100644 (file)
 
                        switch0: switch@0 {
                                compatible = "marvell,mv88e6190";
+                               pinctrl-0 = <&pinctrl_gpio_switch0>;
+                               pinctrl-names = "default";
                                #address-cells = <1>;
                                #size-cells = <0>;
                                reg = <0>;
                                dsa,member = <0 0>;
                                eeprom-length = <512>;
+                               interrupt-parent = <&gpio0>;
+                               interrupts = <27 IRQ_TYPE_LEVEL_LOW>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
 
                                ports {
                                        #address-cells = <1>;
                                        port@1 {
                                                reg = <1>;
                                                label = "lan1";
+                                               phy-handle = <&switch0phy1>;
                                        };
 
                                        port@2 {
                                                reg = <2>;
                                                label = "lan2";
+                                               phy-handle = <&switch0phy2>;
                                        };
 
                                        port@3 {
                                                reg = <3>;
                                                label = "lan3";
+                                               phy-handle = <&switch0phy3>;
                                        };
 
                                        port@4 {
                                                reg = <4>;
                                                label = "lan4";
+                                               phy-handle = <&switch0phy4>;
                                        };
 
                                        switch0port10: port@10 {
                                                link = <&switch1port10>;
                                        };
                                };
+
+                               mdio {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+
+                                       switch0phy1: switch0phy@1 {
+                                               reg = <1>;
+                                               interrupt-parent = <&switch0>;
+                                               interrupts = <1 IRQ_TYPE_LEVEL_HIGH>;
+                                       };
+
+                                       switch0phy2: switch0phy@2 {
+                                               reg = <2>;
+                                               interrupt-parent = <&switch0>;
+                                               interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
+                                       };
+
+                                       switch0phy3: switch0phy@3 {
+                                               reg = <3>;
+                                               interrupt-parent = <&switch0>;
+                                               interrupts = <3 IRQ_TYPE_LEVEL_HIGH>;
+                                       };
+
+                                       switch0phy4: switch0phy@4 {
+                                               reg = <4>;
+                                               interrupt-parent = <&switch0>;
+                                               interrupts = <4 IRQ_TYPE_LEVEL_HIGH>;
+                                       };
+                               };
                        };
                };
 
 
                        switch1: switch@0 {
                                compatible = "marvell,mv88e6190";
+                               pinctrl-0 = <&pinctrl_gpio_switch1>;
+                               pinctrl-names = "default";
                                #address-cells = <1>;
                                #size-cells = <0>;
                                reg = <0>;
                                dsa,member = <0 1>;
                                eeprom-length = <512>;
+                               interrupt-parent = <&gpio0>;
+                               interrupts = <26 IRQ_TYPE_LEVEL_LOW>;
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
 
                                ports {
                                        #address-cells = <1>;
                                        port@1 {
                                                reg = <1>;
                                                label = "lan5";
+                                               phy-handle = <&switch1phy1>;
                                        };
 
                                        port@2 {
                                                reg = <2>;
                                                label = "lan6";
+                                               phy-handle = <&switch1phy2>;
                                        };
 
                                        port@3 {
                                                reg = <3>;
                                                label = "lan7";
+                                               phy-handle = <&switch1phy3>;
                                        };
 
                                        port@4 {
                                                reg = <4>;
                                                label = "lan8";
+                                               phy-handle = <&switch1phy4>;
                                        };
 
 
                                                link = <&switch0port10>;
                                        };
                                };
+                               mdio {
+                                       #address-cells = <1>;
+                                       #size-cells = <0>;
+
+                                       switch1phy1: switch1phy@1 {
+                                               reg = <1>;
+                                               interrupt-parent = <&switch1>;
+                                               interrupts = <1 IRQ_TYPE_LEVEL_HIGH>;
+                                       };
+
+                                       switch1phy2: switch1phy@2 {
+                                               reg = <2>;
+                                               interrupt-parent = <&switch1>;
+                                               interrupts = <2 IRQ_TYPE_LEVEL_HIGH>;
+                                       };
+
+                                       switch1phy3: switch1phy@3 {
+                                               reg = <3>;
+                                               interrupt-parent = <&switch1>;
+                                               interrupts = <3 IRQ_TYPE_LEVEL_HIGH>;
+                                       };
+
+                                       switch1phy4: switch1phy@4 {
+                                               reg = <4>;
+                                               interrupt-parent = <&switch1>;
+                                               interrupts = <4 IRQ_TYPE_LEVEL_HIGH>;
+                                       };
+                               };
                        };
                };
 
index ca9e1bc35e45797eb8dd840182b7055e93003ef3..6b58d3a97992c11daa3fabe5aea74f3531bd1f46 100644 (file)
                >;
        };
 
+       pinctrl_gpio_switch0: pinctrl-gpio-switch0 {
+               fsl,pins = <
+                       VF610_PAD_PTB5__GPIO_27         0x219d
+               >;
+       };
+
+       pinctrl_gpio_switch1: pinctrl-gpio-switch1 {
+               fsl,pins = <
+                       VF610_PAD_PTB4__GPIO_26         0x219d
+               >;
+       };
+
        pinctrl_i2c_mux_reset: pinctrl-i2c-mux-reset {
                fsl,pins = <
                         VF610_PAD_PTE14__GPIO_119      0x31c2
index 9353184d730dfda864c85ec180b906b9ed575681..1181053e3ade766fd0ad5364831920b97d5632a5 100644 (file)
@@ -1,6 +1,3 @@
-config ICST
-       bool
-
 config SA1111
        bool
        select DMABOUNCE if !ARCH_PXA
index 27f23b15b1ea272a227fa431c12a0266de7061fe..29fdf6a3601dcbdf4abfaaa224cc9b75c6bfc932 100644 (file)
@@ -4,7 +4,6 @@
 
 obj-y                          += firmware.o
 
-obj-$(CONFIG_ICST)             += icst.o
 obj-$(CONFIG_SA1111)           += sa1111.o
 obj-$(CONFIG_DMABOUNCE)                += dmabounce.o
 obj-$(CONFIG_SHARP_LOCOMO)     += locomo.o
index d25010e3a0bc6996e678e36aa788c526b834bbd0..cfc2465e8b7791dde460c45beb8a019ee8b960c2 100644 (file)
@@ -1,6 +1,6 @@
 CONFIG_KERNEL_XZ=y
+# CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
-CONFIG_USELIB=y
 CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_NO_HZ_IDLE=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -8,39 +8,65 @@ CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CGROUPS=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_RD_BZIP2 is not set
-# CONFIG_RD_LZMA is not set
 # CONFIG_RD_LZO is not set
 # CONFIG_RD_LZ4 is not set
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_KALLSYMS_ALL=y
 CONFIG_BPF_SYSCALL=y
-# CONFIG_SHMEM is not set
 # CONFIG_AIO is not set
 CONFIG_EMBEDDED=y
 # CONFIG_COMPAT_BRK is not set
 CONFIG_SLAB=y
-CONFIG_CC_STACKPROTECTOR_STRONG=y
+CONFIG_JUMP_LABEL=y
+CONFIG_GCC_PLUGINS=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLOCK is not set
+# CONFIG_LBDAF is not set
 # CONFIG_ARCH_MULTI_V7 is not set
 CONFIG_ARCH_ASPEED=y
 CONFIG_MACH_ASPEED_G4=y
 CONFIG_AEABI=y
-CONFIG_UACCESS_WITH_MEMCPY=y
+# CONFIG_CPU_SW_DOMAIN_PAN is not set
+# CONFIG_COMPACTION is not set
 CONFIG_SECCOMP=y
+# CONFIG_ATAGS is not set
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_ARM_APPENDED_DTB=y
 CONFIG_ARM_ATAG_DTB_COMPAT=y
 CONFIG_KEXEC=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_PACKET_DIAG=y
+CONFIG_UNIX=y
+CONFIG_UNIX_DIAG=y
 CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
 CONFIG_NET_NCSI=y
 # CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_MTD=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_PARTITIONED_MASTER=y
+CONFIG_MTD_SPI_NOR=y
+CONFIG_SPI_ASPEED_SMC=y
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_FASTMAP=y
+CONFIG_MTD_UBI_BLOCK=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_ASPEED_LPC_CTRL=y
+CONFIG_EEPROM_AT24=y
 CONFIG_NETDEVICES=y
+CONFIG_NETCONSOLE=y
 # CONFIG_NET_VENDOR_ALACRITECH is not set
 # CONFIG_NET_VENDOR_AMAZON is not set
 # CONFIG_NET_VENDOR_ARC is not set
@@ -63,9 +89,10 @@ CONFIG_FTGMAC100=y
 # CONFIG_NET_VENDOR_SOLARFLARE is not set
 # CONFIG_NET_VENDOR_SMSC is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
-# CONFIG_NET_VENDOR_SYNOPSYS is not set
 # CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_BROADCOM_PHY=y
+CONFIG_REALTEK_PHY=y
 # CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
@@ -81,35 +108,74 @@ CONFIG_SERIAL_8250_SHARE_IRQ=y
 CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_ASPEED_BT_IPMI_BMC=y
 # CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MUX=y
+CONFIG_I2C_MUX_PCA9541=y
+CONFIG_I2C_MUX_PCA954x=y
 CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_ASPEED=y
-# CONFIG_USB_SUPPORT is not set
+CONFIG_W1=y
+CONFIG_W1_MASTER_GPIO=y
+CONFIG_W1_SLAVE_THERM=y
+CONFIG_SENSORS_ASPEED=y
+CONFIG_SENSORS_IIO_HWMON=y
+CONFIG_SENSORS_LM75=y
+CONFIG_SENSORS_NCT7904=y
+CONFIG_PMBUS=y
+CONFIG_SENSORS_ADM1275=y
+CONFIG_SENSORS_LM25066=y
+CONFIG_SENSORS_UCD9000=y
+CONFIG_SENSORS_TMP421=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_DYNAMIC_MINORS=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_CLASS_FLASH=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_PCF8523=y
+CONFIG_RTC_DRV_RV8803=y
+CONFIG_MAILBOX=y
 # CONFIG_IOMMU_SUPPORT is not set
+CONFIG_IIO=y
+CONFIG_ASPEED_ADC=y
+CONFIG_BMP280=y
 CONFIG_FIRMWARE_MEMMAP=y
 CONFIG_FANOTIFY=y
+CONFIG_OVERLAY_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_UBIFS_FS=y
+CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_XZ=y
 CONFIG_PRINTK_TIME=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_STRIP_ASM_SYMS=y
-CONFIG_PAGE_POISONING=y
-CONFIG_DEBUG_KMEMLEAK=y
-CONFIG_DEBUG_SHIRQ=y
+CONFIG_DEBUG_FS=y
 CONFIG_LOCKUP_DETECTOR=y
 CONFIG_WQ_WATCHDOG=y
+CONFIG_PANIC_TIMEOUT=-1
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_SCHED_STACK_END_CHECK=y
-CONFIG_DEBUG_RT_MUTEXES=y
-CONFIG_DEBUG_WW_MUTEX_SLOWPATH=y
+CONFIG_STACKTRACE=y
 # CONFIG_FTRACE is not set
-CONFIG_MEMTEST=y
-CONFIG_UBSAN=y
 CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_LL=y
-CONFIG_DEBUG_LL_UART_8250=y
-CONFIG_DEBUG_UART_PHYS=0x1e784000
-CONFIG_DEBUG_UART_VIRT=0xe8784000
-CONFIG_EARLY_PRINTK=y
-CONFIG_STRICT_MODULE_RWX=y
-CONFIG_STRICT_KERNEL_RWX=y
+# CONFIG_CRYPTO_ECHAINIV is not set
+# CONFIG_CRYPTO_HW is not set
 # CONFIG_XZ_DEC_X86 is not set
 # CONFIG_XZ_DEC_POWERPC is not set
 # CONFIG_XZ_DEC_IA64 is not set
index 5f660b02abd9024acce489bf2bc25798c975fcd8..3c20d93de389f3b249dd2e71363ef439a595ab92 100644 (file)
@@ -1,6 +1,6 @@
 CONFIG_KERNEL_XZ=y
+# CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
-CONFIG_USELIB=y
 CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_NO_HZ_IDLE=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -8,27 +8,28 @@ CONFIG_LOG_BUF_SHIFT=14
 CONFIG_CGROUPS=y
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_RD_BZIP2 is not set
-# CONFIG_RD_LZMA is not set
 # CONFIG_RD_LZO is not set
 # CONFIG_RD_LZ4 is not set
-CONFIG_CC_OPTIMIZE_FOR_SIZE=y
+CONFIG_KALLSYMS_ALL=y
 CONFIG_BPF_SYSCALL=y
-# CONFIG_SHMEM is not set
 # CONFIG_AIO is not set
 CONFIG_EMBEDDED=y
 # CONFIG_COMPAT_BRK is not set
 CONFIG_SLAB=y
-CONFIG_CC_STACKPROTECTOR_STRONG=y
+CONFIG_JUMP_LABEL=y
+CONFIG_GCC_PLUGINS=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLOCK is not set
+# CONFIG_LBDAF is not set
 CONFIG_ARCH_MULTI_V6=y
 # CONFIG_ARCH_MULTI_V7 is not set
 CONFIG_ARCH_ASPEED=y
 CONFIG_MACH_ASPEED_G5=y
+# CONFIG_CACHE_L2X0 is not set
 CONFIG_VMSPLIT_2G=y
 CONFIG_AEABI=y
-CONFIG_UACCESS_WITH_MEMCPY=y
+# CONFIG_CPU_SW_DOMAIN_PAN is not set
+# CONFIG_COMPACTION is not set
 CONFIG_SECCOMP=y
 # CONFIG_ATAGS is not set
 CONFIG_ZBOOT_ROM_TEXT=0x0
@@ -38,15 +39,37 @@ CONFIG_ARM_ATAG_DTB_COMPAT=y
 CONFIG_KEXEC=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_PACKET_DIAG=y
 CONFIG_UNIX=y
+CONFIG_UNIX_DIAG=y
 CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_SYN_COOKIES=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_DIAG is not set
+# CONFIG_IPV6 is not set
 CONFIG_NET_NCSI=y
 # CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_PREVENT_FIRMWARE_BUILD is not set
+CONFIG_MTD=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_PARTITIONED_MASTER=y
+CONFIG_MTD_SPI_NOR=y
+CONFIG_SPI_ASPEED_SMC=y
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_FASTMAP=y
+CONFIG_MTD_UBI_BLOCK=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_ASPEED_LPC_CTRL=y
+CONFIG_EEPROM_AT24=y
 CONFIG_NETDEVICES=y
+CONFIG_NETCONSOLE=y
 # CONFIG_NET_VENDOR_ALACRITECH is not set
 # CONFIG_NET_VENDOR_AMAZON is not set
 # CONFIG_NET_VENDOR_ARC is not set
@@ -69,9 +92,10 @@ CONFIG_FTGMAC100=y
 # CONFIG_NET_VENDOR_SOLARFLARE is not set
 # CONFIG_NET_VENDOR_SMSC is not set
 # CONFIG_NET_VENDOR_STMICRO is not set
-# CONFIG_NET_VENDOR_SYNOPSYS is not set
 # CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
+CONFIG_BROADCOM_PHY=y
+CONFIG_REALTEK_PHY=y
 # CONFIG_WLAN is not set
 # CONFIG_INPUT is not set
 # CONFIG_SERIO is not set
@@ -87,37 +111,74 @@ CONFIG_SERIAL_8250_SHARE_IRQ=y
 CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_ASPEED_BT_IPMI_BMC=y
 # CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+# CONFIG_I2C_COMPAT is not set
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_MUX=y
+CONFIG_I2C_MUX_PCA9541=y
+CONFIG_I2C_MUX_PCA954x=y
 CONFIG_GPIOLIB=y
+CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_ASPEED=y
-# CONFIG_USB_SUPPORT is not set
+CONFIG_W1=y
+CONFIG_W1_MASTER_GPIO=y
+CONFIG_W1_SLAVE_THERM=y
+CONFIG_SENSORS_ASPEED=y
+CONFIG_SENSORS_IIO_HWMON=y
+CONFIG_SENSORS_LM75=y
+CONFIG_SENSORS_NCT7904=y
+CONFIG_PMBUS=y
+CONFIG_SENSORS_ADM1275=y
+CONFIG_SENSORS_LM25066=y
+CONFIG_SENSORS_UCD9000=y
+CONFIG_SENSORS_TMP421=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_DYNAMIC_MINORS=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_ROOT_HUB_TT=y
+CONFIG_USB_EHCI_HCD_PLATFORM=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_CLASS_FLASH=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_PCF8523=y
+CONFIG_RTC_DRV_RV8803=y
+CONFIG_MAILBOX=y
 # CONFIG_IOMMU_SUPPORT is not set
+CONFIG_IIO=y
+CONFIG_ASPEED_ADC=y
+CONFIG_BMP280=y
 CONFIG_FIRMWARE_MEMMAP=y
 CONFIG_FANOTIFY=y
+CONFIG_OVERLAY_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_JFFS2_SUMMARY=y
+CONFIG_JFFS2_FS_XATTR=y
+CONFIG_UBIFS_FS=y
+CONFIG_SQUASHFS=y
+CONFIG_SQUASHFS_XZ=y
 CONFIG_PRINTK_TIME=y
 CONFIG_DYNAMIC_DEBUG=y
 CONFIG_STRIP_ASM_SYMS=y
-CONFIG_PAGE_POISONING=y
-CONFIG_DEBUG_KMEMLEAK=y
-CONFIG_DEBUG_SHIRQ=y
+CONFIG_DEBUG_FS=y
 CONFIG_LOCKUP_DETECTOR=y
 CONFIG_WQ_WATCHDOG=y
+CONFIG_PANIC_TIMEOUT=-1
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_SCHED_STACK_END_CHECK=y
-CONFIG_DEBUG_RT_MUTEXES=y
-CONFIG_DEBUG_WW_MUTEX_SLOWPATH=y
+CONFIG_STACKTRACE=y
 # CONFIG_FTRACE is not set
-CONFIG_MEMTEST=y
-CONFIG_UBSAN=y
-CONFIG_UBSAN_ALIGNMENT=y
 CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_LL=y
-CONFIG_DEBUG_LL_UART_8250=y
-CONFIG_DEBUG_UART_PHYS=0x1e784000
-CONFIG_DEBUG_UART_VIRT=0xe8784000
-CONFIG_EARLY_PRINTK=y
-CONFIG_STRICT_MODULE_RWX=y
-CONFIG_STRICT_KERNEL_RWX=y
-CONFIG_CRYPTO_ECHAINIV=y
+# CONFIG_CRYPTO_ECHAINIV is not set
+# CONFIG_CRYPTO_HW is not set
 # CONFIG_XZ_DEC_X86 is not set
 # CONFIG_XZ_DEC_POWERPC is not set
 # CONFIG_XZ_DEC_IA64 is not set
index 4b89f4e6e849b44003d237f22cb674427f4a4187..3ba8cd3211f8b0305b2338c9382d4e7f1d9c8100 100644 (file)
@@ -1,6 +1,5 @@
 # CONFIG_LOCALVERSION_AUTO is not set
 CONFIG_SYSVIPC=y
-CONFIG_FHANDLE=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BSD_PROCESS_ACCT=y
@@ -32,6 +31,7 @@ CONFIG_PREEMPT_VOLUNTARY=y
 CONFIG_AEABI=y
 CONFIG_KSM=y
 CONFIG_CLEANCACHE=y
+CONFIG_CMA=y
 CONFIG_SECCOMP=y
 CONFIG_KEXEC=y
 CONFIG_CRASH_DUMP=y
@@ -52,6 +52,7 @@ CONFIG_MAC80211=y
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_STANDALONE is not set
+CONFIG_DMA_CMA=y
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_SCSI_CONSTANTS=y
@@ -62,7 +63,6 @@ CONFIG_USB_NET_SMSC95XX=y
 CONFIG_ZD1211RW=y
 CONFIG_INPUT_EVDEV=y
 # CONFIG_LEGACY_PTYS is not set
-# CONFIG_DEVKMEM is not set
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
 CONFIG_TTY_PRINTK=y
@@ -92,6 +92,7 @@ CONFIG_MMC=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_SDHCI_IPROC=y
+CONFIG_MMC_BCM2835=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_GPIO=y
index c8663eac9b1b462766a848033e3c5fbbd4b79c7b..67db82999c06bb84bed14e1b6a026470ba0ce47f 100644 (file)
@@ -74,12 +74,10 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=1
 CONFIG_BLK_DEV_RAM_SIZE=32768
 CONFIG_EEPROM_AT24=y
-CONFIG_IDE=m
-CONFIG_BLK_DEV_PALMCHIP_BK3710=m
-CONFIG_SCSI=m
 CONFIG_BLK_DEV_SD=m
 CONFIG_ATA=m
 CONFIG_AHCI_DA850=m
+CONFIG_PATA_BK3710=m
 CONFIG_NETDEVICES=y
 CONFIG_NETCONSOLE=y
 CONFIG_TUN=m
@@ -121,6 +119,7 @@ CONFIG_PINCTRL_DA850_PUPD=m
 CONFIG_PINCTRL_SINGLE=y
 CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_PCA953X=y
+CONFIG_GPIO_PCA953X_IRQ=y
 CONFIG_POWER_RESET=y
 CONFIG_POWER_RESET_GPIO=y
 CONFIG_WATCHDOG=y
@@ -133,9 +132,11 @@ CONFIG_REGULATOR_TPS6507X=y
 CONFIG_MEDIA_SUPPORT=m
 CONFIG_MEDIA_CAMERA_SUPPORT=y
 CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_VIDEO_DAVINCI_VPIF_DISPLAY=m
 CONFIG_VIDEO_DAVINCI_VPIF_CAPTURE=m
 # CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set
 CONFIG_VIDEO_TVP514X=m
+CONFIG_VIDEO_ADV7343=m
 CONFIG_DRM=m
 CONFIG_DRM_TILCDC=m
 CONFIG_DRM_DUMB_VGA_DAC=m
@@ -204,12 +205,10 @@ CONFIG_MEMORY=y
 CONFIG_TI_AEMIF=m
 CONFIG_DA8XX_DDRCTL=y
 CONFIG_IIO=m
-CONFIG_IIO_BUFFER=y
 CONFIG_IIO_BUFFER_CB=m
-CONFIG_IIO_KFIFO_BUF=m
-CONFIG_IIO_TRIGGER=y
 CONFIG_IIO_SW_DEVICE=m
 CONFIG_IIO_SW_TRIGGER=m
+CONFIG_TI_ADS7950=m
 CONFIG_IIO_HRTIMER_TRIGGER=m
 CONFIG_IIO_SYSFS_TRIGGER=m
 CONFIG_PWM=y
diff --git a/arch/arm/configs/dram_0xd0000000.config b/arch/arm/configs/dram_0xd0000000.config
new file mode 100644 (file)
index 0000000..61ba704
--- /dev/null
@@ -0,0 +1 @@
+CONFIG_DRAM_BASE=0xd0000000
index 742baf067e1ca87a6251f21804dd6f88d23cfb69..6dc661c4a2c1a9af6d3b08f9349b6838e9629a48 100644 (file)
@@ -53,7 +53,7 @@ CONFIG_RFKILL_REGULATOR=y
 CONFIG_DEVTMPFS=y
 CONFIG_DEVTMPFS_MOUNT=y
 CONFIG_DMA_CMA=y
-CONFIG_CMA_SIZE_MBYTES=64
+CONFIG_CMA_SIZE_MBYTES=96
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_CRYPTOLOOP=y
 CONFIG_BLK_DEV_RAM=y
@@ -240,7 +240,7 @@ CONFIG_PWM=y
 CONFIG_PWM_SAMSUNG=y
 CONFIG_PHY_EXYNOS5250_SATA=y
 CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
 CONFIG_AUTOFS4_FS=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
@@ -255,6 +255,7 @@ CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ASCII=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_PRINTK_TIME=y
+CONFIG_DYNAMIC_DEBUG=y
 CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_FS=y
 CONFIG_MAGIC_SYSRQ=y
diff --git a/arch/arm/configs/gemini_defconfig b/arch/arm/configs/gemini_defconfig
new file mode 100644 (file)
index 0000000..d2d75fa
--- /dev/null
@@ -0,0 +1,68 @@
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_NO_HZ_IDLE=y
+CONFIG_BSD_PROCESS_ACCT=y
+CONFIG_USER_NS=y
+CONFIG_RELAY=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_ARCH_MULTI_V4=y
+# CONFIG_ARCH_MULTI_V7 is not set
+CONFIG_ARCH_GEMINI=y
+CONFIG_PCI=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_CMDLINE="console=ttyS0,115200n8"
+CONFIG_KEXEC=y
+CONFIG_BINFMT_MISC=y
+CONFIG_PM=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_MTD=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_CFI_STAA=y
+CONFIG_MTD_PHYSMAP=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=16384
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+CONFIG_INPUT_EVDEV=y
+CONFIG_KEYBOARD_GPIO=y
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_NR_UARTS=1
+CONFIG_SERIAL_8250_RUNTIME_UARTS=1
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+CONFIG_WATCHDOG=y
+CONFIG_GEMINI_WATCHDOG=y
+CONFIG_USB=y
+CONFIG_USB_MON=y
+CONFIG_USB_FOTG210_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_GEMINI=y
+CONFIG_DMADEVICES=y
+# CONFIG_DNOTIFY is not set
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_ROMFS_FS=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+# CONFIG_ENABLE_WARN_DEPRECATED is not set
+# CONFIG_ENABLE_MUST_CHECK is not set
+CONFIG_DEBUG_FS=y
index eaba3b165d7243a45662d3980210e954c5ebd152..bb6fa568b6200213443295fbe1e614c6d2dd3515 100644 (file)
@@ -143,6 +143,7 @@ CONFIG_SMSC911X=y
 # CONFIG_NET_VENDOR_STMICRO is not set
 CONFIG_AT803X_PHY=y
 CONFIG_MICREL_PHY=y
+CONFIG_SMSC_PHY=y
 CONFIG_USB_PEGASUS=m
 CONFIG_USB_RTL8150=m
 CONFIG_USB_RTL8152=m
@@ -152,7 +153,6 @@ CONFIG_BRCMFMAC=m
 CONFIG_WL12XX=m
 CONFIG_WLCORE_SDIO=m
 # CONFIG_WILINK_PLATFORM_DATA is not set
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 CONFIG_INPUT_EVDEV=y
 CONFIG_INPUT_EVBUG=m
 CONFIG_KEYBOARD_GPIO=y
@@ -165,6 +165,7 @@ CONFIG_TOUCHSCREEN_ADS7846=y
 CONFIG_TOUCHSCREEN_EGALAX=y
 CONFIG_TOUCHSCREEN_IMX6UL_TSC=y
 CONFIG_TOUCHSCREEN_EDT_FT5X06=y
+CONFIG_TOUCHSCREEN_MAX11801=y
 CONFIG_TOUCHSCREEN_MC13783=y
 CONFIG_TOUCHSCREEN_TSC2004=y
 CONFIG_TOUCHSCREEN_TSC2007=y
@@ -173,6 +174,7 @@ CONFIG_TOUCHSCREEN_SX8654=y
 CONFIG_TOUCHSCREEN_COLIBRI_VF50=y
 CONFIG_INPUT_MISC=y
 CONFIG_INPUT_MMA8450=y
+CONFIG_HID_MULTITOUCH=y
 CONFIG_SERIO_SERPORT=m
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SERIAL_IMX=y
@@ -376,7 +378,6 @@ CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_ISO8859_15=m
 CONFIG_NLS_UTF8=y
 CONFIG_PRINTK_TIME=y
-CONFIG_DEBUG_FS=y
 CONFIG_MAGIC_SYSRQ=y
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_PROVE_LOCKING=y
index 6aa7be191f1aadee3371254703d2a0dc5c4abc21..2685e03600b11bc1d48a2a12ca1a80e4de18adea 100644 (file)
@@ -195,7 +195,7 @@ CONFIG_DMA_CMA=y
 CONFIG_CMA_SIZE_MBYTES=64
 CONFIG_OMAP_OCP2SCP=y
 CONFIG_SIMPLE_PM_BUS=y
-CONFIG_SUNXI_RSB=m
+CONFIG_SUNXI_RSB=y
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_BLOCK=y
@@ -482,9 +482,10 @@ CONFIG_MFD_AS3722=y
 CONFIG_MFD_ATMEL_FLEXCOM=y
 CONFIG_MFD_ATMEL_HLCDC=m
 CONFIG_MFD_BCM590XX=y
+CONFIG_MFD_AC100=y
 CONFIG_MFD_AXP20X=y
-CONFIG_MFD_AXP20X_I2C=m
-CONFIG_MFD_AXP20X_RSB=m
+CONFIG_MFD_AXP20X_I2C=y
+CONFIG_MFD_AXP20X_RSB=y
 CONFIG_MFD_CROS_EC=m
 CONFIG_MFD_CROS_EC_I2C=m
 CONFIG_MFD_CROS_EC_SPI=m
@@ -513,7 +514,7 @@ CONFIG_REGULATOR_ACT8865=y
 CONFIG_REGULATOR_ANATOP=y
 CONFIG_REGULATOR_AS3711=y
 CONFIG_REGULATOR_AS3722=y
-CONFIG_REGULATOR_AXP20X=m
+CONFIG_REGULATOR_AXP20X=y
 CONFIG_REGULATOR_BCM590XX=y
 CONFIG_REGULATOR_DA9210=y
 CONFIG_REGULATOR_FAN53555=y
@@ -593,10 +594,10 @@ CONFIG_DRM_EXYNOS_DPI=y
 CONFIG_DRM_EXYNOS_DSI=y
 CONFIG_DRM_EXYNOS_HDMI=y
 CONFIG_DRM_ROCKCHIP=m
-CONFIG_ROCKCHIP_ANALOGIX_DP=m
-CONFIG_ROCKCHIP_DW_HDMI=m
-CONFIG_ROCKCHIP_DW_MIPI_DSI=m
-CONFIG_ROCKCHIP_INNO_HDMI=m
+CONFIG_ROCKCHIP_ANALOGIX_DP=y
+CONFIG_ROCKCHIP_DW_HDMI=y
+CONFIG_ROCKCHIP_DW_MIPI_DSI=y
+CONFIG_ROCKCHIP_INNO_HDMI=y
 CONFIG_DRM_ATMEL_HLCDC=m
 CONFIG_DRM_RCAR_DU=m
 CONFIG_DRM_RCAR_HDMI=y
@@ -730,6 +731,7 @@ CONFIG_MMC_DW_EXYNOS=y
 CONFIG_MMC_DW_ROCKCHIP=y
 CONFIG_MMC_SH_MMCIF=y
 CONFIG_MMC_SUNXI=y
+CONFIG_MMC_BCM2835=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_CLASS_FLASH=m
@@ -751,6 +753,7 @@ CONFIG_EDAC=y
 CONFIG_EDAC_HIGHBANK_MC=y
 CONFIG_EDAC_HIGHBANK_L2=y
 CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AC100=y
 CONFIG_RTC_DRV_AS3722=y
 CONFIG_RTC_DRV_DS1307=y
 CONFIG_RTC_DRV_HYM8563=m
@@ -883,7 +886,7 @@ CONFIG_TI_PIPE3=y
 CONFIG_PHY_BERLIN_USB=y
 CONFIG_PHY_BERLIN_SATA=y
 CONFIG_PHY_ROCKCHIP_DP=m
-CONFIG_PHY_ROCKCHIP_USB=m
+CONFIG_PHY_ROCKCHIP_USB=y
 CONFIG_PHY_QCOM_APQ8064_SATA=m
 CONFIG_PHY_MIPHY28LP=y
 CONFIG_PHY_RCAR_GEN2=m
index decd388d613d7e1d65c5d194f77fb23061ed37e0..a120ae81626003378ebab8afabe4c8358c789d3b 100644 (file)
@@ -64,6 +64,7 @@ CONFIG_CPU_FREQ_GOV_POWERSAVE=y
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
 CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
 CONFIG_CPUFREQ_DT=m
+CONFIG_ARM_TI_CPUFREQ=y
 # CONFIG_ARM_OMAP2PLUS_CPUFREQ is not set
 CONFIG_CPU_IDLE=y
 CONFIG_BINFMT_MISC=y
@@ -141,6 +142,7 @@ CONFIG_BLK_DEV_SD=y
 CONFIG_SCSI_SCAN_ASYNC=y
 CONFIG_ATA=y
 CONFIG_SATA_AHCI_PLATFORM=y
+CONFIG_AHCI_DM816=m
 CONFIG_NETDEVICES=y
 # CONFIG_NET_VENDOR_ARC is not set
 # CONFIG_NET_CADENCE is not set
@@ -167,8 +169,18 @@ CONFIG_TI_CPTS=y
 # CONFIG_NET_VENDOR_VIA is not set
 # CONFIG_NET_VENDOR_WIZNET is not set
 CONFIG_AT803X_PHY=y
+CONFIG_DP83848_PHY=y
 CONFIG_MICREL_PHY=y
 CONFIG_SMSC_PHY=y
+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_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
 CONFIG_USB_USBNET=m
 CONFIG_USB_NET_SMSC75XX=m
 CONFIG_USB_NET_SMSC95XX=m
@@ -176,6 +188,7 @@ CONFIG_USB_ALI_M5632=y
 CONFIG_USB_AN2720=y
 CONFIG_USB_EPSON2888=y
 CONFIG_USB_KC2190=y
+CONFIG_USB_NET_QMI_WWAN=m
 CONFIG_USB_CDC_PHONET=m
 CONFIG_LIBERTAS=m
 CONFIG_LIBERTAS_USB=m
@@ -199,6 +212,7 @@ CONFIG_KEYBOARD_TWL4030=m
 # CONFIG_INPUT_MOUSE is not set
 CONFIG_INPUT_TOUCHSCREEN=y
 CONFIG_TOUCHSCREEN_ADS7846=m
+CONFIG_TOUCHSCREEN_ATMEL_MXT=m
 CONFIG_TOUCHSCREEN_EDT_FT5X06=m
 CONFIG_TOUCHSCREEN_TI_AM335X_TSC=m
 CONFIG_TOUCHSCREEN_PIXCIR=m
@@ -206,6 +220,7 @@ CONFIG_TOUCHSCREEN_TSC2004=m
 CONFIG_TOUCHSCREEN_TSC2005=m
 CONFIG_TOUCHSCREEN_TSC2007=m
 CONFIG_INPUT_MISC=y
+CONFIG_INPUT_CPCAP_PWRBUTTON=m
 CONFIG_INPUT_TPS65218_PWRBUTTON=m
 CONFIG_INPUT_TWL4030_PWRBUTTON=m
 CONFIG_INPUT_PALMAS_PWRBUTTON=m
@@ -241,6 +256,7 @@ CONFIG_W1=m
 CONFIG_HDQ_MASTER_OMAP=m
 CONFIG_POWER_AVS=y
 CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_GPIO=y
 CONFIG_BATTERY_BQ27XXX=m
 CONFIG_CHARGER_ISP1704=m
 CONFIG_CHARGER_TWL4030=m
@@ -263,6 +279,7 @@ CONFIG_DRA752_THERMAL=y
 CONFIG_WATCHDOG=y
 CONFIG_OMAP_WATCHDOG=m
 CONFIG_TWL4030_WATCHDOG=m
+CONFIG_MFD_CPCAP=y
 CONFIG_MFD_TI_AM335X_TSCADC=m
 CONFIG_MFD_PALMAS=y
 CONFIG_MFD_TPS65217=y
@@ -270,7 +287,9 @@ CONFIG_MFD_TI_LP873X=y
 CONFIG_MFD_TPS65218=y
 CONFIG_MFD_TPS65910=y
 CONFIG_TWL6040_CORE=y
+CONFIG_REGULATOR_CPCAP=y
 CONFIG_REGULATOR_GPIO=y
+CONFIG_REGULATOR_LM363X=m
 CONFIG_REGULATOR_LP872X=y
 CONFIG_REGULATOR_LP873X=y
 CONFIG_REGULATOR_PALMAS=y
@@ -339,6 +358,7 @@ CONFIG_SND_SOC=m
 CONFIG_SND_EDMA_SOC=m
 CONFIG_SND_AM33XX_SOC_EVM=m
 CONFIG_SND_OMAP_SOC=m
+CONFIG_SND_OMAP_SOC_HDMI_AUDIO=m
 CONFIG_SND_OMAP_SOC_OMAP_TWL4030=m
 CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040=m
 CONFIG_SND_OMAP_SOC_OMAP3_PANDORA=m
@@ -354,6 +374,7 @@ CONFIG_USB_XHCI_HCD=m
 CONFIG_USB_EHCI_HCD=m
 CONFIG_USB_OHCI_HCD=m
 CONFIG_USB_WDM=m
+CONFIG_USB_ACM=m
 CONFIG_USB_STORAGE=m
 CONFIG_USB_MUSB_HDRC=m
 CONFIG_USB_MUSB_TUSB6010=m
@@ -402,6 +423,7 @@ CONFIG_MMC_OMAP=y
 CONFIG_MMC_OMAP_HS=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=m
+CONFIG_LEDS_CPCAP=m
 CONFIG_LEDS_GPIO=m
 CONFIG_LEDS_PCA963X=m
 CONFIG_LEDS_PWM=m
@@ -420,6 +442,7 @@ CONFIG_RTC_DRV_TWL92330=y
 CONFIG_RTC_DRV_TWL4030=m
 CONFIG_RTC_DRV_PALMAS=m
 CONFIG_RTC_DRV_OMAP=m
+CONFIG_RTC_DRV_CPCAP=m
 CONFIG_DMADEVICES=y
 CONFIG_DMA_OMAP=y
 CONFIG_TI_EDMA=y
@@ -432,6 +455,7 @@ CONFIG_IIO=m
 CONFIG_IIO_SW_DEVICE=m
 CONFIG_IIO_SW_TRIGGER=m
 CONFIG_IIO_ST_ACCEL_3AXIS=m
+CONFIG_CPCAP_ADC=m
 CONFIG_TI_AM335X_ADC=m
 CONFIG_BMP280=m
 CONFIG_PWM=y
index 4ffdd607205dd0757b1c27ea6bddd2962c6c7d4b..07666a7a9de51045556cca9153387613a2ed9227 100644 (file)
@@ -190,11 +190,18 @@ CONFIG_MDM_LCC_9615=y
 CONFIG_MSM_MMCC_8960=y
 CONFIG_MSM_MMCC_8974=y
 CONFIG_HWSPINLOCK_QCOM=y
+CONFIG_REMOTEPROC=y
+CONFIG_QCOM_ADSP_PIL=y
+CONFIG_QCOM_Q6V5_PIL=y
+CONFIG_QCOM_WCNSS_PIL=y
 CONFIG_QCOM_GSBI=y
 CONFIG_QCOM_PM=y
 CONFIG_QCOM_SMEM=y
 CONFIG_QCOM_SMD=y
 CONFIG_QCOM_SMD_RPM=y
+CONFIG_QCOM_SMP2P=y
+CONFIG_QCOM_SMSM=y
+CONFIG_QCOM_WCNSS_CTRL=y
 CONFIG_IIO=y
 CONFIG_IIO_BUFFER_CB=y
 CONFIG_IIO_SW_TRIGGER=y
index 030264c98eecc1dbaf5833c885f1c5c8ff65f2b6..2620ce790db0afaa18ed4d51eca2d886a21b00a8 100644 (file)
@@ -71,6 +71,7 @@ CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 # CONFIG_SCSI_LOWLEVEL is not set
 CONFIG_NETDEVICES=y
+CONFIG_ALTERA_TSE=m
 CONFIG_E1000E=m
 CONFIG_IGB=m
 CONFIG_IXGBE=m
index 03437f8f9ad132d8cf3686cdb257158bb545d05c..a0975386a96c61bfe3dfe897d81d1ed786dc3720 100644 (file)
@@ -20,6 +20,7 @@ CONFIG_EMBEDDED=y
 # CONFIG_MMU is not set
 CONFIG_ARM_SINGLE_ARMV7M=y
 CONFIG_ARCH_STM32=y
+CONFIG_CPU_V7M_NUM_IRQ=240
 CONFIG_SET_MEM_PARAM=y
 CONFIG_DRAM_BASE=0x90000000
 CONFIG_FLASH_MEM_BASE=0x08000000
@@ -47,6 +48,9 @@ CONFIG_SERIAL_NONSTANDARD=y
 CONFIG_SERIAL_STM32=y
 CONFIG_SERIAL_STM32_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_CHARDEV=y
+CONFIG_I2C_STM32F4=y
 # CONFIG_HWMON is not set
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
index da92c25eb7ccd97ffaaa1c2a7f2cbc28723f5e62..5cd5dd70bc836566634393e6d2c36d581d1a4ea9 100644 (file)
@@ -87,6 +87,7 @@ CONFIG_THERMAL_OF=y
 CONFIG_CPU_THERMAL=y
 CONFIG_WATCHDOG=y
 CONFIG_SUNXI_WATCHDOG=y
+CONFIG_MFD_AC100=y
 CONFIG_MFD_AXP20X=y
 CONFIG_MFD_AXP20X_I2C=y
 CONFIG_MFD_AXP20X_RSB=y
@@ -129,6 +130,7 @@ CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
 CONFIG_RTC_CLASS=y
 # CONFIG_RTC_INTF_SYSFS is not set
 # CONFIG_RTC_INTF_PROC is not set
+CONFIG_RTC_DRV_AC100=y
 CONFIG_RTC_DRV_SUN6I=y
 CONFIG_RTC_DRV_SUNXI=y
 CONFIG_DMADEVICES=y
index 02454fa15d2c42a979b06f387e41d2b5d35ecee7..d69bebf697e76d2003bb671645290c938a156abd 100644 (file)
@@ -478,26 +478,6 @@ static inline void __sync_cache_range_r(volatile void *p, size_t size)
        : : : "r0","r1","r2","r3","r4","r5","r6","r7", \
              "r9","r10","lr","memory" )
 
-#ifdef CONFIG_MMU
-int set_memory_ro(unsigned long addr, int numpages);
-int set_memory_rw(unsigned long addr, int numpages);
-int set_memory_x(unsigned long addr, int numpages);
-int set_memory_nx(unsigned long addr, int numpages);
-#else
-static inline int set_memory_ro(unsigned long addr, int numpages) { return 0; }
-static inline int set_memory_rw(unsigned long addr, int numpages) { return 0; }
-static inline int set_memory_x(unsigned long addr, int numpages) { return 0; }
-static inline int set_memory_nx(unsigned long addr, int numpages) { return 0; }
-#endif
-
-#ifdef CONFIG_STRICT_KERNEL_RWX
-void set_kernel_text_rw(void);
-void set_kernel_text_ro(void);
-#else
-static inline void set_kernel_text_rw(void) { }
-static inline void set_kernel_text_ro(void) { }
-#endif
-
 void flush_uprobe_xol_access(struct page *page, unsigned long uaddr,
                             void *kaddr, unsigned long len);
 
index 42871fb8340e0f8ed117fbca46905a29b9ec45c2..2cfbc531f63b61154fc7c18340b8a2c24f9732a8 100644 (file)
@@ -186,6 +186,16 @@ static inline void pci_ioremap_set_mem_type(int mem_type) {}
 
 extern int pci_ioremap_io(unsigned int offset, phys_addr_t phys_addr);
 
+/*
+ * PCI configuration space mapping function.
+ *
+ * The PCI specification does not allow configuration write
+ * transactions to be posted. Add an arch specific
+ * pci_remap_cfgspace() definition that is implemented
+ * through strongly ordered memory mappings.
+ */
+#define pci_remap_cfgspace pci_remap_cfgspace
+void __iomem *pci_remap_cfgspace(resource_size_t res_cookie, size_t size);
 /*
  * Now, pick up the machine-defined IO definitions
  */
index 4917c2f7e45955919509727640b9e54edd940b01..e74ab0fbab79091105dd1e5026c1e3e1e1347ead 100644 (file)
@@ -31,7 +31,8 @@ void kvm_register_target_coproc_table(struct kvm_coproc_target_table *table);
 int kvm_handle_cp10_id(struct kvm_vcpu *vcpu, struct kvm_run *run);
 int kvm_handle_cp_0_13_access(struct kvm_vcpu *vcpu, struct kvm_run *run);
 int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run);
-int kvm_handle_cp14_access(struct kvm_vcpu *vcpu, struct kvm_run *run);
+int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run);
+int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run);
 int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run);
 int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run);
 
index 057d381f4e57bb95167db49c9aea2b52ef303b76..396c92bcc0cf3a903276d9fea00365ad649fc9af 100644 (file)
@@ -29,8 +29,7 @@ static inline int pci_proc_domain(struct pci_bus *bus)
 #define PCI_DMA_BUS_IS_PHYS     (1)
 
 #define HAVE_PCI_MMAP
-extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
-                               enum pci_mmap_state mmap_state, int write_combine);
+#define ARCH_GENERIC_PCI_MMAP_RESOURCE
 
 static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
 {
diff --git a/arch/arm/include/asm/set_memory.h b/arch/arm/include/asm/set_memory.h
new file mode 100644 (file)
index 0000000..5aa4315
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 1999-2002 Russell King
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _ASMARM_SET_MEMORY_H
+#define _ASMARM_SET_MEMORY_H
+
+#ifdef CONFIG_MMU
+int set_memory_ro(unsigned long addr, int numpages);
+int set_memory_rw(unsigned long addr, int numpages);
+int set_memory_x(unsigned long addr, int numpages);
+int set_memory_nx(unsigned long addr, int numpages);
+#else
+static inline int set_memory_ro(unsigned long addr, int numpages) { return 0; }
+static inline int set_memory_rw(unsigned long addr, int numpages) { return 0; }
+static inline int set_memory_x(unsigned long addr, int numpages) { return 0; }
+static inline int set_memory_nx(unsigned long addr, int numpages) { return 0; }
+#endif
+
+#ifdef CONFIG_STRICT_KERNEL_RWX
+void set_kernel_text_rw(void);
+void set_kernel_text_ro(void);
+#else
+static inline void set_kernel_text_rw(void) { }
+static inline void set_kernel_text_ro(void) { }
+#endif
+
+#endif
index 9113d7b33ae001e19c60d6eb23e698042682dd1c..52aaed2b936fb0324c707f801b06a90ce88f60f7 100644 (file)
@@ -22,7 +22,8 @@
 
 #define UARTA_3390             REG_PHYS_ADDR(0x40a900)
 #define UARTA_7250             REG_PHYS_ADDR(0x40b400)
-#define UARTA_7268             REG_PHYS_ADDR(0x40c000)
+#define UARTA_7260             REG_PHYS_ADDR(0x40c000)
+#define UARTA_7268             UARTA_7260
 #define UARTA_7271             UARTA_7268
 #define UARTA_7364             REG_PHYS_ADDR(0x40b000)
 #define UARTA_7366             UARTA_7364
                /* Chip specific detection starts here */
 20:            checkuart(\rp, \rv, 0x33900000, 3390)
 21:            checkuart(\rp, \rv, 0x72500000, 7250)
-22:            checkuart(\rp, \rv, 0x72680000, 7268)
-23:            checkuart(\rp, \rv, 0x72710000, 7271)
-24:            checkuart(\rp, \rv, 0x73640000, 7364)
-25:            checkuart(\rp, \rv, 0x73660000, 7366)
-26:            checkuart(\rp, \rv, 0x07437100, 74371)
-27:            checkuart(\rp, \rv, 0x74390000, 7439)
-28:            checkuart(\rp, \rv, 0x74450000, 7445)
+22:            checkuart(\rp, \rv, 0x72600000, 7260)
+23:            checkuart(\rp, \rv, 0x72680000, 7268)
+24:            checkuart(\rp, \rv, 0x72710000, 7271)
+25:            checkuart(\rp, \rv, 0x73640000, 7364)
+26:            checkuart(\rp, \rv, 0x73660000, 7366)
+27:            checkuart(\rp, \rv, 0x07437100, 74371)
+28:            checkuart(\rp, \rv, 0x74390000, 7439)
+29:            checkuart(\rp, \rv, 0x74450000, 7445)
 
                /* No valid UART found */
 90:            mov     \rp, #0
index 46a76cd6acb628151b3e13389eab557d81d09b80..607f702c2d6276060393ef816361b4d28540c9e4 100644 (file)
@@ -1,23 +1,6 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
-header-y += auxvec.h
-header-y += byteorder.h
-header-y += fcntl.h
-header-y += hwcap.h
-header-y += ioctls.h
-header-y += kvm_para.h
-header-y += mman.h
-header-y += perf_regs.h
-header-y += posix_types.h
-header-y += ptrace.h
-header-y += setup.h
-header-y += sigcontext.h
-header-y += signal.h
-header-y += stat.h
-header-y += statfs.h
-header-y += swab.h
-header-y += unistd.h
 genhdr-y += unistd-common.h
 genhdr-y += unistd-oabi.h
 genhdr-y += unistd-eabi.h
index a88726359e5f149fcb79cdc3c5a65dffc90852bc..5e3c673fa3f4435b027fbc634815be10c26cf39f 100644 (file)
@@ -196,13 +196,17 @@ struct kvm_arch_memory_slot {
 #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
 #define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6
 #define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO  7
+#define KVM_DEV_ARM_VGIC_GRP_ITS_REGS  8
 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT 10
 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \
                        (0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)
 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff
 #define VGIC_LEVEL_INFO_LINE_LEVEL     0
 
-#define   KVM_DEV_ARM_VGIC_CTRL_INIT    0
+#define   KVM_DEV_ARM_VGIC_CTRL_INIT           0
+#define   KVM_DEV_ARM_ITS_SAVE_TABLES          1
+#define   KVM_DEV_ARM_ITS_RESTORE_TABLES       2
+#define   KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES 3
 
 /* KVM_IRQ_LINE irq field index values */
 #define KVM_ARM_IRQ_TYPE_SHIFT         24
index 2f0e07735d1d4715234d94d6bd0e0d7c49f442c0..b259956365a06b63c923f96946f851531708264c 100644 (file)
@@ -597,25 +597,6 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
        return start;
 }
 
-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
-                       enum pci_mmap_state mmap_state, int write_combine)
-{
-       if (mmap_state == pci_mmap_io)
-               return -EINVAL;
-
-       /*
-        * Mark this as IO
-        */
-       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
-       if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
-                            vma->vm_end - vma->vm_start,
-                            vma->vm_page_prot))
-               return -EAGAIN;
-
-       return 0;
-}
-
 void __init pci_map_io_early(unsigned long pfn)
 {
        struct map_desc pci_io_desc = {
index 414e60ed02573d06af2a94ac576cdd75df027d11..833c991075a18decd0fc64f06d1b188bb5c19f37 100644 (file)
@@ -21,6 +21,7 @@
 #include <asm/opcodes.h>
 #include <asm/ftrace.h>
 #include <asm/insn.h>
+#include <asm/set_memory.h>
 
 #ifdef CONFIG_THUMB2_KERNEL
 #define        NOP             0xf85deb04      /* pop.w {lr} */
index 9232caee70604c686e07b7aef4c21598c7196fa4..1bb4c40a3135ff946909a2f423d6295e45add671 100644 (file)
@@ -269,7 +269,7 @@ int kgdb_arch_remove_breakpoint(struct kgdb_bkpt *bpt)
 
 /*
  * Register our undef instruction hooks with ARM undef core.
- * We regsiter a hook specifically looking for the KGB break inst
+ * We register a hook specifically looking for the KGB break inst
  * and we handle the normal undef case within the do_undefinstr
  * handler.
  */
index b18c1ea56bed69b8dd6ffbda657315bdd94230c6..15495887ca14eedc883daa60b9a9a034913f0c3e 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/mach-types.h>
 #include <asm/smp_plat.h>
 #include <asm/system_misc.h>
+#include <asm/set_memory.h>
 
 extern void relocate_new_kernel(void);
 extern const unsigned int relocate_new_kernel_size;
index 80254b47dc3420ec11cb6611f645d5b1faf55b66..3ff571c2c71ce42f47f31730a477f787f4ff91ee 100644 (file)
 #ifdef CONFIG_MMU
 void *module_alloc(unsigned long size)
 {
-       void *p = __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
-                               GFP_KERNEL, PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE,
+       gfp_t gfp_mask = GFP_KERNEL;
+       void *p;
+
+       /* Silence the initial allocation */
+       if (IS_ENABLED(CONFIG_ARM_MODULE_PLTS))
+               gfp_mask |= __GFP_NOWARN;
+
+       p = __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
+                               gfp_mask, PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE,
                                __builtin_return_address(0));
        if (!IS_ENABLED(CONFIG_ARM_MODULE_PLTS) || p)
                return p;
index 7b3670c2ae7bdf8165652281c7ee023ad0b5146c..d9beee652d36cbba48d0900e896f46b82df5c39e 100644 (file)
@@ -18,9 +18,12 @@ KVM := ../../../virt/kvm
 kvm-arm-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o $(KVM)/vfio.o
 
 obj-$(CONFIG_KVM_ARM_HOST) += hyp/
+
 obj-y += kvm-arm.o init.o interrupts.o
-obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o
-obj-y += coproc.o coproc_a15.o coproc_a7.o mmio.o psci.o perf.o vgic-v3-coproc.o
+obj-y += handle_exit.o guest.o emulate.o reset.o
+obj-y += coproc.o coproc_a15.o coproc_a7.o   vgic-v3-coproc.o
+obj-y += $(KVM)/arm/arm.o $(KVM)/arm/mmu.o $(KVM)/arm/mmio.o
+obj-y += $(KVM)/arm/psci.o $(KVM)/arm/perf.o
 obj-y += $(KVM)/arm/aarch32.o
 
 obj-y += $(KVM)/arm/vgic/vgic.o
index 2c14b69511e981816861e16b31ed18dce0f2360f..6d1d2e26dfe5d8cd83e1a89a106f8028eed65c8e 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/vfp.h>
 #include "../vfp/vfpinstr.h"
 
+#define CREATE_TRACE_POINTS
 #include "trace.h"
 #include "coproc.h"
 
@@ -111,12 +112,6 @@ int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run)
        return 1;
 }
 
-int kvm_handle_cp14_access(struct kvm_vcpu *vcpu, struct kvm_run *run)
-{
-       kvm_inject_undefined(vcpu);
-       return 1;
-}
-
 static void reset_mpidr(struct kvm_vcpu *vcpu, const struct coproc_reg *r)
 {
        /*
@@ -284,7 +279,7 @@ static bool access_gic_sre(struct kvm_vcpu *vcpu,
  * must always support PMCCNTR (the cycle counter): we just RAZ/WI for
  * all PM registers, which doesn't crash the guest kernel at least.
  */
-static bool pm_fake(struct kvm_vcpu *vcpu,
+static bool trap_raz_wi(struct kvm_vcpu *vcpu,
                    const struct coproc_params *p,
                    const struct coproc_reg *r)
 {
@@ -294,19 +289,19 @@ static bool pm_fake(struct kvm_vcpu *vcpu,
                return read_zero(vcpu, p);
 }
 
-#define access_pmcr pm_fake
-#define access_pmcntenset pm_fake
-#define access_pmcntenclr pm_fake
-#define access_pmovsr pm_fake
-#define access_pmselr pm_fake
-#define access_pmceid0 pm_fake
-#define access_pmceid1 pm_fake
-#define access_pmccntr pm_fake
-#define access_pmxevtyper pm_fake
-#define access_pmxevcntr pm_fake
-#define access_pmuserenr pm_fake
-#define access_pmintenset pm_fake
-#define access_pmintenclr pm_fake
+#define access_pmcr trap_raz_wi
+#define access_pmcntenset trap_raz_wi
+#define access_pmcntenclr trap_raz_wi
+#define access_pmovsr trap_raz_wi
+#define access_pmselr trap_raz_wi
+#define access_pmceid0 trap_raz_wi
+#define access_pmceid1 trap_raz_wi
+#define access_pmccntr trap_raz_wi
+#define access_pmxevtyper trap_raz_wi
+#define access_pmxevcntr trap_raz_wi
+#define access_pmuserenr trap_raz_wi
+#define access_pmintenset trap_raz_wi
+#define access_pmintenclr trap_raz_wi
 
 /* Architected CP15 registers.
  * CRn denotes the primary register number, but is copied to the CRm in the
@@ -532,12 +527,7 @@ static int emulate_cp15(struct kvm_vcpu *vcpu,
        return 1;
 }
 
-/**
- * kvm_handle_cp15_64 -- handles a mrrc/mcrr trap on a guest CP15 access
- * @vcpu: The VCPU pointer
- * @run:  The kvm_run struct
- */
-int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
+static struct coproc_params decode_64bit_hsr(struct kvm_vcpu *vcpu)
 {
        struct coproc_params params;
 
@@ -551,9 +541,38 @@ int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
        params.Rt2 = (kvm_vcpu_get_hsr(vcpu) >> 10) & 0xf;
        params.CRm = 0;
 
+       return params;
+}
+
+/**
+ * kvm_handle_cp15_64 -- handles a mrrc/mcrr trap on a guest CP15 access
+ * @vcpu: The VCPU pointer
+ * @run:  The kvm_run struct
+ */
+int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+       struct coproc_params params = decode_64bit_hsr(vcpu);
+
        return emulate_cp15(vcpu, &params);
 }
 
+/**
+ * kvm_handle_cp14_64 -- handles a mrrc/mcrr trap on a guest CP14 access
+ * @vcpu: The VCPU pointer
+ * @run:  The kvm_run struct
+ */
+int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+       struct coproc_params params = decode_64bit_hsr(vcpu);
+
+       /* raz_wi cp14 */
+       trap_raz_wi(vcpu, &params, NULL);
+
+       /* handled */
+       kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
+       return 1;
+}
+
 static void reset_coproc_regs(struct kvm_vcpu *vcpu,
                              const struct coproc_reg *table, size_t num)
 {
@@ -564,12 +583,7 @@ static void reset_coproc_regs(struct kvm_vcpu *vcpu,
                        table[i].reset(vcpu, &table[i]);
 }
 
-/**
- * kvm_handle_cp15_32 -- handles a mrc/mcr trap on a guest CP15 access
- * @vcpu: The VCPU pointer
- * @run:  The kvm_run struct
- */
-int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
+static struct coproc_params decode_32bit_hsr(struct kvm_vcpu *vcpu)
 {
        struct coproc_params params;
 
@@ -583,9 +597,37 @@ int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
        params.Op2 = (kvm_vcpu_get_hsr(vcpu) >> 17) & 0x7;
        params.Rt2 = 0;
 
+       return params;
+}
+
+/**
+ * kvm_handle_cp15_32 -- handles a mrc/mcr trap on a guest CP15 access
+ * @vcpu: The VCPU pointer
+ * @run:  The kvm_run struct
+ */
+int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+       struct coproc_params params = decode_32bit_hsr(vcpu);
        return emulate_cp15(vcpu, &params);
 }
 
+/**
+ * kvm_handle_cp14_32 -- handles a mrc/mcr trap on a guest CP14 access
+ * @vcpu: The VCPU pointer
+ * @run:  The kvm_run struct
+ */
+int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+       struct coproc_params params = decode_32bit_hsr(vcpu);
+
+       /* raz_wi cp14 */
+       trap_raz_wi(vcpu, &params, NULL);
+
+       /* handled */
+       kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
+       return 1;
+}
+
 /******************************************************************************
  * Userspace API
  *****************************************************************************/
index 5fd7968cdae9efb4f68968eca13afebffb8c0be4..f86a9aaef462c6d861a80ae60bb26492ddb28d66 100644 (file)
@@ -95,9 +95,9 @@ static exit_handle_fn arm_exit_handlers[] = {
        [HSR_EC_WFI]            = kvm_handle_wfx,
        [HSR_EC_CP15_32]        = kvm_handle_cp15_32,
        [HSR_EC_CP15_64]        = kvm_handle_cp15_64,
-       [HSR_EC_CP14_MR]        = kvm_handle_cp14_access,
+       [HSR_EC_CP14_MR]        = kvm_handle_cp14_32,
        [HSR_EC_CP14_LS]        = kvm_handle_cp14_load_store,
-       [HSR_EC_CP14_64]        = kvm_handle_cp14_access,
+       [HSR_EC_CP14_64]        = kvm_handle_cp14_64,
        [HSR_EC_CP_0_13]        = kvm_handle_cp_0_13_access,
        [HSR_EC_CP10_ID]        = kvm_handle_cp10_id,
        [HSR_EC_HVC]            = handle_hvc,
index 3023bb530edf160ddbbe974e820227950a06ac31..8679405b0b2bb1e7a23232554bf26f71d7ae75ac 100644 (file)
@@ -2,6 +2,8 @@
 # Makefile for Kernel-based Virtual Machine module, HYP part
 #
 
+ccflags-y += -fno-stack-protector
+
 KVM=../../../../virt/kvm
 
 obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/vgic-v2-sr.o
index 92678b7bd046d74b2cb0ad6df34978c3a9e1c112..624a510d31df4095701387da09b4b9a27bd09a17 100644 (file)
@@ -48,7 +48,9 @@ static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu, u32 *fpexc_host)
        write_sysreg(HSTR_T(15), HSTR);
        write_sysreg(HCPTR_TTA | HCPTR_TCP(10) | HCPTR_TCP(11), HCPTR);
        val = read_sysreg(HDCR);
-       write_sysreg(val | HDCR_TPM | HDCR_TPMCR, HDCR);
+       val |= HDCR_TPM | HDCR_TPMCR; /* trap performance monitors */
+       val |= HDCR_TDRA | HDCR_TDOSA | HDCR_TDA; /* trap debug regs */
+       write_sysreg(val, HDCR);
 }
 
 static void __hyp_text __deactivate_traps(struct kvm_vcpu *vcpu)
index c25a88598eb04d02dde1085a20427eb123a18248..b0d10648c4864b22c4566884d252d2554e2ceeb6 100644 (file)
-#if !defined(_TRACE_KVM_H) || defined(TRACE_HEADER_MULTI_READ)
-#define _TRACE_KVM_H
+#if !defined(_TRACE_ARM_KVM_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_ARM_KVM_H
 
 #include <linux/tracepoint.h>
 
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM kvm
 
-/*
- * Tracepoints for entry/exit to guest
- */
-TRACE_EVENT(kvm_entry,
-       TP_PROTO(unsigned long vcpu_pc),
-       TP_ARGS(vcpu_pc),
-
-       TP_STRUCT__entry(
-               __field(        unsigned long,  vcpu_pc         )
-       ),
-
-       TP_fast_assign(
-               __entry->vcpu_pc                = vcpu_pc;
-       ),
-
-       TP_printk("PC: 0x%08lx", __entry->vcpu_pc)
-);
-
-TRACE_EVENT(kvm_exit,
-       TP_PROTO(int idx, unsigned int exit_reason, unsigned long vcpu_pc),
-       TP_ARGS(idx, exit_reason, vcpu_pc),
-
-       TP_STRUCT__entry(
-               __field(        int,            idx             )
-               __field(        unsigned int,   exit_reason     )
-               __field(        unsigned long,  vcpu_pc         )
-       ),
-
-       TP_fast_assign(
-               __entry->idx                    = idx;
-               __entry->exit_reason            = exit_reason;
-               __entry->vcpu_pc                = vcpu_pc;
-       ),
-
-       TP_printk("%s: HSR_EC: 0x%04x (%s), PC: 0x%08lx",
-                 __print_symbolic(__entry->idx, kvm_arm_exception_type),
-                 __entry->exit_reason,
-                 __print_symbolic(__entry->exit_reason, kvm_arm_exception_class),
-                 __entry->vcpu_pc)
-);
-
-TRACE_EVENT(kvm_guest_fault,
-       TP_PROTO(unsigned long vcpu_pc, unsigned long hsr,
-                unsigned long hxfar,
-                unsigned long long ipa),
-       TP_ARGS(vcpu_pc, hsr, hxfar, ipa),
-
-       TP_STRUCT__entry(
-               __field(        unsigned long,  vcpu_pc         )
-               __field(        unsigned long,  hsr             )
-               __field(        unsigned long,  hxfar           )
-               __field(   unsigned long long,  ipa             )
-       ),
-
-       TP_fast_assign(
-               __entry->vcpu_pc                = vcpu_pc;
-               __entry->hsr                    = hsr;
-               __entry->hxfar                  = hxfar;
-               __entry->ipa                    = ipa;
-       ),
-
-       TP_printk("ipa %#llx, hsr %#08lx, hxfar %#08lx, pc %#08lx",
-                 __entry->ipa, __entry->hsr,
-                 __entry->hxfar, __entry->vcpu_pc)
-);
-
-TRACE_EVENT(kvm_access_fault,
-       TP_PROTO(unsigned long ipa),
-       TP_ARGS(ipa),
-
-       TP_STRUCT__entry(
-               __field(        unsigned long,  ipa             )
-       ),
-
-       TP_fast_assign(
-               __entry->ipa            = ipa;
-       ),
-
-       TP_printk("IPA: %lx", __entry->ipa)
-);
-
-TRACE_EVENT(kvm_irq_line,
-       TP_PROTO(unsigned int type, int vcpu_idx, int irq_num, int level),
-       TP_ARGS(type, vcpu_idx, irq_num, level),
-
-       TP_STRUCT__entry(
-               __field(        unsigned int,   type            )
-               __field(        int,            vcpu_idx        )
-               __field(        int,            irq_num         )
-               __field(        int,            level           )
-       ),
-
-       TP_fast_assign(
-               __entry->type           = type;
-               __entry->vcpu_idx       = vcpu_idx;
-               __entry->irq_num        = irq_num;
-               __entry->level          = level;
-       ),
-
-       TP_printk("Inject %s interrupt (%d), vcpu->idx: %d, num: %d, level: %d",
-                 (__entry->type == KVM_ARM_IRQ_TYPE_CPU) ? "CPU" :
-                 (__entry->type == KVM_ARM_IRQ_TYPE_PPI) ? "VGIC PPI" :
-                 (__entry->type == KVM_ARM_IRQ_TYPE_SPI) ? "VGIC SPI" : "UNKNOWN",
-                 __entry->type, __entry->vcpu_idx, __entry->irq_num, __entry->level)
-);
-
-TRACE_EVENT(kvm_mmio_emulate,
-       TP_PROTO(unsigned long vcpu_pc, unsigned long instr,
-                unsigned long cpsr),
-       TP_ARGS(vcpu_pc, instr, cpsr),
-
-       TP_STRUCT__entry(
-               __field(        unsigned long,  vcpu_pc         )
-               __field(        unsigned long,  instr           )
-               __field(        unsigned long,  cpsr            )
-       ),
-
-       TP_fast_assign(
-               __entry->vcpu_pc                = vcpu_pc;
-               __entry->instr                  = instr;
-               __entry->cpsr                   = cpsr;
-       ),
-
-       TP_printk("Emulate MMIO at: 0x%08lx (instr: %08lx, cpsr: %08lx)",
-                 __entry->vcpu_pc, __entry->instr, __entry->cpsr)
-);
-
 /* Architecturally implementation defined CP15 register access */
 TRACE_EVENT(kvm_emulate_cp15_imp,
        TP_PROTO(unsigned long Op1, unsigned long Rt1, unsigned long CRn,
@@ -181,87 +54,6 @@ TRACE_EVENT(kvm_wfx,
                __entry->is_wfe ? 'e' : 'i', __entry->vcpu_pc)
 );
 
-TRACE_EVENT(kvm_unmap_hva,
-       TP_PROTO(unsigned long hva),
-       TP_ARGS(hva),
-
-       TP_STRUCT__entry(
-               __field(        unsigned long,  hva             )
-       ),
-
-       TP_fast_assign(
-               __entry->hva            = hva;
-       ),
-
-       TP_printk("mmu notifier unmap hva: %#08lx", __entry->hva)
-);
-
-TRACE_EVENT(kvm_unmap_hva_range,
-       TP_PROTO(unsigned long start, unsigned long end),
-       TP_ARGS(start, end),
-
-       TP_STRUCT__entry(
-               __field(        unsigned long,  start           )
-               __field(        unsigned long,  end             )
-       ),
-
-       TP_fast_assign(
-               __entry->start          = start;
-               __entry->end            = end;
-       ),
-
-       TP_printk("mmu notifier unmap range: %#08lx -- %#08lx",
-                 __entry->start, __entry->end)
-);
-
-TRACE_EVENT(kvm_set_spte_hva,
-       TP_PROTO(unsigned long hva),
-       TP_ARGS(hva),
-
-       TP_STRUCT__entry(
-               __field(        unsigned long,  hva             )
-       ),
-
-       TP_fast_assign(
-               __entry->hva            = hva;
-       ),
-
-       TP_printk("mmu notifier set pte hva: %#08lx", __entry->hva)
-);
-
-TRACE_EVENT(kvm_age_hva,
-       TP_PROTO(unsigned long start, unsigned long end),
-       TP_ARGS(start, end),
-
-       TP_STRUCT__entry(
-               __field(        unsigned long,  start           )
-               __field(        unsigned long,  end             )
-       ),
-
-       TP_fast_assign(
-               __entry->start          = start;
-               __entry->end            = end;
-       ),
-
-       TP_printk("mmu notifier age hva: %#08lx -- %#08lx",
-                 __entry->start, __entry->end)
-);
-
-TRACE_EVENT(kvm_test_age_hva,
-       TP_PROTO(unsigned long hva),
-       TP_ARGS(hva),
-
-       TP_STRUCT__entry(
-               __field(        unsigned long,  hva             )
-       ),
-
-       TP_fast_assign(
-               __entry->hva            = hva;
-       ),
-
-       TP_printk("mmu notifier test age hva: %#08lx", __entry->hva)
-);
-
 TRACE_EVENT(kvm_hvc,
        TP_PROTO(unsigned long vcpu_pc, unsigned long r0, unsigned long imm),
        TP_ARGS(vcpu_pc, r0, imm),
@@ -282,49 +74,10 @@ TRACE_EVENT(kvm_hvc,
                  __entry->vcpu_pc, __entry->r0, __entry->imm)
 );
 
-TRACE_EVENT(kvm_set_way_flush,
-           TP_PROTO(unsigned long vcpu_pc, bool cache),
-           TP_ARGS(vcpu_pc, cache),
-
-           TP_STRUCT__entry(
-                   __field(    unsigned long,  vcpu_pc         )
-                   __field(    bool,           cache           )
-           ),
-
-           TP_fast_assign(
-                   __entry->vcpu_pc            = vcpu_pc;
-                   __entry->cache              = cache;
-           ),
-
-           TP_printk("S/W flush at 0x%016lx (cache %s)",
-                     __entry->vcpu_pc, __entry->cache ? "on" : "off")
-);
-
-TRACE_EVENT(kvm_toggle_cache,
-           TP_PROTO(unsigned long vcpu_pc, bool was, bool now),
-           TP_ARGS(vcpu_pc, was, now),
-
-           TP_STRUCT__entry(
-                   __field(    unsigned long,  vcpu_pc         )
-                   __field(    bool,           was             )
-                   __field(    bool,           now             )
-           ),
-
-           TP_fast_assign(
-                   __entry->vcpu_pc            = vcpu_pc;
-                   __entry->was                = was;
-                   __entry->now                = now;
-           ),
-
-           TP_printk("VM op at 0x%016lx (cache was %s, now %s)",
-                     __entry->vcpu_pc, __entry->was ? "on" : "off",
-                     __entry->now ? "on" : "off")
-);
-
-#endif /* _TRACE_KVM_H */
+#endif /* _TRACE_ARM_KVM_H */
 
 #undef TRACE_INCLUDE_PATH
-#define TRACE_INCLUDE_PATH arch/arm/kvm
+#define TRACE_INCLUDE_PATH .
 #undef TRACE_INCLUDE_FILE
 #define TRACE_INCLUDE_FILE trace
 
index c5bbf8bb8c0f1653ce54cbd44835eae42a12948a..cfd8f60a9268f85f30048e92949c0d13051e71d8 100644 (file)
@@ -1,7 +1,6 @@
 #
 # Makefile for the linux kernel.
 #
-obj-y          := soc.o
 
 # CPU-specific support
 obj-$(CONFIG_SOC_AT91RM9200)   += at91rm9200.o
@@ -18,3 +17,36 @@ endif
 ifeq ($(CONFIG_PM_DEBUG),y)
 CFLAGS_pm.o += -DDEBUG
 endif
+
+# Default sed regexp - multiline due to syntax constraints
+define sed-y
+       "/^->/{s:->#\(.*\):/* \1 */:; \
+       s:^->\([^ ]*\) [\$$#]*\([-0-9]*\) \(.*\):#define \1 \2 /* \3 */:; \
+       s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \
+       s:->::; p;}"
+endef
+
+# Use filechk to avoid rebuilds when a header changes, but the resulting file
+# does not
+define filechk_offsets
+       (set -e; \
+        echo "#ifndef $2"; \
+        echo "#define $2"; \
+        echo "/*"; \
+        echo " * DO NOT MODIFY."; \
+        echo " *"; \
+        echo " * This file was generated by Kbuild"; \
+        echo " */"; \
+        echo ""; \
+        sed -ne $(sed-y); \
+        echo ""; \
+        echo "#endif" )
+endef
+
+arch/arm/mach-at91/pm_data-offsets.s: arch/arm/mach-at91/pm_data-offsets.c
+       $(call if_changed_dep,cc_s_c)
+
+include/generated/at91_pm_data-offsets.h: arch/arm/mach-at91/pm_data-offsets.s FORCE
+       $(call filechk,offsets,__PM_DATA_OFFSETS_H__)
+
+arch/arm/mach-at91/pm_suspend.o: include/generated/at91_pm_data-offsets.h
index d068ec3cd1f6dbaf7c2e9ff99ac5e22f82fb6e81..656ad409a2533ad832611ade5e0149d0fd80aafb 100644 (file)
 #include <asm/mach/arch.h>
 
 #include "generic.h"
-#include "soc.h"
-
-static const struct at91_soc rm9200_socs[] = {
-       AT91_SOC(AT91RM9200_CIDR_MATCH, 0, "at91rm9200 BGA", "at91rm9200"),
-       { /* sentinel */ },
-};
 
 static void __init at91rm9200_dt_device_init(void)
 {
-       struct soc_device *soc;
-       struct device *soc_dev = NULL;
-
-       soc = at91_soc_init(rm9200_socs);
-       if (soc != NULL)
-               soc_dev = soc_device_to_device(soc);
-
-       of_platform_default_populate(NULL, NULL, soc_dev);
+       of_platform_default_populate(NULL, NULL, NULL);
 
        at91rm9200_pm_init();
 }
index ba28e9cc584d9a336eb5561599525d32cfc075fe..3dbdef4d3cbf5a5f979046abcf6de8241365ae71 100644 (file)
 #include <asm/system_misc.h>
 
 #include "generic.h"
-#include "soc.h"
 
-static const struct at91_soc at91sam9_socs[] = {
-       AT91_SOC(AT91SAM9260_CIDR_MATCH, 0, "at91sam9260", NULL),
-       AT91_SOC(AT91SAM9261_CIDR_MATCH, 0, "at91sam9261", NULL),
-       AT91_SOC(AT91SAM9263_CIDR_MATCH, 0, "at91sam9263", NULL),
-       AT91_SOC(AT91SAM9G20_CIDR_MATCH, 0, "at91sam9g20", NULL),
-       AT91_SOC(AT91SAM9RL64_CIDR_MATCH, 0, "at91sam9rl64", NULL),
-       AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9M11_EXID_MATCH,
-                "at91sam9m11", "at91sam9g45"),
-       AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9M10_EXID_MATCH,
-                "at91sam9m10", "at91sam9g45"),
-       AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9G46_EXID_MATCH,
-                "at91sam9g46", "at91sam9g45"),
-       AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9G45_EXID_MATCH,
-                "at91sam9g45", "at91sam9g45"),
-       AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9G15_EXID_MATCH,
-                "at91sam9g15", "at91sam9x5"),
-       AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9G35_EXID_MATCH,
-                "at91sam9g35", "at91sam9x5"),
-       AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9X35_EXID_MATCH,
-                "at91sam9x35", "at91sam9x5"),
-       AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9G25_EXID_MATCH,
-                "at91sam9g25", "at91sam9x5"),
-       AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9X25_EXID_MATCH,
-                "at91sam9x25", "at91sam9x5"),
-       AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91SAM9CN12_EXID_MATCH,
-                "at91sam9cn12", "at91sam9n12"),
-       AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91SAM9N12_EXID_MATCH,
-                "at91sam9n12", "at91sam9n12"),
-       AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91SAM9CN11_EXID_MATCH,
-                "at91sam9cn11", "at91sam9n12"),
-       AT91_SOC(AT91SAM9XE128_CIDR_MATCH, 0, "at91sam9xe128", "at91sam9xe128"),
-       AT91_SOC(AT91SAM9XE256_CIDR_MATCH, 0, "at91sam9xe256", "at91sam9xe256"),
-       AT91_SOC(AT91SAM9XE512_CIDR_MATCH, 0, "at91sam9xe512", "at91sam9xe512"),
-       { /* sentinel */ },
-};
-
-static void __init at91sam9_common_init(void)
+static void __init at91sam9_init(void)
 {
-       struct soc_device *soc;
-       struct device *soc_dev = NULL;
-
-       soc = at91_soc_init(at91sam9_socs);
-       if (soc != NULL)
-               soc_dev = soc_device_to_device(soc);
+       of_platform_default_populate(NULL, NULL, NULL);
 
-       of_platform_default_populate(NULL, NULL, soc_dev);
-}
-
-static void __init at91sam9_dt_device_init(void)
-{
-       at91sam9_common_init();
-       at91sam9260_pm_init();
+       at91sam9_pm_init();
 }
 
 static const char *const at91_dt_board_compat[] __initconst = {
@@ -77,41 +29,6 @@ static const char *const at91_dt_board_compat[] __initconst = {
 
 DT_MACHINE_START(at91sam_dt, "Atmel AT91SAM9")
        /* Maintainer: Atmel */
-       .init_machine   = at91sam9_dt_device_init,
+       .init_machine   = at91sam9_init,
        .dt_compat      = at91_dt_board_compat,
 MACHINE_END
-
-static void __init at91sam9g45_dt_device_init(void)
-{
-       at91sam9_common_init();
-       at91sam9g45_pm_init();
-}
-
-static const char *const at91sam9g45_board_compat[] __initconst = {
-       "atmel,at91sam9g45",
-       NULL
-};
-
-DT_MACHINE_START(at91sam9g45_dt, "Atmel AT91SAM9G45")
-       /* Maintainer: Atmel */
-       .init_machine   = at91sam9g45_dt_device_init,
-       .dt_compat      = at91sam9g45_board_compat,
-MACHINE_END
-
-static void __init at91sam9x5_dt_device_init(void)
-{
-       at91sam9_common_init();
-       at91sam9x5_pm_init();
-}
-
-static const char *const at91sam9x5_board_compat[] __initconst = {
-       "atmel,at91sam9x5",
-       "atmel,at91sam9n12",
-       NULL
-};
-
-DT_MACHINE_START(at91sam9x5_dt, "Atmel AT91SAM9")
-       /* Maintainer: Atmel */
-       .init_machine   = at91sam9x5_dt_device_init,
-       .dt_compat      = at91sam9x5_board_compat,
-MACHINE_END
index 28ca57a2060f060f4b86b5c5d74a82c76e4a7371..f1ead0f13c19e053a1ffaddd9c031b6f9c9fb978 100644 (file)
 
 #ifdef CONFIG_PM
 extern void __init at91rm9200_pm_init(void);
-extern void __init at91sam9260_pm_init(void);
-extern void __init at91sam9g45_pm_init(void);
-extern void __init at91sam9x5_pm_init(void);
+extern void __init at91sam9_pm_init(void);
 extern void __init sama5_pm_init(void);
 #else
 static inline void __init at91rm9200_pm_init(void) { }
-static inline void __init at91sam9260_pm_init(void) { }
-static inline void __init at91sam9g45_pm_init(void) { }
-static inline void __init at91sam9x5_pm_init(void) { }
+static inline void __init at91sam9_pm_init(void) { }
 static inline void __init sama5_pm_init(void) { }
 #endif
 
index a277981f414d8dd9433569c529068f206daab81f..283e79ab587de91405e0b579fb16d202ca5072b7 100644 (file)
  * (at your option) any later version.
  */
 
-#include <linux/gpio.h>
-#include <linux/suspend.h>
-#include <linux/sched.h>
-#include <linux/proc_fs.h>
 #include <linux/genalloc.h>
-#include <linux/interrupt.h>
-#include <linux/sysfs.h>
-#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/of_address.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
-#include <linux/of_address.h>
-#include <linux/platform_device.h>
-#include <linux/platform_data/atmel.h>
-#include <linux/io.h>
+#include <linux/suspend.h>
+
 #include <linux/clk/at91_pmc.h>
 
-#include <asm/irq.h>
-#include <linux/atomic.h>
-#include <asm/mach/time.h>
-#include <asm/mach/irq.h>
-#include <asm/fncpy.h>
 #include <asm/cacheflush.h>
+#include <asm/fncpy.h>
 #include <asm/system_misc.h>
 
 #include "generic.h"
 #include "pm.h"
 
-static void __iomem *pmc;
-
 /*
  * FIXME: this is needed to communicate between the pinctrl driver and
  * the PM implementation in the machine. Possibly part of the PM
@@ -50,12 +37,13 @@ extern void at91_pinctrl_gpio_suspend(void);
 extern void at91_pinctrl_gpio_resume(void);
 #endif
 
-static struct {
-       unsigned long uhp_udp_mask;
-       int memctrl;
-} at91_pm_data;
+static struct at91_pm_data pm_data;
 
-static void __iomem *at91_ramc_base[2];
+#define at91_ramc_read(id, field) \
+       __raw_readl(pm_data.ramc[id] + field)
+
+#define at91_ramc_write(id, field, value) \
+       __raw_writel(value, pm_data.ramc[id] + field)
 
 static int at91_pm_valid_state(suspend_state_t state)
 {
@@ -91,10 +79,10 @@ static int at91_pm_verify_clocks(void)
        unsigned long scsr;
        int i;
 
-       scsr = readl(pmc + AT91_PMC_SCSR);
+       scsr = readl(pm_data.pmc + AT91_PMC_SCSR);
 
        /* USB must not be using PLLB */
-       if ((scsr & at91_pm_data.uhp_udp_mask) != 0) {
+       if ((scsr & pm_data.uhp_udp_mask) != 0) {
                pr_err("AT91: PM - Suspend-to-RAM with USB still active\n");
                return 0;
        }
@@ -105,7 +93,7 @@ static int at91_pm_verify_clocks(void)
 
                if ((scsr & (AT91_PMC_PCK0 << i)) == 0)
                        continue;
-               css = readl(pmc + AT91_PMC_PCKR(i)) & AT91_PMC_CSS;
+               css = readl(pm_data.pmc + AT91_PMC_PCKR(i)) & AT91_PMC_CSS;
                if (css != AT91_PMC_CSS_SLOW) {
                        pr_err("AT91: PM - Suspend-to-RAM with PCK%d src %d\n", i, css);
                        return 0;
@@ -131,25 +119,18 @@ int at91_suspend_entering_slow_clock(void)
 }
 EXPORT_SYMBOL(at91_suspend_entering_slow_clock);
 
-static void (*at91_suspend_sram_fn)(void __iomem *pmc, void __iomem *ramc0,
-                         void __iomem *ramc1, int memctrl);
-
-extern void at91_pm_suspend_in_sram(void __iomem *pmc, void __iomem *ramc0,
-                           void __iomem *ramc1, int memctrl);
+static void (*at91_suspend_sram_fn)(struct at91_pm_data *);
+extern void at91_pm_suspend_in_sram(struct at91_pm_data *pm_data);
 extern u32 at91_pm_suspend_in_sram_sz;
 
 static void at91_pm_suspend(suspend_state_t state)
 {
-       unsigned int pm_data = at91_pm_data.memctrl;
-
-       pm_data |= (state == PM_SUSPEND_MEM) ?
-                               AT91_PM_MODE(AT91_PM_SLOW_CLOCK) : 0;
+       pm_data.mode = (state == PM_SUSPEND_MEM) ? AT91_PM_SLOW_CLOCK : 0;
 
        flush_cache_all();
        outer_disable();
 
-       at91_suspend_sram_fn(pmc, at91_ramc_base[0],
-                            at91_ramc_base[1], pm_data);
+       at91_suspend_sram_fn(&pm_data);
 
        outer_resume();
 }
@@ -224,12 +205,6 @@ static struct platform_device at91_cpuidle_device = {
        .name = "cpuidle-at91",
 };
 
-static void at91_pm_set_standby(void (*at91_standby)(void))
-{
-       if (at91_standby)
-               at91_cpuidle_device.dev.platform_data = at91_standby;
-}
-
 /*
  * The AT91RM9200 goes into self-refresh mode with this command, and will
  * terminate self-refresh automatically on the next SDRAM access.
@@ -241,20 +216,15 @@ static void at91_pm_set_standby(void (*at91_standby)(void))
  */
 static void at91rm9200_standby(void)
 {
-       u32 lpr = at91_ramc_read(0, AT91_MC_SDRAMC_LPR);
-
        asm volatile(
                "b    1f\n\t"
                ".align    5\n\t"
                "1:  mcr    p15, 0, %0, c7, c10, 4\n\t"
-               "    str    %0, [%1, %2]\n\t"
-               "    str    %3, [%1, %4]\n\t"
+               "    str    %2, [%1, %3]\n\t"
                "    mcr    p15, 0, %0, c7, c0, 4\n\t"
-               "    str    %5, [%1, %2]"
                :
-               : "r" (0), "r" (at91_ramc_base[0]), "r" (AT91_MC_SDRAMC_LPR),
-                 "r" (1), "r" (AT91_MC_SDRAMC_SRR),
-                 "r" (lpr));
+               : "r" (0), "r" (pm_data.ramc[0]),
+                 "r" (1), "r" (AT91_MC_SDRAMC_SRR));
 }
 
 /* We manage both DDRAM/SDRAM controllers, we need more than one value to
@@ -265,12 +235,27 @@ static void at91_ddr_standby(void)
        /* Those two values allow us to delay self-refresh activation
         * to the maximum. */
        u32 lpr0, lpr1 = 0;
+       u32 mdr, saved_mdr0, saved_mdr1 = 0;
        u32 saved_lpr0, saved_lpr1 = 0;
 
-       if (at91_ramc_base[1]) {
+       /* LPDDR1 --> force DDR2 mode during self-refresh */
+       saved_mdr0 = at91_ramc_read(0, AT91_DDRSDRC_MDR);
+       if ((saved_mdr0 & AT91_DDRSDRC_MD) == AT91_DDRSDRC_MD_LOW_POWER_DDR) {
+               mdr = saved_mdr0 & ~AT91_DDRSDRC_MD;
+               mdr |= AT91_DDRSDRC_MD_DDR2;
+               at91_ramc_write(0, AT91_DDRSDRC_MDR, mdr);
+       }
+
+       if (pm_data.ramc[1]) {
                saved_lpr1 = at91_ramc_read(1, AT91_DDRSDRC_LPR);
                lpr1 = saved_lpr1 & ~AT91_DDRSDRC_LPCB;
                lpr1 |= AT91_DDRSDRC_LPCB_SELF_REFRESH;
+               saved_mdr1 = at91_ramc_read(1, AT91_DDRSDRC_MDR);
+               if ((saved_mdr1 & AT91_DDRSDRC_MD) == AT91_DDRSDRC_MD_LOW_POWER_DDR) {
+                       mdr = saved_mdr1 & ~AT91_DDRSDRC_MD;
+                       mdr |= AT91_DDRSDRC_MD_DDR2;
+                       at91_ramc_write(1, AT91_DDRSDRC_MDR, mdr);
+               }
        }
 
        saved_lpr0 = at91_ramc_read(0, AT91_DDRSDRC_LPR);
@@ -279,14 +264,17 @@ static void at91_ddr_standby(void)
 
        /* self-refresh mode now */
        at91_ramc_write(0, AT91_DDRSDRC_LPR, lpr0);
-       if (at91_ramc_base[1])
+       if (pm_data.ramc[1])
                at91_ramc_write(1, AT91_DDRSDRC_LPR, lpr1);
 
        cpu_do_idle();
 
+       at91_ramc_write(0, AT91_DDRSDRC_MDR, saved_mdr0);
        at91_ramc_write(0, AT91_DDRSDRC_LPR, saved_lpr0);
-       if (at91_ramc_base[1])
+       if (pm_data.ramc[1]) {
+               at91_ramc_write(0, AT91_DDRSDRC_MDR, saved_mdr1);
                at91_ramc_write(1, AT91_DDRSDRC_LPR, saved_lpr1);
+       }
 }
 
 static void sama5d3_ddr_standby(void)
@@ -313,7 +301,7 @@ static void at91sam9_sdram_standby(void)
        u32 lpr0, lpr1 = 0;
        u32 saved_lpr0, saved_lpr1 = 0;
 
-       if (at91_ramc_base[1]) {
+       if (pm_data.ramc[1]) {
                saved_lpr1 = at91_ramc_read(1, AT91_SDRAMC_LPR);
                lpr1 = saved_lpr1 & ~AT91_SDRAMC_LPCB;
                lpr1 |= AT91_SDRAMC_LPCB_SELF_REFRESH;
@@ -325,21 +313,33 @@ static void at91sam9_sdram_standby(void)
 
        /* self-refresh mode now */
        at91_ramc_write(0, AT91_SDRAMC_LPR, lpr0);
-       if (at91_ramc_base[1])
+       if (pm_data.ramc[1])
                at91_ramc_write(1, AT91_SDRAMC_LPR, lpr1);
 
        cpu_do_idle();
 
        at91_ramc_write(0, AT91_SDRAMC_LPR, saved_lpr0);
-       if (at91_ramc_base[1])
+       if (pm_data.ramc[1])
                at91_ramc_write(1, AT91_SDRAMC_LPR, saved_lpr1);
 }
 
-static const struct of_device_id const ramc_ids[] __initconst = {
-       { .compatible = "atmel,at91rm9200-sdramc", .data = at91rm9200_standby },
-       { .compatible = "atmel,at91sam9260-sdramc", .data = at91sam9_sdram_standby },
-       { .compatible = "atmel,at91sam9g45-ddramc", .data = at91_ddr_standby },
-       { .compatible = "atmel,sama5d3-ddramc", .data = sama5d3_ddr_standby },
+struct ramc_info {
+       void (*idle)(void);
+       unsigned int memctrl;
+};
+
+static const struct ramc_info ramc_infos[] __initconst = {
+       { .idle = at91rm9200_standby, .memctrl = AT91_MEMCTRL_MC},
+       { .idle = at91sam9_sdram_standby, .memctrl = AT91_MEMCTRL_SDRAMC},
+       { .idle = at91_ddr_standby, .memctrl = AT91_MEMCTRL_DDRSDR},
+       { .idle = sama5d3_ddr_standby, .memctrl = AT91_MEMCTRL_DDRSDR},
+};
+
+static const struct of_device_id ramc_ids[] __initconst = {
+       { .compatible = "atmel,at91rm9200-sdramc", .data = &ramc_infos[0] },
+       { .compatible = "atmel,at91sam9260-sdramc", .data = &ramc_infos[1] },
+       { .compatible = "atmel,at91sam9g45-ddramc", .data = &ramc_infos[2] },
+       { .compatible = "atmel,sama5d3-ddramc", .data = &ramc_infos[3] },
        { /*sentinel*/ }
 };
 
@@ -348,15 +348,18 @@ static __init void at91_dt_ramc(void)
        struct device_node *np;
        const struct of_device_id *of_id;
        int idx = 0;
-       const void *standby = NULL;
+       void *standby = NULL;
+       const struct ramc_info *ramc;
 
        for_each_matching_node_and_match(np, ramc_ids, &of_id) {
-               at91_ramc_base[idx] = of_iomap(np, 0);
-               if (!at91_ramc_base[idx])
+               pm_data.ramc[idx] = of_iomap(np, 0);
+               if (!pm_data.ramc[idx])
                        panic(pr_fmt("unable to map ramc[%d] cpu registers\n"), idx);
 
+               ramc = of_id->data;
                if (!standby)
-                       standby = of_id->data;
+                       standby = ramc->idle;
+               pm_data.memctrl = ramc->memctrl;
 
                idx++;
        }
@@ -369,7 +372,7 @@ static __init void at91_dt_ramc(void)
                return;
        }
 
-       at91_pm_set_standby(standby);
+       at91_cpuidle_device.dev.platform_data = standby;
 }
 
 static void at91rm9200_idle(void)
@@ -378,12 +381,12 @@ static void at91rm9200_idle(void)
         * Disable the processor clock.  The processor will be automatically
         * re-enabled by an interrupt or by a reset.
         */
-       writel(AT91_PMC_PCK, pmc + AT91_PMC_SCDR);
+       writel(AT91_PMC_PCK, pm_data.pmc + AT91_PMC_SCDR);
 }
 
 static void at91sam9_idle(void)
 {
-       writel(AT91_PMC_PCK, pmc + AT91_PMC_SCDR);
+       writel(AT91_PMC_PCK, pm_data.pmc + AT91_PMC_SCDR);
        cpu_do_idle();
 }
 
@@ -433,31 +436,46 @@ static void __init at91_pm_sram_init(void)
                        &at91_pm_suspend_in_sram, at91_pm_suspend_in_sram_sz);
 }
 
+struct pmc_info {
+       unsigned long uhp_udp_mask;
+};
+
+static const struct pmc_info pmc_infos[] __initconst = {
+       { .uhp_udp_mask = AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP },
+       { .uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP },
+       { .uhp_udp_mask = AT91SAM926x_PMC_UHP },
+};
+
 static const struct of_device_id atmel_pmc_ids[] __initconst = {
-       { .compatible = "atmel,at91rm9200-pmc"  },
-       { .compatible = "atmel,at91sam9260-pmc" },
-       { .compatible = "atmel,at91sam9g45-pmc" },
-       { .compatible = "atmel,at91sam9n12-pmc" },
-       { .compatible = "atmel,at91sam9x5-pmc" },
-       { .compatible = "atmel,sama5d3-pmc" },
-       { .compatible = "atmel,sama5d2-pmc" },
+       { .compatible = "atmel,at91rm9200-pmc", .data = &pmc_infos[0] },
+       { .compatible = "atmel,at91sam9260-pmc", .data = &pmc_infos[1] },
+       { .compatible = "atmel,at91sam9g45-pmc", .data = &pmc_infos[2] },
+       { .compatible = "atmel,at91sam9n12-pmc", .data = &pmc_infos[1] },
+       { .compatible = "atmel,at91sam9x5-pmc", .data = &pmc_infos[1] },
+       { .compatible = "atmel,sama5d3-pmc", .data = &pmc_infos[1] },
+       { .compatible = "atmel,sama5d2-pmc", .data = &pmc_infos[1] },
        { /* sentinel */ },
 };
 
 static void __init at91_pm_init(void (*pm_idle)(void))
 {
        struct device_node *pmc_np;
+       const struct of_device_id *of_id;
+       const struct pmc_info *pmc;
 
        if (at91_cpuidle_device.dev.platform_data)
                platform_device_register(&at91_cpuidle_device);
 
-       pmc_np = of_find_matching_node(NULL, atmel_pmc_ids);
-       pmc = of_iomap(pmc_np, 0);
-       if (!pmc) {
+       pmc_np = of_find_matching_node_and_match(NULL, atmel_pmc_ids, &of_id);
+       pm_data.pmc = of_iomap(pmc_np, 0);
+       if (!pm_data.pmc) {
                pr_err("AT91: PM not supported, PMC not found\n");
                return;
        }
 
+       pmc = of_id->data;
+       pm_data.uhp_udp_mask = pmc->uhp_udp_mask;
+
        if (pm_idle)
                arm_pm_idle = pm_idle;
 
@@ -478,40 +496,17 @@ void __init at91rm9200_pm_init(void)
         */
        at91_ramc_write(0, AT91_MC_SDRAMC_LPR, 0);
 
-       at91_pm_data.uhp_udp_mask = AT91RM9200_PMC_UHP | AT91RM9200_PMC_UDP;
-       at91_pm_data.memctrl = AT91_MEMCTRL_MC;
-
        at91_pm_init(at91rm9200_idle);
 }
 
-void __init at91sam9260_pm_init(void)
-{
-       at91_dt_ramc();
-       at91_pm_data.memctrl = AT91_MEMCTRL_SDRAMC;
-       at91_pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP;
-       at91_pm_init(at91sam9_idle);
-}
-
-void __init at91sam9g45_pm_init(void)
-{
-       at91_dt_ramc();
-       at91_pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP;
-       at91_pm_data.memctrl = AT91_MEMCTRL_DDRSDR;
-       at91_pm_init(at91sam9_idle);
-}
-
-void __init at91sam9x5_pm_init(void)
+void __init at91sam9_pm_init(void)
 {
        at91_dt_ramc();
-       at91_pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP;
-       at91_pm_data.memctrl = AT91_MEMCTRL_DDRSDR;
        at91_pm_init(at91sam9_idle);
 }
 
 void __init sama5_pm_init(void)
 {
        at91_dt_ramc();
-       at91_pm_data.uhp_udp_mask = AT91SAM926x_PMC_UHP | AT91SAM926x_PMC_UDP;
-       at91_pm_data.memctrl = AT91_MEMCTRL_DDRSDR;
        at91_pm_init(NULL);
 }
index bf980c6ef2943fec496fb66592020e2409ef840f..fc0f7d048187b68a7e2e504fb143f1d6046ddca6 100644 (file)
 #include <soc/at91/at91sam9_ddrsdr.h>
 #include <soc/at91/at91sam9_sdramc.h>
 
-#ifndef __ASSEMBLY__
-#define at91_ramc_read(id, field) \
-       __raw_readl(at91_ramc_base[id] + field)
-
-#define at91_ramc_write(id, field, value) \
-       __raw_writel(value, at91_ramc_base[id] + field)
-#endif
-
 #define AT91_MEMCTRL_MC                0
 #define AT91_MEMCTRL_SDRAMC    1
 #define AT91_MEMCTRL_DDRSDR    2
 
-#define        AT91_PM_MEMTYPE_MASK    0x0f
-
-#define        AT91_PM_MODE_OFFSET     4
-#define        AT91_PM_MODE_MASK       0x01
-#define        AT91_PM_MODE(x)         (((x) & AT91_PM_MODE_MASK) << AT91_PM_MODE_OFFSET)
-
 #define        AT91_PM_SLOW_CLOCK      0x01
 
+#ifndef __ASSEMBLY__
+struct at91_pm_data {
+       void __iomem *pmc;
+       void __iomem *ramc[2];
+       unsigned long uhp_udp_mask;
+       unsigned int memctrl;
+       unsigned int mode;
+};
+#endif
+
 #endif
diff --git a/arch/arm/mach-at91/pm_data-offsets.c b/arch/arm/mach-at91/pm_data-offsets.c
new file mode 100644 (file)
index 0000000..30302cb
--- /dev/null
@@ -0,0 +1,13 @@
+#include <linux/stddef.h>
+#include <linux/kbuild.h>
+#include "pm.h"
+
+int main(void)
+{
+       DEFINE(PM_DATA_PMC,             offsetof(struct at91_pm_data, pmc));
+       DEFINE(PM_DATA_RAMC0,           offsetof(struct at91_pm_data, ramc[0]));
+       DEFINE(PM_DATA_RAMC1,           offsetof(struct at91_pm_data, ramc[1]));
+       DEFINE(PM_DATA_MEMCTRL, offsetof(struct at91_pm_data, memctrl));
+       DEFINE(PM_DATA_MODE,            offsetof(struct at91_pm_data, mode));
+       return 0;
+}
index a25defda3d226c98469c6150a001266aeec4c2fa..96781daa671a33f15d8939da690eeeed3d44f9f4 100644 (file)
@@ -4,7 +4,7 @@
  *  Copyright (C) 2006 Savin Zlobec
  *
  * AT91SAM9 support:
- *  Copyright (C) 2007 Anti Sullin <anti.sullin@artecdesign.ee
+ *  Copyright (C) 2007 Anti Sullin <anti.sullin@artecdesign.ee>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -14,6 +14,7 @@
 #include <linux/linkage.h>
 #include <linux/clk/at91_pmc.h>
 #include "pm.h"
+#include "generated/at91_pm_data-offsets.h"
 
 #define        SRAMC_SELF_FRESH_ACTIVE         0x01
 #define        SRAMC_SELF_FRESH_EXIT           0x00
@@ -72,13 +73,9 @@ tmp2 .req    r5
        .arm
 
 /*
- * void at91_pm_suspend_in_sram(void __iomem *pmc, void __iomem *sdramc,
- *                     void __iomem *ramc1, int memctrl)
+ * void at91_suspend_sram_fn(struct at91_pm_data*)
  * @input param:
- *     @r0: base address of AT91_PMC
- *     @r1: base address of SDRAM Controller (SDRAM, DDRSDR, or AT91_SYS)
- *     @r2: base address of second SDRAM Controller or 0 if not present
- *     @r3: pm information
+ *     @r0: base address of struct at91_pm_data
  */
 /* at91_pm_suspend_in_sram must be 8-byte aligned per the requirements of fncpy() */
        .align 3
@@ -90,16 +87,16 @@ ENTRY(at91_pm_suspend_in_sram)
        mov     tmp1, #0
        mcr     p15, 0, tmp1, c7, c10, 4
 
-       str     r0, .pmc_base
-       str     r1, .sramc_base
-       str     r2, .sramc1_base
-
-       and     r0, r3, #AT91_PM_MEMTYPE_MASK
-       str     r0, .memtype
-
-       lsr     r0, r3, #AT91_PM_MODE_OFFSET
-       and     r0, r0, #AT91_PM_MODE_MASK
-       str     r0, .pm_mode
+       ldr     tmp1, [r0, #PM_DATA_PMC]
+       str     tmp1, .pmc_base
+       ldr     tmp1, [r0, #PM_DATA_RAMC0]
+       str     tmp1, .sramc_base
+       ldr     tmp1, [r0, #PM_DATA_RAMC1]
+       str     tmp1, .sramc1_base
+       ldr     tmp1, [r0, #PM_DATA_MEMCTRL]
+       str     tmp1, .memtype
+       ldr     tmp1, [r0, #PM_DATA_MODE]
+       str     tmp1, .pm_mode
 
        /* Active the self-refresh mode */
        mov     r0, #SRAMC_SELF_FRESH_ACTIVE
index b272c45b400fe70df69ab46e799fd7dca60efc8b..6d157d0ead8e3d61b474212d538c7a2de86a3b70 100644 (file)
 #include <asm/system_misc.h>
 
 #include "generic.h"
-#include "soc.h"
-
-static const struct at91_soc sama5_socs[] = {
-       AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D21CU_EXID_MATCH,
-                "sama5d21", "sama5d2"),
-       AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D22CU_EXID_MATCH,
-                "sama5d22", "sama5d2"),
-       AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D23CU_EXID_MATCH,
-                "sama5d23", "sama5d2"),
-       AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D24CX_EXID_MATCH,
-                "sama5d24", "sama5d2"),
-       AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D24CU_EXID_MATCH,
-                "sama5d24", "sama5d2"),
-       AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D26CU_EXID_MATCH,
-                "sama5d26", "sama5d2"),
-       AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27CU_EXID_MATCH,
-                "sama5d27", "sama5d2"),
-       AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27CN_EXID_MATCH,
-                "sama5d27", "sama5d2"),
-       AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28CU_EXID_MATCH,
-                "sama5d28", "sama5d2"),
-       AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28CN_EXID_MATCH,
-                "sama5d28", "sama5d2"),
-       AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D31_EXID_MATCH,
-                "sama5d31", "sama5d3"),
-       AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D33_EXID_MATCH,
-                "sama5d33", "sama5d3"),
-       AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D34_EXID_MATCH,
-                "sama5d34", "sama5d3"),
-       AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D35_EXID_MATCH,
-                "sama5d35", "sama5d3"),
-       AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D36_EXID_MATCH,
-                "sama5d36", "sama5d3"),
-       AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D41_EXID_MATCH,
-                "sama5d41", "sama5d4"),
-       AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D42_EXID_MATCH,
-                "sama5d42", "sama5d4"),
-       AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D43_EXID_MATCH,
-                "sama5d43", "sama5d4"),
-       AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D44_EXID_MATCH,
-                "sama5d44", "sama5d4"),
-       { /* sentinel */ },
-};
 
 static void __init sama5_dt_device_init(void)
 {
-       struct soc_device *soc;
-       struct device *soc_dev = NULL;
-
-       soc = at91_soc_init(sama5_socs);
-       if (soc != NULL)
-               soc_dev = soc_device_to_device(soc);
-
-       of_platform_default_populate(NULL, NULL, soc_dev);
+       of_platform_default_populate(NULL, NULL, NULL);
        sama5_pm_init();
 }
 
diff --git a/arch/arm/mach-at91/soc.c b/arch/arm/mach-at91/soc.c
deleted file mode 100644 (file)
index c6fda75..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2015 Atmel
- *
- * Alexandre Belloni <alexandre.belloni@free-electrons.com
- * Boris Brezillon <boris.brezillon@free-electrons.com
- *
- * This file is licensed under the terms of the GNU General Public
- * License version 2.  This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- *
- */
-
-#define pr_fmt(fmt)    "AT91: " fmt
-
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
-#include <linux/of_platform.h>
-#include <linux/slab.h>
-#include <linux/sys_soc.h>
-
-#include "soc.h"
-
-#define AT91_DBGU_CIDR                 0x40
-#define AT91_DBGU_EXID                 0x44
-#define AT91_CHIPID_CIDR               0x00
-#define AT91_CHIPID_EXID               0x04
-#define AT91_CIDR_VERSION(x)           ((x) & 0x1f)
-#define AT91_CIDR_EXT                  BIT(31)
-#define AT91_CIDR_MATCH_MASK           0x7fffffe0
-
-static int __init at91_get_cidr_exid_from_dbgu(u32 *cidr, u32 *exid)
-{
-       struct device_node *np;
-       void __iomem *regs;
-
-       np = of_find_compatible_node(NULL, NULL, "atmel,at91rm9200-dbgu");
-       if (!np)
-               np = of_find_compatible_node(NULL, NULL,
-                                            "atmel,at91sam9260-dbgu");
-       if (!np)
-               return -ENODEV;
-
-       regs = of_iomap(np, 0);
-       of_node_put(np);
-
-       if (!regs) {
-               pr_warn("Could not map DBGU iomem range");
-               return -ENXIO;
-       }
-
-       *cidr = readl(regs + AT91_DBGU_CIDR);
-       *exid = readl(regs + AT91_DBGU_EXID);
-
-       iounmap(regs);
-
-       return 0;
-}
-
-static int __init at91_get_cidr_exid_from_chipid(u32 *cidr, u32 *exid)
-{
-       struct device_node *np;
-       void __iomem *regs;
-
-       np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-chipid");
-       if (!np)
-               return -ENODEV;
-
-       regs = of_iomap(np, 0);
-       of_node_put(np);
-
-       if (!regs) {
-               pr_warn("Could not map DBGU iomem range");
-               return -ENXIO;
-       }
-
-       *cidr = readl(regs + AT91_CHIPID_CIDR);
-       *exid = readl(regs + AT91_CHIPID_EXID);
-
-       iounmap(regs);
-
-       return 0;
-}
-
-struct soc_device * __init at91_soc_init(const struct at91_soc *socs)
-{
-       struct soc_device_attribute *soc_dev_attr;
-       const struct at91_soc *soc;
-       struct soc_device *soc_dev;
-       u32 cidr, exid;
-       int ret;
-
-       /*
-        * With SAMA5D2 and later SoCs, CIDR and EXID registers are no more
-        * in the dbgu device but in the chipid device whose purpose is only
-        * to expose these two registers.
-        */
-       ret = at91_get_cidr_exid_from_dbgu(&cidr, &exid);
-       if (ret)
-               ret = at91_get_cidr_exid_from_chipid(&cidr, &exid);
-       if (ret) {
-               if (ret == -ENODEV)
-                       pr_warn("Could not find identification node");
-               return NULL;
-       }
-
-       for (soc = socs; soc->name; soc++) {
-               if (soc->cidr_match != (cidr & AT91_CIDR_MATCH_MASK))
-                       continue;
-
-               if (!(cidr & AT91_CIDR_EXT) || soc->exid_match == exid)
-                       break;
-       }
-
-       if (!soc->name) {
-               pr_warn("Could not find matching SoC description\n");
-               return NULL;
-       }
-
-       soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
-       if (!soc_dev_attr)
-               return NULL;
-
-       soc_dev_attr->family = soc->family;
-       soc_dev_attr->soc_id = soc->name;
-       soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%X",
-                                          AT91_CIDR_VERSION(cidr));
-       soc_dev = soc_device_register(soc_dev_attr);
-       if (IS_ERR(soc_dev)) {
-               kfree(soc_dev_attr->revision);
-               kfree(soc_dev_attr);
-               pr_warn("Could not register SoC device\n");
-               return NULL;
-       }
-
-       if (soc->family)
-               pr_info("Detected SoC family: %s\n", soc->family);
-       pr_info("Detected SoC: %s, revision %X\n", soc->name,
-               AT91_CIDR_VERSION(cidr));
-
-       return soc_dev;
-}
index a0e66d8200c5cf8f2ea592abf870a32800213fa2..f9389c5910e76bad8353744137a7360a0c549b56 100644 (file)
@@ -198,7 +198,9 @@ config ARCH_BRCMSTB
        select HAVE_ARM_ARCH_TIMER
        select BRCMSTB_L2_IRQ
        select BCM7120_L2_IRQ
+       select ARCH_HAS_HOLES_MEMORYMODEL
        select ARCH_DMA_ADDR_T_64BIT if ARM_LPAE
+       select ZONE_DMA if ARM_LPAE
        select SOC_BRCMSTB
        select SOC_BUS
        help
index cf3f8658f0e5e9849f866e2135f76aa81c11b1cc..a55a7ecf146a277df8c55603837b67d6fdc30a03 100644 (file)
@@ -33,7 +33,7 @@ struct bcm_kona_smc_data {
        unsigned result;
 };
 
-static const struct of_device_id const bcm_kona_smc_ids[] __initconst = {
+static const struct of_device_id bcm_kona_smc_ids[] __initconst = {
        {.compatible = "brcm,kona-smc"},
        {.compatible = "bcm,kona-smc"}, /* deprecated name */
        {},
index 03da3813f1ab631a0f97be7a1d893176820f9b29..7d5a44a06648de2fd8e5e15beef19762d6925e81 100644 (file)
@@ -346,7 +346,7 @@ static struct usb_ohci_pdata cns3xxx_usb_ohci_pdata = {
        .power_off      = csn3xxx_usb_power_off,
 };
 
-static const struct of_dev_auxdata const cns3xxx_auxdata[] __initconst = {
+static const struct of_dev_auxdata cns3xxx_auxdata[] __initconst = {
        { "intel,usb-ehci", CNS3XXX_USB_BASE, "ehci-platform", &cns3xxx_usb_ehci_pdata },
        { "intel,usb-ohci", CNS3XXX_USB_OHCI_BASE, "ohci-platform", &cns3xxx_usb_ohci_pdata },
        { "cavium,cns3420-ahci", CNS3XXX_SATA2_BASE, "ahci", NULL },
index 6f1e1299cab962532016407c1d508b87dded7188..b5625d0092881bbbbb1022de2664c51f2a304844 100644 (file)
@@ -828,6 +828,9 @@ static struct regulator_consumer_supply fixed_supplies[] = {
 
        /* Baseboard 1.8V: 5V -> TPS73701DCQ -> 1.8V */
        REGULATOR_SUPPLY("DVDD", "1-0018"),
+
+       /* UI card 3.3V: 5V -> TPS73701DCQ -> 3.3V */
+       REGULATOR_SUPPLY("vcc", "1-0020"),
 };
 
 /* TPS65070 voltage regulator support */
@@ -1213,6 +1216,7 @@ static struct vpif_subdev_info da850_vpif_capture_sdev_info[] = {
 static struct vpif_capture_config da850_vpif_capture_config = {
        .subdev_info = da850_vpif_capture_sdev_info,
        .subdev_count = ARRAY_SIZE(da850_vpif_capture_sdev_info),
+       .i2c_adapter_id = 1,
        .chan_config[0] = {
                .inputs = da850_ch0_inputs,
                .input_count = ARRAY_SIZE(da850_ch0_inputs),
index 023480b75244a263b35ec1550f2ac1194c2849a2..20f1874a5657e2c4707b7336066acd362707bea2 100644 (file)
@@ -744,7 +744,8 @@ static int davinci_phy_fixup(struct phy_device *phydev)
        return 0;
 }
 
-#define HAS_ATA                IS_ENABLED(CONFIG_BLK_DEV_PALMCHIP_BK3710)
+#define HAS_ATA                (IS_ENABLED(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \
+                        IS_ENABLED(CONFIG_PATA_BK3710))
 
 #define HAS_NOR                IS_ENABLED(CONFIG_MTD_PHYSMAP)
 
index f702d4fc8eb81d47ce02ea93d5472d298723158b..cb176826d1cbe4e0c77b2c955348d6a0adeebd53 100644 (file)
@@ -119,7 +119,8 @@ static struct platform_device davinci_nand_device = {
        },
 };
 
-#define HAS_ATA                IS_ENABLED(CONFIG_BLK_DEV_PALMCHIP_BK3710)
+#define HAS_ATA                (IS_ENABLED(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \
+                        IS_ENABLED(CONFIG_PATA_BK3710))
 
 #ifdef CONFIG_I2C
 /* CPLD Register 0 bits to control ATA */
index 0a7838852649945bf634815db383c66fe536a5fc..0c02aaad0539b025fbf81135e7977c92cfaa9b45 100644 (file)
@@ -163,7 +163,8 @@ static struct davinci_mmc_config davinci_ntosd2_mmc_config = {
        .wires          = 4,
 };
 
-#define HAS_ATA                IS_ENABLED(CONFIG_BLK_DEV_PALMCHIP_BK3710)
+#define HAS_ATA                (IS_ENABLED(CONFIG_BLK_DEV_PALMCHIP_BK3710) || \
+                        IS_ENABLED(CONFIG_PATA_BK3710))
 
 #define HAS_NAND       IS_ENABLED(CONFIG_MTD_NAND_DAVINCI)
 
index 073c458d0c67a71216de7177241e2157e975b4f3..bd88470f3e5c47a2b0979aa500ebda094e5c0314 100644 (file)
@@ -304,6 +304,11 @@ static struct clk usb20_clk = {
        .gpsc           = 1,
 };
 
+static struct clk cppi41_clk = {
+       .name           = "cppi41",
+       .parent         = &usb20_clk,
+};
+
 static struct clk aemif_clk = {
        .name           = "aemif",
        .parent         = &pll0_sysclk3,
@@ -413,6 +418,7 @@ static struct clk_lookup da830_clks[] = {
        CLK("davinci-mcasp.1",  NULL,           &mcasp1_clk),
        CLK("davinci-mcasp.2",  NULL,           &mcasp2_clk),
        CLK("musb-da8xx",       "usb20",        &usb20_clk),
+       CLK("cppi41-dmaengine", NULL,           &cppi41_clk),
        CLK(NULL,               "aemif",        &aemif_clk),
        CLK(NULL,               "aintc",        &aintc_clk),
        CLK(NULL,               "secu_mgr",     &secu_mgr_clk),
index ccad2f99dfc95e0fd4421150364ddde5a7fd77bd..07d6f0eb8c827e499f2f4b51adf931965689076c 100644 (file)
@@ -401,6 +401,11 @@ static struct clk usb20_clk = {
        .gpsc           = 1,
 };
 
+static struct clk cppi41_clk = {
+       .name           = "cppi41",
+       .parent         = &usb20_clk,
+};
+
 static struct clk spi0_clk = {
        .name           = "spi0",
        .parent         = &pll0_sysclk2,
@@ -560,6 +565,7 @@ static struct clk_lookup da850_clks[] = {
        CLK("davinci-nand.0",   "aemif",        &aemif_nand_clk),
        CLK("ohci-da8xx",       "usb11",        &usb11_clk),
        CLK("musb-da8xx",       "usb20",        &usb20_clk),
+       CLK("cppi41-dmaengine", NULL,           &cppi41_clk),
        CLK("spi_davinci.0",    NULL,           &spi0_clk),
        CLK("spi_davinci.1",    NULL,           &spi1_clk),
        CLK("vpif",             NULL,           &vpif_clk),
index e3cef503cd8f3e16d958b3dd82dd2efc92af869a..5699ce39e64f70d9b2ca34865daaaa08f4325a43 100644 (file)
@@ -53,6 +53,7 @@ static struct of_dev_auxdata da850_auxdata_lookup[] __initdata = {
        OF_DEV_AUXDATA("ti,da830-musb", 0x01e00000, "musb-da8xx", NULL),
        OF_DEV_AUXDATA("ti,da830-usb-phy", 0x01c1417c, "da8xx-usb-phy", NULL),
        OF_DEV_AUXDATA("ti,da850-ahci", 0x01e18000, "ahci_da850", NULL),
+       OF_DEV_AUXDATA("ti,da850-vpif", 0x01e17000, "vpif", NULL),
        {}
 };
 
index 5b57da475065cd1fcd7a3fa2cb30d06be36d5db1..329f5402ad1d2ef5f7a1ae807e7c85d8ccad905a 100644 (file)
 #include <linux/kernel.h>
 #include <linux/of_platform.h>
 
+#include <media/i2c/tvp514x.h>
+#include <media/i2c/adv7343.h>
+
 #include <mach/common.h>
+#include <mach/da8xx.h>
 
 struct pdata_init {
        const char *compatible;
        void (*fn)(void);
 };
 
+#define TVP5147_CH0            "tvp514x-0"
+#define TVP5147_CH1            "tvp514x-1"
+
+/* VPIF capture configuration */
+static struct tvp514x_platform_data tvp5146_pdata = {
+               .clk_polarity = 0,
+               .hs_polarity  = 1,
+               .vs_polarity  = 1,
+};
+
+#define TVP514X_STD_ALL (V4L2_STD_NTSC | V4L2_STD_PAL)
+
+static const struct vpif_input da850_ch0_inputs[] = {
+       {
+               .input = {
+                       .index = 0,
+                       .name  = "Composite",
+                       .type  = V4L2_INPUT_TYPE_CAMERA,
+                       .capabilities = V4L2_IN_CAP_STD,
+                       .std   = TVP514X_STD_ALL,
+               },
+               .input_route = INPUT_CVBS_VI2B,
+               .output_route = OUTPUT_10BIT_422_EMBEDDED_SYNC,
+               .subdev_name = TVP5147_CH0,
+       },
+};
+
+static const struct vpif_input da850_ch1_inputs[] = {
+       {
+               .input = {
+                       .index = 0,
+                       .name  = "S-Video",
+                       .type  = V4L2_INPUT_TYPE_CAMERA,
+                       .capabilities = V4L2_IN_CAP_STD,
+                       .std   = TVP514X_STD_ALL,
+               },
+               .input_route = INPUT_SVIDEO_VI2C_VI1C,
+               .output_route = OUTPUT_10BIT_422_EMBEDDED_SYNC,
+               .subdev_name = TVP5147_CH1,
+       },
+};
+
+static struct vpif_subdev_info da850_vpif_capture_sdev_info[] = {
+       {
+               .name = TVP5147_CH0,
+               .board_info = {
+                       I2C_BOARD_INFO("tvp5146", 0x5d),
+                       .platform_data = &tvp5146_pdata,
+               },
+       },
+       {
+               .name = TVP5147_CH1,
+               .board_info = {
+                       I2C_BOARD_INFO("tvp5146", 0x5c),
+                       .platform_data = &tvp5146_pdata,
+               },
+       },
+};
+
+static struct vpif_capture_config da850_vpif_capture_config = {
+       .subdev_info = da850_vpif_capture_sdev_info,
+       .subdev_count = ARRAY_SIZE(da850_vpif_capture_sdev_info),
+       .chan_config[0] = {
+               .inputs = da850_ch0_inputs,
+               .input_count = ARRAY_SIZE(da850_ch0_inputs),
+               .vpif_if = {
+                       .if_type = VPIF_IF_BT656,
+                       .hd_pol  = 1,
+                       .vd_pol  = 1,
+                       .fid_pol = 0,
+               },
+       },
+       .chan_config[1] = {
+               .inputs = da850_ch1_inputs,
+               .input_count = ARRAY_SIZE(da850_ch1_inputs),
+               .vpif_if = {
+                       .if_type = VPIF_IF_BT656,
+                       .hd_pol  = 1,
+                       .vd_pol  = 1,
+                       .fid_pol = 0,
+               },
+       },
+       .card_name = "DA850/OMAP-L138 Video Capture",
+};
+
+static void __init da850_vpif_legacy_register_capture(void)
+{
+       int ret;
+
+       ret = da850_register_vpif_capture(&da850_vpif_capture_config);
+       if (ret)
+               pr_warn("%s: VPIF capture setup failed: %d\n",
+                       __func__, ret);
+}
+
+static void __init da850_vpif_capture_legacy_init_lcdk(void)
+{
+       da850_vpif_capture_config.subdev_count = 1;
+       da850_vpif_legacy_register_capture();
+}
+
+static void __init da850_vpif_capture_legacy_init_evm(void)
+{
+       da850_vpif_legacy_register_capture();
+}
+
+static struct adv7343_platform_data adv7343_pdata = {
+       .mode_config = {
+               .dac = { 1, 1, 1 },
+       },
+       .sd_config = {
+               .sd_dac_out = { 1 },
+       },
+};
+
+static struct vpif_subdev_info da850_vpif_subdev[] = {
+       {
+               .name = "adv7343",
+               .board_info = {
+                       I2C_BOARD_INFO("adv7343", 0x2a),
+                       .platform_data = &adv7343_pdata,
+               },
+       },
+};
+
+static const struct vpif_output da850_ch0_outputs[] = {
+       {
+               .output = {
+                       .index = 0,
+                       .name = "Composite",
+                       .type = V4L2_OUTPUT_TYPE_ANALOG,
+                       .capabilities = V4L2_OUT_CAP_STD,
+                       .std = V4L2_STD_ALL,
+               },
+               .subdev_name = "adv7343",
+               .output_route = ADV7343_COMPOSITE_ID,
+       },
+       {
+               .output = {
+                       .index = 1,
+                       .name = "S-Video",
+                       .type = V4L2_OUTPUT_TYPE_ANALOG,
+                       .capabilities = V4L2_OUT_CAP_STD,
+                       .std = V4L2_STD_ALL,
+               },
+               .subdev_name = "adv7343",
+               .output_route = ADV7343_SVIDEO_ID,
+       },
+};
+
+static struct vpif_display_config da850_vpif_display_config = {
+       .subdevinfo   = da850_vpif_subdev,
+       .subdev_count = ARRAY_SIZE(da850_vpif_subdev),
+       .chan_config[0] = {
+               .outputs = da850_ch0_outputs,
+               .output_count = ARRAY_SIZE(da850_ch0_outputs),
+       },
+       .card_name    = "DA850/OMAP-L138 Video Display",
+};
+
+static void __init da850_vpif_display_legacy_init_evm(void)
+{
+       int ret;
+
+       ret = da850_register_vpif_display(&da850_vpif_display_config);
+       if (ret)
+               pr_warn("%s: VPIF display setup failed: %d\n",
+                       __func__, ret);
+}
+
 static void pdata_quirks_check(struct pdata_init *quirks)
 {
        while (quirks->compatible) {
                if (of_machine_is_compatible(quirks->compatible)) {
                        if (quirks->fn)
                                quirks->fn();
-                       break;
                }
                quirks++;
        }
 }
 
 static struct pdata_init pdata_quirks[] __initdata = {
+       { "ti,da850-lcdk", da850_vpif_capture_legacy_init_lcdk, },
+       { "ti,da850-evm", da850_vpif_display_legacy_init_evm, },
+       { "ti,da850-evm", da850_vpif_capture_legacy_init_evm, },
        { /* sentinel */ },
 };
 
index 0afd201ab980464c1578c45c4ce8275aa982ade5..efb80354f3034d856ab259bb1568dab41173d3b3 100644 (file)
@@ -108,7 +108,6 @@ static int davinci_pm_enter(suspend_state_t state)
        int ret = 0;
 
        switch (state) {
-       case PM_SUSPEND_STANDBY:
        case PM_SUSPEND_MEM:
                davinci_pm_suspend();
                break;
index 6f066ee4bf24ec2177d9f6cc438180d774278a5a..06c8b095154c5dd39b0c052728d9781ebead099d 100644 (file)
@@ -1,40 +1,13 @@
-if ARCH_GEMINI
-
-menu "Cortina Systems Gemini Implementations"
-
-config MACH_NAS4220B
-       bool "Raidsonic NAS-4220-B"
-       select GEMINI_MEM_SWAP
-       help
-         Say Y here if you intend to run this kernel on a
-         Raidsonic NAS-4220-B.
-
-config MACH_RUT100
-       bool "Teltonika RUT100"
-       select GEMINI_MEM_SWAP
-       help
-         Say Y here if you intend to run this kernel on a
-         Teltonika 3G Router RUT100.
-
-config MACH_WBD111
-       bool "Wiliboard WBD-111"
-       select GEMINI_MEM_SWAP
-       help
-         Say Y here if you intend to run this kernel on a
-         Wiliboard WBD-111.
-
-config MACH_WBD222
-        bool "Wiliboard WBD-222"
-        select GEMINI_MEM_SWAP
-        help
-          Say Y here if you intend to run this kernel on a
-          Wiliboard WBD-222.
-
-endmenu
-
-config GEMINI_MEM_SWAP
-       bool "Gemini memory is swapped"
-       help
-         Say Y here if Gemini memory is swapped by bootloader.
-
-endif
+menuconfig ARCH_GEMINI
+       bool "Cortina Systems Gemini"
+       depends on ARCH_MULTI_V4
+       select ARM_APPENDED_DTB # Old Redboot bootloaders deployed
+       select FARADAY_FTINTC010
+       select FTTMR010_TIMER
+       select GPIO_FTGPIO010
+       select GPIOLIB
+       select POWER_RESET
+       select POWER_RESET_GEMINI_POWEROFF
+       select POWER_RESET_SYSCON
+       help
+         Support for the Cortina Systems Gemini family SoCs
index 7963a77be637b9fb13ef2cded4f6f2165096f721..ca0db5477180f51fbf2b8a6e96cb9328954dc766 100644 (file)
@@ -1,13 +1,2 @@
-#
-# Makefile for the linux kernel.
-#
-
-# Object file lists.
-
-obj-y                  := irq.o mm.o time.o devices.o gpio.o idle.o reset.o
-
-# Board-specific support
-obj-$(CONFIG_MACH_NAS4220B)    += board-nas4220b.o
-obj-$(CONFIG_MACH_RUT100)      += board-rut1xx.o
-obj-$(CONFIG_MACH_WBD111)      += board-wbd111.o
-obj-$(CONFIG_MACH_WBD222)      += board-wbd222.o
+# Makefile for Cortina systems Gemini
+obj-y                  := board-dt.o
diff --git a/arch/arm/mach-gemini/Makefile.boot b/arch/arm/mach-gemini/Makefile.boot
deleted file mode 100644 (file)
index 683f52b..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-ifeq ($(CONFIG_GEMINI_MEM_SWAP),y)
-   zreladdr-y  += 0x00008000
-params_phys-y  := 0x00000100
-initrd_phys-y  := 0x00800000
-else
-   zreladdr-y  += 0x10008000
-params_phys-y  := 0x10000100
-initrd_phys-y  := 0x10800000
-endif
diff --git a/arch/arm/mach-gemini/board-dt.c b/arch/arm/mach-gemini/board-dt.c
new file mode 100644 (file)
index 0000000..c0c0ebd
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Gemini Device Tree boot support
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/system_misc.h>
+#include <asm/proc-fns.h>
+
+#ifdef CONFIG_DEBUG_GEMINI
+/* This is needed for LL-debug/earlyprintk/debug-macro.S */
+static struct map_desc gemini_io_desc[] __initdata = {
+       {
+               .virtual = CONFIG_DEBUG_UART_VIRT,
+               .pfn = __phys_to_pfn(CONFIG_DEBUG_UART_PHYS),
+               .length = SZ_4K,
+               .type = MT_DEVICE,
+       },
+};
+
+static void __init gemini_map_io(void)
+{
+       iotable_init(gemini_io_desc, ARRAY_SIZE(gemini_io_desc));
+}
+#else
+#define gemini_map_io NULL
+#endif
+
+static void gemini_idle(void)
+{
+       /*
+        * Because of broken hardware we have to enable interrupts or the CPU
+        * will never wakeup... Acctualy it is not very good to enable
+        * interrupts first since scheduler can miss a tick, but there is
+        * no other way around this. Platforms that needs it for power saving
+        * should enable it in init code, since by default it is
+        * disabled.
+        */
+
+       /* FIXME: Enabling interrupts here is racy! */
+       local_irq_enable();
+       cpu_do_idle();
+}
+
+static void __init gemini_init_machine(void)
+{
+       arm_pm_idle = gemini_idle;
+}
+
+static const char *gemini_board_compat[] = {
+       "cortina,gemini",
+       NULL,
+};
+
+DT_MACHINE_START(GEMINI_DT, "Gemini (Device Tree)")
+       .map_io         = gemini_map_io,
+       .init_machine   = gemini_init_machine,
+       .dt_compat      = gemini_board_compat,
+MACHINE_END
diff --git a/arch/arm/mach-gemini/board-nas4220b.c b/arch/arm/mach-gemini/board-nas4220b.c
deleted file mode 100644 (file)
index 18b1279..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- *  Support for Raidsonic NAS-4220-B
- *
- *  Copyright (C) 2009 Janos Laube <janos.dev@gmail.com>
- *
- * based on rut1xx.c
- *  Copyright (C) 2008 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/leds.h>
-#include <linux/input.h>
-#include <linux/gpio_keys.h>
-#include <linux/io.h>
-
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include <mach/hardware.h>
-#include <mach/global_reg.h>
-
-#include "common.h"
-
-static struct gpio_led ib4220b_leds[] = {
-       {
-               .name                   = "nas4220b:orange:hdd",
-               .default_trigger        = "none",
-               .gpio                   = 60,
-       },
-       {
-               .name                   = "nas4220b:green:os",
-               .default_trigger        = "heartbeat",
-               .gpio                   = 62,
-       },
-};
-
-static struct gpio_led_platform_data ib4220b_leds_data = {
-       .num_leds       = ARRAY_SIZE(ib4220b_leds),
-       .leds           = ib4220b_leds,
-};
-
-static struct platform_device ib4220b_led_device = {
-       .name   = "leds-gpio",
-       .id     = -1,
-       .dev    = {
-               .platform_data = &ib4220b_leds_data,
-       },
-};
-
-static struct gpio_keys_button ib4220b_keys[] = {
-       {
-               .code           = KEY_SETUP,
-               .gpio           = 61,
-               .active_low     = 1,
-               .desc           = "Backup Button",
-               .type           = EV_KEY,
-       },
-       {
-               .code           = KEY_RESTART,
-               .gpio           = 63,
-               .active_low     = 1,
-               .desc           = "Softreset Button",
-               .type           = EV_KEY,
-       },
-};
-
-static struct gpio_keys_platform_data ib4220b_keys_data = {
-       .buttons        = ib4220b_keys,
-       .nbuttons       = ARRAY_SIZE(ib4220b_keys),
-};
-
-static struct platform_device ib4220b_key_device = {
-       .name   = "gpio-keys",
-       .id     = -1,
-       .dev    = {
-               .platform_data = &ib4220b_keys_data,
-       },
-};
-
-static void __init ib4220b_init(void)
-{
-       gemini_gpio_init();
-       platform_register_uart();
-       platform_register_pflash(SZ_16M, NULL, 0);
-       platform_device_register(&ib4220b_led_device);
-       platform_device_register(&ib4220b_key_device);
-       platform_register_rtc();
-}
-
-MACHINE_START(NAS4220B, "Raidsonic NAS IB-4220-B")
-       .atag_offset    = 0x100,
-       .map_io         = gemini_map_io,
-       .init_irq       = gemini_init_irq,
-       .init_time      = gemini_timer_init,
-       .init_machine   = ib4220b_init,
-       .restart        = gemini_restart,
-MACHINE_END
diff --git a/arch/arm/mach-gemini/board-rut1xx.c b/arch/arm/mach-gemini/board-rut1xx.c
deleted file mode 100644 (file)
index 7a675f8..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- *  Support for Teltonika RUT1xx
- *
- *  Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/leds.h>
-#include <linux/input.h>
-#include <linux/gpio_keys.h>
-#include <linux/sizes.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "common.h"
-
-static struct gpio_keys_button rut1xx_keys[] = {
-       {
-               .code           = KEY_SETUP,
-               .gpio           = 60,
-               .active_low     = 1,
-               .desc           = "Reset to defaults",
-               .type           = EV_KEY,
-       },
-};
-
-static struct gpio_keys_platform_data rut1xx_keys_data = {
-       .buttons        = rut1xx_keys,
-       .nbuttons       = ARRAY_SIZE(rut1xx_keys),
-};
-
-static struct platform_device rut1xx_keys_device = {
-       .name   = "gpio-keys",
-       .id     = -1,
-       .dev    = {
-               .platform_data = &rut1xx_keys_data,
-       },
-};
-
-static struct gpio_led rut100_leds[] = {
-       {
-               .name                   = "Power",
-               .default_trigger        = "heartbeat",
-               .gpio                   = 17,
-       },
-       {
-               .name                   = "GSM",
-               .default_trigger        = "default-on",
-               .gpio                   = 7,
-               .active_low             = 1,
-       },
-};
-
-static struct gpio_led_platform_data rut100_leds_data = {
-       .num_leds       = ARRAY_SIZE(rut100_leds),
-       .leds           = rut100_leds,
-};
-
-static struct platform_device rut1xx_leds = {
-       .name   = "leds-gpio",
-       .id     = -1,
-       .dev    = {
-               .platform_data = &rut100_leds_data,
-       },
-};
-
-static void __init rut1xx_init(void)
-{
-       gemini_gpio_init();
-       platform_register_uart();
-       platform_register_pflash(SZ_8M, NULL, 0);
-       platform_device_register(&rut1xx_leds);
-       platform_device_register(&rut1xx_keys_device);
-       platform_register_rtc();
-}
-
-MACHINE_START(RUT100, "Teltonika RUT100")
-       .atag_offset    = 0x100,
-       .map_io         = gemini_map_io,
-       .init_irq       = gemini_init_irq,
-       .init_time      = gemini_timer_init,
-       .init_machine   = rut1xx_init,
-       .restart        = gemini_restart,
-MACHINE_END
diff --git a/arch/arm/mach-gemini/board-wbd111.c b/arch/arm/mach-gemini/board-wbd111.c
deleted file mode 100644 (file)
index 14c56f3..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- *  Support for Wiliboard WBD-111
- *
- *  Copyright (C) 2009 Imre Kaloz <kaloz@openwrt.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/leds.h>
-#include <linux/input.h>
-#include <linux/skbuff.h>
-#include <linux/gpio_keys.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-
-#include "common.h"
-
-static struct gpio_keys_button wbd111_keys[] = {
-       {
-               .code           = KEY_SETUP,
-               .gpio           = 5,
-               .active_low     = 1,
-               .desc           = "reset",
-               .type           = EV_KEY,
-       },
-};
-
-static struct gpio_keys_platform_data wbd111_keys_data = {
-       .buttons        = wbd111_keys,
-       .nbuttons       = ARRAY_SIZE(wbd111_keys),
-};
-
-static struct platform_device wbd111_keys_device = {
-       .name   = "gpio-keys",
-       .id     = -1,
-       .dev    = {
-               .platform_data = &wbd111_keys_data,
-       },
-};
-
-static struct gpio_led wbd111_leds[] = {
-       {
-               .name                   = "L3red",
-               .gpio                   = 1,
-       },
-       {
-               .name                   = "L4green",
-               .gpio                   = 2,
-       },
-       {
-               .name                   = "L4red",
-               .gpio                   = 3,
-       },
-       {
-               .name                   = "L3green",
-               .gpio                   = 5,
-       },
-};
-
-static struct gpio_led_platform_data wbd111_leds_data = {
-       .num_leds       = ARRAY_SIZE(wbd111_leds),
-       .leds           = wbd111_leds,
-};
-
-static struct platform_device wbd111_leds_device = {
-       .name   = "leds-gpio",
-       .id     = -1,
-       .dev    = {
-               .platform_data = &wbd111_leds_data,
-       },
-};
-
-static struct mtd_partition wbd111_partitions[] = {
-       {
-               .name           = "RedBoot",
-               .offset         = 0,
-               .size           = 0x020000,
-               .mask_flags     = MTD_WRITEABLE,
-       } , {
-               .name           = "kernel",
-               .offset         = 0x020000,
-               .size           = 0x100000,
-       } , {
-               .name           = "rootfs",
-               .offset         = 0x120000,
-               .size           = 0x6a0000,
-       } , {
-               .name           = "VCTL",
-               .offset         = 0x7c0000,
-               .size           = 0x010000,
-               .mask_flags     = MTD_WRITEABLE,
-       } , {
-               .name           = "cfg",
-               .offset         = 0x7d0000,
-               .size           = 0x010000,
-               .mask_flags     = MTD_WRITEABLE,
-       } , {
-               .name           = "FIS",
-               .offset         = 0x7e0000,
-               .size           = 0x010000,
-               .mask_flags     = MTD_WRITEABLE,
-       }
-};
-#define wbd111_num_partitions  ARRAY_SIZE(wbd111_partitions)
-
-static void __init wbd111_init(void)
-{
-       gemini_gpio_init();
-       platform_register_uart();
-       platform_register_pflash(SZ_8M, wbd111_partitions,
-                                wbd111_num_partitions);
-       platform_device_register(&wbd111_leds_device);
-       platform_device_register(&wbd111_keys_device);
-       platform_register_rtc();
-}
-
-MACHINE_START(WBD111, "Wiliboard WBD-111")
-       .atag_offset    = 0x100,
-       .map_io         = gemini_map_io,
-       .init_irq       = gemini_init_irq,
-       .init_time      = gemini_timer_init,
-       .init_machine   = wbd111_init,
-       .restart        = gemini_restart,
-MACHINE_END
diff --git a/arch/arm/mach-gemini/board-wbd222.c b/arch/arm/mach-gemini/board-wbd222.c
deleted file mode 100644 (file)
index 6070282..0000000
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- *  Support for Wiliboard WBD-222
- *
- *  Copyright (C) 2009 Imre Kaloz <kaloz@openwrt.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/leds.h>
-#include <linux/input.h>
-#include <linux/skbuff.h>
-#include <linux/gpio_keys.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/partitions.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-
-#include "common.h"
-
-static struct gpio_keys_button wbd222_keys[] = {
-       {
-               .code           = KEY_SETUP,
-               .gpio           = 5,
-               .active_low     = 1,
-               .desc           = "reset",
-               .type           = EV_KEY,
-       },
-};
-
-static struct gpio_keys_platform_data wbd222_keys_data = {
-       .buttons        = wbd222_keys,
-       .nbuttons       = ARRAY_SIZE(wbd222_keys),
-};
-
-static struct platform_device wbd222_keys_device = {
-       .name   = "gpio-keys",
-       .id     = -1,
-       .dev    = {
-               .platform_data = &wbd222_keys_data,
-       },
-};
-
-static struct gpio_led wbd222_leds[] = {
-       {
-               .name                   = "L3red",
-               .gpio                   = 1,
-       },
-       {
-               .name                   = "L4green",
-               .gpio                   = 2,
-       },
-       {
-               .name                   = "L4red",
-               .gpio                   = 3,
-       },
-       {
-               .name                   = "L3green",
-               .gpio                   = 5,
-       },
-};
-
-static struct gpio_led_platform_data wbd222_leds_data = {
-       .num_leds       = ARRAY_SIZE(wbd222_leds),
-       .leds           = wbd222_leds,
-};
-
-static struct platform_device wbd222_leds_device = {
-       .name   = "leds-gpio",
-       .id     = -1,
-       .dev    = {
-               .platform_data = &wbd222_leds_data,
-       },
-};
-
-static struct mtd_partition wbd222_partitions[] = {
-       {
-               .name           = "RedBoot",
-               .offset         = 0,
-               .size           = 0x020000,
-               .mask_flags     = MTD_WRITEABLE,
-       } , {
-               .name           = "kernel",
-               .offset         = 0x020000,
-               .size           = 0x100000,
-       } , {
-               .name           = "rootfs",
-               .offset         = 0x120000,
-               .size           = 0x6a0000,
-       } , {
-               .name           = "VCTL",
-               .offset         = 0x7c0000,
-               .size           = 0x010000,
-               .mask_flags     = MTD_WRITEABLE,
-       } , {
-               .name           = "cfg",
-               .offset         = 0x7d0000,
-               .size           = 0x010000,
-               .mask_flags     = MTD_WRITEABLE,
-       } , {
-               .name           = "FIS",
-               .offset         = 0x7e0000,
-               .size           = 0x010000,
-               .mask_flags     = MTD_WRITEABLE,
-       }
-};
-#define wbd222_num_partitions  ARRAY_SIZE(wbd222_partitions)
-
-static void __init wbd222_init(void)
-{
-       gemini_gpio_init();
-       platform_register_uart();
-       platform_register_pflash(SZ_8M, wbd222_partitions,
-               wbd222_num_partitions);
-       platform_device_register(&wbd222_leds_device);
-       platform_device_register(&wbd222_keys_device);
-       platform_register_rtc();
-}
-
-MACHINE_START(WBD222, "Wiliboard WBD-222")
-       .atag_offset    = 0x100,
-       .map_io         = gemini_map_io,
-       .init_irq       = gemini_init_irq,
-       .init_time      = gemini_timer_init,
-       .init_machine   = wbd222_init,
-       .restart        = gemini_restart,
-MACHINE_END
diff --git a/arch/arm/mach-gemini/common.h b/arch/arm/mach-gemini/common.h
deleted file mode 100644 (file)
index dd88369..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Common Gemini architecture functions
- *
- * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __GEMINI_COMMON_H__
-#define __GEMINI_COMMON_H__
-
-#include <linux/reboot.h>
-
-struct mtd_partition;
-
-extern void gemini_map_io(void);
-extern void gemini_init_irq(void);
-extern void gemini_timer_init(void);
-extern void gemini_gpio_init(void);
-extern void platform_register_rtc(void);
-
-/* Common platform devices registration functions */
-extern int platform_register_uart(void);
-extern int platform_register_pflash(unsigned int size,
-                                   struct mtd_partition *parts,
-                                   unsigned int nr_parts);
-
-extern void gemini_restart(enum reboot_mode mode, const char *cmd);
-
-#endif /* __GEMINI_COMMON_H__ */
diff --git a/arch/arm/mach-gemini/devices.c b/arch/arm/mach-gemini/devices.c
deleted file mode 100644 (file)
index 5cff298..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Common devices definition for Gemini
- *
- * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <linux/serial_8250.h>
-#include <linux/mtd/physmap.h>
-
-#include <mach/irqs.h>
-#include <mach/hardware.h>
-#include <mach/global_reg.h>
-
-static struct plat_serial8250_port serial_platform_data[] = {
-       {
-               .membase        = (void *)IO_ADDRESS(GEMINI_UART_BASE),
-               .mapbase        = GEMINI_UART_BASE,
-               .irq            = IRQ_UART,
-               .uartclk        = UART_CLK,
-               .regshift       = 2,
-               .iotype         = UPIO_MEM,
-               .type           = PORT_16550A,
-               .flags          = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | UPF_FIXED_TYPE,
-       },
-       {},
-};
-
-static struct platform_device serial_device = {
-       .name   = "serial8250",
-       .id     = PLAT8250_DEV_PLATFORM,
-       .dev    = {
-               .platform_data = serial_platform_data,
-       },
-};
-
-int platform_register_uart(void)
-{
-       return platform_device_register(&serial_device);
-}
-
-static struct resource flash_resource = {
-       .start  = GEMINI_FLASH_BASE,
-       .flags  = IORESOURCE_MEM,
-};
-
-static struct physmap_flash_data pflash_platform_data = {};
-
-static struct platform_device pflash_device = {
-       .name   = "physmap-flash",
-       .id     = 0,
-       .dev    = {
-               .platform_data = &pflash_platform_data,
-       },
-       .resource = &flash_resource,
-       .num_resources = 1,
-};
-
-int platform_register_pflash(unsigned int size, struct mtd_partition *parts,
-                            unsigned int nr_parts)
-{
-       unsigned int reg;
-
-       reg = __raw_readl(IO_ADDRESS(GEMINI_GLOBAL_BASE) + GLOBAL_STATUS);
-
-       if ((reg & FLASH_TYPE_MASK) != FLASH_TYPE_PARALLEL)
-               return -ENXIO;
-
-       if (reg & FLASH_WIDTH_16BIT)
-               pflash_platform_data.width = 2;
-       else
-               pflash_platform_data.width = 1;
-
-       /* enable parallel flash pins and disable others */
-       reg = __raw_readl(IO_ADDRESS(GEMINI_GLOBAL_BASE) + GLOBAL_MISC_CTRL);
-       reg &= ~PFLASH_PADS_DISABLE;
-       reg |= SFLASH_PADS_DISABLE | NAND_PADS_DISABLE;
-       __raw_writel(reg, IO_ADDRESS(GEMINI_GLOBAL_BASE) + GLOBAL_MISC_CTRL);
-
-       flash_resource.end = flash_resource.start + size - 1;
-
-       pflash_platform_data.parts = parts;
-       pflash_platform_data.nr_parts = nr_parts;
-
-       return platform_device_register(&pflash_device);
-}
-
-static struct resource gemini_rtc_resources[] = {
-       [0] = {
-               .start  = GEMINI_RTC_BASE,
-               .end    = GEMINI_RTC_BASE + 0x24,
-               .flags  = IORESOURCE_MEM,
-       },
-       [1] = {
-               .start  = IRQ_RTC,
-               .end    = IRQ_RTC,
-               .flags  = IORESOURCE_IRQ,
-       },
-};
-
-static struct platform_device gemini_rtc_device = {
-       .name           = "rtc-gemini",
-       .id             = 0,
-       .num_resources  = ARRAY_SIZE(gemini_rtc_resources),
-       .resource       = gemini_rtc_resources,
-};
-
-int __init platform_register_rtc(void)
-{
-       return platform_device_register(&gemini_rtc_device);
-}
-
diff --git a/arch/arm/mach-gemini/gpio.c b/arch/arm/mach-gemini/gpio.c
deleted file mode 100644 (file)
index 469a76e..0000000
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * Gemini gpiochip and interrupt routines
- *
- * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
- *
- * Based on plat-mxc/gpio.c:
- *  MXC GPIO support. (c) 2008 Daniel Mack <daniel@caiaq.de>
- *  Copyright 2008 Juergen Beisert, kernel@pengutronix.de
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/gpio/driver.h>
-
-#include <mach/hardware.h>
-#include <mach/irqs.h>
-
-#define GPIO_BASE(x)           IO_ADDRESS(GEMINI_GPIO_BASE(x))
-#define irq_to_gpio(x)         ((x) - GPIO_IRQ_BASE)
-
-/* GPIO registers definition */
-#define GPIO_DATA_OUT          0x0
-#define GPIO_DATA_IN           0x4
-#define GPIO_DIR               0x8
-#define GPIO_DATA_SET          0x10
-#define GPIO_DATA_CLR          0x14
-#define GPIO_PULL_EN           0x18
-#define GPIO_PULL_TYPE         0x1C
-#define GPIO_INT_EN            0x20
-#define GPIO_INT_STAT          0x24
-#define GPIO_INT_MASK          0x2C
-#define GPIO_INT_CLR           0x30
-#define GPIO_INT_TYPE          0x34
-#define GPIO_INT_BOTH_EDGE     0x38
-#define GPIO_INT_LEVEL         0x3C
-#define GPIO_DEBOUNCE_EN       0x40
-#define GPIO_DEBOUNCE_PRESCALE 0x44
-
-#define GPIO_PORT_NUM          3
-
-static void _set_gpio_irqenable(void __iomem *base, unsigned int index,
-                               int enable)
-{
-       unsigned int reg;
-
-       reg = __raw_readl(base + GPIO_INT_EN);
-       reg = (reg & (~(1 << index))) | (!!enable << index);
-       __raw_writel(reg, base + GPIO_INT_EN);
-}
-
-static void gpio_ack_irq(struct irq_data *d)
-{
-       unsigned int gpio = irq_to_gpio(d->irq);
-       void __iomem *base = GPIO_BASE(gpio / 32);
-
-       __raw_writel(1 << (gpio % 32), base + GPIO_INT_CLR);
-}
-
-static void gpio_mask_irq(struct irq_data *d)
-{
-       unsigned int gpio = irq_to_gpio(d->irq);
-       void __iomem *base = GPIO_BASE(gpio / 32);
-
-       _set_gpio_irqenable(base, gpio % 32, 0);
-}
-
-static void gpio_unmask_irq(struct irq_data *d)
-{
-       unsigned int gpio = irq_to_gpio(d->irq);
-       void __iomem *base = GPIO_BASE(gpio / 32);
-
-       _set_gpio_irqenable(base, gpio % 32, 1);
-}
-
-static int gpio_set_irq_type(struct irq_data *d, unsigned int type)
-{
-       unsigned int gpio = irq_to_gpio(d->irq);
-       unsigned int gpio_mask = 1 << (gpio % 32);
-       void __iomem *base = GPIO_BASE(gpio / 32);
-       unsigned int reg_both, reg_level, reg_type;
-
-       reg_type = __raw_readl(base + GPIO_INT_TYPE);
-       reg_level = __raw_readl(base + GPIO_INT_LEVEL);
-       reg_both = __raw_readl(base + GPIO_INT_BOTH_EDGE);
-
-       switch (type) {
-       case IRQ_TYPE_EDGE_BOTH:
-               reg_type &= ~gpio_mask;
-               reg_both |= gpio_mask;
-               break;
-       case IRQ_TYPE_EDGE_RISING:
-               reg_type &= ~gpio_mask;
-               reg_both &= ~gpio_mask;
-               reg_level &= ~gpio_mask;
-               break;
-       case IRQ_TYPE_EDGE_FALLING:
-               reg_type &= ~gpio_mask;
-               reg_both &= ~gpio_mask;
-               reg_level |= gpio_mask;
-               break;
-       case IRQ_TYPE_LEVEL_HIGH:
-               reg_type |= gpio_mask;
-               reg_level &= ~gpio_mask;
-               break;
-       case IRQ_TYPE_LEVEL_LOW:
-               reg_type |= gpio_mask;
-               reg_level |= gpio_mask;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       __raw_writel(reg_type, base + GPIO_INT_TYPE);
-       __raw_writel(reg_level, base + GPIO_INT_LEVEL);
-       __raw_writel(reg_both, base + GPIO_INT_BOTH_EDGE);
-
-       gpio_ack_irq(d);
-
-       return 0;
-}
-
-static void gpio_irq_handler(struct irq_desc *desc)
-{
-       unsigned int port = (unsigned int)irq_desc_get_handler_data(desc);
-       unsigned int gpio_irq_no, irq_stat;
-
-       irq_stat = __raw_readl(GPIO_BASE(port) + GPIO_INT_STAT);
-
-       gpio_irq_no = GPIO_IRQ_BASE + port * 32;
-       for (; irq_stat != 0; irq_stat >>= 1, gpio_irq_no++) {
-
-               if ((irq_stat & 1) == 0)
-                       continue;
-
-               generic_handle_irq(gpio_irq_no);
-       }
-}
-
-static struct irq_chip gpio_irq_chip = {
-       .name = "GPIO",
-       .irq_ack = gpio_ack_irq,
-       .irq_mask = gpio_mask_irq,
-       .irq_unmask = gpio_unmask_irq,
-       .irq_set_type = gpio_set_irq_type,
-};
-
-static void _set_gpio_direction(struct gpio_chip *chip, unsigned offset,
-                               int dir)
-{
-       void __iomem *base = GPIO_BASE(offset / 32);
-       unsigned int reg;
-
-       reg = __raw_readl(base + GPIO_DIR);
-       if (dir)
-               reg |= 1 << (offset % 32);
-       else
-               reg &= ~(1 << (offset % 32));
-       __raw_writel(reg, base + GPIO_DIR);
-}
-
-static void gemini_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
-{
-       void __iomem *base = GPIO_BASE(offset / 32);
-
-       if (value)
-               __raw_writel(1 << (offset % 32), base + GPIO_DATA_SET);
-       else
-               __raw_writel(1 << (offset % 32), base + GPIO_DATA_CLR);
-}
-
-static int gemini_gpio_get(struct gpio_chip *chip, unsigned offset)
-{
-       void __iomem *base = GPIO_BASE(offset / 32);
-
-       return (__raw_readl(base + GPIO_DATA_IN) >> (offset % 32)) & 1;
-}
-
-static int gemini_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-       _set_gpio_direction(chip, offset, 0);
-       return 0;
-}
-
-static int gemini_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
-                                       int value)
-{
-       _set_gpio_direction(chip, offset, 1);
-       gemini_gpio_set(chip, offset, value);
-       return 0;
-}
-
-static struct gpio_chip gemini_gpio_chip = {
-       .label                  = "Gemini",
-       .direction_input        = gemini_gpio_direction_input,
-       .get                    = gemini_gpio_get,
-       .direction_output       = gemini_gpio_direction_output,
-       .set                    = gemini_gpio_set,
-       .base                   = 0,
-       .ngpio                  = GPIO_PORT_NUM * 32,
-};
-
-void __init gemini_gpio_init(void)
-{
-       int i, j;
-
-       for (i = 0; i < GPIO_PORT_NUM; i++) {
-               /* disable, unmask and clear all interrupts */
-               __raw_writel(0x0, GPIO_BASE(i) + GPIO_INT_EN);
-               __raw_writel(0x0, GPIO_BASE(i) + GPIO_INT_MASK);
-               __raw_writel(~0x0, GPIO_BASE(i) + GPIO_INT_CLR);
-
-               for (j = GPIO_IRQ_BASE + i * 32;
-                    j < GPIO_IRQ_BASE + (i + 1) * 32; j++) {
-                       irq_set_chip_and_handler(j, &gpio_irq_chip,
-                                                handle_edge_irq);
-                       irq_clear_status_flags(j, IRQ_NOREQUEST);
-               }
-
-               irq_set_chained_handler_and_data(IRQ_GPIO(i), gpio_irq_handler,
-                                                (void *)i);
-       }
-
-       BUG_ON(gpiochip_add_data(&gemini_gpio_chip, NULL));
-}
diff --git a/arch/arm/mach-gemini/idle.c b/arch/arm/mach-gemini/idle.c
deleted file mode 100644 (file)
index ddf8ec9..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * arch/arm/mach-gemini/idle.c
- */
-
-#include <linux/init.h>
-#include <asm/system_misc.h>
-#include <asm/proc-fns.h>
-
-static void gemini_idle(void)
-{
-       /*
-        * Because of broken hardware we have to enable interrupts or the CPU
-        * will never wakeup... Acctualy it is not very good to enable
-        * interrupts first since scheduler can miss a tick, but there is
-        * no other way around this. Platforms that needs it for power saving
-        * should enable it in init code, since by default it is
-        * disabled.
-        */
-
-       /* FIXME: Enabling interrupts here is racy! */
-       local_irq_enable();
-       cpu_do_idle();
-}
-
-static int __init gemini_idle_init(void)
-{
-       arm_pm_idle = gemini_idle;
-       return 0;
-}
-
-arch_initcall(gemini_idle_init);
diff --git a/arch/arm/mach-gemini/include/mach/entry-macro.S b/arch/arm/mach-gemini/include/mach/entry-macro.S
deleted file mode 100644 (file)
index f044e43..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Low-level IRQ helper macros for Gemini platform.
- *
- *  Copyright (C) 2001-2006 Storlink, Corp.
- *  Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
- *
- * This file is licensed under  the terms of the GNU General Public
- * License version 2. This program is licensed "as is" without any
- * warranty of any kind, whether express or implied.
- */
-#include <mach/hardware.h>
-
-#define IRQ_STATUS     0x14
-
-       .macro  get_irqnr_preamble, base, tmp
-       .endm
-
-       .macro  get_irqnr_and_base, irqnr, irqstat, base, tmp
-       ldr     \irqstat, =IO_ADDRESS(GEMINI_INTERRUPT_BASE + IRQ_STATUS)
-       ldr     \irqnr, [\irqstat]
-       cmp     \irqnr, #0
-       beq     2313f
-       mov     \tmp, \irqnr
-       mov     \irqnr, #0
-2312:
-       tst     \tmp, #1
-       bne     2313f
-       add     \irqnr, \irqnr, #1
-       mov     \tmp, \tmp, lsr #1
-       cmp     \irqnr, #31
-       bcc     2312b
-2313:
-       .endm
diff --git a/arch/arm/mach-gemini/include/mach/global_reg.h b/arch/arm/mach-gemini/include/mach/global_reg.h
deleted file mode 100644 (file)
index de7ff7e..0000000
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- *  This file contains the hardware definitions for Gemini.
- *
- *  Copyright (C) 2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-#ifndef __MACH_GLOBAL_REG_H
-#define __MACH_GLOBAL_REG_H
-
-/* Global Word ID Register*/
-#define GLOBAL_ID                      0x00
-
-#define CHIP_ID(reg)                   ((reg) >> 8)
-#define CHIP_REVISION(reg)             ((reg) & 0xFF)
-
-/* Global Status Register */
-#define GLOBAL_STATUS                  0x04
-
-#define CPU_BIG_ENDIAN                 (1 << 31)
-#define PLL_OSC_30M                    (1 << 30)       /* else 60MHz */
-
-#define OPERATION_MODE_MASK            (0xF << 26)
-#define OPM_IDDQ                       (0xF << 26)
-#define OPM_NAND                       (0xE << 26)
-#define OPM_RING                       (0xD << 26)
-#define OPM_DIRECT_BOOT                        (0xC << 26)
-#define OPM_USB1_PHY_TEST              (0xB << 26)
-#define OPM_USB0_PHY_TEST              (0xA << 26)
-#define OPM_SATA1_PHY_TEST             (0x9 << 26)
-#define OPM_SATA0_PHY_TEST             (0x8 << 26)
-#define OPM_ICE_ARM                    (0x7 << 26)
-#define OPM_ICE_FARADAY                        (0x6 << 26)
-#define OPM_PLL_BYPASS                 (0x5 << 26)
-#define OPM_DEBUG                      (0x4 << 26)
-#define OPM_BURN_IN                    (0x3 << 26)
-#define OPM_MBIST                      (0x2 << 26)
-#define OPM_SCAN                       (0x1 << 26)
-#define OPM_REAL                       (0x0 << 26)
-
-#define FLASH_TYPE_MASK                        (0x3 << 24)
-#define FLASH_TYPE_NAND_2K             (0x3 << 24)
-#define FLASH_TYPE_NAND_512            (0x2 << 24)
-#define FLASH_TYPE_PARALLEL            (0x1 << 24)
-#define FLASH_TYPE_SERIAL              (0x0 << 24)
-/* if parallel */
-#define FLASH_WIDTH_16BIT              (1 << 23)       /* else 8 bit */
-/* if serial */
-#define FLASH_ATMEL                    (1 << 23)       /* else STM */
-
-#define FLASH_SIZE_MASK                        (0x3 << 21)
-#define NAND_256M                      (0x3 << 21)     /* and more */
-#define NAND_128M                      (0x2 << 21)
-#define NAND_64M                       (0x1 << 21)
-#define NAND_32M                       (0x0 << 21)
-#define ATMEL_16M                      (0x3 << 21)     /* and more */
-#define ATMEL_8M                       (0x2 << 21)
-#define ATMEL_4M_2M                    (0x1 << 21)
-#define ATMEL_1M                       (0x0 << 21)     /* and less */
-#define STM_32M                                (1 << 22)       /* and more */
-#define STM_16M                                (0 << 22)       /* and less */
-
-#define FLASH_PARALLEL_HIGH_PIN_CNT    (1 << 20)       /* else low pin cnt */
-
-#define CPU_AHB_RATIO_MASK             (0x3 << 18)
-#define CPU_AHB_1_1                    (0x0 << 18)
-#define CPU_AHB_3_2                    (0x1 << 18)
-#define CPU_AHB_24_13                  (0x2 << 18)
-#define CPU_AHB_2_1                    (0x3 << 18)
-
-#define REG_TO_AHB_SPEED(reg)          ((((reg) >> 15) & 0x7) * 10 + 130)
-#define AHB_SPEED_TO_REG(x)            ((((x - 130)) / 10) << 15)
-
-/* it is posible to override some settings, use >> OVERRIDE_xxxx_SHIFT */
-#define OVERRIDE_FLASH_TYPE_SHIFT      16
-#define OVERRIDE_FLASH_WIDTH_SHIFT     16
-#define OVERRIDE_FLASH_SIZE_SHIFT      16
-#define OVERRIDE_CPU_AHB_RATIO_SHIFT   15
-#define OVERRIDE_AHB_SPEED_SHIFT       15
-
-/* Global PLL Control Register */
-#define GLOBAL_PLL_CTRL                        0x08
-
-#define PLL_BYPASS                     (1 << 31)
-#define PLL_POWER_DOWN                 (1 << 8)
-#define PLL_CONTROL_Q                  (0x1F << 0)
-
-/* Global Soft Reset Control Register */
-#define GLOBAL_RESET                   0x0C
-
-#define RESET_GLOBAL                   (1 << 31)
-#define RESET_CPU1                     (1 << 30)
-#define RESET_TVE                      (1 << 28)
-#define RESET_SATA1                    (1 << 27)
-#define RESET_SATA0                    (1 << 26)
-#define RESET_CIR                      (1 << 25)
-#define RESET_EXT_DEV                  (1 << 24)
-#define RESET_WD                       (1 << 23)
-#define RESET_GPIO2                    (1 << 22)
-#define RESET_GPIO1                    (1 << 21)
-#define RESET_GPIO0                    (1 << 20)
-#define RESET_SSP                      (1 << 19)
-#define RESET_UART                     (1 << 18)
-#define RESET_TIMER                    (1 << 17)
-#define RESET_RTC                      (1 << 16)
-#define RESET_INT1                     (1 << 15)
-#define RESET_INT0                     (1 << 14)
-#define RESET_LCD                      (1 << 13)
-#define RESET_LPC                      (1 << 12)
-#define RESET_APB                      (1 << 11)
-#define RESET_DMA                      (1 << 10)
-#define RESET_USB1                     (1 << 9)
-#define RESET_USB0                     (1 << 8)
-#define RESET_PCI                      (1 << 7)
-#define RESET_GMAC1                    (1 << 6)
-#define RESET_GMAC0                    (1 << 5)
-#define RESET_SECURITY                 (1 << 4)
-#define RESET_RAID                     (1 << 3)
-#define RESET_IDE                      (1 << 2)
-#define RESET_FLASH                    (1 << 1)
-#define RESET_DRAM                     (1 << 0)
-
-/* Global IO Pad Driving Capability Control Register */
-#define GLOBAL_IO_DRIVING_CTRL         0x10
-
-#define DRIVING_CURRENT_MASK           0x3
-
-/* here 00-4mA, 01-8mA, 10-12mA, 11-16mA */
-#define GPIO1_PADS_31_28_SHIFT         28
-#define GPIO0_PADS_31_16_SHIFT         26
-#define GPIO0_PADS_15_0_SHIFT          24
-#define PCI_AND_EXT_RESET_PADS_SHIFT   22
-#define IDE_PADS_SHIFT                 20
-#define GMAC1_PADS_SHIFT               18
-#define GMAC0_PADS_SHIFT               16
-/* DRAM is not in mA and poorly documented */
-#define DRAM_CLOCK_PADS_SHIFT          8
-#define DRAM_DATA_PADS_SHIFT           4
-#define DRAM_CONTROL_PADS_SHIFT                0
-
-/* Global IO Pad Slew Rate Control Register */
-#define GLOBAL_IO_SLEW_RATE_CTRL       0x14
-
-#define GPIO1_PADS_31_28_SLOW          (1 << 10)
-#define GPIO0_PADS_31_16_SLOW          (1 << 9)
-#define GPIO0_PADS_15_0_SLOW           (1 << 8)
-#define PCI_PADS_SLOW                  (1 << 7)
-#define IDE_PADS_SLOW                  (1 << 6)
-#define GMAC1_PADS_SLOW                        (1 << 5)
-#define GMAC0_PADS_SLOW                        (1 << 4)
-#define DRAM_CLOCK_PADS_SLOW           (1 << 1)
-#define DRAM_IO_PADS_SLOW              (1 << 0)
-
-/*
- * General skew control defines
- * 16 steps, each step is around 0.2ns
- */
-#define SKEW_MASK                      0xF
-
-/* Global IDE PAD Skew Control Register */
-#define GLOBAL_IDE_SKEW_CTRL           0x18
-
-#define IDE1_HOST_STROBE_DELAY_SHIFT   28
-#define IDE1_DEVICE_STROBE_DELAY_SHIFT 24
-#define IDE1_OUTPUT_IO_SKEW_SHIFT      20
-#define IDE1_INPUT_IO_SKEW_SHIFT       16
-#define IDE0_HOST_STROBE_DELAY_SHIFT   12
-#define IDE0_DEVICE_STROBE_DELAY_SHIFT 8
-#define IDE0_OUTPUT_IO_SKEW_SHIFT      4
-#define IDE0_INPUT_IO_SKEW_SHIFT       0
-
-/* Global GMAC Control Pad Skew Control Register */
-#define GLOBAL_GMAC_CTRL_SKEW_CTRL     0x1C
-
-#define GMAC1_TXC_SKEW_SHIFT           28
-#define GMAC1_TXEN_SKEW_SHIFT          24
-#define GMAC1_RXC_SKEW_SHIFT           20
-#define GMAC1_RXDV_SKEW_SHIFT          16
-#define GMAC0_TXC_SKEW_SHIFT           12
-#define GMAC0_TXEN_SKEW_SHIFT          8
-#define GMAC0_RXC_SKEW_SHIFT           4
-#define GMAC0_RXDV_SKEW_SHIFT          0
-
-/* Global GMAC0 Data PAD Skew Control Register */
-#define GLOBAL_GMAC0_DATA_SKEW_CTRL    0x20
-/* Global GMAC1 Data PAD Skew Control Register */
-#define GLOBAL_GMAC1_DATA_SKEW_CTRL    0x24
-
-#define GMAC_TXD_SKEW_SHIFT(x)         (((x) * 4) + 16)
-#define GMAC_RXD_SKEW_SHIFT(x)         ((x) * 4)
-
-/* CPU has two AHB busses. */
-
-/* Global Arbitration0 Control Register */
-#define GLOBAL_ARBITRATION0_CTRL       0x28
-
-#define BOOT_CONTROLLER_HIGH_PRIO      (1 << 3)
-#define DMA_BUS1_HIGH_PRIO             (1 << 2)
-#define CPU0_HIGH_PRIO                 (1 << 0)
-
-/* Global Arbitration1 Control Register */
-#define GLOBAL_ARBITRATION1_CTRL       0x2C
-
-#define TVE_HIGH_PRIO                  (1 << 9)
-#define PCI_HIGH_PRIO                  (1 << 8)
-#define USB1_HIGH_PRIO                 (1 << 7)
-#define USB0_HIGH_PRIO                 (1 << 6)
-#define GMAC1_HIGH_PRIO                        (1 << 5)
-#define GMAC0_HIGH_PRIO                        (1 << 4)
-#define SECURITY_HIGH_PRIO             (1 << 3)
-#define RAID_HIGH_PRIO                 (1 << 2)
-#define IDE_HIGH_PRIO                  (1 << 1)
-#define DMA_BUS2_HIGH_PRIO             (1 << 0)
-
-/* Common bits for both arbitration registers */
-#define BURST_LENGTH_SHIFT             16
-#define BURST_LENGTH_MASK              (0x3F << 16)
-
-/* Miscellaneous Control Register */
-#define GLOBAL_MISC_CTRL               0x30
-
-#define MEMORY_SPACE_SWAP              (1 << 31)
-#define USB1_PLUG_MINIB                        (1 << 30) /* else plug is mini-A */
-#define USB0_PLUG_MINIB                        (1 << 29)
-#define GMAC_GMII                      (1 << 28)
-#define GMAC_1_ENABLE                  (1 << 27)
-/* TODO: define ATA/SATA bits */
-#define USB1_VBUS_ON                   (1 << 23)
-#define USB0_VBUS_ON                   (1 << 22)
-#define APB_CLKOUT_ENABLE              (1 << 21)
-#define TVC_CLKOUT_ENABLE              (1 << 20)
-#define EXT_CLKIN_ENABLE               (1 << 19)
-#define PCI_66MHZ                      (1 << 18) /* else 33 MHz */
-#define PCI_CLKOUT_ENABLE              (1 << 17)
-#define LPC_CLKOUT_ENABLE              (1 << 16)
-#define USB1_WAKEUP_ON                 (1 << 15)
-#define USB0_WAKEUP_ON                 (1 << 14)
-/* TODO: define PCI idle detect bits */
-#define TVC_PADS_ENABLE                        (1 << 9)
-#define SSP_PADS_ENABLE                        (1 << 8)
-#define LCD_PADS_ENABLE                        (1 << 7)
-#define LPC_PADS_ENABLE                        (1 << 6)
-#define PCI_PADS_ENABLE                        (1 << 5)
-#define IDE_PADS_ENABLE                        (1 << 4)
-#define DRAM_PADS_POWER_DOWN           (1 << 3)
-#define NAND_PADS_DISABLE              (1 << 2)
-#define PFLASH_PADS_DISABLE            (1 << 1)
-#define SFLASH_PADS_DISABLE            (1 << 0)
-
-/* Global Clock Control Register */
-#define GLOBAL_CLOCK_CTRL              0x34
-
-#define POWER_STATE_G0                 (1 << 31)
-#define POWER_STATE_S1                 (1 << 30) /* else it is S3/S4 state */
-#define SECURITY_APB_AHB               (1 << 29)
-/* else Security APB clk will be 0.75xAHB */
-/* TODO: TVC clock divider */
-#define PCI_CLKRUN_ENABLE              (1 << 16)
-#define BOOT_CLK_DISABLE               (1 << 13)
-#define TVC_CLK_DISABLE                        (1 << 12)
-#define FLASH_CLK_DISABLE              (1 << 11)
-#define DDR_CLK_DISABLE                        (1 << 10)
-#define PCI_CLK_DISABLE                        (1 << 9)
-#define IDE_CLK_DISABLE                        (1 << 8)
-#define USB1_CLK_DISABLE               (1 << 7)
-#define USB0_CLK_DISABLE               (1 << 6)
-#define SATA1_CLK_DISABLE              (1 << 5)
-#define SATA0_CLK_DISABLE              (1 << 4)
-#define GMAC1_CLK_DISABLE              (1 << 3)
-#define GMAC0_CLK_DISABLE              (1 << 2)
-#define SECURITY_CLK_DISABLE           (1 << 1)
-
-/* TODO: other registers definitions if needed */
-
-#endif /* __MACH_GLOBAL_REG_H */
diff --git a/arch/arm/mach-gemini/include/mach/hardware.h b/arch/arm/mach-gemini/include/mach/hardware.h
deleted file mode 100644 (file)
index f0390f1..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- *  This file contains the hardware definitions for Gemini.
- *
- *  Copyright (C) 2001-2006 Storlink, Corp.
- *  Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-#ifndef __MACH_HARDWARE_H
-#define __MACH_HARDWARE_H
-
-/*
- * Memory Map definitions
- */
-#ifdef CONFIG_GEMINI_MEM_SWAP
-# define GEMINI_DRAM_BASE      0x00000000
-# define GEMINI_SRAM_BASE      0x70000000
-#else
-# define GEMINI_SRAM_BASE      0x00000000
-# define GEMINI_DRAM_BASE      0x10000000
-#endif
-#define GEMINI_FLASH_BASE      0x30000000
-#define GEMINI_GLOBAL_BASE     0x40000000
-#define GEMINI_WAQTCHDOG_BASE  0x41000000
-#define GEMINI_UART_BASE       0x42000000
-#define GEMINI_TIMER_BASE      0x43000000
-#define GEMINI_LCD_BASE                0x44000000
-#define GEMINI_RTC_BASE                0x45000000
-#define GEMINI_SATA_BASE       0x46000000
-#define GEMINI_LPC_HOST_BASE   0x47000000
-#define GEMINI_LPC_IO_BASE     0x47800000
-#define GEMINI_INTERRUPT_BASE  0x48000000
-/* TODO: Different interrupt controllers when SMP
- * #define GEMINI_INTERRUPT0_BASE      0x48000000
- * #define GEMINI_INTERRUPT1_BASE      0x49000000
- */
-#define GEMINI_SSP_CTRL_BASE   0x4A000000
-#define GEMINI_POWER_CTRL_BASE 0x4B000000
-#define GEMINI_CIR_BASE                0x4C000000
-#define GEMINI_GPIO_BASE(x)    (0x4D000000 + (x) * 0x1000000)
-#define GEMINI_PCI_IO_BASE     0x50000000
-#define GEMINI_PCI_MEM_BASE    0x58000000
-#define GEMINI_TOE_BASE                0x60000000
-#define GEMINI_GMAC0_BASE      0x6000A000
-#define GEMINI_GMAC1_BASE      0x6000E000
-#define GEMINI_SECURITY_BASE   0x62000000
-#define GEMINI_IDE0_BASE       0x63000000
-#define GEMINI_IDE1_BASE       0x63400000
-#define GEMINI_RAID_BASE       0x64000000
-#define GEMINI_FLASH_CTRL_BASE 0x65000000
-#define GEMINI_DRAM_CTRL_BASE  0x66000000
-#define GEMINI_GENERAL_DMA_BASE        0x67000000
-#define GEMINI_USB0_BASE       0x68000000
-#define GEMINI_USB1_BASE       0x69000000
-#define GEMINI_BIG_ENDIAN_BASE 0x80000000
-
-
-/*
- * UART Clock when System clk is 150MHz
- */
-#define UART_CLK       48000000
-
-/*
- * macro to get at IO space when running virtually
- */
-#define IO_ADDRESS(x)  IOMEM((((x) & 0xFFF00000) >> 4) | ((x) & 0x000FFFFF) | 0xF0000000)
-
-#endif
diff --git a/arch/arm/mach-gemini/include/mach/irqs.h b/arch/arm/mach-gemini/include/mach/irqs.h
deleted file mode 100644 (file)
index 06bc47e..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- *  Copyright (C) 2001-2006 Storlink, Corp.
- *  Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __MACH_IRQS_H__
-#define __MACH_IRQS_H__
-
-#define IRQ_SERIRQ1    31
-#define IRQ_SERIRQ0    30
-#define IRQ_PCID       29
-#define IRQ_PCIC       28
-#define IRQ_PCIB       27
-#define IRQ_PWR                26
-#define IRQ_CIR                25
-#define IRQ_GPIO(x)    (22 + (x))
-#define IRQ_SSP                21
-#define IRQ_LPC                20
-#define IRQ_LCD                19
-#define IRQ_UART       18
-#define IRQ_RTC                17
-#define IRQ_TIMER3     16
-#define IRQ_TIMER2     15
-#define IRQ_TIMER1     14
-#define IRQ_FLASH      12
-#define IRQ_USB1       11
-#define IRQ_USB0       10
-#define IRQ_DMA                9
-#define IRQ_PCI                8
-#define IRQ_IPSEC      7
-#define IRQ_RAID       6
-#define IRQ_IDE1       5
-#define IRQ_IDE0       4
-#define IRQ_WATCHDOG   3
-#define IRQ_GMAC1      2
-#define IRQ_GMAC0      1
-#define IRQ_IPI                0
-
-#define NORMAL_IRQ_NUM 32
-
-#define GPIO_IRQ_BASE  NORMAL_IRQ_NUM
-#define GPIO_IRQ_NUM   (3 * 32)
-
-#define ARCH_TIMER_IRQ IRQ_TIMER2
-
-#define NR_IRQS                (NORMAL_IRQ_NUM + GPIO_IRQ_NUM)
-
-#endif /* __MACH_IRQS_H__ */
diff --git a/arch/arm/mach-gemini/include/mach/uncompress.h b/arch/arm/mach-gemini/include/mach/uncompress.h
deleted file mode 100644 (file)
index 02e2256..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
- *
- * Based on mach-pxa/include/mach/uncompress.h:
- * Copyright:  (C) 2001 MontaVista Software Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef __MACH_UNCOMPRESS_H
-#define __MACH_UNCOMPRESS_H
-
-#include <linux/serial_reg.h>
-#include <mach/hardware.h>
-
-static volatile unsigned long * const UART = (unsigned long *)GEMINI_UART_BASE;
-
-/*
- * The following code assumes the serial port has already been
- * initialized by the bootloader.  If you didn't setup a port in
- * your bootloader then nothing will appear (which might be desired).
- */
-static inline void putc(char c)
-{
-       while (!(UART[UART_LSR] & UART_LSR_THRE))
-               barrier();
-       UART[UART_TX] = c;
-}
-
-static inline void flush(void)
-{
-}
-
-/*
- * nothing to do
- */
-#define arch_decomp_setup()
-
-#endif /* __MACH_UNCOMPRESS_H */
diff --git a/arch/arm/mach-gemini/irq.c b/arch/arm/mach-gemini/irq.c
deleted file mode 100644 (file)
index d929b3f..0000000
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- *  Interrupt routines for Gemini
- *
- *  Copyright (C) 2001-2006 Storlink, Corp.
- *  Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/ioport.h>
-#include <linux/stddef.h>
-#include <linux/list.h>
-#include <linux/sched.h>
-#include <linux/cpu.h>
-
-#include <asm/irq.h>
-#include <asm/mach/irq.h>
-#include <asm/system_misc.h>
-#include <mach/hardware.h>
-
-#define IRQ_SOURCE(base_addr)  (base_addr + 0x00)
-#define IRQ_MASK(base_addr)    (base_addr + 0x04)
-#define IRQ_CLEAR(base_addr)   (base_addr + 0x08)
-#define IRQ_TMODE(base_addr)   (base_addr + 0x0C)
-#define IRQ_TLEVEL(base_addr)  (base_addr + 0x10)
-#define IRQ_STATUS(base_addr)  (base_addr + 0x14)
-#define FIQ_SOURCE(base_addr)  (base_addr + 0x20)
-#define FIQ_MASK(base_addr)    (base_addr + 0x24)
-#define FIQ_CLEAR(base_addr)   (base_addr + 0x28)
-#define FIQ_TMODE(base_addr)   (base_addr + 0x2C)
-#define FIQ_LEVEL(base_addr)   (base_addr + 0x30)
-#define FIQ_STATUS(base_addr)  (base_addr + 0x34)
-
-static void gemini_ack_irq(struct irq_data *d)
-{
-       __raw_writel(1 << d->irq, IRQ_CLEAR(IO_ADDRESS(GEMINI_INTERRUPT_BASE)));
-}
-
-static void gemini_mask_irq(struct irq_data *d)
-{
-       unsigned int mask;
-
-       mask = __raw_readl(IRQ_MASK(IO_ADDRESS(GEMINI_INTERRUPT_BASE)));
-       mask &= ~(1 << d->irq);
-       __raw_writel(mask, IRQ_MASK(IO_ADDRESS(GEMINI_INTERRUPT_BASE)));
-}
-
-static void gemini_unmask_irq(struct irq_data *d)
-{
-       unsigned int mask;
-
-       mask = __raw_readl(IRQ_MASK(IO_ADDRESS(GEMINI_INTERRUPT_BASE)));
-       mask |= (1 << d->irq);
-       __raw_writel(mask, IRQ_MASK(IO_ADDRESS(GEMINI_INTERRUPT_BASE)));
-}
-
-static struct irq_chip gemini_irq_chip = {
-       .name           = "INTC",
-       .irq_ack        = gemini_ack_irq,
-       .irq_mask       = gemini_mask_irq,
-       .irq_unmask     = gemini_unmask_irq,
-};
-
-static struct resource irq_resource = {
-       .name   = "irq_handler",
-       .start  = GEMINI_INTERRUPT_BASE,
-       .end    = FIQ_STATUS(GEMINI_INTERRUPT_BASE) + 4,
-};
-
-void __init gemini_init_irq(void)
-{
-       unsigned int i, mode = 0, level = 0;
-
-       /*
-        * Disable the idle handler by default since it is buggy
-        * For more info see arch/arm/mach-gemini/idle.c
-        */
-       cpu_idle_poll_ctrl(true);
-
-       request_resource(&iomem_resource, &irq_resource);
-
-       for (i = 0; i < NR_IRQS; i++) {
-               irq_set_chip(i, &gemini_irq_chip);
-               if((i >= IRQ_TIMER1 && i <= IRQ_TIMER3) || (i >= IRQ_SERIRQ0 && i <= IRQ_SERIRQ1)) {
-                       irq_set_handler(i, handle_edge_irq);
-                       mode |= 1 << i;
-                       level |= 1 << i;
-               } else {                        
-                       irq_set_handler(i, handle_level_irq);
-               }
-               irq_clear_status_flags(i, IRQ_NOREQUEST | IRQ_NOPROBE);
-       }
-
-       /* Disable all interrupts */
-       __raw_writel(0, IRQ_MASK(IO_ADDRESS(GEMINI_INTERRUPT_BASE)));
-       __raw_writel(0, FIQ_MASK(IO_ADDRESS(GEMINI_INTERRUPT_BASE)));
-
-       /* Set interrupt mode */
-       __raw_writel(mode, IRQ_TMODE(IO_ADDRESS(GEMINI_INTERRUPT_BASE)));
-       __raw_writel(level, IRQ_TLEVEL(IO_ADDRESS(GEMINI_INTERRUPT_BASE)));
-}
diff --git a/arch/arm/mach-gemini/mm.c b/arch/arm/mach-gemini/mm.c
deleted file mode 100644 (file)
index 2c2cd28..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- *  Static mappings for Gemini
- *
- *  Copyright (C) 2001-2006 Storlink, Corp.
- *  Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-#include <linux/mm.h>
-#include <linux/init.h>
-
-#include <asm/mach/map.h>
-
-#include <mach/hardware.h>
-
-/* Page table mapping for I/O region */
-static struct map_desc gemini_io_desc[] __initdata = {
-       {
-               .virtual        = (unsigned long)IO_ADDRESS(GEMINI_GLOBAL_BASE),
-               .pfn            =__phys_to_pfn(GEMINI_GLOBAL_BASE),
-               .length         = SZ_512K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = (unsigned long)IO_ADDRESS(GEMINI_UART_BASE),
-               .pfn            = __phys_to_pfn(GEMINI_UART_BASE),
-               .length         = SZ_512K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = (unsigned long)IO_ADDRESS(GEMINI_TIMER_BASE),
-               .pfn            = __phys_to_pfn(GEMINI_TIMER_BASE),
-               .length         = SZ_512K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = (unsigned long)IO_ADDRESS(GEMINI_INTERRUPT_BASE),
-               .pfn            = __phys_to_pfn(GEMINI_INTERRUPT_BASE),
-               .length         = SZ_512K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = (unsigned long)IO_ADDRESS(GEMINI_POWER_CTRL_BASE),
-               .pfn            = __phys_to_pfn(GEMINI_POWER_CTRL_BASE),
-               .length         = SZ_512K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = (unsigned long)IO_ADDRESS(GEMINI_GPIO_BASE(0)),
-               .pfn            = __phys_to_pfn(GEMINI_GPIO_BASE(0)),
-               .length         = SZ_512K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = (unsigned long)IO_ADDRESS(GEMINI_GPIO_BASE(1)),
-               .pfn            = __phys_to_pfn(GEMINI_GPIO_BASE(1)),
-               .length         = SZ_512K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = (unsigned long)IO_ADDRESS(GEMINI_GPIO_BASE(2)),
-               .pfn            = __phys_to_pfn(GEMINI_GPIO_BASE(2)),
-               .length         = SZ_512K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = (unsigned long)IO_ADDRESS(GEMINI_FLASH_CTRL_BASE),
-               .pfn            = __phys_to_pfn(GEMINI_FLASH_CTRL_BASE),
-               .length         = SZ_512K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = (unsigned long)IO_ADDRESS(GEMINI_DRAM_CTRL_BASE),
-               .pfn            = __phys_to_pfn(GEMINI_DRAM_CTRL_BASE),
-               .length         = SZ_512K,
-               .type           = MT_DEVICE,
-       }, {
-               .virtual        = (unsigned long)IO_ADDRESS(GEMINI_GENERAL_DMA_BASE),
-               .pfn            = __phys_to_pfn(GEMINI_GENERAL_DMA_BASE),
-               .length         = SZ_512K,
-               .type           = MT_DEVICE,
-       },
-};
-
-void __init gemini_map_io(void)
-{
-       iotable_init(gemini_io_desc, ARRAY_SIZE(gemini_io_desc));
-}
diff --git a/arch/arm/mach-gemini/reset.c b/arch/arm/mach-gemini/reset.c
deleted file mode 100644 (file)
index 21a6d6d..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- *  Copyright (C) 2001-2006 Storlink, Corp.
- *  Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-#ifndef __MACH_SYSTEM_H
-#define __MACH_SYSTEM_H
-
-#include <linux/io.h>
-#include <mach/hardware.h>
-#include <mach/global_reg.h>
-
-#include "common.h"
-
-void gemini_restart(enum reboot_mode mode, const char *cmd)
-{
-       __raw_writel(RESET_GLOBAL | RESET_CPU1,
-                    IO_ADDRESS(GEMINI_GLOBAL_BASE) + GLOBAL_RESET);
-}
-
-#endif /* __MACH_SYSTEM_H */
diff --git a/arch/arm/mach-gemini/time.c b/arch/arm/mach-gemini/time.c
deleted file mode 100644 (file)
index f5f18df..0000000
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- *  Copyright (C) 2001-2006 Storlink, Corp.
- *  Copyright (C) 2008-2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <mach/hardware.h>
-#include <mach/global_reg.h>
-#include <asm/mach/time.h>
-#include <linux/clockchips.h>
-#include <linux/clocksource.h>
-#include <linux/sched_clock.h>
-
-/*
- * Register definitions for the timers
- */
-
-#define TIMER1_BASE            GEMINI_TIMER_BASE
-#define TIMER2_BASE            (GEMINI_TIMER_BASE + 0x10)
-#define TIMER3_BASE            (GEMINI_TIMER_BASE + 0x20)
-
-#define TIMER_COUNT(BASE)      (IO_ADDRESS(BASE) + 0x00)
-#define TIMER_LOAD(BASE)       (IO_ADDRESS(BASE) + 0x04)
-#define TIMER_MATCH1(BASE)     (IO_ADDRESS(BASE) + 0x08)
-#define TIMER_MATCH2(BASE)     (IO_ADDRESS(BASE) + 0x0C)
-#define TIMER_CR               (IO_ADDRESS(GEMINI_TIMER_BASE) + 0x30)
-#define TIMER_INTR_STATE       (IO_ADDRESS(GEMINI_TIMER_BASE) + 0x34)
-#define TIMER_INTR_MASK                (IO_ADDRESS(GEMINI_TIMER_BASE) + 0x38)
-
-#define TIMER_1_CR_ENABLE      (1 << 0)
-#define TIMER_1_CR_CLOCK       (1 << 1)
-#define TIMER_1_CR_INT         (1 << 2)
-#define TIMER_2_CR_ENABLE      (1 << 3)
-#define TIMER_2_CR_CLOCK       (1 << 4)
-#define TIMER_2_CR_INT         (1 << 5)
-#define TIMER_3_CR_ENABLE      (1 << 6)
-#define TIMER_3_CR_CLOCK       (1 << 7)
-#define TIMER_3_CR_INT         (1 << 8)
-#define TIMER_1_CR_UPDOWN      (1 << 9)
-#define TIMER_2_CR_UPDOWN      (1 << 10)
-#define TIMER_3_CR_UPDOWN      (1 << 11)
-#define TIMER_DEFAULT_FLAGS    (TIMER_1_CR_UPDOWN | \
-                                TIMER_3_CR_ENABLE | \
-                                TIMER_3_CR_UPDOWN)
-
-#define TIMER_1_INT_MATCH1     (1 << 0)
-#define TIMER_1_INT_MATCH2     (1 << 1)
-#define TIMER_1_INT_OVERFLOW   (1 << 2)
-#define TIMER_2_INT_MATCH1     (1 << 3)
-#define TIMER_2_INT_MATCH2     (1 << 4)
-#define TIMER_2_INT_OVERFLOW   (1 << 5)
-#define TIMER_3_INT_MATCH1     (1 << 6)
-#define TIMER_3_INT_MATCH2     (1 << 7)
-#define TIMER_3_INT_OVERFLOW   (1 << 8)
-#define TIMER_INT_ALL_MASK     0x1ff
-
-
-static unsigned int tick_rate;
-
-static u64 notrace gemini_read_sched_clock(void)
-{
-       return readl(TIMER_COUNT(TIMER3_BASE));
-}
-
-static int gemini_timer_set_next_event(unsigned long cycles,
-                                      struct clock_event_device *evt)
-{
-       u32 cr;
-
-       /* Setup the match register */
-       cr = readl(TIMER_COUNT(TIMER1_BASE));
-       writel(cr + cycles, TIMER_MATCH1(TIMER1_BASE));
-       if (readl(TIMER_COUNT(TIMER1_BASE)) - cr > cycles)
-               return -ETIME;
-
-       return 0;
-}
-
-static int gemini_timer_shutdown(struct clock_event_device *evt)
-{
-       u32 cr;
-
-       /*
-        * Disable also for oneshot: the set_next() call will arm the timer
-        * instead.
-        */
-       /* Stop timer and interrupt. */
-       cr = readl(TIMER_CR);
-       cr &= ~(TIMER_1_CR_ENABLE | TIMER_1_CR_INT);
-       writel(cr, TIMER_CR);
-
-       /* Setup counter start from 0 */
-       writel(0, TIMER_COUNT(TIMER1_BASE));
-       writel(0, TIMER_LOAD(TIMER1_BASE));
-
-       /* enable interrupt */
-       cr = readl(TIMER_INTR_MASK);
-       cr &= ~(TIMER_1_INT_OVERFLOW | TIMER_1_INT_MATCH2);
-       cr |= TIMER_1_INT_MATCH1;
-       writel(cr, TIMER_INTR_MASK);
-
-       /* start the timer */
-       cr = readl(TIMER_CR);
-       cr |= TIMER_1_CR_ENABLE;
-       writel(cr, TIMER_CR);
-
-       return 0;
-}
-
-static int gemini_timer_set_periodic(struct clock_event_device *evt)
-{
-       u32 period = DIV_ROUND_CLOSEST(tick_rate, HZ);
-       u32 cr;
-
-       /* Stop timer and interrupt */
-       cr = readl(TIMER_CR);
-       cr &= ~(TIMER_1_CR_ENABLE | TIMER_1_CR_INT);
-       writel(cr, TIMER_CR);
-
-       /* Setup timer to fire at 1/HT intervals. */
-       cr = 0xffffffff - (period - 1);
-       writel(cr, TIMER_COUNT(TIMER1_BASE));
-       writel(cr, TIMER_LOAD(TIMER1_BASE));
-
-       /* enable interrupt on overflow */
-       cr = readl(TIMER_INTR_MASK);
-       cr &= ~(TIMER_1_INT_MATCH1 | TIMER_1_INT_MATCH2);
-       cr |= TIMER_1_INT_OVERFLOW;
-       writel(cr, TIMER_INTR_MASK);
-
-       /* Start the timer */
-       cr = readl(TIMER_CR);
-       cr |= TIMER_1_CR_ENABLE;
-       cr |= TIMER_1_CR_INT;
-       writel(cr, TIMER_CR);
-
-       return 0;
-}
-
-/* Use TIMER1 as clock event */
-static struct clock_event_device gemini_clockevent = {
-       .name                   = "TIMER1",
-       /* Reasonably fast and accurate clock event */
-       .rating                 = 300,
-       .shift                  = 32,
-       .features               = CLOCK_EVT_FEAT_PERIODIC |
-                                 CLOCK_EVT_FEAT_ONESHOT,
-       .set_next_event         = gemini_timer_set_next_event,
-       .set_state_shutdown     = gemini_timer_shutdown,
-       .set_state_periodic     = gemini_timer_set_periodic,
-       .set_state_oneshot      = gemini_timer_shutdown,
-       .tick_resume            = gemini_timer_shutdown,
-};
-
-/*
- * IRQ handler for the timer
- */
-static irqreturn_t gemini_timer_interrupt(int irq, void *dev_id)
-{
-       struct clock_event_device *evt = &gemini_clockevent;
-
-       evt->event_handler(evt);
-       return IRQ_HANDLED;
-}
-
-static struct irqaction gemini_timer_irq = {
-       .name           = "Gemini Timer Tick",
-       .flags          = IRQF_TIMER,
-       .handler        = gemini_timer_interrupt,
-};
-
-/*
- * Set up timer interrupt, and return the current time in seconds.
- */
-void __init gemini_timer_init(void)
-{
-       u32 reg_v;
-
-       reg_v = readl(IO_ADDRESS(GEMINI_GLOBAL_BASE + GLOBAL_STATUS));
-       tick_rate = REG_TO_AHB_SPEED(reg_v) * 1000000;
-
-       printk(KERN_INFO "Bus: %dMHz", tick_rate / 1000000);
-
-       tick_rate /= 6;         /* APB bus run AHB*(1/6) */
-
-       switch(reg_v & CPU_AHB_RATIO_MASK) {
-       case CPU_AHB_1_1:
-               printk(KERN_CONT "(1/1)\n");
-               break;
-       case CPU_AHB_3_2:
-               printk(KERN_CONT "(3/2)\n");
-               break;
-       case CPU_AHB_24_13:
-               printk(KERN_CONT "(24/13)\n");
-               break;
-       case CPU_AHB_2_1:
-               printk(KERN_CONT "(2/1)\n");
-               break;
-       }
-
-       /*
-        * Reset the interrupt mask and status
-        */
-       writel(TIMER_INT_ALL_MASK, TIMER_INTR_MASK);
-       writel(0, TIMER_INTR_STATE);
-       writel(TIMER_DEFAULT_FLAGS, TIMER_CR);
-
-       /*
-        * Setup free-running clocksource timer (interrupts
-        * disabled.)
-        */
-       writel(0, TIMER_COUNT(TIMER3_BASE));
-       writel(0, TIMER_LOAD(TIMER3_BASE));
-       writel(0, TIMER_MATCH1(TIMER3_BASE));
-       writel(0, TIMER_MATCH2(TIMER3_BASE));
-       clocksource_mmio_init(TIMER_COUNT(TIMER3_BASE),
-                             "gemini_clocksource", tick_rate,
-                             300, 32, clocksource_mmio_readl_up);
-       sched_clock_register(gemini_read_sched_clock, 32, tick_rate);
-
-       /*
-        * Setup clockevent timer (interrupt-driven.)
-       */
-       writel(0, TIMER_COUNT(TIMER1_BASE));
-       writel(0, TIMER_LOAD(TIMER1_BASE));
-       writel(0, TIMER_MATCH1(TIMER1_BASE));
-       writel(0, TIMER_MATCH2(TIMER1_BASE));
-       setup_irq(IRQ_TIMER1, &gemini_timer_irq);
-       gemini_clockevent.cpumask = cpumask_of(0);
-       clockevents_config_and_register(&gemini_clockevent, tick_rate,
-                                       1, 0xffffffff);
-
-}
index a6c117622d67619ae4eccc7f720b785878935585..f66815c3dd07e4708e8a4f7dd1a19f733c0b35a8 100644 (file)
@@ -279,6 +279,8 @@ static int __init hip04_smp_init(void)
                                         &hip04_boot_method[0], 4);
        if (ret)
                goto err;
+
+       ret = -ENODEV;
        np_sctl = of_find_compatible_node(NULL, NULL, "hisilicon,sysctrl");
        if (!np_sctl)
                goto err;
index 1dc2a34b9dbd452531479d0766187c8547cb13fd..93f584ba0130eb480b001d98946d9981da19d34c 100644 (file)
  * http://www.gnu.org/copyleft/gpl.html
  */
 
-#include <linux/clk.h>
-#include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/irq.h>
 #include <linux/irqchip.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
-#include <linux/platform_device.h>
-#include <linux/pm_domain.h>
-#include <linux/regulator/consumer.h>
 #include <linux/irqchip/arm-gic.h>
 #include "common.h"
 #include "hardware.h"
 
-#define GPC_CNTR               0x000
 #define GPC_IMR1               0x008
-#define GPC_PGC_GPU_PDN                0x260
-#define GPC_PGC_GPU_PUPSCR     0x264
-#define GPC_PGC_GPU_PDNSCR     0x268
 #define GPC_PGC_CPU_PDN                0x2a0
 #define GPC_PGC_CPU_PUPSCR     0x2a4
 #define GPC_PGC_CPU_PDNSCR     0x2a8
 #define IMR_NUM                        4
 #define GPC_MAX_IRQS           (IMR_NUM * 32)
 
-#define GPU_VPU_PUP_REQ                BIT(1)
-#define GPU_VPU_PDN_REQ                BIT(0)
-
-#define GPC_CLK_MAX            6
-
-struct pu_domain {
-       struct generic_pm_domain base;
-       struct regulator *reg;
-       struct clk *clk[GPC_CLK_MAX];
-       int num_clks;
-};
-
 static void __iomem *gpc_base;
 static u32 gpc_wake_irqs[IMR_NUM];
 static u32 gpc_saved_imrs[IMR_NUM];
@@ -296,199 +275,3 @@ void __init imx_gpc_check_dt(void)
                gpc_base = of_iomap(np, 0);
        }
 }
-
-static void _imx6q_pm_pu_power_off(struct generic_pm_domain *genpd)
-{
-       int iso, iso2sw;
-       u32 val;
-
-       /* Read ISO and ISO2SW power down delays */
-       val = readl_relaxed(gpc_base + GPC_PGC_GPU_PDNSCR);
-       iso = val & 0x3f;
-       iso2sw = (val >> 8) & 0x3f;
-
-       /* Gate off PU domain when GPU/VPU when powered down */
-       writel_relaxed(0x1, gpc_base + GPC_PGC_GPU_PDN);
-
-       /* Request GPC to power down GPU/VPU */
-       val = readl_relaxed(gpc_base + GPC_CNTR);
-       val |= GPU_VPU_PDN_REQ;
-       writel_relaxed(val, gpc_base + GPC_CNTR);
-
-       /* Wait ISO + ISO2SW IPG clock cycles */
-       ndelay((iso + iso2sw) * 1000 / 66);
-}
-
-static int imx6q_pm_pu_power_off(struct generic_pm_domain *genpd)
-{
-       struct pu_domain *pu = container_of(genpd, struct pu_domain, base);
-
-       _imx6q_pm_pu_power_off(genpd);
-
-       if (pu->reg)
-               regulator_disable(pu->reg);
-
-       return 0;
-}
-
-static int imx6q_pm_pu_power_on(struct generic_pm_domain *genpd)
-{
-       struct pu_domain *pu = container_of(genpd, struct pu_domain, base);
-       int i, ret, sw, sw2iso;
-       u32 val;
-
-       if (pu->reg)
-               ret = regulator_enable(pu->reg);
-       if (pu->reg && ret) {
-               pr_err("%s: failed to enable regulator: %d\n", __func__, ret);
-               return ret;
-       }
-
-       /* Enable reset clocks for all devices in the PU domain */
-       for (i = 0; i < pu->num_clks; i++)
-               clk_prepare_enable(pu->clk[i]);
-
-       /* Gate off PU domain when GPU/VPU when powered down */
-       writel_relaxed(0x1, gpc_base + GPC_PGC_GPU_PDN);
-
-       /* Read ISO and ISO2SW power down delays */
-       val = readl_relaxed(gpc_base + GPC_PGC_GPU_PUPSCR);
-       sw = val & 0x3f;
-       sw2iso = (val >> 8) & 0x3f;
-
-       /* Request GPC to power up GPU/VPU */
-       val = readl_relaxed(gpc_base + GPC_CNTR);
-       val |= GPU_VPU_PUP_REQ;
-       writel_relaxed(val, gpc_base + GPC_CNTR);
-
-       /* Wait ISO + ISO2SW IPG clock cycles */
-       ndelay((sw + sw2iso) * 1000 / 66);
-
-       /* Disable reset clocks for all devices in the PU domain */
-       for (i = 0; i < pu->num_clks; i++)
-               clk_disable_unprepare(pu->clk[i]);
-
-       return 0;
-}
-
-static struct generic_pm_domain imx6q_arm_domain = {
-       .name = "ARM",
-};
-
-static struct pu_domain imx6q_pu_domain = {
-       .base = {
-               .name = "PU",
-               .power_off = imx6q_pm_pu_power_off,
-               .power_on = imx6q_pm_pu_power_on,
-       },
-};
-
-static struct generic_pm_domain imx6sl_display_domain = {
-       .name = "DISPLAY",
-};
-
-static struct generic_pm_domain *imx_gpc_domains[] = {
-       &imx6q_arm_domain,
-       &imx6q_pu_domain.base,
-       &imx6sl_display_domain,
-};
-
-static struct genpd_onecell_data imx_gpc_onecell_data = {
-       .domains = imx_gpc_domains,
-       .num_domains = ARRAY_SIZE(imx_gpc_domains),
-};
-
-static int imx_gpc_genpd_init(struct device *dev, struct regulator *pu_reg)
-{
-       struct clk *clk;
-       int i, ret;
-
-       imx6q_pu_domain.reg = pu_reg;
-
-       for (i = 0; ; i++) {
-               clk = of_clk_get(dev->of_node, i);
-               if (IS_ERR(clk))
-                       break;
-               if (i >= GPC_CLK_MAX) {
-                       dev_err(dev, "more than %d clocks\n", GPC_CLK_MAX);
-                       goto clk_err;
-               }
-               imx6q_pu_domain.clk[i] = clk;
-       }
-       imx6q_pu_domain.num_clks = i;
-
-       /* Enable power always in case bootloader disabled it. */
-       imx6q_pm_pu_power_on(&imx6q_pu_domain.base);
-
-       if (!IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS))
-               return 0;
-
-       imx6q_pu_domain.base.states = devm_kzalloc(dev,
-                                       sizeof(*imx6q_pu_domain.base.states),
-                                       GFP_KERNEL);
-       if (!imx6q_pu_domain.base.states)
-               return -ENOMEM;
-
-       imx6q_pu_domain.base.states[0].power_off_latency_ns = 25000;
-       imx6q_pu_domain.base.states[0].power_on_latency_ns = 2000000;
-       imx6q_pu_domain.base.state_count = 1;
-
-       for (i = 0; i < ARRAY_SIZE(imx_gpc_domains); i++)
-               pm_genpd_init(imx_gpc_domains[i], NULL, false);
-
-       ret =  of_genpd_add_provider_onecell(dev->of_node,
-                                            &imx_gpc_onecell_data);
-       if (ret)
-               goto power_off;
-
-       return 0;
-
-power_off:
-       imx6q_pm_pu_power_off(&imx6q_pu_domain.base);
-clk_err:
-       while (i--)
-               clk_put(imx6q_pu_domain.clk[i]);
-       imx6q_pu_domain.reg = NULL;
-       return -EINVAL;
-}
-
-static int imx_gpc_probe(struct platform_device *pdev)
-{
-       struct regulator *pu_reg;
-       int ret;
-
-       /* bail out if DT too old and doesn't provide the necessary info */
-       if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells"))
-               return 0;
-
-       pu_reg = devm_regulator_get_optional(&pdev->dev, "pu");
-       if (PTR_ERR(pu_reg) == -ENODEV)
-               pu_reg = NULL;
-       if (IS_ERR(pu_reg)) {
-               ret = PTR_ERR(pu_reg);
-               dev_err(&pdev->dev, "failed to get pu regulator: %d\n", ret);
-               return ret;
-       }
-
-       return imx_gpc_genpd_init(&pdev->dev, pu_reg);
-}
-
-static const struct of_device_id imx_gpc_dt_ids[] = {
-       { .compatible = "fsl,imx6q-gpc" },
-       { .compatible = "fsl,imx6sl-gpc" },
-       { }
-};
-
-static struct platform_driver imx_gpc_driver = {
-       .driver = {
-               .name = "imx-gpc",
-               .of_match_table = imx_gpc_dt_ids,
-       },
-       .probe = imx_gpc_probe,
-};
-
-static int __init imx_pgc_init(void)
-{
-       return platform_driver_register(&imx_gpc_driver);
-}
-subsys_initcall(imx_pgc_init);
index 32dcb5e99e23312709231d4d8809407a654989cb..353b86e3808f93afa297d3ce961a001cab43270c 100644 (file)
@@ -23,6 +23,11 @@ static void __init imx25_init_early(void)
        mxc_set_cpu_type(MXC_CPU_MX25);
 }
 
+static void __init imx25_dt_init(void)
+{
+       imx_aips_allow_unprivileged_access("fsl,imx25-aips");
+}
+
 static void __init mx25_init_irq(void)
 {
        struct device_node *np;
@@ -41,6 +46,7 @@ static const char * const imx25_dt_board_compat[] __initconst = {
 
 DT_MACHINE_START(IMX25_DT, "Freescale i.MX25 (Device Tree Support)")
        .init_early     = imx25_init_early,
+       .init_machine   = imx25_dt_init,
        .init_late      = imx25_pm_init,
        .init_irq       = mx25_init_irq,
        .dt_compat      = imx25_dt_board_compat,
index 558e5f8589cbafccd2504b030e71833cfbc5f2fd..68c3f0799d5bbab62ce2cb9b94788014e6998800 100644 (file)
@@ -375,6 +375,8 @@ static struct imx_ssi_platform_data mx31_3ds_ssi_pdata = {
 
 /* SPI */
 static int spi0_internal_chipselect[] = {
+       MXC_SPI_CS(0),
+       MXC_SPI_CS(1),
        MXC_SPI_CS(2),
 };
 
@@ -385,6 +387,7 @@ static const struct spi_imx_master spi0_pdata __initconst = {
 
 static int spi1_internal_chipselect[] = {
        MXC_SPI_CS(0),
+       MXC_SPI_CS(1),
        MXC_SPI_CS(2),
 };
 
@@ -398,7 +401,7 @@ static struct spi_board_info mx31_3ds_spi_devs[] __initdata = {
                .modalias       = "mc13783",
                .max_speed_hz   = 1000000,
                .bus_num        = 1,
-               .chip_select    = 1, /* SS2 */
+               .chip_select    = 2, /* SS2 */
                .platform_data  = &mc13783_pdata,
                /* irq number is run-time assigned */
                .mode = SPI_CS_HIGH,
@@ -406,7 +409,7 @@ static struct spi_board_info mx31_3ds_spi_devs[] __initdata = {
                .modalias       = "l4f00242t03",
                .max_speed_hz   = 5000000,
                .bus_num        = 0,
-               .chip_select    = 0, /* SS2 */
+               .chip_select    = 2, /* SS2 */
                .platform_data  = &mx31_3ds_l4f00242t03_pdata,
        },
 };
index cc867682520ef144cc6d54ced7e3285c2044b55d..bde9a9af67142ad2c3867b998aaee5d0426fda4e 100644 (file)
@@ -296,14 +296,14 @@ static struct spi_board_info moboard_spi_board_info[] __initdata = {
                /* irq number is run-time assigned */
                .max_speed_hz = 300000,
                .bus_num = 1,
-               .chip_select = 0,
+               .chip_select = 1,
                .platform_data = &moboard_pmic,
                .mode = SPI_CS_HIGH,
        },
 };
 
 static int moboard_spi2_cs[] = {
-       MXC_SPI_CS(1),
+       MXC_SPI_CS(0), MXC_SPI_CS(1),
 };
 
 static const struct spi_imx_master moboard_spi2_pdata __initconst = {
index 8fd8255068eed31bce063e3db0d3b8a9f903c605..95bd97710494e4e0041ad36c82ef0e0eaa220003 100644 (file)
@@ -50,13 +50,13 @@ static struct spi_board_info pcm037_spi_dev[] = {
                .modalias       = "dac124s085",
                .max_speed_hz   = 400000,
                .bus_num        = 0,
-               .chip_select    = 0,            /* Index in pcm037_spi1_cs[] */
+               .chip_select    = 1,            /* Index in pcm037_spi1_cs[] */
                .mode           = SPI_CPHA,
        },
 };
 
 /* Platform Data for MXC CSPI */
-static int pcm037_spi1_cs[] = {MXC_SPI_CS(1), IOMUX_TO_GPIO(MX31_PIN_KEY_COL7)};
+static int pcm037_spi1_cs[] = { MXC_SPI_CS(0), MXC_SPI_CS(1), };
 
 static const struct spi_imx_master pcm037_spi1_pdata __initconst = {
        .chipselect = pcm037_spi1_cs,
index c03bf28d8bbc9a1a3f2be4187465c3cb674e25f1..78262899a59031f8e5af1bc097fc71495cde294f 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright 2017 NXP
  * Copyright 2011,2016 Freescale Semiconductor, Inc.
  * Copyright 2011 Linaro Ltd.
  *
@@ -47,6 +48,7 @@
 #define PROFILE_SEL            0x10
 
 #define MMDC_MADPCR0   0x410
+#define MMDC_MADPCR1   0x414
 #define MMDC_MADPSR0   0x418
 #define MMDC_MADPSR1   0x41C
 #define MMDC_MADPSR2   0x420
@@ -57,6 +59,7 @@
 #define MMDC_NUM_COUNTERS      6
 
 #define MMDC_FLAG_PROFILE_SEL  0x1
+#define MMDC_PRF_AXI_ID_CLEAR  0x0
 
 #define to_mmdc_pmu(p) container_of(p, struct mmdc_pmu, pmu)
 
@@ -87,7 +90,7 @@ static DEFINE_IDA(mmdc_ida);
 PMU_EVENT_ATTR_STRING(total-cycles, mmdc_pmu_total_cycles, "event=0x00")
 PMU_EVENT_ATTR_STRING(busy-cycles, mmdc_pmu_busy_cycles, "event=0x01")
 PMU_EVENT_ATTR_STRING(read-accesses, mmdc_pmu_read_accesses, "event=0x02")
-PMU_EVENT_ATTR_STRING(write-accesses, mmdc_pmu_write_accesses, "config=0x03")
+PMU_EVENT_ATTR_STRING(write-accesses, mmdc_pmu_write_accesses, "event=0x03")
 PMU_EVENT_ATTR_STRING(read-bytes, mmdc_pmu_read_bytes, "event=0x04")
 PMU_EVENT_ATTR_STRING(read-bytes.unit, mmdc_pmu_read_bytes_unit, "MB");
 PMU_EVENT_ATTR_STRING(read-bytes.scale, mmdc_pmu_read_bytes_scale, "0.000001");
@@ -161,8 +164,11 @@ static struct attribute_group mmdc_pmu_events_attr_group = {
 };
 
 PMU_FORMAT_ATTR(event, "config:0-63");
+PMU_FORMAT_ATTR(axi_id, "config1:0-63");
+
 static struct attribute *mmdc_pmu_format_attrs[] = {
        &format_attr_event.attr,
+       &format_attr_axi_id.attr,
        NULL,
 };
 
@@ -345,6 +351,14 @@ static void mmdc_pmu_event_start(struct perf_event *event, int flags)
 
        writel(DBG_RST, reg);
 
+       /*
+        * Write the AXI id parameter to MADPCR1.
+        */
+       val = event->attr.config1;
+       reg = mmdc_base + MMDC_MADPCR1;
+       writel(val, reg);
+
+       reg = mmdc_base + MMDC_MADPCR0;
        val = DBG_EN;
        if (pmu_mmdc->devtype_data->flags & MMDC_FLAG_PROFILE_SEL)
                val |= PROFILE_SEL;
@@ -382,6 +396,10 @@ static void mmdc_pmu_event_stop(struct perf_event *event, int flags)
        reg = mmdc_base + MMDC_MADPCR0;
 
        writel(PRF_FRZ, reg);
+
+       reg = mmdc_base + MMDC_MADPCR1;
+       writel(MMDC_PRF_AXI_ID_CLEAR, reg);
+
        mmdc_pmu_event_update(event);
 }
 
index 4977296f0c7804272a5854ba5223b786761b7716..bcf3df59f71b447aeb1880a9c9e7743bb9d92398 100644 (file)
 int (*ixp4xx_pci_read)(u32 addr, u32 cmd, u32* data);
 
 /*
- * Base address for PCI regsiter region
+ * Base address for PCI register region
  */
 unsigned long ixp4xx_pci_reg_base = 0;
 
 /*
  * PCI cfg an I/O routines are done by programming a 
  * command/byte enable register, and then read/writing
- * the data from a data regsiter. We need to ensure
+ * the data from a data register. We need to ensure
  * these transactions are atomic or we will end up
  * with corrupt data on the bus or in a driver.
  */
index 554357035f3037f37b31dcb868df3c6e90b5d324..db122356b410f6e2e1dadefa7ecea749e4fd9087 100644 (file)
@@ -10,6 +10,7 @@ config ARCH_KEYSTONE
        select ARCH_SUPPORTS_BIG_ENDIAN
        select ZONE_DMA if ARM_LPAE
        select PINCTRL
+       select PM_GENERIC_DOMAINS if PM
        help
          Support for boards based on the Texas Instruments Keystone family of
          SoCs.
index 8cbb35765a19f359d1cf854e7fbae8bf64621d48..fe57e26926292fe3dccc1adaf7d6c5e8552fd055 100644 (file)
@@ -32,7 +32,9 @@ static struct pm_clk_notifier_block platform_domain_notifier = {
 };
 
 static const struct of_device_id of_keystone_table[] = {
-       {.compatible = "ti,keystone"},
+       {.compatible = "ti,k2hk"},
+       {.compatible = "ti,k2e"},
+       {.compatible = "ti,k2l"},
        { /* end of list */ },
 };
 
index ac6633d0b69bca52bc126b495cb2b40335ab73d9..28fe64c6e2f5c50bca23a8d9f973d79be88b555b 100644 (file)
@@ -67,6 +67,9 @@ void clk_disable(struct clk *clk)
 {
        unsigned long flags;
 
+       if (!clk)
+               return;
+
        WARN_ON(clk->enabled == 0);
 
        spin_lock_irqsave(&clocks_lock, flags);
index e4f21086b42b448e8b0b95002adb454bfe5dfbaa..1c6062d240c8b851061d1209ba6336a54ad708f5 100644 (file)
@@ -419,7 +419,8 @@ static void __init mxs_machine_init(void)
                crystalfontz_init();
        else if (of_machine_is_compatible("eukrea,mbmx283lc"))
                eukrea_mbmx283lc_init();
-       else if (of_machine_is_compatible("i2se,duckbill"))
+       else if (of_machine_is_compatible("i2se,duckbill") ||
+                of_machine_is_compatible("i2se,duckbill-2"))
                duckbill_init();
        else if (of_machine_is_compatible("msr,m28cu3"))
                m28cu3_init();
index ee5460b8ec2ee6e93c06ab60c10bac27c03774c3..f1135bf8940ed82d9027270253cac53c859521cd 100644 (file)
@@ -581,7 +581,6 @@ static int omap_pm_enter(suspend_state_t state)
 {
        switch (state)
        {
-       case PM_SUSPEND_STANDBY:
        case PM_SUSPEND_MEM:
                omap1_pm_suspend();
                break;
index 6b6fda65fb3b599f6b18704e3648020199aac493..91272db09fa3c26ca9fbbbcfed146e1ce1f5050a 100644 (file)
@@ -117,7 +117,7 @@ static struct musb_hdrc_platform_data tusb_data = {
 static void __init n8x0_usb_init(void)
 {
        int ret = 0;
-       static char     announce[] __initdata = KERN_INFO "TUSB 6010\n";
+       static const char announce[] __initconst = KERN_INFO "TUSB 6010\n";
 
        /* PM companion chip power control pin */
        ret = gpio_request_one(TUSB6010_GPIO_ENABLE, GPIOF_OUT_INIT_LOW,
index 59cf310bc1e92cd0b95aeb161c46f58d81c48d12..e8d417309f339511bf8b23c9f6ded380fa81d811 100644 (file)
@@ -138,7 +138,8 @@ int omap2_reprogram_dpllcore(struct clk_hw *hw, unsigned long rate,
                if (!dd)
                        return -EINVAL;
 
-               tmpset.cm_clksel1_pll = readl_relaxed(dd->mult_div1_reg);
+               tmpset.cm_clksel1_pll =
+                       omap_clk_ll_ops.clk_readl(&dd->mult_div1_reg);
                tmpset.cm_clksel1_pll &= ~(dd->mult_mask |
                                           dd->div1_mask);
                div = ((curr_prcm_set->xtal_speed / 1000000) - 1);
index 1270afdcacdf89c9b8fa8e76d3826f3ddb8e8aff..42881f21cede1659fbe3518ad0da1df2d42f96d9 100644 (file)
@@ -54,9 +54,10 @@ u16 cpu_mask;
 #define OMAP3PLUS_DPLL_FINT_MIN                32000
 #define OMAP3PLUS_DPLL_FINT_MAX                52000000
 
-static struct ti_clk_ll_ops omap_clk_ll_ops = {
+struct ti_clk_ll_ops omap_clk_ll_ops = {
        .clkdm_clk_enable = clkdm_clk_enable,
        .clkdm_clk_disable = clkdm_clk_disable,
+       .clkdm_lookup = clkdm_lookup,
        .cm_wait_module_ready = omap_cm_wait_module_ready,
        .cm_split_idlest_reg = cm_split_idlest_reg,
 };
@@ -78,38 +79,6 @@ int __init omap2_clk_setup_ll_ops(void)
  * OMAP2+ specific clock functions
  */
 
-/* Public functions */
-
-/**
- * omap2_init_clk_clkdm - look up a clockdomain name, store pointer in clk
- * @clk: OMAP clock struct ptr to use
- *
- * Convert a clockdomain name stored in a struct clk 'clk' into a
- * clockdomain pointer, and save it into the struct clk.  Intended to be
- * called during clk_register().  No return value.
- */
-void omap2_init_clk_clkdm(struct clk_hw *hw)
-{
-       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
-       struct clockdomain *clkdm;
-       const char *clk_name;
-
-       if (!clk->clkdm_name)
-               return;
-
-       clk_name = __clk_get_name(hw->clk);
-
-       clkdm = clkdm_lookup(clk->clkdm_name);
-       if (clkdm) {
-               pr_debug("clock: associated clk %s to clkdm %s\n",
-                        clk_name, clk->clkdm_name);
-               clk->clkdm = clkdm;
-       } else {
-               pr_debug("clock: could not associate clk %s to clkdm %s\n",
-                        clk_name, clk->clkdm_name);
-       }
-}
-
 /**
  * ti_clk_init_features - init clock features struct for the SoC
  *
index 4e66295dca25aaf4ea324843c326a0e33a044b9b..cf45550197e68869c73dc5563032a2bb542d6bb0 100644 (file)
@@ -64,6 +64,8 @@
 #define OMAP4XXX_EN_DPLL_FRBYPASS              0x6
 #define OMAP4XXX_EN_DPLL_LOCKED                        0x7
 
+extern struct ti_clk_ll_ops omap_clk_ll_ops;
+
 extern u16 cpu_mask;
 
 extern const struct clkops clkops_omap2_dflt_wait;
index 6c679659cda5d502d97f31cf53fe8abce82ae22f..67ebff829cf258a3ec457d3b62e01a522f0d6a28 100644 (file)
@@ -524,7 +524,7 @@ static struct clockdomain pcie_7xx_clkdm = {
        .dep_bit          = DRA7XX_PCIE_STATDEP_SHIFT,
        .wkdep_srcs       = pcie_wkup_sleep_deps,
        .sleepdep_srcs    = pcie_wkup_sleep_deps,
-       .flags            = CLKDM_CAN_HWSUP_SWSUP,
+       .flags            = CLKDM_CAN_SWSUP,
 };
 
 static struct clockdomain atl_7xx_clkdm = {
index 3b5fb05ae7017341b81a009e9e96ca36adc9b8ad..65fbd136b20cca91f83e3ea2644649e151789539 100644 (file)
@@ -91,6 +91,14 @@ static struct clockdomain default_l3_slow_81xx_clkdm = {
        .flags          = CLKDM_CAN_SWSUP,
 };
 
+static struct clockdomain default_sata_81xx_clkdm = {
+       .name           = "default_clkdm",
+       .pwrdm          = { .name = "default_pwrdm" },
+       .cm_inst        = TI81XX_CM_DEFAULT_MOD,
+       .clkdm_offs     = TI816X_CM_DEFAULT_SATA_CLKDM,
+       .flags          = CLKDM_CAN_SWSUP,
+};
+
 /* 816x only */
 
 static struct clockdomain alwon_mpu_816x_clkdm = {
@@ -173,6 +181,7 @@ static struct clockdomain *clockdomains_ti814x[] __initdata = {
        &mmu_81xx_clkdm,
        &mmu_cfg_81xx_clkdm,
        &default_l3_slow_81xx_clkdm,
+       &default_sata_81xx_clkdm,
        NULL,
 };
 
@@ -200,6 +209,7 @@ static struct clockdomain *clockdomains_ti816x[] __initdata = {
        &default_ducati_816x_clkdm,
        &default_pci_816x_clkdm,
        &default_l3_slow_81xx_clkdm,
+       &default_sata_81xx_clkdm,
        NULL,
 };
 
index 1fe3e6b833d255e76a8c564b68c532c1a63f0c83..de75cbcdc9d1bdf34db8edb78a4347f873e331fa 100644 (file)
@@ -23,6 +23,7 @@
 #define MAX_MODULE_READY_TIME          2000
 
 # ifndef __ASSEMBLER__
+#include <linux/clk/ti.h>
 extern void __iomem *cm_base;
 extern void __iomem *cm2_base;
 extern void omap2_set_globals_cm(void __iomem *cm, void __iomem *cm2);
@@ -50,7 +51,7 @@ extern void omap2_set_globals_cm(void __iomem *cm, void __iomem *cm2);
  * @module_disable: ptr to the SoC CM-specific module_disable impl
  */
 struct cm_ll_data {
-       int (*split_idlest_reg)(void __iomem *idlest_reg, s16 *prcm_inst,
+       int (*split_idlest_reg)(struct clk_omap_reg *idlest_reg, s16 *prcm_inst,
                                u8 *idlest_reg_id);
        int (*wait_module_ready)(u8 part, s16 prcm_mod, u16 idlest_reg,
                                 u8 idlest_shift);
@@ -60,7 +61,7 @@ struct cm_ll_data {
        void (*module_disable)(u8 part, u16 inst, u16 clkctrl_offs);
 };
 
-extern int cm_split_idlest_reg(void __iomem *idlest_reg, s16 *prcm_inst,
+extern int cm_split_idlest_reg(struct clk_omap_reg *idlest_reg, s16 *prcm_inst,
                               u8 *idlest_reg_id);
 int omap_cm_wait_module_ready(u8 part, s16 prcm_mod, u16 idlest_reg,
                              u8 idlest_shift);
index 3e5fd3587eb1870e16daa70d2e27001cb449f01a..cd90b4c6a06ba300d2261b91428e1666e26a7b72 100644 (file)
@@ -204,7 +204,7 @@ void omap2xxx_cm_apll96_disable(void)
  * XXX This function is only needed until absolute register addresses are
  * removed from the OMAP struct clk records.
  */
-static int omap2xxx_cm_split_idlest_reg(void __iomem *idlest_reg,
+static int omap2xxx_cm_split_idlest_reg(struct clk_omap_reg *idlest_reg,
                                        s16 *prcm_inst,
                                        u8 *idlest_reg_id)
 {
@@ -212,10 +212,7 @@ static int omap2xxx_cm_split_idlest_reg(void __iomem *idlest_reg,
        u8 idlest_offs;
        int i;
 
-       if (idlest_reg < cm_base || idlest_reg > (cm_base + 0x0fff))
-               return -EINVAL;
-
-       idlest_offs = (unsigned long)idlest_reg & 0xff;
+       idlest_offs = idlest_reg->offset & 0xff;
        for (i = 0; i < ARRAY_SIZE(omap2xxx_cm_idlest_offs); i++) {
                if (idlest_offs == omap2xxx_cm_idlest_offs[i]) {
                        *idlest_reg_id = i + 1;
@@ -226,7 +223,7 @@ static int omap2xxx_cm_split_idlest_reg(void __iomem *idlest_reg,
        if (i == ARRAY_SIZE(omap2xxx_cm_idlest_offs))
                return -EINVAL;
 
-       offs = idlest_reg - cm_base;
+       offs = idlest_reg->offset;
        offs &= 0xff00;
        *prcm_inst = offs;
 
index d91ae8206d1e0cf6a69539a743e2fbed9a330157..55b046a719dc653275eb7421b735f876b3dc81cd 100644 (file)
@@ -118,7 +118,7 @@ static int omap3xxx_cm_wait_module_ready(u8 part, s16 prcm_mod, u16 idlest_id,
  * XXX This function is only needed until absolute register addresses are
  * removed from the OMAP struct clk records.
  */
-static int omap3xxx_cm_split_idlest_reg(void __iomem *idlest_reg,
+static int omap3xxx_cm_split_idlest_reg(struct clk_omap_reg *idlest_reg,
                                        s16 *prcm_inst,
                                        u8 *idlest_reg_id)
 {
@@ -126,11 +126,7 @@ static int omap3xxx_cm_split_idlest_reg(void __iomem *idlest_reg,
        u8 idlest_offs;
        int i;
 
-       if (idlest_reg < (cm_base + OMAP3430_IVA2_MOD) ||
-           idlest_reg > (cm_base + 0x1ffff))
-               return -EINVAL;
-
-       idlest_offs = (unsigned long)idlest_reg & 0xff;
+       idlest_offs = idlest_reg->offset & 0xff;
        for (i = 0; i < ARRAY_SIZE(omap3xxx_cm_idlest_offs); i++) {
                if (idlest_offs == omap3xxx_cm_idlest_offs[i]) {
                        *idlest_reg_id = i + 1;
@@ -141,7 +137,7 @@ static int omap3xxx_cm_split_idlest_reg(void __iomem *idlest_reg,
        if (i == ARRAY_SIZE(omap3xxx_cm_idlest_offs))
                return -EINVAL;
 
-       offs = idlest_reg - cm_base;
+       offs = idlest_reg->offset;
        offs &= 0xff00;
        *prcm_inst = offs;
 
index 3a0ccf07c76feae7e2e683f6fb7636a6b973cfce..5d73a1057c8222666cc88a4eda41367e917444d0 100644 (file)
@@ -57,5 +57,6 @@
 #define TI816X_CM_DEFAULT_PCI_CLKDM            0x0010
 #define TI816X_CM_DEFAULT_L3_SLOW_CLKDM                0x0014
 #define TI816X_CM_DEFAULT_DUCATI_CLKDM         0x0018
+#define TI816X_CM_DEFAULT_SATA_CLKDM           0x0060
 
 #endif
index 23e8bcec34e33c89d7f9f196badb57136db57378..bbe41f4c9dc8ca58fb5d8fbb8e15126e5ecfb9a0 100644 (file)
@@ -65,7 +65,7 @@ void __init omap2_set_globals_cm(void __iomem *cm, void __iomem *cm2)
  * or 0 upon success.  XXX This function is only needed until absolute
  * register addresses are removed from the OMAP struct clk records.
  */
-int cm_split_idlest_reg(void __iomem *idlest_reg, s16 *prcm_inst,
+int cm_split_idlest_reg(struct clk_omap_reg *idlest_reg, s16 *prcm_inst,
                        u8 *idlest_reg_id)
 {
        if (!cm_ll_data->split_idlest_reg) {
index 3089d3bfa19b4a5c595e6872824c81f103d4c5e2..8cc6338fcb1288022854d7bb3347b9e000139c76 100644 (file)
@@ -266,11 +266,12 @@ extern int omap4_cpu_kill(unsigned int cpu);
 extern const struct smp_operations omap4_smp_ops;
 #endif
 
+extern u32 omap4_get_cpu1_ns_pa_addr(void);
+
 #if defined(CONFIG_SMP) && defined(CONFIG_PM)
 extern int omap4_mpuss_init(void);
 extern int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state);
 extern int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state);
-extern u32 omap4_get_cpu1_ns_pa_addr(void);
 #else
 static inline int omap4_enter_lowpower(unsigned int cpu,
                                        unsigned int power_state)
index 3fdb945991848c5f969e8061448f0ace56399465..4739512031049a75206e597409a5750cef29156d 100644 (file)
@@ -121,7 +121,7 @@ static inline void omap_init_mcspi(void) {}
  *
  * Bind the RNG hwmod to the RNG omap_device.  No return value.
  */
-static void omap_init_rng(void)
+static void __init omap_init_rng(void)
 {
        struct omap_hwmod *oh;
        struct platform_device *pdev;
index 03ec6d307c8235fc907a599322991b1efd6c27bf..4cfc4f9b2c6944d935d210190a0afb99b1b0c816 100644 (file)
@@ -213,11 +213,6 @@ static void __init save_l2x0_context(void)
 {}
 #endif
 
-u32 omap4_get_cpu1_ns_pa_addr(void)
-{
-       return old_cpu1_ns_pa_addr;
-}
-
 /**
  * omap4_enter_lowpower: OMAP4 MPUSS Low Power Entry Function
  * The purpose of this function is to manage low power programming
@@ -457,6 +452,11 @@ int __init omap4_mpuss_init(void)
 
 #endif
 
+u32 omap4_get_cpu1_ns_pa_addr(void)
+{
+       return old_cpu1_ns_pa_addr;
+}
+
 /*
  * For kexec, we must set CPU1_WAKEUP_NS_PA_ADDR to point to
  * current kernel's secondary_startup() early before
index 3faf454ba4871c8f60d5e12e912a1ff9dd9af271..33e4953c61a8843b5dde41994b30ea41c52a0abf 100644 (file)
@@ -306,7 +306,6 @@ static void __init omap4_smp_maybe_reset_cpu1(struct omap_smp_config *c)
 
        cpu1_startup_pa = readl_relaxed(cfg.wakeupgen_base +
                                        OMAP_AUX_CORE_BOOT_1);
-       cpu1_ns_pa_addr = omap4_get_cpu1_ns_pa_addr();
 
        /* Did the configured secondary_startup() get overwritten? */
        if (!omap4_smp_cpu1_startup_valid(cpu1_startup_pa))
@@ -316,9 +315,13 @@ static void __init omap4_smp_maybe_reset_cpu1(struct omap_smp_config *c)
         * If omap4 or 5 has NS_PA_ADDR configured, CPU1 may be in a
         * deeper idle state in WFI and will wake to an invalid address.
         */
-       if ((soc_is_omap44xx() || soc_is_omap54xx()) &&
-           !omap4_smp_cpu1_startup_valid(cpu1_ns_pa_addr))
-               needs_reset = true;
+       if ((soc_is_omap44xx() || soc_is_omap54xx())) {
+               cpu1_ns_pa_addr = omap4_get_cpu1_ns_pa_addr();
+               if (!omap4_smp_cpu1_startup_valid(cpu1_ns_pa_addr))
+                       needs_reset = true;
+       } else {
+               cpu1_ns_pa_addr = 0;
+       }
 
        if (!needs_reset || !c->cpu1_rstctrl_va)
                return;
index 0da4f2ea76c46a0fc4812e3f0603eb8909dab0c4..8bcea0d83fa09e8e4985d81697097d1756d34931 100644 (file)
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
 #include <linux/slab.h>
-#include <linux/bootmem.h>
 #include <linux/cpu.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
@@ -216,48 +215,11 @@ static LIST_HEAD(omap_hwmod_list);
 /* mpu_oh: used to add/remove MPU initiator from sleepdep list */
 static struct omap_hwmod *mpu_oh;
 
-/*
- * linkspace: ptr to a buffer that struct omap_hwmod_link records are
- * allocated from - used to reduce the number of small memory
- * allocations, which has a significant impact on performance
- */
-static struct omap_hwmod_link *linkspace;
-
-/*
- * free_ls, max_ls: array indexes into linkspace; representing the
- * next free struct omap_hwmod_link index, and the maximum number of
- * struct omap_hwmod_link records allocated (respectively)
- */
-static unsigned short free_ls, max_ls, ls_supp;
-
 /* inited: set to true once the hwmod code is initialized */
 static bool inited;
 
 /* Private functions */
 
-/**
- * _fetch_next_ocp_if - return the next OCP interface in a list
- * @p: ptr to a ptr to the list_head inside the ocp_if to return
- * @i: pointer to the index of the element pointed to by @p in the list
- *
- * Return a pointer to the struct omap_hwmod_ocp_if record
- * containing the struct list_head pointed to by @p, and increment
- * @p such that a future call to this routine will return the next
- * record.
- */
-static struct omap_hwmod_ocp_if *_fetch_next_ocp_if(struct list_head **p,
-                                                   int *i)
-{
-       struct omap_hwmod_ocp_if *oi;
-
-       oi = list_entry(*p, struct omap_hwmod_link, node)->ocp_if;
-       *p = (*p)->next;
-
-       *i = *i + 1;
-
-       return oi;
-}
-
 /**
  * _update_sysc_cache - return the module OCP_SYSCONFIG register, keep copy
  * @oh: struct omap_hwmod *
@@ -794,15 +756,10 @@ static int _init_main_clk(struct omap_hwmod *oh)
 static int _init_interface_clks(struct omap_hwmod *oh)
 {
        struct omap_hwmod_ocp_if *os;
-       struct list_head *p;
        struct clk *c;
-       int i = 0;
        int ret = 0;
 
-       p = oh->slave_ports.next;
-
-       while (i < oh->slaves_cnt) {
-               os = _fetch_next_ocp_if(&p, &i);
+       list_for_each_entry(os, &oh->slave_ports, node) {
                if (!os->clk)
                        continue;
 
@@ -905,19 +862,13 @@ static void _disable_optional_clocks(struct omap_hwmod *oh)
 static int _enable_clocks(struct omap_hwmod *oh)
 {
        struct omap_hwmod_ocp_if *os;
-       struct list_head *p;
-       int i = 0;
 
        pr_debug("omap_hwmod: %s: enabling clocks\n", oh->name);
 
        if (oh->_clk)
                clk_enable(oh->_clk);
 
-       p = oh->slave_ports.next;
-
-       while (i < oh->slaves_cnt) {
-               os = _fetch_next_ocp_if(&p, &i);
-
+       list_for_each_entry(os, &oh->slave_ports, node) {
                if (os->_clk && (os->flags & OCPIF_SWSUP_IDLE))
                        clk_enable(os->_clk);
        }
@@ -939,19 +890,13 @@ static int _enable_clocks(struct omap_hwmod *oh)
 static int _disable_clocks(struct omap_hwmod *oh)
 {
        struct omap_hwmod_ocp_if *os;
-       struct list_head *p;
-       int i = 0;
 
        pr_debug("omap_hwmod: %s: disabling clocks\n", oh->name);
 
        if (oh->_clk)
                clk_disable(oh->_clk);
 
-       p = oh->slave_ports.next;
-
-       while (i < oh->slaves_cnt) {
-               os = _fetch_next_ocp_if(&p, &i);
-
+       list_for_each_entry(os, &oh->slave_ports, node) {
                if (os->_clk && (os->flags & OCPIF_SWSUP_IDLE))
                        clk_disable(os->_clk);
        }
@@ -1190,16 +1135,11 @@ static int _get_sdma_req_by_name(struct omap_hwmod *oh, const char *name,
 static int _get_addr_space_by_name(struct omap_hwmod *oh, const char *name,
                                   u32 *pa_start, u32 *pa_end)
 {
-       int i, j;
+       int j;
        struct omap_hwmod_ocp_if *os;
-       struct list_head *p = NULL;
        bool found = false;
 
-       p = oh->slave_ports.next;
-
-       i = 0;
-       while (i < oh->slaves_cnt) {
-               os = _fetch_next_ocp_if(&p, &i);
+       list_for_each_entry(os, &oh->slave_ports, node) {
 
                if (!os->addr)
                        return -ENOENT;
@@ -1239,18 +1179,13 @@ static int _get_addr_space_by_name(struct omap_hwmod *oh, const char *name,
 static void __init _save_mpu_port_index(struct omap_hwmod *oh)
 {
        struct omap_hwmod_ocp_if *os = NULL;
-       struct list_head *p;
-       int i = 0;
 
        if (!oh)
                return;
 
        oh->_int_flags |= _HWMOD_NO_MPU_PORT;
 
-       p = oh->slave_ports.next;
-
-       while (i < oh->slaves_cnt) {
-               os = _fetch_next_ocp_if(&p, &i);
+       list_for_each_entry(os, &oh->slave_ports, node) {
                if (os->user & OCP_USER_MPU) {
                        oh->_mpu_port = os;
                        oh->_int_flags &= ~_HWMOD_NO_MPU_PORT;
@@ -1393,7 +1328,7 @@ static void _enable_sysc(struct omap_hwmod *oh)
         */
        if ((oh->flags & HWMOD_SET_DEFAULT_CLOCKACT) &&
            (sf & SYSC_HAS_CLOCKACTIVITY))
-               _set_clockactivity(oh, oh->class->sysc->clockact, &v);
+               _set_clockactivity(oh, CLOCKACT_TEST_ICLK, &v);
 
        _write_sysconfig(v, oh);
 
@@ -2092,7 +2027,7 @@ static int _enable(struct omap_hwmod *oh)
 
        r = (soc_ops.wait_target_ready) ? soc_ops.wait_target_ready(oh) :
                -EINVAL;
-       if (oh->clkdm)
+       if (oh->clkdm && !(oh->flags & HWMOD_CLKDM_NOAUTO))
                clkdm_allow_idle(oh->clkdm);
 
        if (!r) {
@@ -2149,7 +2084,12 @@ static int _idle(struct omap_hwmod *oh)
                _idle_sysc(oh);
        _del_initiator_dep(oh, mpu_oh);
 
-       if (oh->clkdm)
+       /*
+        * If HWMOD_CLKDM_NOAUTO is set then we don't
+        * deny idle the clkdm again since idle was already denied
+        * in _enable()
+        */
+       if (oh->clkdm && !(oh->flags & HWMOD_CLKDM_NOAUTO))
                clkdm_deny_idle(oh->clkdm);
 
        if (oh->flags & HWMOD_BLOCK_WFI)
@@ -2451,15 +2391,11 @@ static int __init _init(struct omap_hwmod *oh, void *data)
 static void __init _setup_iclk_autoidle(struct omap_hwmod *oh)
 {
        struct omap_hwmod_ocp_if *os;
-       struct list_head *p;
-       int i = 0;
+
        if (oh->_state != _HWMOD_STATE_INITIALIZED)
                return;
 
-       p = oh->slave_ports.next;
-
-       while (i < oh->slaves_cnt) {
-               os = _fetch_next_ocp_if(&p, &i);
+       list_for_each_entry(os, &oh->slave_ports, node) {
                if (!os->_clk)
                        continue;
 
@@ -2657,7 +2593,6 @@ static int __init _register(struct omap_hwmod *oh)
 
        list_add_tail(&oh->node, &omap_hwmod_list);
 
-       INIT_LIST_HEAD(&oh->master_ports);
        INIT_LIST_HEAD(&oh->slave_ports);
        spin_lock_init(&oh->_lock);
        lockdep_set_class(&oh->_lock, &oh->hwmod_key);
@@ -2674,50 +2609,11 @@ static int __init _register(struct omap_hwmod *oh)
        return 0;
 }
 
-/**
- * _alloc_links - return allocated memory for hwmod links
- * @ml: pointer to a struct omap_hwmod_link * for the master link
- * @sl: pointer to a struct omap_hwmod_link * for the slave link
- *
- * Return pointers to two struct omap_hwmod_link records, via the
- * addresses pointed to by @ml and @sl.  Will first attempt to return
- * memory allocated as part of a large initial block, but if that has
- * been exhausted, will allocate memory itself.  Since ideally this
- * second allocation path will never occur, the number of these
- * 'supplemental' allocations will be logged when debugging is
- * enabled.  Returns 0.
- */
-static int __init _alloc_links(struct omap_hwmod_link **ml,
-                              struct omap_hwmod_link **sl)
-{
-       unsigned int sz;
-
-       if ((free_ls + LINKS_PER_OCP_IF) <= max_ls) {
-               *ml = &linkspace[free_ls++];
-               *sl = &linkspace[free_ls++];
-               return 0;
-       }
-
-       sz = sizeof(struct omap_hwmod_link) * LINKS_PER_OCP_IF;
-
-       *sl = NULL;
-       *ml = memblock_virt_alloc(sz, 0);
-
-       *sl = (void *)(*ml) + sizeof(struct omap_hwmod_link);
-
-       ls_supp++;
-       pr_debug("omap_hwmod: supplemental link allocations needed: %d\n",
-                ls_supp * LINKS_PER_OCP_IF);
-
-       return 0;
-};
-
 /**
  * _add_link - add an interconnect between two IP blocks
  * @oi: pointer to a struct omap_hwmod_ocp_if record
  *
- * Add struct omap_hwmod_link records connecting the master IP block
- * specified in @oi->master to @oi, and connecting the slave IP block
+ * Add struct omap_hwmod_link records connecting the slave IP block
  * specified in @oi->slave to @oi.  This code is assumed to run before
  * preemption or SMP has been enabled, thus avoiding the need for
  * locking in this code.  Changes to this assumption will require
@@ -2725,19 +2621,10 @@ static int __init _alloc_links(struct omap_hwmod_link **ml,
  */
 static int __init _add_link(struct omap_hwmod_ocp_if *oi)
 {
-       struct omap_hwmod_link *ml, *sl;
-
        pr_debug("omap_hwmod: %s -> %s: adding link\n", oi->master->name,
                 oi->slave->name);
 
-       _alloc_links(&ml, &sl);
-
-       ml->ocp_if = oi;
-       list_add(&ml->node, &oi->master->master_ports);
-       oi->master->masters_cnt++;
-
-       sl->ocp_if = oi;
-       list_add(&sl->node, &oi->slave->slave_ports);
+       list_add(&oi->node, &oi->slave->slave_ports);
        oi->slave->slaves_cnt++;
 
        return 0;
@@ -2784,45 +2671,6 @@ static int __init _register_link(struct omap_hwmod_ocp_if *oi)
        return 0;
 }
 
-/**
- * _alloc_linkspace - allocate large block of hwmod links
- * @ois: pointer to an array of struct omap_hwmod_ocp_if records to count
- *
- * Allocate a large block of struct omap_hwmod_link records.  This
- * improves boot time significantly by avoiding the need to allocate
- * individual records one by one.  If the number of records to
- * allocate in the block hasn't been manually specified, this function
- * will count the number of struct omap_hwmod_ocp_if records in @ois
- * and use that to determine the allocation size.  For SoC families
- * that require multiple list registrations, such as OMAP3xxx, this
- * estimation process isn't optimal, so manual estimation is advised
- * in those cases.  Returns -EEXIST if the allocation has already occurred
- * or 0 upon success.
- */
-static int __init _alloc_linkspace(struct omap_hwmod_ocp_if **ois)
-{
-       unsigned int i = 0;
-       unsigned int sz;
-
-       if (linkspace) {
-               WARN(1, "linkspace already allocated\n");
-               return -EEXIST;
-       }
-
-       if (max_ls == 0)
-               while (ois[i++])
-                       max_ls += LINKS_PER_OCP_IF;
-
-       sz = sizeof(struct omap_hwmod_link) * max_ls;
-
-       pr_debug("omap_hwmod: %s: allocating %d byte linkspace (%d links)\n",
-                __func__, sz, max_ls);
-
-       linkspace = memblock_virt_alloc(sz, 0);
-
-       return 0;
-}
-
 /* Static functions intended only for use in soc_ops field function pointers */
 
 /**
@@ -3180,13 +3028,6 @@ int __init omap_hwmod_register_links(struct omap_hwmod_ocp_if **ois)
        if (ois[0] == NULL) /* Empty list */
                return 0;
 
-       if (!linkspace) {
-               if (_alloc_linkspace(ois)) {
-                       pr_err("omap_hwmod: could not allocate link space\n");
-                       return -ENOMEM;
-               }
-       }
-
        i = 0;
        do {
                r = _register_link(ois[i]);
@@ -3398,14 +3239,10 @@ int omap_hwmod_count_resources(struct omap_hwmod *oh, unsigned long flags)
                ret += _count_sdma_reqs(oh);
 
        if (flags & IORESOURCE_MEM) {
-               int i = 0;
                struct omap_hwmod_ocp_if *os;
-               struct list_head *p = oh->slave_ports.next;
 
-               while (i < oh->slaves_cnt) {
-                       os = _fetch_next_ocp_if(&p, &i);
+               list_for_each_entry(os, &oh->slave_ports, node)
                        ret += _count_ocp_if_addr_spaces(os);
-               }
        }
 
        return ret;
@@ -3424,7 +3261,6 @@ int omap_hwmod_count_resources(struct omap_hwmod *oh, unsigned long flags)
 int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res)
 {
        struct omap_hwmod_ocp_if *os;
-       struct list_head *p;
        int i, j, mpu_irqs_cnt, sdma_reqs_cnt, addr_cnt;
        int r = 0;
 
@@ -3454,11 +3290,7 @@ int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res)
                r++;
        }
 
-       p = oh->slave_ports.next;
-
-       i = 0;
-       while (i < oh->slaves_cnt) {
-               os = _fetch_next_ocp_if(&p, &i);
+       list_for_each_entry(os, &oh->slave_ports, node) {
                addr_cnt = _count_ocp_if_addr_spaces(os);
 
                for (j = 0; j < addr_cnt; j++) {
index 78904017f18ce03669fdf396cbedf31d735b8f19..a8f779381fd80cef320a9b982d4a4932f0cc10f3 100644 (file)
@@ -313,6 +313,7 @@ struct omap_hwmod_ocp_if {
        struct omap_hwmod_addr_space    *addr;
        const char                      *clk;
        struct clk                      *_clk;
+       struct list_head                node;
        union {
                struct omap_hwmod_omap2_firewall omap2;
        }                               fw;
@@ -410,7 +411,6 @@ struct omap_hwmod_class_sysconfig {
        struct omap_hwmod_sysc_fields *sysc_fields;
        u8 srst_udelay;
        u8 idlemodes;
-       u8 clockact;
 };
 
 /**
@@ -531,6 +531,10 @@ struct omap_hwmod_omap4_prcm {
  *     operate and they need to be handled at the same time as the main_clk.
  * HWMOD_NO_IDLE: Do not idle the hwmod at all. Useful to handle certain
  *     IPs like CPSW on DRA7, where clocks to this module cannot be disabled.
+ * HWMOD_CLKDM_NOAUTO: Allows the hwmod's clockdomain to be prevented from
+ *     entering HW_AUTO while hwmod is active. This is needed to workaround
+ *     some modules which don't function correctly with HW_AUTO. For example,
+ *     DCAN on DRA7x SoC needs this to workaround errata i893.
  */
 #define HWMOD_SWSUP_SIDLE                      (1 << 0)
 #define HWMOD_SWSUP_MSTANDBY                   (1 << 1)
@@ -548,6 +552,7 @@ struct omap_hwmod_omap4_prcm {
 #define HWMOD_RECONFIG_IO_CHAIN                        (1 << 13)
 #define HWMOD_OPT_CLKS_NEEDED                  (1 << 14)
 #define HWMOD_NO_IDLE                          (1 << 15)
+#define HWMOD_CLKDM_NOAUTO                     (1 << 16)
 
 /*
  * omap_hwmod._int_flags definitions
@@ -616,16 +621,6 @@ struct omap_hwmod_class {
        void                                    (*unlock)(struct omap_hwmod *oh);
 };
 
-/**
- * struct omap_hwmod_link - internal structure linking hwmods with ocp_ifs
- * @ocp_if: OCP interface structure record pointer
- * @node: list_head pointing to next struct omap_hwmod_link in a list
- */
-struct omap_hwmod_link {
-       struct omap_hwmod_ocp_if        *ocp_if;
-       struct list_head                node;
-};
-
 /**
  * struct omap_hwmod - integration data for OMAP hardware "modules" (IP blocks)
  * @name: name of the hwmod
@@ -686,9 +681,8 @@ struct omap_hwmod {
        const char                      *main_clk;
        struct clk                      *_clk;
        struct omap_hwmod_opt_clk       *opt_clks;
-       char                            *clkdm_name;
+       const char                      *clkdm_name;
        struct clockdomain              *clkdm;
-       struct list_head                master_ports; /* connect to *_IA */
        struct list_head                slave_ports; /* connect to *_TA */
        void                            *dev_attr;
        u32                             _sysc_cache;
@@ -698,12 +692,11 @@ struct omap_hwmod {
        struct list_head                node;
        struct omap_hwmod_ocp_if        *_mpu_port;
        unsigned int                    (*xlate_irq)(unsigned int);
-       u16                             flags;
+       u32                             flags;
        u8                              mpu_rt_idx;
        u8                              response_lat;
        u8                              rst_lines_cnt;
        u8                              opt_clks_cnt;
-       u8                              masters_cnt;
        u8                              slaves_cnt;
        u8                              hwmods_cnt;
        u8                              _int_flags;
index e047033caa3e913bfb317c00b4974ee56ec4a424..d190f1ad97b73b96a7c4f43bb9cf1e68f7ed320e 100644 (file)
@@ -55,7 +55,6 @@ static struct omap_hwmod_class_sysconfig omap2xxx_timer_sysc = {
                           SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
                           SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
        .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-       .clockact       = CLOCKACT_TEST_ICLK,
        .sysc_fields    = &omap_hwmod_sysc_type1,
 };
 
index 1435fee39a89ba18239291859c97f0f333ca877f..1c6ca4d5fa2d9513614c6105748dd1b5eb2590a2 100644 (file)
@@ -149,7 +149,6 @@ static struct omap_hwmod_class_sysconfig omap3xxx_timer_sysc = {
                           SYSC_HAS_EMUFREE | SYSC_HAS_AUTOIDLE |
                           SYSS_HAS_RESET_STATUS),
        .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-       .clockact       = CLOCKACT_TEST_ICLK,
        .sysc_fields    = &omap_hwmod_sysc_type1,
 };
 
@@ -424,7 +423,6 @@ static struct omap_hwmod_class_sysconfig i2c_sysc = {
                           SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
                           SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
        .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-       .clockact       = CLOCKACT_TEST_ICLK,
        .sysc_fields    = &omap_hwmod_sysc_type1,
 };
 
@@ -1045,7 +1043,6 @@ static struct omap_hwmod_class_sysconfig omap3xxx_mcbsp_sysc = {
                           SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
        .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
        .sysc_fields    = &omap_hwmod_sysc_type1,
-       .clockact       = 0x2,
 };
 
 static struct omap_hwmod_class omap3xxx_mcbsp_hwmod_class = {
@@ -1210,7 +1207,6 @@ static struct omap_hwmod_sysc_fields omap34xx_sr_sysc_fields = {
 static struct omap_hwmod_class_sysconfig omap34xx_sr_sysc = {
        .sysc_offs      = 0x24,
        .sysc_flags     = (SYSC_HAS_CLOCKACTIVITY | SYSC_NO_CACHE),
-       .clockact       = CLOCKACT_TEST_ICLK,
        .sysc_fields    = &omap34xx_sr_sysc_fields,
 };
 
index dad871a4cd9657ed40f380dcfd7d6e8e72c48cde..94f09c720f2900f5d3cf4fd27e1b30fa531fc3af 100644 (file)
@@ -1320,7 +1320,6 @@ static struct omap_hwmod_class_sysconfig omap44xx_i2c_sysc = {
                           SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
        .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
                           SIDLE_SMART_WKUP),
-       .clockact       = CLOCKACT_TEST_ICLK,
        .sysc_fields    = &omap_hwmod_sysc_type1,
 };
 
@@ -2548,7 +2547,6 @@ static struct omap_hwmod_class_sysconfig omap44xx_timer_1ms_sysc = {
                           SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
                           SYSS_HAS_RESET_STATUS),
        .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
-       .clockact       = CLOCKACT_TEST_ICLK,
        .sysc_fields    = &omap_hwmod_sysc_type1,
 };
 
index a2d763a4cc575f1e599266255d368af3b712aafa..9a67f013ebad6a40d63e97cd8de8caae4b007686 100644 (file)
@@ -839,7 +839,6 @@ static struct omap_hwmod_class_sysconfig omap54xx_i2c_sysc = {
                           SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
        .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
                           SIDLE_SMART_WKUP),
-       .clockact       = CLOCKACT_TEST_ICLK,
        .sysc_fields    = &omap_hwmod_sysc_type1,
 };
 
@@ -1530,7 +1529,6 @@ static struct omap_hwmod_class_sysconfig omap54xx_timer_1ms_sysc = {
        .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
                           SIDLE_SMART_WKUP),
        .sysc_fields    = &omap_hwmod_sysc_type2,
-       .clockact       = CLOCKACT_TEST_ICLK,
 };
 
 static struct omap_hwmod_class omap54xx_timer_1ms_hwmod_class = {
index d0585293a381bdb54edc89982e2fa94f7cfb70bc..b3abb8d8b2f6add6af321ecadc1a7ed9ca158cca 100644 (file)
@@ -359,6 +359,7 @@ static struct omap_hwmod dra7xx_dcan1_hwmod = {
        .class          = &dra7xx_dcan_hwmod_class,
        .clkdm_name     = "wkupaon_clkdm",
        .main_clk       = "dcan1_sys_clk_mux",
+       .flags          = HWMOD_CLKDM_NOAUTO,
        .prcm = {
                .omap4 = {
                        .clkctrl_offs = DRA7XX_CM_WKUPAON_DCAN1_CLKCTRL_OFFSET,
@@ -374,6 +375,7 @@ static struct omap_hwmod dra7xx_dcan2_hwmod = {
        .class          = &dra7xx_dcan_hwmod_class,
        .clkdm_name     = "l4per2_clkdm",
        .main_clk       = "sys_clkin1",
+       .flags          = HWMOD_CLKDM_NOAUTO,
        .prcm = {
                .omap4 = {
                        .clkctrl_offs = DRA7XX_CM_L4PER2_DCAN2_CLKCTRL_OFFSET,
@@ -1098,7 +1100,6 @@ static struct omap_hwmod_class_sysconfig dra7xx_i2c_sysc = {
                           SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
        .idlemodes      = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
                           SIDLE_SMART_WKUP),
-       .clockact       = CLOCKACT_TEST_ICLK,
        .sysc_fields    = &omap_hwmod_sysc_type1,
 };
 
@@ -2700,6 +2701,7 @@ static struct omap_hwmod dra7xx_usb_otg_ss1_hwmod = {
        .class          = &dra7xx_usb_otg_ss_hwmod_class,
        .clkdm_name     = "l3init_clkdm",
        .main_clk       = "dpll_core_h13x2_ck",
+       .flags          = HWMOD_CLKDM_NOAUTO,
        .prcm = {
                .omap4 = {
                        .clkctrl_offs = DRA7XX_CM_L3INIT_USB_OTG_SS1_CLKCTRL_OFFSET,
@@ -2721,6 +2723,7 @@ static struct omap_hwmod dra7xx_usb_otg_ss2_hwmod = {
        .class          = &dra7xx_usb_otg_ss_hwmod_class,
        .clkdm_name     = "l3init_clkdm",
        .main_clk       = "dpll_core_h13x2_ck",
+       .flags          = HWMOD_CLKDM_NOAUTO,
        .prcm = {
                .omap4 = {
                        .clkctrl_offs = DRA7XX_CM_L3INIT_USB_OTG_SS2_CLKCTRL_OFFSET,
index b82b77cff24c2c7ae5bb5ee59fa16d88301c34c9..310afe474ec46a5d0674ab0d62d811c50c342ed6 100644 (file)
  */
 #define DM81XX_CM_DEFAULT_OFFSET       0x500
 #define DM81XX_CM_DEFAULT_USB_CLKCTRL  (0x558 - DM81XX_CM_DEFAULT_OFFSET)
+#define DM81XX_CM_DEFAULT_SATA_CLKCTRL (0x560 - DM81XX_CM_DEFAULT_OFFSET)
 
 /* L3 Interconnect entries clocked at 125, 250 and 500MHz */
 static struct omap_hwmod dm81xx_alwon_l3_slow_hwmod = {
@@ -973,6 +974,38 @@ static struct omap_hwmod_ocp_if dm816x_l4_hs__emac1 = {
        .user           = OCP_USER_MPU,
 };
 
+static struct omap_hwmod_class_sysconfig dm81xx_sata_sysc = {
+       .sysc_offs      = 0x1100,
+       .sysc_flags     = SYSC_HAS_SIDLEMODE,
+       .idlemodes      = SIDLE_FORCE,
+       .sysc_fields    = &omap_hwmod_sysc_type3,
+};
+
+static struct omap_hwmod_class dm81xx_sata_hwmod_class = {
+       .name   = "sata",
+       .sysc   = &dm81xx_sata_sysc,
+};
+
+static struct omap_hwmod dm81xx_sata_hwmod = {
+       .name           = "sata",
+       .clkdm_name     = "default_sata_clkdm",
+       .flags          = HWMOD_NO_IDLEST,
+       .prcm = {
+               .omap4 = {
+                       .clkctrl_offs = DM81XX_CM_DEFAULT_SATA_CLKCTRL,
+                       .modulemode   = MODULEMODE_SWCTRL,
+               },
+       },
+       .class          = &dm81xx_sata_hwmod_class,
+};
+
+static struct omap_hwmod_ocp_if dm81xx_l4_hs__sata = {
+       .master         = &dm81xx_l4_hs_hwmod,
+       .slave          = &dm81xx_sata_hwmod,
+       .clk            = "sysclk5_ck",
+       .user           = OCP_USER_MPU,
+};
+
 static struct omap_hwmod_class_sysconfig dm81xx_mmc_sysc = {
        .rev_offs       = 0x0,
        .sysc_offs      = 0x110,
@@ -1474,6 +1507,7 @@ static struct omap_hwmod_ocp_if *dm816x_hwmod_ocp_ifs[] __initdata = {
        &dm81xx_l4_hs__emac0,
        &dm81xx_emac0__mdio,
        &dm816x_l4_hs__emac1,
+       &dm81xx_l4_hs__sata,
        &dm81xx_alwon_l3_fast__tpcc,
        &dm81xx_alwon_l3_fast__tptc0,
        &dm81xx_alwon_l3_fast__tptc1,
index 0598630c17786242d20277fe59e9bbdb9cc9e928..63027e60cc209f1cb9b6067958ff692813233665 100644 (file)
@@ -163,7 +163,6 @@ static int omap_pm_enter(suspend_state_t suspend_state)
                return -ENOENT; /* XXX doublecheck */
 
        switch (suspend_state) {
-       case PM_SUSPEND_STANDBY:
        case PM_SUSPEND_MEM:
                ret = omap_pm_suspend();
                break;
index 2b138b65129a5d609ff2ae02a55181c10154113b..dc11841ca334c64aa0f70a04781463737c191282 100644 (file)
@@ -711,7 +711,7 @@ static struct omap_prcm_init_data scrm_data __initdata = {
 };
 #endif
 
-static const struct of_device_id const omap_prcm_dt_match_table[] __initconst = {
+static const struct of_device_id omap_prcm_dt_match_table[] __initconst = {
 #ifdef CONFIG_SOC_AM33XX
        { .compatible = "ti,am3-prcm", .data = &am3_prm_data },
 #endif
index 2028167fff310041cf54037798f81cc8efa9efc2..d76b1e5eb8ba50ed9a09b0e1df3c56b1e2f0c6bb 100644 (file)
@@ -559,7 +559,7 @@ struct i2c_init_data {
        u8 hsscll_12;
 };
 
-static const struct i2c_init_data const omap4_i2c_timing_data[] __initconst = {
+static const struct i2c_init_data omap4_i2c_timing_data[] __initconst = {
        {
                .load = 50,
                .loadbits = 0x3,
index 8fa4557e27a97bb82d8e49db827a619d9ae577f9..e3610c5b309bd90b6eac593eaed14690415891ae 100644 (file)
@@ -28,7 +28,6 @@ config MACH_OX820
        depends on ARCH_MULTI_V6
        select ARM_GIC
        select DMA_CACHE_RWFO if SMP
-       select CPU_V6K
        select HAVE_SMP
        select HAVE_ARM_SCU if SMP
        select HAVE_ARM_TWD if SMP
index 4878ba90026df68bb0d06683df795c94ee20d7ec..289e036c9c3054a3e0ba3b9d9f553867c9bd09ef 100644 (file)
@@ -204,7 +204,7 @@ static void __init spear_clockevent_init(int irq)
        setup_irq(irq, &spear_timer_irq);
 }
 
-static const struct of_device_id const timer_of_match[] __initconst = {
+static const struct of_device_id timer_of_match[] __initconst = {
        { .compatible = "st,spear-timer", },
        { },
 };
diff --git a/arch/arm/mach-stm32/Kconfig b/arch/arm/mach-stm32/Kconfig
new file mode 100644 (file)
index 0000000..2d1419e
--- /dev/null
@@ -0,0 +1,26 @@
+config ARCH_STM32
+       bool "STMicrolectronics STM32"
+       depends on ARM_SINGLE_ARMV7M
+       select ARCH_HAS_RESET_CONTROLLER
+       select ARMV7M_SYSTICK
+       select CLKSRC_STM32
+       select PINCTRL
+       select RESET_CONTROLLER
+       select STM32_EXTI
+       help
+         Support for STMicroelectronics STM32 processors.
+
+config MACH_STM32F429
+       bool "STMicrolectronics STM32F429"
+       depends on ARCH_STM32
+       default y
+
+config MACH_STM32F746
+       bool "STMicrolectronics STM32F746"
+       depends on ARCH_STM32
+       default y
+
+config MACH_STM32H743
+       bool "STMicrolectronics STM32H743"
+       depends on ARCH_STM32
+       default y
index c354222a4158e9452337b408152752535fbaa8ed..e918686e4191bd86386f5a7cbd19d8238e6b1ba7 100644 (file)
@@ -12,6 +12,7 @@ static const char *const stm32_compat[] __initconst = {
        "st,stm32f429",
        "st,stm32f469",
        "st,stm32f746",
+       "st,stm32h743",
        NULL
 };
 
index b9863f9a35fae9eedaa053c13d505a6d2d6dee04..58153cdf025b80580a3d865a8b3bd3d2093a93e4 100644 (file)
@@ -6,6 +6,7 @@ menuconfig ARCH_SUNXI
        select GENERIC_IRQ_CHIP
        select GPIOLIB
        select PINCTRL
+       select PM_OPP
        select SUN4I_TIMER
        select RESET_CONTROLLER
 
index fffad2426ee4bc0ea1689b0de9e760db41713a0f..3b33f0bb78ae4bd9da4f1b1c810cdd3f740a75ba 100644 (file)
@@ -2,7 +2,6 @@ asflags-y                               += -march=armv7-a
 
 obj-y                                   += io.o
 obj-y                                   += irq.o
-obj-y                                  += flowctrl.o
 obj-y                                  += pm.o
 obj-y                                  += reset.o
 obj-y                                  += reset-handler.o
index afcee04f2616aa5c8c1e443b2feaa4f3465c1fea..76e4c83cd5c8dd54e1f644618beef62087e0b0b2 100644 (file)
 #include <linux/kernel.h>
 #include <linux/module.h>
 
+#include <soc/tegra/flowctrl.h>
+
 #include <asm/cpuidle.h>
 #include <asm/smp_plat.h>
 #include <asm/suspend.h>
 
 #include "cpuidle.h"
-#include "flowctrl.h"
 #include "iomap.h"
 #include "irq.h"
 #include "pm.h"
index 75620ae73913a18d92fd4521b7ae06aea397e1e1..b5a2afe99101f9008a34510a9bf3dbd17e2d5cf1 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/jiffies.h>
 #include <linux/smp.h>
 
+#include <soc/tegra/flowctrl.h>
 #include <soc/tegra/fuse.h>
 #include <soc/tegra/pmc.h>
 
@@ -30,7 +31,6 @@
 #include <asm/smp_scu.h>
 
 #include "common.h"
-#include "flowctrl.h"
 #include "iomap.h"
 #include "reset.h"
 
index b0f48a3946fae27277dd8ca49f9432896e89cfb0..1ad5719779b00ab1fa4ea5d6a1c2d944e5b7e0f0 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/spinlock.h>
 #include <linux/suspend.h>
 
+#include <soc/tegra/flowctrl.h>
 #include <soc/tegra/fuse.h>
 #include <soc/tegra/pm.h>
 #include <soc/tegra/pmc.h>
@@ -38,7 +39,6 @@
 #include <asm/suspend.h>
 #include <asm/tlbflush.h>
 
-#include "flowctrl.h"
 #include "iomap.h"
 #include "pm.h"
 #include "reset.h"
index e3070fdab80b8b7481c0527e2d649ae7d664dc58..805f306fa6f707f055878a31f00a2f412a89f9c5 100644 (file)
 #include <linux/init.h>
 #include <linux/linkage.h>
 
+#include <soc/tegra/flowctrl.h>
 #include <soc/tegra/fuse.h>
 
 #include <asm/asm-offsets.h>
 #include <asm/cache.h>
 
-#include "flowctrl.h"
 #include "iomap.h"
 #include "reset.h"
 #include "sleep.h"
index f5d19667484edd38e65bb1aa1d1a4413a036bfbf..5c8e638ee51a3b590cc8274a3edb22e5a93dd996 100644 (file)
@@ -20,6 +20,8 @@
 
 #include <linux/linkage.h>
 
+#include <soc/tegra/flowctrl.h>
+
 #include <asm/assembler.h>
 #include <asm/proc-fns.h>
 #include <asm/cp15.h>
@@ -27,7 +29,6 @@
 
 #include "irammap.h"
 #include "sleep.h"
-#include "flowctrl.h"
 
 #define EMC_CFG                                0xc
 #define EMC_ADR_CFG                    0x10
index 16e5ff03383cad5b709eb42b24340b033f86a2c7..dd4a67dabd91692dffae18fd07245c372770840f 100644 (file)
 
 #include <linux/linkage.h>
 
+#include <soc/tegra/flowctrl.h>
 #include <soc/tegra/fuse.h>
 
 #include <asm/asm-offsets.h>
 #include <asm/assembler.h>
 #include <asm/cache.h>
 
-#include "flowctrl.h"
 #include "irammap.h"
 #include "sleep.h"
 
index f024a5109e8e7c91ec8427f060748c7c47990462..5e3496753df184a556f0143cfc357e58224d7803 100644 (file)
@@ -30,8 +30,6 @@
 #include <asm/hardware/cache-l2x0.h>
 
 #include "iomap.h"
-
-#include "flowctrl.h"
 #include "sleep.h"
 
 #define CLK_RESET_CCLK_BURST   0x20
index e01cbca196b544f57e95ffb1e21e831b93adec03..649e9e8c7bccdf2e566ec0ad05c52c8a85a4fc04 100644 (file)
@@ -48,7 +48,6 @@
 #include "board.h"
 #include "common.h"
 #include "cpuidle.h"
-#include "flowctrl.h"
 #include "iomap.h"
 #include "irq.h"
 #include "pm.h"
@@ -75,7 +74,6 @@ static void __init tegra_init_early(void)
 {
        of_register_trusted_foundations();
        tegra_cpu_reset_handler_init();
-       tegra_flowctrl_init();
 }
 
 static void __init tegra_dt_init_irq(void)
index 2c371ff22e517ad17776902f5af31e8e198d1a66..ac6fd1a2cb59fb43897d00581d18e53aa354ca80 100644 (file)
@@ -46,6 +46,9 @@ void clk_disable(struct clk *clk)
 {
        unsigned long flags;
 
+       if (!clk)
+               return;
+
        WARN_ON(clk->enabled == 0);
 
        spin_lock_irqsave(&clocks_lock, flags);
index 0268584f1fa0a73a8fcef7ffadf5194f23dfe308..c742dfd2967bcae6057c3ea59b81979fcf60aa55 100644 (file)
@@ -2408,6 +2408,15 @@ 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;
+
+       /*
+        * Don't override the dma_ops if they have already been set. Ideally
+        * this should be the only location where dma_ops are set, remove this
+        * check when all other callers of set_dma_ops will have disappeared.
+        */
+       if (dev->dma_ops)
+               return;
+
        if (arm_setup_iommu_dma_ops(dev, dma_base, size, iommu))
                dma_ops = arm_get_iommu_dma_map_ops(coherent);
        else
index ff0eed23ddf1354afd26ee0711f34680380227a1..fc91205ff46cebd2218940214c12e6ab84355b21 100644 (file)
@@ -481,6 +481,13 @@ int pci_ioremap_io(unsigned int offset, phys_addr_t phys_addr)
                                  __pgprot(get_mem_type(pci_ioremap_mem_type)->prot_pte));
 }
 EXPORT_SYMBOL_GPL(pci_ioremap_io);
+
+void __iomem *pci_remap_cfgspace(resource_size_t res_cookie, size_t size)
+{
+       return arch_ioremap_caller(res_cookie, size, MT_UNCACHED,
+                                  __builtin_return_address(0));
+}
+EXPORT_SYMBOL_GPL(pci_remap_cfgspace);
 #endif
 
 /*
index 33a45bd9686012c2547b218133f59a0169fea33d..3b8e728cc9443975c6cd66c63350a2074df310b7 100644 (file)
@@ -436,6 +436,18 @@ void __iomem *ioremap_wc(resource_size_t res_cookie, size_t size)
 }
 EXPORT_SYMBOL(ioremap_wc);
 
+#ifdef CONFIG_PCI
+
+#include <asm/mach/map.h>
+
+void __iomem *pci_remap_cfgspace(resource_size_t res_cookie, size_t size)
+{
+       return arch_ioremap_caller(res_cookie, size, MT_UNCACHED,
+                                  __builtin_return_address(0));
+}
+EXPORT_SYMBOL_GPL(pci_remap_cfgspace);
+#endif
+
 void *arch_memremap_wb(phys_addr_t phys_addr, size_t size)
 {
        return (void *)phys_addr;
index 3b69f26425130fd65aebc4342bcfbdbbd84a68c7..1403cb4a0c3da8c3be996722739ae6c0c9e9c3a1 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
+#include <asm/set_memory.h>
 
 struct page_change_data {
        pgprot_t set_mask;
index 93d0b6d0b63eede5f36de91428bb181bab2e0971..d5b9fa19b684b69758661ef9fbd8d023e04d1d68 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/if_vlan.h>
 
 #include <asm/cacheflush.h>
+#include <asm/set_memory.h>
 #include <asm/hwcap.h>
 #include <asm/opcodes.h>
 
index 03fac123676db0c5eb9901076ead5b65c33bd889..dc269d9143bca73b6201350fc1b85895787da460 100644 (file)
@@ -10,7 +10,6 @@
  * published by the Free Software Foundation.
 */
 
-#include <linux/amba/pl330.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/interrupt.h>
diff --git a/arch/arm/plat-versatile/include/plat/clock.h b/arch/arm/plat-versatile/include/plat/clock.h
deleted file mode 100644 (file)
index 3cfb024..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef PLAT_CLOCK_H
-#define PLAT_CLOCK_H
-
-#include <asm/hardware/icst.h>
-
-struct clk_ops {
-       long    (*round)(struct clk *, unsigned long);
-       int     (*set)(struct clk *, unsigned long);
-       void    (*setvco)(struct clk *, struct icst_vco);
-};
-
-int icst_clk_set(struct clk *, unsigned long);
-long icst_clk_round(struct clk *, unsigned long);
-
-#endif
index 129cc5ae4091489c08eb751f3e1b85b6eaa2eb9c..73272f43ca012faac98c0aceed350dcd49814b28 100644 (file)
@@ -2,9 +2,10 @@ menu "Platform selection"
 
 config ARCH_SUNXI
        bool "Allwinner sunxi 64-bit SoC Family"
+       select ARCH_HAS_RESET_CONTROLLER
        select GENERIC_IRQ_CHIP
        select PINCTRL
-       select PINCTRL_SUN50I_A64
+       select RESET_CONTROLLER
        help
          This enables support for Allwinner sunxi based SoCs like the A64.
 
@@ -54,6 +55,8 @@ config ARCH_BRCMSTB
 config ARCH_EXYNOS
        bool "ARMv8 based Samsung Exynos SoC family"
        select COMMON_CLK_SAMSUNG
+       select EXYNOS_PM_DOMAINS if PM_GENERIC_DOMAINS
+       select EXYNOS_PMU
        select HAVE_S3C2410_WATCHDOG if WATCHDOG
        select HAVE_S3C_RTC if RTC_CLASS
        select PINCTRL
@@ -103,8 +106,13 @@ config ARCH_MVEBU
        select ARMADA_AP806_SYSCON
        select ARMADA_CP110_SYSCON
        select ARMADA_37XX_CLK
+       select GPIOLIB
+       select GPIOLIB_IRQCHIP
        select MVEBU_ODMI
        select MVEBU_PIC
+       select OF_GPIO
+       select PINCTRL
+       select PINCTRL_ARMADA_37XX
        help
          This enables support for Marvell EBU familly, including:
           - Armada 3700 SoC Family
index 7dedf2d8494e368865e0f18c0095f53c499f2649..f839ecd919f934c54a73d8e9f8179aff3d3cba26 100644 (file)
@@ -102,12 +102,12 @@ libs-y            := arch/arm64/lib/ $(libs-y)
 core-$(CONFIG_EFI_STUB) += $(objtree)/drivers/firmware/efi/libstub/lib.a
 
 # Default target when executing plain make
-KBUILD_IMAGE   := Image.gz
+boot           := arch/arm64/boot
+KBUILD_IMAGE   := $(boot)/Image.gz
 KBUILD_DTBS    := dtbs
 
-all:   $(KBUILD_IMAGE) $(KBUILD_DTBS)
+all:   Image.gz $(KBUILD_DTBS)
 
-boot := arch/arm64/boot
 
 Image: vmlinux
        $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
index bc6f342be59ffcc05cdfc89b7ced42ed2a45c7ac..244e8b7565f9b5ab2ff4a5aac0c317e578728b3b 100644 (file)
@@ -1,5 +1,6 @@
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-bananapi-m64.dtb
 dtb-$(CONFIG_ARCH_SUNXI) += sun50i-a64-pine64-plus.dtb sun50i-a64-pine64.dtb
+dtb-$(CONFIG_ARCH_SUNXI) += sun50i-h5-orangepi-pc2.dtb
 
 always         := $(dtb-y)
 subdir-y       := $(dts-dirs)
index 0565779e66fafd9755048c2a1c7f8ebc15533eff..c7f669f5884f910c6e4be44ac1dd09a216cb97f0 100644 (file)
                clock-output-names = "osc32k";
        };
 
+       iosc: internal-osc-clk {
+               #clock-cells = <0>;
+               compatible = "fixed-clock";
+               clock-frequency = <16000000>;
+               clock-accuracy = <300000000>;
+               clock-output-names = "iosc";
+       };
+
        psci {
                compatible = "arm,psci-0.2";
                method = "smc";
                        interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>,
                                     <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
                };
+
+               r_ccu: clock@1f01400 {
+                       compatible = "allwinner,sun50i-a64-r-ccu";
+                       reg = <0x01f01400 0x100>;
+                       clocks = <&osc24M>, <&osc32k>, <&iosc>;
+                       clock-names = "hosc", "losc", "iosc";
+                       #clock-cells = <1>;
+                       #reset-cells = <1>;
+               };
+
+               r_pio: pinctrl@01f02c00 {
+                       compatible = "allwinner,sun50i-a64-r-pinctrl";
+                       reg = <0x01f02c00 0x400>;
+                       interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&r_ccu 3>, <&osc24M>, <&osc32k>;
+                       clock-names = "apb", "hosc", "losc";
+                       gpio-controller;
+                       #gpio-cells = <3>;
+                       interrupt-controller;
+                       #interrupt-cells = <3>;
+               };
        };
 };
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-pc2.dts
new file mode 100644 (file)
index 0000000..dfecc17
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+ * Copyright (C) 2016 ARM Ltd.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "sun50i-h5.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include <dt-bindings/pinctrl/sun4i-a10.h>
+
+/ {
+       model = "Xunlong Orange Pi PC 2";
+       compatible = "xunlong,orangepi-pc2", "allwinner,sun50i-h5";
+
+       reg_vcc3v3: vcc3v3 {
+               compatible = "regulator-fixed";
+               regulator-name = "vcc3v3";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+       };
+
+       aliases {
+               serial0 = &uart0;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               pwr {
+                       label = "orangepi:green:pwr";
+                       gpios = <&r_pio 0 10 GPIO_ACTIVE_HIGH>;
+                       default-state = "on";
+               };
+
+               status {
+                       label = "orangepi:red:status";
+                       gpios = <&pio 0 20 GPIO_ACTIVE_HIGH>;
+               };
+       };
+
+       r-gpio-keys {
+               compatible = "gpio-keys";
+
+               sw4 {
+                       label = "sw4";
+                       linux,code = <BTN_0>;
+                       gpios = <&r_pio 0 3 GPIO_ACTIVE_LOW>;
+               };
+       };
+
+       reg_usb0_vbus: usb0-vbus {
+               compatible = "regulator-fixed";
+               regulator-name = "usb0-vbus";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               enable-active-high;
+               gpio = <&r_pio 0 2 GPIO_ACTIVE_HIGH>; /* PL2 */
+               status = "okay";
+       };
+};
+
+&codec {
+       allwinner,audio-routing =
+               "Line Out", "LINEOUT",
+               "MIC1", "Mic",
+               "Mic",  "MBIAS";
+       status = "okay";
+};
+
+&ehci0 {
+       status = "okay";
+};
+
+&ehci1 {
+       status = "okay";
+};
+
+&ehci2 {
+       status = "okay";
+};
+
+&ehci3 {
+       status = "okay";
+};
+
+&ir {
+       pinctrl-names = "default";
+       pinctrl-0 = <&ir_pins_a>;
+       status = "okay";
+};
+
+&mmc0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mmc0_pins_a>, <&mmc0_cd_pin>;
+       vmmc-supply = <&reg_vcc3v3>;
+       bus-width = <4>;
+       cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */
+       status = "okay";
+};
+
+&ohci0 {
+       status = "okay";
+};
+
+&ohci1 {
+       status = "okay";
+};
+
+&ohci2 {
+       status = "okay";
+};
+
+&ohci3 {
+       status = "okay";
+};
+
+&uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart0_pins_a>;
+       status = "okay";
+};
+
+&uart1 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart1_pins>;
+       status = "disabled";
+};
+
+&uart2 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart2_pins>;
+       status = "disabled";
+};
+
+&usb_otg {
+       dr_mode = "otg";
+       status = "okay";
+};
+
+&usbphy {
+       /* USB Type-A ports' VBUS is always on */
+       usb0_id_det-gpios = <&pio 6 12 GPIO_ACTIVE_HIGH>; /* PG12 */
+       usb0_vbus-supply = <&reg_usb0_vbus>;
+       status = "okay";
+};
diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h5.dtsi
new file mode 100644 (file)
index 0000000..4d314a2
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2016 ARM Ltd.
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "sunxi-h3-h5.dtsi"
+
+/ {
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu@0 {
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       device_type = "cpu";
+                       reg = <0>;
+                       enable-method = "psci";
+               };
+
+               cpu@1 {
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       device_type = "cpu";
+                       reg = <1>;
+                       enable-method = "psci";
+               };
+
+               cpu@2 {
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       device_type = "cpu";
+                       reg = <2>;
+                       enable-method = "psci";
+               };
+
+               cpu@3 {
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       device_type = "cpu";
+                       reg = <3>;
+                       enable-method = "psci";
+               };
+       };
+
+       psci {
+               compatible = "arm,psci-0.2";
+               method = "smc";
+       };
+
+       timer {
+               compatible = "arm,armv8-timer";
+               interrupts = <GIC_PPI 13
+                               (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+                            <GIC_PPI 14
+                               (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+                            <GIC_PPI 11
+                               (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+                            <GIC_PPI 10
+                               (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+       };
+};
+
+&ccu {
+       compatible = "allwinner,sun50i-h5-ccu";
+};
+
+&mmc0 {
+       compatible = "allwinner,sun50i-h5-mmc",
+                    "allwinner,sun50i-a64-mmc";
+       clocks = <&ccu CLK_BUS_MMC0>, <&ccu CLK_MMC0>;
+       clock-names = "ahb", "mmc";
+};
+
+&mmc1 {
+       compatible = "allwinner,sun50i-h5-mmc",
+                    "allwinner,sun50i-a64-mmc";
+       clocks = <&ccu CLK_BUS_MMC1>, <&ccu CLK_MMC1>;
+       clock-names = "ahb", "mmc";
+};
+
+&mmc2 {
+       compatible = "allwinner,sun50i-h5-emmc",
+                    "allwinner,sun50i-a64-emmc";
+       clocks = <&ccu CLK_BUS_MMC2>, <&ccu CLK_MMC2>;
+       clock-names = "ahb", "mmc";
+};
+
+&pio {
+       compatible = "allwinner,sun50i-h5-pinctrl";
+};
diff --git a/arch/arm64/boot/dts/allwinner/sunxi-h3-h5.dtsi b/arch/arm64/boot/dts/allwinner/sunxi-h3-h5.dtsi
new file mode 120000 (symlink)
index 0000000..036f01d
--- /dev/null
@@ -0,0 +1 @@
+../../../../arm/boot/dts/sunxi-h3-h5.dtsi
\ No newline at end of file
index 3f94bce33b7f4ac1455528f59724e0944f2c53d7..b9ad2db7398ba6bc2457308accaf8bac28b78766 100644 (file)
@@ -7,9 +7,11 @@ dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-vega-s95-meta.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-vega-s95-telos.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-wetek-hub.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxbb-wetek-play2.dtb
+dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-khadas-vim.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-p212.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-p230.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905d-p231.dtb
+dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-hwacom-amazetv.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxl-s905x-nexbox-a95x.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxm-q200.dtb
 dtb-$(CONFIG_ARCH_MESON) += meson-gxm-q201.dtb
index 7a078bef04cd59d4059e328d6a5c40f8dfbae83a..a84e27622639724da6661540d1e0ccb5192e2d39 100644 (file)
                clocks = <&wifi32k>;
                clock-names = "ext_clock";
        };
+
+       cvbs-connector {
+               compatible = "composite-video-connector";
+
+               port {
+                       cvbs_connector_in: endpoint {
+                               remote-endpoint = <&cvbs_vdac_out>;
+                       };
+               };
+       };
+
+       hdmi-connector {
+               compatible = "hdmi-connector";
+               type = "a";
+
+               port {
+                       hdmi_connector_in: endpoint {
+                               remote-endpoint = <&hdmi_tx_tmds_out>;
+                       };
+               };
+       };
 };
 
 /* This UART is brought out to the DB9 connector */
 &ethmac {
        status = "okay";
 };
+
+&cvbs_vdac_port {
+       cvbs_vdac_out: endpoint {
+               remote-endpoint = <&cvbs_connector_in>;
+       };
+};
+
+&hdmi_tx {
+       status = "okay";
+       pinctrl-0 = <&hdmi_hpd_pins>, <&hdmi_i2c_pins>;
+       pinctrl-names = "default";
+};
+
+&hdmi_tx_tmds_port {
+       hdmi_tx_tmds_out: endpoint {
+               remote-endpoint = <&hdmi_connector_in>;
+       };
+};
index 620495a43363928e926b76ff2e654e2aea15dd98..436b875060e708340beb6b8332655f259d63e450 100644 (file)
                        reg = <0x0 0x10000000 0x0 0x200000>;
                        no-map;
                };
+
+               linux,cma {
+                       compatible = "shared-dma-pool";
+                       reusable;
+                       size = <0x0 0xbc00000>;
+                       alignment = <0x0 0x400000>;
+                       linux,cma-default;
+               };
        };
 
        cpus {
                        };
 
                        i2c_A: i2c@8500 {
-                               compatible = "amlogic,meson-gxbb-i2c";
+                               compatible = "amlogic,meson-gx-i2c", "amlogic,meson-gxbb-i2c";
                                reg = <0x0 0x08500 0x0 0x20>;
                                interrupts = <GIC_SPI 21 IRQ_TYPE_EDGE_RISING>;
                                #address-cells = <1>;
                        };
 
                        i2c_B: i2c@87c0 {
-                               compatible = "amlogic,meson-gxbb-i2c";
+                               compatible = "amlogic,meson-gx-i2c", "amlogic,meson-gxbb-i2c";
                                reg = <0x0 0x087c0 0x0 0x20>;
                                interrupts = <GIC_SPI 214 IRQ_TYPE_EDGE_RISING>;
                                #address-cells = <1>;
                        };
 
                        i2c_C: i2c@87e0 {
-                               compatible = "amlogic,meson-gxbb-i2c";
+                               compatible = "amlogic,meson-gx-i2c", "amlogic,meson-gxbb-i2c";
                                reg = <0x0 0x087e0 0x0 0x20>;
                                interrupts = <GIC_SPI 215 IRQ_TYPE_EDGE_RISING>;
                                #address-cells = <1>;
                                status = "disabled";
                        };
 
+                       spifc: spi@8c80 {
+                               compatible = "amlogic,meson-gx-spifc", "amlogic,meson-gxbb-spifc";
+                               reg = <0x0 0x08c80 0x0 0x80>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
                        watchdog@98d0 {
                                compatible = "amlogic,meson-gx-wdt", "amlogic,meson-gxbb-wdt";
                                reg = <0x0 0x098d0 0x0 0x10>;
                };
 
                sram: sram@c8000000 {
-                       compatible = "amlogic,meson-gxbb-sram", "mmio-sram";
+                       compatible = "amlogic,meson-gx-sram", "amlogic,meson-gxbb-sram", "mmio-sram";
                        reg = <0x0 0xc8000000 0x0 0x14000>;
 
                        #address-cells = <1>;
                        ranges = <0 0x0 0xc8000000 0x14000>;
 
                        cpu_scp_lpri: scp-shmem@0 {
-                               compatible = "amlogic,meson-gxbb-scp-shmem";
+                               compatible = "amlogic,meson-gx-scp-shmem", "amlogic,meson-gxbb-scp-shmem";
                                reg = <0x13000 0x400>;
                        };
 
                        cpu_scp_hpri: scp-shmem@200 {
-                               compatible = "amlogic,meson-gxbb-scp-shmem";
+                               compatible = "amlogic,meson-gx-scp-shmem", "amlogic,meson-gxbb-scp-shmem";
                                reg = <0x13400 0x400>;
                        };
                };
                        #size-cells = <2>;
                        ranges = <0x0 0x0 0x0 0xc8100000 0x0 0x100000>;
 
+                       clkc_AO: clock-controller@040 {
+                               compatible = "amlogic,gx-aoclkc", "amlogic,gxbb-aoclkc";
+                               reg = <0x0 0x00040 0x0 0x4>;
+                               #clock-cells = <1>;
+                               #reset-cells = <1>;
+                       };
+
                        uart_AO: serial@4c0 {
                                compatible = "amlogic,meson-uart";
                                reg = <0x0 0x004c0 0x0 0x14>;
                                status = "disabled";
                        };
 
+                       i2c_AO: i2c@500 {
+                               compatible = "amlogic,meson-gx-i2c", "amlogic,meson-gxbb-i2c";
+                               reg = <0x0 0x500 0x0 0x20>;
+                               interrupts = <GIC_SPI 195 IRQ_TYPE_EDGE_RISING>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               status = "disabled";
+                       };
+
                        pwm_AO_ab: pwm@550 {
                                compatible = "amlogic,meson-gx-pwm", "amlogic,meson-gxbb-pwm";
                                reg = <0x0 0x00550 0x0 0x10>;
                        };
 
                        ir: ir@580 {
-                               compatible = "amlogic,meson-gxbb-ir";
+                               compatible = "amlogic,meson-gx-ir", "amlogic,meson-gxbb-ir";
                                reg = <0x0 0x00580 0x0 0x40>;
                                interrupts = <GIC_SPI 196 IRQ_TYPE_EDGE_RISING>;
                                status = "disabled";
                        };
                };
 
-
                hiubus: hiubus@c883c000 {
                        compatible = "simple-bus";
                        reg = <0x0 0xc883c000 0x0 0x2000>;
                               0x0 0xc8834540 0x0 0x4>;
                        interrupts = <0 8 1>;
                        interrupt-names = "macirq";
-                       phy-mode = "rgmii";
                        status = "disabled";
                };
 
                        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>;
+                               };
+                       };
+               };
+
+               hdmi_tx: hdmi-tx@c883a000 {
+                       compatible = "amlogic,meson-gx-dw-hdmi";
+                       reg = <0x0 0xc883a000 0x0 0x1c>;
+                       interrupts = <GIC_SPI 57 IRQ_TYPE_EDGE_RISING>;
+                       #address-cells = <1>;
+                       #size-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>;
+                       };
                };
        };
 };
index 4cbd626a9e887b01285c6052fb3590d46bcae176..87198eafb04b678c840a0b5d047c7365ad4f7e63 100644 (file)
                        };
                };
        };
+
+       hdmi-connector {
+               compatible = "hdmi-connector";
+               type = "a";
+
+               port {
+                       hdmi_connector_in: endpoint {
+                               remote-endpoint = <&hdmi_tx_tmds_out>;
+                       };
+               };
+       };
 };
 
 &uart_AO {
        status = "okay";
        pinctrl-0 = <&eth_rmii_pins>;
        pinctrl-names = "default";
+
+       phy-handle = <&eth_phy0>;
        phy-mode = "rmii";
+
+       snps,reset-gpio = <&gpio GPIOZ_14 0>;
+       snps,reset-delays-us = <0 10000 1000000>;
+       snps,reset-active-low;
+
+       mdio {
+               compatible = "snps,dwmac-mdio";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               eth_phy0: ethernet-phy@0 {
+                       /* IC Plus IP101GR (0x02430c54) */
+                       reg = <0>;
+               };
+       };
 };
 
 &ir {
                remote-endpoint = <&cvbs_connector_in>;
        };
 };
+
+&hdmi_tx {
+       status = "okay";
+       pinctrl-0 = <&hdmi_hpd_pins>, <&hdmi_i2c_pins>;
+       pinctrl-names = "default";
+};
+
+&hdmi_tx_tmds_port {
+       hdmi_tx_tmds_out: endpoint {
+               remote-endpoint = <&hdmi_connector_in>;
+       };
+};
index c59403adb387dbcd33d375561ee3eaa07ebdfa3f..54a9c6a6b3923cda35270c3719a274882bc56ef5 100644 (file)
@@ -96,7 +96,7 @@
                regulator-min-microvolt = <3300000>;
                regulator-max-microvolt = <3300000>;
 
-               gpio = <&gpio_ao GPIOAO_12 GPIO_ACTIVE_HIGH>;
+               gpio = <&gpio GPIOY_12 GPIO_ACTIVE_HIGH>;
                enable-active-high;
        };
 
        pinctrl-0 = <&eth_rgmii_pins>;
        pinctrl-names = "default";
        phy-handle = <&eth_phy0>;
+       phy-mode = "rgmii";
+
+       snps,reset-gpio = <&gpio GPIOZ_14 0>;
+       snps,reset-delays-us = <0 10000 1000000>;
+       snps,reset-active-low;
+
+       amlogic,tx-delay-ns = <2>;
 
        mdio {
                compatible = "snps,dwmac-mdio";
        };
 };
 
+&pinctrl_aobus {
+       gpio-line-names = "UART TX", "UART RX", "VCCK En", "TF 3V3/1V8 En",
+                         "USB HUB nRESET", "USB OTG Power En",
+                         "J7 Header Pin2", "IR In", "J7 Header Pin4",
+                         "J7 Header Pin6", "J7 Header Pin5", "J7 Header Pin7",
+                         "HDMI CEC", "SYS LED";
+};
+
+&pinctrl_periphs {
+       gpio-line-names = /* Bank GPIOZ */
+                         "Eth MDIO", "Eth MDC", "Eth RGMII RX Clk",
+                         "Eth RX DV", "Eth RX D0", "Eth RX D1", "Eth RX D2",
+                         "Eth RX D3", "Eth RGMII TX Clk", "Eth TX En",
+                         "Eth TX D0", "Eth TX D1", "Eth TX D2", "Eth TX D3",
+                         "Eth PHY nRESET", "Eth PHY Intc",
+                         /* Bank GPIOH */
+                         "HDMI HPD", "HDMI DDC SDA", "HDMI DDC SCL", "",
+                         /* Bank BOOT */
+                         "eMMC D0", "eMMC D1", "eMMC D2", "eMMC D3", "eMMC D4",
+                         "eMMC D5", "eMMC D6", "eMMC D7", "eMMC Clk",
+                         "eMMC Reset", "eMMC CMD",
+                         "", "", "", "", "", "", "",
+                         /* Bank CARD */
+                         "SDCard D1", "SDCard D0", "SDCard CLK", "SDCard CMD",
+                         "SDCard D3", "SDCard D2", "SDCard Det",
+                         /* Bank GPIODV */
+                         "", "", "", "", "", "", "", "", "", "", "", "", "",
+                         "", "", "", "", "", "", "", "", "", "", "",
+                         "I2C A SDA", "I2C A SCK", "I2C B SDA", "I2C B SCK",
+                         "PWM D", "PWM B",
+                         /* Bank GPIOY */
+                         "Revision Bit0", "Revision Bit1", "",
+                         "J2 Header Pin35", "", "", "", "J2 Header Pin36",
+                         "J2 Header Pin31", "", "", "", "TF VDD En",
+                         "J2 Header Pin32", "J2 Header Pin26", "", "",
+                         /* Bank GPIOX */
+                         "J2 Header Pin29", "J2 Header Pin24",
+                         "J2 Header Pin23", "J2 Header Pin22",
+                         "J2 Header Pin21", "J2 Header Pin18",
+                         "J2 Header Pin33", "J2 Header Pin19",
+                         "J2 Header Pin16", "J2 Header Pin15",
+                         "J2 Header Pin12", "J2 Header Pin13",
+                         "J2 Header Pin8", "J2 Header Pin10",
+                         "", "", "", "", "",
+                         "J2 Header Pin11", "", "J2 Header Pin7",
+                         /* Bank GPIOCLK */
+                         "", "", "", "",
+                         /* GPIO_TEST_N */
+                         "";
+};
+
 &ir {
        status = "okay";
        pinctrl-0 = <&remote_input_ao_pins>;
        pinctrl-names = "default";
 };
 
+&gpio_ao {
+       /*
+        * WARNING: The USB Hub on the Odroid-C2 needs a reset signal
+        * to be turned high in order to be detected by the USB Controller
+        * This signal should be handled by a USB specific power sequence
+        * in order to reset the Hub when USB bus is powered down.
+        */
+       usb-hub {
+               gpio-hog;
+               gpios = <GPIOAO_4 GPIO_ACTIVE_HIGH>;
+               output-high;
+               line-name = "usb-hub-reset";
+       };
+};
+
 &usb0_phy {
        status = "okay";
        phy-supply = <&usb_otg_pwr>;
        status = "okay";
 };
 
+&saradc {
+       status = "okay";
+       vref-supply = <&vcc1v8>;
+};
+
 /* SD */
 &sd_emmc_b {
        status = "okay";
index fc0e86cb4cdedc00a8796b2276bc3b53c0df9b03..2054a474e0a91dc58a883a9b4a563e32bcd9e32d 100644 (file)
        };
 };
 
+&ethmac {
+       status = "okay";
+       pinctrl-0 = <&eth_rgmii_pins>;
+       pinctrl-names = "default";
+       phy-handle = <&eth_phy0>;
+       phy-mode = "rgmii";
+
+       amlogic,tx-delay-ns = <2>;
+
+       snps,reset-gpio = <&gpio GPIOZ_14 0>;
+       snps,reset-delays-us = <0 10000 1000000>;
+       snps,reset-active-low;
+
+       mdio {
+               compatible = "snps,dwmac-mdio";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               eth_phy0: ethernet-phy@3 {
+                       /* Micrel KSZ9031 (0x00221620) */
+                       reg = <3>;
+               };
+       };
+};
+
 &i2c_B {
        status = "okay";
        pinctrl-0 = <&i2c_b_pins>;
index 39bb037a3e475fec1e202aaaa10d1ce17900bc06..ae3194663d642709ac950b7826f22685936717a9 100644 (file)
        compatible = "amlogic,p201", "amlogic,meson-gxbb";
        model = "Amlogic Meson GXBB P201 Development Board";
 };
+
+&ethmac {
+       status = "okay";
+       pinctrl-0 = <&eth_rmii_pins>;
+       pinctrl-names = "default";
+       phy-mode = "rmii";
+
+       snps,reset-gpio = <&gpio GPIOZ_14 0>;
+       snps,reset-delays-us = <0 10000 1000000>;
+       snps,reset-active-low;
+};
index 4a96e0f6f9265b858287c039714e652062134c9e..3c6c0b7f4187dac8b4794e2e9117d45ca3fe0199 100644 (file)
                        };
                };
        };
+
+       hdmi-connector {
+               compatible = "hdmi-connector";
+               type = "a";
+
+               port {
+                       hdmi_connector_in: endpoint {
+                               remote-endpoint = <&hdmi_tx_tmds_out>;
+                       };
+               };
+       };
 };
 
 /* This UART is brought out to the DB9 connector */
        pinctrl-names = "default";
 };
 
-&ethmac {
-       status = "okay";
-       pinctrl-0 = <&eth_rgmii_pins>;
-       pinctrl-names = "default";
-};
-
 &ir {
        status = "okay";
        pinctrl-0 = <&remote_input_ao_pins>;
                remote-endpoint = <&cvbs_connector_in>;
        };
 };
+
+&hdmi_tx {
+       status = "okay";
+       pinctrl-0 = <&hdmi_hpd_pins>, <&hdmi_i2c_pins>;
+       pinctrl-names = "default";
+};
+
+&hdmi_tx_tmds_port {
+       hdmi_tx_tmds_out: endpoint {
+               remote-endpoint = <&hdmi_connector_in>;
+       };
+};
index 86709929fd208cf1d66221bf5d58687a1acedc22..aefa66dff72dc52042a01753d28734798cf75866 100644 (file)
        status = "okay";
        pinctrl-0 = <&uart_ao_a_pins>;
        pinctrl-names = "default";
-
 };
 
 &ir {
        status = "okay";
        pinctrl-0 = <&eth_rgmii_pins>;
        pinctrl-names = "default";
+
+       phy-handle = <&eth_phy0>;
+       phy-mode = "rgmii";
+
+       amlogic,tx-delay-ns = <2>;
+
+       snps,reset-gpio = <&gpio GPIOZ_14 0>;
+       snps,reset-delays-us = <0 10000 1000000>;
+       snps,reset-active-low;
+
+       mdio {
+               compatible = "snps,dwmac-mdio";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               eth_phy0: ethernet-phy@0 {
+                       /* Realtek RTL8211F (0x001cc916) */
+                       reg = <0>;
+               };
+       };
 };
 
 &usb0_phy {
index 56f855901262c3b736b5e9b8d5deab1b15491e02..f057fb48fee5563d2f9e0a3ba38a6753c559b922 100644 (file)
                status = "disabled";
        };
 };
+
+&ethmac {
+       status = "okay";
+       pinctrl-0 = <&eth_rgmii_pins>;
+       pinctrl-names = "default";
+
+       phy-handle = <&eth_phy0>;
+       phy-mode = "rgmii";
+
+       amlogic,tx-delay-ns = <2>;
+
+       snps,reset-gpio = <&gpio GPIOZ_14 0>;
+       snps,reset-delays-us = <0 10000 1000000>;
+       snps,reset-active-low;
+
+       mdio {
+               compatible = "snps,dwmac-mdio";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               eth_phy0: ethernet-phy@0 {
+                       /* Realtek RTL8211F (0x001cc916) */
+                       reg = <0>;
+               };
+       };
+};
index ea79fdd2c248a348f340d1f98a9cd842b52b0163..743acb5f5d06353e010c857ba5c3efd6489d26b2 100644 (file)
        };
 };
 
+&ethmac {
+       status = "okay";
+       pinctrl-0 = <&eth_rgmii_pins>;
+       pinctrl-names = "default";
+
+       phy-handle = <&eth_phy0>;
+       phy-mode = "rgmii";
+
+       amlogic,tx-delay-ns = <2>;
+
+       snps,reset-gpio = <&gpio GPIOZ_14 0>;
+       snps,reset-delays-us = <0 10000 1000000>;
+       snps,reset-active-low;
+
+       mdio {
+               compatible = "snps,dwmac-mdio";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               eth_phy0: ethernet-phy@0 {
+                       /* Realtek RTL8211F (0x001cc916) */
+                       reg = <0>;
+               };
+       };
+};
+
 &i2c_A {
        status = "okay";
        pinctrl-0 = <&i2c_a_pins>;
index a375cb21cc8b10f7efc9b71eb9d64faa3493ae97..86105a69690aa8c66342e7e22e6846a6140203cb 100644 (file)
        };
 };
 
-&cbus {
-       spifc: spi@8c80 {
-               compatible = "amlogic,meson-gxbb-spifc";
-               reg = <0x0 0x08c80 0x0 0x80>;
-               #address-cells = <1>;
-               #size-cells = <0>;
-               clocks = <&clkc CLKID_SPI>;
-               status = "disabled";
-       };
-};
-
 &ethmac {
        clocks = <&clkc CLKID_ETH>,
                 <&clkc CLKID_FCLK_DIV2>,
                        reg-names = "mux", "pull", "gpio";
                        gpio-controller;
                        #gpio-cells = <2>;
+                       gpio-ranges = <&pinctrl_aobus 0 0 14>;
                };
 
                uart_ao_a_pins: uart_ao_a {
                                function = "pwm_ao_b";
                        };
                };
-       };
 
-       clkc_AO: clock-controller@040 {
-               compatible = "amlogic,gxbb-aoclkc";
-               reg = <0x0 0x00040 0x0 0x4>;
-               #clock-cells = <1>;
-               #reset-cells = <1>;
-       };
+               i2s_am_clk_pins: i2s_am_clk {
+                       mux {
+                               groups = "i2s_am_clk";
+                               function = "i2s_out_ao";
+                       };
+               };
 
-       pwm_ab_AO: pwm@550 {
-               compatible = "amlogic,meson-gxbb-pwm";
-               reg = <0x0 0x0550 0x0 0x10>;
-               #pwm-cells = <3>;
-               status = "disabled";
-       };
+               i2s_out_ao_clk_pins: i2s_out_ao_clk {
+                       mux {
+                               groups = "i2s_out_ao_clk";
+                               function = "i2s_out_ao";
+                       };
+               };
 
-       i2c_AO: i2c@500 {
-               compatible = "amlogic,meson-gxbb-i2c";
-               reg = <0x0 0x500 0x0 0x20>;
-               interrupts = <GIC_SPI 195 IRQ_TYPE_EDGE_RISING>;
-               clocks = <&clkc CLKID_AO_I2C>;
-               #address-cells = <1>;
-               #size-cells = <0>;
-               status = "disabled";
+               i2s_out_lr_clk_pins: i2s_out_lr_clk {
+                       mux {
+                               groups = "i2s_out_lr_clk";
+                               function = "i2s_out_ao";
+                       };
+               };
+
+               i2s_out_ch01_ao_pins: i2s_out_ch01_ao {
+                       mux {
+                               groups = "i2s_out_ch01_ao";
+                               function = "i2s_out_ao";
+                       };
+               };
+
+               i2s_out_ch23_ao_pins: i2s_out_ch23_ao {
+                       mux {
+                               groups = "i2s_out_ch23_ao";
+                               function = "i2s_out_ao";
+                       };
+               };
+
+               i2s_out_ch45_ao_pins: i2s_out_ch45_ao {
+                       mux {
+                               groups = "i2s_out_ch45_ao";
+                               function = "i2s_out_ao";
+                       };
+               };
+
+               spdif_out_ao_6_pins: spdif_out_ao_6 {
+                       mux {
+                               groups = "spdif_out_ao_6";
+                               function = "spdif_out_ao";
+                       };
+               };
+
+               spdif_out_ao_13_pins: spdif_out_ao_13 {
+                       mux {
+                               groups = "spdif_out_ao_13";
+                               function = "spdif_out_ao";
+                       };
+               };
        };
 };
 
                        reg-names = "mux", "pull", "pull-enable", "gpio";
                        gpio-controller;
                        #gpio-cells = <2>;
+                       gpio-ranges = <&pinctrl_periphs 0 14 120>;
                };
 
                emmc_pins: emmc {
                                function = "hdmi_i2c";
                        };
                };
+
+               i2sout_ch23_y_pins: i2sout_ch23_y {
+                       mux {
+                               groups = "i2sout_ch23_y";
+                               function = "i2s_out";
+                       };
+               };
+
+               i2sout_ch45_y_pins: i2sout_ch45_y {
+                       mux {
+                               groups = "i2sout_ch45_y";
+                               function = "i2s_out";
+                       };
+               };
+
+               i2sout_ch67_y_pins: i2sout_ch67_y {
+                       mux {
+                               groups = "i2sout_ch67_y";
+                               function = "i2s_out";
+                       };
+               };
+
+               spdif_out_y_pins: spdif_out_y {
+                       mux {
+                               groups = "spdif_out_y";
+                               function = "spdif_out";
+                       };
+               };
        };
 };
 
        };
 };
 
+&apb {
+       mali: gpu@c0000 {
+               compatible = "amlogic,meson-gxbb-mali", "arm,mali-450";
+               reg = <0x0 0xc0000 0x0 0x40000>;
+               interrupts = <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "gp", "gpmmu", "pp", "pmu",
+                       "pp0", "ppmmu0", "pp1", "ppmmu1",
+                       "pp2", "ppmmu2";
+               clocks = <&clkc CLKID_CLK81>, <&clkc CLKID_MALI>;
+               clock-names = "bus", "core";
+
+               /*
+                * 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_DIV3>,
+                                        <0>, /* Do Nothing */
+                                        <&clkc CLKID_MALI_0>;
+               assigned-clock-rates = <0>, /* Do Nothing */
+                                      <666666666>,
+                                      <0>; /* Do Nothing */
+       };
+};
+
 &i2c_A {
        clocks = <&clkc CLKID_I2C>;
 };
 
+&i2c_AO {
+       clocks = <&clkc CLKID_AO_I2C>;
+};
+
 &i2c_B {
        clocks = <&clkc CLKID_I2C>;
 };
        clock-names = "core", "clkin0", "clkin1";
 };
 
+&spifc {
+       clocks = <&clkc CLKID_SPI>;
+};
+
 &vpu {
        compatible = "amlogic,meson-gxbb-vpu", "amlogic,meson-gx-vpu";
 };
        clocks = <&clkc CLKID_RNG0>;
        clock-names = "core";
 };
+
+&hdmi_tx {
+       compatible = "amlogic,meson-gxbb-dw-hdmi", "amlogic,meson-gx-dw-hdmi";
+       resets = <&reset RESET_HDMITX_CAPB3>,
+                <&reset RESET_HDMI_SYSTEM_RESET>,
+                <&reset RESET_HDMI_TX>;
+       reset-names = "hdmitx_apb", "hdmitx", "hdmitx_phy";
+       clocks = <&clkc CLKID_HDMI_PCLK>,
+                <&clkc CLKID_CLK81>,
+                <&clkc CLKID_GCLK_VENCI_INT0>;
+       clock-names = "isfr", "iahb", "venci";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-mali.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl-mali.dtsi
new file mode 100644 (file)
index 0000000..f06cc23
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2017 BayLibre SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+ */
+
+&apb {
+       mali: gpu@c0000 {
+               compatible = "amlogic,meson-gxbb-mali", "arm,mali-450";
+               reg = <0x0 0xc0000 0x0 0x40000>;
+               interrupts = <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 162 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 163 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 164 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 165 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 166 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 167 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "gp", "gpmmu", "pp", "pmu",
+                       "pp0", "ppmmu0", "pp1", "ppmmu1",
+                       "pp2", "ppmmu2";
+               clocks = <&clkc CLKID_CLK81>, <&clkc CLKID_MALI>;
+               clock-names = "bus", "core";
+
+               /*
+                * 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_DIV3>,
+                                        <0>, /* Do Nothing */
+                                        <&clkc CLKID_MALI_0>;
+               assigned-clock-rates = <0>, /* Do Nothing */
+                                      <666666666>,
+                                      <0>; /* Do Nothing */
+       };
+};
index f66939cacd3713bf9b3bc290c74220128ba09d6a..f9fbfdad8ddef6ca5fc291fc40672254a2bf61c8 100644 (file)
 
 /dts-v1/;
 
+#include <dt-bindings/input/input.h>
+
 #include "meson-gxl-s905d.dtsi"
 #include "meson-gx-p23x-q20x.dtsi"
 
 / {
        compatible = "amlogic,p230", "amlogic,s905d", "amlogic,meson-gxl";
        model = "Amlogic Meson GXL (S905D) P230 Development Board";
+
+       adc-keys {
+               compatible = "adc-keys";
+               io-channels = <&saradc 0>;
+               io-channel-names = "buttons";
+               keyup-threshold-microvolt = <1710000>;
+
+               button-function {
+                       label = "Update";
+                       linux,code = <KEY_VENDOR>;
+                       press-threshold-microvolt = <10000>;
+               };
+       };
+
+       gpio-keys-polled {
+               compatible = "gpio-keys-polled";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               poll-interval = <100>;
+
+               button@0 {
+                       label = "power";
+                       linux,code = <KEY_POWER>;
+                       gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_LOW>;
+               };
+       };
+
+       vddio_ao18: regulator-vddio_ao18 {
+               compatible = "regulator-fixed";
+               regulator-name = "VDDIO_AO18";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+       };
 };
 
 /* P230 has exclusive choice between internal or external PHY */
@@ -59,6 +94,8 @@
        /* Select external PHY by default */
        phy-handle = <&external_phy>;
 
+       amlogic,tx-delay-ns = <2>;
+
        /* External PHY reset is shared with internal PHY Led signals */
        snps,reset-gpio = <&gpio GPIOZ_14 0>;
        snps,reset-delays-us = <0 10000 1000000>;
                max-speed = <1000>;
        };
 };
+
+&saradc {
+       status = "okay";
+       vref-supply = <&vddio_ao18>;
+};
index 615308e555764781183617a29a51847813fa64a1..5a90e30c10067e15fbdf3c9ed463964651e5562f 100644 (file)
@@ -42,6 +42,7 @@
  */
 
 #include "meson-gxl.dtsi"
+#include "meson-gxl-mali.dtsi"
 
 / {
        compatible = "amlogic,s905d", "amlogic,meson-gxl";
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-hwacom-amazetv.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-hwacom-amazetv.dts
new file mode 100644 (file)
index 0000000..2a5804c
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2017 Carlo Caione
+ * Copyright (c) 2016 BayLibre, Inc.
+ * Author: Neil Armstrong <narmstrong@kernel.org>
+ *
+ * SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+ */
+
+/dts-v1/;
+
+#include "meson-gxl-s905x.dtsi"
+
+/ {
+       compatible = "hwacom,amazetv", "amlogic,s905x", "amlogic,meson-gxl";
+       model = "Hwacom AmazeTV (S905X)";
+
+       aliases {
+               serial0 = &uart_AO;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+
+       memory@0 {
+               device_type = "memory";
+               reg = <0x0 0x0 0x0 0x80000000>;
+       };
+
+       vddio_card: gpio-regulator {
+               compatible = "regulator-gpio";
+
+               regulator-name = "VDDIO_CARD";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <3300000>;
+
+               gpios = <&gpio_ao GPIOAO_5 GPIO_ACTIVE_HIGH>;
+               gpios-states = <1>;
+
+               /* Based on P200 schematics, signal CARD_1.8V/3.3V_CTR */
+               states = <1800000 0
+                         3300000 1>;
+       };
+
+       vddio_boot: regulator-vddio_boot {
+               compatible = "regulator-fixed";
+               regulator-name = "VDDIO_BOOT";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+       };
+
+       vddao_3v3: regulator-vddao_3v3 {
+               compatible = "regulator-fixed";
+               regulator-name = "VDDAO_3V3";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+       };
+
+       vcc_3v3: regulator-vcc_3v3 {
+               compatible = "regulator-fixed";
+               regulator-name = "VCC_3V3";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+       };
+
+       emmc_pwrseq: emmc-pwrseq {
+               compatible = "mmc-pwrseq-emmc";
+               reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
+       };
+
+       wifi32k: wifi32k {
+               compatible = "pwm-clock";
+               #clock-cells = <0>;
+               clock-frequency = <32768>;
+               pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */
+       };
+
+       sdio_pwrseq: sdio-pwrseq {
+               compatible = "mmc-pwrseq-simple";
+               reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>;
+               clocks = <&wifi32k>;
+               clock-names = "ext_clock";
+       };
+
+       cvbs-connector {
+               compatible = "composite-video-connector";
+
+               port {
+                       cvbs_connector_in: endpoint {
+                               remote-endpoint = <&cvbs_vdac_out>;
+                       };
+               };
+       };
+};
+
+&cvbs_vdac_port {
+       cvbs_vdac_out: endpoint {
+               remote-endpoint = <&cvbs_connector_in>;
+       };
+};
+
+&ethmac {
+       status = "okay";
+       phy-mode = "rmii";
+       phy-handle = <&internal_phy>;
+};
+
+&ir {
+       status = "okay";
+       pinctrl-0 = <&remote_input_ao_pins>;
+       pinctrl-names = "default";
+};
+
+&pwm_ef {
+       status = "okay";
+       pinctrl-0 = <&pwm_e_pins>;
+       pinctrl-names = "default";
+       clocks = <&clkc CLKID_FCLK_DIV4>;
+       clock-names = "clkin0";
+};
+
+/* SD card */
+&sd_emmc_b {
+       status = "okay";
+       pinctrl-0 = <&sdcard_pins>;
+       pinctrl-names = "default";
+
+       bus-width = <4>;
+       cap-sd-highspeed;
+       max-frequency = <100000000>;
+       disable-wp;
+
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
+       cd-inverted;
+
+       vmmc-supply = <&vddao_3v3>;
+       vqmmc-supply = <&vddio_card>;
+};
+
+/* eMMC */
+&sd_emmc_c {
+       status = "okay";
+       pinctrl-0 = <&emmc_pins>;
+       pinctrl-names = "default";
+
+       bus-width = <8>;
+       cap-sd-highspeed;
+       cap-mmc-highspeed;
+       max-frequency = <100000000>;
+       non-removable;
+       disable-wp;
+       mmc-ddr-1_8v;
+       mmc-hs200-1_8v;
+
+       mmc-pwrseq = <&emmc_pwrseq>;
+       vmmc-supply = <&vcc_3v3>;
+       vqmmc-supply = <&vddio_boot>;
+};
+
+&uart_AO {
+       status = "okay";
+       pinctrl-0 = <&uart_ao_a_pins>;
+       pinctrl-names = "default";
+};
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-khadas-vim.dts
new file mode 100644 (file)
index 0000000..3c8b0b5
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2017 Martin Blumenstingl <martin.blumenstingl@googlemail.com>.
+ *
+ * SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/input/input.h>
+
+#include "meson-gxl-s905x-p212.dtsi"
+
+/ {
+       compatible = "khadas,vim", "amlogic,s905x", "amlogic,meson-gxl";
+       model = "Khadas VIM";
+
+       adc-keys {
+               compatible = "adc-keys";
+               io-channels = <&saradc 0>;
+               io-channel-names = "buttons";
+               keyup-threshold-microvolt = <1710000>;
+
+               button-function {
+                       label = "Function";
+                       linux,code = <KEY_FN>;
+                       press-threshold-microvolt = <10000>;
+               };
+       };
+
+       aliases {
+               serial2 = &uart_AO_B;
+       };
+
+       gpio-keys-polled {
+               compatible = "gpio-keys-polled";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               poll-interval = <100>;
+
+               button@0 {
+                       label = "power";
+                       linux,code = <KEY_POWER>;
+                       gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_LOW>;
+               };
+       };
+
+       pwmleds {
+               compatible = "pwm-leds";
+
+               power {
+                       label = "vim:red:power";
+                       pwms = <&pwm_AO_ab 1 7812500 0>;
+                       max-brightness = <255>;
+                       linux,default-trigger = "default-on";
+               };
+       };
+};
+
+&i2c_A {
+       status = "okay";
+       pinctrl-0 = <&i2c_a_pins>;
+       pinctrl-names = "default";
+};
+
+&i2c_B {
+       status = "okay";
+       pinctrl-0 = <&i2c_b_pins>;
+       pinctrl-names = "default";
+
+       rtc: rtc@51 {
+               /* has to be enabled manually when a battery is connected: */
+               status = "disabled";
+               compatible = "haoyu,hym8563";
+               reg = <0x51>;
+               #clock-cells = <0>;
+               clock-frequency = <32768>;
+               clock-output-names = "xin32k";
+       };
+};
+
+&ir {
+       linux,rc-map-name = "rc-geekbox";
+};
+
+&pwm_AO_ab {
+       status = "okay";
+       pinctrl-0 = <&pwm_ao_a_3_pins>, <&pwm_ao_b_pins>;
+       pinctrl-names = "default";
+       clocks = <&clkc CLKID_FCLK_DIV4>;
+       clock-names = "clkin0";
+};
+
+&pwm_ef {
+       pinctrl-0 = <&pwm_e_pins>, <&pwm_f_clk_pins>;
+};
+
+&sd_emmc_a {
+       brcmf: bcrmf@1 {
+               reg = <1>;
+               compatible = "brcm,bcm4329-fmac";
+       };
+};
+
+/* This is brought out on the Linux_RX (18) and Linux_TX (19) pins: */
+&uart_AO {
+       status = "okay";
+};
+
+/* This is brought out on the UART_RX_AO_B (15) and UART_TX_AO_B (16) pins: */
+&uart_AO_B {
+       status = "okay";
+       pinctrl-0 = <&uart_ao_b_pins>;
+       pinctrl-names = "default";
+};
index cea4a3eded9b805983e0af414cfd6d901ad5a703..8873c058fad232c1bd7c945f8dd9e0e9285c8421 100644 (file)
                        };
                };
        };
+
+       hdmi-connector {
+               compatible = "hdmi-connector";
+               type = "a";
+
+               port {
+                       hdmi_connector_in: endpoint {
+                               remote-endpoint = <&hdmi_tx_tmds_out>;
+                       };
+               };
+       };
 };
 
 &uart_AO {
                remote-endpoint = <&cvbs_connector_in>;
        };
 };
+
+&hdmi_tx {
+       status = "okay";
+       pinctrl-0 = <&hdmi_hpd_pins>, <&hdmi_i2c_pins>;
+       pinctrl-names = "default";
+};
+
+&hdmi_tx_tmds_port {
+       hdmi_tx_tmds_out: endpoint {
+               remote-endpoint = <&hdmi_connector_in>;
+       };
+};
index 9639f012b02bd23dadd8c7bc92c378a0c33bac1a..db31e093f40e07eaf2a0d8c253dffd6d38706c46 100644 (file)
 
 /dts-v1/;
 
-#include "meson-gxl-s905x.dtsi"
+#include "meson-gxl-s905x-p212.dtsi"
 
 / {
        compatible = "amlogic,p212", "amlogic,s905x", "amlogic,meson-gxl";
        model = "Amlogic Meson GXL (S905X) P212 Development Board";
 
-       aliases {
-               serial0 = &uart_AO;
-       };
+       cvbs-connector {
+               compatible = "composite-video-connector";
 
-       chosen {
-               stdout-path = "serial0:115200n8";
+               port {
+                       cvbs_connector_in: endpoint {
+                               remote-endpoint = <&cvbs_vdac_out>;
+                       };
+               };
        };
+};
 
-       memory@0 {
-               device_type = "memory";
-               reg = <0x0 0x0 0x0 0x80000000>;
+&cvbs_vdac_port {
+       cvbs_vdac_out: endpoint {
+               remote-endpoint = <&cvbs_connector_in>;
        };
 };
 
diff --git a/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi b/arch/arm64/boot/dts/amlogic/meson-gxl-s905x-p212.dtsi
new file mode 100644 (file)
index 0000000..f3eea8e
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ * Copyright (c) 2016 Martin Blumenstingl <martin.blumenstingl@googlemail.com>.
+ * Based on meson-gx-p23x-q20x.dtsi:
+ * - Copyright (c) 2016 Endless Computers, Inc.
+ *   Author: Carlo Caione <carlo@endlessm.com>
+ * - Copyright (c) 2016 BayLibre, SAS.
+ *   Author: Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+ */
+
+/* Common DTSI for devices which are based on the P212 reference board. */
+
+#include "meson-gxl-s905x.dtsi"
+
+/ {
+       aliases {
+               serial0 = &uart_AO;
+               serial1 = &uart_A;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+
+       memory@0 {
+               device_type = "memory";
+               reg = <0x0 0x0 0x0 0x80000000>;
+       };
+
+       vddio_boot: regulator-vddio_boot {
+               compatible = "regulator-fixed";
+               regulator-name = "VDDIO_BOOT";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+       };
+
+       vddao_3v3: regulator-vddao_3v3 {
+               compatible = "regulator-fixed";
+               regulator-name = "VDDAO_3V3";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+       };
+
+       vddio_ao18: regulator-vddio_ao18 {
+               compatible = "regulator-fixed";
+               regulator-name = "VDDIO_AO18";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+       };
+
+       vcc_3v3: regulator-vcc_3v3 {
+               compatible = "regulator-fixed";
+               regulator-name = "VCC_3V3";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+       };
+
+       emmc_pwrseq: emmc-pwrseq {
+               compatible = "mmc-pwrseq-emmc";
+               reset-gpios = <&gpio BOOT_9 GPIO_ACTIVE_LOW>;
+       };
+
+       wifi32k: wifi32k {
+               compatible = "pwm-clock";
+               #clock-cells = <0>;
+               clock-frequency = <32768>;
+               pwms = <&pwm_ef 0 30518 0>; /* PWM_E at 32.768KHz */
+       };
+
+       sdio_pwrseq: sdio-pwrseq {
+               compatible = "mmc-pwrseq-simple";
+               reset-gpios = <&gpio GPIOX_6 GPIO_ACTIVE_LOW>;
+               clocks = <&wifi32k>;
+               clock-names = "ext_clock";
+       };
+};
+
+&ethmac {
+       status = "okay";
+};
+
+&ir {
+       status = "okay";
+       pinctrl-0 = <&remote_input_ao_pins>;
+       pinctrl-names = "default";
+};
+
+&saradc {
+       status = "okay";
+       vref-supply = <&vddio_ao18>;
+};
+
+/* Wireless SDIO Module */
+&sd_emmc_a {
+       status = "okay";
+       pinctrl-0 = <&sdio_pins>;
+       pinctrl-names = "default";
+       #address-cells = <1>;
+       #size-cells = <0>;
+
+       bus-width = <4>;
+       cap-sd-highspeed;
+       max-frequency = <100000000>;
+
+       non-removable;
+       disable-wp;
+
+       mmc-pwrseq = <&sdio_pwrseq>;
+
+       vmmc-supply = <&vddao_3v3>;
+       vqmmc-supply = <&vddio_boot>;
+};
+
+/* SD card */
+&sd_emmc_b {
+       status = "okay";
+       pinctrl-0 = <&sdcard_pins>;
+       pinctrl-names = "default";
+
+       bus-width = <4>;
+       cap-sd-highspeed;
+       max-frequency = <100000000>;
+       disable-wp;
+
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
+       cd-inverted;
+
+       vmmc-supply = <&vddao_3v3>;
+       vqmmc-supply = <&vddio_boot>;
+};
+
+/* eMMC */
+&sd_emmc_c {
+       status = "okay";
+       pinctrl-0 = <&emmc_pins>;
+       pinctrl-names = "default";
+
+       bus-width = <8>;
+       cap-sd-highspeed;
+       cap-mmc-highspeed;
+       max-frequency = <200000000>;
+       non-removable;
+       disable-wp;
+       mmc-ddr-1_8v;
+       mmc-hs200-1_8v;
+
+       mmc-pwrseq = <&emmc_pwrseq>;
+       vmmc-supply = <&vcc_3v3>;
+       vqmmc-supply = <&vddio_boot>;
+};
+
+&pwm_ef {
+       status = "okay";
+       pinctrl-0 = <&pwm_e_pins>;
+       pinctrl-names = "default";
+       clocks = <&clkc CLKID_FCLK_DIV4>;
+       clock-names = "clkin0";
+};
+
+/* This is connected to the Bluetooth module: */
+&uart_A {
+       status = "okay";
+       pinctrl-0 = <&uart_a_pins>, <&uart_a_cts_rts_pins>;
+       pinctrl-names = "default";
+       uart-has-rtscts;
+};
+
+&uart_AO {
+       status = "okay";
+       pinctrl-0 = <&uart_ao_a_pins>;
+       pinctrl-names = "default";
+};
index 08237ee1e36235459d31973a12bcd8bb5d173887..0f78d836edaf5d4977739fe61d176fc9bd58ffab 100644 (file)
@@ -42,6 +42,7 @@
  */
 
 #include "meson-gxl.dtsi"
+#include "meson-gxl-mali.dtsi"
 
 / {
        compatible = "amlogic,s905x", "amlogic,meson-gxl";
index fe11b5fc61f78e02ae8972bed013969de854e840..d8e096dff10a4906e3125b6064e8ed8d301c68be 100644 (file)
@@ -44,6 +44,7 @@
 #include "meson-gx.dtsi"
 #include <dt-bindings/clock/gxbb-clkc.h>
 #include <dt-bindings/gpio/meson-gxl-gpio.h>
+#include <dt-bindings/reset/amlogic,meson-gxbb-reset.h>
 
 / {
        compatible = "amlogic,meson-gxl";
@@ -79,6 +80,7 @@
                        reg-names = "mux", "pull", "gpio";
                        gpio-controller;
                        #gpio-cells = <2>;
+                       gpio-ranges = <&pinctrl_aobus 0 0 14>;
                };
 
                uart_ao_a_pins: uart_ao_a {
                        };
                };
 
+               uart_ao_b_0_1_pins: uart_ao_b_0_1 {
+                       mux {
+                               groups = "uart_tx_ao_b_0", "uart_rx_ao_b_1";
+                               function = "uart_ao_b";
+                       };
+               };
+
                uart_ao_b_cts_rts_pins: uart_ao_b_cts_rts {
                        mux {
                                groups = "uart_cts_ao_b",
                        };
                };
 
+               i2c_ao_pins: i2c_ao {
+                       mux {
+                               groups = "i2c_sck_ao",
+                                      "i2c_sda_ao";
+                               function = "i2c_ao";
+                       };
+               };
+
+               pwm_ao_a_3_pins: pwm_ao_a_3 {
+                       mux {
+                               groups = "pwm_ao_a_3";
+                               function = "pwm_ao_a";
+                       };
+               };
+
+               pwm_ao_a_8_pins: pwm_ao_a_8 {
+                       mux {
+                               groups = "pwm_ao_a_8";
+                               function = "pwm_ao_a";
+                       };
+               };
+
                pwm_ao_b_pins: pwm_ao_b {
                        mux {
                                groups = "pwm_ao_b";
                                function = "pwm_ao_b";
                        };
                };
+
+               pwm_ao_b_6_pins: pwm_ao_b_6 {
+                       mux {
+                               groups = "pwm_ao_b_6";
+                               function = "pwm_ao_b";
+                       };
+               };
+
+               i2s_out_ch23_ao_pins: i2s_out_ch23_ao {
+                       mux {
+                               groups = "i2s_out_ch23_ao";
+                               function = "i2s_out_ao";
+                       };
+               };
+
+               i2s_out_ch45_ao_pins: i2s_out_ch45_ao {
+                       mux {
+                               groups = "i2s_out_ch45_ao";
+                               function = "i2s_out_ao";
+                       };
+               };
+
+               spdif_out_ao_6_pins: spdif_out_ao_6 {
+                       mux {
+                               groups = "spdif_out_ao_6";
+                               function = "spdif_out_ao";
+                       };
+               };
+
+               spdif_out_ao_9_pins: spdif_out_ao_9 {
+                       mux {
+                               groups = "spdif_out_ao_9";
+                               function = "spdif_out_ao";
+                       };
+               };
        };
 };
 
                        reg-names = "mux", "pull", "pull-enable", "gpio";
                        gpio-controller;
                        #gpio-cells = <2>;
+                       gpio-ranges = <&pinctrl_periphs 0 14 101>;
                };
 
                emmc_pins: emmc {
                        };
                };
 
+               nor_pins: nor {
+                       mux {
+                               groups = "nor_d",
+                                      "nor_q",
+                                      "nor_c",
+                                      "nor_cs";
+                               function = "nor";
+                       };
+               };
+
                sdcard_pins: sdcard {
                        mux {
                                groups = "sdcard_d0",
                        };
                };
 
+               pwm_a_pins: pwm_a {
+                       mux {
+                               groups = "pwm_a";
+                               function = "pwm_a";
+                       };
+               };
+
+               pwm_b_pins: pwm_b {
+                       mux {
+                               groups = "pwm_b";
+                               function = "pwm_b";
+                       };
+               };
+
+               pwm_c_pins: pwm_c {
+                       mux {
+                               groups = "pwm_c";
+                               function = "pwm_c";
+                       };
+               };
+
+               pwm_d_pins: pwm_d {
+                       mux {
+                               groups = "pwm_d";
+                               function = "pwm_d";
+                       };
+               };
+
                pwm_e_pins: pwm_e {
                        mux {
                                groups = "pwm_e";
                        };
                };
 
+               pwm_f_clk_pins: pwm_f_clk {
+                       mux {
+                               groups = "pwm_f_clk";
+                               function = "pwm_f";
+                       };
+               };
+
+               pwm_f_x_pins: pwm_f_x {
+                       mux {
+                               groups = "pwm_f_x";
+                               function = "pwm_f";
+                       };
+               };
+
                hdmi_hpd_pins: hdmi_hpd {
                        mux {
                                groups = "hdmi_hpd";
                                function = "hdmi_i2c";
                        };
                };
+
+               i2s_am_clk_pins: i2s_am_clk {
+                       mux {
+                               groups = "i2s_am_clk";
+                               function = "i2s_out";
+                       };
+               };
+
+               i2s_out_ao_clk_pins: i2s_out_ao_clk {
+                       mux {
+                               groups = "i2s_out_ao_clk";
+                               function = "i2s_out";
+                       };
+               };
+
+               i2s_out_lr_clk_pins: i2s_out_lr_clk {
+                       mux {
+                               groups = "i2s_out_lr_clk";
+                               function = "i2s_out";
+                       };
+               };
+
+               i2s_out_ch01_pins: i2s_out_ch01 {
+                       mux {
+                               groups = "i2s_out_ch01";
+                               function = "i2s_out";
+                       };
+               };
+               i2sout_ch23_z_pins: i2sout_ch23_z {
+                       mux {
+                               groups = "i2sout_ch23_z";
+                               function = "i2s_out";
+                       };
+               };
+
+               i2sout_ch45_z_pins: i2sout_ch45_z {
+                       mux {
+                               groups = "i2sout_ch45_z";
+                               function = "i2s_out";
+                       };
+               };
+
+               i2sout_ch67_z_pins: i2sout_ch67_z {
+                       mux {
+                               groups = "i2sout_ch67_z";
+                               function = "i2s_out";
+                       };
+               };
+
+               spdif_out_h_pins: spdif_out_ao_h {
+                       mux {
+                               groups = "spdif_out_h";
+                               function = "spdif_out";
+                       };
+               };
        };
 
        eth-phy-mux {
        clocks = <&clkc CLKID_I2C>;
 };
 
+&i2c_AO {
+       clocks = <&clkc CLKID_AO_I2C>;
+};
+
 &i2c_B {
        clocks = <&clkc CLKID_I2C>;
 };
        clock-names = "core", "clkin0", "clkin1";
 };
 
+&spifc {
+       clocks = <&clkc CLKID_SPI>;
+};
+
 &vpu {
        compatible = "amlogic,meson-gxl-vpu", "amlogic,meson-gx-vpu";
 };
+
+&hdmi_tx {
+       compatible = "amlogic,meson-gxl-dw-hdmi", "amlogic,meson-gx-dw-hdmi";
+       resets = <&reset RESET_HDMITX_CAPB3>,
+                <&reset RESET_HDMI_SYSTEM_RESET>,
+                <&reset RESET_HDMI_TX>;
+       reset-names = "hdmitx_apb", "hdmitx", "hdmitx_phy";
+       clocks = <&clkc CLKID_HDMI_PCLK>,
+                <&clkc CLKID_CLK81>,
+                <&clkc CLKID_GCLK_VENCI_INT0>;
+       clock-names = "isfr", "iahb", "venci";
+};
index 5a337d339df1d58b984ab575ba88b07a03a067c2..11b0bf46a95c4df067741079255ff7f5b26a1b4d 100644 (file)
                        };
                };
        };
+
+       hdmi-connector {
+               compatible = "hdmi-connector";
+               type = "a";
+
+               port {
+                       hdmi_connector_in: endpoint {
+                               remote-endpoint = <&hdmi_tx_tmds_out>;
+                       };
+               };
+       };
 };
 
 /* This UART is brought out to the DB9 connector */
        /* Select external PHY by default */
        phy-handle = <&external_phy>;
 
+       amlogic,tx-delay-ns = <2>;
+
        snps,reset-gpio = <&gpio GPIOZ_14 0>;
        snps,reset-delays-us = <0 10000 1000000>;
        snps,reset-active-low;
                remote-endpoint = <&cvbs_connector_in>;
        };
 };
+
+&hdmi_tx {
+       status = "okay";
+       pinctrl-0 = <&hdmi_hpd_pins>, <&hdmi_i2c_pins>;
+       pinctrl-names = "default";
+};
+
+&hdmi_tx_tmds_port {
+       hdmi_tx_tmds_out: endpoint {
+               remote-endpoint = <&hdmi_connector_in>;
+       };
+};
index 5dbc660883553a1ddfb80b6cb951f08f3f895a1b..b65776b019118d21851b6fa59202a3b80aba9b6e 100644 (file)
 
 /dts-v1/;
 
+#include <dt-bindings/input/input.h>
+
 #include "meson-gxm.dtsi"
 #include "meson-gx-p23x-q20x.dtsi"
 
 / {
        compatible = "amlogic,q200", "amlogic,s912", "amlogic,meson-gxm";
        model = "Amlogic Meson GXM (S912) Q200 Development Board";
+
+       adc-keys {
+               compatible = "adc-keys";
+               io-channels = <&saradc 0>;
+               io-channel-names = "buttons";
+               keyup-threshold-microvolt = <1710000>;
+
+               button-function {
+                       label = "Update";
+                       linux,code = <KEY_VENDOR>;
+                       press-threshold-microvolt = <10000>;
+               };
+       };
+
+       gpio-keys-polled {
+               compatible = "gpio-keys-polled";
+               #address-cells = <1>;
+               #size-cells = <0>;
+               poll-interval = <100>;
+
+               button@0 {
+                       label = "power";
+                       linux,code = <KEY_POWER>;
+                       gpios = <&gpio_ao GPIOAO_2 GPIO_ACTIVE_LOW>;
+               };
+       };
+
+       vddio_ao18: regulator-vddio_ao18 {
+               compatible = "regulator-fixed";
+               regulator-name = "VDDIO_AO18";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+       };
 };
 
 /* Q200 has exclusive choice between internal or external PHY */
@@ -59,6 +94,8 @@
        /* Select external PHY by default */
        phy-handle = <&external_phy>;
 
+       amlogic,tx-delay-ns = <2>;
+
        /* External PHY reset is shared with internal PHY Led signals */
        snps,reset-gpio = <&gpio GPIOZ_14 0>;
        snps,reset-delays-us = <0 10000 1000000>;
                max-speed = <1000>;
        };
 };
+
+&saradc {
+       status = "okay";
+       vref-supply = <&vddio_ao18>;
+};
index ddea7305c644afdb7d1358395ea8f58ab7e26321..fe451cce93e783ce12b857117ab6c3eaa84a9108 100644 (file)
        compatible = "amlogic,meson-gxm-vpu", "amlogic,meson-gx-vpu";
 };
 
+&hdmi_tx {
+       compatible = "amlogic,meson-gxm-dw-hdmi", "amlogic,meson-gx-dw-hdmi";
+};
index df539e865b903cc0ecc9870573bf5b57d5198b25..bfe7d683a42e1b27b6e90997f9ebf18abb79afce 100644 (file)
                };
        };
 
-       pcie_ctlr: pcie-controller@40000000 {
+       pcie_ctlr: pcie@40000000 {
                compatible = "arm,juno-r1-pcie", "plda,xpressrich3-axi", "pci-host-ecam-generic";
                device_type = "pci";
                reg = <0 0x40000000 0 0x10000000>;      /* ECAM config space */
                      <0x00000008 0x80000000 0x1 0x80000000>;
        };
 
-       smb@08000000 {
+       smb@8000000 {
                compatible = "simple-bus";
                #address-cells = <2>;
                #size-cells = <1>;
index 098601657f82394846f02031b4c6e95395624d24..2ac43221ddb680acafd1507a866da58514a53370 100644 (file)
                                #size-cells = <1>;
                                ranges = <0 3 0 0x200000>;
 
-                               v2m_sysctl: sysctl@020000 {
+                               v2m_sysctl: sysctl@20000 {
                                        compatible = "arm,sp810", "arm,primecell";
                                        reg = <0x020000 0x1000>;
                                        clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&mb_clk24mhz>;
                                        assigned-clock-parents = <&v2m_refclk1mhz>, <&v2m_refclk1mhz>, <&v2m_refclk1mhz>, <&v2m_refclk1mhz>;
                                };
 
-                               apbregs@010000 {
+                               apbregs@10000 {
                                        compatible = "syscon", "simple-mfd";
                                        reg = <0x010000 0x1000>;
 
                                        };
                                };
 
-                               mmci@050000 {
+                               mmci@50000 {
                                        compatible = "arm,pl180", "arm,primecell";
                                        reg = <0x050000 0x1000>;
                                        interrupts = <5>;
                                        clock-names = "mclk", "apb_pclk";
                                };
 
-                               kmi@060000 {
+                               kmi@60000 {
                                        compatible = "arm,pl050", "arm,primecell";
                                        reg = <0x060000 0x1000>;
                                        interrupts = <8>;
                                        clock-names = "KMIREFCLK", "apb_pclk";
                                };
 
-                               kmi@070000 {
+                               kmi@70000 {
                                        compatible = "arm,pl050", "arm,primecell";
                                        reg = <0x070000 0x1000>;
                                        interrupts = <8>;
                                        clock-names = "KMIREFCLK", "apb_pclk";
                                };
 
-                               wdt@0f0000 {
+                               wdt@f0000 {
                                        compatible = "arm,sp805", "arm,primecell";
                                        reg = <0x0f0000 0x10000>;
                                        interrupts = <7>;
index 0033c59a64b585ac20321f90abcbcccfef88a451..0e8943ab94d77497ad28f6699e23d7bc4dec7958 100644 (file)
                        reg = <0x0 0x0>;
                        device_type = "cpu";
                        enable-method = "psci";
+                       i-cache-size = <0xc000>;
+                       i-cache-line-size = <64>;
+                       i-cache-sets = <256>;
+                       d-cache-size = <0x8000>;
+                       d-cache-line-size = <64>;
+                       d-cache-sets = <256>;
                        next-level-cache = <&A57_L2>;
                        clocks = <&scpi_dvfs 0>;
                        cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
                        reg = <0x0 0x1>;
                        device_type = "cpu";
                        enable-method = "psci";
+                       i-cache-size = <0xc000>;
+                       i-cache-line-size = <64>;
+                       i-cache-sets = <256>;
+                       d-cache-size = <0x8000>;
+                       d-cache-line-size = <64>;
+                       d-cache-sets = <256>;
                        next-level-cache = <&A57_L2>;
                        clocks = <&scpi_dvfs 0>;
                        cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
                        reg = <0x0 0x100>;
                        device_type = "cpu";
                        enable-method = "psci";
+                       i-cache-size = <0x8000>;
+                       i-cache-line-size = <64>;
+                       i-cache-sets = <256>;
+                       d-cache-size = <0x8000>;
+                       d-cache-line-size = <64>;
+                       d-cache-sets = <128>;
                        next-level-cache = <&A53_L2>;
                        clocks = <&scpi_dvfs 1>;
                        cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
                        reg = <0x0 0x101>;
                        device_type = "cpu";
                        enable-method = "psci";
+                       i-cache-size = <0x8000>;
+                       i-cache-line-size = <64>;
+                       i-cache-sets = <256>;
+                       d-cache-size = <0x8000>;
+                       d-cache-line-size = <64>;
+                       d-cache-sets = <128>;
                        next-level-cache = <&A53_L2>;
                        clocks = <&scpi_dvfs 1>;
                        cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
                        reg = <0x0 0x102>;
                        device_type = "cpu";
                        enable-method = "psci";
+                       i-cache-size = <0x8000>;
+                       i-cache-line-size = <64>;
+                       i-cache-sets = <256>;
+                       d-cache-size = <0x8000>;
+                       d-cache-line-size = <64>;
+                       d-cache-sets = <128>;
                        next-level-cache = <&A53_L2>;
                        clocks = <&scpi_dvfs 1>;
                        cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
                        reg = <0x0 0x103>;
                        device_type = "cpu";
                        enable-method = "psci";
+                       i-cache-size = <0x8000>;
+                       i-cache-line-size = <64>;
+                       i-cache-sets = <256>;
+                       d-cache-size = <0x8000>;
+                       d-cache-line-size = <64>;
+                       d-cache-sets = <128>;
                        next-level-cache = <&A53_L2>;
                        clocks = <&scpi_dvfs 1>;
                        cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
 
                A57_L2: l2-cache0 {
                        compatible = "cache";
+                       cache-size = <0x200000>;
+                       cache-line-size = <64>;
+                       cache-sets = <2048>;
                };
 
                A53_L2: l2-cache1 {
                        compatible = "cache";
+                       cache-size = <0x100000>;
+                       cache-line-size = <64>;
+                       cache-sets = <1024>;
                };
        };
 
index 218d0e4736a86784e5d159ef6d1d4fd4e07f89fa..405e2fba025beeec73c8ba020fa2329f2438f533 100644 (file)
                        reg = <0x0 0x0>;
                        device_type = "cpu";
                        enable-method = "psci";
+                       i-cache-size = <0xc000>;
+                       i-cache-line-size = <64>;
+                       i-cache-sets = <256>;
+                       d-cache-size = <0x8000>;
+                       d-cache-line-size = <64>;
+                       d-cache-sets = <256>;
                        next-level-cache = <&A72_L2>;
                        clocks = <&scpi_dvfs 0>;
                        cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
                        reg = <0x0 0x1>;
                        device_type = "cpu";
                        enable-method = "psci";
+                       i-cache-size = <0xc000>;
+                       i-cache-line-size = <64>;
+                       i-cache-sets = <256>;
+                       d-cache-size = <0x8000>;
+                       d-cache-line-size = <64>;
+                       d-cache-sets = <256>;
                        next-level-cache = <&A72_L2>;
                        clocks = <&scpi_dvfs 0>;
                        cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
                        reg = <0x0 0x100>;
                        device_type = "cpu";
                        enable-method = "psci";
+                       i-cache-size = <0x8000>;
+                       i-cache-line-size = <64>;
+                       i-cache-sets = <256>;
+                       d-cache-size = <0x8000>;
+                       d-cache-line-size = <64>;
+                       d-cache-sets = <128>;
                        next-level-cache = <&A53_L2>;
                        clocks = <&scpi_dvfs 1>;
                        cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
                        reg = <0x0 0x101>;
                        device_type = "cpu";
                        enable-method = "psci";
+                       i-cache-size = <0x8000>;
+                       i-cache-line-size = <64>;
+                       i-cache-sets = <256>;
+                       d-cache-size = <0x8000>;
+                       d-cache-line-size = <64>;
+                       d-cache-sets = <128>;
                        next-level-cache = <&A53_L2>;
                        clocks = <&scpi_dvfs 1>;
                        cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
                        reg = <0x0 0x102>;
                        device_type = "cpu";
                        enable-method = "psci";
+                       i-cache-size = <0x8000>;
+                       i-cache-line-size = <64>;
+                       i-cache-sets = <256>;
+                       d-cache-size = <0x8000>;
+                       d-cache-line-size = <64>;
+                       d-cache-sets = <128>;
                        next-level-cache = <&A53_L2>;
                        clocks = <&scpi_dvfs 1>;
                        cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
                        reg = <0x0 0x103>;
                        device_type = "cpu";
                        enable-method = "psci";
+                       i-cache-size = <0x8000>;
+                       i-cache-line-size = <64>;
+                       i-cache-sets = <256>;
+                       d-cache-size = <0x8000>;
+                       d-cache-line-size = <64>;
+                       d-cache-sets = <128>;
                        next-level-cache = <&A53_L2>;
                        clocks = <&scpi_dvfs 1>;
                        cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
 
                A72_L2: l2-cache0 {
                        compatible = "cache";
+                       cache-size = <0x200000>;
+                       cache-line-size = <64>;
+                       cache-sets = <2048>;
                };
 
                A53_L2: l2-cache1 {
                        compatible = "cache";
+                       cache-size = <0x100000>;
+                       cache-line-size = <64>;
+                       cache-sets = <1024>;
                };
        };
 
index bb2820ef3d5b04a40091fc0777d9a5a3bee5bf28..0220494c9b80222d742fb1285e52d1a01a7066ba 100644 (file)
                        reg = <0x0 0x0>;
                        device_type = "cpu";
                        enable-method = "psci";
+                       i-cache-size = <0xc000>;
+                       i-cache-line-size = <64>;
+                       i-cache-sets = <256>;
+                       d-cache-size = <0x8000>;
+                       d-cache-line-size = <64>;
+                       d-cache-sets = <256>;
                        next-level-cache = <&A57_L2>;
                        clocks = <&scpi_dvfs 0>;
                        cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
                        reg = <0x0 0x1>;
                        device_type = "cpu";
                        enable-method = "psci";
+                       i-cache-size = <0xc000>;
+                       i-cache-line-size = <64>;
+                       i-cache-sets = <256>;
+                       d-cache-size = <0x8000>;
+                       d-cache-line-size = <64>;
+                       d-cache-sets = <256>;
                        next-level-cache = <&A57_L2>;
                        clocks = <&scpi_dvfs 0>;
                        cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
                        reg = <0x0 0x100>;
                        device_type = "cpu";
                        enable-method = "psci";
+                       i-cache-size = <0x8000>;
+                       i-cache-line-size = <64>;
+                       i-cache-sets = <256>;
+                       d-cache-size = <0x8000>;
+                       d-cache-line-size = <64>;
+                       d-cache-sets = <128>;
                        next-level-cache = <&A53_L2>;
                        clocks = <&scpi_dvfs 1>;
                        cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
                        reg = <0x0 0x101>;
                        device_type = "cpu";
                        enable-method = "psci";
+                       i-cache-size = <0x8000>;
+                       i-cache-line-size = <64>;
+                       i-cache-sets = <256>;
+                       d-cache-size = <0x8000>;
+                       d-cache-line-size = <64>;
+                       d-cache-sets = <128>;
                        next-level-cache = <&A53_L2>;
                        clocks = <&scpi_dvfs 1>;
                        cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
                        reg = <0x0 0x102>;
                        device_type = "cpu";
                        enable-method = "psci";
+                       i-cache-size = <0x8000>;
+                       i-cache-line-size = <64>;
+                       i-cache-sets = <256>;
+                       d-cache-size = <0x8000>;
+                       d-cache-line-size = <64>;
+                       d-cache-sets = <128>;
                        next-level-cache = <&A53_L2>;
                        clocks = <&scpi_dvfs 1>;
                        cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
                        reg = <0x0 0x103>;
                        device_type = "cpu";
                        enable-method = "psci";
+                       i-cache-size = <0x8000>;
+                       i-cache-line-size = <64>;
+                       i-cache-sets = <256>;
+                       d-cache-size = <0x8000>;
+                       d-cache-line-size = <64>;
+                       d-cache-sets = <128>;
                        next-level-cache = <&A53_L2>;
                        clocks = <&scpi_dvfs 1>;
                        cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>;
 
                A57_L2: l2-cache0 {
                        compatible = "cache";
+                       cache-size = <0x200000>;
+                       cache-line-size = <64>;
+                       cache-sets = <2048>;
                };
 
                A53_L2: l2-cache1 {
                        compatible = "cache";
+                       cache-size = <0x100000>;
+                       cache-line-size = <64>;
+                       cache-sets = <1024>;
                };
        };
 
index f1caece9d3a7ae7af8f95f9b9675e935a59ace6b..bfa8f8e4c5af0643a9cff94917ccf932a5ee98cb 100644 (file)
@@ -1,6 +1,5 @@
 dtb-$(CONFIG_ARCH_BCM2835) += bcm2837-rpi-3-b.dtb
 dtb-$(CONFIG_ARCH_BCM_IPROC) += ns2-svk.dtb ns2-xmc.dtb
-dtb-$(CONFIG_ARCH_VULCAN) += vulcan-eval.dtb
 
 always         := $(dtb-y)
 subdir-y       := $(dts-dirs)
index 5ae08161649ed4fcd3ef6ca3656aff92a51db928..ec19fbf928a142db6d9e853fee7e98f1e31d66b2 100644 (file)
 };
 
 &enet {
-       status = "ok";
+       status = "okay";
 };
 
 &pci_phy0 {
-       status = "ok";
+       status = "okay";
 };
 
 &pci_phy1 {
-       status = "ok";
+       status = "okay";
 };
 
 &pcie0 {
-       status = "ok";
+       status = "okay";
 };
 
 &pcie4 {
-       status = "ok";
+       status = "okay";
 };
 
 &pcie8 {
-       status = "ok";
+       status = "okay";
 };
 
 &i2c0 {
-       status = "ok";
+       status = "okay";
 };
 
 &i2c1 {
-       status = "ok";
+       status = "okay";
 };
 
 &uart0 {
-       status = "ok";
+       status = "okay";
 };
 
 &uart1 {
-       status = "ok";
+       status = "okay";
 };
 
 &uart2 {
-       status = "ok";
+       status = "okay";
 };
 
 &uart3 {
-       status = "ok";
+       status = "okay";
 };
 
 &ssp0 {
-       status = "ok";
+       status = "okay";
 
        slic@0 {
                compatible = "silabs,si3226x";
 };
 
 &ssp1 {
-       status = "ok";
+       status = "okay";
 
        at25@0 {
                compatible = "atmel,at25";
 };
 
 &sata_phy0 {
-       status = "ok";
+       status = "okay";
 };
 
 &sata_phy1 {
-       status = "ok";
+       status = "okay";
 };
 
 &sata {
-       status = "ok";
+       status = "okay";
 };
 
 &sdio0 {
-       status = "ok";
+       status = "okay";
 };
 
 &sdio1 {
-       status = "ok";
+       status = "okay";
 };
 
 &nand {
index 99a2723cccd28b3b4f46ed62a588af97f5a085c3..ab4ae1a32fabd48527694b384f6622ccd125107d 100644 (file)
 };
 
 &enet {
-       status = "ok";
+       status = "okay";
 };
 
 &i2c0 {
-       status = "ok";
+       status = "okay";
 };
 
 &i2c1 {
-       status = "ok";
+       status = "okay";
 };
 
 &mdio_mux_iproc {
 };
 
 &pci_phy0 {
-       status = "ok";
+       status = "okay";
 };
 
 &pcie0 {
-       status = "ok";
+       status = "okay";
 };
 
 &pcie8 {
-       status = "ok";
+       status = "okay";
 };
 
 &sata_phy0 {
-       status = "ok";
+       status = "okay";
 };
 
 &sata_phy1 {
-       status = "ok";
+       status = "okay";
 };
 
 &sata {
-       status = "ok";
+       status = "okay";
 };
 
 &qspi {
 };
 
 &uart3 {
-       status = "ok";
+       status = "okay";
 };
index bcb03fc3266552e22ce855ac81677584d0937e63..35a309ae3ed87767c9b7525f3c03a1ae6e9d9206 100644 (file)
                        brcm,use-bcm-hdr;
                };
 
+               crypto0: crypto@612d0000 {
+                       compatible = "brcm,spum-crypto";
+                       reg = <0x612d0000 0x900>;
+                       mboxes = <&pdc0 0>;
+               };
+
                pdc1: iproc-pdc1@612e0000 {
                        compatible = "brcm,iproc-pdc-mbox";
                        reg = <0x612e0000 0x445>;  /* PDC FS1 regs */
                        brcm,use-bcm-hdr;
                };
 
+               crypto1: crypto@612f0000 {
+                       compatible = "brcm,spum-crypto";
+                       reg = <0x612f0000 0x900>;
+                       mboxes = <&pdc1 0>;
+               };
+
                pdc2: iproc-pdc2@61300000 {
                        compatible = "brcm,iproc-pdc-mbox";
                        reg = <0x61300000 0x445>;  /* PDC FS2 regs */
                        brcm,use-bcm-hdr;
                };
 
+               crypto2: crypto@61310000 {
+                       compatible = "brcm,spum-crypto";
+                       reg = <0x61310000 0x900>;
+                       mboxes = <&pdc2 0>;
+               };
+
                pdc3: iproc-pdc3@61320000 {
                        compatible = "brcm,iproc-pdc-mbox";
                        reg = <0x61320000 0x445>;  /* PDC FS3 regs */
                        brcm,use-bcm-hdr;
                };
 
+               crypto3: crypto@61330000 {
+                       compatible = "brcm,spum-crypto";
+                       reg = <0x61330000 0x900>;
+                       mboxes = <&pdc3 0>;
+               };
+
                dma0: dma@61360000 {
                        compatible = "arm,pl330", "arm,primecell";
                        reg = <0x61360000 0x1000>;
index e34f89ddabb250a341dae3cd9bf03b91c04a990b..581b2c1c400abe1398e2c1543f09bddcbd1cacef 100644 (file)
@@ -1,4 +1,5 @@
 dtb-$(CONFIG_ARCH_THUNDER) += thunder-88xx.dtb
+dtb-$(CONFIG_ARCH_THUNDER2) += thunder2-99xx.dtb
 
 always         := $(dtb-y)
 subdir-y       := $(dts-dirs)
similarity index 72%
rename from arch/arm64/boot/dts/broadcom/vulcan-eval.dts
rename to arch/arm64/boot/dts/cavium/thunder2-99xx.dts
index 9ee8d3da0e3f17923a94c381b76c65e33666c5e9..6c6fb8692fdeeb59fe8c9bfc661e6fafec7a8e03 100644 (file)
@@ -1,6 +1,7 @@
 /*
- * dts file for Broadcom (BRCM) Vulcan Evaluation Platform
+ * dts file for Cavium ThunderX2 CN99XX Evaluation Platform
  *
+ * Copyright (c) 2017 Cavium Inc.
  * Copyright (c) 2013-2016 Broadcom
  *
  * This program is free software; you can redistribute it and/or
 
 /dts-v1/;
 
-#include "vulcan.dtsi"
+#include "thunder2-99xx.dtsi"
 
 / {
-       model = "Broadcom Vulcan Eval Platform";
-       compatible = "brcm,vulcan-eval", "brcm,vulcan-soc";
+       model = "Cavium ThunderX2 CN99XX";
+       compatible = "cavium,thunderx2-cn9900", "brcm,vulcan-soc";
 
        memory {
                device_type = "memory";
similarity index 88%
rename from arch/arm64/boot/dts/broadcom/vulcan.dtsi
rename to arch/arm64/boot/dts/cavium/thunder2-99xx.dtsi
index 34e11a9db2a0d586123b05cd277f6a8760511f66..4220fbdcb24a7f18c5e3ab66574ba22c8c92c873 100644 (file)
@@ -1,6 +1,7 @@
 /*
- * dtsi file for Broadcom (BRCM) Vulcan processor
+ * dtsi file for Cavium ThunderX2 CN99XX processor
  *
+ * Copyright (c) 2017 Cavium Inc.
  * Copyright (c) 2013-2016 Broadcom
  * Author: Zi Shen Lim <zlim@broadcom.com>
  *
@@ -13,8 +14,8 @@
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 
 / {
-       model = "Broadcom Vulcan";
-       compatible = "brcm,vulcan-soc";
+       model = "Cavium ThunderX2 CN99XX";
+       compatible = "cavium,thunderx2-cn9900", "brcm,vulcan-soc";
        interrupt-parent = <&gic>;
        #address-cells = <2>;
        #size-cells = <2>;
 
                cpu@0 {
                        device_type = "cpu";
-                       compatible = "brcm,vulcan", "arm,armv8";
+                       compatible = "cavium,thunder2", "brcm,vulcan", "arm,armv8";
                        reg = <0x0 0x0>;
                        enable-method = "psci";
                };
 
                cpu@1 {
                        device_type = "cpu";
-                       compatible = "brcm,vulcan", "arm,armv8";
+                       compatible = "cavium,thunder2", "brcm,vulcan", "arm,armv8";
                        reg = <0x0 0x1>;
                        enable-method = "psci";
                };
 
                cpu@2 {
                        device_type = "cpu";
-                       compatible = "brcm,vulcan", "arm,armv8";
+                       compatible = "cavium,thunder2", "brcm,vulcan", "arm,armv8";
                        reg = <0x0 0x2>;
                        enable-method = "psci";
                };
 
                cpu@3 {
                        device_type = "cpu";
-                       compatible = "brcm,vulcan", "arm,armv8";
+                       compatible = "cavium,thunder2", "brcm,vulcan", "arm,armv8";
                        reg = <0x0 0x3>;
                        enable-method = "psci";
                };
index c42dc39c32237f69bfa854964bcc19db192923df..ec11343dc5282f32e4ff9410977f89356d1eed35 100644 (file)
                compatible = "operating-points-v2";
                opp-shared;
 
-               opp@400000000 {
+               opp-400000000 {
                        opp-hz = /bits/ 64 <400000000>;
                        opp-microvolt = <1075000>;
                };
-               opp@267000000 {
+               opp-267000000 {
                        opp-hz = /bits/ 64 <267000000>;
                        opp-microvolt = <1000000>;
                };
-               opp@200000000 {
+               opp-200000000 {
                        opp-hz = /bits/ 64 <200000000>;
                        opp-microvolt = <975000>;
                };
-               opp@160000000 {
+               opp-160000000 {
                        opp-hz = /bits/ 64 <160000000>;
                        opp-microvolt = <962500>;
                };
-               opp@134000000 {
+               opp-134000000 {
                        opp-hz = /bits/ 64 <134000000>;
                        opp-microvolt = <950000>;
                };
-               opp@100000000 {
+               opp-100000000 {
                        opp-hz = /bits/ 64 <100000000>;
                        opp-microvolt = <937500>;
                };
        bus_g2d_266_opp_table: opp_table3 {
                compatible = "operating-points-v2";
 
-               opp@267000000 {
+               opp-267000000 {
                        opp-hz = /bits/ 64 <267000000>;
                };
-               opp@200000000 {
+               opp-200000000 {
                        opp-hz = /bits/ 64 <200000000>;
                };
-               opp@160000000 {
+               opp-160000000 {
                        opp-hz = /bits/ 64 <160000000>;
                };
-               opp@134000000 {
+               opp-134000000 {
                        opp-hz = /bits/ 64 <134000000>;
                };
-               opp@100000000 {
+               opp-100000000 {
                        opp-hz = /bits/ 64 <100000000>;
                };
        };
        bus_gscl_opp_table: opp_table4 {
                compatible = "operating-points-v2";
 
-               opp@333000000 {
+               opp-333000000 {
                        opp-hz = /bits/ 64 <333000000>;
                };
-               opp@222000000 {
+               opp-222000000 {
                        opp-hz = /bits/ 64 <222000000>;
                };
-               opp@166500000 {
+               opp-166500000 {
                        opp-hz = /bits/ 64 <166500000>;
                };
        };
                compatible = "operating-points-v2";
                opp-shared;
 
-               opp@400000000 {
+               opp-400000000 {
                        opp-hz = /bits/ 64 <400000000>;
                };
-               opp@267000000 {
+               opp-267000000 {
                        opp-hz = /bits/ 64 <267000000>;
                };
-               opp@200000000 {
+               opp-200000000 {
                        opp-hz = /bits/ 64 <200000000>;
                };
-               opp@160000000 {
+               opp-160000000 {
                        opp-hz = /bits/ 64 <160000000>;
                };
-               opp@134000000 {
+               opp-134000000 {
                        opp-hz = /bits/ 64 <134000000>;
                };
-               opp@100000000 {
+               opp-100000000 {
                        opp-hz = /bits/ 64 <100000000>;
                };
        };
        bus_noc2_opp_table: opp_table6 {
                compatible = "operating-points-v2";
 
-               opp@400000000 {
+               opp-400000000 {
                        opp-hz = /bits/ 64 <400000000>;
                };
-               opp@200000000 {
+               opp-200000000 {
                        opp-hz = /bits/ 64 <200000000>;
                };
-               opp@134000000 {
+               opp-134000000 {
                        opp-hz = /bits/ 64 <134000000>;
                };
-               opp@100000000 {
+               opp-100000000 {
                        opp-hz = /bits/ 64 <100000000>;
                };
        };
index 098ad557fee3259677340800eef05d10e71e06bd..e2b0da2c0bc771a5d5f3ef721ee45f58ad466554 100644 (file)
                };
        };
 
+       irda_regulator: irda-regulator {
+               compatible = "regulator-fixed";
+               enable-active-high;
+               gpio = <&gpr3 3 GPIO_ACTIVE_HIGH>;
+               regulator-name = "irda_regulator";
+       };
+
        sound {
                compatible = "samsung,tm2-audio";
                audio-codec = <&wm5110>;
        status = "okay";
        vddcore-supply = <&ldo6_reg>;
        vddio-supply = <&ldo7_reg>;
+       samsung,burst-clock-frequency = <512000000>;
+       samsung,esc-clock-frequency = <16000000>;
        samsung,pll-clock-frequency = <24000000>;
        pinctrl-names = "default";
        pinctrl-0 = <&te_irq>;
        };
 };
 
+&hsi2c_5 {
+       status = "okay";
+
+       stmfts: touchscreen@49 {
+               compatible = "st,stmfts";
+               reg = <0x49>;
+               interrupt-parent = <&gpa1>;
+               interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
+               avdd-supply = <&ldo30_reg>;
+               vdd-supply = <&ldo31_reg>;
+       };
+};
+
 &hsi2c_7 {
        status = "okay";
 
                PIN(INPUT, gpa0-7, NONE, FAST_SR1);
 
                PIN(INPUT, gpa1-0, UP, FAST_SR1);
-               PIN(INPUT, gpa1-1, NONE, FAST_SR1);
+               PIN(INPUT, gpa1-1, UP, FAST_SR1);
                PIN(INPUT, gpa1-2, NONE, FAST_SR1);
                PIN(INPUT, gpa1-3, DOWN, FAST_SR1);
                PIN(INPUT, gpa1-4, DOWN, FAST_SR1);
                PIN(INPUT, gpg3-0, DOWN, FAST_SR1);
                PIN(INPUT, gpg3-1, DOWN, FAST_SR1);
                PIN(INPUT, gpg3-5, DOWN, FAST_SR1);
-               PIN(INPUT, gpg3-7, DOWN, FAST_SR1);
        };
 };
 
        };
 };
 
+&spi_3 {
+       status = "okay";
+       no-cs-readback;
+
+       irled@0 {
+               compatible = "ir-spi-led";
+               reg = <0x0>;
+               spi-max-frequency = <5000000>;
+               power-supply = <&irda_regulator>;
+               duty-cycle = <60>;
+               led-active-low;
+
+               controller-data {
+                       samsung,spi-feedback-delay = <0>;
+               };
+       };
+};
+
 &timer {
        clock-frequency = <24000000>;
 };
index dea0a6f5bc18f048b30fa6d543e19623cc18ca4c..3ff95277a8ec92b8981ab5a1cfc65acf17ad5468 100644 (file)
        assigned-clock-rates = <250000000>, <400000000>;
 };
 
+&dsi {
+       panel@0 {
+               compatible = "samsung,s6e3ha2";
+               reg = <0>;
+               vdd3-supply = <&ldo27_reg>;
+               vci-supply = <&ldo28_reg>;
+               reset-gpios = <&gpg0 0 GPIO_ACTIVE_LOW>;
+               enable-gpios = <&gpf1 5 GPIO_ACTIVE_HIGH>;
+               te-gpios = <&gpf1 3 GPIO_ACTIVE_HIGH>;
+       };
+};
+
 &hsi2c_9 {
        status = "okay";
 
@@ -76,3 +88,8 @@
        regulator-min-microvolt = <3000000>;
        regulator-max-microvolt = <3000000>;
 };
+
+&stmfts {
+       touchscreen-size-x = <1439>;
+       touchscreen-size-y = <2559>;
+};
index 7891a31adc17594112a8edf1a9ad4914f3446718..b73e1231a86f5563e725873b2f1d02fc661332d6 100644 (file)
        assigned-clock-rates = <278000000>, <400000000>;
 };
 
+&dsi {
+       panel@0 {
+               compatible = "samsung,s6e3hf2";
+               reg = <0>;
+               vdd3-supply = <&ldo27_reg>;
+               vci-supply = <&ldo28_reg>;
+               reset-gpios = <&gpg0 0 GPIO_ACTIVE_LOW>;
+               enable-gpios = <&gpf1 5 GPIO_ACTIVE_HIGH>;
+       };
+};
+
 &ldo31_reg {
        regulator-name = "TSP_VDD_1.8V_AP";
        regulator-min-microvolt = <1800000>;
        regulator-min-microvolt = <3300000>;
        regulator-max-microvolt = <3300000>;
 };
+
+&stmfts {
+       touchscreen-size-x = <1599>;
+       touchscreen-size-y = <2559>;
+       touch-key-connected;
+       ledvdd-supply = <&ldo33_reg>;
+};
index 16072c1c3ed3eaece9b91049d33a1ffd0ff7156b..727f36abf3d478d1bd2b86fe09fbe535705401ff 100644 (file)
                compatible = "operating-points-v2";
                opp-shared;
 
-               opp@400000000 {
+               opp-400000000 {
                        opp-hz = /bits/ 64 <400000000>;
                        opp-microvolt = <900000>;
                };
-               opp@500000000 {
+               opp-500000000 {
                        opp-hz = /bits/ 64 <500000000>;
                        opp-microvolt = <925000>;
                };
-               opp@600000000 {
+               opp-600000000 {
                        opp-hz = /bits/ 64 <600000000>;
                        opp-microvolt = <950000>;
                };
-               opp@700000000 {
+               opp-700000000 {
                        opp-hz = /bits/ 64 <700000000>;
                        opp-microvolt = <975000>;
                };
-               opp@800000000 {
+               opp-800000000 {
                        opp-hz = /bits/ 64 <800000000>;
                        opp-microvolt = <1000000>;
                };
-               opp@900000000 {
+               opp-900000000 {
                        opp-hz = /bits/ 64 <900000000>;
                        opp-microvolt = <1050000>;
                };
-               opp@1000000000 {
+               opp-1000000000 {
                        opp-hz = /bits/ 64 <1000000000>;
                        opp-microvolt = <1075000>;
                };
-               opp@1100000000 {
+               opp-1100000000 {
                        opp-hz = /bits/ 64 <1100000000>;
                        opp-microvolt = <1112500>;
                };
-               opp@1200000000 {
+               opp-1200000000 {
                        opp-hz = /bits/ 64 <1200000000>;
                        opp-microvolt = <1112500>;
                };
-               opp@1300000000 {
+               opp-1300000000 {
                        opp-hz = /bits/ 64 <1300000000>;
                        opp-microvolt = <1150000>;
                };
                compatible = "operating-points-v2";
                opp-shared;
 
-               opp@500000000 {
+               opp-500000000 {
                        opp-hz = /bits/ 64 <500000000>;
                        opp-microvolt = <900000>;
                };
-               opp@600000000 {
+               opp-600000000 {
                        opp-hz = /bits/ 64 <600000000>;
                        opp-microvolt = <900000>;
                };
-               opp@700000000 {
+               opp-700000000 {
                        opp-hz = /bits/ 64 <700000000>;
                        opp-microvolt = <912500>;
                };
-               opp@800000000 {
+               opp-800000000 {
                        opp-hz = /bits/ 64 <800000000>;
                        opp-microvolt = <912500>;
                };
-               opp@900000000 {
+               opp-900000000 {
                        opp-hz = /bits/ 64 <900000000>;
                        opp-microvolt = <937500>;
                };
-               opp@1000000000 {
+               opp-1000000000 {
                        opp-hz = /bits/ 64 <1000000000>;
                        opp-microvolt = <975000>;
                };
-               opp@1100000000 {
+               opp-1100000000 {
                        opp-hz = /bits/ 64 <1100000000>;
                        opp-microvolt = <1012500>;
                };
-               opp@1200000000 {
+               opp-1200000000 {
                        opp-hz = /bits/ 64 <1200000000>;
                        opp-microvolt = <1037500>;
                };
-               opp@1300000000 {
+               opp-1300000000 {
                        opp-hz = /bits/ 64 <1300000000>;
                        opp-microvolt = <1062500>;
                };
-               opp@1400000000 {
+               opp-1400000000 {
                        opp-hz = /bits/ 64 <1400000000>;
                        opp-microvolt = <1087500>;
                };
-               opp@1500000000 {
+               opp-1500000000 {
                        opp-hz = /bits/ 64 <1500000000>;
                        opp-microvolt = <1125000>;
                };
-               opp@1600000000 {
+               opp-1600000000 {
                        opp-hz = /bits/ 64 <1600000000>;
                        opp-microvolt = <1137500>;
                };
-               opp@1700000000 {
+               opp-1700000000 {
                        opp-hz = /bits/ 64 <1700000000>;
                        opp-microvolt = <1175000>;
                };
-               opp@1800000000 {
+               opp-1800000000 {
                        opp-hz = /bits/ 64 <1800000000>;
                        opp-microvolt = <1212500>;
                };
-               opp@1900000000 {
+               opp-1900000000 {
                        opp-hz = /bits/ 64 <1900000000>;
                        opp-microvolt = <1262500>;
                };
index 39db645b268e1f2119f15c8f8817dff35748dc37..72c4b525726f9ddabbb872b575afbd147f1eeb93 100644 (file)
@@ -5,9 +5,13 @@ dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1043a-qds.dtb
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1043a-rdb.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
+dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls1088a-rdb.dtb
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2080a-qds.dtb
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2080a-rdb.dtb
 dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2080a-simu.dtb
+dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2088a-qds.dtb
+dtb-$(CONFIG_ARCH_LAYERSCAPE) += fsl-ls2088a-rdb.dtb
  
 always         := $(dtb-y)
 subdir-y       := $(dts-dirs)
index a619f6496a4cff44d38feea97fef0d06d269855b..17fae8112e4d96d610ea6623e8f7c29fee9f8f9d 100644 (file)
 &sai2 {
        status = "okay";
 };
+
+&sata {
+       status = "okay";
+};
index 14a67f1709e7c1e28939e598cac98f289b3a040d..e2a93d53d3d8dc77c0b205fc617bed1cb4c1679e 100644 (file)
 &sai2 {
        status = "okay";
 };
+
+&sata {
+       status = "okay";
+};
index 62c5c7123a1599f116b44e08492739d21aae6a4e..ed77f6b0937b278dc2ed881f70682727fa98bf32 100644 (file)
@@ -57,3 +57,7 @@
 &i2c0 {
        status = "okay";
 };
+
+&sata {
+       status = "okay";
+};
index cffebb4b3df11de0b5defefd2bb239d6c4add329..b497ac196ccc1e5ea2c2dd9bff6194e9a751ab15 100644 (file)
@@ -42,7 +42,8 @@
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/thermal/thermal.h>
 
 / {
        compatible = "fsl,ls1012a";
        #address-cells = <2>;
        #size-cells = <2>;
 
+       aliases {
+               crypto = &crypto;
+               rtic_a = &rtic_a;
+               rtic_b = &rtic_b;
+               rtic_c = &rtic_c;
+               rtic_d = &rtic_d;
+               sec_mon = &sec_mon;
+       };
+
        cpus {
                #address-cells = <1>;
                #size-cells = <0>;
                        big-endian;
                };
 
+               crypto: crypto@1700000 {
+                       compatible = "fsl,sec-v5.4", "fsl,sec-v5.0",
+                                    "fsl,sec-v4.0";
+                       fsl,sec-era = <8>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0x0 0x00 0x1700000 0x100000>;
+                       reg = <0x00 0x1700000 0x0 0x100000>;
+                       interrupts = <GIC_SPI 75 IRQ_TYPE_LEVEL_HIGH>;
+
+                       sec_jr0: jr@10000 {
+                               compatible = "fsl,sec-v5.4-job-ring",
+                                            "fsl,sec-v5.0-job-ring",
+                                            "fsl,sec-v4.0-job-ring";
+                               reg        = <0x10000 0x10000>;
+                               interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+                       };
+
+                       sec_jr1: jr@20000 {
+                               compatible = "fsl,sec-v5.4-job-ring",
+                                            "fsl,sec-v5.0-job-ring",
+                                            "fsl,sec-v4.0-job-ring";
+                               reg        = <0x20000 0x10000>;
+                               interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
+                       };
+
+                       sec_jr2: jr@30000 {
+                               compatible = "fsl,sec-v5.4-job-ring",
+                                            "fsl,sec-v5.0-job-ring",
+                                            "fsl,sec-v4.0-job-ring";
+                               reg        = <0x30000 0x10000>;
+                               interrupts = <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+                       };
+
+                       sec_jr3: jr@40000 {
+                               compatible = "fsl,sec-v5.4-job-ring",
+                                            "fsl,sec-v5.0-job-ring",
+                                            "fsl,sec-v4.0-job-ring";
+                               reg        = <0x40000 0x10000>;
+                               interrupts = <GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>;
+                       };
+
+                       rtic@60000 {
+                               compatible = "fsl,sec-v5.4-rtic",
+                                            "fsl,sec-v5.0-rtic",
+                                            "fsl,sec-v4.0-rtic";
+                               #address-cells = <1>;
+                               #size-cells = <1>;
+                               reg = <0x60000 0x100 0x60e00 0x18>;
+                               ranges = <0x0 0x60100 0x500>;
+
+                               rtic_a: rtic-a@0 {
+                                       compatible = "fsl,sec-v5.4-rtic-memory",
+                                                    "fsl,sec-v5.0-rtic-memory",
+                                                    "fsl,sec-v4.0-rtic-memory";
+                                       reg = <0x00 0x20 0x100 0x100>;
+                               };
+
+                               rtic_b: rtic-b@20 {
+                                       compatible = "fsl,sec-v5.4-rtic-memory",
+                                                    "fsl,sec-v5.0-rtic-memory",
+                                                    "fsl,sec-v4.0-rtic-memory";
+                                       reg = <0x20 0x20 0x200 0x100>;
+                               };
+
+                               rtic_c: rtic-c@40 {
+                                       compatible = "fsl,sec-v5.4-rtic-memory",
+                                                    "fsl,sec-v5.0-rtic-memory",
+                                                    "fsl,sec-v4.0-rtic-memory";
+                                       reg = <0x40 0x20 0x300 0x100>;
+                               };
+
+                               rtic_d: rtic-d@60 {
+                                       compatible = "fsl,sec-v5.4-rtic-memory",
+                                                    "fsl,sec-v5.0-rtic-memory",
+                                                    "fsl,sec-v4.0-rtic-memory";
+                                       reg = <0x60 0x20 0x400 0x100>;
+                               };
+                       };
+               };
+
+               sec_mon: sec_mon@1e90000 {
+                       compatible = "fsl,sec-v5.4-mon", "fsl,sec-v5.0-mon",
+                                    "fsl,sec-v4.0-mon";
+                       reg = <0x0 0x1e90000 0x0 0x10000>;
+                       interrupts = <GIC_SPI 78 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 79 IRQ_TYPE_LEVEL_HIGH>;
+               };
+
                dcfg: dcfg@1ee0000 {
                        compatible = "fsl,ls1012a-dcfg",
                                     "syscon";
                        clocks = <&sysclk>;
                };
 
+               tmu: tmu@1f00000 {
+                       compatible = "fsl,qoriq-tmu";
+                       reg = <0x0 0x1f00000 0x0 0x10000>;
+                       interrupts = <0 33 0x4>;
+                       fsl,tmu-range = <0xb0000 0x9002a 0x6004c 0x30062>;
+                       fsl,tmu-calibration = <0x00000000 0x00000026
+                                              0x00000001 0x0000002d
+                                              0x00000002 0x00000032
+                                              0x00000003 0x00000039
+                                              0x00000004 0x0000003f
+                                              0x00000005 0x00000046
+                                              0x00000006 0x0000004d
+                                              0x00000007 0x00000054
+                                              0x00000008 0x0000005a
+                                              0x00000009 0x00000061
+                                              0x0000000a 0x0000006a
+                                              0x0000000b 0x00000071
+
+                                              0x00010000 0x00000025
+                                              0x00010001 0x0000002c
+                                              0x00010002 0x00000035
+                                              0x00010003 0x0000003d
+                                              0x00010004 0x00000045
+                                              0x00010005 0x0000004e
+                                              0x00010006 0x00000057
+                                              0x00010007 0x00000061
+                                              0x00010008 0x0000006b
+                                              0x00010009 0x00000076
+
+                                              0x00020000 0x00000029
+                                              0x00020001 0x00000033
+                                              0x00020002 0x0000003d
+                                              0x00020003 0x00000049
+                                              0x00020004 0x00000056
+                                              0x00020005 0x00000061
+                                              0x00020006 0x0000006d
+
+                                              0x00030000 0x00000021
+                                              0x00030001 0x0000002a
+                                              0x00030002 0x0000003c
+                                              0x00030003 0x0000004e>;
+                       big-endian;
+                       #thermal-sensor-cells = <1>;
+               };
+
+               thermal-zones {
+                       cpu_thermal: cpu-thermal {
+                               polling-delay-passive = <1000>;
+                               polling-delay = <5000>;
+                               thermal-sensors = <&tmu 0>;
+
+                               trips {
+                                       cpu_alert: cpu-alert {
+                                               temperature = <85000>;
+                                               hysteresis = <2000>;
+                                               type = "passive";
+                                       };
+
+                                       cpu_crit: cpu-crit {
+                                               temperature = <95000>;
+                                               hysteresis = <2000>;
+                                               type = "critical";
+                                       };
+                               };
+
+                               cooling-maps {
+                                       map0 {
+                                               trip = <&cpu_alert>;
+                                               cooling-device =
+                                                       <&cpu0 THERMAL_NO_LIMIT
+                                                       THERMAL_NO_LIMIT>;
+                                       };
+                               };
+                       };
+               };
+
                i2c0: i2c@2180000 {
                        compatible = "fsl,vf610-i2c";
                        #address-cells = <1>;
 
                sata: sata@3200000 {
                        compatible = "fsl,ls1012a-ahci", "fsl,ls1043a-ahci";
-                       reg = <0x0 0x3200000 0x0 0x10000>;
+                       reg = <0x0 0x3200000 0x0 0x10000>,
+                               <0x0 0x20140520 0x0 0x4>;
+                       reg-names = "ahci", "sata-ecc";
                        interrupts = <0 69 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&clockgen 4 0>;
+                       dma-coherent;
                        status = "disabled";
                };
        };
index ec13a6ecb75402d846f06b23978d64c8782b4552..45cface08cbbf6ae74537d01e6207987e190c5db 100644 (file)
 
                sata: sata@3200000 {
                        compatible = "fsl,ls1043a-ahci";
-                       reg = <0x0 0x3200000 0x0 0x10000>;
+                       reg = <0x0 0x3200000 0x0 0x10000>,
+                               <0x0 0x20140520 0x0 0x4>;
+                       reg-names = "ahci", "sata-ecc";
                        interrupts = <0 69 0x4>;
                        clocks = <&clockgen 4 0>;
                        dma-coherent;
index 4a164b801882f0c8afd22023c367142d65246f22..f4b8b7edaf9dbad72c1256fc6a220463ff5c3c19 100644 (file)
 
                sata: sata@3200000 {
                        compatible = "fsl,ls1046a-ahci";
-                       reg = <0x0 0x3200000 0x0 0x10000>;
+                       reg = <0x0 0x3200000 0x0 0x10000>,
+                               <0x0 0x20140520 0x0 0x4>;
+                       reg-names = "ahci", "sata-ecc";
                        interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&clockgen 4 1>;
                };
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls1088a-qds.dts
new file mode 100644 (file)
index 0000000..8c3cae5
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Device Tree file for NXP LS1088A QDS Board.
+ *
+ * Copyright 2017 NXP
+ *
+ * Harninder Rai <harninder.rai@nxp.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPLv2 or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include "fsl-ls1088a.dtsi"
+
+/ {
+       model = "LS1088A QDS Board";
+       compatible = "fsl,ls1088a-qds", "fsl,ls1088a";
+};
+
+&i2c0 {
+       status = "okay";
+
+       i2c-switch@77 {
+               compatible = "nxp,pca9547";
+               reg = <0x77>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               i2c@2 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x2>;
+
+                       ina220@40 {
+                               compatible = "ti,ina220";
+                               reg = <0x40>;
+                               shunt-resistor = <1000>;
+                       };
+
+                       ina220@41 {
+                               compatible = "ti,ina220";
+                               reg = <0x41>;
+                               shunt-resistor = <1000>;
+                       };
+               };
+
+               i2c@3 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x3>;
+
+                       temp-sensor@4c {
+                               compatible = "adi,adt7461a";
+                               reg = <0x4c>;
+                       };
+
+                       rtc@51 {
+                               compatible = "nxp,pcf2129";
+                               reg = <0x51>;
+                               /* IRQ10_B */
+                               interrupts = <0 150 IRQ_TYPE_LEVEL_HIGH>;
+                       };
+
+                       eeprom@56 {
+                               compatible = "atmel,24c512";
+                               reg = <0x56>;
+                       };
+
+                       eeprom@57 {
+                               compatible = "atmel,24c512";
+                               reg = <0x57>;
+                       };
+               };
+       };
+};
+
+&duart0 {
+       status = "okay";
+};
+
+&duart1 {
+       status = "okay";
+};
+
+&sata {
+       status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls1088a-rdb.dts
new file mode 100644 (file)
index 0000000..8a04fbb
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Device Tree file for NXP LS1088A RDB Board.
+ *
+ * Copyright 2017 NXP
+ *
+ * Harninder Rai <harninder.rai@nxp.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPLv2 or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include "fsl-ls1088a.dtsi"
+
+/ {
+       model = "L1088A RDB Board";
+       compatible = "fsl,ls1088a-rdb", "fsl,ls1088a";
+};
+
+&i2c0 {
+       status = "okay";
+
+       i2c-switch@77 {
+               compatible = "nxp,pca9547";
+               reg = <0x77>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               i2c@2 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x2>;
+
+                       ina220@40 {
+                               compatible = "ti,ina220";
+                               reg = <0x40>;
+                               shunt-resistor = <1000>;
+                       };
+               };
+
+               i2c@3 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x3>;
+
+                       temp-sensor@4c {
+                               compatible = "adi,adt7461a";
+                               reg = <0x4c>;
+                       };
+
+                       rtc@51 {
+                               compatible = "nxp,pcf2129";
+                               reg = <0x51>;
+                               /* IRQ10_B */
+                               interrupts = <0 150 IRQ_TYPE_LEVEL_HIGH>;
+                       };
+               };
+       };
+};
+
+&duart0 {
+       status = "okay";
+};
+
+&duart1 {
+       status = "okay";
+};
+
+&sata {
+       status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls1088a.dtsi
new file mode 100644 (file)
index 0000000..2946fd7
--- /dev/null
@@ -0,0 +1,275 @@
+/*
+ * Device Tree Include file for NXP Layerscape-1088A family SoC.
+ *
+ * Copyright 2017 NXP
+ *
+ * Harninder Rai <harninder.rai@nxp.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPLv2 or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+/ {
+       compatible = "fsl,ls1088a";
+       interrupt-parent = <&gic>;
+       #address-cells = <2>;
+       #size-cells = <2>;
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               /* We have 2 clusters having 4 Cortex-A53 cores each */
+               cpu0: cpu@0 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53";
+                       reg = <0x0>;
+                       clocks = <&clockgen 1 0>;
+               };
+
+               cpu1: cpu@1 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53";
+                       reg = <0x1>;
+                       clocks = <&clockgen 1 0>;
+               };
+
+               cpu2: cpu@2 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53";
+                       reg = <0x2>;
+                       clocks = <&clockgen 1 0>;
+               };
+
+               cpu3: cpu@3 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53";
+                       reg = <0x3>;
+                       clocks = <&clockgen 1 0>;
+               };
+
+               cpu4: cpu@100 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53";
+                       reg = <0x100>;
+                       clocks = <&clockgen 1 1>;
+               };
+
+               cpu5: cpu@101 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53";
+                       reg = <0x101>;
+                       clocks = <&clockgen 1 1>;
+               };
+
+               cpu6: cpu@102 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53";
+                       reg = <0x102>;
+                       clocks = <&clockgen 1 1>;
+               };
+
+               cpu7: cpu@103 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53";
+                       reg = <0x103>;
+                       clocks = <&clockgen 1 1>;
+               };
+       };
+
+       gic: interrupt-controller@6000000 {
+               compatible = "arm,gic-v3";
+               #interrupt-cells = <3>;
+               interrupt-controller;
+               reg = <0x0 0x06000000 0 0x10000>, /* GIC Dist */
+                     <0x0 0x06100000 0 0x100000>, /* GICR(RD_base+SGI_base)*/
+                     <0x0 0x0c0c0000 0 0x2000>, /* GICC */
+                     <0x0 0x0c0d0000 0 0x1000>, /* GICH */
+                     <0x0 0x0c0e0000 0 0x20000>; /* GICV */
+               interrupts = <1 9 IRQ_TYPE_LEVEL_HIGH>;
+       };
+
+       timer {
+               compatible = "arm,armv8-timer";
+               interrupts = <1 13 IRQ_TYPE_LEVEL_LOW>,/* Physical Secure PPI */
+                            <1 14 IRQ_TYPE_LEVEL_LOW>,/* Physical Non-Secure PPI */
+                            <1 11 IRQ_TYPE_LEVEL_LOW>,/* Virtual PPI */
+                            <1 10 IRQ_TYPE_LEVEL_LOW>;/* Hypervisor PPI */
+       };
+
+       sysclk: sysclk {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <100000000>;
+               clock-output-names = "sysclk";
+       };
+
+       soc {
+               compatible = "simple-bus";
+               #address-cells = <2>;
+               #size-cells = <2>;
+               ranges;
+
+               clockgen: clocking@1300000 {
+                       compatible = "fsl,ls1088a-clockgen";
+                       reg = <0 0x1300000 0 0xa0000>;
+                       #clock-cells = <2>;
+                       clocks = <&sysclk>;
+               };
+
+               duart0: serial@21c0500 {
+                       compatible = "fsl,ns16550", "ns16550a";
+                       reg = <0x0 0x21c0500 0x0 0x100>;
+                       clocks = <&clockgen 4 3>;
+                       interrupts = <0 32 IRQ_TYPE_LEVEL_HIGH>;
+                       status = "disabled";
+               };
+
+               duart1: serial@21c0600 {
+                       compatible = "fsl,ns16550", "ns16550a";
+                       reg = <0x0 0x21c0600 0x0 0x100>;
+                       clocks = <&clockgen 4 3>;
+                       interrupts = <0 32 IRQ_TYPE_LEVEL_HIGH>;
+                       status = "disabled";
+               };
+
+               gpio0: gpio@2300000 {
+                       compatible = "fsl,qoriq-gpio";
+                       reg = <0x0 0x2300000 0x0 0x10000>;
+                       interrupts = <0 36 IRQ_TYPE_LEVEL_HIGH>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpio1: gpio@2310000 {
+                       compatible = "fsl,qoriq-gpio";
+                       reg = <0x0 0x2310000 0x0 0x10000>;
+                       interrupts = <0 36 IRQ_TYPE_LEVEL_HIGH>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpio2: gpio@2320000 {
+                       compatible = "fsl,qoriq-gpio";
+                       reg = <0x0 0x2320000 0x0 0x10000>;
+                       interrupts = <0 37 IRQ_TYPE_LEVEL_HIGH>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpio3: gpio@2330000 {
+                       compatible = "fsl,qoriq-gpio";
+                       reg = <0x0 0x2330000 0x0 0x10000>;
+                       interrupts = <0 37 IRQ_TYPE_LEVEL_HIGH>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               ifc: ifc@2240000 {
+                       compatible = "fsl,ifc", "simple-bus";
+                       reg = <0x0 0x2240000 0x0 0x20000>;
+                       interrupts = <0 21 IRQ_TYPE_LEVEL_HIGH>;
+                       little-endian;
+                       #address-cells = <2>;
+                       #size-cells = <1>;
+
+                       ranges = <0 0 0x5 0x80000000 0x08000000
+                                 2 0 0x5 0x30000000 0x00010000
+                                 3 0 0x5 0x20000000 0x00010000>;
+                       status = "disabled";
+               };
+
+               i2c0: i2c@2000000 {
+                       compatible = "fsl,vf610-i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x0 0x2000000 0x0 0x10000>;
+                       interrupts = <0 34 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clockgen 4 3>;
+                       status = "disabled";
+               };
+
+               i2c1: i2c@2010000 {
+                       compatible = "fsl,vf610-i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x0 0x2010000 0x0 0x10000>;
+                       interrupts = <0 34 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clockgen 4 3>;
+                       status = "disabled";
+               };
+
+               i2c2: i2c@2020000 {
+                       compatible = "fsl,vf610-i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x0 0x2020000 0x0 0x10000>;
+                       interrupts = <0 35 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clockgen 4 3>;
+                       status = "disabled";
+               };
+
+               i2c3: i2c@2030000 {
+                       compatible = "fsl,vf610-i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x0 0x2030000 0x0 0x10000>;
+                       interrupts = <0 35 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clockgen 4 3>;
+                       status = "disabled";
+               };
+
+               sata: sata@3200000 {
+                       compatible = "fsl,ls1088a-ahci", "fsl,ls1043a-ahci";
+                       reg = <0x0 0x3200000 0x0 0x10000>;
+                       interrupts = <0 133 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&clockgen 4 3>;
+                       status = "disabled";
+               };
+       };
+
+};
index 8bc1f8f6fcfc2f2c6a819a483e0beb14bfccf20e..c1e76dfca48efe22fe6d0686a14d7573abc4ffaf 100644 (file)
@@ -1,8 +1,9 @@
 /*
  * Device Tree file for Freescale LS2080a QDS Board.
  *
- * Copyright (C) 2015, Freescale Semiconductor
+ * Copyright (C) 2015-17, Freescale Semiconductor
  *
+ * Abhimanyu Saini <abhimanyu.saini@nxp.com>
  * Bhupesh Sharma <bhupesh.sharma@freescale.com>
  *
  * This file is dual-licensed: you can use it either under the terms
@@ -47,6 +48,7 @@
 /dts-v1/;
 
 #include "fsl-ls2080a.dtsi"
+#include "fsl-ls208xa-qds.dtsi"
 
 / {
        model = "Freescale Layerscape 2080a QDS Board";
                stdout-path = "serial0:115200n8";
        };
 };
-
-&esdhc {
-       status = "okay";
-};
-
-&ifc {
-       status = "okay";
-       #address-cells = <2>;
-       #size-cells = <1>;
-       ranges = <0x0 0x0 0x5 0x80000000 0x08000000
-                 0x2 0x0 0x5 0x30000000 0x00010000
-                 0x3 0x0 0x5 0x20000000 0x00010000>;
-
-       nor@0,0 {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               compatible = "cfi-flash";
-               reg = <0x0 0x0 0x8000000>;
-               bank-width = <2>;
-               device-width = <1>;
-       };
-
-       nand@2,0 {
-            compatible = "fsl,ifc-nand";
-            reg = <0x2 0x0 0x10000>;
-       };
-
-       cpld@3,0 {
-            reg = <0x3 0x0 0x10000>;
-            compatible = "fsl,ls2080aqds-fpga", "fsl,fpga-qixis";
-       };
-};
-
-&i2c0 {
-       status = "okay";
-       pca9547@77 {
-               compatible = "nxp,pca9547";
-               reg = <0x77>;
-               #address-cells = <1>;
-               #size-cells = <0>;
-               i2c@0 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       reg = <0x00>;
-                       rtc@68 {
-                               compatible = "dallas,ds3232";
-                               reg = <0x68>;
-                       };
-               };
-
-               i2c@2 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       reg = <0x02>;
-
-                       ina220@40 {
-                               compatible = "ti,ina220";
-                               reg = <0x40>;
-                               shunt-resistor = <500>;
-                       };
-
-                       ina220@41 {
-                               compatible = "ti,ina220";
-                               reg = <0x41>;
-                               shunt-resistor = <1000>;
-                       };
-               };
-
-               i2c@3 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       reg = <0x3>;
-
-                       adt7481@4c {
-                               compatible = "adi,adt7461";
-                               reg = <0x4c>;
-                       };
-               };
-       };
-};
-
-&i2c1 {
-       status = "disabled";
-};
-
-&i2c2 {
-       status = "disabled";
-};
-
-&i2c3 {
-       status = "disabled";
-};
-
-&dspi {
-       status = "okay";
-       dflash0: n25q128a {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               compatible = "st,m25p80";
-               spi-max-frequency = <3000000>;
-               reg = <0>;
-       };
-       dflash1: sst25wf040b {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               compatible = "st,m25p80";
-               spi-max-frequency = <3000000>;
-               reg = <1>;
-       };
-       dflash2: en25s64 {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               compatible = "st,m25p80";
-               spi-max-frequency = <3000000>;
-               reg = <2>;
-       };
-};
-
-&qspi {
-       status = "okay";
-       flash0: s25fl256s1@0 {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               compatible = "st,m25p80";
-               spi-max-frequency = <20000000>;
-               reg = <0>;
-       };
-       flash2: s25fl256s1@2 {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               compatible = "st,m25p80";
-               spi-max-frequency = <20000000>;
-               reg = <0>;
-       };
-};
-
-&sata0 {
-       status = "okay";
-};
-
-&sata1 {
-       status = "okay";
-};
-
-&usb0 {
-       status = "okay";
-};
-
-&usb1 {
-       status = "okay";
-};
index 2ff46ca450b17f2afdf35d7fbe1c1b6eebc7c583..18ad1958731175f6bc33f733e6d1e503bbb9bcfd 100644 (file)
@@ -1,8 +1,9 @@
 /*
  * Device Tree file for Freescale LS2080a RDB Board.
  *
- * Copyright (C) 2015, Freescale Semiconductor
+ * Copyright (C) 2016-17, Freescale Semiconductor
  *
+ * Abhimanyu Saini <abhimanyu.saini@nxp.com>
  * Bhupesh Sharma <bhupesh.sharma@freescale.com>
  *
  * This file is dual-licensed: you can use it either under the terms
@@ -47,6 +48,7 @@
 /dts-v1/;
 
 #include "fsl-ls2080a.dtsi"
+#include "fsl-ls208xa-rdb.dtsi"
 
 / {
        model = "Freescale Layerscape 2080a RDB Board";
                stdout-path = "serial1:115200n8";
        };
 };
-
-&esdhc {
-       status = "okay";
-};
-
-&ifc {
-       status = "okay";
-       #address-cells = <2>;
-       #size-cells = <1>;
-       ranges = <0x0 0x0 0x5 0x80000000 0x08000000
-                 0x2 0x0 0x5 0x30000000 0x00010000
-                 0x3 0x0 0x5 0x20000000 0x00010000>;
-
-       nor@0,0 {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               compatible = "cfi-flash";
-               reg = <0x0 0x0 0x8000000>;
-               bank-width = <2>;
-               device-width = <1>;
-       };
-
-       nand@2,0 {
-            compatible = "fsl,ifc-nand";
-            reg = <0x2 0x0 0x10000>;
-       };
-
-       cpld@3,0 {
-            reg = <0x3 0x0 0x10000>;
-            compatible = "fsl,ls2080aqds-fpga", "fsl,fpga-qixis";
-       };
-
-};
-
-&i2c0 {
-       status = "okay";
-       pca9547@75 {
-               compatible = "nxp,pca9547";
-               reg = <0x75>;
-               #address-cells = <1>;
-               #size-cells = <0>;
-               i2c@1 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       reg = <0x01>;
-                       rtc@68 {
-                               compatible = "dallas,ds3232";
-                               reg = <0x68>;
-                       };
-               };
-
-               i2c@3 {
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       reg = <0x3>;
-
-                       adt7481@4c {
-                               compatible = "adi,adt7461";
-                               reg = <0x4c>;
-                       };
-               };
-       };
-};
-
-&i2c1 {
-       status = "disabled";
-};
-
-&i2c2 {
-       status = "disabled";
-};
-
-&i2c3 {
-       status = "disabled";
-};
-
-&dspi {
-       status = "okay";
-       dflash0: n25q512a {
-               #address-cells = <1>;
-               #size-cells = <1>;
-               compatible = "st,m25p80";
-               spi-max-frequency = <3000000>;
-               reg = <0>;
-       };
-};
-
-&qspi {
-       status = "disabled";
-};
-
-&sata0 {
-       status = "okay";
-};
-
-&sata1 {
-       status = "okay";
-};
-
-&usb0 {
-       status = "okay";
-};
-
-&usb1 {
-       status = "okay";
-};
index e5935f28848c564ae3627c6314248dc82070bcbc..46a26c0214219c26a1e50527db55cfab2618a97a 100644 (file)
@@ -1,8 +1,9 @@
 /*
  * Device Tree Include file for Freescale Layerscape-2080A family SoC.
  *
- * Copyright (C) 2014-2015, Freescale Semiconductor
+ * Copyright (C) 2014-2016, Freescale Semiconductor
  *
+ * Abhimanyu Saini <abhimanyu.saini@nxp.com>
  * Bhupesh Sharma <bhupesh.sharma@freescale.com>
  *
  * This file is dual-licensed: you can use it either under the terms
  *     OTHER DEALINGS IN THE SOFTWARE.
  */
 
-#include <dt-bindings/thermal/thermal.h>
+#include "fsl-ls208xa.dtsi"
 
-/ {
-       compatible = "fsl,ls2080a";
-       interrupt-parent = <&gic>;
-       #address-cells = <2>;
-       #size-cells = <2>;
-
-       cpus {
-               #address-cells = <1>;
-               #size-cells = <0>;
-
-               /*
-                * We expect the enable-method for cpu's to be "psci", but this
-                * is dependent on the SoC FW, which will fill this in.
-                *
-                * Currently supported enable-method is psci v0.2
-                */
-
-               /* We have 4 clusters having 2 Cortex-A57 cores each */
-               cpu0: cpu@0 {
-                       device_type = "cpu";
-                       compatible = "arm,cortex-a57";
-                       reg = <0x0>;
-                       clocks = <&clockgen 1 0>;
-                       next-level-cache = <&cluster0_l2>;
-                       #cooling-cells = <2>;
-               };
-
-               cpu1: cpu@1 {
-                       device_type = "cpu";
-                       compatible = "arm,cortex-a57";
-                       reg = <0x1>;
-                       clocks = <&clockgen 1 0>;
-                       next-level-cache = <&cluster0_l2>;
-               };
-
-               cpu2: cpu@100 {
-                       device_type = "cpu";
-                       compatible = "arm,cortex-a57";
-                       reg = <0x100>;
-                       clocks = <&clockgen 1 1>;
-                       next-level-cache = <&cluster1_l2>;
-                       #cooling-cells = <2>;
-               };
-
-               cpu3: cpu@101 {
-                       device_type = "cpu";
-                       compatible = "arm,cortex-a57";
-                       reg = <0x101>;
-                       clocks = <&clockgen 1 1>;
-                       next-level-cache = <&cluster1_l2>;
-               };
-
-               cpu4: cpu@200 {
-                       device_type = "cpu";
-                       compatible = "arm,cortex-a57";
-                       reg = <0x200>;
-                       clocks = <&clockgen 1 2>;
-                       next-level-cache = <&cluster2_l2>;
-                       #cooling-cells = <2>;
-               };
-
-               cpu5: cpu@201 {
-                       device_type = "cpu";
-                       compatible = "arm,cortex-a57";
-                       reg = <0x201>;
-                       clocks = <&clockgen 1 2>;
-                       next-level-cache = <&cluster2_l2>;
-               };
-
-               cpu6: cpu@300 {
-                       device_type = "cpu";
-                       compatible = "arm,cortex-a57";
-                       reg = <0x300>;
-                       clocks = <&clockgen 1 3>;
-                       next-level-cache = <&cluster3_l2>;
-                       #cooling-cells = <2>;
-               };
-
-               cpu7: cpu@301 {
-                       device_type = "cpu";
-                       compatible = "arm,cortex-a57";
-                       reg = <0x301>;
-                       clocks = <&clockgen 1 3>;
-                       next-level-cache = <&cluster3_l2>;
-               };
-
-               cluster0_l2: l2-cache0 {
-                       compatible = "cache";
-               };
-
-               cluster1_l2: l2-cache1 {
-                       compatible = "cache";
-               };
-
-               cluster2_l2: l2-cache2 {
-                       compatible = "cache";
-               };
-
-               cluster3_l2: l2-cache3 {
-                       compatible = "cache";
-               };
+&cpu {
+       cpu0: cpu@0 {
+               device_type = "cpu";
+               compatible = "arm,cortex-a57";
+               reg = <0x0>;
+               clocks = <&clockgen 1 0>;
+               next-level-cache = <&cluster0_l2>;
+               #cooling-cells = <2>;
        };
 
-       memory@80000000 {
-               device_type = "memory";
-               reg = <0x00000000 0x80000000 0 0x80000000>;
-                     /* DRAM space - 1, size : 2 GB DRAM */
+       cpu1: cpu@1 {
+               device_type = "cpu";
+               compatible = "arm,cortex-a57";
+               reg = <0x1>;
+               clocks = <&clockgen 1 0>;
+               next-level-cache = <&cluster0_l2>;
        };
 
-       sysclk: sysclk {
-               compatible = "fixed-clock";
-               #clock-cells = <0>;
-               clock-frequency = <100000000>;
-               clock-output-names = "sysclk";
+       cpu2: cpu@100 {
+               device_type = "cpu";
+               compatible = "arm,cortex-a57";
+               reg = <0x100>;
+               clocks = <&clockgen 1 1>;
+               next-level-cache = <&cluster1_l2>;
+               #cooling-cells = <2>;
        };
 
-       gic: interrupt-controller@6000000 {
-               compatible = "arm,gic-v3";
-               reg = <0x0 0x06000000 0 0x10000>, /* GIC Dist */
-                       <0x0 0x06100000 0 0x100000>, /* GICR (RD_base + SGI_base) */
-                       <0x0 0x0c0c0000 0 0x2000>, /* GICC */
-                       <0x0 0x0c0d0000 0 0x1000>, /* GICH */
-                       <0x0 0x0c0e0000 0 0x20000>; /* GICV */
-               #interrupt-cells = <3>;
-               #address-cells = <2>;
-               #size-cells = <2>;
-               ranges;
-               interrupt-controller;
-               interrupts = <1 9 0x4>;
-
-               its: gic-its@6020000 {
-                       compatible = "arm,gic-v3-its";
-                       msi-controller;
-                       reg = <0x0 0x6020000 0 0x20000>;
-               };
+       cpu3: cpu@101 {
+               device_type = "cpu";
+               compatible = "arm,cortex-a57";
+               reg = <0x101>;
+               clocks = <&clockgen 1 1>;
+               next-level-cache = <&cluster1_l2>;
        };
 
-       rstcr: syscon@1e60000 {
-               compatible = "fsl,ls2080a-rstcr", "syscon";
-               reg = <0x0 0x1e60000 0x0 0x4>;
+       cpu4: cpu@200 {
+               device_type = "cpu";
+               compatible = "arm,cortex-a57";
+               reg = <0x200>;
+               clocks = <&clockgen 1 2>;
+               next-level-cache = <&cluster2_l2>;
+               #cooling-cells = <2>;
        };
 
-       reboot {
-               compatible ="syscon-reboot";
-               regmap = <&rstcr>;
-               offset = <0x0>;
-               mask = <0x2>;
+       cpu5: cpu@201 {
+               device_type = "cpu";
+               compatible = "arm,cortex-a57";
+               reg = <0x201>;
+               clocks = <&clockgen 1 2>;
+               next-level-cache = <&cluster2_l2>;
        };
 
-       timer {
-               compatible = "arm,armv8-timer";
-               interrupts = <1 13 4>, /* Physical Secure PPI, active-low */
-                            <1 14 4>, /* Physical Non-Secure PPI, active-low */
-                            <1 11 4>, /* Virtual PPI, active-low */
-                            <1 10 4>; /* Hypervisor PPI, active-low */
-               fsl,erratum-a008585;
+       cpu6: cpu@300 {
+               device_type = "cpu";
+               compatible = "arm,cortex-a57";
+               reg = <0x300>;
+               clocks = <&clockgen 1 3>;
+               next-level-cache = <&cluster3_l2>;
+               #cooling-cells = <2>;
        };
 
-       pmu {
-               compatible = "arm,armv8-pmuv3";
-               interrupts = <1 7 0x8>; /* PMU PPI, Level low type */
+       cpu7: cpu@301 {
+               device_type = "cpu";
+               compatible = "arm,cortex-a57";
+               reg = <0x301>;
+               clocks = <&clockgen 1 3>;
+               next-level-cache = <&cluster3_l2>;
        };
 
-       soc {
-               compatible = "simple-bus";
-               #address-cells = <2>;
-               #size-cells = <2>;
-               ranges;
-
-               clockgen: clocking@1300000 {
-                       compatible = "fsl,ls2080a-clockgen";
-                       reg = <0 0x1300000 0 0xa0000>;
-                       #clock-cells = <2>;
-                       clocks = <&sysclk>;
-               };
-
-               dcfg: dcfg@1e00000 {
-                       compatible = "fsl,ls2080a-dcfg", "syscon";
-                       reg = <0x0 0x1e00000 0x0 0x10000>;
-                       little-endian;
-               };
-
-               tmu: tmu@1f80000 {
-                       compatible = "fsl,qoriq-tmu";
-                       reg = <0x0 0x1f80000 0x0 0x10000>;
-                       interrupts = <0 23 0x4>;
-                       fsl,tmu-range = <0xb0000 0x9002a 0x6004c 0x30062>;
-                       fsl,tmu-calibration = <0x00000000 0x00000026
-                                              0x00000001 0x0000002d
-                                              0x00000002 0x00000032
-                                              0x00000003 0x00000039
-                                              0x00000004 0x0000003f
-                                              0x00000005 0x00000046
-                                              0x00000006 0x0000004d
-                                              0x00000007 0x00000054
-                                              0x00000008 0x0000005a
-                                              0x00000009 0x00000061
-                                              0x0000000a 0x0000006a
-                                              0x0000000b 0x00000071
-
-                                              0x00010000 0x00000025
-                                              0x00010001 0x0000002c
-                                              0x00010002 0x00000035
-                                              0x00010003 0x0000003d
-                                              0x00010004 0x00000045
-                                              0x00010005 0x0000004e
-                                              0x00010006 0x00000057
-                                              0x00010007 0x00000061
-                                              0x00010008 0x0000006b
-                                              0x00010009 0x00000076
-
-                                              0x00020000 0x00000029
-                                              0x00020001 0x00000033
-                                              0x00020002 0x0000003d
-                                              0x00020003 0x00000049
-                                              0x00020004 0x00000056
-                                              0x00020005 0x00000061
-                                              0x00020006 0x0000006d
-
-                                              0x00030000 0x00000021
-                                              0x00030001 0x0000002a
-                                              0x00030002 0x0000003c
-                                              0x00030003 0x0000004e>;
-                       little-endian;
-                       #thermal-sensor-cells = <1>;
-               };
-
-               thermal-zones {
-                       cpu_thermal: cpu-thermal {
-                               polling-delay-passive = <1000>;
-                               polling-delay = <5000>;
-
-                               thermal-sensors = <&tmu 4>;
-
-                               trips {
-                                       cpu_alert: cpu-alert {
-                                               temperature = <75000>;
-                                               hysteresis = <2000>;
-                                               type = "passive";
-                                       };
-                                       cpu_crit: cpu-crit {
-                                               temperature = <85000>;
-                                               hysteresis = <2000>;
-                                               type = "critical";
-                                       };
-                               };
-
-                               cooling-maps {
-                                       map0 {
-                                               trip = <&cpu_alert>;
-                                               cooling-device =
-                                                       <&cpu0 THERMAL_NO_LIMIT
-                                                       THERMAL_NO_LIMIT>;
-                                       };
-                                       map1 {
-                                               trip = <&cpu_alert>;
-                                               cooling-device =
-                                                       <&cpu2 THERMAL_NO_LIMIT
-                                                       THERMAL_NO_LIMIT>;
-                                       };
-                                       map2 {
-                                               trip = <&cpu_alert>;
-                                               cooling-device =
-                                                       <&cpu4 THERMAL_NO_LIMIT
-                                                       THERMAL_NO_LIMIT>;
-                                       };
-                                       map3 {
-                                               trip = <&cpu_alert>;
-                                               cooling-device =
-                                                       <&cpu6 THERMAL_NO_LIMIT
-                                                       THERMAL_NO_LIMIT>;
-                                       };
-                               };
-                       };
-               };
-
-               serial0: serial@21c0500 {
-                       compatible = "fsl,ns16550", "ns16550a";
-                       reg = <0x0 0x21c0500 0x0 0x100>;
-                       clocks = <&clockgen 4 3>;
-                       interrupts = <0 32 0x4>; /* Level high type */
-               };
-
-               serial1: serial@21c0600 {
-                       compatible = "fsl,ns16550", "ns16550a";
-                       reg = <0x0 0x21c0600 0x0 0x100>;
-                       clocks = <&clockgen 4 3>;
-                       interrupts = <0 32 0x4>; /* Level high type */
-               };
-
-               cluster1_core0_watchdog: wdt@c000000 {
-                       compatible = "arm,sp805-wdt", "arm,primecell";
-                       reg = <0x0 0xc000000 0x0 0x1000>;
-                       clocks = <&clockgen 4 3>, <&clockgen 4 3>;
-                       clock-names = "apb_pclk", "wdog_clk";
-               };
-
-               cluster1_core1_watchdog: wdt@c010000 {
-                       compatible = "arm,sp805-wdt", "arm,primecell";
-                       reg = <0x0 0xc010000 0x0 0x1000>;
-                       clocks = <&clockgen 4 3>, <&clockgen 4 3>;
-                       clock-names = "apb_pclk", "wdog_clk";
-               };
-
-               cluster2_core0_watchdog: wdt@c100000 {
-                       compatible = "arm,sp805-wdt", "arm,primecell";
-                       reg = <0x0 0xc100000 0x0 0x1000>;
-                       clocks = <&clockgen 4 3>, <&clockgen 4 3>;
-                       clock-names = "apb_pclk", "wdog_clk";
-               };
-
-               cluster2_core1_watchdog: wdt@c110000 {
-                       compatible = "arm,sp805-wdt", "arm,primecell";
-                       reg = <0x0 0xc110000 0x0 0x1000>;
-                       clocks = <&clockgen 4 3>, <&clockgen 4 3>;
-                       clock-names = "apb_pclk", "wdog_clk";
-               };
-
-               cluster3_core0_watchdog: wdt@c200000 {
-                       compatible = "arm,sp805-wdt", "arm,primecell";
-                       reg = <0x0 0xc200000 0x0 0x1000>;
-                       clocks = <&clockgen 4 3>, <&clockgen 4 3>;
-                       clock-names = "apb_pclk", "wdog_clk";
-               };
-
-               cluster3_core1_watchdog: wdt@c210000 {
-                       compatible = "arm,sp805-wdt", "arm,primecell";
-                       reg = <0x0 0xc210000 0x0 0x1000>;
-                       clocks = <&clockgen 4 3>, <&clockgen 4 3>;
-                       clock-names = "apb_pclk", "wdog_clk";
-               };
-
-               cluster4_core0_watchdog: wdt@c300000 {
-                       compatible = "arm,sp805-wdt", "arm,primecell";
-                       reg = <0x0 0xc300000 0x0 0x1000>;
-                       clocks = <&clockgen 4 3>, <&clockgen 4 3>;
-                       clock-names = "apb_pclk", "wdog_clk";
-               };
-
-               cluster4_core1_watchdog: wdt@c310000 {
-                       compatible = "arm,sp805-wdt", "arm,primecell";
-                       reg = <0x0 0xc310000 0x0 0x1000>;
-                       clocks = <&clockgen 4 3>, <&clockgen 4 3>;
-                       clock-names = "apb_pclk", "wdog_clk";
-               };
-
-               fsl_mc: fsl-mc@80c000000 {
-                       compatible = "fsl,qoriq-mc";
-                       reg = <0x00000008 0x0c000000 0 0x40>,    /* MC portal base */
-                             <0x00000000 0x08340000 0 0x40000>; /* MC control reg */
-                       msi-parent = <&its>;
-                       #address-cells = <3>;
-                       #size-cells = <1>;
-
-                       /*
-                        * Region type 0x0 - MC portals
-                        * Region type 0x1 - QBMAN portals
-                        */
-                       ranges = <0x0 0x0 0x0 0x8 0x0c000000 0x4000000
-                                 0x1 0x0 0x0 0x8 0x18000000 0x8000000>;
-
-                       /*
-                        * Define the maximum number of MACs present on the SoC.
-                        */
-                       dpmacs {
-                               #address-cells = <1>;
-                               #size-cells = <0>;
-
-                               dpmac1: dpmac@1 {
-                                       compatible = "fsl,qoriq-mc-dpmac";
-                                       reg = <0x1>;
-                               };
-
-                               dpmac2: dpmac@2 {
-                                       compatible = "fsl,qoriq-mc-dpmac";
-                                       reg = <0x2>;
-                               };
-
-                               dpmac3: dpmac@3 {
-                                       compatible = "fsl,qoriq-mc-dpmac";
-                                       reg = <0x3>;
-                               };
-
-                               dpmac4: dpmac@4 {
-                                       compatible = "fsl,qoriq-mc-dpmac";
-                                       reg = <0x4>;
-                               };
-
-                               dpmac5: dpmac@5 {
-                                       compatible = "fsl,qoriq-mc-dpmac";
-                                       reg = <0x5>;
-                               };
-
-                               dpmac6: dpmac@6 {
-                                       compatible = "fsl,qoriq-mc-dpmac";
-                                       reg = <0x6>;
-                               };
-
-                               dpmac7: dpmac@7 {
-                                       compatible = "fsl,qoriq-mc-dpmac";
-                                       reg = <0x7>;
-                               };
-
-                               dpmac8: dpmac@8 {
-                                       compatible = "fsl,qoriq-mc-dpmac";
-                                       reg = <0x8>;
-                               };
-
-                               dpmac9: dpmac@9 {
-                                       compatible = "fsl,qoriq-mc-dpmac";
-                                       reg = <0x9>;
-                               };
-
-                               dpmac10: dpmac@a {
-                                       compatible = "fsl,qoriq-mc-dpmac";
-                                       reg = <0xa>;
-                               };
-
-                               dpmac11: dpmac@b {
-                                       compatible = "fsl,qoriq-mc-dpmac";
-                                       reg = <0xb>;
-                               };
-
-                               dpmac12: dpmac@c {
-                                       compatible = "fsl,qoriq-mc-dpmac";
-                                       reg = <0xc>;
-                               };
-
-                               dpmac13: dpmac@d {
-                                       compatible = "fsl,qoriq-mc-dpmac";
-                                       reg = <0xd>;
-                               };
-
-                               dpmac14: dpmac@e {
-                                       compatible = "fsl,qoriq-mc-dpmac";
-                                       reg = <0xe>;
-                               };
-
-                               dpmac15: dpmac@f {
-                                       compatible = "fsl,qoriq-mc-dpmac";
-                                       reg = <0xf>;
-                               };
-
-                               dpmac16: dpmac@10 {
-                                       compatible = "fsl,qoriq-mc-dpmac";
-                                       reg = <0x10>;
-                               };
-                       };
-               };
-
-               smmu: iommu@5000000 {
-                       compatible = "arm,mmu-500";
-                       reg = <0 0x5000000 0 0x800000>;
-                       #global-interrupts = <12>;
-                       interrupts = <0 13 4>, /* global secure fault */
-                                    <0 14 4>, /* combined secure interrupt */
-                                    <0 15 4>, /* global non-secure fault */
-                                    <0 16 4>, /* combined non-secure interrupt */
-                               /* performance counter interrupts 0-7 */
-                                    <0 211 4>, <0 212 4>,
-                                    <0 213 4>, <0 214 4>,
-                                    <0 215 4>, <0 216 4>,
-                                    <0 217 4>, <0 218 4>,
-                               /* per context interrupt, 64 interrupts */
-                                    <0 146 4>, <0 147 4>,
-                                    <0 148 4>, <0 149 4>,
-                                    <0 150 4>, <0 151 4>,
-                                    <0 152 4>, <0 153 4>,
-                                    <0 154 4>, <0 155 4>,
-                                    <0 156 4>, <0 157 4>,
-                                    <0 158 4>, <0 159 4>,
-                                    <0 160 4>, <0 161 4>,
-                                    <0 162 4>, <0 163 4>,
-                                    <0 164 4>, <0 165 4>,
-                                    <0 166 4>, <0 167 4>,
-                                    <0 168 4>, <0 169 4>,
-                                    <0 170 4>, <0 171 4>,
-                                    <0 172 4>, <0 173 4>,
-                                    <0 174 4>, <0 175 4>,
-                                    <0 176 4>, <0 177 4>,
-                                    <0 178 4>, <0 179 4>,
-                                    <0 180 4>, <0 181 4>,
-                                    <0 182 4>, <0 183 4>,
-                                    <0 184 4>, <0 185 4>,
-                                    <0 186 4>, <0 187 4>,
-                                    <0 188 4>, <0 189 4>,
-                                    <0 190 4>, <0 191 4>,
-                                    <0 192 4>, <0 193 4>,
-                                    <0 194 4>, <0 195 4>,
-                                    <0 196 4>, <0 197 4>,
-                                    <0 198 4>, <0 199 4>,
-                                    <0 200 4>, <0 201 4>,
-                                    <0 202 4>, <0 203 4>,
-                                    <0 204 4>, <0 205 4>,
-                                    <0 206 4>, <0 207 4>,
-                                    <0 208 4>, <0 209 4>;
-                       mmu-masters = <&fsl_mc 0x300 0>;
-               };
-
-               dspi: dspi@2100000 {
-                       status = "disabled";
-                       compatible = "fsl,ls2080a-dspi", "fsl,ls2085a-dspi";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       reg = <0x0 0x2100000 0x0 0x10000>;
-                       interrupts = <0 26 0x4>; /* Level high type */
-                       clocks = <&clockgen 4 3>;
-                       clock-names = "dspi";
-                       spi-num-chipselects = <5>;
-                       bus-num = <0>;
-               };
-
-               esdhc: esdhc@2140000 {
-                       status = "disabled";
-                       compatible = "fsl,ls2080a-esdhc", "fsl,esdhc";
-                       reg = <0x0 0x2140000 0x0 0x10000>;
-                       interrupts = <0 28 0x4>; /* Level high type */
-                       clock-frequency = <0>;  /* Updated by bootloader */
-                       voltage-ranges = <1800 1800 3300 3300>;
-                       sdhci,auto-cmd12;
-                       little-endian;
-                       bus-width = <4>;
-               };
-
-               gpio0: gpio@2300000 {
-                       compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio";
-                       reg = <0x0 0x2300000 0x0 0x10000>;
-                       interrupts = <0 36 0x4>; /* Level high type */
-                       gpio-controller;
-                       little-endian;
-                       #gpio-cells = <2>;
-                       interrupt-controller;
-                       #interrupt-cells = <2>;
-               };
-
-               gpio1: gpio@2310000 {
-                       compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio";
-                       reg = <0x0 0x2310000 0x0 0x10000>;
-                       interrupts = <0 36 0x4>; /* Level high type */
-                       gpio-controller;
-                       little-endian;
-                       #gpio-cells = <2>;
-                       interrupt-controller;
-                       #interrupt-cells = <2>;
-               };
-
-               gpio2: gpio@2320000 {
-                       compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio";
-                       reg = <0x0 0x2320000 0x0 0x10000>;
-                       interrupts = <0 37 0x4>; /* Level high type */
-                       gpio-controller;
-                       little-endian;
-                       #gpio-cells = <2>;
-                       interrupt-controller;
-                       #interrupt-cells = <2>;
-               };
-
-               gpio3: gpio@2330000 {
-                       compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio";
-                       reg = <0x0 0x2330000 0x0 0x10000>;
-                       interrupts = <0 37 0x4>; /* Level high type */
-                       gpio-controller;
-                       little-endian;
-                       #gpio-cells = <2>;
-                       interrupt-controller;
-                       #interrupt-cells = <2>;
-               };
-
-               i2c0: i2c@2000000 {
-                       status = "disabled";
-                       compatible = "fsl,vf610-i2c";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       reg = <0x0 0x2000000 0x0 0x10000>;
-                       interrupts = <0 34 0x4>; /* Level high type */
-                       clock-names = "i2c";
-                       clocks = <&clockgen 4 3>;
-               };
-
-               i2c1: i2c@2010000 {
-                       status = "disabled";
-                       compatible = "fsl,vf610-i2c";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       reg = <0x0 0x2010000 0x0 0x10000>;
-                       interrupts = <0 34 0x4>; /* Level high type */
-                       clock-names = "i2c";
-                       clocks = <&clockgen 4 3>;
-               };
-
-               i2c2: i2c@2020000 {
-                       status = "disabled";
-                       compatible = "fsl,vf610-i2c";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       reg = <0x0 0x2020000 0x0 0x10000>;
-                       interrupts = <0 35 0x4>; /* Level high type */
-                       clock-names = "i2c";
-                       clocks = <&clockgen 4 3>;
-               };
-
-               i2c3: i2c@2030000 {
-                       status = "disabled";
-                       compatible = "fsl,vf610-i2c";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       reg = <0x0 0x2030000 0x0 0x10000>;
-                       interrupts = <0 35 0x4>; /* Level high type */
-                       clock-names = "i2c";
-                       clocks = <&clockgen 4 3>;
-               };
-
-               ifc: ifc@2240000 {
-                       compatible = "fsl,ifc", "simple-bus";
-                       reg = <0x0 0x2240000 0x0 0x20000>;
-                       interrupts = <0 21 0x4>; /* Level high type */
-                       little-endian;
-                       #address-cells = <2>;
-                       #size-cells = <1>;
-
-                       ranges = <0 0 0x5 0x80000000 0x08000000
-                                 2 0 0x5 0x30000000 0x00010000
-                                 3 0 0x5 0x20000000 0x00010000>;
-               };
-
-               qspi: quadspi@20c0000 {
-                       status = "disabled";
-                       compatible = "fsl,ls2080a-qspi", "fsl,ls1021a-qspi";
-                       #address-cells = <1>;
-                       #size-cells = <0>;
-                       reg = <0x0 0x20c0000 0x0 0x10000>,
-                             <0x0 0x20000000 0x0 0x10000000>;
-                       reg-names = "QuadSPI", "QuadSPI-memory";
-                       interrupts = <0 25 0x4>; /* Level high type */
-                       clocks = <&clockgen 4 3>, <&clockgen 4 3>;
-                       clock-names = "qspi_en", "qspi";
-               };
+       cluster0_l2: l2-cache0 {
+               compatible = "cache";
+       };
 
-               pcie@3400000 {
-                       compatible = "fsl,ls2080a-pcie", "fsl,ls2085a-pcie",
-                                    "snps,dw-pcie";
-                       reg = <0x00 0x03400000 0x0 0x00100000   /* controller registers */
-                              0x10 0x00000000 0x0 0x00002000>; /* configuration space */
-                       reg-names = "regs", "config";
-                       interrupts = <0 108 0x4>; /* Level high type */
-                       interrupt-names = "intr";
-                       #address-cells = <3>;
-                       #size-cells = <2>;
-                       device_type = "pci";
-                       dma-coherent;
-                       num-lanes = <4>;
-                       bus-range = <0x0 0xff>;
-                       ranges = <0x81000000 0x0 0x00000000 0x10 0x00010000 0x0 0x00010000   /* downstream I/O */
-                                 0x82000000 0x0 0x40000000 0x10 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
-                       msi-parent = <&its>;
-                       #interrupt-cells = <1>;
-                       interrupt-map-mask = <0 0 0 7>;
-                       interrupt-map = <0000 0 0 1 &gic 0 0 0 109 4>,
-                                       <0000 0 0 2 &gic 0 0 0 110 4>,
-                                       <0000 0 0 3 &gic 0 0 0 111 4>,
-                                       <0000 0 0 4 &gic 0 0 0 112 4>;
-               };
+       cluster1_l2: l2-cache1 {
+               compatible = "cache";
+       };
 
-               pcie@3500000 {
-                       compatible = "fsl,ls2080a-pcie", "fsl,ls2085a-pcie",
-                                    "snps,dw-pcie";
-                       reg = <0x00 0x03500000 0x0 0x00100000   /* controller registers */
-                              0x12 0x00000000 0x0 0x00002000>; /* configuration space */
-                       reg-names = "regs", "config";
-                       interrupts = <0 113 0x4>; /* Level high type */
-                       interrupt-names = "intr";
-                       #address-cells = <3>;
-                       #size-cells = <2>;
-                       device_type = "pci";
-                       dma-coherent;
-                       num-lanes = <4>;
-                       bus-range = <0x0 0xff>;
-                       ranges = <0x81000000 0x0 0x00000000 0x12 0x00010000 0x0 0x00010000   /* downstream I/O */
-                                 0x82000000 0x0 0x40000000 0x12 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
-                       msi-parent = <&its>;
-                       #interrupt-cells = <1>;
-                       interrupt-map-mask = <0 0 0 7>;
-                       interrupt-map = <0000 0 0 1 &gic 0 0 0 114 4>,
-                                       <0000 0 0 2 &gic 0 0 0 115 4>,
-                                       <0000 0 0 3 &gic 0 0 0 116 4>,
-                                       <0000 0 0 4 &gic 0 0 0 117 4>;
-               };
+       cluster2_l2: l2-cache2 {
+               compatible = "cache";
+       };
 
-               pcie@3600000 {
-                       compatible = "fsl,ls2080a-pcie", "fsl,ls2085a-pcie",
-                                    "snps,dw-pcie";
-                       reg = <0x00 0x03600000 0x0 0x00100000   /* controller registers */
-                              0x14 0x00000000 0x0 0x00002000>; /* configuration space */
-                       reg-names = "regs", "config";
-                       interrupts = <0 118 0x4>; /* Level high type */
-                       interrupt-names = "intr";
-                       #address-cells = <3>;
-                       #size-cells = <2>;
-                       device_type = "pci";
-                       dma-coherent;
-                       num-lanes = <8>;
-                       bus-range = <0x0 0xff>;
-                       ranges = <0x81000000 0x0 0x00000000 0x14 0x00010000 0x0 0x00010000   /* downstream I/O */
-                                 0x82000000 0x0 0x40000000 0x14 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
-                       msi-parent = <&its>;
-                       #interrupt-cells = <1>;
-                       interrupt-map-mask = <0 0 0 7>;
-                       interrupt-map = <0000 0 0 1 &gic 0 0 0 119 4>,
-                                       <0000 0 0 2 &gic 0 0 0 120 4>,
-                                       <0000 0 0 3 &gic 0 0 0 121 4>,
-                                       <0000 0 0 4 &gic 0 0 0 122 4>;
-               };
+       cluster3_l2: l2-cache3 {
+               compatible = "cache";
+       };
+};
 
-               pcie@3700000 {
-                       compatible = "fsl,ls2080a-pcie", "fsl,ls2085a-pcie",
-                                    "snps,dw-pcie";
-                       reg = <0x00 0x03700000 0x0 0x00100000   /* controller registers */
-                              0x16 0x00000000 0x0 0x00002000>; /* configuration space */
-                       reg-names = "regs", "config";
-                       interrupts = <0 123 0x4>; /* Level high type */
-                       interrupt-names = "intr";
-                       #address-cells = <3>;
-                       #size-cells = <2>;
-                       device_type = "pci";
-                       dma-coherent;
-                       num-lanes = <4>;
-                       bus-range = <0x0 0xff>;
-                       ranges = <0x81000000 0x0 0x00000000 0x16 0x00010000 0x0 0x00010000   /* downstream I/O */
-                                 0x82000000 0x0 0x40000000 0x16 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
-                       msi-parent = <&its>;
-                       #interrupt-cells = <1>;
-                       interrupt-map-mask = <0 0 0 7>;
-                       interrupt-map = <0000 0 0 1 &gic 0 0 0 124 4>,
-                                       <0000 0 0 2 &gic 0 0 0 125 4>,
-                                       <0000 0 0 3 &gic 0 0 0 126 4>,
-                                       <0000 0 0 4 &gic 0 0 0 127 4>;
-               };
+&pcie1 {
+       reg = <0x00 0x03400000 0x0 0x00100000   /* controller registers */
+              0x10 0x00000000 0x0 0x00002000>; /* configuration space */
 
-               sata0: sata@3200000 {
-                       status = "disabled";
-                       compatible = "fsl,ls2080a-ahci";
-                       reg = <0x0 0x3200000 0x0 0x10000>;
-                       interrupts = <0 133 0x4>; /* Level high type */
-                       clocks = <&clockgen 4 3>;
-                       dma-coherent;
-               };
+       ranges = <0x81000000 0x0 0x00000000 0x10 0x00010000 0x0 0x00010000   /* downstream I/O */
+                 0x82000000 0x0 0x40000000 0x10 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
+};
 
-               sata1: sata@3210000 {
-                       status = "disabled";
-                       compatible = "fsl,ls2080a-ahci";
-                       reg = <0x0 0x3210000 0x0 0x10000>;
-                       interrupts = <0 136 0x4>; /* Level high type */
-                       clocks = <&clockgen 4 3>;
-                       dma-coherent;
-               };
+&pcie2 {
+       reg = <0x00 0x03500000 0x0 0x00100000   /* controller registers */
+              0x12 0x00000000 0x0 0x00002000>; /* configuration space */
 
-               usb0: usb3@3100000 {
-                       status = "disabled";
-                       compatible = "snps,dwc3";
-                       reg = <0x0 0x3100000 0x0 0x10000>;
-                       interrupts = <0 80 0x4>; /* Level high type */
-                       dr_mode = "host";
-                       snps,quirk-frame-length-adjustment = <0x20>;
-                       snps,dis_rxdet_inp3_quirk;
-               };
+       ranges = <0x81000000 0x0 0x00000000 0x12 0x00010000 0x0 0x00010000   /* downstream I/O */
+                 0x82000000 0x0 0x40000000 0x12 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
+};
 
-               usb1: usb3@3110000 {
-                       status = "disabled";
-                       compatible = "snps,dwc3";
-                       reg = <0x0 0x3110000 0x0 0x10000>;
-                       interrupts = <0 81 0x4>; /* Level high type */
-                       dr_mode = "host";
-                       snps,quirk-frame-length-adjustment = <0x20>;
-                       snps,dis_rxdet_inp3_quirk;
-               };
+&pcie3 {
+       reg = <0x00 0x03600000 0x0 0x00100000   /* controller registers */
+              0x14 0x00000000 0x0 0x00002000>; /* configuration space */
 
-               ccn@4000000 {
-                       compatible = "arm,ccn-504";
-                       reg = <0x0 0x04000000 0x0 0x01000000>;
-                       interrupts = <0 12 4>;
-               };
-       };
+       ranges = <0x81000000 0x0 0x00000000 0x14 0x00010000 0x0 0x00010000   /* downstream I/O */
+                 0x82000000 0x0 0x40000000 0x14 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
+};
 
-       ddr1: memory-controller@1080000 {
-               compatible = "fsl,qoriq-memory-controller";
-               reg = <0x0 0x1080000 0x0 0x1000>;
-               interrupts = <0 17 0x4>;
-               little-endian;
-       };
+&pcie4 {
+       reg = <0x00 0x03700000 0x0 0x00100000   /* controller registers */
+              0x16 0x00000000 0x0 0x00002000>; /* configuration space */
 
-       ddr2: memory-controller@1090000 {
-               compatible = "fsl,qoriq-memory-controller";
-               reg = <0x0 0x1090000 0x0 0x1000>;
-               interrupts = <0 18 0x4>;
-               little-endian;
-       };
+       ranges = <0x81000000 0x0 0x00000000 0x16 0x00010000 0x0 0x00010000   /* downstream I/O */
+                 0x82000000 0x0 0x40000000 0x16 0x40000000 0x0 0x40000000>; /* non-prefetchable memory */
 };
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2088a-qds.dts b/arch/arm64/boot/dts/freescale/fsl-ls2088a-qds.dts
new file mode 100644 (file)
index 0000000..ebcd6ee
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Device Tree file for Freescale LS2088A QDS Board.
+ *
+ * Copyright (C) 2016-17, Freescale Semiconductor
+ *
+ * Abhimanyu Saini <abhimanyu.saini@nxp.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPLv2 or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include "fsl-ls2088a.dtsi"
+#include "fsl-ls208xa-qds.dtsi"
+
+/ {
+       model = "Freescale Layerscape 2088A QDS Board";
+       compatible = "fsl,ls2088a-qds", "fsl,ls2088a";
+
+       aliases {
+               serial0 = &serial0;
+               serial1 = &serial1;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2088a-rdb.dts b/arch/arm64/boot/dts/freescale/fsl-ls2088a-rdb.dts
new file mode 100644 (file)
index 0000000..5992dc1
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Device Tree file for Freescale LS2088A RDB Board.
+ *
+ * Copyright (C) 2016-17, Freescale Semiconductor
+ *
+ * Abhimanyu Saini <abhimanyu.saini@nxp.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPLv2 or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+
+#include "fsl-ls2088a.dtsi"
+#include "fsl-ls208xa-rdb.dtsi"
+
+/ {
+       model = "Freescale Layerscape 2088A RDB Board";
+       compatible = "fsl,ls2088a-rdb", "fsl,ls2088a";
+
+       aliases {
+               serial0 = &serial0;
+               serial1 = &serial1;
+       };
+
+       chosen {
+               stdout-path = "serial1:115200n8";
+       };
+};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls2088a.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls2088a.dtsi
new file mode 100644 (file)
index 0000000..33ce404
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * Device Tree Include file for Freescale Layerscape-2088A family SoC.
+ *
+ * Copyright (C) 2016-17, Freescale Semiconductor
+ *
+ * Abhimanyu Saini <abhimanyu.saini@nxp.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPLv2 or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include "fsl-ls208xa.dtsi"
+
+&cpu {
+       cpu0: cpu@0 {
+               device_type = "cpu";
+               compatible = "arm,cortex-a72";
+               reg = <0x0>;
+               clocks = <&clockgen 1 0>;
+               next-level-cache = <&cluster0_l2>;
+               #cooling-cells = <2>;
+       };
+
+       cpu1: cpu@1 {
+               device_type = "cpu";
+               compatible = "arm,cortex-a72";
+               reg = <0x1>;
+               clocks = <&clockgen 1 0>;
+               next-level-cache = <&cluster0_l2>;
+       };
+
+       cpu2: cpu@100 {
+               device_type = "cpu";
+               compatible = "arm,cortex-a72";
+               reg = <0x100>;
+               clocks = <&clockgen 1 1>;
+               next-level-cache = <&cluster1_l2>;
+               #cooling-cells = <2>;
+       };
+
+       cpu3: cpu@101 {
+               device_type = "cpu";
+               compatible = "arm,cortex-a72";
+               reg = <0x101>;
+               clocks = <&clockgen 1 1>;
+               next-level-cache = <&cluster1_l2>;
+       };
+
+       cpu4: cpu@200 {
+               device_type = "cpu";
+               compatible = "arm,cortex-a72";
+               reg = <0x200>;
+               clocks = <&clockgen 1 2>;
+               next-level-cache = <&cluster2_l2>;
+               #cooling-cells = <2>;
+       };
+
+       cpu5: cpu@201 {
+               device_type = "cpu";
+               compatible = "arm,cortex-a72";
+               reg = <0x201>;
+               clocks = <&clockgen 1 2>;
+               next-level-cache = <&cluster2_l2>;
+       };
+
+       cpu6: cpu@300 {
+               device_type = "cpu";
+               compatible = "arm,cortex-a72";
+               reg = <0x300>;
+               clocks = <&clockgen 1 3>;
+               next-level-cache = <&cluster3_l2>;
+               #cooling-cells = <2>;
+       };
+
+       cpu7: cpu@301 {
+               device_type = "cpu";
+               compatible = "arm,cortex-a72";
+               reg = <0x301>;
+               clocks = <&clockgen 1 3>;
+               next-level-cache = <&cluster3_l2>;
+       };
+
+       cluster0_l2: l2-cache0 {
+               compatible = "cache";
+       };
+
+       cluster1_l2: l2-cache1 {
+               compatible = "cache";
+       };
+
+       cluster2_l2: l2-cache2 {
+               compatible = "cache";
+       };
+
+       cluster3_l2: l2-cache3 {
+               compatible = "cache";
+       };
+};
+
+&pcie1 {
+       reg = <0x00 0x03400000 0x0 0x00100000   /* controller registers */
+              0x20 0x00000000 0x0 0x00002000>; /* configuration space */
+
+       ranges = <0x81000000 0x0 0x00000000 0x20 0x00010000 0x0 0x00010000
+                 0x82000000 0x0 0x40000000 0x20 0x40000000 0x0 0x40000000>;
+};
+
+&pcie2 {
+       reg = <0x00 0x03500000 0x0 0x00100000   /* controller registers */
+              0x28 0x00000000 0x0 0x00002000>; /* configuration space */
+
+       ranges = <0x81000000 0x0 0x00000000 0x28 0x00010000 0x0 0x00010000
+                 0x82000000 0x0 0x40000000 0x28 0x40000000 0x0 0x40000000>;
+};
+
+&pcie3 {
+       reg = <0x00 0x03600000 0x0 0x00100000   /* controller registers */
+              0x30 0x00000000 0x0 0x00002000>; /* configuration space */
+
+       ranges = <0x81000000 0x0 0x00000000 0x30 0x00010000 0x0 0x00010000
+                 0x82000000 0x0 0x40000000 0x30 0x40000000 0x0 0x40000000>;
+};
+
+&pcie4 {
+       reg = <0x00 0x03700000 0x0 0x00100000   /* controller registers */
+              0x38 0x00000000 0x0 0x00002000>; /* configuration space */
+
+       ranges = <0x81000000 0x0 0x00000000 0x38 0x00010000 0x0 0x00010000
+                 0x82000000 0x0 0x40000000 0x38 0x40000000 0x0 0x40000000>;
+};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls208xa-qds.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls208xa-qds.dtsi
new file mode 100644 (file)
index 0000000..8b62048
--- /dev/null
@@ -0,0 +1,196 @@
+/*
+ * Device Tree file for Freescale LS2080A QDS Board.
+ *
+ * Copyright (C) 2016-17, Freescale Semiconductor
+ *
+ * Abhimanyu Saini <abhimanyu.saini@nxp.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPLv2 or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+&esdhc {
+       status = "okay";
+};
+
+&ifc {
+       status = "okay";
+       #address-cells = <2>;
+       #size-cells = <1>;
+       ranges = <0x0 0x0 0x5 0x80000000 0x08000000
+                 0x2 0x0 0x5 0x30000000 0x00010000
+                 0x3 0x0 0x5 0x20000000 0x00010000>;
+
+       nor@0,0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "cfi-flash";
+               reg = <0x0 0x0 0x8000000>;
+               bank-width = <2>;
+               device-width = <1>;
+       };
+
+       nand@2,0 {
+            compatible = "fsl,ifc-nand";
+            reg = <0x2 0x0 0x10000>;
+       };
+
+       cpld@3,0 {
+            reg = <0x3 0x0 0x10000>;
+            compatible = "fsl,ls2080aqds-fpga", "fsl,fpga-qixis";
+       };
+};
+
+&i2c0 {
+       status = "okay";
+       pca9547@77 {
+               compatible = "nxp,pca9547";
+               reg = <0x77>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               i2c@0 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x00>;
+                       rtc@68 {
+                               compatible = "dallas,ds3232";
+                               reg = <0x68>;
+                       };
+               };
+
+               i2c@2 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x02>;
+
+                       ina220@40 {
+                               compatible = "ti,ina220";
+                               reg = <0x40>;
+                               shunt-resistor = <500>;
+                       };
+
+                       ina220@41 {
+                               compatible = "ti,ina220";
+                               reg = <0x41>;
+                               shunt-resistor = <1000>;
+                       };
+               };
+
+               i2c@3 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x3>;
+
+                       adt7481@4c {
+                               compatible = "adi,adt7461";
+                               reg = <0x4c>;
+                       };
+               };
+       };
+};
+
+&i2c1 {
+       status = "disabled";
+};
+
+&i2c2 {
+       status = "disabled";
+};
+
+&i2c3 {
+       status = "disabled";
+};
+
+&dspi {
+       status = "okay";
+       dflash0: n25q128a {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "st,m25p80";
+               spi-max-frequency = <3000000>;
+               reg = <0>;
+       };
+       dflash1: sst25wf040b {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "st,m25p80";
+               spi-max-frequency = <3000000>;
+               reg = <1>;
+       };
+       dflash2: en25s64 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "st,m25p80";
+               spi-max-frequency = <3000000>;
+               reg = <2>;
+       };
+};
+
+&qspi {
+       status = "okay";
+       flash0: s25fl256s1@0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "st,m25p80";
+               spi-max-frequency = <20000000>;
+               reg = <0>;
+       };
+       flash2: s25fl256s1@2 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "st,m25p80";
+               spi-max-frequency = <20000000>;
+               reg = <0>;
+       };
+};
+
+&sata0 {
+       status = "okay";
+};
+
+&sata1 {
+       status = "okay";
+};
+
+&usb0 {
+       status = "okay";
+};
+
+&usb1 {
+       status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls208xa-rdb.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls208xa-rdb.dtsi
new file mode 100644 (file)
index 0000000..3737587
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * Device Tree file for Freescale LS2080A RDB Board.
+ *
+ * Copyright (C) 2016-17, Freescale Semiconductor
+ *
+ * Abhimanyu Saini <abhimanyu.saini@nxp.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPLv2 or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+&esdhc {
+       status = "okay";
+};
+
+&ifc {
+       status = "okay";
+       #address-cells = <2>;
+       #size-cells = <1>;
+       ranges = <0x0 0x0 0x5 0x80000000 0x08000000
+                 0x2 0x0 0x5 0x30000000 0x00010000
+                 0x3 0x0 0x5 0x20000000 0x00010000>;
+
+       nor@0,0 {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "cfi-flash";
+               reg = <0x0 0x0 0x8000000>;
+               bank-width = <2>;
+               device-width = <1>;
+       };
+
+       nand@2,0 {
+            compatible = "fsl,ifc-nand";
+            reg = <0x2 0x0 0x10000>;
+       };
+
+       cpld@3,0 {
+            reg = <0x3 0x0 0x10000>;
+            compatible = "fsl,ls2080aqds-fpga", "fsl,fpga-qixis";
+       };
+
+};
+
+&i2c0 {
+       status = "okay";
+       pca9547@75 {
+               compatible = "nxp,pca9547";
+               reg = <0x75>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               i2c@1 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x01>;
+                       rtc@68 {
+                               compatible = "dallas,ds3232";
+                               reg = <0x68>;
+                       };
+               };
+
+               i2c@3 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x3>;
+
+                       adt7481@4c {
+                               compatible = "adi,adt7461";
+                               reg = <0x4c>;
+                       };
+               };
+       };
+};
+
+&i2c1 {
+       status = "disabled";
+};
+
+&i2c2 {
+       status = "disabled";
+};
+
+&i2c3 {
+       status = "disabled";
+};
+
+&dspi {
+       status = "okay";
+       dflash0: n25q512a {
+               #address-cells = <1>;
+               #size-cells = <1>;
+               compatible = "st,m25p80";
+               spi-max-frequency = <3000000>;
+               reg = <0>;
+       };
+};
+
+&qspi {
+       status = "disabled";
+};
+
+&sata0 {
+       status = "okay";
+};
+
+&sata1 {
+       status = "okay";
+};
+
+&usb0 {
+       status = "okay";
+};
+
+&usb1 {
+       status = "okay";
+};
diff --git a/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi b/arch/arm64/boot/dts/freescale/fsl-ls208xa.dtsi
new file mode 100644 (file)
index 0000000..abb2fff
--- /dev/null
@@ -0,0 +1,737 @@
+/*
+ * Device Tree Include file for Freescale Layerscape-2080A family SoC.
+ *
+ * Copyright (C) 2016-2017, Freescale Semiconductor
+ *
+ * Abhimanyu Saini <abhimanyu.saini@nxp.com>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPLv2 or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <dt-bindings/thermal/thermal.h>
+
+/ {
+       compatible = "fsl,ls2080a";
+       interrupt-parent = <&gic>;
+       #address-cells = <2>;
+       #size-cells = <2>;
+
+       cpu: cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+       };
+
+       memory@80000000 {
+               device_type = "memory";
+               reg = <0x00000000 0x80000000 0 0x80000000>;
+                     /* DRAM space - 1, size : 2 GB DRAM */
+       };
+
+       sysclk: sysclk {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <100000000>;
+               clock-output-names = "sysclk";
+       };
+
+       gic: interrupt-controller@6000000 {
+               compatible = "arm,gic-v3";
+               reg = <0x0 0x06000000 0 0x10000>, /* GIC Dist */
+                       <0x0 0x06100000 0 0x100000>, /* GICR (RD_base + SGI_base) */
+                       <0x0 0x0c0c0000 0 0x2000>, /* GICC */
+                       <0x0 0x0c0d0000 0 0x1000>, /* GICH */
+                       <0x0 0x0c0e0000 0 0x20000>; /* GICV */
+               #interrupt-cells = <3>;
+               #address-cells = <2>;
+               #size-cells = <2>;
+               ranges;
+               interrupt-controller;
+               interrupts = <1 9 0x4>;
+
+               its: gic-its@6020000 {
+                       compatible = "arm,gic-v3-its";
+                       msi-controller;
+                       reg = <0x0 0x6020000 0 0x20000>;
+               };
+       };
+
+       rstcr: syscon@1e60000 {
+               compatible = "fsl,ls2080a-rstcr", "syscon";
+               reg = <0x0 0x1e60000 0x0 0x4>;
+       };
+
+       reboot {
+               compatible ="syscon-reboot";
+               regmap = <&rstcr>;
+               offset = <0x0>;
+               mask = <0x2>;
+       };
+
+       timer {
+               compatible = "arm,armv8-timer";
+               interrupts = <1 13 4>, /* Physical Secure PPI, active-low */
+                            <1 14 4>, /* Physical Non-Secure PPI, active-low */
+                            <1 11 4>, /* Virtual PPI, active-low */
+                            <1 10 4>; /* Hypervisor PPI, active-low */
+               fsl,erratum-a008585;
+       };
+
+       pmu {
+               compatible = "arm,armv8-pmuv3";
+               interrupts = <1 7 0x8>; /* PMU PPI, Level low type */
+       };
+
+       soc {
+               compatible = "simple-bus";
+               #address-cells = <2>;
+               #size-cells = <2>;
+               ranges;
+
+               clockgen: clocking@1300000 {
+                       compatible = "fsl,ls2080a-clockgen";
+                       reg = <0 0x1300000 0 0xa0000>;
+                       #clock-cells = <2>;
+                       clocks = <&sysclk>;
+               };
+
+               dcfg: dcfg@1e00000 {
+                       compatible = "fsl,ls2080a-dcfg", "syscon";
+                       reg = <0x0 0x1e00000 0x0 0x10000>;
+                       little-endian;
+               };
+
+               tmu: tmu@1f80000 {
+                       compatible = "fsl,qoriq-tmu";
+                       reg = <0x0 0x1f80000 0x0 0x10000>;
+                       interrupts = <0 23 0x4>;
+                       fsl,tmu-range = <0xb0000 0x9002a 0x6004c 0x30062>;
+                       fsl,tmu-calibration = <0x00000000 0x00000026
+                                              0x00000001 0x0000002d
+                                              0x00000002 0x00000032
+                                              0x00000003 0x00000039
+                                              0x00000004 0x0000003f
+                                              0x00000005 0x00000046
+                                              0x00000006 0x0000004d
+                                              0x00000007 0x00000054
+                                              0x00000008 0x0000005a
+                                              0x00000009 0x00000061
+                                              0x0000000a 0x0000006a
+                                              0x0000000b 0x00000071
+
+                                              0x00010000 0x00000025
+                                              0x00010001 0x0000002c
+                                              0x00010002 0x00000035
+                                              0x00010003 0x0000003d
+                                              0x00010004 0x00000045
+                                              0x00010005 0x0000004e
+                                              0x00010006 0x00000057
+                                              0x00010007 0x00000061
+                                              0x00010008 0x0000006b
+                                              0x00010009 0x00000076
+
+                                              0x00020000 0x00000029
+                                              0x00020001 0x00000033
+                                              0x00020002 0x0000003d
+                                              0x00020003 0x00000049
+                                              0x00020004 0x00000056
+                                              0x00020005 0x00000061
+                                              0x00020006 0x0000006d
+
+                                              0x00030000 0x00000021
+                                              0x00030001 0x0000002a
+                                              0x00030002 0x0000003c
+                                              0x00030003 0x0000004e>;
+                       little-endian;
+                       #thermal-sensor-cells = <1>;
+               };
+
+               thermal-zones {
+                       cpu_thermal: cpu-thermal {
+                               polling-delay-passive = <1000>;
+                               polling-delay = <5000>;
+
+                               thermal-sensors = <&tmu 4>;
+
+                               trips {
+                                       cpu_alert: cpu-alert {
+                                               temperature = <75000>;
+                                               hysteresis = <2000>;
+                                               type = "passive";
+                                       };
+                                       cpu_crit: cpu-crit {
+                                               temperature = <85000>;
+                                               hysteresis = <2000>;
+                                               type = "critical";
+                                       };
+                               };
+
+                               cooling-maps {
+                                       map0 {
+                                               trip = <&cpu_alert>;
+                                               cooling-device =
+                                                       <&cpu0 THERMAL_NO_LIMIT
+                                                       THERMAL_NO_LIMIT>;
+                                       };
+                                       map1 {
+                                               trip = <&cpu_alert>;
+                                               cooling-device =
+                                                       <&cpu2 THERMAL_NO_LIMIT
+                                                       THERMAL_NO_LIMIT>;
+                                       };
+                                       map2 {
+                                               trip = <&cpu_alert>;
+                                               cooling-device =
+                                                       <&cpu4 THERMAL_NO_LIMIT
+                                                       THERMAL_NO_LIMIT>;
+                                       };
+                                       map3 {
+                                               trip = <&cpu_alert>;
+                                               cooling-device =
+                                                       <&cpu6 THERMAL_NO_LIMIT
+                                                       THERMAL_NO_LIMIT>;
+                                       };
+                               };
+                       };
+               };
+
+               serial0: serial@21c0500 {
+                       compatible = "fsl,ns16550", "ns16550a";
+                       reg = <0x0 0x21c0500 0x0 0x100>;
+                       clocks = <&clockgen 4 3>;
+                       interrupts = <0 32 0x4>; /* Level high type */
+               };
+
+               serial1: serial@21c0600 {
+                       compatible = "fsl,ns16550", "ns16550a";
+                       reg = <0x0 0x21c0600 0x0 0x100>;
+                       clocks = <&clockgen 4 3>;
+                       interrupts = <0 32 0x4>; /* Level high type */
+               };
+
+               cluster1_core0_watchdog: wdt@c000000 {
+                       compatible = "arm,sp805-wdt", "arm,primecell";
+                       reg = <0x0 0xc000000 0x0 0x1000>;
+                       clocks = <&clockgen 4 3>, <&clockgen 4 3>;
+                       clock-names = "apb_pclk", "wdog_clk";
+               };
+
+               cluster1_core1_watchdog: wdt@c010000 {
+                       compatible = "arm,sp805-wdt", "arm,primecell";
+                       reg = <0x0 0xc010000 0x0 0x1000>;
+                       clocks = <&clockgen 4 3>, <&clockgen 4 3>;
+                       clock-names = "apb_pclk", "wdog_clk";
+               };
+
+               cluster2_core0_watchdog: wdt@c100000 {
+                       compatible = "arm,sp805-wdt", "arm,primecell";
+                       reg = <0x0 0xc100000 0x0 0x1000>;
+                       clocks = <&clockgen 4 3>, <&clockgen 4 3>;
+                       clock-names = "apb_pclk", "wdog_clk";
+               };
+
+               cluster2_core1_watchdog: wdt@c110000 {
+                       compatible = "arm,sp805-wdt", "arm,primecell";
+                       reg = <0x0 0xc110000 0x0 0x1000>;
+                       clocks = <&clockgen 4 3>, <&clockgen 4 3>;
+                       clock-names = "apb_pclk", "wdog_clk";
+               };
+
+               cluster3_core0_watchdog: wdt@c200000 {
+                       compatible = "arm,sp805-wdt", "arm,primecell";
+                       reg = <0x0 0xc200000 0x0 0x1000>;
+                       clocks = <&clockgen 4 3>, <&clockgen 4 3>;
+                       clock-names = "apb_pclk", "wdog_clk";
+               };
+
+               cluster3_core1_watchdog: wdt@c210000 {
+                       compatible = "arm,sp805-wdt", "arm,primecell";
+                       reg = <0x0 0xc210000 0x0 0x1000>;
+                       clocks = <&clockgen 4 3>, <&clockgen 4 3>;
+                       clock-names = "apb_pclk", "wdog_clk";
+               };
+
+               cluster4_core0_watchdog: wdt@c300000 {
+                       compatible = "arm,sp805-wdt", "arm,primecell";
+                       reg = <0x0 0xc300000 0x0 0x1000>;
+                       clocks = <&clockgen 4 3>, <&clockgen 4 3>;
+                       clock-names = "apb_pclk", "wdog_clk";
+               };
+
+               cluster4_core1_watchdog: wdt@c310000 {
+                       compatible = "arm,sp805-wdt", "arm,primecell";
+                       reg = <0x0 0xc310000 0x0 0x1000>;
+                       clocks = <&clockgen 4 3>, <&clockgen 4 3>;
+                       clock-names = "apb_pclk", "wdog_clk";
+               };
+
+               fsl_mc: fsl-mc@80c000000 {
+                       compatible = "fsl,qoriq-mc";
+                       reg = <0x00000008 0x0c000000 0 0x40>,    /* MC portal base */
+                             <0x00000000 0x08340000 0 0x40000>; /* MC control reg */
+                       msi-parent = <&its>;
+                       #address-cells = <3>;
+                       #size-cells = <1>;
+
+                       /*
+                        * Region type 0x0 - MC portals
+                        * Region type 0x1 - QBMAN portals
+                        */
+                       ranges = <0x0 0x0 0x0 0x8 0x0c000000 0x4000000
+                                 0x1 0x0 0x0 0x8 0x18000000 0x8000000>;
+
+                       /*
+                        * Define the maximum number of MACs present on the SoC.
+                        */
+                       dpmacs {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               dpmac1: dpmac@1 {
+                                       compatible = "fsl,qoriq-mc-dpmac";
+                                       reg = <0x1>;
+                               };
+
+                               dpmac2: dpmac@2 {
+                                       compatible = "fsl,qoriq-mc-dpmac";
+                                       reg = <0x2>;
+                               };
+
+                               dpmac3: dpmac@3 {
+                                       compatible = "fsl,qoriq-mc-dpmac";
+                                       reg = <0x3>;
+                               };
+
+                               dpmac4: dpmac@4 {
+                                       compatible = "fsl,qoriq-mc-dpmac";
+                                       reg = <0x4>;
+                               };
+
+                               dpmac5: dpmac@5 {
+                                       compatible = "fsl,qoriq-mc-dpmac";
+                                       reg = <0x5>;
+                               };
+
+                               dpmac6: dpmac@6 {
+                                       compatible = "fsl,qoriq-mc-dpmac";
+                                       reg = <0x6>;
+                               };
+
+                               dpmac7: dpmac@7 {
+                                       compatible = "fsl,qoriq-mc-dpmac";
+                                       reg = <0x7>;
+                               };
+
+                               dpmac8: dpmac@8 {
+                                       compatible = "fsl,qoriq-mc-dpmac";
+                                       reg = <0x8>;
+                               };
+
+                               dpmac9: dpmac@9 {
+                                       compatible = "fsl,qoriq-mc-dpmac";
+                                       reg = <0x9>;
+                               };
+
+                               dpmac10: dpmac@a {
+                                       compatible = "fsl,qoriq-mc-dpmac";
+                                       reg = <0xa>;
+                               };
+
+                               dpmac11: dpmac@b {
+                                       compatible = "fsl,qoriq-mc-dpmac";
+                                       reg = <0xb>;
+                               };
+
+                               dpmac12: dpmac@c {
+                                       compatible = "fsl,qoriq-mc-dpmac";
+                                       reg = <0xc>;
+                               };
+
+                               dpmac13: dpmac@d {
+                                       compatible = "fsl,qoriq-mc-dpmac";
+                                       reg = <0xd>;
+                               };
+
+                               dpmac14: dpmac@e {
+                                       compatible = "fsl,qoriq-mc-dpmac";
+                                       reg = <0xe>;
+                               };
+
+                               dpmac15: dpmac@f {
+                                       compatible = "fsl,qoriq-mc-dpmac";
+                                       reg = <0xf>;
+                               };
+
+                               dpmac16: dpmac@10 {
+                                       compatible = "fsl,qoriq-mc-dpmac";
+                                       reg = <0x10>;
+                               };
+                       };
+               };
+
+               smmu: iommu@5000000 {
+                       compatible = "arm,mmu-500";
+                       reg = <0 0x5000000 0 0x800000>;
+                       #global-interrupts = <12>;
+                       interrupts = <0 13 4>, /* global secure fault */
+                                    <0 14 4>, /* combined secure interrupt */
+                                    <0 15 4>, /* global non-secure fault */
+                                    <0 16 4>, /* combined non-secure interrupt */
+                               /* performance counter interrupts 0-7 */
+                                    <0 211 4>, <0 212 4>,
+                                    <0 213 4>, <0 214 4>,
+                                    <0 215 4>, <0 216 4>,
+                                    <0 217 4>, <0 218 4>,
+                               /* per context interrupt, 64 interrupts */
+                                    <0 146 4>, <0 147 4>,
+                                    <0 148 4>, <0 149 4>,
+                                    <0 150 4>, <0 151 4>,
+                                    <0 152 4>, <0 153 4>,
+                                    <0 154 4>, <0 155 4>,
+                                    <0 156 4>, <0 157 4>,
+                                    <0 158 4>, <0 159 4>,
+                                    <0 160 4>, <0 161 4>,
+                                    <0 162 4>, <0 163 4>,
+                                    <0 164 4>, <0 165 4>,
+                                    <0 166 4>, <0 167 4>,
+                                    <0 168 4>, <0 169 4>,
+                                    <0 170 4>, <0 171 4>,
+                                    <0 172 4>, <0 173 4>,
+                                    <0 174 4>, <0 175 4>,
+                                    <0 176 4>, <0 177 4>,
+                                    <0 178 4>, <0 179 4>,
+                                    <0 180 4>, <0 181 4>,
+                                    <0 182 4>, <0 183 4>,
+                                    <0 184 4>, <0 185 4>,
+                                    <0 186 4>, <0 187 4>,
+                                    <0 188 4>, <0 189 4>,
+                                    <0 190 4>, <0 191 4>,
+                                    <0 192 4>, <0 193 4>,
+                                    <0 194 4>, <0 195 4>,
+                                    <0 196 4>, <0 197 4>,
+                                    <0 198 4>, <0 199 4>,
+                                    <0 200 4>, <0 201 4>,
+                                    <0 202 4>, <0 203 4>,
+                                    <0 204 4>, <0 205 4>,
+                                    <0 206 4>, <0 207 4>,
+                                    <0 208 4>, <0 209 4>;
+                       mmu-masters = <&fsl_mc 0x300 0>;
+               };
+
+               dspi: dspi@2100000 {
+                       status = "disabled";
+                       compatible = "fsl,ls2080a-dspi", "fsl,ls2085a-dspi";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x0 0x2100000 0x0 0x10000>;
+                       interrupts = <0 26 0x4>; /* Level high type */
+                       clocks = <&clockgen 4 3>;
+                       clock-names = "dspi";
+                       spi-num-chipselects = <5>;
+                       bus-num = <0>;
+               };
+
+               esdhc: esdhc@2140000 {
+                       status = "disabled";
+                       compatible = "fsl,ls2080a-esdhc", "fsl,esdhc";
+                       reg = <0x0 0x2140000 0x0 0x10000>;
+                       interrupts = <0 28 0x4>; /* Level high type */
+                       clock-frequency = <0>;  /* Updated by bootloader */
+                       voltage-ranges = <1800 1800 3300 3300>;
+                       sdhci,auto-cmd12;
+                       little-endian;
+                       bus-width = <4>;
+               };
+
+               gpio0: gpio@2300000 {
+                       compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio";
+                       reg = <0x0 0x2300000 0x0 0x10000>;
+                       interrupts = <0 36 0x4>; /* Level high type */
+                       gpio-controller;
+                       little-endian;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpio1: gpio@2310000 {
+                       compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio";
+                       reg = <0x0 0x2310000 0x0 0x10000>;
+                       interrupts = <0 36 0x4>; /* Level high type */
+                       gpio-controller;
+                       little-endian;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpio2: gpio@2320000 {
+                       compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio";
+                       reg = <0x0 0x2320000 0x0 0x10000>;
+                       interrupts = <0 37 0x4>; /* Level high type */
+                       gpio-controller;
+                       little-endian;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpio3: gpio@2330000 {
+                       compatible = "fsl,ls2080a-gpio", "fsl,qoriq-gpio";
+                       reg = <0x0 0x2330000 0x0 0x10000>;
+                       interrupts = <0 37 0x4>; /* Level high type */
+                       gpio-controller;
+                       little-endian;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               i2c0: i2c@2000000 {
+                       status = "disabled";
+                       compatible = "fsl,vf610-i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x0 0x2000000 0x0 0x10000>;
+                       interrupts = <0 34 0x4>; /* Level high type */
+                       clock-names = "i2c";
+                       clocks = <&clockgen 4 3>;
+               };
+
+               i2c1: i2c@2010000 {
+                       status = "disabled";
+                       compatible = "fsl,vf610-i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x0 0x2010000 0x0 0x10000>;
+                       interrupts = <0 34 0x4>; /* Level high type */
+                       clock-names = "i2c";
+                       clocks = <&clockgen 4 3>;
+               };
+
+               i2c2: i2c@2020000 {
+                       status = "disabled";
+                       compatible = "fsl,vf610-i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x0 0x2020000 0x0 0x10000>;
+                       interrupts = <0 35 0x4>; /* Level high type */
+                       clock-names = "i2c";
+                       clocks = <&clockgen 4 3>;
+               };
+
+               i2c3: i2c@2030000 {
+                       status = "disabled";
+                       compatible = "fsl,vf610-i2c";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x0 0x2030000 0x0 0x10000>;
+                       interrupts = <0 35 0x4>; /* Level high type */
+                       clock-names = "i2c";
+                       clocks = <&clockgen 4 3>;
+               };
+
+               ifc: ifc@2240000 {
+                       compatible = "fsl,ifc", "simple-bus";
+                       reg = <0x0 0x2240000 0x0 0x20000>;
+                       interrupts = <0 21 0x4>; /* Level high type */
+                       little-endian;
+                       #address-cells = <2>;
+                       #size-cells = <1>;
+
+                       ranges = <0 0 0x5 0x80000000 0x08000000
+                                 2 0 0x5 0x30000000 0x00010000
+                                 3 0 0x5 0x20000000 0x00010000>;
+               };
+
+               qspi: quadspi@20c0000 {
+                       status = "disabled";
+                       compatible = "fsl,ls2080a-qspi", "fsl,ls1021a-qspi";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x0 0x20c0000 0x0 0x10000>,
+                             <0x0 0x20000000 0x0 0x10000000>;
+                       reg-names = "QuadSPI", "QuadSPI-memory";
+                       interrupts = <0 25 0x4>; /* Level high type */
+                       clocks = <&clockgen 4 3>, <&clockgen 4 3>;
+                       clock-names = "qspi_en", "qspi";
+               };
+
+               pcie1: pcie@3400000 {
+                       compatible = "fsl,ls2080a-pcie", "fsl,ls2085a-pcie",
+                                    "snps,dw-pcie";
+                       reg-names = "regs", "config";
+                       interrupts = <0 108 0x4>; /* Level high type */
+                       interrupt-names = "intr";
+                       #address-cells = <3>;
+                       #size-cells = <2>;
+                       device_type = "pci";
+                       dma-coherent;
+                       num-lanes = <4>;
+                       bus-range = <0x0 0xff>;
+                       msi-parent = <&its>;
+                       #interrupt-cells = <1>;
+                       interrupt-map-mask = <0 0 0 7>;
+                       interrupt-map = <0000 0 0 1 &gic 0 0 0 109 4>,
+                                       <0000 0 0 2 &gic 0 0 0 110 4>,
+                                       <0000 0 0 3 &gic 0 0 0 111 4>,
+                                       <0000 0 0 4 &gic 0 0 0 112 4>;
+               };
+
+               pcie2: pcie@3500000 {
+                       compatible = "fsl,ls2080a-pcie", "fsl,ls2085a-pcie",
+                                    "snps,dw-pcie";
+                       reg-names = "regs", "config";
+                       interrupts = <0 113 0x4>; /* Level high type */
+                       interrupt-names = "intr";
+                       #address-cells = <3>;
+                       #size-cells = <2>;
+                       device_type = "pci";
+                       dma-coherent;
+                       num-lanes = <4>;
+                       bus-range = <0x0 0xff>;
+                       msi-parent = <&its>;
+                       #interrupt-cells = <1>;
+                       interrupt-map-mask = <0 0 0 7>;
+                       interrupt-map = <0000 0 0 1 &gic 0 0 0 114 4>,
+                                       <0000 0 0 2 &gic 0 0 0 115 4>,
+                                       <0000 0 0 3 &gic 0 0 0 116 4>,
+                                       <0000 0 0 4 &gic 0 0 0 117 4>;
+               };
+
+               pcie3: pcie@3600000 {
+                       compatible = "fsl,ls2080a-pcie", "fsl,ls2085a-pcie",
+                                    "snps,dw-pcie";
+                       reg-names = "regs", "config";
+                       interrupts = <0 118 0x4>; /* Level high type */
+                       interrupt-names = "intr";
+                       #address-cells = <3>;
+                       #size-cells = <2>;
+                       device_type = "pci";
+                       dma-coherent;
+                       num-lanes = <8>;
+                       bus-range = <0x0 0xff>;
+                       msi-parent = <&its>;
+                       #interrupt-cells = <1>;
+                       interrupt-map-mask = <0 0 0 7>;
+                       interrupt-map = <0000 0 0 1 &gic 0 0 0 119 4>,
+                                       <0000 0 0 2 &gic 0 0 0 120 4>,
+                                       <0000 0 0 3 &gic 0 0 0 121 4>,
+                                       <0000 0 0 4 &gic 0 0 0 122 4>;
+               };
+
+               pcie4: pcie@3700000 {
+                       compatible = "fsl,ls2080a-pcie", "fsl,ls2085a-pcie",
+                                    "snps,dw-pcie";
+                       reg-names = "regs", "config";
+                       interrupts = <0 123 0x4>; /* Level high type */
+                       interrupt-names = "intr";
+                       #address-cells = <3>;
+                       #size-cells = <2>;
+                       device_type = "pci";
+                       dma-coherent;
+                       num-lanes = <4>;
+                       bus-range = <0x0 0xff>;
+                       msi-parent = <&its>;
+                       #interrupt-cells = <1>;
+                       interrupt-map-mask = <0 0 0 7>;
+                       interrupt-map = <0000 0 0 1 &gic 0 0 0 124 4>,
+                                       <0000 0 0 2 &gic 0 0 0 125 4>,
+                                       <0000 0 0 3 &gic 0 0 0 126 4>,
+                                       <0000 0 0 4 &gic 0 0 0 127 4>;
+               };
+
+               sata0: sata@3200000 {
+                       status = "disabled";
+                       compatible = "fsl,ls2080a-ahci";
+                       reg = <0x0 0x3200000 0x0 0x10000>;
+                       interrupts = <0 133 0x4>; /* Level high type */
+                       clocks = <&clockgen 4 3>;
+                       dma-coherent;
+               };
+
+               sata1: sata@3210000 {
+                       status = "disabled";
+                       compatible = "fsl,ls2080a-ahci";
+                       reg = <0x0 0x3210000 0x0 0x10000>;
+                       interrupts = <0 136 0x4>; /* Level high type */
+                       clocks = <&clockgen 4 3>;
+                       dma-coherent;
+               };
+
+               usb0: usb3@3100000 {
+                       status = "disabled";
+                       compatible = "snps,dwc3";
+                       reg = <0x0 0x3100000 0x0 0x10000>;
+                       interrupts = <0 80 0x4>; /* Level high type */
+                       dr_mode = "host";
+                       snps,quirk-frame-length-adjustment = <0x20>;
+                       snps,dis_rxdet_inp3_quirk;
+               };
+
+               usb1: usb3@3110000 {
+                       status = "disabled";
+                       compatible = "snps,dwc3";
+                       reg = <0x0 0x3110000 0x0 0x10000>;
+                       interrupts = <0 81 0x4>; /* Level high type */
+                       dr_mode = "host";
+                       snps,quirk-frame-length-adjustment = <0x20>;
+                       snps,dis_rxdet_inp3_quirk;
+               };
+
+               ccn@4000000 {
+                       compatible = "arm,ccn-504";
+                       reg = <0x0 0x04000000 0x0 0x01000000>;
+                       interrupts = <0 12 4>;
+               };
+       };
+
+       ddr1: memory-controller@1080000 {
+               compatible = "fsl,qoriq-memory-controller";
+               reg = <0x0 0x1080000 0x0 0x1000>;
+               interrupts = <0 17 0x4>;
+               little-endian;
+       };
+
+       ddr2: memory-controller@1090000 {
+               compatible = "fsl,qoriq-memory-controller";
+               reg = <0x0 0x1090000 0x0 0x1000>;
+               interrupts = <0 18 0x4>;
+               little-endian;
+       };
+};
index c3a6c1943038f112313b3eb93b57621d77fa4884..8960ecafd37db2aff5767bf296b41feb55388c34 100644 (file)
@@ -1,4 +1,5 @@
 dtb-$(CONFIG_ARCH_HISI) += hi3660-hikey960.dtb
+dtb-$(CONFIG_ARCH_HISI) += hi3798cv200-poplar.dtb
 dtb-$(CONFIG_ARCH_HISI) += hi6220-hikey.dtb
 dtb-$(CONFIG_ARCH_HISI) += hip05-d02.dtb
 dtb-$(CONFIG_ARCH_HISI) += hip06-d03.dtb
index ff37f0a0aa939db0a54b3718d611f40f851203cf..186251ffc6b200d7e1be4544aae67b98e6d56c4b 100644 (file)
@@ -8,6 +8,7 @@
 /dts-v1/;
 
 #include "hi3660.dtsi"
+#include "hikey960-pinctrl.dtsi"
 
 / {
        model = "HiKey960";
diff --git a/arch/arm64/boot/dts/hisilicon/hi3798cv200-poplar.dts b/arch/arm64/boot/dts/hisilicon/hi3798cv200-poplar.dts
new file mode 100644 (file)
index 0000000..b914287
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * DTS File for HiSilicon Poplar Development Board
+ *
+ * Copyright (c) 2016-2017 HiSilicon Technologies Co., Ltd.
+ *
+ * Released under the GPLv2 only.
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+/dts-v1/;
+
+#include <dt-bindings/gpio/gpio.h>
+#include "hi3798cv200.dtsi"
+
+/ {
+       model = "HiSilicon Poplar Development Board";
+       compatible = "hisilicon,hi3798cv200-poplar", "hisilicon,hi3798cv200";
+
+       aliases {
+               serial0 = &uart0;
+               serial2 = &uart2;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+       };
+
+       memory@0 {
+               device_type = "memory";
+               reg = <0x0 0x0 0x0 0x80000000>;
+       };
+
+       leds {
+               compatible = "gpio-leds";
+
+               user-led0 {
+                       label = "USER-LED0";
+                       gpios = <&gpio6 3 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "heartbeat";
+                       default-state = "off";
+               };
+
+               user-led1 {
+                       label = "USER-LED1";
+                       gpios = <&gpio5 1 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "mmc0";
+                       default-state = "off";
+               };
+
+               user-led2 {
+                       label = "USER-LED2";
+                       gpios = <&gpio5 2 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "none";
+                       default-state = "off";
+               };
+
+               user-led3 {
+                       label = "USER-LED3";
+                       gpios = <&gpio10 6 GPIO_ACTIVE_LOW>;
+                       linux,default-trigger = "cpu0";
+                       default-state = "off";
+               };
+       };
+};
+
+&gmac1 {
+       status = "okay";
+       #address-cells = <1>;
+       #size-cells = <0>;
+       phy-handle = <&eth_phy1>;
+       phy-mode = "rgmii";
+       hisilicon,phy-reset-delays-us = <10000 10000 30000>;
+
+       eth_phy1: phy@3 {
+               reg = <3>;
+       };
+};
+
+&gpio1 {
+       status = "okay";
+       gpio-line-names = "LS-GPIO-E",  "",
+                         "",           "",
+                         "",           "LS-GPIO-F",
+                         "",           "LS-GPIO-J";
+};
+
+&gpio2 {
+       status = "okay";
+       gpio-line-names = "LS-GPIO-H",  "LS-GPIO-I",
+                         "LS-GPIO-L",  "LS-GPIO-G",
+                         "LS-GPIO-K",  "",
+                         "",           "";
+};
+
+&gpio3 {
+       status = "okay";
+       gpio-line-names = "",           "",
+                         "",           "",
+                         "LS-GPIO-C",  "",
+                         "",           "LS-GPIO-B";
+};
+
+&gpio4 {
+       status = "okay";
+       gpio-line-names = "",           "",
+                         "",           "",
+                         "",           "LS-GPIO-D",
+                         "",           "";
+};
+
+&gpio5 {
+       status = "okay";
+       gpio-line-names = "",           "USER-LED-1",
+                         "USER-LED-2", "",
+                         "",           "LS-GPIO-A",
+                         "",           "";
+};
+
+&gpio6 {
+       status = "okay";
+       gpio-line-names = "",           "",
+                         "",           "USER-LED-0",
+                         "",           "",
+                         "",           "";
+};
+
+&gpio10 {
+       status = "okay";
+       gpio-line-names = "",           "",
+                         "",           "",
+                         "",           "",
+                         "USER-LED-3", "";
+};
+
+&i2c0 {
+       status = "okay";
+       label = "LS-I2C0";
+};
+
+&i2c2 {
+       status = "okay";
+       label = "LS-I2C1";
+};
+
+&ir {
+       status = "okay";
+};
+
+&spi0 {
+       status = "okay";
+       label = "LS-SPI0";
+};
+
+&uart0 {
+       status = "okay";
+};
+
+&uart2 {
+       status = "okay";
+       label = "LS-UART0";
+};
+/* No optional LS-UART1 on Low Speed Expansion Connector. */
diff --git a/arch/arm64/boot/dts/hisilicon/hi3798cv200.dtsi b/arch/arm64/boot/dts/hisilicon/hi3798cv200.dtsi
new file mode 100644 (file)
index 0000000..75865f8
--- /dev/null
@@ -0,0 +1,411 @@
+/*
+ * DTS File for HiSilicon Hi3798cv200 SoC.
+ *
+ * Copyright (c) 2016-2017 HiSilicon Technologies Co., Ltd.
+ *
+ * Released under the GPLv2 only.
+ * SPDX-License-Identifier: GPL-2.0
+ */
+
+#include <dt-bindings/clock/histb-clock.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/reset/ti-syscon.h>
+
+/ {
+       compatible = "hisilicon,hi3798cv200";
+       interrupt-parent = <&gic>;
+       #address-cells = <2>;
+       #size-cells = <2>;
+
+       psci {
+               compatible = "arm,psci-0.2";
+               method = "smc";
+       };
+
+       cpus {
+               #address-cells = <2>;
+               #size-cells = <0>;
+
+               cpu@0 {
+                       compatible = "arm,cortex-a53";
+                       device_type = "cpu";
+                       reg = <0x0 0x0>;
+                       enable-method = "psci";
+               };
+
+               cpu@1 {
+                       compatible = "arm,cortex-a53";
+                       device_type = "cpu";
+                       reg = <0x0 0x1>;
+                       enable-method = "psci";
+               };
+
+               cpu@2 {
+                       compatible = "arm,cortex-a53";
+                       device_type = "cpu";
+                       reg = <0x0 0x2>;
+                       enable-method = "psci";
+               };
+
+               cpu@3 {
+                       compatible = "arm,cortex-a53";
+                       device_type = "cpu";
+                       reg = <0x0 0x3>;
+                       enable-method = "psci";
+               };
+       };
+
+       gic: interrupt-controller@f1001000 {
+               compatible = "arm,gic-400";
+               reg = <0x0 0xf1001000 0x0 0x1000>,  /* GICD */
+                     <0x0 0xf1002000 0x0 0x100>;   /* GICC */
+               #address-cells = <0>;
+               #interrupt-cells = <3>;
+               interrupt-controller;
+       };
+
+       timer {
+               compatible = "arm,armv8-timer";
+               interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) |
+                             IRQ_TYPE_LEVEL_LOW)>,
+                            <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) |
+                             IRQ_TYPE_LEVEL_LOW)>,
+                            <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) |
+                             IRQ_TYPE_LEVEL_LOW)>,
+                            <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) |
+                             IRQ_TYPE_LEVEL_LOW)>;
+       };
+
+       soc: soc@f0000000 {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <1>;
+               ranges = <0x0 0x0 0xf0000000 0x10000000>;
+
+               crg: clock-reset-controller@8a22000 {
+                       compatible = "hisilicon,hi3798cv200-crg", "syscon", "simple-mfd";
+                       reg = <0x8a22000 0x1000>;
+                       #clock-cells = <1>;
+                       #reset-cells = <2>;
+
+                       gmacphyrst: reset-controller {
+                               compatible = "ti,syscon-reset";
+                               #reset-cells = <1>;
+                               ti,reset-bits =
+                                       <0xcc 12 0xcc 12 0 0 (ASSERT_CLEAR |
+                                        DEASSERT_SET|STATUS_NONE)>,
+                                       <0xcc 13 0xcc 13 0 0 (ASSERT_CLEAR |
+                                        DEASSERT_SET|STATUS_NONE)>;
+                       };
+               };
+
+               sysctrl: system-controller@8000000 {
+                       compatible = "hisilicon,hi3798cv200-sysctrl", "syscon";
+                       reg = <0x8000000 0x1000>;
+                       #clock-cells = <1>;
+                       #reset-cells = <2>;
+               };
+
+               uart0: serial@8b00000 {
+                       compatible = "arm,pl011", "arm,primecell";
+                       reg = <0x8b00000 0x1000>;
+                       interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&sysctrl HISTB_UART0_CLK>;
+                       clock-names = "apb_pclk";
+                       status = "disabled";
+               };
+
+               uart2: serial@8b02000 {
+                       compatible = "arm,pl011", "arm,primecell";
+                       reg = <0x8b02000 0x1000>;
+                       interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&crg HISTB_UART2_CLK>;
+                       clock-names = "apb_pclk";
+                       status = "disabled";
+               };
+
+               i2c0: i2c@8b10000 {
+                       compatible = "hisilicon,hix5hd2-i2c";
+                       reg = <0x8b10000 0x1000>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+                       clock-frequency = <400000>;
+                       clocks = <&crg HISTB_I2C0_CLK>;
+                       status = "disabled";
+               };
+
+               i2c1: i2c@8b11000 {
+                       compatible = "hisilicon,hix5hd2-i2c";
+                       reg = <0x8b11000 0x1000>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+                       clock-frequency = <400000>;
+                       clocks = <&crg HISTB_I2C1_CLK>;
+                       status = "disabled";
+               };
+
+               i2c2: i2c@8b12000 {
+                       compatible = "hisilicon,hix5hd2-i2c";
+                       reg = <0x8b12000 0x1000>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+                       clock-frequency = <400000>;
+                       clocks = <&crg HISTB_I2C2_CLK>;
+                       status = "disabled";
+               };
+
+               i2c3: i2c@8b13000 {
+                       compatible = "hisilicon,hix5hd2-i2c";
+                       reg = <0x8b13000 0x1000>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       interrupts = <GIC_SPI 41 IRQ_TYPE_LEVEL_HIGH>;
+                       clock-frequency = <400000>;
+                       clocks = <&crg HISTB_I2C3_CLK>;
+                       status = "disabled";
+               };
+
+               i2c4: i2c@8b14000 {
+                       compatible = "hisilicon,hix5hd2-i2c";
+                       reg = <0x8b14000 0x1000>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       interrupts = <GIC_SPI 42 IRQ_TYPE_LEVEL_HIGH>;
+                       clock-frequency = <400000>;
+                       clocks = <&crg HISTB_I2C4_CLK>;
+                       status = "disabled";
+               };
+
+               spi0: spi@8b1a000 {
+                       compatible = "arm,pl022", "arm,primecell";
+                       reg = <0x8b1a000 0x1000>;
+                       interrupts = <GIC_SPI 45 IRQ_TYPE_LEVEL_HIGH>;
+                       num-cs = <1>;
+                       cs-gpios = <&gpio7 1 0>;
+                       clocks = <&crg HISTB_SPI0_CLK>;
+                       clock-names = "apb_pclk";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       status = "disabled";
+               };
+
+               emmc: mmc@9830000 {
+                       compatible = "snps,dw-mshc";
+                       reg = <0x9830000 0x10000>;
+                       interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&crg HISTB_MMC_CIU_CLK>,
+                                <&crg HISTB_MMC_BIU_CLK>;
+                       clock-names = "ciu", "biu";
+               };
+
+               gpio0: gpio@8b20000 {
+                       compatible = "arm,pl061", "arm,primecell";
+                       reg = <0x8b20000 0x1000>;
+                       interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       clocks = <&crg HISTB_APB_CLK>;
+                       clock-names = "apb_pclk";
+                       status = "disabled";
+               };
+
+               gpio1: gpio@8b21000 {
+                       compatible = "arm,pl061", "arm,primecell";
+                       reg = <0x8b21000 0x1000>;
+                       interrupts = <GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       clocks = <&crg HISTB_APB_CLK>;
+                       clock-names = "apb_pclk";
+                       status = "disabled";
+               };
+
+               gpio2: gpio@8b22000 {
+                       compatible = "arm,pl061", "arm,primecell";
+                       reg = <0x8b22000 0x1000>;
+                       interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       clocks = <&crg HISTB_APB_CLK>;
+                       clock-names = "apb_pclk";
+                       status = "disabled";
+               };
+
+               gpio3: gpio@8b23000 {
+                       compatible = "arm,pl061", "arm,primecell";
+                       reg = <0x8b23000 0x1000>;
+                       interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       clocks = <&crg HISTB_APB_CLK>;
+                       clock-names = "apb_pclk";
+                       status = "disabled";
+               };
+
+               gpio4: gpio@8b24000 {
+                       compatible = "arm,pl061", "arm,primecell";
+                       reg = <0x8b24000 0x1000>;
+                       interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       clocks = <&crg HISTB_APB_CLK>;
+                       clock-names = "apb_pclk";
+                       status = "disabled";
+               };
+
+               gpio5: gpio@8004000 {
+                       compatible = "arm,pl061", "arm,primecell";
+                       reg = <0x8004000 0x1000>;
+                       interrupts = <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       clocks = <&crg HISTB_APB_CLK>;
+                       clock-names = "apb_pclk";
+                       status = "disabled";
+               };
+
+               gpio6: gpio@8b26000 {
+                       compatible = "arm,pl061", "arm,primecell";
+                       reg = <0x8b26000 0x1000>;
+                       interrupts = <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       clocks = <&crg HISTB_APB_CLK>;
+                       clock-names = "apb_pclk";
+                       status = "disabled";
+               };
+
+               gpio7: gpio@8b27000 {
+                       compatible = "arm,pl061", "arm,primecell";
+                       reg = <0x8b27000 0x1000>;
+                       interrupts = <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       clocks = <&crg HISTB_APB_CLK>;
+                       clock-names = "apb_pclk";
+                       status = "disabled";
+               };
+
+               gpio8: gpio@8b28000 {
+                       compatible = "arm,pl061", "arm,primecell";
+                       reg = <0x8b28000 0x1000>;
+                       interrupts = <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       clocks = <&crg HISTB_APB_CLK>;
+                       clock-names = "apb_pclk";
+                       status = "disabled";
+               };
+
+               gpio9: gpio@8b29000 {
+                       compatible = "arm,pl061", "arm,primecell";
+                       reg = <0x8b29000 0x1000>;
+                       interrupts = <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       clocks = <&crg HISTB_APB_CLK>;
+                       clock-names = "apb_pclk";
+                       status = "disabled";
+               };
+
+               gpio10: gpio@8b2a000 {
+                       compatible = "arm,pl061", "arm,primecell";
+                       reg = <0x8b2a000 0x1000>;
+                       interrupts = <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       clocks = <&crg HISTB_APB_CLK>;
+                       clock-names = "apb_pclk";
+                       status = "disabled";
+               };
+
+               gpio11: gpio@8b2b000 {
+                       compatible = "arm,pl061", "arm,primecell";
+                       reg = <0x8b2b000 0x1000>;
+                       interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       clocks = <&crg HISTB_APB_CLK>;
+                       clock-names = "apb_pclk";
+                       status = "disabled";
+               };
+
+               gpio12: gpio@8b2c000 {
+                       compatible = "arm,pl061", "arm,primecell";
+                       reg = <0x8b2c000 0x1000>;
+                       interrupts = <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+                       gpio-controller;
+                       #gpio-cells = <2>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       clocks = <&crg HISTB_APB_CLK>;
+                       clock-names = "apb_pclk";
+                       status = "disabled";
+               };
+
+               gmac0: ethernet@9840000 {
+                       compatible = "hisilicon,hi3798cv200-gmac", "hisilicon,hisi-gmac-v2";
+                       reg = <0x9840000 0x1000>,
+                             <0x984300c 0x4>;
+                       interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&crg HISTB_ETH0_MAC_CLK>,
+                                <&crg HISTB_ETH0_MACIF_CLK>;
+                       clock-names = "mac_core", "mac_ifc";
+                       resets = <&crg 0xcc 8>,
+                                <&crg 0xcc 10>,
+                                <&gmacphyrst 0>;
+                       reset-names = "mac_core", "mac_ifc", "phy";
+                       status = "disabled";
+               };
+
+               gmac1: ethernet@9841000 {
+                       compatible = "hisilicon,hi3798cv200-gmac", "hisilicon,hisi-gmac-v2";
+                       reg = <0x9841000 0x1000>,
+                             <0x9843010 0x4>;
+                       interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&crg HISTB_ETH1_MAC_CLK>,
+                                <&crg HISTB_ETH1_MACIF_CLK>;
+                       clock-names = "mac_core", "mac_ifc";
+                       resets = <&crg 0xcc 9>,
+                                <&crg 0xcc 11>,
+                                <&gmacphyrst 1>;
+                       reset-names = "mac_core", "mac_ifc", "phy";
+                       status = "disabled";
+               };
+
+               ir: ir@8001000 {
+                       compatible = "hisilicon,hix5hd2-ir";
+                       reg = <0x8001000 0x1000>;
+                       interrupts = <GIC_SPI 47 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&sysctrl HISTB_IR_CLK>;
+                       status = "disabled";
+               };
+       };
+};
index 9b4ba71692101077d5a77a6b18749b7c6c4d26f6..75bce2d0b1a83fa9f953b55a75ebdcb2ff4dc526 100644 (file)
                        };
                };
        };
+
+       firmware {
+               optee {
+                       compatible = "linaro,optee-tz";
+                       method = "smc";
+               };
+       };
 };
 
 &uart2 {
index 470461ddd4276a1cf4fece290db7858b5ddc9960..1e5129b19280bf8195a9ac24e506ec096493b084 100644 (file)
                        clocks = <&sys_ctrl 2>, <&sys_ctrl 1>;
                        clock-names = "ciu", "biu";
                        resets = <&sys_ctrl PERIPH_RSTDIS0_MMC0>;
+                       reset-names = "reset";
                        bus-width = <0x8>;
                        vmmc-supply = <&ldo19>;
                        pinctrl-names = "default";
                        clocks = <&sys_ctrl 4>, <&sys_ctrl 3>;
                        clock-names = "ciu", "biu";
                        resets = <&sys_ctrl PERIPH_RSTDIS0_MMC1>;
+                       reset-names = "reset";
                        vqmmc-supply = <&ldo7>;
                        vmmc-supply = <&ldo10>;
                        bus-width = <0x4>;
                        clocks = <&sys_ctrl HI6220_MMC2_CIUCLK>, <&sys_ctrl HI6220_MMC2_CLK>;
                        clock-names = "ciu", "biu";
                        resets = <&sys_ctrl PERIPH_RSTDIS0_MMC2>;
+                       reset-names = "reset";
                        bus-width = <0x4>;
                        broken-cd;
                        pinctrl-names = "default", "idle";
diff --git a/arch/arm64/boot/dts/hisilicon/hikey960-pinctrl.dtsi b/arch/arm64/boot/dts/hisilicon/hikey960-pinctrl.dtsi
new file mode 100644 (file)
index 0000000..719c4bc
--- /dev/null
@@ -0,0 +1,407 @@
+/*
+ * pinctrl dts fils for Hislicon HiKey960 development board
+ *
+ */
+
+#include <dt-bindings/pinctrl/hisi.h>
+
+/ {
+       soc {
+               /* [IOMG_000, IOMG_123] */
+               range: gpio-range {
+                       #pinctrl-single,gpio-range-cells = <3>;
+               };
+
+               pmx0: pinmux@e896c000 {
+                       compatible = "pinctrl-single";
+                       reg = <0x0 0xe896c000 0x0 0x1f0>;
+                       #pinctrl-cells = <1>;
+                       #gpio-range-cells = <0x3>;
+                       pinctrl-single,register-width = <0x20>;
+                       pinctrl-single,function-mask = <0x7>;
+                       /* pin base, nr pins & gpio function */
+                       pinctrl-single,gpio-range = <
+                               &range 0 7 0
+                               &range 8 116 0>;
+
+                       isp0_pmx_func: isp0_pmx_func {
+                               pinctrl-single,pins = <
+                                       0x058 MUX_M1 /* ISP_CLK0 */
+                                       0x064 MUX_M1 /* ISP_SCL0 */
+                                       0x068 MUX_M1 /* ISP_SDA0 */
+                               >;
+                       };
+
+                       isp1_pmx_func: isp1_pmx_func {
+                               pinctrl-single,pins = <
+                                       0x05c MUX_M1 /* ISP_CLK1 */
+                                       0x06c MUX_M1 /* ISP_SCL1 */
+                                       0x070 MUX_M1 /* ISP_SDA1 */
+                               >;
+                       };
+
+                       i2c3_pmx_func: i2c3_pmx_func {
+                               pinctrl-single,pins = <
+                                       0x02c MUX_M1 /* I2C3_SCL */
+                                       0x030 MUX_M1 /* I2C3_SDA */
+                               >;
+                       };
+
+                       i2c4_pmx_func: i2c4_pmx_func {
+                               pinctrl-single,pins = <
+                                       0x090 MUX_M1 /* I2C4_SCL */
+                                       0x094 MUX_M1 /* I2C4_SDA */
+                               >;
+                       };
+
+                       pcie_perstn_pmx_func: pcie_perstn_pmx_func {
+                               pinctrl-single,pins = <
+                                       0x15c MUX_M1 /* PCIE_PERST_N */
+                               >;
+                       };
+
+                       usbhub5734_pmx_func: usbhub5734_pmx_func {
+                               pinctrl-single,pins = <
+                                       0x11c MUX_M0 /* GPIO_073 */
+                                       0x120 MUX_M0 /* GPIO_074 */
+                               >;
+                       };
+
+                       spi1_pmx_func: spi1_pmx_func {
+                               pinctrl-single,pins = <
+                                       0x034 MUX_M1 /* SPI1_CLK */
+                                       0x038 MUX_M1 /* SPI1_DI */
+                                       0x03c MUX_M1 /* SPI1_DO */
+                                       0x040 MUX_M1 /* SPI1_CS_N */
+                               >;
+                       };
+
+                       uart0_pmx_func: uart0_pmx_func {
+                               pinctrl-single,pins = <
+                                       0x0cc MUX_M2 /* UART0_RXD */
+                                       0x0d0 MUX_M2 /* UART0_TXD */
+                                       0x0d4 MUX_M2 /* UART0_RXD_M */
+                                       0x0d8 MUX_M2 /* UART0_TXD_M */
+                               >;
+                       };
+
+                       uart1_pmx_func: uart1_pmx_func {
+                               pinctrl-single,pins = <
+                                       0x0b0 MUX_M2 /* UART1_CTS_N */
+                                       0x0b4 MUX_M2 /* UART1_RTS_N */
+                                       0x0a8 MUX_M2 /* UART1_RXD */
+                                       0x0ac MUX_M2 /* UART1_TXD */
+                               >;
+                       };
+
+                       uart2_pmx_func: uart2_pmx_func {
+                               pinctrl-single,pins = <
+                                       0x0bc MUX_M2 /* UART2_CTS_N */
+                                       0x0c0 MUX_M2 /* UART2_RTS_N */
+                                       0x0c8 MUX_M2 /* UART2_RXD */
+                                       0x0c4 MUX_M2 /* UART2_TXD */
+                               >;
+                       };
+
+                       uart3_pmx_func: uart3_pmx_func {
+                               pinctrl-single,pins = <
+                                       0x0dc MUX_M1 /* UART3_CTS_N */
+                                       0x0e0 MUX_M1 /* UART3_RTS_N */
+                                       0x0e4 MUX_M1 /* UART3_RXD */
+                                       0x0e8 MUX_M1 /* UART3_TXD */
+                               >;
+                       };
+
+                       uart4_pmx_func: uart4_pmx_func {
+                               pinctrl-single,pins = <
+                                       0x0ec MUX_M1 /* UART4_CTS_N */
+                                       0x0f0 MUX_M1 /* UART4_RTS_N */
+                                       0x0f4 MUX_M1 /* UART4_RXD */
+                                       0x0f8 MUX_M1 /* UART4_TXD */
+                               >;
+                       };
+
+                       uart5_pmx_func: uart5_pmx_func {
+                               pinctrl-single,pins = <
+                                       0x0c4 MUX_M3 /* UART5_CTS_N */
+                                       0x0c8 MUX_M3 /* UART5_RTS_N */
+                                       0x0bc MUX_M3 /* UART5_RXD */
+                                       0x0c0 MUX_M3 /* UART5_TXD */
+                               >;
+                       };
+
+                       uart6_pmx_func: uart6_pmx_func {
+                               pinctrl-single,pins = <
+                                       0x0cc MUX_M1 /* UART6_CTS_N */
+                                       0x0d0 MUX_M1 /* UART6_RTS_N */
+                                       0x0d4 MUX_M1 /* UART6_RXD */
+                                       0x0d8 MUX_M1 /* UART6_TXD */
+                               >;
+                       };
+               };
+
+               /* [IOMG_MMC0_000, IOMG_MMC0_005] */
+               pmx1: pinmux@ff37e000 {
+                       compatible = "pinctrl-single";
+                       reg = <0x0 0xff37e000 0x0 0x18>;
+                       #gpio-range-cells = <0x3>;
+                       #pinctrl-cells = <1>;
+                       pinctrl-single,register-width = <0x20>;
+                       pinctrl-single,function-mask = <0x7>;
+                       /* pin base, nr pins & gpio function */
+                       pinctrl-single,gpio-range = <&range 0 6 0>;
+
+                       sd_pmx_func: sd_pmx_func {
+                               pinctrl-single,pins = <
+                                       0x000 MUX_M1 /* SD_CLK */
+                                       0x004 MUX_M1 /* SD_CMD */
+                                       0x008 MUX_M1 /* SD_DATA0 */
+                                       0x00c MUX_M1 /* SD_DATA1 */
+                                       0x010 MUX_M1 /* SD_DATA2 */
+                                       0x014 MUX_M1 /* SD_DATA3 */
+                               >;
+                       };
+               };
+
+               /* [IOMG_FIX_000, IOMG_FIX_011] */
+               pmx2: pinmux@ff3b6000 {
+                       compatible = "pinctrl-single";
+                       reg = <0x0 0xff3b6000 0x0 0x30>;
+                       #pinctrl-cells = <1>;
+                       #gpio-range-cells = <0x3>;
+                       pinctrl-single,register-width = <0x20>;
+                       pinctrl-single,function-mask = <0x7>;
+                       /* pin base, nr pins & gpio function */
+                       pinctrl-single,gpio-range = <&range 0 12 0>;
+
+                       spi3_pmx_func: spi3_pmx_func {
+                               pinctrl-single,pins = <
+                                       0x008 MUX_M1 /* SPI3_CLK */
+                                       0x00c MUX_M1 /* SPI3_DI */
+                                       0x010 MUX_M1 /* SPI3_DO */
+                                       0x014 MUX_M1 /* SPI3_CS0_N */
+                               >;
+                       };
+               };
+
+               /* [IOMG_MMC1_000, IOMG_MMC1_005] */
+               pmx3: pinmux@ff3fd000 {
+                       compatible = "pinctrl-single";
+                       reg = <0x0 0xff3fd000 0x0 0x18>;
+                       #pinctrl-cells = <1>;
+                       #gpio-range-cells = <0x3>;
+                       pinctrl-single,register-width = <0x20>;
+                       pinctrl-single,function-mask = <0x7>;
+                       /* pin base, nr pins & gpio function */
+                       pinctrl-single,gpio-range = <&range 0 6 0>;
+
+                       sdio_pmx_func: sdio_pmx_func {
+                               pinctrl-single,pins = <
+                                       0x000 MUX_M1 /* SDIO_CLK */
+                                       0x004 MUX_M1 /* SDIO_CMD */
+                                       0x008 MUX_M1 /* SDIO_DATA0 */
+                                       0x00c MUX_M1 /* SDIO_DATA1 */
+                                       0x010 MUX_M1 /* SDIO_DATA2 */
+                                       0x014 MUX_M1 /* SDIO_DATA3 */
+                               >;
+                       };
+               };
+
+               /* [IOMG_AO_000, IOMG_AO_041] */
+               pmx4: pinmux@fff11000 {
+                       compatible = "pinctrl-single";
+                       reg = <0x0 0xfff11000 0x0 0xa8>;
+                       #pinctrl-cells = <1>;
+                       #gpio-range-cells = <0x3>;
+                       pinctrl-single,register-width = <0x20>;
+                       pinctrl-single,function-mask = <0x7>;
+                       /* pin base in node, nr pins & gpio function */
+                       pinctrl-single,gpio-range = <&range 0 42 0>;
+
+                       i2s2_pmx_func: i2s2_pmx_func {
+                               pinctrl-single,pins = <
+                                       0x044 MUX_M1 /* I2S2_DI */
+                                       0x048 MUX_M1 /* I2S2_DO */
+                                       0x04c MUX_M1 /* I2S2_XCLK */
+                                       0x050 MUX_M1 /* I2S2_XFS */
+                               >;
+                       };
+
+                       slimbus_pmx_func: slimbus_pmx_func {
+                               pinctrl-single,pins = <
+                                       0x02c MUX_M1 /* SLIMBUS_CLK */
+                                       0x030 MUX_M1 /* SLIMBUS_DATA */
+                               >;
+                       };
+
+                       i2c0_pmx_func: i2c0_pmx_func {
+                               pinctrl-single,pins = <
+                                       0x014 MUX_M1 /* I2C0_SCL */
+                                       0x018 MUX_M1 /* I2C0_SDA */
+                               >;
+                       };
+
+                       i2c1_pmx_func: i2c1_pmx_func {
+                               pinctrl-single,pins = <
+                                       0x01c MUX_M1 /* I2C1_SCL */
+                                       0x020 MUX_M1 /* I2C1_SDA */
+                               >;
+                       };
+
+                       i2c2_pmx_func: i2c2_pmx_func {
+                               pinctrl-single,pins = <
+                                       0x024 MUX_M1 /* I2C2_SCL */
+                                       0x028 MUX_M1 /* I2C2_SDA */
+                               >;
+                       };
+
+                       i2c7_pmx_func: i2c7_pmx_func {
+                               pinctrl-single,pins = <
+                                       0x024 MUX_M3 /* I2C7_SCL */
+                                       0x028 MUX_M3 /* I2C7_SDA */
+                               >;
+                       };
+
+                       spi2_pmx_func: spi2_pmx_func {
+                               pinctrl-single,pins = <
+                                       0x08c MUX_M1 /* SPI2_CLK */
+                                       0x090 MUX_M1 /* SPI2_DI */
+                                       0x094 MUX_M1 /* SPI2_DO */
+                                       0x098 MUX_M1 /* SPI2_CS0_N */
+                               >;
+                       };
+
+                       spi4_pmx_func: spi4_pmx_func {
+                               pinctrl-single,pins = <
+                                       0x08c MUX_M4 /* SPI4_CLK */
+                                       0x090 MUX_M4 /* SPI4_DI */
+                                       0x094 MUX_M4 /* SPI4_DO */
+                                       0x098 MUX_M4 /* SPI4_CS0_N */
+                               >;
+                       };
+
+                       i2s0_pmx_func: i2s0_pmx_func {
+                               pinctrl-single,pins = <
+                                       0x034 MUX_M1 /* I2S0_DI */
+                                       0x038 MUX_M1 /* I2S0_DO */
+                                       0x03c MUX_M1 /* I2S0_XCLK */
+                                       0x040 MUX_M1 /* I2S0_XFS */
+                               >;
+                       };
+               };
+
+               pmx5: pinmux@ff3fd800 {
+                       compatible = "pinconf-single";
+                       reg = <0x0 0xff3fd800 0x0 0x18>;
+                       #pinctrl-cells = <1>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       pinctrl-single,register-width = <32>;
+
+                       sdio_clk_cfg_func: sdio_clk_cfg_func {
+                               pinctrl-single,pins = <
+                                       0x000 0x0 /* SDIO_CLK */
+                               >;
+                               pinctrl-single,bias-pulldown = <
+                                       PULL_DIS
+                                       PULL_DOWN
+                                       PULL_DIS
+                                       PULL_DOWN
+                               >;
+                               pinctrl-single,bias-pullup = <
+                                       PULL_DIS
+                                       PULL_UP
+                                       PULL_DIS
+                                       PULL_UP
+                               >;
+                               pinctrl-single,drive-strength = <
+                                       DRIVE6_32MA
+                                       DRIVE6_MASK
+                               >;
+                       };
+
+                       sdio_cfg_func: sdio_cfg_func {
+                               pinctrl-single,pins = <
+                                       0x004 0x0 /* SDIO_CMD */
+                                       0x008 0x0 /* SDIO_DATA0 */
+                                       0x00c 0x0 /* SDIO_DATA1 */
+                                       0x010 0x0 /* SDIO_DATA2 */
+                                       0x014 0x0 /* SDIO_DATA3 */
+                               >;
+                               pinctrl-single,bias-pulldown = <
+                                       PULL_DIS
+                                       PULL_DOWN
+                                       PULL_DIS
+                                       PULL_DOWN
+                               >;
+                               pinctrl-single,bias-pullup = <
+                                       PULL_UP
+                                       PULL_UP
+                                       PULL_DIS
+                                       PULL_UP
+                               >;
+                               pinctrl-single,drive-strength = <
+                                       DRIVE6_19MA
+                                       DRIVE6_MASK
+                               >;
+                       };
+               };
+
+               pmx6: pinmux@ff37e800 {
+                       compatible = "pinconf-single";
+                       reg = <0x0 0xff37e800 0x0 0x18>;
+                       #pinctrl-cells = <1>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       pinctrl-single,register-width = <32>;
+
+                       sd_clk_cfg_func: sd_clk_cfg_func {
+                               pinctrl-single,pins = <
+                                       0x000 0x0 /* SD_CLK */
+                               >;
+                               pinctrl-single,bias-pulldown = <
+                                       PULL_DIS
+                                       PULL_DOWN
+                                       PULL_DIS
+                                       PULL_DOWN
+                               >;
+                               pinctrl-single,bias-pullup = <
+                                       PULL_DIS
+                                       PULL_UP
+                                       PULL_DIS
+                                       PULL_UP
+                               >;
+                               pinctrl-single,drive-strength = <
+                                       DRIVE6_32MA
+                                       DRIVE6_MASK
+                               >;
+                       };
+
+                       sd_cfg_func: sd_cfg_func {
+                               pinctrl-single,pins = <
+                                       0x004 0x0 /* SD_CMD */
+                                       0x008 0x0 /* SD_DATA0 */
+                                       0x00c 0x0 /* SD_DATA1 */
+                                       0x010 0x0 /* SD_DATA2 */
+                                       0x014 0x0 /* SD_DATA3 */
+                               >;
+                               pinctrl-single,bias-pulldown = <
+                                       PULL_DIS
+                                       PULL_DOWN
+                                       PULL_DIS
+                                       PULL_DOWN
+                               >;
+                               pinctrl-single,bias-pullup = <
+                                       PULL_UP
+                                       PULL_UP
+                                       PULL_DIS
+                                       PULL_UP
+                               >;
+                               pinctrl-single,drive-strength = <
+                                       DRIVE6_19MA
+                                       DRIVE6_MASK
+                               >;
+                       };
+               };
+       };
+};
index e0584423058336f46f33db3538ead300fde93eb7..f5d7f0889b41db47ad784f668845b3e5218c6b84 100644 (file)
 &usb_ehci {
        status = "ok";
 };
+
+&eth0 {
+       status = "ok";
+};
+
+&eth1 {
+       status = "ok";
+};
+
+&eth2 {
+       status = "ok";
+};
+
+&eth3 {
+       status = "ok";
+};
+
+&sas1 {
+       status = "ok";
+};
index 5144eb1c179d48929a0815f08fccdbb9e834f77a..283d7b532e161742c3d1be58e5e6621f21bae51a 100644 (file)
                compatible = "hisilicon,mbigen-v2";
                reg = <0x0 0xa0080000 0x0 0x10000>;
 
+               mbigen_pcie2_a: intc_pcie2_a {
+                       msi-parent = <&p0_its_dsa_a 0x40087>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       num-pins = <10>;
+               };
+
+               mbigen_sas1: intc_sas1 {
+                       msi-parent = <&p0_its_dsa_a 0x40000>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       num-pins = <128>;
+               };
+
+               mbigen_sas2: intc_sas2 {
+                       msi-parent = <&p0_its_dsa_a 0x40040>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       num-pins = <128>;
+               };
+
+               mbigen_smmu_pcie: intc_smmu_pcie {
+                       msi-parent = <&p0_its_dsa_a 0x40b0c>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       num-pins = <3>;
+               };
+
                mbigen_usb: intc_usb {
                        msi-parent = <&p0_its_dsa_a 0x40080>;
                        interrupt-controller;
                };
        };
 
+       p0_mbigen_dsa_a: interrupt-controller@c0080000 {
+               compatible = "hisilicon,mbigen-v2";
+               reg = <0x0 0xc0080000 0x0 0x10000>;
+
+               mbigen_dsaf0: intc_dsaf0 {
+                       msi-parent = <&p0_its_dsa_a 0x40800>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       num-pins = <409>;
+               };
+
+               mbigen_dsa_roce: intc-roce {
+                       msi-parent = <&p0_its_dsa_a 0x40B1E>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       num-pins = <34>;
+               };
+
+               mbigen_sas0: intc-sas0 {
+                       msi-parent = <&p0_its_dsa_a 0x40900>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       num-pins = <128>;
+               };
+
+               mbigen_smmu_dsa: intc_smmu_dsa {
+                       msi-parent = <&p0_its_dsa_a 0x40b20>;
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+                       num-pins = <3>;
+               };
+       };
+
        soc {
                compatible = "simple-bus";
                #address-cells = <2>;
                        dma-coherent;
                        status = "disabled";
                };
+
+               peri_c_subctrl: sub_ctrl_c@60000000 {
+                       compatible = "hisilicon,peri-subctrl","syscon";
+                       reg = <0 0x60000000 0x0 0x10000>;
+               };
+
+               dsa_subctrl: dsa_subctrl@c0000000 {
+                       compatible = "hisilicon,dsa-subctrl", "syscon";
+                       reg = <0x0 0xc0000000 0x0 0x10000>;
+               };
+
+               pcie_subctl: pcie_subctl@a0000000 {
+                       compatible = "hisilicon,pcie-sas-subctrl", "syscon";
+                       reg = <0x0 0xa0000000 0x0 0x10000>;
+               };
+
+               serdes_ctrl: sds_ctrl@c2200000 {
+                       compatible = "syscon";
+                       reg = <0 0xc2200000 0x0 0x80000>;
+               };
+
+               mdio@603c0000 {
+                       compatible = "hisilicon,hns-mdio";
+                       reg = <0x0 0x603c0000 0x0 0x1000>;
+                       subctrl-vbase = <&peri_c_subctrl 0x338 0xa38
+                                        0x531c 0x5a1c>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       phy0: ethernet-phy@0 {
+                               compatible = "ethernet-phy-ieee802.3-c22";
+                               reg = <0>;
+                       };
+
+                       phy1: ethernet-phy@1 {
+                               compatible = "ethernet-phy-ieee802.3-c22";
+                               reg = <1>;
+                       };
+               };
+
+               dsaf0: dsa@c7000000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "hisilicon,hns-dsaf-v2";
+                       mode = "6port-16rss";
+                       reg = <0x0 0xc5000000 0x0 0x890000
+                              0x0 0xc7000000 0x0 0x600000>;
+                       reg-names = "ppe-base", "dsaf-base";
+                       interrupt-parent = <&mbigen_dsaf0>;
+                       subctrl-syscon = <&dsa_subctrl>;
+                       reset-field-offset = <0>;
+                       interrupts =
+                       <576 1>, <577 1>, <578 1>, <579 1>, <580 1>,
+                       <581 1>, <582 1>, <583 1>, <584 1>, <585 1>,
+                       <586 1>, <587 1>, <588 1>, <589 1>, <590 1>,
+                       <591 1>, <592 1>, <593 1>, <594 1>, <595 1>,
+                       <596 1>, <597 1>, <598 1>, <599 1>, <600 1>,
+                       <960 1>, <961 1>, <962 1>, <963 1>, <964 1>,
+                       <965 1>, <966 1>, <967 1>, <968 1>, <969 1>,
+                       <970 1>, <971 1>, <972 1>, <973 1>, <974 1>,
+                       <975 1>, <976 1>, <977 1>, <978 1>, <979 1>,
+                       <980 1>, <981 1>, <982 1>, <983 1>, <984 1>,
+                       <985 1>, <986 1>, <987 1>, <988 1>, <989 1>,
+                       <990 1>, <991 1>, <992 1>, <993 1>, <994 1>,
+                       <995 1>, <996 1>, <997 1>, <998 1>, <999 1>,
+                       <1000 1>, <1001 1>, <1002 1>, <1003 1>, <1004 1>,
+                       <1005 1>, <1006 1>, <1007 1>, <1008 1>, <1009 1>,
+                       <1010 1>, <1011 1>, <1012 1>, <1013 1>, <1014 1>,
+                       <1015 1>, <1016 1>, <1017 1>, <1018 1>, <1019 1>,
+                       <1020 1>, <1021 1>, <1022 1>, <1023 1>, <1024 1>,
+                       <1025 1>, <1026 1>, <1027 1>, <1028 1>, <1029 1>,
+                       <1030 1>, <1031 1>, <1032 1>, <1033 1>, <1034 1>,
+                       <1035 1>, <1036 1>, <1037 1>, <1038 1>, <1039 1>,
+                       <1040 1>, <1041 1>, <1042 1>, <1043 1>, <1044 1>,
+                       <1045 1>, <1046 1>, <1047 1>, <1048 1>, <1049 1>,
+                       <1050 1>, <1051 1>, <1052 1>, <1053 1>, <1054 1>,
+                       <1055 1>, <1056 1>, <1057 1>, <1058 1>, <1059 1>,
+                       <1060 1>, <1061 1>, <1062 1>, <1063 1>, <1064 1>,
+                       <1065 1>, <1066 1>, <1067 1>, <1068 1>, <1069 1>,
+                       <1070 1>, <1071 1>, <1072 1>, <1073 1>, <1074 1>,
+                       <1075 1>, <1076 1>, <1077 1>, <1078 1>, <1079 1>,
+                       <1080 1>, <1081 1>, <1082 1>, <1083 1>, <1084 1>,
+                       <1085 1>, <1086 1>, <1087 1>, <1088 1>, <1089 1>,
+                       <1090 1>, <1091 1>, <1092 1>, <1093 1>, <1094 1>,
+                       <1095 1>, <1096 1>, <1097 1>, <1098 1>, <1099 1>,
+                       <1100 1>, <1101 1>, <1102 1>, <1103 1>, <1104 1>,
+                       <1105 1>, <1106 1>, <1107 1>, <1108 1>, <1109 1>,
+                       <1110 1>, <1111 1>, <1112 1>, <1113 1>, <1114 1>,
+                       <1115 1>, <1116 1>, <1117 1>, <1118 1>, <1119 1>,
+                       <1120 1>, <1121 1>, <1122 1>, <1123 1>, <1124 1>,
+                       <1125 1>, <1126 1>, <1127 1>, <1128 1>, <1129 1>,
+                       <1130 1>, <1131 1>, <1132 1>, <1133 1>, <1134 1>,
+                       <1135 1>, <1136 1>, <1137 1>, <1138 1>, <1139 1>,
+                       <1140 1>, <1141 1>, <1142 1>, <1143 1>, <1144 1>,
+                       <1145 1>, <1146 1>, <1147 1>, <1148 1>, <1149 1>,
+                       <1150 1>, <1151 1>, <1152 1>, <1153 1>, <1154 1>,
+                       <1155 1>, <1156 1>, <1157 1>, <1158 1>, <1159 1>,
+                       <1160 1>, <1161 1>, <1162 1>, <1163 1>, <1164 1>,
+                       <1165 1>, <1166 1>, <1167 1>, <1168 1>, <1169 1>,
+                       <1170 1>, <1171 1>, <1172 1>, <1173 1>, <1174 1>,
+                       <1175 1>, <1176 1>, <1177 1>, <1178 1>, <1179 1>,
+                       <1180 1>, <1181 1>, <1182 1>, <1183 1>, <1184 1>,
+                       <1185 1>, <1186 1>, <1187 1>, <1188 1>, <1189 1>,
+                       <1190 1>, <1191 1>, <1192 1>, <1193 1>, <1194 1>,
+                       <1195 1>, <1196 1>, <1197 1>, <1198 1>, <1199 1>,
+                       <1200 1>, <1201 1>, <1202 1>, <1203 1>, <1204 1>,
+                       <1205 1>, <1206 1>, <1207 1>, <1208 1>, <1209 1>,
+                       <1210 1>, <1211 1>, <1212 1>, <1213 1>, <1214 1>,
+                       <1215 1>, <1216 1>, <1217 1>, <1218 1>, <1219 1>,
+                       <1220 1>, <1221 1>, <1222 1>, <1223 1>, <1224 1>,
+                       <1225 1>, <1226 1>, <1227 1>, <1228 1>, <1229 1>,
+                       <1230 1>, <1231 1>, <1232 1>, <1233 1>, <1234 1>,
+                       <1235 1>, <1236 1>, <1237 1>, <1238 1>, <1239 1>,
+                       <1240 1>, <1241 1>, <1242 1>, <1243 1>, <1244 1>,
+                       <1245 1>, <1246 1>, <1247 1>, <1248 1>, <1249 1>,
+                       <1250 1>, <1251 1>, <1252 1>, <1253 1>, <1254 1>,
+                       <1255 1>, <1256 1>, <1257 1>, <1258 1>, <1259 1>,
+                       <1260 1>, <1261 1>, <1262 1>, <1263 1>, <1264 1>,
+                       <1265 1>, <1266 1>, <1267 1>, <1268 1>, <1269 1>,
+                       <1270 1>, <1271 1>, <1272 1>, <1273 1>, <1274 1>,
+                       <1275 1>, <1276 1>, <1277 1>, <1278 1>, <1279 1>,
+                       <1280 1>, <1281 1>, <1282 1>, <1283 1>, <1284 1>,
+                       <1285 1>, <1286 1>, <1287 1>, <1288 1>, <1289 1>,
+                       <1290 1>, <1291 1>, <1292 1>, <1293 1>, <1294 1>,
+                       <1295 1>, <1296 1>, <1297 1>, <1298 1>, <1299 1>,
+                       <1300 1>, <1301 1>, <1302 1>, <1303 1>, <1304 1>,
+                       <1305 1>, <1306 1>, <1307 1>, <1308 1>, <1309 1>,
+                       <1310 1>, <1311 1>, <1312 1>, <1313 1>, <1314 1>,
+                       <1315 1>, <1316 1>, <1317 1>, <1318 1>, <1319 1>,
+                       <1320 1>, <1321 1>, <1322 1>, <1323 1>, <1324 1>,
+                       <1325 1>, <1326 1>, <1327 1>, <1328 1>, <1329 1>,
+                       <1330 1>, <1331 1>, <1332 1>, <1333 1>, <1334 1>,
+                       <1335 1>, <1336 1>, <1337 1>, <1338 1>, <1339 1>,
+                       <1340 1>, <1341 1>, <1342 1>, <1343 1>;
+
+                       desc-num = <0x400>;
+                       buf-size = <0x1000>;
+                       dma-coherent;
+
+                       port@0 {
+                               reg = <0>;
+                               serdes-syscon = <&serdes_ctrl>;
+                               port-rst-offset = <0>;
+                               port-mode-offset = <0>;
+                               mc-mac-mask = [ff f0 00 00 00 00];
+                               media-type = "fiber";
+                       };
+
+                       port@1 {
+                               reg = <1>;
+                               serdes-syscon= <&serdes_ctrl>;
+                               port-rst-offset = <1>;
+                               port-mode-offset = <1>;
+                               mc-mac-mask = [ff f0 00 00 00 00];
+                               media-type = "fiber";
+                       };
+
+                       port@4 {
+                               reg = <4>;
+                               phy-handle = <&phy0>;
+                               serdes-syscon= <&serdes_ctrl>;
+                               port-rst-offset = <4>;
+                               port-mode-offset = <2>;
+                               mc-mac-mask = [ff f0 00 00 00 00];
+                               media-type = "copper";
+                       };
+
+                       port@5 {
+                               reg = <5>;
+                               phy-handle = <&phy1>;
+                               serdes-syscon= <&serdes_ctrl>;
+                               port-rst-offset = <5>;
+                               port-mode-offset = <3>;
+                               mc-mac-mask = [ff f0 00 00 00 00];
+                               media-type = "copper";
+                       };
+               };
+
+               eth0: ethernet@4{
+                       compatible = "hisilicon,hns-nic-v2";
+                       ae-handle = <&dsaf0>;
+                       port-idx-in-ae = <4>;
+                       local-mac-address = [00 00 00 00 00 00];
+                       status = "disabled";
+                       dma-coherent;
+               };
+
+               eth1: ethernet@5{
+                       compatible = "hisilicon,hns-nic-v2";
+                       ae-handle = <&dsaf0>;
+                       port-idx-in-ae = <5>;
+                       local-mac-address = [00 00 00 00 00 00];
+                       status = "disabled";
+                       dma-coherent;
+               };
+
+               eth2: ethernet@0{
+                       compatible = "hisilicon,hns-nic-v2";
+                       ae-handle = <&dsaf0>;
+                       port-idx-in-ae = <0>;
+                       local-mac-address = [00 00 00 00 00 00];
+                       status = "disabled";
+                       dma-coherent;
+               };
+
+               eth3: ethernet@1{
+                       compatible = "hisilicon,hns-nic-v2";
+                       ae-handle = <&dsaf0>;
+                       port-idx-in-ae = <1>;
+                       local-mac-address = [00 00 00 00 00 00];
+                       status = "disabled";
+                       dma-coherent;
+               };
+
+               infiniband@c4000000 {
+                       compatible = "hisilicon,hns-roce-v1";
+                       reg = <0x0 0xc4000000 0x0 0x100000>;
+                       dma-coherent;
+                       eth-handle = <&eth2 &eth3 0 0 &eth0 &eth1>;
+                       dsaf-handle = <&dsaf0>;
+                       node-guid = [00 9A CD 00 00 01 02 03];
+                       #address-cells = <2>;
+                       #size-cells = <2>;
+                       interrupt-parent = <&mbigen_dsa_roce>;
+                       interrupts = <722 1>,
+                                    <723 1>,
+                                    <724 1>,
+                                    <725 1>,
+                                    <726 1>,
+                                    <727 1>,
+                                    <728 1>,
+                                    <729 1>,
+                                    <730 1>,
+                                    <731 1>,
+                                    <732 1>,
+                                    <733 1>,
+                                    <734 1>,
+                                    <735 1>,
+                                    <736 1>,
+                                    <737 1>,
+                                    <738 1>,
+                                    <739 1>,
+                                    <740 1>,
+                                    <741 1>,
+                                    <742 1>,
+                                    <743 1>,
+                                    <744 1>,
+                                    <745 1>,
+                                    <746 1>,
+                                    <747 1>,
+                                    <748 1>,
+                                    <749 1>,
+                                    <750 1>,
+                                    <751 1>,
+                                    <752 1>,
+                                    <753 1>,
+                                    <785 1>,
+                                    <754 4>;
+
+                       interrupt-names = "hns-roce-comp-0",
+                                         "hns-roce-comp-1",
+                                         "hns-roce-comp-2",
+                                         "hns-roce-comp-3",
+                                         "hns-roce-comp-4",
+                                         "hns-roce-comp-5",
+                                         "hns-roce-comp-6",
+                                         "hns-roce-comp-7",
+                                         "hns-roce-comp-8",
+                                         "hns-roce-comp-9",
+                                         "hns-roce-comp-10",
+                                         "hns-roce-comp-11",
+                                         "hns-roce-comp-12",
+                                         "hns-roce-comp-13",
+                                         "hns-roce-comp-14",
+                                         "hns-roce-comp-15",
+                                         "hns-roce-comp-16",
+                                         "hns-roce-comp-17",
+                                         "hns-roce-comp-18",
+                                         "hns-roce-comp-19",
+                                         "hns-roce-comp-20",
+                                         "hns-roce-comp-21",
+                                         "hns-roce-comp-22",
+                                         "hns-roce-comp-23",
+                                         "hns-roce-comp-24",
+                                         "hns-roce-comp-25",
+                                         "hns-roce-comp-26",
+                                         "hns-roce-comp-27",
+                                         "hns-roce-comp-28",
+                                         "hns-roce-comp-29",
+                                         "hns-roce-comp-30",
+                                         "hns-roce-comp-31",
+                                         "hns-roce-async",
+                                         "hns-roce-common";
+               };
+
+               sas0: sas@c3000000 {
+                       compatible = "hisilicon,hip07-sas-v2";
+                       reg = <0 0xc3000000 0 0x10000>;
+                       sas-addr = [50 01 88 20 16 00 00 00];
+                       hisilicon,sas-syscon = <&dsa_subctrl>;
+                       ctrl-reset-reg = <0xa60>;
+                       ctrl-reset-sts-reg = <0x5a30>;
+                       ctrl-clock-ena-reg = <0x338>;
+                       queue-count = <16>;
+                       phy-count = <8>;
+                       dma-coherent;
+                       interrupt-parent = <&mbigen_sas0>;
+                       interrupts = <64 4>,<65 4>,<66 4>,<67 4>,<68 4>,
+                                    <69 4>,<70 4>,<71 4>,<72 4>,<73 4>,
+                                    <74 4>,<75 4>,<76 4>,<77 4>,<78 4>,
+                                    <79 4>,<80 4>,<81 4>,<82 4>,<83 4>,
+                                    <84 4>,<85 4>,<86 4>,<87 4>,<88 4>,
+                                    <89 4>,<90 4>,<91 4>,<92 4>,<93 4>,
+                                    <94 4>,<95 4>,<96 4>,<97 4>,<98 4>,
+                                    <99 4>,<100 4>,<101 4>,<102 4>,<103 4>,
+                                    <104 4>,<105 4>,<106 4>,<107 4>,<108 4>,
+                                    <109 4>,<110 4>,<111 4>,<112 4>,<113 4>,
+                                    <114 4>,<115 4>,<116 4>,<117 4>,<118 4>,
+                                    <119 4>,<120 4>,<121 4>,<122 4>,<123 4>,
+                                    <124 4>,<125 4>,<126 4>,<127 4>,<128 4>,
+                                    <129 4>,<130 4>,<131 4>,<132 4>,<133 4>,
+                                    <134 4>,<135 4>,<136 4>,<137 4>,<138 4>,
+                                    <139 4>,<140 4>,<141 4>,<142 4>,<143 4>,
+                                    <144 4>,<145 4>,<146 4>,<147 4>,<148 4>,
+                                    <149 4>,<150 4>,<151 4>,<152 4>,<153 4>,
+                                    <154 4>,<155 4>,<156 4>,<157 4>,<158 4>,
+                                    <159 4>,<601 1>,<602 1>,<603 1>,<604 1>,
+                                    <605 1>,<606 1>,<607 1>,<608 1>,<609 1>,
+                                    <610 1>,<611 1>,<612 1>,<613 1>,<614 1>,
+                                    <615 1>,<616 1>,<617 1>,<618 1>,<619 1>,
+                                    <620 1>,<621 1>,<622 1>,<623 1>,<624 1>,
+                                    <625 1>,<626 1>,<627 1>,<628 1>,<629 1>,
+                                    <630 1>,<631 1>,<632 1>;
+                       status = "disabled";
+               };
+
+               sas1: sas@a2000000 {
+                       compatible = "hisilicon,hip07-sas-v2";
+                       reg = <0 0xa2000000 0 0x10000>;
+                       sas-addr = [50 01 88 20 16 00 00 00];
+                       hisilicon,sas-syscon = <&pcie_subctl>;
+                       hip06-sas-v2-quirk-amt;
+                       ctrl-reset-reg = <0xa18>;
+                       ctrl-reset-sts-reg = <0x5a0c>;
+                       ctrl-clock-ena-reg = <0x318>;
+                       queue-count = <16>;
+                       phy-count = <8>;
+                       dma-coherent;
+                       interrupt-parent = <&mbigen_sas1>;
+                       interrupts = <64 4>,<65 4>,<66 4>,<67 4>,<68 4>,
+                                    <69 4>,<70 4>,<71 4>,<72 4>,<73 4>,
+                                    <74 4>,<75 4>,<76 4>,<77 4>,<78 4>,
+                                    <79 4>,<80 4>,<81 4>,<82 4>,<83 4>,
+                                    <84 4>,<85 4>,<86 4>,<87 4>,<88 4>,
+                                    <89 4>,<90 4>,<91 4>,<92 4>,<93 4>,
+                                    <94 4>,<95 4>,<96 4>,<97 4>,<98 4>,
+                                    <99 4>,<100 4>,<101 4>,<102 4>,<103 4>,
+                                    <104 4>,<105 4>,<106 4>,<107 4>,<108 4>,
+                                    <109 4>,<110 4>,<111 4>,<112 4>,<113 4>,
+                                    <114 4>,<115 4>,<116 4>,<117 4>,<118 4>,
+                                    <119 4>,<120 4>,<121 4>,<122 4>,<123 4>,
+                                    <124 4>,<125 4>,<126 4>,<127 4>,<128 4>,
+                                    <129 4>,<130 4>,<131 4>,<132 4>,<133 4>,
+                                    <134 4>,<135 4>,<136 4>,<137 4>,<138 4>,
+                                    <139 4>,<140 4>,<141 4>,<142 4>,<143 4>,
+                                    <144 4>,<145 4>,<146 4>,<147 4>,<148 4>,
+                                    <149 4>,<150 4>,<151 4>,<152 4>,<153 4>,
+                                    <154 4>,<155 4>,<156 4>,<157 4>,<158 4>,
+                                    <159 4>,<576 1>,<577 1>,<578 1>,<579 1>,
+                                    <580 1>,<581 1>,<582 1>,<583 1>,<584 1>,
+                                    <585 1>,<586 1>,<587 1>,<588 1>,<589 1>,
+                                    <590 1>,<591 1>,<592 1>,<593 1>,<594 1>,
+                                    <595 1>,<596 1>,<597 1>,<598 1>,<599 1>,
+                                    <600 1>,<601 1>,<602 1>,<603 1>,<604 1>,
+                                    <605 1>,<606 1>,<607 1>;
+                       status = "disabled";
+               };
+
+               sas2: sas@a3000000 {
+                       compatible = "hisilicon,hip07-sas-v2";
+                       reg = <0 0xa3000000 0 0x10000>;
+                       sas-addr = [50 01 88 20 16 00 00 00];
+                       hisilicon,sas-syscon = <&pcie_subctl>;
+                       ctrl-reset-reg = <0xae0>;
+                       ctrl-reset-sts-reg = <0x5a70>;
+                       ctrl-clock-ena-reg = <0x3a8>;
+                       queue-count = <16>;
+                       phy-count = <9>;
+                       dma-coherent;
+                       interrupt-parent = <&mbigen_sas2>;
+                       interrupts = <192 4>,<193 4>,<194 4>,<195 4>,<196 4>,
+                                    <197 4>,<198 4>,<199 4>,<200 4>,<201 4>,
+                                    <202 4>,<203 4>,<204 4>,<205 4>,<206 4>,
+                                    <207 4>,<208 4>,<209 4>,<210 4>,<211 4>,
+                                    <212 4>,<213 4>,<214 4>,<215 4>,<216 4>,
+                                    <217 4>,<218 4>,<219 4>,<220 4>,<221 4>,
+                                    <222 4>,<223 4>,<224 4>,<225 4>,<226 4>,
+                                    <227 4>,<228 4>,<229 4>,<230 4>,<231 4>,
+                                    <232 4>,<233 4>,<234 4>,<235 4>,<236 4>,
+                                    <237 4>,<238 4>,<239 4>,<240 4>,<241 4>,
+                                    <242 4>,<243 4>,<244 4>,<245 4>,<246 4>,
+                                    <247 4>,<248 4>,<249 4>,<250 4>,<251 4>,
+                                    <252 4>,<253 4>,<254 4>,<255 4>,<256 4>,
+                                    <257 4>,<258 4>,<259 4>,<260 4>,<261 4>,
+                                    <262 4>,<263 4>,<264 4>,<265 4>,<266 4>,
+                                    <267 4>,<268 4>,<269 4>,<270 4>,<271 4>,
+                                    <272 4>,<273 4>,<274 4>,<275 4>,<276 4>,
+                                    <277 4>,<278 4>,<279 4>,<280 4>,<281 4>,
+                                    <282 4>,<283 4>,<284 4>,<285 4>,<286 4>,
+                                    <287 4>,<608 1>,<609 1>,<610 1>,<611 1>,
+                                    <612 1>,<613 1>,<614 1>,<615 1>,<616 1>,
+                                    <617 1>,<618 1>,<619 1>,<620 1>,<621 1>,
+                                    <622 1>,<623 1>,<624 1>,<625 1>,<626 1>,
+                                    <627 1>,<628 1>,<629 1>,<630 1>,<631 1>,
+                                    <632 1>,<633 1>,<634 1>,<635 1>,<636 1>,
+                                    <637 1>,<638 1>,<639 1>;
+                       status = "disabled";
+               };
        };
 };
diff --git a/arch/arm64/boot/dts/include/dt-bindings b/arch/arm64/boot/dts/include/dt-bindings
deleted file mode 120000 (symlink)
index 08c00e4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../include/dt-bindings
\ No newline at end of file
index a07a0c1cd4e6ae1ea07eb08f6387dd964a210da6..a89855f57091fac35d3ba4b9821fd2a902f5ed77 100644 (file)
@@ -46,6 +46,7 @@
 
 /dts-v1/;
 
+#include <dt-bindings/gpio/gpio.h>
 #include "armada-372x.dtsi"
 
 / {
                device_type = "memory";
                reg = <0x00000000 0x00000000 0x00000000 0x20000000>;
        };
+
+       exp_usb3_vbus: usb3-vbus {
+               compatible = "regulator-fixed";
+               regulator-name = "usb3-vbus";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               enable-active-high;
+               regulator-always-on;
+               gpio = <&gpio_exp 1 GPIO_ACTIVE_HIGH>;
+       };
+
+       usb3_phy: usb3-phy {
+               compatible = "usb-nop-xceiv";
+               vcc-supply = <&exp_usb3_vbus>;
+       };
 };
 
 &i2c0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&i2c1_pins>;
        status = "okay";
+
+       gpio_exp: pca9555@22 {
+               compatible = "nxp,pca9555";
+               gpio-controller;
+               #gpio-cells = <2>;
+
+               reg = <0x22>;
+               /*
+                * IO0_0: PWR_EN_USB2   IO1_0: PWR_EN_VTT
+                * IO0_1: PWR_EN_USB23  IO1_1: MPCIE_WDISABLE
+                * IO0_2: PWR_EN_SATA   IO1_2: RGMII_DEV_RSTN
+                * IO0_3: PWR_EN_PCIE   IO1_3: SGMII_DEV_RSTN
+                * IO0_4: PWR_EN_SD
+                * IO0_5: PWR_EN_EMMC
+                * IO0_6: PWR_EN_RGMII  IO1_6: SATA_USB3.0_SEL
+                * IO0_7: PWR_EN_SGMII  IO1_7: PWR_MCI_PS
+                */
+       };
+
+       rtc@68  {
+               /* PT7C4337A from pericom fully compatible with the ds1337 */
+               compatible = "dallas,ds1337";
+               reg = <0x68>;
+       };
 };
 
 /* CON3 */
 
 &spi0 {
        status = "okay";
+       pinctrl-names = "default";
+       pinctrl-0 = <&spi_quad_pins>;
 
        m25p80@0 {
                compatible = "jedec,spi-nor";
 
 /* Exported on the micro USB connector CON32 through an FTDI */
 &uart0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&uart1_pins>;
+       status = "okay";
+};
+
+&sdhci0 {
+       non-removable;
+       bus-width = <8>;
+       mmc-ddr-1_8v;
+       mmc-hs400-1_8v;
+       marvell,pad-type = "fixed-1-8v";
        status = "okay";
 };
 
 /* CON31 */
 &usb3 {
        status = "okay";
+       usb-phy = <&usb3_phy>;
 };
 
 /* CON17 (PCIe) / CON12 (mini-PCIe) */
 };
 
 &eth0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&rgmii_pins>;
        phy-mode = "rgmii-id";
        phy = <&phy0>;
        status = "okay";
index 42747b7db6839dcdd96deb64011138fc65c5750a..4d495ec39202d0c34b46996598466ec87d116eea 100644 (file)
                        i2c0: i2c@11000 {
                                compatible = "marvell,armada-3700-i2c";
                                reg = <0x11000 0x24>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
                                clocks = <&nb_periph_clk 10>;
                                interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
                                mrvl,i2c-fast-mode;
                        i2c1: i2c@11080 {
                                compatible = "marvell,armada-3700-i2c";
                                reg = <0x11080 0x24>;
+                               #address-cells = <1>;
+                               #size-cells = <0>;
                                clocks = <&nb_periph_clk 9>;
                                interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
                                mrvl,i2c-fast-mode;
                                #clock-cells = <1>;
                        };
 
-                       gpio1: gpio@13800 {
-                               compatible = "marvell,mvebu-gpio-3700",
+                       pinctrl_nb: pinctrl@13800 {
+                               compatible = "marvell,armada3710-nb-pinctrl",
                                "syscon", "simple-mfd";
-                               reg = <0x13800 0x500>;
+                               reg = <0x13800 0x100>, <0x13C00 0x20>;
+                               gpionb: gpio {
+                                       #gpio-cells = <2>;
+                                       gpio-ranges = <&pinctrl_nb 0 0 36>;
+                                       gpio-controller;
+                                       interrupts =
+                                       <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>,
+                                       <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>,
+                                       <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
+                                       <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
+                                       <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
+                                       <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
+                                       <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>,
+                                       <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
+                                       <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>,
+                                       <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>,
+                                       <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>,
+                                       <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>;
+
+                               };
 
                                xtalclk: xtal-clk {
                                        compatible = "marvell,armada-3700-xtal-clock";
                                        clock-output-names = "xtal";
                                        #clock-cells = <0>;
                                };
+
+                               spi_quad_pins: spi-quad-pins {
+                                       groups = "spi_quad";
+                                       function = "spi";
+                               };
+
+                               i2c1_pins: i2c1-pins {
+                                       groups = "i2c1";
+                                       function = "i2c";
+                               };
+
+                               i2c2_pins: i2c2-pins {
+                                       groups = "i2c2";
+                                       function = "i2c";
+                               };
+
+                               uart1_pins: uart1-pins {
+                                       groups = "uart1";
+                                       function = "uart";
+                               };
+
+                               uart2_pins: uart2-pins {
+                                       groups = "uart2";
+                                       function = "uart";
+                               };
+                       };
+
+                       pinctrl_sb: pinctrl@18800 {
+                               compatible = "marvell,armada3710-sb-pinctrl",
+                               "syscon", "simple-mfd";
+                               reg = <0x18800 0x100>, <0x18C00 0x20>;
+                               gpiosb: gpio {
+                                       #gpio-cells = <2>;
+                                       gpio-ranges = <&pinctrl_sb 0 0 29>;
+                                       gpio-controller;
+                                       interrupts =
+                                       <GIC_SPI 160 IRQ_TYPE_LEVEL_HIGH>,
+                                       <GIC_SPI 159 IRQ_TYPE_LEVEL_HIGH>,
+                                       <GIC_SPI 158 IRQ_TYPE_LEVEL_HIGH>,
+                                       <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>,
+                                       <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>;
+                               };
+
+                               rgmii_pins: mii-pins {
+                                       groups = "rgmii";
+                                       function = "mii";
+                               };
+
                        };
 
                        eth0: ethernet@30000 {
                                compatible = "marvell,armada3700-xhci",
                                "generic-xhci";
                                reg = <0x58000 0x4000>;
-                               interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&sb_periph_clk 12>;
                                status = "disabled";
                        };
 
                                };
                        };
 
+                       sdhci0: sdhci@d8000 {
+                               compatible = "marvell,armada-3700-sdhci",
+                               "marvell,sdhci-xenon";
+                               reg = <0xd8000 0x300
+                                      0x17808 0x4>;
+                               interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&nb_periph_clk 0>;
+                               clock-names = "core";
+                               status = "disabled";
+                       };
+
                        sata: sata@e0000 {
                                compatible = "marvell,armada-3700-ahci";
                                reg = <0xe0000 0x2000>;
index 070b589680c59cb4d355ad680dea15a84d011660..12442329b80f1147da2c59e4ab0dc91f30b5d5e3 100644 (file)
 &cpm_usb3_1 {
        status = "okay";
 };
+
+&ap_sdhci0 {
+       status = "okay";
+       bus-width = <4>;
+       no-1-8-v;
+       non-removable;
+};
+
+&cpm_sdhci0 {
+       status = "okay";
+       bus-width = <4>;
+       no-1-8-v;
+       non-removable;
+};
+
+&cpm_mdio {
+       phy0: ethernet-phy@0 {
+               reg = <0>;
+       };
+       phy1: ethernet-phy@1 {
+               reg = <1>;
+       };
+};
+
+&cpm_ethernet {
+       status = "okay";
+};
+
+&cpm_eth1 {
+       status = "okay";
+       phy = <&phy0>;
+       phy-mode = "sgmii";
+};
+
+&cpm_eth2 {
+       status = "okay";
+       phy = <&phy1>;
+       phy-mode = "rgmii-id";
+};
+
+&cpm_crypto {
+       status = "okay";
+};
index 048e5cf5160e9740896e3057b08120163cc78e1c..7c08f1f28d9e05ab95c388b6aec41193970f52c1 100644 (file)
        compatible = "marvell,armada8020", "marvell,armada-ap806-dual",
                     "marvell,armada-ap806";
 };
+
+/* The RTC requires external oscillator. But on Aramda 80x0, the RTC clock
+ * in CP master is not connected (by package) to the oscillator. So
+ * disable it. However, the RTC clock in CP slave is connected to the
+ * oscillator so this one is let enabled.
+ */
+
+&cpm_rtc {
+       status = "disabled";
+};
index 6e6f182fb2971a895efded70f6e4ae7b7287bd39..dc0d084005b2ef1b23bc97bf8b940e75eda50576 100644 (file)
        status = "okay";
 };
 
+&cpm_mdio {
+       phy1: ethernet-phy@1 {
+               reg = <1>;
+       };
+};
+
+&cpm_ethernet {
+       status = "okay";
+};
+
+&cpm_eth2 {
+       status = "okay";
+       phy = <&phy1>;
+       phy-mode = "rgmii-id";
+};
+
+&cpm_crypto {
+       status = "okay";
+};
+
 /* CON5 on CP1 expansion */
 &cps_pcie2 {
        status = "okay";
 &cps_usb3_1 {
        status = "okay";
 };
+
+&ap_sdhci0 {
+       status = "okay";
+       bus-width = <4>;
+       non-removable;
+};
+
+&cpm_sdhci0 {
+       status = "okay";
+       bus-width = <8>;
+       non-removable;
+};
index 9c1b28c476838fc20009b35740d825627b0ff5c3..33813a75bc309032cff84b51f97269c1c15abddc 100644 (file)
        compatible = "marvell,armada8040", "marvell,armada-ap806-quad",
                     "marvell,armada-ap806";
 };
+
+/* The RTC requires external oscillator. But on Aramda 80x0, the RTC clock
+ * in CP master is not connected (by package) to the oscillator. So
+ * disable it. However, the RTC clock in CP slave is connected to the
+ * oscillator so this one is let enabled.
+ */
+&cpm_rtc {
+       status = "disabled";
+};
index 5019c8f4acd03f06556f893e23182a0256c8db7c..fe41bf9c301e2f81e18da871b53f41e4f2ca77f0 100644 (file)
 
                        };
 
+                       ap_sdhci0: sdhci@6e0000 {
+                               compatible = "marvell,armada-ap806-sdhci";
+                               reg = <0x6e0000 0x300>;
+                               interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+                               clock-names = "core";
+                               clocks = <&ap_syscon 4>;
+                               dma-coherent;
+                               marvell,xenon-phy-slow-mode;
+                               status = "disabled";
+                       };
+
                        ap_syscon: system-controller@6f4000 {
                                compatible = "marvell,ap806-system-controller",
                                             "syscon";
index 3a99c36433d6f9bb0c82c13fd68aa10dfb0f037a..ac8df5201cd656d70073bc03cd13436435b79c66 100644 (file)
                        interrupt-parent = <&gic>;
                        ranges = <0x0 0x0 0xf2000000 0x2000000>;
 
+                       cpm_ethernet: ethernet@0 {
+                               compatible = "marvell,armada-7k-pp22";
+                               reg = <0x0 0x100000>, <0x129000 0xb000>;
+                               clocks = <&cpm_syscon0 1 3>, <&cpm_syscon0 1 9>, <&cpm_syscon0 1 5>;
+                               clock-names = "pp_clk", "gop_clk", "mg_clk";
+                               status = "disabled";
+                               dma-coherent;
+
+                               cpm_eth0: eth0 {
+                                       interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+                                       port-id = <0>;
+                                       gop-port-id = <0>;
+                                       status = "disabled";
+                               };
+
+                               cpm_eth1: eth1 {
+                                       interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+                                       port-id = <1>;
+                                       gop-port-id = <2>;
+                                       status = "disabled";
+                               };
+
+                               cpm_eth2: eth2 {
+                                       interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+                                       port-id = <2>;
+                                       gop-port-id = <3>;
+                                       status = "disabled";
+                               };
+                       };
+
+                       cpm_mdio: mdio@12a200 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               compatible = "marvell,orion-mdio";
+                               reg = <0x12a200 0x10>;
+                       };
+
                        cpm_syscon0: system-controller@440000 {
                                compatible = "marvell,cp110-system-controller0",
                                             "syscon";
                                        "cpm-usb3dev", "cpm-eip150", "cpm-eip197";
                        };
 
+                       cpm_rtc: rtc@284000 {
+                               compatible = "marvell,armada-8k-rtc";
+                               reg = <0x284000 0x20>, <0x284080 0x24>;
+                               reg-names = "rtc", "rtc-soc";
+                               interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+                       };
+
                        cpm_sata0: sata@540000 {
                                compatible = "marvell,armada-8k-ahci",
                                             "generic-ahci";
                                clocks = <&cpm_syscon0 1 25>;
                                status = "okay";
                        };
+
+                       cpm_sdhci0: sdhci@780000 {
+                               compatible = "marvell,armada-cp110-sdhci";
+                               reg = <0x780000 0x300>;
+                               interrupts = <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
+                               clock-names = "core";
+                               clocks = <&cpm_syscon0 1 4>;
+                               dma-coherent;
+                               status = "disabled";
+                       };
+
+                       cpm_crypto: crypto@800000 {
+                               compatible = "inside-secure,safexcel-eip197";
+                               reg = <0x800000 0x200000>;
+                               interrupts = <GIC_SPI 34 (IRQ_TYPE_EDGE_RISING
+                               | IRQ_TYPE_LEVEL_HIGH)>,
+                                            <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
+                                            <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
+                                            <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
+                                            <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>,
+                                            <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-names = "mem", "ring0", "ring1",
+                               "ring2", "ring3", "eip";
+                               clocks = <&cpm_syscon0 1 26>;
+                               status = "disabled";
+                       };
                };
 
                cpm_pcie0: pcie@f2600000 {
index 9e09c4d3b6bd8412deb29353a6d67a9fbe35beb2..7740a75a823084d027ffab1c02d221f3083dea87 100644 (file)
                        interrupt-parent = <&gic>;
                        ranges = <0x0 0x0 0xf4000000 0x2000000>;
 
+                       cps_rtc: rtc@284000 {
+                               compatible = "marvell,armada-8k-rtc";
+                               reg = <0x284000 0x20>, <0x284080 0x24>;
+                               reg-names = "rtc", "rtc-soc";
+                               interrupts = <GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+                       };
+
+                       cps_ethernet: ethernet@0 {
+                               compatible = "marvell,armada-7k-pp22";
+                               reg = <0x0 0x100000>, <0x129000 0xb000>;
+                               clocks = <&cps_syscon0 1 3>, <&cps_syscon0 1 9>, <&cps_syscon0 1 5>;
+                               clock-names = "pp_clk", "gop_clk", "mg_clk";
+                               status = "disabled";
+                               dma-coherent;
+
+                               cps_eth0: eth0 {
+                                       interrupts = <GIC_SPI 261 IRQ_TYPE_LEVEL_HIGH>;
+                                       port-id = <0>;
+                                       gop-port-id = <0>;
+                                       status = "disabled";
+                               };
+
+                               cps_eth1: eth1 {
+                                       interrupts = <GIC_SPI 262 IRQ_TYPE_LEVEL_HIGH>;
+                                       port-id = <1>;
+                                       gop-port-id = <2>;
+                                       status = "disabled";
+                               };
+
+                               cps_eth2: eth2 {
+                                       interrupts = <GIC_SPI 263 IRQ_TYPE_LEVEL_HIGH>;
+                                       port-id = <2>;
+                                       gop-port-id = <3>;
+                                       status = "disabled";
+                               };
+                       };
+
+                       cps_mdio: mdio@12a200 {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+                               compatible = "marvell,orion-mdio";
+                               reg = <0x12a200 0x10>;
+                       };
+
                        cps_syscon0: system-controller@440000 {
                                compatible = "marvell,cp110-system-controller0",
                                             "syscon";
                                clocks = <&cps_syscon0 1 25>;
                                status = "okay";
                        };
+
+                       cps_crypto: crypto@800000 {
+                               compatible = "inside-secure,safexcel-eip197";
+                               reg = <0x800000 0x200000>;
+                               interrupts = <GIC_SPI 34 (IRQ_TYPE_EDGE_RISING
+                               | IRQ_TYPE_LEVEL_HIGH)>,
+                                            <GIC_SPI 278 IRQ_TYPE_LEVEL_HIGH>,
+                                            <GIC_SPI 279 IRQ_TYPE_LEVEL_HIGH>,
+                                            <GIC_SPI 280 IRQ_TYPE_LEVEL_HIGH>,
+                                            <GIC_SPI 281 IRQ_TYPE_LEVEL_HIGH>,
+                                            <GIC_SPI 282 IRQ_TYPE_LEVEL_HIGH>;
+                               interrupt-names = "mem", "ring0", "ring1",
+                                                 "ring2", "ring3", "eip";
+                               clocks = <&cps_syscon0 1 26>;
+                               status = "disabled";
+                       };
                };
 
                cps_pcie0: pcie@f4600000 {
index 0ecaad4333a7690f68c019d660ee0bc75b8580b3..1c3634fa94bf4e7c6a65d85e9c76a6e240e4d14a 100644 (file)
        bus-width = <8>;
        max-frequency = <50000000>;
        cap-mmc-highspeed;
+       mediatek,hs200-cmd-int-delay=<26>;
+       mediatek,hs400-cmd-int-delay=<14>;
+       mediatek,hs400-cmd-resp-sel-rising;
        vmmc-supply = <&mt6397_vemc_3v3_reg>;
        vqmmc-supply = <&mt6397_vio18_reg>;
        non-removable;
index 3f3a46a4bd01b0d0003ffccd14c3b106ef1138aa..2b17936ac5be4cda30af18031effcd28fc990ab0 100644 (file)
        };
 
        flow-controller@60007000 {
-               compatible = "nvidia,tegra124-flowctrl";
+               compatible = "nvidia,tegra132-flowctrl", "nvidia,tegra124-flowctrl";
                reg = <0x0 0x60007000 0x0 0x1000>;
        };
 
index 0d3c0996d8325c2dc53a5dcec8041e4a7bf6b93e..8daadadec63a5f4470cbde4864c3986693a5d564 100644 (file)
@@ -1,8 +1,99 @@
 /dts-v1/;
 
+#include <dt-bindings/input/linux-event-codes.h>
+
 #include "tegra186-p3310.dtsi"
 
 / {
        model = "NVIDIA Tegra186 P2771-0000 Development Board";
        compatible = "nvidia,p2771-0000", "nvidia,tegra186";
+
+       i2c@3160000 {
+               power-monitor@42 {
+                       compatible = "ti,ina3221";
+                       reg = <0x42>;
+               };
+
+               power-monitor@43 {
+                       compatible = "ti,ina3221";
+                       reg = <0x43>;
+               };
+
+               exp1: gpio@74 {
+                       compatible = "ti,tca9539";
+                       reg = <0x74>;
+
+                       interrupt-parent = <&gpio>;
+                       interrupts = <TEGRA_MAIN_GPIO(Y, 0) GPIO_ACTIVE_LOW>;
+
+                       #gpio-cells = <2>;
+                       gpio-controller;
+               };
+
+               exp2: gpio@77 {
+                       compatible = "ti,tca9539";
+                       reg = <0x77>;
+
+                       interrupt-parent = <&gpio>;
+                       interrupts = <TEGRA_MAIN_GPIO(Y, 6) GPIO_ACTIVE_LOW>;
+
+                       #gpio-cells = <2>;
+                       gpio-controller;
+               };
+       };
+
+       /* SDMMC1 (SD/MMC) */
+       sdhci@3400000 {
+               status = "okay";
+
+               vmmc-supply = <&vdd_sd>;
+       };
+
+       gpio-keys {
+               compatible = "gpio-keys";
+
+               power {
+                       label = "Power";
+                       gpios = <&gpio_aon TEGRA_AON_GPIO(FF, 0)
+                                          GPIO_ACTIVE_LOW>;
+                       linux,input-type = <EV_KEY>;
+                       linux,code = <KEY_POWER>;
+                       debounce-interval = <10>;
+                       wakeup-source;
+               };
+
+               volume-up {
+                       label = "Volume Up";
+                       gpios = <&gpio_aon TEGRA_AON_GPIO(FF, 1)
+                                          GPIO_ACTIVE_LOW>;
+                       linux,input-type = <EV_KEY>;
+                       linux,code = <KEY_VOLUMEUP>;
+                       debounce-interval = <10>;
+               };
+
+               volume-down {
+                       label = "Volume Down";
+                       gpios = <&gpio_aon TEGRA_AON_GPIO(FF, 2)
+                                          GPIO_ACTIVE_LOW>;
+                       linux,input-type = <EV_KEY>;
+                       linux,code = <KEY_VOLUMEDOWN>;
+                       debounce-interval = <10>;
+               };
+       };
+
+       regulators {
+               vdd_sd: regulator@100 {
+                       compatible = "regulator-fixed";
+                       reg = <100>;
+
+                       regulator-name = "SD_CARD_SW_PWR";
+                       regulator-min-microvolt = <3300000>;
+                       regulator-max-microvolt = <3300000>;
+
+                       gpio = <&gpio TEGRA_MAIN_GPIO(P, 6) GPIO_ACTIVE_HIGH>;
+                       enable-active-high;
+
+                       vin-supply = <&vdd_3v3_sys>;
+               };
+       };
 };
index 1abe2eceb3d132d59f1db6a82bd7f3c058d93498..cf84d7046ad5847650b56226f5f7977f0d0c28b0 100644 (file)
@@ -1,11 +1,23 @@
 #include "tegra186.dtsi"
 
+#include <dt-bindings/mfd/max77620.h>
+
 / {
        model = "NVIDIA Tegra186 P3310 Processor Module";
        compatible = "nvidia,p3310", "nvidia,tegra186";
 
        aliases {
+               sdhci0 = "/sdhci@3460000";
+               sdhci1 = "/sdhci@3400000";
                serial0 = &uarta;
+               i2c0 = "/bpmp/i2c";
+               i2c1 = "/i2c@3160000";
+               i2c2 = "/i2c@c240000";
+               i2c3 = "/i2c@3180000";
+               i2c4 = "/i2c@3190000";
+               i2c5 = "/i2c@31c0000";
+               i2c6 = "/i2c@c250000";
+               i2c7 = "/i2c@31e0000";
        };
 
        chosen {
                reg = <0x0 0x80000000 0x2 0x00000000>;
        };
 
+       ethernet@2490000 {
+               status = "okay";
+
+               phy-reset-gpios = <&gpio TEGRA_MAIN_GPIO(M, 4) GPIO_ACTIVE_LOW>;
+               phy-handle = <&phy>;
+               phy-mode = "rgmii";
+
+               mdio {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       phy: phy@0 {
+                               compatible = "ethernet-phy-ieee802.3-c22";
+                               reg = <0x0>;
+                               interrupt-parent = <&gpio>;
+                               interrupts = <TEGRA_MAIN_GPIO(M, 5) IRQ_TYPE_LEVEL_HIGH>;
+                       };
+               };
+       };
+
        serial@3100000 {
                status = "okay";
        };
 
+       i2c@3160000 {
+               status = "okay";
+
+               power-monitor@40 {
+                       compatible = "ti,ina3221";
+                       reg = <0x40>;
+               };
+
+               power-monitor@41 {
+                       compatible = "ti,ina3221";
+                       reg = <0x41>;
+               };
+       };
+
+       i2c@3180000 {
+               status = "okay";
+       };
+
+       i2c@3190000 {
+               status = "okay";
+       };
+
+       i2c@31c0000 {
+               status = "okay";
+       };
+
+       i2c@31e0000 {
+               status = "okay";
+       };
+
+       /* SDMMC1 (SD/MMC) */
+       sdhci@3400000 {
+               cd-gpios = <&gpio TEGRA_MAIN_GPIO(P, 5) GPIO_ACTIVE_LOW>;
+               wp-gpios = <&gpio TEGRA_MAIN_GPIO(P, 4) GPIO_ACTIVE_LOW>;
+
+               vqmmc-supply = <&vddio_sdmmc1>;
+       };
+
+       /* SDMMC3 (SDIO) */
+       sdhci@3440000 {
+               status = "okay";
+       };
+
+       /* SDMMC4 (eMMC) */
+       sdhci@3460000 {
+               status = "okay";
+               bus-width = <8>;
+               non-removable;
+
+               vqmmc-supply = <&vdd_1v8_ap>;
+               vmmc-supply = <&vdd_3v3_sys>;
+       };
+
        hsp@3c00000 {
                status = "okay";
        };
 
+       i2c@c240000 {
+               status = "okay";
+       };
+
+       i2c@c250000 {
+               status = "okay";
+       };
+
+       pmc@c360000 {
+               nvidia,invert-interrupt;
+       };
+
        cpus {
                cpu@0 {
                        enable-method = "psci";
        };
 
        bpmp {
-               status = "okay";
+               i2c {
+                       status = "okay";
+
+                       pmic: pmic@3c {
+                               compatible = "maxim,max77620";
+                               reg = <0x3c>;
+
+                               interrupts = <GIC_SPI 209 IRQ_TYPE_LEVEL_HIGH>;
+                               #interrupt-cells = <2>;
+                               interrupt-controller;
+
+                               #gpio-cells = <2>;
+                               gpio-controller;
+
+                               pinctrl-names = "default";
+                               pinctrl-0 = <&max77620_default>;
+
+                               max77620_default: pinmux {
+                                       gpio0 {
+                                               pins = "gpio0";
+                                               function = "gpio";
+                                       };
+
+                                       gpio1 {
+                                               pins = "gpio1";
+                                               function = "fps-out";
+                                               maxim,active-fps-source = <MAX77620_FPS_SRC_0>;
+                                       };
+
+                                       gpio2 {
+                                               pins = "gpio2";
+                                               function = "fps-out";
+                                               maxim,active-fps-source = <MAX77620_FPS_SRC_1>;
+                                       };
+
+                                       gpio3 {
+                                               pins = "gpio3";
+                                               function = "fps-out";
+                                               maxim,active-fps-source = <MAX77620_FPS_SRC_1>;
+                                       };
+
+                                       gpio4 {
+                                               pins = "gpio4";
+                                               function = "32k-out1";
+                                               drive-push-pull = <1>;
+                                       };
+
+                                       gpio5 {
+                                               pins = "gpio5";
+                                               function = "gpio";
+                                               drive-push-pull = <0>;
+                                       };
+
+                                       gpio6 {
+                                               pins = "gpio6";
+                                               function = "gpio";
+                                               drive-push-pull = <1>;
+                                       };
+
+                                       gpio7 {
+                                               pins = "gpio7";
+                                               function = "gpio";
+                                               drive-push-pull = <0>;
+                                       };
+                               };
+
+                               fps {
+                                       fps0 {
+                                               maxim,fps-event-source = <MAX77620_FPS_EVENT_SRC_EN0>;
+                                               maxim,shutdown-fps-time-period-us = <640>;
+                                       };
+
+                                       fps1 {
+                                               maxim,fps-event-source = <MAX77620_FPS_EVENT_SRC_EN1>;
+                                               maxim,shutdown-fps-time-period-us = <640>;
+                                       };
+
+                                       fps2 {
+                                               maxim,fps-event-source = <MAX77620_FPS_EVENT_SRC_EN0>;
+                                               maxim,shutdown-fps-time-period-us = <640>;
+                                       };
+                               };
+
+                               regulators {
+                                       in-sd0-supply = <&vdd_5v0_sys>;
+                                       in-sd1-supply = <&vdd_5v0_sys>;
+                                       in-sd2-supply = <&vdd_5v0_sys>;
+                                       in-sd3-supply = <&vdd_5v0_sys>;
+
+                                       in-ldo0-1-supply = <&vdd_5v0_sys>;
+                                       in-ldo2-supply = <&vdd_5v0_sys>;
+                                       in-ldo3-5-supply = <&vdd_5v0_sys>;
+                                       in-ldo4-6-supply = <&vdd_1v8>;
+                                       in-ldo7-8-supply = <&avdd_dsi_csi>;
+
+                                       sd0 {
+                                               regulator-name = "VDD_DDR_1V1_PMIC";
+                                               regulator-min-microvolt = <1100000>;
+                                               regulator-max-microvolt = <1100000>;
+                                               regulator-always-on;
+                                               regulator-boot-on;
+                                       };
+
+                                       avdd_dsi_csi: sd1 {
+                                               regulator-name = "AVDD_DSI_CSI_1V2";
+                                               regulator-min-microvolt = <1200000>;
+                                               regulator-max-microvolt = <1200000>;
+                                               /* XXX */
+                                               regulator-always-on;
+                                               regulator-boot-on;
+                                       };
+
+                                       vdd_1v8: sd2 {
+                                               regulator-name = "VDD_1V8";
+                                               regulator-min-microvolt = <1800000>;
+                                               regulator-max-microvolt = <1800000>;
+                                               /* XXX */
+                                               regulator-always-on;
+                                               regulator-boot-on;
+                                       };
+
+                                       vdd_3v3_sys: sd3 {
+                                               regulator-name = "VDD_3V3_SYS";
+                                               regulator-min-microvolt = <3300000>;
+                                               regulator-max-microvolt = <3300000>;
+                                               /* XXX */
+                                               regulator-always-on;
+                                               regulator-boot-on;
+                                       };
+
+                                       ldo0 {
+                                               regulator-name = "VDD_1V8_AP_PLL";
+                                               regulator-min-microvolt = <1800000>;
+                                               regulator-max-microvolt = <1800000>;
+                                               /* XXX */
+                                               regulator-always-on;
+                                               regulator-boot-on;
+                                       };
+
+                                       ldo2 {
+                                               regulator-name = "VDDIO_3V3_AOHV";
+                                               regulator-min-microvolt = <3300000>;
+                                               regulator-max-microvolt = <3300000>;
+                                               /* XXX */
+                                               regulator-always-on;
+                                               regulator-boot-on;
+                                       };
+
+                                       vddio_sdmmc1: ldo3 {
+                                               regulator-name = "VDDIO_SDMMC1_AP";
+                                               regulator-min-microvolt = <1800000>;
+                                               regulator-max-microvolt = <3300000>;
+                                       };
+
+                                       ldo4 {
+                                               regulator-name = "VDD_RTC";
+                                               regulator-min-microvolt = <1000000>;
+                                               regulator-max-microvolt = <1000000>;
+                                       };
+
+                                       vddio_sdmmc3: ldo5 {
+                                               regulator-name = "VDDIO_SDMMC3_AP";
+                                               regulator-min-microvolt = <2800000>;
+                                               regulator-max-microvolt = <2800000>;
+                                       };
+
+                                       avdd_1v05: ldo7 {
+                                               regulator-name = "VDD_HDMI_1V05";
+                                               regulator-min-microvolt = <1050000>;
+                                               regulator-max-microvolt = <1050000>;
+                                               /* XXX */
+                                               regulator-always-on;
+                                               regulator-boot-on;
+                                       };
+
+                                       vdd_pex: ldo8 {
+                                               regulator-name = "VDD_PEX_1V05";
+                                               regulator-min-microvolt = <1050000>;
+                                               regulator-max-microvolt = <1050000>;
+                                               /* XXX */
+                                               regulator-always-on;
+                                               regulator-boot-on;
+                                       };
+                               };
+                       };
+               };
        };
 
        psci {
                status = "okay";
                method = "smc";
        };
+
+       regulators {
+               compatible = "simple-bus";
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               vdd_5v0_sys: regulator@0 {
+                       compatible = "regulator-fixed";
+                       reg = <0>;
+
+                       regulator-name = "VDD_5V0_SYS";
+                       regulator-min-microvolt = <5000000>;
+                       regulator-max-microvolt = <5000000>;
+                       regulator-always-on;
+                       regulator-boot-on;
+               };
+
+               vdd_1v8_ap: regulator@1 {
+                       compatible = "regulator-fixed";
+                       reg = <1>;
+
+                       regulator-name = "VDD_1V8_AP";
+                       regulator-min-microvolt = <1800000>;
+                       regulator-max-microvolt = <1800000>;
+
+                       /* XXX */
+                       regulator-always-on;
+                       regulator-boot-on;
+
+                       gpio = <&pmic 1 GPIO_ACTIVE_HIGH>;
+                       enable-active-high;
+
+                       vin-supply = <&vdd_1v8>;
+               };
+       };
 };
index 62fa85ae02718f214903e0229454af70dc48b8f9..5e62e68ac05385b525e2ff2ef9282b0e153fd2f6 100644 (file)
@@ -2,6 +2,7 @@
 #include <dt-bindings/gpio/tegra186-gpio.h>
 #include <dt-bindings/interrupt-controller/arm-gic.h>
 #include <dt-bindings/mailbox/tegra186-hsp.h>
+#include <dt-bindings/power/tegra186-powergate.h>
 #include <dt-bindings/reset/tegra186-reset.h>
 
 / {
                gpio-controller;
        };
 
+       ethernet@2490000 {
+               compatible = "nvidia,tegra186-eqos",
+                            "snps,dwc-qos-ethernet-4.10";
+               reg = <0x0 0x02490000 0x0 0x10000>;
+               interrupts = <GIC_SPI 194 IRQ_TYPE_LEVEL_HIGH>, /* common */
+                            <GIC_SPI 195 IRQ_TYPE_LEVEL_HIGH>, /* power */
+                            <GIC_SPI 190 IRQ_TYPE_LEVEL_HIGH>, /* rx0 */
+                            <GIC_SPI 186 IRQ_TYPE_LEVEL_HIGH>, /* tx0 */
+                            <GIC_SPI 191 IRQ_TYPE_LEVEL_HIGH>, /* rx1 */
+                            <GIC_SPI 187 IRQ_TYPE_LEVEL_HIGH>, /* tx1 */
+                            <GIC_SPI 192 IRQ_TYPE_LEVEL_HIGH>, /* rx2 */
+                            <GIC_SPI 188 IRQ_TYPE_LEVEL_HIGH>, /* tx2 */
+                            <GIC_SPI 193 IRQ_TYPE_LEVEL_HIGH>, /* rx3 */
+                            <GIC_SPI 189 IRQ_TYPE_LEVEL_HIGH>; /* tx3 */
+               clocks = <&bpmp TEGRA186_CLK_AXI_CBB>,
+                        <&bpmp TEGRA186_CLK_EQOS_AXI>,
+                        <&bpmp TEGRA186_CLK_EQOS_RX>,
+                        <&bpmp TEGRA186_CLK_EQOS_TX>,
+                        <&bpmp TEGRA186_CLK_EQOS_PTP_REF>;
+               clock-names = "master_bus", "slave_bus", "rx", "tx", "ptp_ref";
+               resets = <&bpmp TEGRA186_RESET_EQOS>;
+               reset-names = "eqos";
+               status = "disabled";
+
+               snps,write-requests = <1>;
+               snps,read-requests = <3>;
+               snps,burst-map = <0x7>;
+               snps,txpbl = <32>;
+               snps,rxpbl = <8>;
+       };
+
        uarta: serial@3100000 {
                compatible = "nvidia,tegra186-uart", "nvidia,tegra20-uart";
                reg = <0x0 0x03100000 0x0 0x40>;
                #interrupt-cells = <2>;
        };
 
+       pmc@c360000 {
+               compatible = "nvidia,tegra186-pmc";
+               reg = <0 0x0c360000 0 0x10000>,
+                     <0 0x0c370000 0 0x10000>,
+                     <0 0x0c380000 0 0x10000>,
+                     <0 0x0c390000 0 0x10000>;
+               reg-names = "pmc", "wake", "aotag", "scratch";
+       };
+
+       gpu@17000000 {
+               compatible = "nvidia,gp10b";
+               reg = <0x0 0x17000000 0x0 0x1000000>,
+                     <0x0 0x18000000 0x0 0x1000000>;
+               interrupts = <GIC_SPI 70 IRQ_TYPE_LEVEL_HIGH
+                             GIC_SPI 71 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "stall", "nonstall";
+
+               clocks = <&bpmp TEGRA186_CLK_GPCCLK>,
+                        <&bpmp TEGRA186_CLK_GPU>;
+               clock-names = "gpu", "pwr";
+               resets = <&bpmp TEGRA186_RESET_GPU>;
+               reset-names = "gpu";
+               status = "disabled";
+
+               power-domains = <&bpmp TEGRA186_POWER_DOMAIN_GPU>;
+       };
+
        sysram@30000000 {
                compatible = "nvidia,tegra186-sysram", "mmio-sram";
                reg = <0x0 0x30000000 0x0 0x50000>;
index 2f832df29da8522bf05fdb1168580ea1ea105bbf..8f26c4d4409aad7d1a880cfbef78d1e5946f7763 100644 (file)
@@ -89,6 +89,8 @@
 
                ranges = <0x0 0x54000000 0x0 0x54000000 0x0 0x01000000>;
 
+               iommus = <&mc TEGRA_SWGROUP_HC>;
+
                dpaux1: dpaux@54040000 {
                        compatible = "nvidia,tegra210-dpaux";
                        reg = <0x0 0x54040000 0x0 0x00040000>;
                vic@54340000 {
                        compatible = "nvidia,tegra210-vic";
                        reg = <0x0 0x54340000 0x0 0x00040000>;
-                       status = "disabled";
+                       interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&tegra_car TEGRA210_CLK_VIC03>;
+                       clock-names = "vic";
+                       resets = <&tegra_car 178>;
+                       reset-names = "vic";
+
+                       iommus = <&mc TEGRA_SWGROUP_VIC>;
+                       power-domains = <&pd_vic>;
                };
 
                nvjpg@54380000 {
                                resets = <&tegra_car TEGRA210_CLK_XUSB_HOST>;
                                #power-domain-cells = <0>;
                        };
+
+                       pd_vic: vic {
+                               clocks = <&tegra_car TEGRA210_CLK_VIC03>;
+                               clock-names = "vic";
+                               resets = <&tegra_car 178>;
+                               reset-names = "vic";
+                               #power-domain-cells = <0>;
+                       };
                };
        };
 
index eac5389f2f3813c8fdf230e59ad696efd9ceaa59..a17f5b9a5de6116020ae030f67e904b21f6af941 100644 (file)
                stdout-path = "serial0";
        };
 
+       reserved-memory {
+               ramoops@bff00000{
+                       compatible = "ramoops";
+                       reg = <0x0 0xbff00000 0x0 0x100000>;
+
+                       record-size = <0x20000>;
+                       console-size = <0x20000>;
+                       ftrace-size = <0x20000>;
+               };
+       };
+
        soc {
                dma@7884000 {
                        status = "okay";
index 68a8e67cba29cc67648f1e419f88fba67d7481b4..ab3093995ded75d7784946376b3bda12fc90b649 100644 (file)
        };
 
        pmu {
-               compatible = "arm,armv8-pmuv3";
+               compatible = "arm,cortex-a53-pmu";
                interrupts = <GIC_PPI 7 GIC_CPU_MASK_SIMPLE(4)>;
        };
 
 
                        clocks = <&gcc GCC_MSS_CFG_AHB_CLK>,
                                 <&gcc GCC_MSS_Q6_BIMC_AXI_CLK>,
-                                <&gcc GCC_BOOT_ROM_AHB_CLK>;
-                       clock-names = "iface", "bus", "mem";
+                                <&gcc GCC_BOOT_ROM_AHB_CLK>,
+                                <&xo_board>;
+                       clock-names = "iface", "bus", "mem", "xo";
 
                        qcom,smem-states = <&hexagon_smp2p_out 0>;
                        qcom,smem-state-names = "stop";
                        resets = <&scm 0>;
                        reset-names = "mss_restart";
 
+                       cx-supply = <&pm8916_s1>;
                        mx-supply = <&pm8916_l3>;
                        pll-supply = <&pm8916_l7>;
 
                        mpss {
                                memory-region = <&mpss_mem>;
                        };
+
+                       smd-edge {
+                               interrupts = <0 25 IRQ_TYPE_EDGE_RISING>;
+
+                               qcom,smd-edge = <0>;
+                               qcom,ipc = <&apcs 8 12>;
+                               qcom,remote-pid = <1>;
+
+                               label = "hexagon";
+                       };
                };
 
                pronto: wcnss@a21b000 {
                                };
                        };
                };
-
-               hexagon {
-                       interrupts = <0 25 IRQ_TYPE_EDGE_RISING>;
-
-                       qcom,smd-edge = <0>;
-                       qcom,ipc = <&apcs 8 12>;
-                       qcom,remote-pid = <1>;
-               };
        };
 
        hexagon-smp2p {
index ed7223d3c8cbff723c83687345227f4e84421cb3..9bc9c857a000190c0ad2d655874233470d3c1cb9 100644 (file)
                };
        };
 
+       adsp-pil {
+               compatible = "qcom,msm8996-adsp-pil";
+
+               interrupts-extended = <&intc 0 162 IRQ_TYPE_EDGE_RISING>,
+                                     <&adsp_smp2p_in 0 IRQ_TYPE_EDGE_RISING>,
+                                     <&adsp_smp2p_in 1 IRQ_TYPE_EDGE_RISING>,
+                                     <&adsp_smp2p_in 2 IRQ_TYPE_EDGE_RISING>,
+                                     <&adsp_smp2p_in 3 IRQ_TYPE_EDGE_RISING>;
+               interrupt-names = "wdog", "fatal", "ready",
+                                 "handover", "stop-ack";
+
+               clocks = <&xo_board>;
+               clock-names = "xo";
+
+               memory-region = <&adsp_region>;
+
+               qcom,smem-states = <&adsp_smp2p_out 0>;
+               qcom,smem-state-names = "stop";
+       };
+
        adsp-smp2p {
                compatible = "qcom,smp2p";
                qcom,smem = <443>, <429>;
 
                adsp_smp2p_out: master-kernel {
                        qcom,entry-name = "master-kernel";
-                       #qcom,state-cells = <1>;
+                       #qcom,smem-state-cells = <1>;
                };
 
                adsp_smp2p_in: slave-kernel {
                        #interrupt-cells = <2>;
                };
        };
+
+       smp2p-slpi {
+               compatible = "qcom,smp2p";
+               qcom,smem = <481>, <430>;
+
+               interrupts = <GIC_SPI 178 IRQ_TYPE_EDGE_RISING>;
+
+               qcom,ipc = <&apcs 16 26>;
+
+               qcom,local-pid = <0>;
+               qcom,remote-pid = <3>;
+
+               slpi_smp2p_in: slave-kernel {
+                       qcom,entry-name = "slave-kernel";
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               slpi_smp2p_out: master-kernel {
+                       qcom,entry-name = "master-kernel";
+                       #qcom,smem-state-cells = <1>;
+               };
+       };
+
 };
 #include "msm8996-pins.dtsi"
index 0f1866024ae3679bce6bf2de226838466afb8823..b413e44fd09e3d8cfd6df277e7ec0de09463885c 100644 (file)
@@ -9,6 +9,13 @@
                #address-cells = <1>;
                #size-cells = <0>;
 
+               rtc@6000 {
+                       compatible = "qcom,pm8941-rtc";
+                       reg = <0x6000>, <0x6100>;
+                       reg-names = "rtc", "alarm";
+                       interrupts = <0x0 0x61 0x1 IRQ_TYPE_EDGE_RISING>;
+               };
+
                pm8994_gpios: gpios@c000 {
                        compatible = "qcom,pm8994-gpio";
                        reg = <0xc000>;
index c5f8f69a4f5f54a063ff4d46d22a1c9d739a83f6..ab352159de6572c99a32eb0b1ab9775b08202863 100644 (file)
                reg = <0x0 0x48000000 0x0 0x38000000>;
        };
 
+       memory@500000000 {
+               device_type = "memory";
+               reg = <0x5 0x00000000 0x0 0x40000000>;
+       };
+
+       memory@600000000 {
+               device_type = "memory";
+               reg = <0x6 0x00000000 0x0 0x40000000>;
+       };
+
+       memory@700000000 {
+               device_type = "memory";
+               reg = <0x7 0x00000000 0x0 0x40000000>;
+       };
+
        leds {
                compatible = "gpio-leds";
 
 
 &scif_clk {
        clock-frequency = <14745600>;
-       status = "okay";
 };
 
 &i2c2 {
        status = "okay";
 
        phy0: ethernet-phy@0 {
-               rxc-skew-ps = <900>;
-               rxdv-skew-ps = <0>;
-               rxd0-skew-ps = <0>;
-               rxd1-skew-ps = <0>;
-               rxd2-skew-ps = <0>;
-               rxd3-skew-ps = <0>;
-               txc-skew-ps = <900>;
-               txen-skew-ps = <0>;
-               txd0-skew-ps = <0>;
-               txd1-skew-ps = <0>;
-               txd2-skew-ps = <0>;
-               txd3-skew-ps = <0>;
+               rxc-skew-ps = <1500>;
                reg = <0>;
                interrupt-parent = <&gpio2>;
                interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
index 7a8986edcdc0d14da9e5bcec1f8b974f80ff2c4b..639aa085d9966676b07b6eaf4c54ee3b9b5476cb 100644 (file)
@@ -56,7 +56,7 @@
                reg = <0x0 0x48000000 0x0 0x38000000>;
        };
 
-       x12_clk: x12_clk {
+       x12_clk: x12 {
                compatible = "fixed-clock";
                #clock-cells = <0>;
                clock-frequency = <24576000>;
        };
 
        avb_pins: avb {
-               groups = "avb_mdc";
-               function = "avb";
+               mux {
+                       groups = "avb_link", "avb_phy_int", "avb_mdc",
+                                "avb_mii";
+                       function = "avb";
+               };
+
+               pins_mdc {
+                       groups = "avb_mdc";
+                       drive-strength = <24>;
+               };
+
+               pins_mii_tx {
+                       pins = "PIN_AVB_TX_CTL", "PIN_AVB_TXC", "PIN_AVB_TD0",
+                              "PIN_AVB_TD1", "PIN_AVB_TD2", "PIN_AVB_TD3";
+                       drive-strength = <12>;
+               };
        };
 
        du_pins: du {
 
 &scif_clk {
        clock-frequency = <14745600>;
-       status = "okay";
 };
 
 &i2c2 {
        clock-frequency = <22579200>;
 };
 
+&i2c_dvfs {
+       status = "okay";
+};
+
 &avb {
        pinctrl-0 = <&avb_pins>;
        pinctrl-names = "default";
        status = "okay";
 
        phy0: ethernet-phy@0 {
-               rxc-skew-ps = <900>;
-               rxdv-skew-ps = <0>;
-               rxd0-skew-ps = <0>;
-               rxd1-skew-ps = <0>;
-               rxd2-skew-ps = <0>;
-               rxd3-skew-ps = <0>;
-               txc-skew-ps = <900>;
-               txen-skew-ps = <0>;
-               txd0-skew-ps = <0>;
-               txd1-skew-ps = <0>;
-               txd2-skew-ps = <0>;
-               txd3-skew-ps = <0>;
+               rxc-skew-ps = <1500>;
                reg = <0>;
                interrupt-parent = <&gpio2>;
                interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
 
 &pcie_bus_clk {
        clock-frequency = <100000000>;
-       status = "okay";
 };
 
 &pciec0 {
index eac4f29aa5cde62300640d89800c5ee0466d1207..e99d6443b3e493a48da79c1f54060d6eddc3b963 100644 (file)
                i2c4 = &i2c4;
                i2c5 = &i2c5;
                i2c6 = &i2c6;
+               i2c7 = &i2c_dvfs;
        };
 
        psci {
-               compatible = "arm,psci-0.2";
+               compatible = "arm,psci-1.0", "arm,psci-0.2";
                method = "smc";
        };
 
                        enable-method = "psci";
                };
 
-               L2_CA57: cache-controller@0 {
+               a53_0: cpu@100 {
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       reg = <0x100>;
+                       device_type = "cpu";
+                       power-domains = <&sysc R8A7795_PD_CA53_CPU0>;
+                       next-level-cache = <&L2_CA53>;
+                       enable-method = "psci";
+               };
+
+               a53_1: cpu@101 {
+                       compatible = "arm,cortex-a53","arm,armv8";
+                       reg = <0x101>;
+                       device_type = "cpu";
+                       power-domains = <&sysc R8A7795_PD_CA53_CPU1>;
+                       next-level-cache = <&L2_CA53>;
+                       enable-method = "psci";
+               };
+
+               a53_2: cpu@102 {
+                       compatible = "arm,cortex-a53","arm,armv8";
+                       reg = <0x102>;
+                       device_type = "cpu";
+                       power-domains = <&sysc R8A7795_PD_CA53_CPU2>;
+                       next-level-cache = <&L2_CA53>;
+                       enable-method = "psci";
+               };
+
+               a53_3: cpu@103 {
+                       compatible = "arm,cortex-a53","arm,armv8";
+                       reg = <0x103>;
+                       device_type = "cpu";
+                       power-domains = <&sysc R8A7795_PD_CA53_CPU3>;
+                       next-level-cache = <&L2_CA53>;
+                       enable-method = "psci";
+               };
+
+               L2_CA57: cache-controller-0 {
                        compatible = "cache";
-                       reg = <0>;
                        power-domains = <&sysc R8A7795_PD_CA57_SCU>;
                        cache-unified;
                        cache-level = <2>;
                };
 
-               L2_CA53: cache-controller@100 {
+               L2_CA53: cache-controller-1 {
                        compatible = "cache";
-                       reg = <0x100>;
                        power-domains = <&sysc R8A7795_PD_CA53_SCU>;
                        cache-unified;
                        cache-level = <2>;
                              <0x0 0xf1040000 0 0x20000>,
                              <0x0 0xf1060000 0 0x20000>;
                        interrupts = <GIC_PPI 9
-                                       (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+                                       (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_HIGH)>;
                        clocks = <&cpg CPG_MOD 408>;
                        clock-names = "clk";
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 408>;
                };
 
                wdt0: watchdog@e6020000 {
                        reg = <0 0xe6020000 0 0x0c>;
                        clocks = <&cpg CPG_MOD 402>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 402>;
                        status = "disabled";
                };
 
                        interrupt-controller;
                        clocks = <&cpg CPG_MOD 912>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 912>;
                };
 
                gpio1: gpio@e6051000 {
                        interrupt-controller;
                        clocks = <&cpg CPG_MOD 911>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 911>;
                };
 
                gpio2: gpio@e6052000 {
                        interrupt-controller;
                        clocks = <&cpg CPG_MOD 910>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 910>;
                };
 
                gpio3: gpio@e6053000 {
                        interrupt-controller;
                        clocks = <&cpg CPG_MOD 909>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 909>;
                };
 
                gpio4: gpio@e6054000 {
                        interrupt-controller;
                        clocks = <&cpg CPG_MOD 908>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 908>;
                };
 
                gpio5: gpio@e6055000 {
                        interrupt-controller;
                        clocks = <&cpg CPG_MOD 907>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 907>;
                };
 
                gpio6: gpio@e6055400 {
                        interrupt-controller;
                        clocks = <&cpg CPG_MOD 906>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 906>;
                };
 
                gpio7: gpio@e6055800 {
                        interrupt-controller;
                        clocks = <&cpg CPG_MOD 905>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 905>;
                };
 
                pmu_a57 {
                                             <&a57_3>;
                };
 
+               pmu_a53 {
+                       compatible = "arm,cortex-a53-pmu";
+                       interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupt-affinity = <&a53_0>,
+                                            <&a53_1>,
+                                            <&a53_2>,
+                                            <&a53_3>;
+               };
+
                timer {
                        compatible = "arm,armv8-timer";
                        interrupts = <GIC_PPI 13
-                                       (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+                                       (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
                                     <GIC_PPI 14
-                                       (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+                                       (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
                                     <GIC_PPI 11
-                                       (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+                                       (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>,
                                     <GIC_PPI 10
-                                       (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+                                       (GIC_CPU_MASK_SIMPLE(8) | IRQ_TYPE_LEVEL_LOW)>;
                };
 
                cpg: clock-controller@e6150000 {
                        clock-names = "extal", "extalr";
                        #clock-cells = <2>;
                        #power-domain-cells = <0>;
+                       #reset-cells = <1>;
                };
 
                rst: reset-controller@e6160000 {
                                      GIC_SPI 161 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 407>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 407>;
                };
 
                dmac0: dma-controller@e6700000 {
                        clocks = <&cpg CPG_MOD 219>;
                        clock-names = "fck";
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 219>;
                        #dma-cells = <1>;
                        dma-channels = <16>;
                };
                        clocks = <&cpg CPG_MOD 218>;
                        clock-names = "fck";
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 218>;
                        #dma-cells = <1>;
                        dma-channels = <16>;
                };
                        clocks = <&cpg CPG_MOD 217>;
                        clock-names = "fck";
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 217>;
                        #dma-cells = <1>;
                        dma-channels = <16>;
                };
                        clocks = <&cpg CPG_MOD 502>;
                        clock-names = "fck";
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 502>;
                        #dma-cells = <1>;
                        dma-channels = <16>;
                };
                        clocks = <&cpg CPG_MOD 501>;
                        clock-names = "fck";
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 501>;
                        #dma-cells = <1>;
                        dma-channels = <16>;
                };
                                          "ch24";
                        clocks = <&cpg CPG_MOD 812>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
-                       phy-mode = "rgmii-id";
+                       resets = <&cpg 812>;
+                       phy-mode = "rgmii-txid";
                        #address-cells = <1>;
                        #size-cells = <0>;
                        status = "disabled";
                        assigned-clocks = <&cpg CPG_CORE R8A7795_CLK_CANFD>;
                        assigned-clock-rates = <40000000>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 916>;
                        status = "disabled";
                };
 
                        assigned-clocks = <&cpg CPG_CORE R8A7795_CLK_CANFD>;
                        assigned-clock-rates = <40000000>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 915>;
                        status = "disabled";
                };
 
                        assigned-clocks = <&cpg CPG_CORE R8A7795_CLK_CANFD>;
                        assigned-clock-rates = <40000000>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 914>;
                        status = "disabled";
 
                        channel0 {
                        dmas = <&dmac1 0x31>, <&dmac1 0x30>;
                        dma-names = "tx", "rx";
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 520>;
                        status = "disabled";
                };
 
                        dmas = <&dmac1 0x33>, <&dmac1 0x32>;
                        dma-names = "tx", "rx";
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 519>;
                        status = "disabled";
                };
 
                        dmas = <&dmac1 0x35>, <&dmac1 0x34>;
                        dma-names = "tx", "rx";
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 518>;
                        status = "disabled";
                };
 
                        dmas = <&dmac0 0x37>, <&dmac0 0x36>;
                        dma-names = "tx", "rx";
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 517>;
                        status = "disabled";
                };
 
                        dmas = <&dmac0 0x39>, <&dmac0 0x38>;
                        dma-names = "tx", "rx";
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 516>;
                        status = "disabled";
                };
 
                        dmas = <&dmac1 0x51>, <&dmac1 0x50>;
                        dma-names = "tx", "rx";
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 207>;
                        status = "disabled";
                };
 
                        dmas = <&dmac1 0x53>, <&dmac1 0x52>;
                        dma-names = "tx", "rx";
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 206>;
                        status = "disabled";
                };
 
                        dmas = <&dmac1 0x13>, <&dmac1 0x12>;
                        dma-names = "tx", "rx";
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 310>;
                        status = "disabled";
                };
 
                        dmas = <&dmac0 0x57>, <&dmac0 0x56>;
                        dma-names = "tx", "rx";
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 204>;
                        status = "disabled";
                };
 
                        dmas = <&dmac0 0x59>, <&dmac0 0x58>;
                        dma-names = "tx", "rx";
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 203>;
                        status = "disabled";
                };
 
                        dmas = <&dmac1 0x5b>, <&dmac1 0x5a>;
                        dma-names = "tx", "rx";
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 202>;
+                       status = "disabled";
+               };
+
+               i2c_dvfs: i2c@e60b0000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "renesas,iic-r8a7795",
+                                    "renesas,rcar-gen3-iic",
+                                    "renesas,rmobile-iic";
+                       reg = <0 0xe60b0000 0 0x425>;
+                       interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 926>;
+                       power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 926>;
                        status = "disabled";
                };
 
                        interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 931>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 931>;
                        dmas = <&dmac1 0x91>, <&dmac1 0x90>;
                        dma-names = "tx", "rx";
                        i2c-scl-internal-delay-ns = <110>;
                        interrupts = <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 930>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 930>;
                        dmas = <&dmac1 0x93>, <&dmac1 0x92>;
                        dma-names = "tx", "rx";
                        i2c-scl-internal-delay-ns = <6>;
                        interrupts = <GIC_SPI 286 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 929>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 929>;
                        dmas = <&dmac1 0x95>, <&dmac1 0x94>;
                        dma-names = "tx", "rx";
                        i2c-scl-internal-delay-ns = <6>;
                        interrupts = <GIC_SPI 290 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 928>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 928>;
                        dmas = <&dmac0 0x97>, <&dmac0 0x96>;
                        dma-names = "tx", "rx";
                        i2c-scl-internal-delay-ns = <110>;
                        interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 927>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 927>;
                        dmas = <&dmac0 0x99>, <&dmac0 0x98>;
                        dma-names = "tx", "rx";
                        i2c-scl-internal-delay-ns = <110>;
                        interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 919>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 919>;
                        dmas = <&dmac0 0x9b>, <&dmac0 0x9a>;
                        dma-names = "tx", "rx";
                        i2c-scl-internal-delay-ns = <110>;
                        interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 918>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 918>;
                        dmas = <&dmac0 0x9d>, <&dmac0 0x9c>;
                        dma-names = "tx", "rx";
                        i2c-scl-internal-delay-ns = <6>;
                        reg = <0 0xe6e30000 0 0x8>;
                        clocks = <&cpg CPG_MOD 523>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 523>;
                        #pwm-cells = <2>;
                        status = "disabled";
                };
                        reg = <0 0xe6e31000 0 0x8>;
                        clocks = <&cpg CPG_MOD 523>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 523>;
                        #pwm-cells = <2>;
                        status = "disabled";
                };
                        reg = <0 0xe6e32000 0 0x8>;
                        clocks = <&cpg CPG_MOD 523>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 523>;
                        #pwm-cells = <2>;
                        status = "disabled";
                };
                        reg = <0 0xe6e33000 0 0x8>;
                        clocks = <&cpg CPG_MOD 523>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 523>;
                        #pwm-cells = <2>;
                        status = "disabled";
                };
                        reg = <0 0xe6e34000 0 0x8>;
                        clocks = <&cpg CPG_MOD 523>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 523>;
                        #pwm-cells = <2>;
                        status = "disabled";
                };
                        reg = <0 0xe6e35000 0 0x8>;
                        clocks = <&cpg CPG_MOD 523>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 523>;
                        #pwm-cells = <2>;
                        status = "disabled";
                };
                        reg = <0 0xe6e36000 0 0x8>;
                        clocks = <&cpg CPG_MOD 523>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 523>;
                        #pwm-cells = <2>;
                        status = "disabled";
                };
 
                        rcar_sound,dvc {
                                dvc0: dvc-0 {
-                                       dmas = <&audma0 0xbc>;
+                                       dmas = <&audma1 0xbc>;
                                        dma-names = "tx";
                                };
                                dvc1: dvc-1 {
-                                       dmas = <&audma0 0xbe>;
+                                       dmas = <&audma1 0xbe>;
                                        dma-names = "tx";
                                };
                        };
 
                sata: sata@ee300000 {
                        compatible = "renesas,sata-r8a7795";
-                       reg = <0 0xee300000 0 0x1fff>;
+                       reg = <0 0xee300000 0 0x200000>;
                        interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 815>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 815>;
                        status = "disabled";
                };
 
                        interrupts = <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 328>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 328>;
                        status = "disabled";
                };
 
                        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";
                };
 
                        interrupt-names = "ch0", "ch1";
                        clocks = <&cpg CPG_MOD 330>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 330>;
                        #dma-cells = <1>;
                        dma-channels = <2>;
                };
                        interrupt-names = "ch0", "ch1";
                        clocks = <&cpg CPG_MOD 331>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 331>;
                        #dma-cells = <1>;
                        dma-channels = <2>;
                };
                        clocks = <&cpg CPG_MOD 314>;
                        max-frequency = <200000000>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 314>;
                        status = "disabled";
                };
 
                        clocks = <&cpg CPG_MOD 313>;
                        max-frequency = <200000000>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 313>;
                        status = "disabled";
                };
 
                        clocks = <&cpg CPG_MOD 312>;
                        max-frequency = <200000000>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 312>;
                        status = "disabled";
                };
 
                        clocks = <&cpg CPG_MOD 311>;
                        max-frequency = <200000000>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 311>;
                        status = "disabled";
                };
 
                        interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 703>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 703>;
                        #phy-cells = <0>;
                        status = "disabled";
                };
                        reg = <0 0xee0a0200 0 0x700>;
                        clocks = <&cpg CPG_MOD 702>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 702>;
                        #phy-cells = <0>;
                        status = "disabled";
                };
                        reg = <0 0xee0c0200 0 0x700>;
                        clocks = <&cpg CPG_MOD 701>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 701>;
                        #phy-cells = <0>;
                        status = "disabled";
                };
                        phys = <&usb2_phy0>;
                        phy-names = "usb";
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 703>;
                        status = "disabled";
                };
 
                        phys = <&usb2_phy1>;
                        phy-names = "usb";
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 702>;
                        status = "disabled";
                };
 
                        phys = <&usb2_phy2>;
                        phy-names = "usb";
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 701>;
                        status = "disabled";
                };
 
                        phys = <&usb2_phy0>;
                        phy-names = "usb";
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 703>;
                        status = "disabled";
                };
 
                        phys = <&usb2_phy1>;
                        phy-names = "usb";
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 702>;
                        status = "disabled";
                };
 
                        phys = <&usb2_phy2>;
                        phy-names = "usb";
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 701>;
                        status = "disabled";
                };
 
                        phys = <&usb2_phy0>;
                        phy-names = "usb";
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 704>;
                        status = "disabled";
                };
 
                        clocks = <&cpg CPG_MOD 319>, <&pcie_bus_clk>;
                        clock-names = "pcie", "pcie_bus";
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 319>;
                        status = "disabled";
                };
 
                        clocks = <&cpg CPG_MOD 318>, <&pcie_bus_clk>;
                        clock-names = "pcie", "pcie_bus";
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 318>;
                        status = "disabled";
                };
 
                        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>;
                };
                        reg = <0 0xfe92f000 0 0x200>;
                        clocks = <&cpg CPG_MOD 606>;
                        power-domains = <&sysc R8A7795_PD_A3VP>;
+                       resets = <&cpg 606>;
                };
 
                fcpf0: fcp@fe950000 {
                        reg = <0 0xfe950000 0 0x200>;
                        clocks = <&cpg CPG_MOD 615>;
                        power-domains = <&sysc R8A7795_PD_A3VP>;
+                       resets = <&cpg 615>;
                };
 
                fcpf1: fcp@fe951000 {
                        reg = <0 0xfe951000 0 0x200>;
                        clocks = <&cpg CPG_MOD 614>;
                        power-domains = <&sysc R8A7795_PD_A3VP>;
+                       resets = <&cpg 614>;
                };
 
                fcpf2: fcp@fe952000 {
                        reg = <0 0xfe952000 0 0x200>;
                        clocks = <&cpg CPG_MOD 613>;
                        power-domains = <&sysc R8A7795_PD_A3VP>;
+                       resets = <&cpg 613>;
                };
 
                vspbd: vsp@fe960000 {
                        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>;
                };
                        reg = <0 0xfe96f000 0 0x200>;
                        clocks = <&cpg CPG_MOD 607>;
                        power-domains = <&sysc R8A7795_PD_A3VP>;
+                       resets = <&cpg 607>;
                };
 
                vspi0: vsp@fe9a0000 {
                        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>;
                };
                        reg = <0 0xfe9af000 0 0x200>;
                        clocks = <&cpg CPG_MOD 611>;
                        power-domains = <&sysc R8A7795_PD_A3VP>;
+                       resets = <&cpg 611>;
                };
 
                vspi1: vsp@fe9b0000 {
                        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>;
                };
                        reg = <0 0xfe9bf000 0 0x200>;
                        clocks = <&cpg CPG_MOD 610>;
                        power-domains = <&sysc R8A7795_PD_A3VP>;
+                       resets = <&cpg 610>;
                };
 
                vspi2: vsp@fe9c0000 {
                        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>;
                };
                        reg = <0 0xfe9cf000 0 0x200>;
                        clocks = <&cpg CPG_MOD 609>;
                        power-domains = <&sysc R8A7795_PD_A3VP>;
+                       resets = <&cpg 609>;
                };
 
                vspd0: vsp@fea20000 {
                        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>;
                };
                        reg = <0 0xfea27000 0 0x200>;
                        clocks = <&cpg CPG_MOD 603>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 603>;
                };
 
                vspd1: vsp@fea28000 {
                        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>;
                };
                        reg = <0 0xfea2f000 0 0x200>;
                        clocks = <&cpg CPG_MOD 602>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 602>;
                };
 
                vspd2: vsp@fea30000 {
                        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>;
                };
                        reg = <0 0xfea37000 0 0x200>;
                        clocks = <&cpg CPG_MOD 601>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 601>;
                };
 
                vspd3: vsp@fea38000 {
                        interrupts = <GIC_SPI 469 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 620>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 620>;
 
                        renesas,fcp = <&fcpvd3>;
                };
                        reg = <0 0xfea3f000 0 0x200>;
                        clocks = <&cpg CPG_MOD 600>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 600>;
                };
 
                fdp1@fe940000 {
                        interrupts = <GIC_SPI 262 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 119>;
                        power-domains = <&sysc R8A7795_PD_A3VP>;
+                       resets = <&cpg 119>;
                        renesas,fcp = <&fcpf0>;
                };
 
                        interrupts = <GIC_SPI 263 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 118>;
                        power-domains = <&sysc R8A7795_PD_A3VP>;
+                       resets = <&cpg 118>;
                        renesas,fcp = <&fcpf1>;
                };
 
                        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>;
                };
 
                                     <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 522>;
                        power-domains = <&sysc R8A7795_PD_ALWAYS_ON>;
+                       resets = <&cpg 522>;
                        #thermal-sensor-cells = <1>;
                        status = "okay";
                };
index c3f064ac2cb44971b2b91bae39faec4124fe3528..372b2a9447163b24cd6bd08849c25be3ab6f27a6 100644 (file)
 
 &scif_clk {
        clock-frequency = <14745600>;
-       status = "okay";
 };
 
 &wdt0 {
index c7f40f8f3169f36bdd5727c1004858b90580f362..c9f59b6ce33f693fa62dae7ad7d0f82b7ee4c337 100644 (file)
@@ -18,6 +18,7 @@
 
        aliases {
                serial0 = &scif2;
+               serial1 = &scif1;
                ethernet0 = &avb;
        };
 
                function = "avb";
        };
 
+       scif1_pins: scif1 {
+               groups = "scif1_data_a", "scif1_ctrl";
+               function = "scif1";
+       };
+
        scif2_pins: scif2 {
                groups = "scif2_data_a";
                function = "scif2";
        status = "okay";
 
        phy0: ethernet-phy@0 {
-               rxc-skew-ps = <900>;
-               rxdv-skew-ps = <0>;
-               rxd0-skew-ps = <0>;
-               rxd1-skew-ps = <0>;
-               rxd2-skew-ps = <0>;
-               rxd3-skew-ps = <0>;
-               txc-skew-ps = <900>;
-               txen-skew-ps = <0>;
-               txd0-skew-ps = <0>;
-               txd1-skew-ps = <0>;
-               txd2-skew-ps = <0>;
-               txd3-skew-ps = <0>;
+               rxc-skew-ps = <1500>;
                reg = <0>;
                interrupt-parent = <&gpio2>;
                interrupts = <11 IRQ_TYPE_LEVEL_LOW>;
        status = "okay";
 };
 
+&scif1 {
+       pinctrl-0 = <&scif1_pins>;
+       pinctrl-names = "default";
+
+       uart-has-rtscts;
+       status = "okay";
+};
+
 &scif2 {
        pinctrl-0 = <&scif2_pins>;
        pinctrl-names = "default";
 
 &scif_clk {
        clock-frequency = <14745600>;
-       status = "okay";
 };
 
 &i2c2 {
        timeout-sec = <60>;
        status = "okay";
 };
+
+&i2c_dvfs {
+       status = "okay";
+};
index f7120cdedd0d67b2d60dc06ae83ca9d26ecf7c79..2ec1ed5f499165ada8a7b2e41cbf4bf1339aa6af 100644 (file)
                i2c4 = &i2c4;
                i2c5 = &i2c5;
                i2c6 = &i2c6;
+               i2c7 = &i2c_dvfs;
        };
 
        psci {
-               compatible = "arm,psci-0.2";
+               compatible = "arm,psci-1.0", "arm,psci-0.2";
                method = "smc";
        };
 
@@ -36,7 +37,6 @@
                #address-cells = <1>;
                #size-cells = <0>;
 
-               /* 1 core only at this point */
                a57_0: cpu@0 {
                        compatible = "arm,cortex-a57", "arm,armv8";
                        reg = <0x0>;
                        enable-method = "psci";
                };
 
-               L2_CA57: cache-controller@0 {
+               a57_1: cpu@1 {
+                       compatible = "arm,cortex-a57","arm,armv8";
+                       reg = <0x1>;
+                       device_type = "cpu";
+                       power-domains = <&sysc R8A7796_PD_CA57_CPU1>;
+                       next-level-cache = <&L2_CA57>;
+                       enable-method = "psci";
+               };
+
+               a53_0: cpu@100 {
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       reg = <0x100>;
+                       device_type = "cpu";
+                       power-domains = <&sysc R8A7796_PD_CA53_CPU0>;
+                       next-level-cache = <&L2_CA53>;
+                       enable-method = "psci";
+               };
+
+               a53_1: cpu@101 {
+                       compatible = "arm,cortex-a53","arm,armv8";
+                       reg = <0x101>;
+                       device_type = "cpu";
+                       power-domains = <&sysc R8A7796_PD_CA53_CPU1>;
+                       next-level-cache = <&L2_CA53>;
+                       enable-method = "psci";
+               };
+
+               a53_2: cpu@102 {
+                       compatible = "arm,cortex-a53","arm,armv8";
+                       reg = <0x102>;
+                       device_type = "cpu";
+                       power-domains = <&sysc R8A7796_PD_CA53_CPU2>;
+                       next-level-cache = <&L2_CA53>;
+                       enable-method = "psci";
+               };
+
+               a53_3: cpu@103 {
+                       compatible = "arm,cortex-a53","arm,armv8";
+                       reg = <0x103>;
+                       device_type = "cpu";
+                       power-domains = <&sysc R8A7796_PD_CA53_CPU3>;
+                       next-level-cache = <&L2_CA53>;
+                       enable-method = "psci";
+               };
+
+               L2_CA57: cache-controller-0 {
                        compatible = "cache";
-                       reg = <0>;
                        power-domains = <&sysc R8A7796_PD_CA57_SCU>;
                        cache-unified;
                        cache-level = <2>;
                };
+
+               L2_CA53: cache-controller-1 {
+                       compatible = "cache";
+                       power-domains = <&sysc R8A7796_PD_CA53_SCU>;
+                       cache-unified;
+                       cache-level = <2>;
+               };
        };
 
        extal_clk: extal {
                              <0x0 0xf1040000 0 0x20000>,
                              <0x0 0xf1060000 0 0x20000>;
                        interrupts = <GIC_PPI 9
-                                       (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_HIGH)>;
+                                       (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_HIGH)>;
                        clocks = <&cpg CPG_MOD 408>;
                        clock-names = "clk";
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 408>;
                };
 
                timer {
                        compatible = "arm,armv8-timer";
                        interrupts = <GIC_PPI 13
-                                       (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
+                                       (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>,
                                     <GIC_PPI 14
-                                       (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
+                                       (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>,
                                     <GIC_PPI 11
-                                       (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>,
+                                       (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>,
                                     <GIC_PPI 10
-                                       (GIC_CPU_MASK_SIMPLE(1) | IRQ_TYPE_LEVEL_LOW)>;
+                                       (GIC_CPU_MASK_SIMPLE(6) | IRQ_TYPE_LEVEL_LOW)>;
                };
 
                wdt0: watchdog@e6020000 {
                        reg = <0 0xe6020000 0 0x0c>;
                        clocks = <&cpg CPG_MOD 402>;
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 402>;
                        status = "disabled";
                };
 
                        interrupt-controller;
                        clocks = <&cpg CPG_MOD 912>;
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 912>;
                };
 
                gpio1: gpio@e6051000 {
                        interrupt-controller;
                        clocks = <&cpg CPG_MOD 911>;
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 911>;
                };
 
                gpio2: gpio@e6052000 {
                        interrupt-controller;
                        clocks = <&cpg CPG_MOD 910>;
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 910>;
                };
 
                gpio3: gpio@e6053000 {
                        interrupt-controller;
                        clocks = <&cpg CPG_MOD 909>;
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 909>;
                };
 
                gpio4: gpio@e6054000 {
                        interrupt-controller;
                        clocks = <&cpg CPG_MOD 908>;
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 908>;
                };
 
                gpio5: gpio@e6055000 {
                        interrupt-controller;
                        clocks = <&cpg CPG_MOD 907>;
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 907>;
                };
 
                gpio6: gpio@e6055400 {
                        interrupt-controller;
                        clocks = <&cpg CPG_MOD 906>;
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 906>;
                };
 
                gpio7: gpio@e6055800 {
                        interrupt-controller;
                        clocks = <&cpg CPG_MOD 905>;
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 905>;
                };
 
                pfc: pin-controller@e6060000 {
                        reg = <0 0xe6060000 0 0x50c>;
                };
 
+               pmu_a57 {
+                       compatible = "arm,cortex-a57-pmu";
+                       interrupts = <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 73 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupt-affinity = <&a57_0>,
+                                            <&a57_1>;
+               };
+
+               pmu_a53 {
+                       compatible = "arm,cortex-a53-pmu";
+                       interrupts = <GIC_SPI 84 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 87 IRQ_TYPE_LEVEL_HIGH>;
+                       interrupt-affinity = <&a53_0>,
+                                            <&a53_1>,
+                                            <&a53_2>,
+                                            <&a53_3>;
+               };
+
                cpg: clock-controller@e6150000 {
                        compatible = "renesas,r8a7796-cpg-mssr";
                        reg = <0 0xe6150000 0 0x1000>;
                        clock-names = "extal", "extalr";
                        #clock-cells = <2>;
                        #power-domain-cells = <0>;
+                       #reset-cells = <1>;
                };
 
                rst: reset-controller@e6160000 {
                        #power-domain-cells = <1>;
                };
 
+               i2c_dvfs: i2c@e60b0000 {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       compatible = "renesas,iic-r8a7796",
+                                    "renesas,rcar-gen3-iic",
+                                    "renesas,rmobile-iic";
+                       reg = <0 0xe60b0000 0 0x425>;
+                       interrupts = <GIC_SPI 173 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 926>;
+                       power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 926>;
+                       status = "disabled";
+               };
+
                i2c0: i2c@e6500000 {
                        #address-cells = <1>;
                        #size-cells = <0>;
                        interrupts = <GIC_SPI 287 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 931>;
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 931>;
                        dmas = <&dmac1 0x91>, <&dmac1 0x90>,
                               <&dmac2 0x91>, <&dmac2 0x90>;
                        dma-names = "tx", "rx", "tx", "rx";
                        interrupts = <GIC_SPI 288 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 930>;
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 930>;
                        dmas = <&dmac1 0x93>, <&dmac1 0x92>,
                               <&dmac2 0x93>, <&dmac2 0x92>;
                        dma-names = "tx", "rx", "tx", "rx";
                        interrupts = <GIC_SPI 286 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 929>;
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 929>;
                        dmas = <&dmac1 0x95>, <&dmac1 0x94>,
                               <&dmac2 0x95>, <&dmac2 0x94>;
                        dma-names = "tx", "rx", "tx", "rx";
                        interrupts = <GIC_SPI 290 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 928>;
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 928>;
                        dmas = <&dmac0 0x97>, <&dmac0 0x96>;
                        dma-names = "tx", "rx";
                        i2c-scl-internal-delay-ns = <110>;
                        interrupts = <GIC_SPI 19 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 927>;
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 927>;
                        dmas = <&dmac0 0x99>, <&dmac0 0x98>;
                        dma-names = "tx", "rx";
                        i2c-scl-internal-delay-ns = <110>;
                        interrupts = <GIC_SPI 20 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 919>;
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 919>;
                        dmas = <&dmac0 0x9b>, <&dmac0 0x9a>;
                        dma-names = "tx", "rx";
                        i2c-scl-internal-delay-ns = <110>;
                        interrupts = <GIC_SPI 21 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 918>;
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 918>;
                        dmas = <&dmac0 0x9d>, <&dmac0 0x9c>;
                        dma-names = "tx", "rx";
                        i2c-scl-internal-delay-ns = <6>;
                        assigned-clocks = <&cpg CPG_CORE R8A7796_CLK_CANFD>;
                        assigned-clock-rates = <40000000>;
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 916>;
                        status = "disabled";
                };
 
                        assigned-clocks = <&cpg CPG_CORE R8A7796_CLK_CANFD>;
                        assigned-clock-rates = <40000000>;
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 915>;
                        status = "disabled";
                };
 
                        assigned-clocks = <&cpg CPG_CORE R8A7796_CLK_CANFD>;
                        assigned-clock-rates = <40000000>;
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 914>;
                        status = "disabled";
 
                        channel0 {
                                          "ch24";
                        clocks = <&cpg CPG_MOD 812>;
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
-                       phy-mode = "rgmii-id";
+                       resets = <&cpg 812>;
+                       phy-mode = "rgmii-txid";
                        #address-cells = <1>;
                        #size-cells = <0>;
                        status = "disabled";
                };
 
+               hscif0: serial@e6540000 {
+                       compatible = "renesas,hscif-r8a7796",
+                                    "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 R8A7796_CLK_S3D1>,
+                                <&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 R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 520>;
+                       status = "disabled";
+               };
+
+               hscif1: serial@e6550000 {
+                       compatible = "renesas,hscif-r8a7796",
+                                    "renesas,rcar-gen3-hscif",
+                                    "renesas,hscif";
+                       reg = <0 0xe6550000 0 0x60>;
+                       interrupts = <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 519>,
+                                <&cpg CPG_CORE R8A7796_CLK_S3D1>,
+                                <&scif_clk>;
+                       clock-names = "fck", "brg_int", "scif_clk";
+                       dmas = <&dmac1 0x33>, <&dmac1 0x32>,
+                              <&dmac2 0x33>, <&dmac2 0x32>;
+                       dma-names = "tx", "rx", "tx", "rx";
+                       power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 519>;
+                       status = "disabled";
+               };
+
+               hscif2: serial@e6560000 {
+                       compatible = "renesas,hscif-r8a7796",
+                                    "renesas,rcar-gen3-hscif",
+                                    "renesas,hscif";
+                       reg = <0 0xe6560000 0 0x60>;
+                       interrupts = <GIC_SPI 144 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 518>,
+                                <&cpg CPG_CORE R8A7796_CLK_S3D1>,
+                                <&scif_clk>;
+                       clock-names = "fck", "brg_int", "scif_clk";
+                       dmas = <&dmac1 0x35>, <&dmac1 0x34>,
+                              <&dmac2 0x35>, <&dmac2 0x34>;
+                       dma-names = "tx", "rx", "tx", "rx";
+                       power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 518>;
+                       status = "disabled";
+               };
+
+               hscif3: serial@e66a0000 {
+                       compatible = "renesas,hscif-r8a7796",
+                                    "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 R8A7796_CLK_S3D1>,
+                                <&scif_clk>;
+                       clock-names = "fck", "brg_int", "scif_clk";
+                       dmas = <&dmac0 0x37>, <&dmac0 0x36>;
+                       dma-names = "tx", "rx";
+                       power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 517>;
+                       status = "disabled";
+               };
+
+               hscif4: serial@e66b0000 {
+                       compatible = "renesas,hscif-r8a7796",
+                                    "renesas,rcar-gen3-hscif",
+                                    "renesas,hscif";
+                       reg = <0 0xe66b0000 0 0x60>;
+                       interrupts = <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 516>,
+                                <&cpg CPG_CORE R8A7796_CLK_S3D1>,
+                                <&scif_clk>;
+                       clock-names = "fck", "brg_int", "scif_clk";
+                       dmas = <&dmac0 0x39>, <&dmac0 0x38>;
+                       dma-names = "tx", "rx";
+                       power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 516>;
+                       status = "disabled";
+               };
+
+               scif0: serial@e6e60000 {
+                       compatible = "renesas,scif-r8a7796",
+                                    "renesas,rcar-gen3-scif", "renesas,scif";
+                       reg = <0 0xe6e60000 0 64>;
+                       interrupts = <GIC_SPI 152 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 207>,
+                                <&cpg CPG_CORE R8A7796_CLK_S3D1>,
+                                <&scif_clk>;
+                       clock-names = "fck", "brg_int", "scif_clk";
+                       dmas = <&dmac1 0x51>, <&dmac1 0x50>,
+                              <&dmac2 0x51>, <&dmac2 0x50>;
+                       dma-names = "tx", "rx", "tx", "rx";
+                       power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 207>;
+                       status = "disabled";
+               };
+
+               scif1: serial@e6e68000 {
+                       compatible = "renesas,scif-r8a7796",
+                                    "renesas,rcar-gen3-scif", "renesas,scif";
+                       reg = <0 0xe6e68000 0 64>;
+                       interrupts = <GIC_SPI 153 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 206>,
+                                <&cpg CPG_CORE R8A7796_CLK_S3D1>,
+                                <&scif_clk>;
+                       clock-names = "fck", "brg_int", "scif_clk";
+                       dmas = <&dmac1 0x53>, <&dmac1 0x52>,
+                              <&dmac2 0x53>, <&dmac2 0x52>;
+                       dma-names = "tx", "rx", "tx", "rx";
+                       power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 206>;
+                       status = "disabled";
+               };
+
                scif2: serial@e6e88000 {
                        compatible = "renesas,scif-r8a7796",
                                     "renesas,rcar-gen3-scif", "renesas,scif";
                                 <&scif_clk>;
                        clock-names = "fck", "brg_int", "scif_clk";
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 310>;
+                       status = "disabled";
+               };
+
+               scif3: serial@e6c50000 {
+                       compatible = "renesas,scif-r8a7796",
+                                    "renesas,rcar-gen3-scif", "renesas,scif";
+                       reg = <0 0xe6c50000 0 64>;
+                       interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 204>,
+                                <&cpg CPG_CORE R8A7796_CLK_S3D1>,
+                                <&scif_clk>;
+                       clock-names = "fck", "brg_int", "scif_clk";
+                       dmas = <&dmac0 0x57>, <&dmac0 0x56>;
+                       dma-names = "tx", "rx";
+                       power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 204>;
+                       status = "disabled";
+               };
+
+               scif4: serial@e6c40000 {
+                       compatible = "renesas,scif-r8a7796",
+                                    "renesas,rcar-gen3-scif", "renesas,scif";
+                       reg = <0 0xe6c40000 0 64>;
+                       interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 203>,
+                                <&cpg CPG_CORE R8A7796_CLK_S3D1>,
+                                <&scif_clk>;
+                       clock-names = "fck", "brg_int", "scif_clk";
+                       dmas = <&dmac0 0x59>, <&dmac0 0x58>;
+                       dma-names = "tx", "rx";
+                       power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 203>;
+                       status = "disabled";
+               };
+
+               scif5: serial@e6f30000 {
+                       compatible = "renesas,scif-r8a7796",
+                                    "renesas,rcar-gen3-scif", "renesas,scif";
+                       reg = <0 0xe6f30000 0 64>;
+                       interrupts = <GIC_SPI 17 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cpg CPG_MOD 202>,
+                                <&cpg CPG_CORE R8A7796_CLK_S3D1>,
+                                <&scif_clk>;
+                       clock-names = "fck", "brg_int", "scif_clk";
+                       dmas = <&dmac1 0x5b>, <&dmac1 0x5a>,
+                              <&dmac2 0x5b>, <&dmac2 0x5a>;
+                       dma-names = "tx", "rx", "tx", "rx";
+                       power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 202>;
                        status = "disabled";
                };
 
                               <&dmac2 0x41>, <&dmac2 0x40>;
                        dma-names = "tx", "rx";
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 211>;
                        #address-cells = <1>;
                        #size-cells = <0>;
                        status = "disabled";
                               <&dmac2 0x43>, <&dmac2 0x42>;
                        dma-names = "tx", "rx";
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 210>;
                        #address-cells = <1>;
                        #size-cells = <0>;
                        status = "disabled";
                        dmas = <&dmac0 0x45>, <&dmac0 0x44>;
                        dma-names = "tx", "rx";
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 209>;
                        #address-cells = <1>;
                        #size-cells = <0>;
                        status = "disabled";
                        dmas = <&dmac0 0x47>, <&dmac0 0x46>;
                        dma-names = "tx", "rx";
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 208>;
                        #address-cells = <1>;
                        #size-cells = <0>;
                        status = "disabled";
                        clocks = <&cpg CPG_MOD 219>;
                        clock-names = "fck";
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 219>;
                        #dma-cells = <1>;
                        dma-channels = <16>;
                };
                        clocks = <&cpg CPG_MOD 218>;
                        clock-names = "fck";
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 218>;
                        #dma-cells = <1>;
                        dma-channels = <16>;
                };
                        clocks = <&cpg CPG_MOD 217>;
                        clock-names = "fck";
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 217>;
                        #dma-cells = <1>;
                        dma-channels = <16>;
                };
                        clocks = <&cpg CPG_MOD 314>;
                        max-frequency = <200000000>;
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 314>;
                        status = "disabled";
                };
 
                        clocks = <&cpg CPG_MOD 313>;
                        max-frequency = <200000000>;
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 313>;
                        status = "disabled";
                };
 
                        clocks = <&cpg CPG_MOD 312>;
                        max-frequency = <200000000>;
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 312>;
                        status = "disabled";
                };
 
                        clocks = <&cpg CPG_MOD 311>;
                        max-frequency = <200000000>;
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 311>;
                        status = "disabled";
                };
 
                                     <GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 522>;
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
+                       resets = <&cpg 522>;
                        #thermal-sensor-cells = <1>;
                        status = "okay";
                };
index 3a862894ea44f5b17da2a6e3fa208a631738535b..b5636bba6b1c0ed9150d40bf32fae3209a040e5e 100644 (file)
@@ -1,9 +1,11 @@
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3328-evb.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-evb-act8846.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-geekbox.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-orion-r68-meta.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-px5-evb.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3368-r88.dtb
 dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-evb.dtb
+dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3399-gru-kevin.dtb
 
 always         := $(dtb-y)
 subdir-y       := $(dts-dirs)
diff --git a/arch/arm64/boot/dts/rockchip/rk3328-evb.dts b/arch/arm64/boot/dts/rockchip/rk3328-evb.dts
new file mode 100644 (file)
index 0000000..cf27239
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "rk3328.dtsi"
+
+/ {
+       model = "Rockchip RK3328 EVB";
+       compatible = "rockchip,rk3328-evb", "rockchip,rk3328";
+
+       chosen {
+               stdout-path = "serial2:1500000n8";
+       };
+};
+
+&uart2 {
+       status = "okay";
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3328.dtsi b/arch/arm64/boot/dts/rockchip/rk3328.dtsi
new file mode 100644 (file)
index 0000000..7e69f1f
--- /dev/null
@@ -0,0 +1,1264 @@
+/*
+ * Copyright (c) 2017 Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <dt-bindings/clock/rk3328-cru.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/pinctrl/rockchip.h>
+#include <dt-bindings/power/rk3328-power.h>
+#include <dt-bindings/soc/rockchip,boot-mode.h>
+
+/ {
+       compatible = "rockchip,rk3328";
+
+       interrupt-parent = <&gic>;
+       #address-cells = <2>;
+       #size-cells = <2>;
+
+       aliases {
+               serial0 = &uart0;
+               serial1 = &uart1;
+               serial2 = &uart2;
+               i2c0 = &i2c0;
+               i2c1 = &i2c1;
+               i2c2 = &i2c2;
+               i2c3 = &i2c3;
+       };
+
+       cpus {
+               #address-cells = <2>;
+               #size-cells = <0>;
+
+               cpu0: cpu@0 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       reg = <0x0 0x0>;
+                       clocks = <&cru ARMCLK>;
+                       enable-method = "psci";
+                       next-level-cache = <&l2>;
+               };
+
+               cpu1: cpu@1 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       reg = <0x0 0x1>;
+                       clocks = <&cru ARMCLK>;
+                       enable-method = "psci";
+                       next-level-cache = <&l2>;
+               };
+
+               cpu2: cpu@2 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       reg = <0x0 0x2>;
+                       clocks = <&cru ARMCLK>;
+                       enable-method = "psci";
+                       next-level-cache = <&l2>;
+               };
+
+               cpu3: cpu@3 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       reg = <0x0 0x3>;
+                       clocks = <&cru ARMCLK>;
+                       enable-method = "psci";
+                       next-level-cache = <&l2>;
+               };
+
+               l2: l2-cache0 {
+                       compatible = "cache";
+               };
+       };
+
+       amba {
+               compatible = "simple-bus";
+               #address-cells = <2>;
+               #size-cells = <2>;
+               ranges;
+
+               dmac: dmac@ff1f0000 {
+                       compatible = "arm,pl330", "arm,primecell";
+                       reg = <0x0 0xff1f0000 0x0 0x4000>;
+                       interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cru ACLK_DMAC>;
+                       clock-names = "apb_pclk";
+                       #dma-cells = <1>;
+               };
+       };
+
+       arm-pmu {
+               compatible = "arm,cortex-a53-pmu";
+               interrupts = <GIC_SPI 100 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-affinity = <&cpu0>, <&cpu1>, <&cpu2>, <&cpu3>;
+       };
+
+       psci {
+               compatible = "arm,psci-1.0", "arm,psci-0.2";
+               method = "smc";
+       };
+
+       timer {
+               compatible = "arm,armv8-timer";
+               interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+                            <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+                            <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
+                            <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+       };
+
+       xin24m: xin24m {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <24000000>;
+               clock-output-names = "xin24m";
+       };
+
+       grf: syscon@ff100000 {
+               compatible = "rockchip,rk3328-grf", "syscon", "simple-mfd";
+               reg = <0x0 0xff100000 0x0 0x1000>;
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               power: power-controller {
+                       compatible = "rockchip,rk3328-power-controller";
+                       #power-domain-cells = <1>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       pd_hevc@RK3328_PD_HEVC {
+                               reg = <RK3328_PD_HEVC>;
+                       };
+                       pd_video@RK3328_PD_VIDEO {
+                               reg = <RK3328_PD_VIDEO>;
+                       };
+                       pd_vpu@RK3328_PD_VPU {
+                               reg = <RK3328_PD_VPU>;
+                       };
+               };
+
+               reboot-mode {
+                       compatible = "syscon-reboot-mode";
+                       offset = <0x5c8>;
+                       mode-normal = <BOOT_NORMAL>;
+                       mode-recovery = <BOOT_RECOVERY>;
+                       mode-bootloader = <BOOT_FASTBOOT>;
+                       mode-loader = <BOOT_BL_DOWNLOAD>;
+               };
+
+       };
+
+       uart0: serial@ff110000 {
+               compatible = "rockchip,rk3328-uart", "snps,dw-apb-uart";
+               reg = <0x0 0xff110000 0x0 0x100>;
+               interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&cru SCLK_UART0>, <&cru PCLK_UART0>;
+               clock-names = "baudclk", "apb_pclk";
+               dmas = <&dmac 2>, <&dmac 3>;
+               #dma-cells = <2>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&uart0_xfer &uart0_cts &uart0_rts>;
+               reg-io-width = <4>;
+               reg-shift = <2>;
+               status = "disabled";
+       };
+
+       uart1: serial@ff120000 {
+               compatible = "rockchip,rk3328-uart", "snps,dw-apb-uart";
+               reg = <0x0 0xff120000 0x0 0x100>;
+               interrupts = <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&cru SCLK_UART1>, <&cru PCLK_UART1>;
+               clock-names = "sclk_uart", "pclk_uart";
+               dmas = <&dmac 4>, <&dmac 5>;
+               #dma-cells = <2>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&uart1_xfer &uart1_cts &uart1_rts>;
+               reg-io-width = <4>;
+               reg-shift = <2>;
+               status = "disabled";
+       };
+
+       uart2: serial@ff130000 {
+               compatible = "rockchip,rk3328-uart", "snps,dw-apb-uart";
+               reg = <0x0 0xff130000 0x0 0x100>;
+               interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+               clocks = <&cru SCLK_UART2>, <&cru PCLK_UART2>;
+               clock-names = "baudclk", "apb_pclk";
+               dmas = <&dmac 6>, <&dmac 7>;
+               #dma-cells = <2>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&uart2m1_xfer>;
+               reg-io-width = <4>;
+               reg-shift = <2>;
+               status = "disabled";
+       };
+
+       i2c0: i2c@ff150000 {
+               compatible = "rockchip,rk3328-i2c", "rockchip,rk3399-i2c";
+               reg = <0x0 0xff150000 0x0 0x1000>;
+               interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               clocks = <&cru SCLK_I2C0>, <&cru PCLK_I2C0>;
+               clock-names = "i2c", "pclk";
+               pinctrl-names = "default";
+               pinctrl-0 = <&i2c0_xfer>;
+               status = "disabled";
+       };
+
+       i2c1: i2c@ff160000 {
+               compatible = "rockchip,rk3328-i2c", "rockchip,rk3399-i2c";
+               reg = <0x0 0xff160000 0x0 0x1000>;
+               interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               clocks = <&cru SCLK_I2C1>, <&cru PCLK_I2C1>;
+               clock-names = "i2c", "pclk";
+               pinctrl-names = "default";
+               pinctrl-0 = <&i2c1_xfer>;
+               status = "disabled";
+       };
+
+       i2c2: i2c@ff170000 {
+               compatible = "rockchip,rk3328-i2c", "rockchip,rk3399-i2c";
+               reg = <0x0 0xff170000 0x0 0x1000>;
+               interrupts = <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               clocks = <&cru SCLK_I2C2>, <&cru PCLK_I2C2>;
+               clock-names = "i2c", "pclk";
+               pinctrl-names = "default";
+               pinctrl-0 = <&i2c2_xfer>;
+               status = "disabled";
+       };
+
+       i2c3: i2c@ff180000 {
+               compatible = "rockchip,rk3328-i2c", "rockchip,rk3399-i2c";
+               reg = <0x0 0xff180000 0x0 0x1000>;
+               interrupts = <GIC_SPI 39 IRQ_TYPE_LEVEL_HIGH>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               clocks = <&cru SCLK_I2C3>, <&cru PCLK_I2C3>;
+               clock-names = "i2c", "pclk";
+               pinctrl-names = "default";
+               pinctrl-0 = <&i2c3_xfer>;
+               status = "disabled";
+       };
+
+       spi0: spi@ff190000 {
+               compatible = "rockchip,rk3328-spi", "rockchip,rk3066-spi";
+               reg = <0x0 0xff190000 0x0 0x1000>;
+               interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>;
+               #address-cells = <1>;
+               #size-cells = <0>;
+               clocks = <&cru SCLK_SPI>, <&cru PCLK_SPI>;
+               clock-names = "spiclk", "apb_pclk";
+               dmas = <&dmac 8>, <&dmac 9>;
+               dma-names = "tx", "rx";
+               pinctrl-names = "default";
+               pinctrl-0 = <&spi0m2_clk &spi0m2_tx &spi0m2_rx &spi0m2_cs0>;
+               status = "disabled";
+       };
+
+       wdt: watchdog@ff1a0000 {
+               compatible = "snps,dw-wdt";
+               reg = <0x0 0xff1a0000 0x0 0x100>;
+               interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+       };
+
+       saradc: adc@ff280000 {
+               compatible = "rockchip,rk3328-saradc", "rockchip,rk3399-saradc";
+               reg = <0x0 0xff280000 0x0 0x100>;
+               interrupts = <GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>;
+               #io-channel-cells = <1>;
+               clocks = <&cru SCLK_SARADC>, <&cru PCLK_SARADC>;
+               clock-names = "saradc", "apb_pclk";
+               resets = <&cru SRST_SARADC_P>;
+               reset-names = "saradc-apb";
+               status = "disabled";
+       };
+
+       cru: clock-controller@ff440000 {
+               compatible = "rockchip,rk3328-cru", "rockchip,cru", "syscon";
+               reg = <0x0 0xff440000 0x0 0x1000>;
+               rockchip,grf = <&grf>;
+               #clock-cells = <1>;
+               #reset-cells = <1>;
+               assigned-clocks =
+                       /*
+                        * CPLL should run at 1200, but that is to high for
+                        * the initial dividers of most of its children.
+                        * We need set cpll child clk div first,
+                        * and then set the cpll frequency.
+                        */
+                       <&cru DCLK_LCDC>, <&cru SCLK_PDM>,
+                       <&cru SCLK_RTC32K>, <&cru SCLK_UART0>,
+                       <&cru SCLK_UART1>, <&cru SCLK_UART2>,
+                       <&cru ACLK_BUS_PRE>, <&cru ACLK_PERI_PRE>,
+                       <&cru ACLK_VIO_PRE>, <&cru ACLK_RGA_PRE>,
+                       <&cru ACLK_VOP_PRE>, <&cru ACLK_RKVDEC_PRE>,
+                       <&cru ACLK_RKVENC>, <&cru ACLK_VPU_PRE>,
+                       <&cru SCLK_VDEC_CABAC>, <&cru SCLK_VDEC_CORE>,
+                       <&cru SCLK_VENC_CORE>, <&cru SCLK_VENC_DSP>,
+                       <&cru SCLK_SDIO>, <&cru SCLK_TSP>,
+                       <&cru SCLK_WIFI>, <&cru ARMCLK>,
+                       <&cru PLL_GPLL>, <&cru PLL_CPLL>,
+                       <&cru ACLK_BUS_PRE>, <&cru HCLK_BUS_PRE>,
+                       <&cru PCLK_BUS_PRE>, <&cru ACLK_PERI_PRE>,
+                       <&cru HCLK_PERI>, <&cru PCLK_PERI>,
+                       <&cru SCLK_RTC32K>;
+               assigned-clock-parents =
+                       <&cru HDMIPHY>, <&cru PLL_APLL>,
+                       <&cru PLL_GPLL>, <&xin24m>,
+                       <&xin24m>, <&xin24m>;
+               assigned-clock-rates =
+                       <0>, <61440000>,
+                       <0>, <24000000>,
+                       <24000000>, <24000000>,
+                       <15000000>, <15000000>,
+                       <100000000>, <100000000>,
+                       <100000000>, <100000000>,
+                       <50000000>, <100000000>,
+                       <100000000>, <100000000>,
+                       <50000000>, <50000000>,
+                       <50000000>, <50000000>,
+                       <24000000>, <600000000>,
+                       <491520000>, <1200000000>,
+                       <150000000>, <75000000>,
+                       <75000000>, <150000000>,
+                       <75000000>, <75000000>,
+                       <32768>;
+       };
+
+       gmac2io: ethernet@ff540000 {
+               compatible = "rockchip,rk3328-gmac";
+               reg = <0x0 0xff540000 0x0 0x10000>;
+               interrupts = <GIC_SPI 24 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-names = "macirq";
+               clocks = <&cru SCLK_MAC2IO>, <&cru SCLK_MAC2IO_RX>,
+                        <&cru SCLK_MAC2IO_TX>, <&cru SCLK_MAC2IO_REF>,
+                        <&cru SCLK_MAC2IO_REFOUT>, <&cru ACLK_MAC2IO>,
+                        <&cru PCLK_MAC2IO>;
+               clock-names = "stmmaceth", "mac_clk_rx",
+                             "mac_clk_tx", "clk_mac_ref",
+                             "clk_mac_refout", "aclk_mac",
+                             "pclk_mac";
+               resets = <&cru SRST_GMAC2IO_A>;
+               reset-names = "stmmaceth";
+               rockchip,grf = <&grf>;
+               status = "disabled";
+       };
+
+       gic: interrupt-controller@ff811000 {
+               compatible = "arm,gic-400";
+               #interrupt-cells = <3>;
+               #address-cells = <0>;
+               interrupt-controller;
+               reg = <0x0 0xff811000 0 0x1000>,
+                     <0x0 0xff812000 0 0x2000>,
+                     <0x0 0xff814000 0 0x2000>,
+                     <0x0 0xff816000 0 0x2000>;
+               interrupts = <GIC_PPI 9
+                     (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+       };
+
+       pinctrl: pinctrl {
+               compatible = "rockchip,rk3328-pinctrl";
+               rockchip,grf = <&grf>;
+               #address-cells = <2>;
+               #size-cells = <2>;
+               ranges;
+
+               gpio0: gpio0@ff210000 {
+                       compatible = "rockchip,gpio-bank";
+                       reg = <0x0 0xff210000 0x0 0x100>;
+                       interrupts = <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cru PCLK_GPIO0>;
+
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpio1: gpio1@ff220000 {
+                       compatible = "rockchip,gpio-bank";
+                       reg = <0x0 0xff220000 0x0 0x100>;
+                       interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cru PCLK_GPIO1>;
+
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpio2: gpio2@ff230000 {
+                       compatible = "rockchip,gpio-bank";
+                       reg = <0x0 0xff230000 0x0 0x100>;
+                       interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cru PCLK_GPIO2>;
+
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               gpio3: gpio3@ff240000 {
+                       compatible = "rockchip,gpio-bank";
+                       reg = <0x0 0xff240000 0x0 0x100>;
+                       interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&cru PCLK_GPIO3>;
+
+                       gpio-controller;
+                       #gpio-cells = <2>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <2>;
+               };
+
+               pcfg_pull_up: pcfg-pull-up {
+                       bias-pull-up;
+               };
+
+               pcfg_pull_down: pcfg-pull-down {
+                       bias-pull-down;
+               };
+
+               pcfg_pull_none: pcfg-pull-none {
+                       bias-disable;
+               };
+
+               pcfg_pull_none_2ma: pcfg-pull-none-2ma {
+                       bias-disable;
+                       drive-strength = <2>;
+               };
+
+               pcfg_pull_up_2ma: pcfg-pull-up-2ma {
+                       bias-pull-up;
+                       drive-strength = <2>;
+               };
+
+               pcfg_pull_up_4ma: pcfg-pull-up-4ma {
+                       bias-pull-up;
+                       drive-strength = <4>;
+               };
+
+               pcfg_pull_none_4ma: pcfg-pull-none-4ma {
+                       bias-disable;
+                       drive-strength = <4>;
+               };
+
+               pcfg_pull_down_4ma: pcfg-pull-down-4ma {
+                       bias-pull-down;
+                       drive-strength = <4>;
+               };
+
+               pcfg_pull_none_8ma: pcfg-pull-none-8ma {
+                       bias-disable;
+                       drive-strength = <8>;
+               };
+
+               pcfg_pull_up_8ma: pcfg-pull-up-8ma {
+                       bias-pull-up;
+                       drive-strength = <8>;
+               };
+
+               pcfg_pull_none_12ma: pcfg-pull-none-12ma {
+                       bias-disable;
+                       drive-strength = <12>;
+               };
+
+               pcfg_pull_up_12ma: pcfg-pull-up-12ma {
+                       bias-pull-up;
+                       drive-strength = <12>;
+               };
+
+               pcfg_output_high: pcfg-output-high {
+                       output-high;
+               };
+
+               pcfg_output_low: pcfg-output-low {
+                       output-low;
+               };
+
+               pcfg_input_high: pcfg-input-high {
+                       bias-pull-up;
+                       input-enable;
+               };
+
+               pcfg_input: pcfg-input {
+                       input-enable;
+               };
+
+               i2c0 {
+                       i2c0_xfer: i2c0-xfer {
+                               rockchip,pins = <2 RK_PD0 1 &pcfg_pull_none>,
+                                               <2 RK_PD1 1 &pcfg_pull_none>;
+                       };
+               };
+
+               i2c1 {
+                       i2c1_xfer: i2c1-xfer {
+                               rockchip,pins = <2 RK_PA4 2 &pcfg_pull_none>,
+                                               <2 RK_PA5 2 &pcfg_pull_none>;
+                       };
+               };
+
+               i2c2 {
+                       i2c2_xfer: i2c2-xfer {
+                               rockchip,pins = <2 RK_PB5 1 &pcfg_pull_none>,
+                                               <2 RK_PB6 1 &pcfg_pull_none>;
+                       };
+               };
+
+               i2c3 {
+                       i2c3_xfer: i2c3-xfer {
+                               rockchip,pins = <0 RK_PA5 2 &pcfg_pull_none>,
+                                               <0 RK_PA6 2 &pcfg_pull_none>;
+                       };
+                       i2c3_gpio: i2c3-gpio {
+                               rockchip,pins =
+                                       <0 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>,
+                                       <0 RK_PA6 RK_FUNC_GPIO &pcfg_pull_none>;
+                       };
+               };
+
+               hdmi_i2c {
+                       hdmii2c_xfer: hdmii2c-xfer {
+                               rockchip,pins = <0 RK_PA5 1 &pcfg_pull_none>,
+                                               <0 RK_PA6 1 &pcfg_pull_none>;
+                       };
+               };
+
+               tsadc {
+                       otp_gpio: otp-gpio {
+                               rockchip,pins = <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>;
+                       };
+
+                       otp_out: otp-out {
+                               rockchip,pins = <2 RK_PB5 1 &pcfg_pull_none>;
+                       };
+               };
+
+               uart0 {
+                       uart0_xfer: uart0-xfer {
+                               rockchip,pins = <1 RK_PB1 1 &pcfg_pull_up>,
+                                               <1 RK_PB0 1 &pcfg_pull_none>;
+                       };
+
+                       uart0_cts: uart0-cts {
+                               rockchip,pins = <1 RK_PB3 1 &pcfg_pull_none>;
+                       };
+
+                       uart0_rts: uart0-rts {
+                               rockchip,pins = <1 RK_PB2 1 &pcfg_pull_none>;
+                       };
+
+                       uart0_rts_gpio: uart0-rts-gpio {
+                               rockchip,pins = <1 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>;
+                       };
+               };
+
+               uart1 {
+                       uart1_xfer: uart1-xfer {
+                               rockchip,pins = <3 RK_PA4 4 &pcfg_pull_up>,
+                                               <3 RK_PA6 4 &pcfg_pull_none>;
+                       };
+
+                       uart1_cts: uart1-cts {
+                               rockchip,pins = <3 RK_PA7 4 &pcfg_pull_none>;
+                       };
+
+                       uart1_rts: uart1-rts {
+                               rockchip,pins = <3 RK_PA5 4 &pcfg_pull_none>;
+                       };
+
+                       uart1_rts_gpio: uart1-rts-gpio {
+                               rockchip,pins = <3 RK_PA5 RK_FUNC_GPIO &pcfg_pull_none>;
+                       };
+               };
+
+               uart2-0 {
+                       uart2m0_xfer: uart2m0-xfer {
+                               rockchip,pins = <1 RK_PA0 2 &pcfg_pull_up>,
+                                               <1 RK_PA1 2 &pcfg_pull_none>;
+                       };
+               };
+
+               uart2-1 {
+                       uart2m1_xfer: uart2m1-xfer {
+                               rockchip,pins = <2 RK_PA0 1 &pcfg_pull_up>,
+                                               <2 RK_PA1 1 &pcfg_pull_none>;
+                       };
+               };
+
+               spi0-0 {
+                       spi0m0_clk: spi0m0-clk {
+                               rockchip,pins = <2 RK_PB0 1 &pcfg_pull_up>;
+                       };
+
+                       spi0m0_cs0: spi0m0-cs0 {
+                               rockchip,pins = <2 RK_PB3 1 &pcfg_pull_up>;
+                       };
+
+                       spi0m0_tx: spi0m0-tx {
+                               rockchip,pins = <2 RK_PB1 1 &pcfg_pull_up>;
+                       };
+
+                       spi0m0_rx: spi0m0-rx {
+                               rockchip,pins = <2 RK_PB2 1 &pcfg_pull_up>;
+                       };
+
+                       spi0m0_cs1: spi0m0-cs1 {
+                               rockchip,pins = <2 RK_PB4 1 &pcfg_pull_up>;
+                       };
+               };
+
+               spi0-1 {
+                       spi0m1_clk: spi0m1-clk {
+                               rockchip,pins = <3 RK_PC7 2 &pcfg_pull_up>;
+                       };
+
+                       spi0m1_cs0: spi0m1-cs0 {
+                               rockchip,pins = <3 RK_PD2 2 &pcfg_pull_up>;
+                       };
+
+                       spi0m1_tx: spi0m1-tx {
+                               rockchip,pins = <3 RK_PD1 2 &pcfg_pull_up>;
+                       };
+
+                       spi0m1_rx: spi0m1-rx {
+                               rockchip,pins = <3 RK_PD0 2 &pcfg_pull_up>;
+                       };
+
+                       spi0m1_cs1: spi0m1-cs1 {
+                               rockchip,pins = <3 RK_PD3 2 &pcfg_pull_up>;
+                       };
+               };
+
+               spi0-2 {
+                       spi0m2_clk: spi0m2-clk {
+                               rockchip,pins = <3 RK_PA0 4 &pcfg_pull_up>;
+                       };
+
+                       spi0m2_cs0: spi0m2-cs0 {
+                               rockchip,pins = <3 RK_PB0 3 &pcfg_pull_up>;
+                       };
+
+                       spi0m2_tx: spi0m2-tx {
+                               rockchip,pins = <3 RK_PA1 4 &pcfg_pull_up>;
+                       };
+
+                       spi0m2_rx: spi0m2-rx {
+                               rockchip,pins = <3 RK_PA2 4 &pcfg_pull_up>;
+                       };
+               };
+
+               i2s1 {
+                       i2s1_mclk: i2s1-mclk {
+                               rockchip,pins = <2 RK_PB7 1 &pcfg_pull_none>;
+                       };
+
+                       i2s1_sclk: i2s1-sclk {
+                               rockchip,pins = <2 RK_PC2 1 &pcfg_pull_none>;
+                       };
+
+                       i2s1_lrckrx: i2s1-lrckrx {
+                               rockchip,pins = <2 RK_PC0 1 &pcfg_pull_none>;
+                       };
+
+                       i2s1_lrcktx: i2s1-lrcktx {
+                               rockchip,pins = <2 RK_PC1 1 &pcfg_pull_none>;
+                       };
+
+                       i2s1_sdi: i2s1-sdi {
+                               rockchip,pins = <2 RK_PC3 1 &pcfg_pull_none>;
+                       };
+
+                       i2s1_sdo: i2s1-sdo {
+                               rockchip,pins = <2 RK_PC7 1 &pcfg_pull_none>;
+                       };
+
+                       i2s1_sdio1: i2s1-sdio1 {
+                               rockchip,pins = <2 RK_PC4 1 &pcfg_pull_none>;
+                       };
+
+                       i2s1_sdio2: i2s1-sdio2 {
+                               rockchip,pins = <2 RK_PC5 1 &pcfg_pull_none>;
+                       };
+
+                       i2s1_sdio3: i2s1-sdio3 {
+                               rockchip,pins = <2 RK_PC6 1 &pcfg_pull_none>;
+                       };
+
+                       i2s1_sleep: i2s1-sleep {
+                               rockchip,pins =
+                                       <2 RK_PB7 RK_FUNC_GPIO &pcfg_input_high>,
+                                       <2 RK_PC0 RK_FUNC_GPIO &pcfg_input_high>,
+                                       <2 RK_PC1 RK_FUNC_GPIO &pcfg_input_high>,
+                                       <2 RK_PC2 RK_FUNC_GPIO &pcfg_input_high>,
+                                       <2 RK_PC3 RK_FUNC_GPIO &pcfg_input_high>,
+                                       <2 RK_PC4 RK_FUNC_GPIO &pcfg_input_high>,
+                                       <2 RK_PC5 RK_FUNC_GPIO &pcfg_input_high>,
+                                       <2 RK_PC6 RK_FUNC_GPIO &pcfg_input_high>,
+                                       <2 RK_PC7 RK_FUNC_GPIO &pcfg_input_high>;
+                       };
+               };
+
+               i2s2-0 {
+                       i2s2m0_mclk: i2s2m0-mclk {
+                               rockchip,pins = <1 RK_PC5 1 &pcfg_pull_none>;
+                       };
+
+                       i2s2m0_sclk: i2s2m0-sclk {
+                               rockchip,pins = <1 RK_PC6 1 &pcfg_pull_none>;
+                       };
+
+                       i2s2m0_lrckrx: i2s2m0-lrckrx {
+                               rockchip,pins = <1 RK_PD2 1 &pcfg_pull_none>;
+                       };
+
+                       i2s2m0_lrcktx: i2s2m0-lrcktx {
+                               rockchip,pins = <1 RK_PC7 1 &pcfg_pull_none>;
+                       };
+
+                       i2s2m0_sdi: i2s2m0-sdi {
+                               rockchip,pins = <1 RK_PD0 1 &pcfg_pull_none>;
+                       };
+
+                       i2s2m0_sdo: i2s2m0-sdo {
+                               rockchip,pins = <1 RK_PD1 1 &pcfg_pull_none>;
+                       };
+
+                       i2s2m0_sleep: i2s2m0-sleep {
+                               rockchip,pins =
+                                       <1 RK_PC5 RK_FUNC_GPIO &pcfg_input_high>,
+                                       <1 RK_PC6 RK_FUNC_GPIO &pcfg_input_high>,
+                                       <1 RK_PD2 RK_FUNC_GPIO &pcfg_input_high>,
+                                       <1 RK_PC7 RK_FUNC_GPIO &pcfg_input_high>,
+                                       <1 RK_PD0 RK_FUNC_GPIO &pcfg_input_high>,
+                                       <1 RK_PD1 RK_FUNC_GPIO &pcfg_input_high>;
+                       };
+               };
+
+               i2s2-1 {
+                       i2s2m1_mclk: i2s2m1-mclk {
+                               rockchip,pins = <1 RK_PC5 1 &pcfg_pull_none>;
+                       };
+
+                       i2s2m1_sclk: i2s2m1-sclk {
+                               rockchip,pins = <3 RK_PA0 6 &pcfg_pull_none>;
+                       };
+
+                       i2s2m1_lrckrx: i2sm1-lrckrx {
+                               rockchip,pins = <3 RK_PB0 6 &pcfg_pull_none>;
+                       };
+
+                       i2s2m1_lrcktx: i2s2m1-lrcktx {
+                               rockchip,pins = <3 RK_PB0 4 &pcfg_pull_none>;
+                       };
+
+                       i2s2m1_sdi: i2s2m1-sdi {
+                               rockchip,pins = <3 RK_PA2 6 &pcfg_pull_none>;
+                       };
+
+                       i2s2m1_sdo: i2s2m1-sdo {
+                               rockchip,pins = <3 RK_PA1 6 &pcfg_pull_none>;
+                       };
+
+                       i2s2m1_sleep: i2s2m1-sleep {
+                               rockchip,pins =
+                                       <1 RK_PC5 RK_FUNC_GPIO &pcfg_input_high>,
+                                       <3 RK_PA0 RK_FUNC_GPIO &pcfg_input_high>,
+                                       <3 RK_PB0 RK_FUNC_GPIO &pcfg_input_high>,
+                                       <3 RK_PA2 RK_FUNC_GPIO &pcfg_input_high>,
+                                       <3 RK_PA1 RK_FUNC_GPIO &pcfg_input_high>;
+                       };
+               };
+
+               spdif-0 {
+                       spdifm0_tx: spdifm0-tx {
+                               rockchip,pins = <0 RK_PD3 1 &pcfg_pull_none>;
+                       };
+               };
+
+               spdif-1 {
+                       spdifm1_tx: spdifm1-tx {
+                               rockchip,pins = <2 RK_PC1 2 &pcfg_pull_none>;
+                       };
+               };
+
+               spdif-2 {
+                       spdifm2_tx: spdifm2-tx {
+                               rockchip,pins = <0 RK_PA2 2 &pcfg_pull_none>;
+                       };
+               };
+
+               sdmmc0-0 {
+                       sdmmc0m0_pwren: sdmmc0m0-pwren {
+                               rockchip,pins = <2 RK_PA7 1 &pcfg_pull_up_4ma>;
+                       };
+
+                       sdmmc0m0_gpio: sdmmc0m0-gpio {
+                               rockchip,pins = <2 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up_4ma>;
+                       };
+               };
+
+               sdmmc0-1 {
+                       sdmmc0m1_pwren: sdmmc0m1-pwren {
+                               rockchip,pins = <0 RK_PD6 3 &pcfg_pull_up_4ma>;
+                       };
+
+                       sdmmc0m1_gpio: sdmmc0m1-gpio {
+                               rockchip,pins = <0 RK_PD6 RK_FUNC_GPIO &pcfg_pull_up_4ma>;
+                       };
+               };
+
+               sdmmc0 {
+                       sdmmc0_clk: sdmmc0-clk {
+                               rockchip,pins = <1 RK_PA6 1 &pcfg_pull_none_4ma>;
+                       };
+
+                       sdmmc0_cmd: sdmmc0-cmd {
+                               rockchip,pins = <1 RK_PA4 1 &pcfg_pull_up_4ma>;
+                       };
+
+                       sdmmc0_dectn: sdmmc0-dectn {
+                               rockchip,pins = <1 RK_PA5 1 &pcfg_pull_up_4ma>;
+                       };
+
+                       sdmmc0_wrprt: sdmmc0-wrprt {
+                               rockchip,pins = <1 RK_PA7 1 &pcfg_pull_up_4ma>;
+                       };
+
+                       sdmmc0_bus1: sdmmc0-bus1 {
+                               rockchip,pins = <1 RK_PA0 1 &pcfg_pull_up_4ma>;
+                       };
+
+                       sdmmc0_bus4: sdmmc0-bus4 {
+                               rockchip,pins = <1 RK_PA0 1 &pcfg_pull_up_4ma>,
+                                               <1 RK_PA1 1 &pcfg_pull_up_4ma>,
+                                               <1 RK_PA2 1 &pcfg_pull_up_4ma>,
+                                               <1 RK_PA3 1 &pcfg_pull_up_4ma>;
+                       };
+
+                       sdmmc0_gpio: sdmmc0-gpio {
+                               rockchip,pins =
+                                       <1 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up_4ma>,
+                                       <1 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up_4ma>,
+                                       <1 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up_4ma>,
+                                       <1 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up_4ma>,
+                                       <1 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up_4ma>,
+                                       <1 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up_4ma>,
+                                       <1 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up_4ma>,
+                                       <1 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up_4ma>;
+                       };
+               };
+
+               sdmmc0ext {
+                       sdmmc0ext_clk: sdmmc0ext-clk {
+                               rockchip,pins = <3 RK_PA2 3 &pcfg_pull_none_4ma>;
+                       };
+
+                       sdmmc0ext_cmd: sdmmc0ext-cmd {
+                               rockchip,pins = <3 RK_PA0 3 &pcfg_pull_up_4ma>;
+                       };
+
+                       sdmmc0ext_wrprt: sdmmc0ext-wrprt {
+                               rockchip,pins = <3 RK_PA3 3 &pcfg_pull_up_4ma>;
+                       };
+
+                       sdmmc0ext_dectn: sdmmc0ext-dectn {
+                               rockchip,pins = <3 RK_PA1 3 &pcfg_pull_up_4ma>;
+                       };
+
+                       sdmmc0ext_bus1: sdmmc0ext-bus1 {
+                               rockchip,pins = <3 RK_PA4 3 &pcfg_pull_up_4ma>;
+                       };
+
+                       sdmmc0ext_bus4: sdmmc0ext-bus4 {
+                               rockchip,pins =
+                                       <3 RK_PA4 3 &pcfg_pull_up_4ma>,
+                                       <3 RK_PA5 3 &pcfg_pull_up_4ma>,
+                                       <3 RK_PA6 3 &pcfg_pull_up_4ma>,
+                                       <3 RK_PA7 3 &pcfg_pull_up_4ma>;
+                       };
+
+                       sdmmc0ext_gpio: sdmmc0ext-gpio {
+                               rockchip,pins =
+                                       <3 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up_4ma>,
+                                       <3 RK_PA1 RK_FUNC_GPIO &pcfg_pull_up_4ma>,
+                                       <3 RK_PA2 RK_FUNC_GPIO &pcfg_pull_up_4ma>,
+                                       <3 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up_4ma>,
+                                       <3 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up_4ma>,
+                                       <3 RK_PA5 RK_FUNC_GPIO &pcfg_pull_up_4ma>,
+                                       <3 RK_PA6 RK_FUNC_GPIO &pcfg_pull_up_4ma>,
+                                       <3 RK_PA7 RK_FUNC_GPIO &pcfg_pull_up_4ma>;
+                       };
+               };
+
+               sdmmc1 {
+                       sdmmc1_clk: sdmmc1-clk {
+                               rockchip,pins = <1 RK_PB4 1 &pcfg_pull_none_8ma>;
+                       };
+
+                       sdmmc1_cmd: sdmmc1-cmd {
+                               rockchip,pins = <1 RK_PB5 1 &pcfg_pull_up_8ma>;
+                       };
+
+                       sdmmc1_pwren: sdmmc1-pwren {
+                               rockchip,pins = <1 RK_PC2 1 &pcfg_pull_up_8ma>;
+                       };
+
+                       sdmmc1_wrprt: sdmmc1-wrprt {
+                               rockchip,pins = <1 RK_PC4 1 &pcfg_pull_up_8ma>;
+                       };
+
+                       sdmmc1_dectn: sdmmc1-dectn {
+                               rockchip,pins = <1 RK_PC3 1 &pcfg_pull_up_8ma>;
+                       };
+
+                       sdmmc1_bus1: sdmmc1-bus1 {
+                               rockchip,pins = <1 RK_PB6 1 &pcfg_pull_up_8ma>;
+                       };
+
+                       sdmmc1_bus4: sdmmc1-bus4 {
+                               rockchip,pins = <1 RK_PB6 1 &pcfg_pull_up_8ma>,
+                                               <1 RK_PB7 1 &pcfg_pull_up_8ma>,
+                                               <1 RK_PC0 1 &pcfg_pull_up_8ma>,
+                                               <1 RK_PC1 1 &pcfg_pull_up_8ma>;
+                       };
+
+                       sdmmc1_gpio: sdmmc1-gpio {
+                               rockchip,pins =
+                                       <1 RK_PB4 RK_FUNC_GPIO &pcfg_pull_up_4ma>,
+                                       <1 RK_PB5 RK_FUNC_GPIO &pcfg_pull_up_4ma>,
+                                       <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_up_4ma>,
+                                       <1 RK_PB7 RK_FUNC_GPIO &pcfg_pull_up_4ma>,
+                                       <1 RK_PC0 RK_FUNC_GPIO &pcfg_pull_up_4ma>,
+                                       <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_up_4ma>,
+                                       <1 RK_PC2 RK_FUNC_GPIO &pcfg_pull_up_4ma>,
+                                       <1 RK_PC3 RK_FUNC_GPIO &pcfg_pull_up_4ma>,
+                                       <1 RK_PC4 RK_FUNC_GPIO &pcfg_pull_up_4ma>;
+                       };
+               };
+
+               emmc {
+                       emmc_clk: emmc-clk {
+                               rockchip,pins = <3 RK_PC5 2 &pcfg_pull_none_12ma>;
+                       };
+
+                       emmc_cmd: emmc-cmd {
+                               rockchip,pins = <3 RK_PC3 2 &pcfg_pull_up_12ma>;
+                       };
+
+                       emmc_pwren: emmc-pwren {
+                               rockchip,pins = <3 RK_PC6 2 &pcfg_pull_none>;
+                       };
+
+                       emmc_rstnout: emmc-rstnout {
+                               rockchip,pins = <3 RK_PC4 2 &pcfg_pull_none>;
+                       };
+
+                       emmc_bus1: emmc-bus1 {
+                               rockchip,pins = <0 RK_PA7 2 &pcfg_pull_up_12ma>;
+                       };
+
+                       emmc_bus4: emmc-bus4 {
+                               rockchip,pins =
+                                       <0 RK_PA7 2 &pcfg_pull_up_12ma>,
+                                       <2 RK_PD4 2 &pcfg_pull_up_12ma>,
+                                       <2 RK_PD5 2 &pcfg_pull_up_12ma>,
+                                       <2 RK_PD6 2 &pcfg_pull_up_12ma>;
+                       };
+
+                       emmc_bus8: emmc-bus8 {
+                               rockchip,pins =
+                                       <0 RK_PA7 2 &pcfg_pull_up_12ma>,
+                                       <2 RK_PD4 2 &pcfg_pull_up_12ma>,
+                                       <2 RK_PD5 2 &pcfg_pull_up_12ma>,
+                                       <2 RK_PD6 2 &pcfg_pull_up_12ma>,
+                                       <2 RK_PD7 2 &pcfg_pull_up_12ma>,
+                                       <3 RK_PC0 2 &pcfg_pull_up_12ma>,
+                                       <3 RK_PC1 2 &pcfg_pull_up_12ma>,
+                                       <3 RK_PC2 2 &pcfg_pull_up_12ma>;
+                       };
+               };
+
+               pwm0 {
+                       pwm0_pin: pwm0-pin {
+                               rockchip,pins = <2 RK_PA4 1 &pcfg_pull_none>;
+                       };
+               };
+
+               pwm1 {
+                       pwm1_pin: pwm1-pin {
+                               rockchip,pins = <2 RK_PA5 1 &pcfg_pull_none>;
+                       };
+               };
+
+               pwm2 {
+                       pwm2_pin: pwm2-pin {
+                               rockchip,pins = <2 RK_PA6 1 &pcfg_pull_none>;
+                       };
+               };
+
+               pwmir {
+                       pwmir_pin: pwmir-pin {
+                               rockchip,pins = <2 RK_PA2 1 &pcfg_pull_none>;
+                       };
+               };
+
+               gmac-1 {
+                       rgmiim1_pins: rgmiim1-pins {
+                               rockchip,pins =
+                                       /* mac_txclk */
+                                       <1 RK_PB4 2 &pcfg_pull_none_12ma>,
+                                       /* mac_rxclk */
+                                       <1 RK_PB5 2 &pcfg_pull_none_2ma>,
+                                       /* mac_mdio */
+                                       <1 RK_PC3 2 &pcfg_pull_none_2ma>,
+                                       /* mac_txen */
+                                       <1 RK_PD1 2 &pcfg_pull_none_12ma>,
+                                       /* mac_clk */
+                                       <1 RK_PC5 2 &pcfg_pull_none_2ma>,
+                                       /* mac_rxdv */
+                                       <1 RK_PC6 2 &pcfg_pull_none_2ma>,
+                                       /* mac_mdc */
+                                       <1 RK_PC7 2 &pcfg_pull_none_2ma>,
+                                       /* mac_rxd1 */
+                                       <1 RK_PB2 2 &pcfg_pull_none_2ma>,
+                                       /* mac_rxd0 */
+                                       <1 RK_PB3 2 &pcfg_pull_none_2ma>,
+                                       /* mac_txd1 */
+                                       <1 RK_PB0 2 &pcfg_pull_none_12ma>,
+                                       /* mac_txd0 */
+                                       <1 RK_PB1 2 &pcfg_pull_none_12ma>,
+                                       /* mac_rxd3 */
+                                       <1 RK_PB6 2 &pcfg_pull_none_2ma>,
+                                       /* mac_rxd2 */
+                                       <1 RK_PB7 2 &pcfg_pull_none_2ma>,
+                                       /* mac_txd3 */
+                                       <1 RK_PC0 2 &pcfg_pull_none_12ma>,
+                                       /* mac_txd2 */
+                                       <1 RK_PC1 2 &pcfg_pull_none_12ma>,
+
+                                       /* mac_txclk */
+                                       <0 RK_PB0 1 &pcfg_pull_none>,
+                                       /* mac_txen */
+                                       <0 RK_PB4 1 &pcfg_pull_none>,
+                                       /* mac_clk */
+                                       <0 RK_PD0 1 &pcfg_pull_none>,
+                                       /* mac_txd1 */
+                                       <0 RK_PC0 1 &pcfg_pull_none>,
+                                       /* mac_txd0 */
+                                       <0 RK_PC1 1 &pcfg_pull_none>,
+                                       /* mac_txd3 */
+                                       <0 RK_PC7 1 &pcfg_pull_none>,
+                                       /* mac_txd2 */
+                                       <0 RK_PC6 1 &pcfg_pull_none>;
+                       };
+
+                       rmiim1_pins: rmiim1-pins {
+                               rockchip,pins =
+                                       /* mac_mdio */
+                                       <1 RK_PC3 2 &pcfg_pull_none_2ma>,
+                                       /* mac_txen */
+                                       <1 RK_PD1 2 &pcfg_pull_none_12ma>,
+                                       /* mac_clk */
+                                       <1 RK_PC5 2 &pcfg_pull_none_2ma>,
+                                       /* mac_rxer */
+                                       <1 RK_PD0 2 &pcfg_pull_none_2ma>,
+                                       /* mac_rxdv */
+                                       <1 RK_PC6 2 &pcfg_pull_none_2ma>,
+                                       /* mac_mdc */
+                                       <1 RK_PC7 2 &pcfg_pull_none_2ma>,
+                                       /* mac_rxd1 */
+                                       <1 RK_PB2 2 &pcfg_pull_none_2ma>,
+                                       /* mac_rxd0 */
+                                       <1 RK_PB3 2 &pcfg_pull_none_2ma>,
+                                       /* mac_txd1 */
+                                       <1 RK_PB0 2 &pcfg_pull_none_12ma>,
+                                       /* mac_txd0 */
+                                       <1 RK_PB1 2 &pcfg_pull_none_12ma>,
+
+                                       /* mac_mdio */
+                                       <0 RK_PB3 1 &pcfg_pull_none>,
+                                       /* mac_txen */
+                                       <0 RK_PB4 1 &pcfg_pull_none>,
+                                       /* mac_clk */
+                                       <0 RK_PD0 1 &pcfg_pull_none>,
+                                       /* mac_mdc */
+                                       <0 RK_PC3 1 &pcfg_pull_none>,
+                                       /* mac_txd1 */
+                                       <0 RK_PC0 1 &pcfg_pull_none>,
+                                       /* mac_txd0 */
+                                       <0 RK_PC1 1 &pcfg_pull_none>;
+                       };
+               };
+
+               gmac2phy {
+                       fephyled_speed100: fephyled-speed100 {
+                               rockchip,pins = <0 RK_PD7 1 &pcfg_pull_none>;
+                       };
+
+                       fephyled_speed10: fephyled-speed10 {
+                               rockchip,pins = <0 RK_PD6 1 &pcfg_pull_none>;
+                       };
+
+                       fephyled_duplex: fephyled-duplex {
+                               rockchip,pins = <0 RK_PD6 2 &pcfg_pull_none>;
+                       };
+
+                       fephyled_rxm0: fephyled-rxm0 {
+                               rockchip,pins = <0 RK_PD5 1 &pcfg_pull_none>;
+                       };
+
+                       fephyled_txm0: fephyled-txm0 {
+                               rockchip,pins = <0 RK_PD5 2 &pcfg_pull_none>;
+                       };
+
+                       fephyled_linkm0: fephyled-linkm0 {
+                               rockchip,pins = <0 RK_PD4 1 &pcfg_pull_none>;
+                       };
+
+                       fephyled_rxm1: fephyled-rxm1 {
+                               rockchip,pins = <2 RK_PD1 2 &pcfg_pull_none>;
+                       };
+
+                       fephyled_txm1: fephyled-txm1 {
+                               rockchip,pins = <2 RK_PD1 3 &pcfg_pull_none>;
+                       };
+
+                       fephyled_linkm1: fephyled-linkm1 {
+                               rockchip,pins = <2 RK_PD0 2 &pcfg_pull_none>;
+                       };
+               };
+
+               tsadc_pin {
+                       tsadc_int: tsadc-int {
+                               rockchip,pins = <2 RK_PB5 2 &pcfg_pull_none>;
+                       };
+                       tsadc_gpio: tsadc-gpio {
+                               rockchip,pins = <2 RK_PB5 RK_FUNC_GPIO &pcfg_pull_none>;
+                       };
+               };
+
+               hdmi_pin {
+                       hdmi_cec: hdmi-cec {
+                               rockchip,pins = <0 RK_PA3 1 &pcfg_pull_none>;
+                       };
+
+                       hdmi_hpd: hdmi-hpd {
+                               rockchip,pins = <0 RK_PA4 1 &pcfg_pull_down>;
+                       };
+               };
+
+               cif-0 {
+                       dvp_d2d9_m0:dvp-d2d9-m0 {
+                               rockchip,pins =
+                                       /* cif_d0 */
+                                       <3 RK_PA4 2 &pcfg_pull_none>,
+                                       /* cif_d1 */
+                                       <3 RK_PA5 2 &pcfg_pull_none>,
+                                       /* cif_d2 */
+                                       <3 RK_PA6 2 &pcfg_pull_none>,
+                                       /* cif_d3 */
+                                       <3 RK_PA7 2 &pcfg_pull_none>,
+                                       /* cif_d4 */
+                                       <3 RK_PB0 2 &pcfg_pull_none>,
+                                       /* cif_d5m0 */
+                                       <3 RK_PB1 2 &pcfg_pull_none>,
+                                       /* cif_d6m0 */
+                                       <3 RK_PB2 2 &pcfg_pull_none>,
+                                       /* cif_d7m0 */
+                                       <3 RK_PB3 2 &pcfg_pull_none>,
+                                       /* cif_href */
+                                       <3 RK_PA1 2 &pcfg_pull_none>,
+                                       /* cif_vsync */
+                                       <3 RK_PA0 2 &pcfg_pull_none>,
+                                       /* cif_clkoutm0 */
+                                       <3 RK_PA3 2 &pcfg_pull_none>,
+                                       /* cif_clkin */
+                                       <3 RK_PA2 2 &pcfg_pull_none>;
+                       };
+               };
+
+               cif-1 {
+                       dvp_d2d9_m1:dvp-d2d9-m1 {
+                               rockchip,pins =
+                                       /* cif_d0 */
+                                       <3 RK_PA4 2 &pcfg_pull_none>,
+                                       /* cif_d1 */
+                                       <3 RK_PA5 2 &pcfg_pull_none>,
+                                       /* cif_d2 */
+                                       <3 RK_PA6 2 &pcfg_pull_none>,
+                                       /* cif_d3 */
+                                       <3 RK_PA7 2 &pcfg_pull_none>,
+                                       /* cif_d4 */
+                                       <3 RK_PB0 2 &pcfg_pull_none>,
+                                       /* cif_d5m1 */
+                                       <2 RK_PC0 4 &pcfg_pull_none>,
+                                       /* cif_d6m1 */
+                                       <2 RK_PC1 4 &pcfg_pull_none>,
+                                       /* cif_d7m1 */
+                                       <2 RK_PC2 4 &pcfg_pull_none>,
+                                       /* cif_href */
+                                       <3 RK_PA1 2 &pcfg_pull_none>,
+                                       /* cif_vsync */
+                                       <3 RK_PA0 2 &pcfg_pull_none>,
+                                       /* cif_clkoutm1 */
+                                       <2 RK_PB7 4 &pcfg_pull_none>,
+                                       /* cif_clkin */
+                                       <3 RK_PA2 2 &pcfg_pull_none>;
+                       };
+               };
+       };
+};
index 8cdb3bff9c55b1d8935ac03cadd6a8803d9de8f6..ff48edd8e3482bcafcf4920ecdf1b93995bd5a5b 100644 (file)
@@ -53,7 +53,7 @@
        };
 
        memory@0 {
-               reg = <0x0 0x0 0x0 0x80000000>;
+               reg = <0x0 0x0 0x0 0x40000000>;
                device_type = "memory";
        };
 
index a635adc47e742c1bdf3a3cd5be613532fe807a8f..6d5dc0587e599dd768ed00d0df92145a862dce1b 100644 (file)
                        };
                };
 
-               idle-states {
-                       entry-method = "psci";
-
-                       cpu_sleep: cpu-sleep-0 {
-                               compatible = "arm,idle-state";
-                               arm,psci-suspend-param = <0x1010000>;
-                               entry-latency-us = <0x3fffffff>;
-                               exit-latency-us = <0x40000000>;
-                               min-residency-us = <0xffffffff>;
-                       };
-               };
-
                cpu_l0: cpu@0 {
                        device_type = "cpu";
                        compatible = "arm,cortex-a53", "arm,armv8";
                        reg = <0x0 0x0>;
-                       cpu-idle-states = <&cpu_sleep>;
                        enable-method = "psci";
 
                        #cooling-cells = <2>; /* min followed by max */
                        device_type = "cpu";
                        compatible = "arm,cortex-a53", "arm,armv8";
                        reg = <0x0 0x1>;
-                       cpu-idle-states = <&cpu_sleep>;
                        enable-method = "psci";
                };
 
                        device_type = "cpu";
                        compatible = "arm,cortex-a53", "arm,armv8";
                        reg = <0x0 0x2>;
-                       cpu-idle-states = <&cpu_sleep>;
                        enable-method = "psci";
                };
 
                        device_type = "cpu";
                        compatible = "arm,cortex-a53", "arm,armv8";
                        reg = <0x0 0x3>;
-                       cpu-idle-states = <&cpu_sleep>;
                        enable-method = "psci";
                };
 
                        device_type = "cpu";
                        compatible = "arm,cortex-a53", "arm,armv8";
                        reg = <0x0 0x100>;
-                       cpu-idle-states = <&cpu_sleep>;
                        enable-method = "psci";
 
                        #cooling-cells = <2>; /* min followed by max */
                        device_type = "cpu";
                        compatible = "arm,cortex-a53", "arm,armv8";
                        reg = <0x0 0x101>;
-                       cpu-idle-states = <&cpu_sleep>;
                        enable-method = "psci";
                };
 
                        device_type = "cpu";
                        compatible = "arm,cortex-a53", "arm,armv8";
                        reg = <0x0 0x102>;
-                       cpu-idle-states = <&cpu_sleep>;
                        enable-method = "psci";
                };
 
                        device_type = "cpu";
                        compatible = "arm,cortex-a53", "arm,armv8";
                        reg = <0x0 0x103>;
-                       cpu-idle-states = <&cpu_sleep>;
                        enable-method = "psci";
                };
        };
 
+       amba {
+               compatible = "simple-bus";
+               #address-cells = <2>;
+               #size-cells = <2>;
+               ranges;
+
+               dmac_peri: dma-controller@ff250000 {
+                       compatible = "arm,pl330", "arm,primecell";
+                       reg = <0x0 0xff250000 0x0 0x4000>;
+                       interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+                       #dma-cells = <1>;
+                       arm,pl330-broken-no-flushp;
+                       clocks = <&cru ACLK_DMAC_PERI>;
+                       clock-names = "apb_pclk";
+               };
+
+               dmac_bus: dma-controller@ff600000 {
+                       compatible = "arm,pl330", "arm,primecell";
+                       reg = <0x0 0xff600000 0x0 0x4000>;
+                       interrupts = <GIC_SPI 0 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
+                       #dma-cells = <1>;
+                       arm,pl330-broken-no-flushp;
+                       clocks = <&cru ACLK_DMAC_BUS>;
+                       clock-names = "apb_pclk";
+               };
+       };
+
        arm-pmu {
                compatible = "arm,armv8-pmuv3";
                interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>,
                clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
                fifo-depth = <0x100>;
                interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+               resets = <&cru SRST_MMC0>;
+               reset-names = "reset";
                status = "disabled";
        };
 
                clock-names = "biu", "ciu", "ciu_drv", "ciu_sample";
                fifo-depth = <0x100>;
                interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+               resets = <&cru SRST_SDIO0>;
+               reset-names = "reset";
                status = "disabled";
        };
 
                clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
                fifo-depth = <0x100>;
                interrupts = <GIC_SPI 35 IRQ_TYPE_LEVEL_HIGH>;
+               resets = <&cru SRST_EMMC>;
+               reset-names = "reset";
                status = "disabled";
        };
 
                clocks = <&cru PCLK_MAILBOX>;
                clock-names = "pclk_mailbox";
                #mbox-cells = <1>;
+               status = "disabled";
        };
 
        pmugrf: syscon@ff738000 {
                interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
        };
 
+       i2s_2ch: i2s-2ch@ff890000 {
+               compatible = "rockchip,rk3368-i2s", "rockchip,rk3066-i2s";
+               reg = <0x0 0xff890000 0x0 0x1000>;
+               interrupts = <GIC_SPI 40 IRQ_TYPE_LEVEL_HIGH>;
+               clock-names = "i2s_clk", "i2s_hclk";
+               clocks = <&cru SCLK_I2S_2CH>, <&cru HCLK_I2S_2CH>;
+               dmas = <&dmac_bus 6>, <&dmac_bus 7>;
+               dma-names = "tx", "rx";
+               status = "disabled";
+       };
+
+       i2s_8ch: i2s-8ch@ff898000 {
+               compatible = "rockchip,rk3368-i2s", "rockchip,rk3066-i2s";
+               reg = <0x0 0xff898000 0x0 0x1000>;
+               interrupts = <GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>;
+               clock-names = "i2s_clk", "i2s_hclk";
+               clocks = <&cru SCLK_I2S_8CH>, <&cru HCLK_I2S_8CH>;
+               dmas = <&dmac_bus 0>, <&dmac_bus 1>;
+               dma-names = "tx", "rx";
+               pinctrl-names = "default";
+               pinctrl-0 = <&i2s_8ch_bus>;
+               status = "disabled";
+       };
+
        gic: interrupt-controller@ffb71000 {
                compatible = "arm,gic-400";
                interrupt-controller;
                        };
                };
 
+               i2s {
+                       i2s_8ch_bus: i2s-8ch-bus {
+                               rockchip,pins = <2 12 RK_FUNC_1 &pcfg_pull_none>,
+                                               <2 13 RK_FUNC_1 &pcfg_pull_none>,
+                                               <2 14 RK_FUNC_1 &pcfg_pull_none>,
+                                               <2 15 RK_FUNC_1 &pcfg_pull_none>,
+                                               <2 16 RK_FUNC_1 &pcfg_pull_none>,
+                                               <2 17 RK_FUNC_1 &pcfg_pull_none>,
+                                               <2 18 RK_FUNC_1 &pcfg_pull_none>,
+                                               <2 19 RK_FUNC_1 &pcfg_pull_none>,
+                                               <2 20 RK_FUNC_1 &pcfg_pull_none>;
+                       };
+               };
+
                pwm0 {
                        pwm0_pin: pwm0-pin {
                                rockchip,pins = <3 8 RK_FUNC_2 &pcfg_pull_none>;
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts b/arch/arm64/boot/dts/rockchip/rk3399-gru-kevin.dts
new file mode 100644 (file)
index 0000000..7bd3106
--- /dev/null
@@ -0,0 +1,306 @@
+/*
+ * Google Gru-Kevin Rev 6+ board device tree source
+ *
+ * Copyright 2016-2017 Google, Inc
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *  Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/dts-v1/;
+#include "rk3399-gru.dtsi"
+#include <dt-bindings/input/linux-event-codes.h>
+
+/*
+ * Kevin-specific things
+ *
+ * Things in this section should use names from Kevin schematic since no
+ * equivalent exists in Gru schematic.  If referring to signals that exist
+ * in Gru we use the Gru names, though.  Confusing enough for you?
+ */
+/ {
+       model = "Google Kevin";
+       compatible = "google,kevin-rev15", "google,kevin-rev14",
+                    "google,kevin-rev13", "google,kevin-rev12",
+                    "google,kevin-rev11", "google,kevin-rev10",
+                    "google,kevin-rev9", "google,kevin-rev8",
+                    "google,kevin-rev7", "google,kevin-rev6",
+                    "google,kevin", "google,gru", "rockchip,rk3399";
+
+       /* Power tree */
+
+       p3_3v_dig: p3-3v-dig {
+               compatible = "regulator-fixed";
+               regulator-name = "p3.3v_dig";
+               pinctrl-names = "default";
+               pinctrl-0 = <&cpu3_pen_pwr_en>;
+
+               enable-active-high;
+               gpio = <&gpio4 30 GPIO_ACTIVE_HIGH>;
+               vin-supply = <&pp3300>;
+       };
+
+       backlight: backlight {
+               compatible = "pwm-backlight";
+               pwms = <&cros_ec_pwm 1>;
+               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>;
+               default-brightness-level = <51>;
+               enable-gpios = <&gpio1 17 GPIO_ACTIVE_HIGH>;
+               power-supply = <&pp3300_disp>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&bl_en>;
+               pwm-delay-us = <10000>;
+       };
+
+       thermistor_ppvar_bigcpu: thermistor-ppvar-bigcpu {
+               compatible = "murata,ncp15wb473";
+               pullup-uv = <1800000>;
+               pullup-ohm = <25500>;
+               pulldown-ohm = <0>;
+               io-channels = <&saradc 2>;
+               #thermal-sensor-cells = <0>;
+       };
+
+       thermistor_ppvar_litcpu: thermistor-ppvar-litcpu {
+               compatible = "murata,ncp15wb473";
+               pullup-uv = <1800000>;
+               pullup-ohm = <25500>;
+               pulldown-ohm = <0>;
+               io-channels = <&saradc 3>;
+               #thermal-sensor-cells = <0>;
+       };
+};
+
+&gpio_keys {
+       pinctrl-names = "default";
+       pinctrl-0 = <&bt_host_wake_l>, <&cpu1_pen_eject>;
+
+       pen-insert {
+               label = "Pen Insert";
+               /* Insert = low, eject = high */
+               gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
+               linux,code = <SW_PEN_INSERTED>;
+               linux,input-type = <EV_SW>;
+               wakeup-source;
+       };
+};
+
+&thermal_zones {
+       bigcpu_reg_thermal: bigcpu-reg-thermal {
+               polling-delay-passive = <100>; /* milliseconds */
+               polling-delay = <1000>; /* milliseconds */
+               thermal-sensors = <&thermistor_ppvar_bigcpu 0>;
+               sustainable-power = <4000>;
+
+               ppvar_bigcpu_trips: trips {
+                       ppvar_bigcpu_on: ppvar-bigcpu-on {
+                               temperature = <40000>;  /* millicelsius */
+                               hysteresis = <2000>;    /* millicelsius */
+                               type = "passive";
+                       };
+
+                       ppvar_bigcpu_alert: ppvar-bigcpu-alert {
+                               temperature = <50000>;  /* millicelsius */
+                               hysteresis = <2000>;    /* millicelsius */
+                               type = "passive";
+                       };
+
+                       ppvar_bigcpu_crit: ppvar-bigcpu-crit {
+                               temperature = <90000>;  /* millicelsius */
+                               hysteresis = <0>;       /* millicelsius */
+                               type = "critical";
+                       };
+               };
+
+               cooling-maps {
+                       map0 {
+                               trip = <&ppvar_bigcpu_alert>;
+                               cooling-device =
+                                       <&cpu_l0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+                               contribution = <4096>;
+                       };
+                       map1 {
+                               trip = <&ppvar_bigcpu_alert>;
+                               cooling-device =
+                                       <&cpu_b0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+                               contribution = <1024>;
+                       };
+               };
+       };
+
+       litcpu_reg_thermal: litcpu-reg-thermal {
+               polling-delay-passive = <100>; /* milliseconds */
+               polling-delay = <1000>; /* milliseconds */
+               thermal-sensors = <&thermistor_ppvar_litcpu 0>;
+               sustainable-power = <4000>;
+
+               ppvar_litcpu_trips: trips {
+                       ppvar_litcpu_on: ppvar-litcpu-on {
+                               temperature = <40000>;  /* millicelsius */
+                               hysteresis = <2000>;    /* millicelsius */
+                               type = "passive";
+                       };
+
+                       ppvar_litcpu_alert: ppvar-litcpu-alert {
+                               temperature = <50000>;  /* millicelsius */
+                               hysteresis = <2000>;    /* millicelsius */
+                               type = "passive";
+                       };
+
+                       ppvar_litcpu_crit: ppvar-litcpu-crit {
+                               temperature = <90000>;  /* millicelsius */
+                               hysteresis = <0>;       /* millicelsius */
+                               type = "critical";
+                       };
+               };
+       };
+};
+
+ap_i2c_tpm: &i2c0 {
+       status = "okay";
+
+       clock-frequency = <400000>;
+
+       /* These are relatively safe rise/fall times. */
+       i2c-scl-falling-time-ns = <50>;
+       i2c-scl-rising-time-ns = <300>;
+
+       tpm: tpm@20 {
+               compatible = "infineon,slb9645tt";
+               reg = <0x20>;
+               powered-while-suspended;
+       };
+};
+
+ap_i2c_dig: &i2c2 {
+       status = "okay";
+
+       clock-frequency = <400000>;
+
+       /* These are relatively safe rise/fall times. */
+       i2c-scl-falling-time-ns = <50>;
+       i2c-scl-rising-time-ns = <300>;
+
+       digitizer: digitizer@9 {
+               /* wacom,w9013 */
+               compatible = "hid-over-i2c";
+               reg = <0x9>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&cpu1_dig_irq_l &cpu1_dig_pdct_l>;
+
+               vdd-supply = <&p3_3v_dig>;
+               post-power-on-delay-ms = <100>;
+
+               interrupt-parent = <&gpio2>;
+               interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+
+               hid-descr-addr = <0x1>;
+       };
+};
+
+/* Adjustments to things in the gru baseboard */
+
+&ap_i2c_tp {
+       trackpad@4a {
+               compatible = "atmel,atmel_mxt_tp";
+               reg = <0x4a>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&trackpad_int_l>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <4 IRQ_TYPE_LEVEL_LOW>;
+               wakeup-source;
+       };
+};
+
+&ap_i2c_ts {
+       touchscreen@4b {
+               compatible = "atmel,atmel_mxt_ts";
+               reg = <0x4b>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&touch_int_l>;
+               interrupt-parent = <&gpio3>;
+               interrupts = <13 IRQ_TYPE_LEVEL_LOW>;
+       };
+};
+
+&saradc {
+       status = "okay";
+       vref-supply = <&pp1800_ap_io>;
+};
+
+&mvl_wifi {
+       marvell,wakeup-pin = <14>; /* GPIO_14 on Marvell */
+};
+
+&pinctrl {
+       digitizer {
+               /* Has external pullup */
+               cpu1_dig_irq_l: cpu1-dig-irq-l {
+                       rockchip,pins = <2 4 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+
+               /* Has external pullup */
+               cpu1_dig_pdct_l: cpu1-dig-pdct-l {
+                       rockchip,pins = <2 5 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       discrete-regulators {
+               cpu3_pen_pwr_en: cpu3-pen-pwr-en {
+                       rockchip,pins = <4 30 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       pen {
+               cpu1_pen_eject: cpu1-pen-eject {
+                       rockchip,pins = <0 13 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+       };
+
+       wifi {
+               wlan_host_wake_l: wlan-host-wake-l {
+                       rockchip,pins = <0 8 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-gru.dtsi
new file mode 100644 (file)
index 0000000..0d960b7
--- /dev/null
@@ -0,0 +1,1103 @@
+/*
+ * Google Gru (and derivatives) board device tree source
+ *
+ * Copyright 2016-2017 Google, Inc
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ *  Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <dt-bindings/input/input.h>
+#include "rk3399.dtsi"
+#include "rk3399-opp.dtsi"
+
+/ {
+       chosen {
+               stdout-path = "serial2:115200n8";
+       };
+
+       /*
+        * Power Tree
+        *
+        * In general an attempt is made to include all rails called out by
+        * the schematic as long as those rails interact in some way with
+        * the AP.  AKA:
+        * - Rails that only connect to the EC (or devices that the EC talks to)
+        *   are not included.
+        * - Rails _are_ included if the rails go to the AP even if the AP
+        *   doesn't currently care about them / they are always on.  The idea
+        *   here is that it makes it easier to map to the schematic or extend
+        *   later.
+        *
+        * If two rails are substantially the same from the AP's point of
+        * view, though, we won't create a full fixed regulator.  We'll just
+        * put the child rail as an alias of the parent rail.  Sometimes rails
+        * look the same to the AP because one of these is true:
+        * - The EC controls the enable and the EC always enables a rail as
+        *   long as the AP is running.
+        * - The rails are actually connected to each other by a jumper and
+        *   the distinction is just there to add clarity/flexibility to the
+        *   schematic.
+        */
+
+       ppvar_sys: ppvar-sys {
+               compatible = "regulator-fixed";
+               regulator-name = "ppvar_sys";
+               regulator-always-on;
+               regulator-boot-on;
+       };
+
+       pp900_ap: pp900-ap {
+               compatible = "regulator-fixed";
+               regulator-name = "pp900_ap";
+
+               /* EC turns on w/ pp900_ap_en; always on for AP */
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-min-microvolt = <900000>;
+               regulator-max-microvolt = <900000>;
+
+               vin-supply = <&ppvar_sys>;
+       };
+
+       pp1200_lpddr: pp1200-lpddr {
+               compatible = "regulator-fixed";
+               regulator-name = "pp1200_lpddr";
+
+               /* EC turns on w/ lpddr_pwr_en; always on for AP */
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-min-microvolt = <1200000>;
+               regulator-max-microvolt = <1200000>;
+
+               vin-supply = <&ppvar_sys>;
+       };
+
+       pp1800: pp1800 {
+               compatible = "regulator-fixed";
+               regulator-name = "pp1800";
+
+               /* Always on when ppvar_sys shows power good */
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+
+               vin-supply = <&ppvar_sys>;
+       };
+
+       pp3000: pp3000 {
+               compatible = "regulator-fixed";
+               regulator-name = "pp3000";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pp3000_en>;
+
+               enable-active-high;
+               gpio = <&gpio0 12 GPIO_ACTIVE_HIGH>;
+
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-min-microvolt = <3000000>;
+               regulator-max-microvolt = <3000000>;
+
+               vin-supply = <&ppvar_sys>;
+       };
+
+       pp3300: pp3300 {
+               compatible = "regulator-fixed";
+               regulator-name = "pp3300";
+
+               /* Always on; plain and simple */
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+
+               vin-supply = <&ppvar_sys>;
+       };
+
+       pp5000: pp5000 {
+               compatible = "regulator-fixed";
+               regulator-name = "pp5000";
+
+               /* EC turns on w/ pp5000_en; always on for AP */
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+
+               vin-supply = <&ppvar_sys>;
+       };
+
+       ppvar_bigcpu: ppvar-bigcpu {
+               compatible = "pwm-regulator";
+               regulator-name = "ppvar_bigcpu";
+               /*
+                * OVP circuit requires special handling which is not yet
+                * represented. Keep disabled for now.
+                */
+               status = "disabled";
+
+               pwms = <&pwm1 0 3337 0>;
+               pwm-supply = <&ppvar_sys>;
+               pwm-dutycycle-range = <100 0>;
+               pwm-dutycycle-unit = <100>;
+
+               /* EC turns on w/ ap_core_en; always on for AP */
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-min-microvolt = <798674>;
+               regulator-max-microvolt = <1302172>;
+       };
+
+       ppvar_litcpu: ppvar-litcpu {
+               compatible = "pwm-regulator";
+               regulator-name = "ppvar_litcpu";
+               /*
+                * OVP circuit requires special handling which is not yet
+                * represented. Keep disabled for now.
+                */
+               status = "disabled";
+
+               pwms = <&pwm2 0 3337 0>;
+               pwm-supply = <&ppvar_sys>;
+               pwm-dutycycle-range = <100 0>;
+               pwm-dutycycle-unit = <100>;
+
+               /* EC turns on w/ ap_core_en; always on for AP */
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-min-microvolt = <799065>;
+               regulator-max-microvolt = <1303738>;
+       };
+
+       ppvar_gpu: ppvar-gpu {
+               compatible = "pwm-regulator";
+               regulator-name = "ppvar_gpu";
+               /*
+                * OVP circuit requires special handling which is not yet
+                * represented. Keep disabled for now.
+                */
+               status = "disabled";
+
+               pwms = <&pwm0 0 3337 0>;
+               pwm-supply = <&ppvar_sys>;
+               pwm-dutycycle-range = <100 0>;
+               pwm-dutycycle-unit = <100>;
+
+               /* EC turns on w/ ap_core_en; always on for AP */
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-min-microvolt = <785782>;
+               regulator-max-microvolt = <1217729>;
+       };
+
+       ppvar_centerlogic: ppvar-centerlogic {
+               compatible = "pwm-regulator";
+               regulator-name = "ppvar_centerlogic";
+               /*
+                * OVP circuit requires special handling which is not yet
+                * represented. Keep disabled for now.
+                */
+               status = "disabled";
+
+               pwms = <&pwm3 0 3337 0>;
+               pwm-supply = <&ppvar_sys>;
+               pwm-dutycycle-range = <100 0>;
+               pwm-dutycycle-unit = <100>;
+
+               /* EC turns on w/ ppvar_centerlogic_en; always on for AP */
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-min-microvolt = <800069>;
+               regulator-max-microvolt = <1049692>;
+       };
+
+       /* Schematics call this PPVAR even though it's fixed */
+       ppvar_logic: ppvar-logic {
+               compatible = "regulator-fixed";
+               regulator-name = "ppvar_logic";
+
+               /* EC turns on w/ ppvar_logic_en; always on for AP */
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-min-microvolt = <900000>;
+               regulator-max-microvolt = <900000>;
+
+               vin-supply = <&ppvar_sys>;
+       };
+
+       /* EC turns on w/ pp900_ddrpll_en */
+       pp900_ddrpll: pp900-ap {
+       };
+
+       /* EC turns on w/ pp900_pcie_en */
+       pp900_pcie: pp900-ap {
+       };
+
+       /* EC turns on w/ pp900_pll_en */
+       pp900_pll: pp900-ap {
+       };
+
+       /* EC turns on w/ pp900_pmu_en */
+       pp900_pmu: pp900-ap {
+       };
+
+       /* EC turns on w/ pp900_usb_en */
+       pp900_usb: pp900-ap {
+       };
+
+       /* EC turns on w/ pp1800_s0_en_l */
+       pp1800_ap_io: pp1800_emmc: pp1800_nfc: pp1800_s0: pp1800 {
+       };
+
+       /* EC turns on w/ pp1800_avdd_en_l */
+       pp1800_avdd: pp1800 {
+       };
+
+       /* EC turns on w/ pp1800_lid_en_l */
+       pp1800_lid: pp1800_mic: pp1800 {
+       };
+
+       /* EC turns on w/ lpddr_pwr_en */
+       pp1800_lpddr: pp1800 {
+       };
+
+       /* EC turns on w/ pp1800_pmu_en_l */
+       pp1800_pmu: pp1800 {
+       };
+
+       /* EC turns on w/ pp1800_usb_en_l */
+       pp1800_usb: pp1800 {
+       };
+
+       pp1500_ap_io: pp1500-ap-io {
+               compatible = "regulator-fixed";
+               regulator-name = "pp1500_ap_io";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pp1500_en>;
+
+               enable-active-high;
+               gpio = <&gpio0 10 GPIO_ACTIVE_HIGH>;
+
+               regulator-always-on;
+               regulator-boot-on;
+               regulator-min-microvolt = <1500000>;
+               regulator-max-microvolt = <1500000>;
+
+               vin-supply = <&pp1800>;
+       };
+
+       pp1800_audio: pp1800-audio {
+               compatible = "regulator-fixed";
+               regulator-name = "pp1800_audio";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pp1800_audio_en>;
+
+               enable-active-high;
+               gpio = <&gpio0 2 GPIO_ACTIVE_HIGH>;
+
+               regulator-always-on;
+               regulator-boot-on;
+
+               vin-supply = <&pp1800>;
+       };
+
+       /* gpio is shared with pp3300_wifi_bt */
+       pp1800_pcie: pp1800-pcie {
+               compatible = "regulator-fixed";
+               regulator-name = "pp1800_pcie";
+               pinctrl-names = "default";
+               pinctrl-0 = <&wlan_module_pd_l>;
+
+               enable-active-high;
+               gpio = <&gpio0 4 GPIO_ACTIVE_HIGH>;
+
+               /*
+                * Need to wait 1ms + ramp-up time before we can power on WiFi.
+                * This has been approximated as 8ms total.
+                */
+               regulator-enable-ramp-delay = <8000>;
+
+               vin-supply = <&pp1800>;
+       };
+
+       /*
+        * This is a bit of a hack. The WiFi module should be reset at least
+        * 1ms after its regulators have ramped up (max rampup time is ~7ms).
+        * With some stretching of the imagination, we can call the 1.8V
+        * regulator a supply.
+        */
+       wlan_pd_n: wlan-pd-n {
+               compatible = "regulator-fixed";
+               regulator-name = "wlan_pd_n";
+
+               /* Note the wlan_module_reset_l pinctrl */
+               enable-active-high;
+               gpio = <&gpio1 11 GPIO_ACTIVE_HIGH>;
+
+               vin-supply = <&pp1800_pcie>;
+       };
+
+       /* Always on; plain and simple */
+       pp3000_ap: pp3000_emmc: pp3000 {
+       };
+
+       pp3000_sd_slot: pp3000-sd-slot {
+               compatible = "regulator-fixed";
+               regulator-name = "pp3000_sd_slot";
+               pinctrl-names = "default";
+               pinctrl-0 = <&sd_slot_pwr_en>;
+
+               enable-active-high;
+               gpio = <&gpio4 29 GPIO_ACTIVE_HIGH>;
+
+               vin-supply = <&pp3000>;
+       };
+
+       /*
+        * Technically, this is a small abuse of 'regulator-gpio'; this
+        * regulator is a mux between pp1800 and pp3300. pp1800 and pp3300 are
+        * always on though, so it is sufficient to simply control the mux
+        * here.
+        */
+       ppvar_sd_card_io: ppvar-sd-card-io {
+               compatible = "regulator-gpio";
+               regulator-name = "ppvar_sd_card_io";
+               pinctrl-names = "default";
+               pinctrl-0 = <&sd_io_pwr_en &sd_pwr_1800_sel>;
+
+               enable-active-high;
+               enable-gpio = <&gpio2 2 GPIO_ACTIVE_HIGH>;
+               gpios = <&gpio2 28 GPIO_ACTIVE_HIGH>;
+               states = <1800000 0x1
+                         3000000 0x0>;
+
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <3000000>;
+       };
+
+       /* EC turns on w/ pp3300_trackpad_en_l */
+       pp3300_trackpad: pp3300-trackpad {
+       };
+
+       /* EC turns on w/ pp3300_usb_en_l */
+       pp3300_usb: pp3300 {
+       };
+
+       pp3300_disp: pp3300-disp {
+               compatible = "regulator-fixed";
+               regulator-name = "pp3300_disp";
+               pinctrl-names = "default";
+               pinctrl-0 = <&pp3300_disp_en>;
+
+               enable-active-high;
+               gpio = <&gpio4 27 GPIO_ACTIVE_HIGH>;
+
+               startup-delay-us = <2000>;
+               vin-supply = <&pp3300>;
+       };
+
+       /* gpio is shared with pp1800_pcie and pinctrl is set there */
+       pp3300_wifi_bt: pp3300-wifi-bt {
+               compatible = "regulator-fixed";
+               regulator-name = "pp3300_wifi_bt";
+
+               enable-active-high;
+               gpio = <&gpio0 4 GPIO_ACTIVE_HIGH>;
+
+               vin-supply = <&pp3300>;
+       };
+
+       /* EC turns on w/ usb_a_en */
+       pp5000_usb_a_vbus: pp5000 {
+       };
+
+       gpio_keys: gpio-keys {
+               compatible = "gpio-keys";
+               pinctrl-names = "default";
+               pinctrl-0 = <&bt_host_wake_l>;
+
+               wake-on-bt {
+                       label = "Wake-on-Bluetooth";
+                       gpios = <&gpio0 3 GPIO_ACTIVE_LOW>;
+                       linux,code = <KEY_WAKEUP>;
+                       wakeup-source;
+               };
+       };
+
+       max98357a: max98357a {
+               compatible = "maxim,max98357a";
+               pinctrl-names = "default";
+               pinctrl-0 = <&sdmode_en>;
+               sdmode-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>;
+               sdmode-delay = <2>;
+               #sound-dai-cells = <0>;
+               status = "okay";
+       };
+
+       sound {
+               compatible = "rockchip,rk3399-gru-sound";
+               rockchip,cpu = <&i2s0 &i2s2>;
+               rockchip,codec = <&max98357a &headsetcodec &codec>;
+       };
+};
+
+/*
+ * Set some suspend operating points to avoid OVP in suspend
+ *
+ * When we go into S3 ARM Trusted Firmware will transition our PWM regulators
+ * from wherever they're at back to the "default" operating point (whatever
+ * voltage we get when we set the PWM pins to "input").
+ *
+ * This quick transition under light load has the possibility to trigger the
+ * regulator "over voltage protection" (OVP).
+ *
+ * To make extra certain that we don't hit this OVP at suspend time, we'll
+ * transition to a voltage that's much closer to the default (~1.0 V) so that
+ * there will not be a big jump.  Technically we only need to get within 200 mV
+ * of the default voltage, but the speed here should be fast enough and we need
+ * suspend/resume to be rock solid.
+ */
+
+&cluster0_opp {
+       opp05 {
+               opp-suspend;
+       };
+};
+
+&cluster1_opp {
+       opp06 {
+               opp-suspend;
+       };
+};
+
+&cpu_l0 {
+       cpu-supply = <&ppvar_litcpu>;
+};
+
+&cpu_l1 {
+       cpu-supply = <&ppvar_litcpu>;
+};
+
+&cpu_l2 {
+       cpu-supply = <&ppvar_litcpu>;
+};
+
+&cpu_l3 {
+       cpu-supply = <&ppvar_litcpu>;
+};
+
+&cpu_b0 {
+       cpu-supply = <&ppvar_bigcpu>;
+};
+
+&cpu_b1 {
+       cpu-supply = <&ppvar_bigcpu>;
+};
+
+
+&cru {
+       assigned-clocks =
+               <&cru PLL_GPLL>, <&cru PLL_CPLL>,
+               <&cru PLL_NPLL>,
+               <&cru ACLK_PERIHP>, <&cru HCLK_PERIHP>,
+               <&cru PCLK_PERIHP>,
+               <&cru ACLK_PERILP0>, <&cru HCLK_PERILP0>,
+               <&cru PCLK_PERILP0>, <&cru ACLK_CCI>,
+               <&cru HCLK_PERILP1>, <&cru PCLK_PERILP1>;
+       assigned-clock-rates =
+               <600000000>, <800000000>,
+               <1000000000>,
+               <150000000>, <75000000>,
+               <37500000>,
+               <100000000>, <100000000>,
+               <50000000>, <800000000>,
+               <100000000>, <50000000>;
+};
+
+&emmc_phy {
+       status = "okay";
+};
+
+ap_i2c_mic: &i2c1 {
+       status = "okay";
+
+       clock-frequency = <400000>;
+
+       /* These are relatively safe rise/fall times */
+       i2c-scl-falling-time-ns = <50>;
+       i2c-scl-rising-time-ns = <300>;
+
+       headsetcodec: rt5514@57 {
+               compatible = "realtek,rt5514";
+               reg = <0x57>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <13 IRQ_TYPE_LEVEL_HIGH>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&mic_int>;
+               realtek,dmic-init-delay = <20>;
+               wakeup-source;
+       };
+};
+
+ap_i2c_ts: &i2c3 {
+       status = "okay";
+
+       clock-frequency = <400000>;
+
+       /* These are relatively safe rise/fall times */
+       i2c-scl-falling-time-ns = <50>;
+       i2c-scl-rising-time-ns = <300>;
+};
+
+ap_i2c_tp: &i2c5 {
+       status = "okay";
+
+       clock-frequency = <400000>;
+
+       /* These are relatively safe rise/fall times */
+       i2c-scl-falling-time-ns = <50>;
+       i2c-scl-rising-time-ns = <300>;
+
+       /*
+        * Note strange pullup enable.  Apparently this avoids leakage but
+        * still allows us to get nice 4.7K pullups for high speed i2c
+        * transfers.  Basically we want the pullup on whenever the ap is
+        * alive, so the "en" pin just gets set to output high.
+        */
+       pinctrl-0 = <&i2c5_xfer &ap_i2c_tp_pu_en>;
+};
+
+ap_i2c_audio: &i2c8 {
+       status = "okay";
+
+       clock-frequency = <400000>;
+
+       /* These are relatively safe rise/fall times */
+       i2c-scl-falling-time-ns = <50>;
+       i2c-scl-rising-time-ns = <300>;
+
+       codec: da7219@1a {
+               compatible = "dlg,da7219";
+               reg = <0x1a>;
+               interrupt-parent = <&gpio1>;
+               interrupts = <23 IRQ_TYPE_LEVEL_LOW>;
+               clocks = <&cru SCLK_I2S_8CH_OUT>;
+               clock-names = "mclk";
+               dlg,micbias-lvl = <2600>;
+               dlg,mic-amp-in-sel = "diff";
+               pinctrl-names = "default";
+               pinctrl-0 = <&headset_int_l>;
+               VDD-supply = <&pp1800>;
+               VDDMIC-supply = <&pp3300>;
+               VDDIO-supply = <&pp1800>;
+
+               da7219_aad {
+                       dlg,adc-1bit-rpt = <1>;
+                       dlg,btn-avg = <4>;
+                       dlg,btn-cfg = <50>;
+                       dlg,mic-det-thr = <500>;
+                       dlg,jack-ins-deb = <20>;
+                       dlg,jack-det-rate = "32ms_64ms";
+                       dlg,jack-rem-deb = <1>;
+
+                       dlg,a-d-btn-thr = <0xa>;
+                       dlg,d-b-btn-thr = <0x16>;
+                       dlg,b-c-btn-thr = <0x21>;
+                       dlg,c-mic-btn-thr = <0x3E>;
+               };
+       };
+};
+
+&i2s0 {
+       status = "okay";
+};
+
+&i2s2 {
+       status = "okay";
+};
+
+&io_domains {
+       status = "okay";
+
+       audio-supply = <&pp1800_audio>;         /* APIO5_VDD;  3d 4a */
+       bt656-supply = <&pp1800_ap_io>;         /* APIO2_VDD;  2a 2b */
+       gpio1830-supply = <&pp3000_ap>;         /* APIO4_VDD;  4c 4d */
+       sdmmc-supply = <&ppvar_sd_card_io>;     /* SDMMC0_VDD; 4b    */
+};
+
+&pcie0 {
+       status = "okay";
+
+       ep-gpios = <&gpio2 27 GPIO_ACTIVE_HIGH>;
+       pinctrl-names = "default";
+       pinctrl-0 = <&pcie_clkreqn_cpm>, <&wifi_perst_l>;
+       vpcie3v3-supply = <&pp3300_wifi_bt>;
+       vpcie1v8-supply = <&wlan_pd_n>; /* HACK: see &wlan_pd_n */
+       vpcie0v9-supply = <&pp900_pcie>;
+
+       pci_rootport: pcie@0,0 {
+               reg = <0x83000000 0x0 0x00000000 0x0 0x00000000>;
+               #address-cells = <3>;
+               #size-cells = <2>;
+               ranges;
+
+               mvl_wifi: wifi@0,0 {
+                       compatible = "pci1b4b,2b42";
+                       reg = <0x83010000 0x0 0x00000000 0x0 0x00100000
+                              0x83010000 0x0 0x00100000 0x0 0x00100000>;
+                       interrupt-parent = <&gpio0>;
+                       interrupts = <8 IRQ_TYPE_LEVEL_LOW>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&wlan_host_wake_l>;
+                       wakeup-source;
+               };
+       };
+};
+
+&pcie_phy {
+       status = "okay";
+};
+
+&pmu_io_domains {
+       status = "okay";
+
+       pmu1830-supply = <&pp1800_pmu>;         /* PMUIO2_VDD */
+};
+
+&pwm0 {
+       status = "okay";
+};
+
+&pwm1 {
+       status = "okay";
+};
+
+&pwm2 {
+       status = "okay";
+};
+
+&pwm3 {
+       status = "okay";
+};
+
+&sdhci {
+       /*
+        * Signal integrity isn't great at 200 MHz and 150 MHz (DDR) gives the
+        * same (or nearly the same) performance for all eMMC that are intended
+        * to be used.
+        */
+       assigned-clock-rates = <150000000>;
+
+       bus-width = <8>;
+       mmc-hs400-1_8v;
+       mmc-hs400-enhanced-strobe;
+       non-removable;
+       status = "okay";
+};
+
+&sdmmc {
+       status = "okay";
+
+       /*
+        * Note: configure "sdmmc_cd" as card detect even though it's actually
+        * hooked to ground.  Because we specified "cd-gpios" below dw_mmc
+        * should be ignoring card detect anyway.  Specifying the pin as
+        * sdmmc_cd means that even if you've got GRF_SOC_CON7[12] (force_jtag)
+        * turned on that the system will still make sure the port is
+        * configured as SDMMC and not JTAG.
+        */
+       pinctrl-names = "default";
+       pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_cd &sdmmc_cd_gpio
+                    &sdmmc_bus4>;
+
+       bus-width = <4>;
+       cap-mmc-highspeed;
+       cap-sd-highspeed;
+       cd-gpios = <&gpio4 24 GPIO_ACTIVE_LOW>;
+       disable-wp;
+       sd-uhs-sdr12;
+       sd-uhs-sdr25;
+       sd-uhs-sdr50;
+       sd-uhs-sdr104;
+       vmmc-supply = <&pp3000_sd_slot>;
+       vqmmc-supply = <&ppvar_sd_card_io>;
+};
+
+&spi1 {
+       status = "okay";
+
+       pinctrl-names = "default", "sleep";
+       pinctrl-1 = <&spi1_sleep>;
+
+       spiflash@0 {
+               compatible = "jedec,spi-nor";
+               reg = <0>;
+
+               /* May run faster once verified. */
+               spi-max-frequency = <10000000>;
+       };
+};
+
+&spi2 {
+       status = "okay";
+
+       wacky_spi_audio: spi2@0 {
+               compatible = "realtek,rt5514";
+               reg = <0>;
+
+               /* May run faster once verified. */
+               spi-max-frequency = <10000000>;
+       };
+};
+
+&spi5 {
+       status = "okay";
+
+       cros_ec: ec@0 {
+               compatible = "google,cros-ec-spi";
+               reg = <0>;
+               interrupt-parent = <&gpio0>;
+               interrupts = <1 IRQ_TYPE_LEVEL_LOW>;
+               pinctrl-names = "default";
+               pinctrl-0 = <&ec_ap_int_l>;
+               spi-max-frequency = <3000000>;
+
+               i2c_tunnel: i2c-tunnel {
+                       compatible = "google,cros-ec-i2c-tunnel";
+                       google,remote-bus = <4>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+               };
+
+               cros_ec_pwm: ec-pwm {
+                       compatible = "google,cros-ec-pwm";
+                       #pwm-cells = <1>;
+               };
+       };
+};
+
+&tsadc {
+       status = "okay";
+
+       rockchip,hw-tshut-mode = <1>; /* tshut mode 0:CRU 1:GPIO */
+       rockchip,hw-tshut-polarity = <1>; /* tshut polarity 0:LOW 1:HIGH */
+};
+
+&u2phy0 {
+       status = "okay";
+};
+
+&u2phy1 {
+       status = "okay";
+};
+
+&u2phy0_host {
+       status = "okay";
+};
+
+&u2phy1_host {
+       status = "okay";
+};
+
+&u2phy0_otg {
+       status = "okay";
+};
+
+&u2phy1_otg {
+       status = "okay";
+};
+
+&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 = "host";
+};
+
+&usbdrd3_1 {
+       status = "okay";
+};
+
+&usbdrd_dwc3_1 {
+       status = "okay";
+       dr_mode = "host";
+};
+
+#include <arm/cros-ec-keyboard.dtsi>
+#include <arm/cros-ec-sbs.dtsi>
+
+&pinctrl {
+       /*
+        * pinctrl settings for pins that have no real owners.
+        *
+        * At the moment settings are identical for S0 and S3, but if we later
+        * need to configure things differently for S3 we'll adjust here.
+        */
+       pinctrl-names = "default";
+       pinctrl-0 = <
+               &ap_pwroff      /* AP will auto-assert this when in S3 */
+               &clk_32k        /* This pin is always 32k on gru boards */
+
+               /*
+                * We want this driven low ASAP; firmware should help us, but
+                * we can help ourselves too.
+                */
+               &wlan_module_reset_l
+       >;
+
+       pcfg_output_low: pcfg-output-low {
+               output-low;
+       };
+
+       pcfg_output_high: pcfg-output-high {
+               output-high;
+       };
+
+       pcfg_pull_none_8ma: pcfg-pull-none-8ma {
+               bias-disable;
+               drive-strength = <8>;
+       };
+
+       backlight-enable {
+               bl_en: bl-en {
+                       rockchip,pins = <1 17 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       cros-ec {
+               ec_ap_int_l: ec-ap-int-l {
+                       rockchip,pins = <RK_GPIO0 1 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+       };
+
+       discrete-regulators {
+               pp1500_en: pp1500-en {
+                       rockchip,pins = <RK_GPIO0 10 RK_FUNC_GPIO
+                                        &pcfg_pull_none>;
+               };
+
+               pp1800_audio_en: pp1800-audio-en {
+                       rockchip,pins = <RK_GPIO0 2 RK_FUNC_GPIO
+                                        &pcfg_pull_down>;
+               };
+
+               pp3300_disp_en: pp3300-disp-en {
+                       rockchip,pins = <RK_GPIO4 27 RK_FUNC_GPIO
+                                        &pcfg_pull_none>;
+               };
+
+               pp3000_en: pp3000-en {
+                       rockchip,pins = <RK_GPIO0 12 RK_FUNC_GPIO
+                                        &pcfg_pull_none>;
+               };
+
+               sd_io_pwr_en: sd-io-pwr-en {
+                       rockchip,pins = <RK_GPIO2 2 RK_FUNC_GPIO
+                                        &pcfg_pull_none>;
+               };
+
+               sd_pwr_1800_sel: sd-pwr-1800-sel {
+                       rockchip,pins = <RK_GPIO2 28 RK_FUNC_GPIO
+                                        &pcfg_pull_none>;
+               };
+
+               sd_slot_pwr_en: sd-slot-pwr-en {
+                       rockchip,pins = <RK_GPIO4 29 RK_FUNC_GPIO
+                                        &pcfg_pull_none>;
+               };
+
+               wlan_module_pd_l: wlan-module-pd-l {
+                       rockchip,pins = <RK_GPIO0 4 RK_FUNC_GPIO
+                                        &pcfg_pull_down>;
+               };
+       };
+
+       codec {
+               /* Has external pullup */
+               headset_int_l: headset-int-l {
+                       rockchip,pins = <1 23 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+
+               mic_int: mic-int {
+                       rockchip,pins = <1 13 RK_FUNC_GPIO &pcfg_pull_down>;
+               };
+       };
+
+       max98357a {
+               sdmode_en: sdmode-en {
+                       rockchip,pins = <1 2 RK_FUNC_GPIO &pcfg_pull_down>;
+               };
+       };
+
+       pcie {
+               pcie_clkreqn_cpm: pci-clkreqn-cpm {
+                       /*
+                        * Since our pcie doesn't support ClockPM(CPM), we want
+                        * to hack this as gpio, so the EP could be able to
+                        * de-assert it along and make ClockPM(CPM) work.
+                        */
+                       rockchip,pins = <2 26 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       sdmmc {
+               /*
+                * We run sdmmc at max speed; bump up drive strength.
+                * We also have external pulls, so disable the internal ones.
+                */
+               sdmmc_bus4: sdmmc-bus4 {
+                       rockchip,pins =
+                               <4 8 RK_FUNC_1 &pcfg_pull_none_8ma>,
+                               <4 9 RK_FUNC_1 &pcfg_pull_none_8ma>,
+                               <4 10 RK_FUNC_1 &pcfg_pull_none_8ma>,
+                               <4 11 RK_FUNC_1 &pcfg_pull_none_8ma>;
+               };
+
+               sdmmc_clk: sdmmc-clk {
+                       rockchip,pins =
+                               <4 12 RK_FUNC_1 &pcfg_pull_none_8ma>;
+               };
+
+               sdmmc_cmd: sdmmc-cmd {
+                       rockchip,pins =
+                               <4 13 RK_FUNC_1 &pcfg_pull_none_8ma>;
+               };
+
+               /*
+                * In our case the official card detect is hooked to ground
+                * to avoid getting access to JTAG just by sticking something
+                * in the SD card slot (see the force_jtag bit in the TRM).
+                *
+                * We still configure it as card detect because it doesn't
+                * hurt and dw_mmc will ignore it.  We make sure to disable
+                * the pull though so we don't burn needless power.
+                */
+               sdmmc_cd: sdmcc-cd {
+                       rockchip,pins =
+                               <0 7 RK_FUNC_1 &pcfg_pull_none>;
+               };
+
+               /* This is where we actually hook up CD; has external pull */
+               sdmmc_cd_gpio: sdmmc-cd-gpio {
+                       rockchip,pins = <4 24 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       spi1 {
+               spi1_sleep: spi1-sleep {
+                       /*
+                        * Pull down SPI1 CLK/CS/RX/TX during suspend, to
+                        * prevent leakage.
+                        */
+                       rockchip,pins = <1 9 RK_FUNC_GPIO &pcfg_pull_down>,
+                                       <1 10 RK_FUNC_GPIO &pcfg_pull_down>,
+                                       <1 7 RK_FUNC_GPIO &pcfg_pull_down>,
+                                       <1 8 RK_FUNC_GPIO &pcfg_pull_down>;
+               };
+       };
+
+       touchscreen {
+               touch_int_l: touch-int-l {
+                       rockchip,pins = <3 13 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+
+               touch_reset_l: touch-reset-l {
+                       rockchip,pins = <4 26 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+       };
+
+       trackpad {
+               ap_i2c_tp_pu_en: ap-i2c-tp-pu-en {
+                       rockchip,pins = <3 12 RK_FUNC_GPIO &pcfg_output_high>;
+               };
+
+               trackpad_int_l: trackpad-int-l {
+                       rockchip,pins = <1 4 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+       };
+
+       wifi {
+               wifi_perst_l: wifi-perst-l {
+                       rockchip,pins = <2 27 RK_FUNC_GPIO &pcfg_pull_none>;
+               };
+
+               wlan_module_reset_l: wlan-module-reset-l {
+                       /*
+                        * We want this driven low ASAP (As {Soon,Strongly} As
+                        * Possible), to avoid leakage through the powered-down
+                        * WiFi.
+                        */
+                       rockchip,pins = <1 11 RK_FUNC_GPIO &pcfg_output_low>;
+               };
+
+               bt_host_wake_l: bt-host-wake-l {
+                       /* Kevin has an external pull up, but Gru does not */
+                       rockchip,pins = <0 3 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+       };
+
+       write-protect {
+               ap_fw_wp: ap-fw-wp {
+                       rockchip,pins = <1 18 RK_FUNC_GPIO &pcfg_pull_up>;
+               };
+       };
+};
diff --git a/arch/arm64/boot/dts/rockchip/rk3399-opp.dtsi b/arch/arm64/boot/dts/rockchip/rk3399-opp.dtsi
new file mode 100644 (file)
index 0000000..dd82e16
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 2016-2017 Fuzhou Rockchip Electronics Co., Ltd
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This library is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This library is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/ {
+       cluster0_opp: opp-table0 {
+               compatible = "operating-points-v2";
+               opp-shared;
+
+               opp00 {
+                       opp-hz = /bits/ 64 <408000000>;
+                       opp-microvolt = <800000>;
+                       clock-latency-ns = <40000>;
+               };
+               opp01 {
+                       opp-hz = /bits/ 64 <600000000>;
+                       opp-microvolt = <800000>;
+               };
+               opp02 {
+                       opp-hz = /bits/ 64 <816000000>;
+                       opp-microvolt = <800000>;
+               };
+               opp03 {
+                       opp-hz = /bits/ 64 <1008000000>;
+                       opp-microvolt = <875000>;
+               };
+               opp04 {
+                       opp-hz = /bits/ 64 <1200000000>;
+                       opp-microvolt = <925000>;
+               };
+               opp05 {
+                       opp-hz = /bits/ 64 <1416000000>;
+                       opp-microvolt = <1050000>;
+               };
+               opp06 {
+                       opp-hz = /bits/ 64 <1512000000>;
+                       opp-microvolt = <1125000>;
+               };
+       };
+
+       cluster1_opp: opp-table1 {
+               compatible = "operating-points-v2";
+               opp-shared;
+
+               opp00 {
+                       opp-hz = /bits/ 64 <408000000>;
+                       opp-microvolt = <800000>;
+                       clock-latency-ns = <40000>;
+               };
+               opp01 {
+                       opp-hz = /bits/ 64 <600000000>;
+                       opp-microvolt = <800000>;
+               };
+               opp02 {
+                       opp-hz = /bits/ 64 <816000000>;
+                       opp-microvolt = <825000>;
+               };
+               opp03 {
+                       opp-hz = /bits/ 64 <1008000000>;
+                       opp-microvolt = <875000>;
+               };
+               opp04 {
+                       opp-hz = /bits/ 64 <1200000000>;
+                       opp-microvolt = <950000>;
+               };
+               opp05 {
+                       opp-hz = /bits/ 64 <1416000000>;
+                       opp-microvolt = <1025000>;
+               };
+               opp06 {
+                       opp-hz = /bits/ 64 <1608000000>;
+                       opp-microvolt = <1075000>;
+               };
+               opp07 {
+                       opp-hz = /bits/ 64 <1800000000>;
+                       opp-microvolt = <1150000>;
+               };
+               opp08 {
+                       opp-hz = /bits/ 64 <2016000000>;
+                       opp-microvolt = <1250000>;
+               };
+       };
+};
+
+&cpu_l0 {
+       operating-points-v2 = <&cluster0_opp>;
+};
+
+&cpu_l1 {
+       operating-points-v2 = <&cluster0_opp>;
+};
+
+&cpu_l2 {
+       operating-points-v2 = <&cluster0_opp>;
+};
+
+&cpu_l3 {
+       operating-points-v2 = <&cluster0_opp>;
+};
+
+&cpu_b0 {
+       operating-points-v2 = <&cluster1_opp>;
+};
+
+&cpu_b1 {
+       operating-points-v2 = <&cluster1_opp>;
+};
index 8e6d1bdeb9c3bdd83f1b4d1b37d92f4073698cb6..f4f3c96c798d0c0caf5def9b155c8b273f3ba6e4 100644 (file)
                };
        };
 
+       pcie0: pcie@f8000000 {
+               compatible = "rockchip,rk3399-pcie";
+               reg = <0x0 0xf8000000 0x0 0x2000000>,
+                     <0x0 0xfd000000 0x0 0x1000000>;
+               reg-names = "axi-base", "apb-base";
+               #address-cells = <3>;
+               #size-cells = <2>;
+               #interrupt-cells = <1>;
+               aspm-no-l0s;
+               bus-range = <0x0 0x1>;
+               clocks = <&cru ACLK_PCIE>, <&cru ACLK_PERF_PCIE>,
+                        <&cru PCLK_PCIE>, <&cru SCLK_PCIE_PM>;
+               clock-names = "aclk", "aclk-perf",
+                             "hclk", "pm";
+               interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH 0>,
+                            <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH 0>,
+                            <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH 0>;
+               interrupt-names = "sys", "legacy", "client";
+               interrupt-map-mask = <0 0 0 7>;
+               interrupt-map = <0 0 0 1 &pcie0_intc 0>,
+                               <0 0 0 2 &pcie0_intc 1>,
+                               <0 0 0 3 &pcie0_intc 2>,
+                               <0 0 0 4 &pcie0_intc 3>;
+               linux,pci-domain = <0>;
+               max-link-speed = <1>;
+               msi-map = <0x0 &its 0x0 0x1000>;
+               phys = <&pcie_phy>;
+               phy-names = "pcie-phy";
+               ranges = <0x83000000 0x0 0xfa000000 0x0 0xfa000000 0x0 0x600000
+                         0x81000000 0x0 0xfa600000 0x0 0xfa600000 0x0 0x100000>;
+               resets = <&cru SRST_PCIE_CORE>, <&cru SRST_PCIE_MGMT>,
+                        <&cru SRST_PCIE_MGMT_STICKY>, <&cru SRST_PCIE_PIPE>,
+                        <&cru SRST_PCIE_PM>, <&cru SRST_P_PCIE>,
+                        <&cru SRST_A_PCIE>;
+               reset-names = "core", "mgmt", "mgmt-sticky", "pipe",
+                             "pm", "pclk", "aclk";
+               status = "disabled";
+
+               pcie0_intc: interrupt-controller {
+                       interrupt-controller;
+                       #address-cells = <0>;
+                       #interrupt-cells = <1>;
+               };
+       };
+
        gmac: ethernet@fe300000 {
                compatible = "rockchip,rk3399-gmac";
                reg = <0x0 0xfe300000 0x0 0x10000>;
                         <&cru SCLK_SDIO_DRV>, <&cru SCLK_SDIO_SAMPLE>;
                clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
                fifo-depth = <0x100>;
+               resets = <&cru SRST_SDIO0>;
+               reset-names = "reset";
                status = "disabled";
        };
 
                clock-names = "biu", "ciu", "ciu-drive", "ciu-sample";
                fifo-depth = <0x100>;
                power-domains = <&power RK3399_PD_SD>;
+               resets = <&cru SRST_SDMMC>;
+               reset-names = "reset";
                status = "disabled";
        };
 
                status = "disabled";
        };
 
-       pcie0: pcie@f8000000 {
-               compatible = "rockchip,rk3399-pcie";
-               reg = <0x0 0xf8000000 0x0 0x2000000>,
-                     <0x0 0xfd000000 0x0 0x1000000>;
-               reg-names = "axi-base", "apb-base";
-               #address-cells = <3>;
-               #size-cells = <2>;
-               #interrupt-cells = <1>;
-               aspm-no-l0s;
-               bus-range = <0x0 0x1>;
-               clocks = <&cru ACLK_PCIE>, <&cru ACLK_PERF_PCIE>,
-                        <&cru PCLK_PCIE>, <&cru SCLK_PCIE_PM>;
-               clock-names = "aclk", "aclk-perf",
-                             "hclk", "pm";
-               interrupts = <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH 0>,
-                            <GIC_SPI 50 IRQ_TYPE_LEVEL_HIGH 0>,
-                            <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH 0>;
-               interrupt-names = "sys", "legacy", "client";
-               interrupt-map-mask = <0 0 0 7>;
-               interrupt-map = <0 0 0 1 &pcie0_intc 0>,
-                               <0 0 0 2 &pcie0_intc 1>,
-                               <0 0 0 3 &pcie0_intc 2>,
-                               <0 0 0 4 &pcie0_intc 3>;
-               max-link-speed = <1>;
-               msi-map = <0x0 &its 0x0 0x1000>;
-               phys = <&pcie_phy>;
-               phy-names = "pcie-phy";
-               ranges = <0x83000000 0x0 0xfa000000 0x0 0xfa000000 0x0 0x600000
-                         0x81000000 0x0 0xfa600000 0x0 0xfa600000 0x0 0x100000>;
-               resets = <&cru SRST_PCIE_CORE>, <&cru SRST_PCIE_MGMT>,
-                        <&cru SRST_PCIE_MGMT_STICKY>, <&cru SRST_PCIE_PIPE>,
-                        <&cru SRST_PCIE_PM>, <&cru SRST_P_PCIE>,
-                        <&cru SRST_A_PCIE>;
-               reset-names = "core", "mgmt", "mgmt-sticky", "pipe",
-                             "pm", "pclk", "aclk";
-               status = "disabled";
-
-               pcie0_intc: interrupt-controller {
-                       interrupt-controller;
-                       #address-cells = <0>;
-                       #interrupt-cells = <1>;
-               };
-       };
-
        usb_host0_ehci: usb@fe380000 {
                compatible = "generic-ehci";
                reg = <0x0 0xfe380000 0x0 0x20000>;
                status = "disabled";
        };
 
+       usbdrd3_0: usb@fe800000 {
+               compatible = "rockchip,rk3399-dwc3";
+               #address-cells = <2>;
+               #size-cells = <2>;
+               ranges;
+               clocks = <&cru SCLK_USB3OTG0_REF>, <&cru SCLK_USB3OTG0_SUSPEND>,
+                        <&cru ACLK_USB3OTG0>, <&cru ACLK_USB3_GRF>;
+               clock-names = "ref_clk", "suspend_clk",
+                             "bus_clk", "grf_clk";
+               status = "disabled";
+
+               usbdrd_dwc3_0: dwc3 {
+                       compatible = "snps,dwc3";
+                       reg = <0x0 0xfe800000 0x0 0x100000>;
+                       interrupts = <GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH 0>;
+                       dr_mode = "otg";
+                       phys = <&u2phy0_otg>;
+                       phy-names = "usb2-phy";
+                       phy_type = "utmi_wide";
+                       snps,dis_enblslpm_quirk;
+                       snps,dis-u2-freeclk-exists-quirk;
+                       snps,dis_u2_susphy_quirk;
+                       snps,dis-del-phy-power-chg-quirk;
+                       status = "disabled";
+               };
+       };
+
+       usbdrd3_1: usb@fe900000 {
+               compatible = "rockchip,rk3399-dwc3";
+               #address-cells = <2>;
+               #size-cells = <2>;
+               ranges;
+               clocks = <&cru SCLK_USB3OTG1_REF>, <&cru SCLK_USB3OTG1_SUSPEND>,
+                        <&cru ACLK_USB3OTG1>, <&cru ACLK_USB3_GRF>;
+               clock-names = "ref_clk", "suspend_clk",
+                             "bus_clk", "grf_clk";
+               status = "disabled";
+
+               usbdrd_dwc3_1: dwc3 {
+                       compatible = "snps,dwc3";
+                       reg = <0x0 0xfe900000 0x0 0x100000>;
+                       interrupts = <GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH 0>;
+                       dr_mode = "otg";
+                       phys = <&u2phy1_otg>;
+                       phy-names = "usb2-phy";
+                       phy_type = "utmi_wide";
+                       snps,dis_enblslpm_quirk;
+                       snps,dis-u2-freeclk-exists-quirk;
+                       snps,dis_u2_susphy_quirk;
+                       snps,dis-del-phy-power-chg-quirk;
+                       status = "disabled";
+               };
+       };
+
        gic: interrupt-controller@fee00000 {
                compatible = "arm,gic-v3";
                #interrupt-cells = <4>;
index 7168cf818ad8dc4f942887abfdb965211c3d2991..0173e93ab14169f51d7ba4b673e1b98cd6b0a689 100644 (file)
        model = "UniPhier LD11 Reference Board";
        compatible = "socionext,uniphier-ld11-ref", "socionext,uniphier-ld11";
 
-       memory {
-               device_type = "memory";
-               reg = <0 0x80000000 0 0x40000000>;
-       };
-
        chosen {
                stdout-path = "serial0:115200n8";
        };
                i2c4 = &i2c4;
                i2c5 = &i2c5;
        };
+
+       memory@80000000 {
+               device_type = "memory";
+               reg = <0 0x80000000 0 0x40000000>;
+       };
 };
 
 &ethsc {
index da881f5b6ed46df6b5319e034ddf3e073090a0f1..151c043b4835a14cd5db873b640b04f8731b2c19 100644 (file)
                             <1 10 4>;
        };
 
-       soc {
+       soc@0 {
                compatible = "simple-bus";
                #address-cells = <1>;
                #size-cells = <1>;
                        compatible = "socionext,uniphier-sd4hc", "cdns,sd4hc";
                        reg = <0x5a000000 0x400>;
                        interrupts = <0 78 4>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_emmc>;
                        clocks = <&sys_clk 4>;
                        bus-width = <8>;
                        mmc-ddr-1_8v;
                        pinctrl-names = "default";
                        pinctrl-0 = <&pinctrl_usb0>;
                        clocks = <&mio_clk 7>, <&mio_clk 8>, <&mio_clk 12>;
-                       resets = <&mio_rst 7>, <&mio_rst 8>, <&mio_rst 12>, <&sys_rst 8>;
+                       resets = <&sys_rst 8>, <&mio_rst 7>, <&mio_rst 8>,
+                                <&mio_rst 12>;
                };
 
                usb1: usb@5a810100 {
                        pinctrl-names = "default";
                        pinctrl-0 = <&pinctrl_usb1>;
                        clocks = <&mio_clk 7>, <&mio_clk 9>, <&mio_clk 13>;
-                       resets = <&mio_rst 7>, <&mio_rst 9>, <&mio_rst 13>, <&sys_rst 8>;
+                       resets = <&sys_rst 8>, <&mio_rst 7>, <&mio_rst 9>,
+                                <&mio_rst 13>;
                };
 
                usb2: usb@5a820100 {
                        pinctrl-names = "default";
                        pinctrl-0 = <&pinctrl_usb2>;
                        clocks = <&mio_clk 7>, <&mio_clk 10>, <&mio_clk 14>;
-                       resets = <&mio_rst 7>, <&mio_rst 10>, <&mio_rst 14>, <&sys_rst 8>;
+                       resets = <&sys_rst 8>, <&mio_rst 7>, <&mio_rst 10>,
+                                <&mio_rst 14>;
                };
 
                mioctrl@5b3e0000 {
index 609162a1a322445e1f11a8c45a43719f1a6b0c21..fca4c479b469956fc9934c5104a8b48c9ac67443 100644 (file)
        model = "UniPhier LD20 Reference Board";
        compatible = "socionext,uniphier-ld20-ref", "socionext,uniphier-ld20";
 
-       memory {
-               device_type = "memory";
-               reg = <0 0x80000000 0 0xc0000000>;
-       };
-
        chosen {
                stdout-path = "serial0:115200n8";
        };
                i2c4 = &i2c4;
                i2c5 = &i2c5;
        };
+
+       memory@80000000 {
+               device_type = "memory";
+               reg = <0 0x80000000 0 0xc0000000>;
+       };
 };
 
 &ethsc {
index a6b3a70dae831bf0206a5c3500b3fd779d25b10b..6193f11acb78dba818f17e954db47a4e23593888 100644 (file)
                             <1 10 4>;
        };
 
-       soc {
+       soc@0 {
                compatible = "simple-bus";
                #address-cells = <1>;
                #size-cells = <1>;
                        compatible = "socionext,uniphier-sd4hc", "cdns,sd4hc";
                        reg = <0x5a000000 0x400>;
                        interrupts = <0 78 4>;
+                       pinctrl-names = "default";
+                       pinctrl-0 = <&pinctrl_emmc>;
                        clocks = <&sys_clk 4>;
                        bus-width = <8>;
                        mmc-ddr-1_8v;
index b658c5e09b15f7b47137484f1e1191002a88cdb9..f0535e6eaaaa0ae9e72a08ed0c2c2235b5962c1f 100644 (file)
@@ -1,4 +1,5 @@
-dtb-$(CONFIG_ARCH_SPRD) += sc9836-openphone.dtb
+dtb-$(CONFIG_ARCH_SPRD) += sc9836-openphone.dtb \
+                       sp9860g-1h10.dtb
 
 always         := $(dtb-y)
 subdir-y       := $(dts-dirs)
diff --git a/arch/arm64/boot/dts/sprd/sc9860.dtsi b/arch/arm64/boot/dts/sprd/sc9860.dtsi
new file mode 100644 (file)
index 0000000..7b7d8ce
--- /dev/null
@@ -0,0 +1,569 @@
+/*
+ * Spreadtrum SC9860 SoC
+ *
+ * Copyright (C) 2016, Spreadtrum Communications Inc.
+ *
+ * SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "whale2.dtsi"
+
+/ {
+       cpus {
+               #address-cells = <2>;
+               #size-cells = <0>;
+
+               cpu-map {
+                       cluster0 {
+                               core0 {
+                                       cpu = <&CPU0>;
+                               };
+                               core1 {
+                                       cpu = <&CPU1>;
+                               };
+                               core2 {
+                                       cpu = <&CPU2>;
+                               };
+                               core3 {
+                                       cpu = <&CPU3>;
+                               };
+                       };
+
+                       cluster1 {
+                               core0 {
+                                       cpu = <&CPU4>;
+                               };
+                               core1 {
+                                       cpu = <&CPU5>;
+                               };
+                               core2 {
+                                       cpu = <&CPU6>;
+                               };
+                               core3 {
+                                       cpu = <&CPU7>;
+                               };
+                       };
+               };
+
+               CPU0: cpu@530000 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       reg = <0x0 0x530000>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CORE_PD &CLUSTER_PD>;
+               };
+
+               CPU1: cpu@530001 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       reg = <0x0 0x530001>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CORE_PD &CLUSTER_PD>;
+               };
+
+               CPU2: cpu@530002 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       reg = <0x0 0x530002>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CORE_PD &CLUSTER_PD>;
+               };
+
+               CPU3: cpu@530003 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       reg = <0x0 0x530003>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CORE_PD &CLUSTER_PD>;
+               };
+
+               CPU4: cpu@530100 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       reg = <0x0 0x530100>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CORE_PD &CLUSTER_PD>;
+               };
+
+               CPU5: cpu@530101 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       reg = <0x0 0x530101>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CORE_PD &CLUSTER_PD>;
+               };
+
+               CPU6: cpu@530102 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       reg = <0x0 0x530102>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CORE_PD &CLUSTER_PD>;
+               };
+
+               CPU7: cpu@530103 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53", "arm,armv8";
+                       reg = <0x0 0x530103>;
+                       enable-method = "psci";
+                       cpu-idle-states = <&CORE_PD &CLUSTER_PD>;
+               };
+       };
+
+       idle-states{
+               entry-method = "arm,psci";
+
+               CORE_PD: core_pd {
+                       compatible = "arm,idle-state";
+                       entry-latency-us = <1000>;
+                       exit-latency-us = <700>;
+                       min-residency-us = <2500>;
+                       local-timer-stop;
+                       arm,psci-suspend-param = <0x00010002>;
+               };
+
+               CLUSTER_PD: cluster_pd {
+                       compatible = "arm,idle-state";
+                       entry-latency-us = <1000>;
+                       exit-latency-us = <1000>;
+                       min-residency-us = <3000>;
+                       local-timer-stop;
+                       arm,psci-suspend-param = <0x01010003>;
+               };
+       };
+
+       gic: interrupt-controller@12001000 {
+               compatible = "arm,gic-400";
+               reg = <0 0x12001000 0 0x1000>,
+                     <0 0x12002000 0 0x2000>,
+                     <0 0x12004000 0 0x2000>,
+                     <0 0x12006000 0 0x2000>;
+               #interrupt-cells = <3>;
+               interrupt-controller;
+               interrupts = <GIC_PPI 9 (GIC_CPU_MASK_SIMPLE(8)
+                                       | IRQ_TYPE_LEVEL_HIGH)>;
+       };
+
+       psci {
+               compatible = "arm,psci-0.2";
+               method = "smc";
+       };
+
+       timer {
+               compatible = "arm,armv8-timer";
+               interrupts = <GIC_PPI 13 (GIC_CPU_MASK_SIMPLE(8)
+                                        | IRQ_TYPE_LEVEL_LOW)>,
+                            <GIC_PPI 14 (GIC_CPU_MASK_SIMPLE(8)
+                                        | IRQ_TYPE_LEVEL_LOW)>,
+                            <GIC_PPI 11 (GIC_CPU_MASK_SIMPLE(8)
+                                        | IRQ_TYPE_LEVEL_LOW)>,
+                            <GIC_PPI 10 (GIC_CPU_MASK_SIMPLE(8)
+                                        | IRQ_TYPE_LEVEL_LOW)>;
+       };
+
+       pmu {
+               compatible = "arm,cortex-a53-pmu", "arm,armv8-pmuv3";
+               interrupts = <GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 123 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 124 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 125 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 154 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 155 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 156 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SPI 157 IRQ_TYPE_LEVEL_HIGH>;
+               interrupt-affinity = <&CPU0>,
+                                    <&CPU1>,
+                                    <&CPU2>,
+                                    <&CPU3>,
+                                    <&CPU4>,
+                                    <&CPU5>,
+                                    <&CPU6>,
+                                    <&CPU7>;
+       };
+
+       soc {
+               funnel@10001000 { /* SoC Funnel */
+                       compatible = "arm,coresight-funnel", "arm,primecell";
+                       reg = <0 0x10001000 0 0x1000>;
+                       clocks = <&ext_26m>;
+                       clock-names = "apb_pclk";
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               port@0 {
+                                       reg = <0>;
+                                       soc_funnel_out_port: endpoint {
+                                               remote-endpoint = <&etb_in>;
+                                       };
+                               };
+
+                               port@1 {
+                                       reg = <0>;
+                                       soc_funnel_in_port0: endpoint {
+                                               slave-mode;
+                                               remote-endpoint =
+                                               <&main_funnel_out_port>;
+                                       };
+                               };
+
+                               port@2 {
+                                       reg = <4>;
+                                       soc_funnel_in_port1: endpoint {
+                                               slave-mode;
+                                               remote-endpioint =
+                                                       <&stm_out_port>;
+                                       };
+                               };
+                       };
+               };
+
+               etb@10003000 {
+                       compatible = "arm,coresight-tmc", "arm,primecell";
+                       reg = <0 0x10003000 0 0x1000>;
+                       clocks = <&ext_26m>;
+                       clock-names = "apb_pclk";
+                       port {
+                               etb_in: endpoint {
+                                       slave-mode;
+                                       remote-endpoint =
+                                               <&soc_funnel_out_port>;
+                               };
+                       };
+               };
+
+               stm@10006000 {
+                       compatible = "arm,coresight-stm", "arm,primecell";
+                       reg = <0 0x10006000 0 0x1000>,
+                             <0 0x01000000 0 0x180000>;
+                       reg-names = "stm-base", "stm-stimulus-base";
+                       clocks = <&ext_26m>;
+                       clock-names = "apb_pclk";
+                       port {
+                               stm_out_port: endpoint {
+                                       remote-endpoint =
+                                               <&soc_funnel_in_port1>;
+                               };
+                       };
+               };
+
+               funnel@11001000 { /* Cluster0 Funnel */
+                       compatible = "arm,coresight-funnel", "arm,primecell";
+                       reg = <0 0x11001000 0 0x1000>;
+                       clocks = <&ext_26m>;
+                       clock-names = "apb_pclk";
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               port@0 {
+                                       reg = <0>;
+                                       cluster0_funnel_out_port: endpoint {
+                                               remote-endpoint =
+                                                       <&cluster0_etf_in>;
+                                       };
+                               };
+
+                               port@1 {
+                                       reg = <0>;
+                                       cluster0_funnel_in_port0: endpoint {
+                                               slave-mode;
+                                               remote-endpoint = <&etm0_out>;
+                                       };
+                               };
+
+                               port@2 {
+                                       reg = <1>;
+                                       cluster0_funnel_in_port1: endpoint {
+                                               slave-mode;
+                                               remote-endpoint = <&etm1_out>;
+                                       };
+                               };
+
+                               port@3 {
+                                       reg = <2>;
+                                       cluster0_funnel_in_port2: endpoint {
+                                               slave-mode;
+                                               remote-endpoint = <&etm2_out>;
+                                       };
+                               };
+
+                               port@4 {
+                                       reg = <4>;
+                                       cluster0_funnel_in_port3: endpoint {
+                                               slave-mode;
+                                               remote-endpoint = <&etm3_out>;
+                                       };
+                               };
+                       };
+               };
+
+               funnel@11002000 { /* Cluster1 Funnel */
+                       compatible = "arm,coresight-funnel", "arm,primecell";
+                       reg = <0 0x11002000 0 0x1000>;
+                       clocks = <&ext_26m>;
+                       clock-names = "apb_pclk";
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               port@0 {
+                                       reg = <0>;
+                                       cluster1_funnel_out_port: endpoint {
+                                               remote-endpoint =
+                                                       <&cluster1_etf_in>;
+                                       };
+                               };
+
+                               port@1 {
+                                       reg = <0>;
+                                       cluster1_funnel_in_port0: endpoint {
+                                               slave-mode;
+                                               remote-endpoint = <&etm4_out>;
+                                       };
+                               };
+
+                               port@2 {
+                                       reg = <1>;
+                                       cluster1_funnel_in_port1: endpoint {
+                                               slave-mode;
+                                               remote-endpoint = <&etm5_out>;
+                                       };
+                               };
+
+                               port@3 {
+                                       reg = <2>;
+                                       cluster1_funnel_in_port2: endpoint {
+                                               slave-mode;
+                                               remote-endpoint = <&etm6_out>;
+                                       };
+                               };
+
+                               port@4 {
+                                       reg = <3>;
+                                       cluster1_funnel_in_port3: endpoint {
+                                               slave-mode;
+                                               remote-endpoint = <&etm7_out>;
+                                       };
+                               };
+                       };
+               };
+
+               etf@11003000 { /*  ETF on Cluster0 */
+                       compatible = "arm,coresight-tmc", "arm,primecell";
+                       reg = <0 0x11003000 0 0x1000>;
+                       clocks = <&ext_26m>;
+                       clock-names = "apb_pclk";
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               port@0 {
+                                       reg = <0>;
+                                       cluster0_etf_out: endpoint {
+                                               remote-endpoint =
+                                               <&main_funnel_in_port0>;
+                                       };
+                               };
+
+                               port@1 {
+                                       reg = <0>;
+                                       cluster0_etf_in: endpoint {
+                                               slave-mode;
+                                               remote-endpoint =
+                                               <&cluster0_funnel_out_port>;
+                                       };
+                               };
+                       };
+               };
+
+               etf@11004000 { /* ETF on Cluster1 */
+                       compatible = "arm,coresight-tmc", "arm,primecell";
+                       reg = <0 0x11004000 0 0x1000>;
+                       clocks = <&ext_26m>;
+                       clock-names = "apb_pclk";
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               port@0 {
+                                       reg = <0>;
+                                       cluster1_etf_out: endpoint {
+                                               remote-endpoint =
+                                               <&main_funnel_in_port1>;
+                                       };
+                               };
+
+                               port@1 {
+                                       reg = <0>;
+                                       cluster1_etf_in: endpoint {
+                                               slave-mode;
+                                               remote-endpoint =
+                                               <&cluster1_funnel_out_port>;
+                                       };
+                               };
+                       };
+               };
+
+               funnel@11005000 { /* Main Funnel */
+                       compatible = "arm,coresight-funnel", "arm,primecell";
+                       reg = <0 0x11005000 0 0x1000>;
+                       clocks = <&ext_26m>;
+                       clock-names = "apb_pclk";
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               port@0 {
+                                       reg = <0>;
+                                       main_funnel_out_port: endpoint {
+                                               remote-endpoint =
+                                                       <&soc_funnel_in_port0>;
+                                       };
+                               };
+
+                               port@1 {
+                                       reg = <0>;
+                                       main_funnel_in_port0: endpoint {
+                                               slave-mode;
+                                               remote-endpoint =
+                                                       <&cluster0_etf_out>;
+                                       };
+                               };
+
+                               port@2 {
+                                       reg = <1>;
+                                       main_funnel_in_port1: endpoint {
+                                               slave-mode;
+                                               remote-endpoint =
+                                                       <&cluster1_etf_out>;
+                                       };
+                               };
+                       };
+               };
+
+               etm@11440000 {
+                       compatible = "arm,coresight-etm4x", "arm,primecell";
+                       reg = <0 0x11440000 0 0x1000>;
+                       cpu = <&CPU0>;
+                       clocks = <&ext_26m>;
+                       clock-names = "apb_pclk";
+
+                       port {
+                               etm0_out: endpoint {
+                                       remote-endpoint =
+                                               <&cluster0_funnel_in_port0>;
+                               };
+                       };
+               };
+
+               etm@11540000 {
+                       compatible = "arm,coresight-etm4x", "arm,primecell";
+                       reg = <0 0x11540000 0 0x1000>;
+                       cpu = <&CPU1>;
+                       clocks = <&ext_26m>;
+                       clock-names = "apb_pclk";
+
+                       port {
+                               etm1_out: endpoint {
+                                       remote-endpoint =
+                                               <&cluster0_funnel_in_port1>;
+                               };
+                       };
+               };
+
+               etm@11640000 {
+                       compatible = "arm,coresight-etm4x", "arm,primecell";
+                       reg = <0 0x11640000 0 0x1000>;
+                       cpu = <&CPU2>;
+                       clocks = <&ext_26m>;
+                       clock-names = "apb_pclk";
+
+                       port {
+                               etm2_out: endpoint {
+                                       remote-endpoint =
+                                               <&cluster0_funnel_in_port2>;
+                               };
+                       };
+               };
+
+               etm@11740000 {
+                       compatible = "arm,coresight-etm4x", "arm,primecell";
+                       reg = <0 0x11740000 0 0x1000>;
+                       cpu = <&CPU3>;
+                       clocks = <&ext_26m>;
+                       clock-names = "apb_pclk";
+
+                       port {
+                               etm3_out: endpoint {
+                                       remote-endpoint =
+                                               <&cluster0_funnel_in_port3>;
+                               };
+                       };
+               };
+
+               etm@11840000 {
+                       compatible = "arm,coresight-etm4x", "arm,primecell";
+                       reg = <0 0x11840000 0 0x1000>;
+                       cpu = <&CPU4>;
+                       clocks = <&ext_26m>;
+                       clock-names = "apb_pclk";
+
+                       port {
+                               etm4_out: endpoint {
+                                       remote-endpoint =
+                                               <&cluster1_funnel_in_port0>;
+                               };
+                       };
+               };
+
+               etm@11940000 {
+                       compatible = "arm,coresight-etm4x", "arm,primecell";
+                       reg = <0 0x11940000 0 0x1000>;
+                       cpu = <&CPU5>;
+                       clocks = <&ext_26m>;
+                       clock-names = "apb_pclk";
+
+                       port {
+                               etm5_out: endpoint {
+                                       remote-endpoint =
+                                               <&cluster1_funnel_in_port1>;
+                               };
+                       };
+               };
+
+               etm@11a40000 {
+                       compatible = "arm,coresight-etm4x", "arm,primecell";
+                       reg = <0 0x11a40000 0 0x1000>;
+                       cpu = <&CPU6>;
+                       clocks = <&ext_26m>;
+                       clock-names = "apb_pclk";
+
+                       port {
+                               etm6_out: endpoint {
+                                       remote-endpoint =
+                                               <&cluster1_funnel_in_port2>;
+                               };
+                       };
+               };
+
+               etm@11b40000 {
+                       compatible = "arm,coresight-etm4x", "arm,primecell";
+                       reg = <0 0x11b40000 0 0x1000>;
+                       cpu = <&CPU7>;
+                       clocks = <&ext_26m>;
+                       clock-names = "apb_pclk";
+
+                       port {
+                               etm7_out: endpoint {
+                                       remote-endpoint =
+                                               <&cluster1_funnel_in_port3>;
+                               };
+                       };
+               };
+       };
+};
diff --git a/arch/arm64/boot/dts/sprd/sp9860g-1h10.dts b/arch/arm64/boot/dts/sprd/sp9860g-1h10.dts
new file mode 100644 (file)
index 0000000..ae0b28c
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Spreadtrum SP9860g board
+ *
+ * Copyright (C) 2017, Spreadtrum Communications Inc.
+ *
+ * SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+ */
+
+/dts-v1/;
+
+#include "sc9860.dtsi"
+
+/ {
+       model = "Spreadtrum SP9860G 3GFHD Board";
+
+       compatible = "sprd,sp9860g-1h10", "sprd,sc9860";
+
+       aliases {
+               serial0 = &uart0; /* for Bluetooth */
+               serial1 = &uart1; /* UART console */
+               serial2 = &uart2; /* Reserved */
+               serial3 = &uart3; /* for GPS */
+       };
+
+       memory{
+               device_type = "memory";
+               reg = <0x0 0x80000000 0 0x60000000>,
+                     <0x1 0x80000000 0 0x60000000>;
+       };
+
+       chosen {
+               stdout-path = "serial1:115200n8";
+       };
+
+       reserved-memory {
+               #address-cells = <2>;
+               #size-cells = <2>;
+               ranges;
+       };
+};
+
+&uart0 {
+       status = "okay";
+};
+
+&uart1 {
+       status = "okay";
+};
+
+&uart2 {
+       status = "okay";
+};
+
+&uart3 {
+       status = "okay";
+};
diff --git a/arch/arm64/boot/dts/sprd/whale2.dtsi b/arch/arm64/boot/dts/sprd/whale2.dtsi
new file mode 100644 (file)
index 0000000..7c217c5
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Spreadtrum Whale2 platform peripherals
+ *
+ * Copyright (C) 2016, Spreadtrum Communications Inc.
+ *
+ * SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+ */
+
+/ {
+       interrupt-parent = <&gic>;
+       #address-cells = <2>;
+       #size-cells = <2>;
+
+       soc: soc {
+               compatible = "simple-bus";
+               #address-cells = <2>;
+               #size-cells = <2>;
+               ranges;
+
+               ap-apb {
+                       compatible = "simple-bus";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0 0x0 0x70000000 0x10000000>;
+
+                       uart0: serial@0 {
+                               compatible = "sprd,sc9860-uart",
+                                            "sprd,sc9836-uart";
+                               reg = <0x0 0x100>;
+                               interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&ext_26m>;
+                               status = "disabled";
+                       };
+
+                       uart1: serial@100000 {
+                               compatible = "sprd,sc9860-uart",
+                                            "sprd,sc9836-uart";
+                               reg = <0x100000 0x100>;
+                               interrupts = <GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&ext_26m>;
+                               status = "disabled";
+                       };
+
+                       uart2: serial@200000 {
+                               compatible = "sprd,sc9860-uart",
+                                            "sprd,sc9836-uart";
+                               reg = <0x200000 0x100>;
+                               interrupts = <GIC_SPI 4 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&ext_26m>;
+                               status = "disabled";
+                       };
+
+                       uart3: serial@300000 {
+                               compatible = "sprd,sc9860-uart",
+                                            "sprd,sc9836-uart";
+                               reg = <0x300000 0x100>;
+                               interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&ext_26m>;
+                               status = "disabled";
+                       };
+               };
+
+       };
+
+       ext_26m: ext-26m {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <26000000>;
+               clock-output-names = "ext_26m";
+       };
+};
index e164ff6de5fc5e305ec7783845305b60b2bae955..bb900d2bbcfb5e6b9ca88187fc491142f359ed31 100644 (file)
                reg = <0x40000000 0x40000000>;
        };
 
+       sound0 {
+               compatible = "simple-audio-card";
+               simple-audio-card,name = "zx_snd_spdif0";
+
+               simple-audio-card,cpu {
+                       sound-dai = <&spdif0>;
+               };
+
+               simple-audio-card,codec {
+                       sound-dai = <&hdmi>;
+               };
+       };
+};
+
+&emmc {
+       status = "okay";
+};
+
+&hdmi {
+       status = "okay";
+};
+
+&sd1 {
+       status = "okay";
+};
+
+&spdif0 {
+       status = "okay";
 };
 
 &uart0 {
index b850b2cd0adc42aee1e671738ad6b6f40b33bc3d..316dc713268c68f8dcd93afd8c0b8bde27e30ac5 100644 (file)
                clock-output-names = "pll_mac";
        };
 
-       pll_vga: clk-pll-1073m {
-               compatible = "fixed-clock";
-               #clock-cells = <0>;
-               clock-frequency = <1073000000>;
-               clock-output-names = "pll_vga";
-       };
-
        pll_mm0: clk-pll-1188m {
                compatible = "fixed-clock";
                #clock-cells = <0>;
                        status = "disabled";
                };
 
+               sd0: mmc@1110000 {
+                       compatible = "zte,zx296718-dw-mshc";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x01110000 0x1000>;
+                       interrupts = <GIC_SPI 15 IRQ_TYPE_LEVEL_HIGH>;
+                       fifo-depth = <32>;
+                       data-addr = <0x200>;
+                       fifo-watermark-aligned;
+                       bus-width = <4>;
+                       clock-frequency = <50000000>;
+                       clocks = <&topcrm SD0_AHB>, <&topcrm SD0_WCLK>;
+                       clock-names = "biu", "ciu";
+                       num-slots = <1>;
+                       max-frequency = <50000000>;
+                       cap-sdio-irq;
+                       cap-sd-highspeed;
+                       sd-uhs-sdr12;
+                       sd-uhs-sdr25;
+                       sd-uhs-sdr50;
+                       sd-uhs-sdr104;
+                       sd-uhs-ddr50;
+                       status = "disabled";
+               };
+
+               sd1: mmc@1111000 {
+                       compatible = "zte,zx296718-dw-mshc";
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+                       reg = <0x01111000 0x1000>;
+                       interrupts = <GIC_SPI 16 IRQ_TYPE_LEVEL_HIGH>;
+                       fifo-depth = <32>;
+                       data-addr = <0x200>;
+                       fifo-watermark-aligned;
+                       bus-width = <4>;
+                       clock-frequency = <167000000>;
+                       clocks = <&topcrm SD1_AHB>, <&topcrm SD1_WCLK>;
+                       clock-names = "biu", "ciu";
+                       num-slots = <1>;
+                       max-frequency = <167000000>;
+                       cap-sdio-irq;
+                       cap-sd-highspeed;
+                       status = "disabled";
+               };
+
                dma: dma-controller@1460000 {
                        compatible = "zte,zx296702-dma";
                        reg = <0x01460000 0x1000>;
                        #clock-cells = <1>;
                };
 
+               vou: vou@1440000 {
+                       compatible = "zte,zx296718-vou";
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       ranges = <0 0x1440000 0x10000>;
+
+                       dpc: dpc@0 {
+                               compatible = "zte,zx296718-dpc";
+                               reg = <0x0000 0x1000>, <0x1000 0x1000>,
+                                     <0x5000 0x1000>, <0x6000 0x1000>,
+                                     <0xa000 0x1000>;
+                               reg-names = "osd", "timing_ctrl",
+                                           "dtrc", "vou_ctrl",
+                                           "otfppu";
+                               interrupts = <GIC_SPI 81 IRQ_TYPE_LEVEL_HIGH>;
+                               clocks = <&topcrm VOU_ACLK>, <&topcrm VOU_PPU_WCLK>,
+                                        <&topcrm VOU_MAIN_WCLK>, <&topcrm VOU_AUX_WCLK>;
+                               clock-names = "aclk", "ppu_wclk",
+                                             "main_wclk", "aux_wclk";
+                       };
+
+                       hdmi: hdmi@c000 {
+                               compatible = "zte,zx296718-hdmi";
+                               reg = <0xc000 0x4000>;
+                               interrupts = <GIC_SPI 82 IRQ_TYPE_EDGE_RISING>;
+                               clocks = <&topcrm HDMI_OSC_CEC>,
+                                        <&topcrm HDMI_OSC_CLK>,
+                                        <&topcrm HDMI_XCLK>;
+                               clock-names = "osc_cec", "osc_clk", "xclk";
+                               #sound-dai-cells = <0>;
+                               status = "disabled";
+                       };
+
+                       tvenc: tvenc@2000 {
+                               compatible = "zte,zx296718-tvenc";
+                               reg = <0x2000 0x1000>;
+                               zte,tvenc-power-control = <&sysctrl 0x170 0x10>;
+                               status = "disabled";
+                       };
+               };
+
                topcrm: clock-controller@1461000 {
                        compatible = "zte,zx296718-topcrm";
                        reg = <0x01461000 0x1000>;
                        reg = <0x1463000 0x1000>;
                };
 
+               emmc: mmc@1470000{
+                       compatible = "zte,zx296718-dw-mshc";
+                       reg = <0x01470000 0x1000>;
+                       interrupts = <GIC_SPI 23 IRQ_TYPE_LEVEL_HIGH>;
+                       zte,aon-syscon = <&aon_sysctrl>;
+                       bus-width = <8>;
+                       fifo-depth = <128>;
+                       data-addr = <0x200>;
+                       fifo-watermark-aligned;
+                       clock-frequency = <167000000>;
+                       clocks = <&topcrm EMMC_NAND_AHB>, <&topcrm EMMC_WCLK>;
+                       clock-names = "biu", "ciu";
+                       max-frequency = <167000000>;
+                       cap-mmc-highspeed;
+                       mmc-ddr-1_8v;
+                       mmc-hs200-1_8v;
+                       non-removable;
+                       disable-wp;
+                       status = "disabled";
+               };
+
                audiocrm: clock-controller@1480000 {
                        compatible = "zte,zx296718-audiocrm";
                        reg = <0x01480000 0x1000>;
                        #clock-cells = <1>;
                };
+
+               spdif0: spdif@1488000 {
+                       compatible = "zte,zx296702-spdif";
+                       reg = <0x1488000 0x1000>;
+                       clocks = <&audiocrm AUDIO_SPDIF0_WCLK>;
+                       clock-names = "tx";
+                       interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
+                       #sound-dai-cells = <0>;
+                       dmas = <&dma 30>;
+                       dma-names = "tx";
+                       status = "disabled";
+               };
        };
 };
index 927ee18bbdf2fd2ab4494fa5c62dd6821c456452..65cdd878cfbd603b323a08006872f5de90e90aee 100644 (file)
@@ -30,7 +30,6 @@ CONFIG_PROFILING=y
 CONFIG_JUMP_LABEL=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
 # CONFIG_IOSCHED_DEADLINE is not set
 CONFIG_ARCH_SUNXI=y
 CONFIG_ARCH_ALPINE=y
@@ -62,16 +61,15 @@ CONFIG_ARCH_XGENE=y
 CONFIG_ARCH_ZX=y
 CONFIG_ARCH_ZYNQMP=y
 CONFIG_PCI=y
-CONFIG_PCI_MSI=y
 CONFIG_PCI_IOV=y
-CONFIG_PCI_AARDVARK=y
-CONFIG_PCIE_RCAR=y
-CONFIG_PCI_HOST_GENERIC=y
-CONFIG_PCI_XGENE=y
 CONFIG_PCI_LAYERSCAPE=y
 CONFIG_PCI_HISI=y
 CONFIG_PCIE_QCOM=y
 CONFIG_PCIE_ARMADA_8K=y
+CONFIG_PCI_AARDVARK=y
+CONFIG_PCIE_RCAR=y
+CONFIG_PCI_HOST_GENERIC=y
+CONFIG_PCI_XGENE=y
 CONFIG_ARM64_VA_BITS_48=y
 CONFIG_SCHED_MC=y
 CONFIG_NUMA=y
@@ -80,12 +78,11 @@ CONFIG_KSM=y
 CONFIG_TRANSPARENT_HUGEPAGE=y
 CONFIG_CMA=y
 CONFIG_SECCOMP=y
-CONFIG_XEN=y
 CONFIG_KEXEC=y
 CONFIG_CRASH_DUMP=y
+CONFIG_XEN=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_COMPAT=y
-CONFIG_CPU_IDLE=y
 CONFIG_HIBERNATION=y
 CONFIG_ARM_CPUIDLE=y
 CONFIG_CPU_FREQ=y
@@ -155,8 +152,8 @@ CONFIG_MTD_SPI_NOR=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_NBD=m
 CONFIG_VIRTIO_BLK=y
-CONFIG_EEPROM_AT25=m
 CONFIG_SRAM=y
+CONFIG_EEPROM_AT25=m
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
 CONFIG_SCSI_SAS_ATA=y
@@ -168,8 +165,8 @@ CONFIG_AHCI_CEVA=y
 CONFIG_AHCI_MVEBU=y
 CONFIG_AHCI_XGENE=y
 CONFIG_AHCI_QORIQ=y
-CONFIG_SATA_RCAR=y
 CONFIG_SATA_SIL24=y
+CONFIG_SATA_RCAR=y
 CONFIG_PATA_PLATFORM=y
 CONFIG_PATA_OF_PLATFORM=y
 CONFIG_NETDEVICES=y
@@ -186,16 +183,17 @@ CONFIG_HNS_ENET=y
 CONFIG_E1000E=y
 CONFIG_IGB=y
 CONFIG_IGBVF=y
+CONFIG_MVNETA=y
+CONFIG_MVPP2=y
 CONFIG_SKY2=y
 CONFIG_RAVB=y
 CONFIG_SMC91X=y
 CONFIG_SMSC911X=y
 CONFIG_STMMAC_ETH=m
-CONFIG_REALTEK_PHY=m
+CONFIG_MDIO_BUS_MUX_MMIOREG=y
 CONFIG_MESON_GXL_PHY=m
 CONFIG_MICREL_PHY=y
-CONFIG_MDIO_BUS_MUX=y
-CONFIG_MDIO_BUS_MUX_MMIOREG=y
+CONFIG_REALTEK_PHY=m
 CONFIG_USB_PEGASUS=m
 CONFIG_USB_RTL8150=m
 CONFIG_USB_RTL8152=m
@@ -228,14 +226,14 @@ CONFIG_SERIAL_8250_UNIPHIER=y
 CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+CONFIG_SERIAL_MESON=y
+CONFIG_SERIAL_MESON_CONSOLE=y
 CONFIG_SERIAL_SAMSUNG=y
 CONFIG_SERIAL_SAMSUNG_CONSOLE=y
 CONFIG_SERIAL_TEGRA=y
 CONFIG_SERIAL_SH_SCI=y
 CONFIG_SERIAL_SH_SCI_NR_UARTS=11
 CONFIG_SERIAL_SH_SCI_CONSOLE=y
-CONFIG_SERIAL_MESON=y
-CONFIG_SERIAL_MESON_CONSOLE=y
 CONFIG_SERIAL_MSM=y
 CONFIG_SERIAL_MSM_CONSOLE=y
 CONFIG_SERIAL_XILINX_PS_UART=y
@@ -250,21 +248,23 @@ CONFIG_I2C_DESIGNWARE_PLATFORM=y
 CONFIG_I2C_IMX=y
 CONFIG_I2C_MESON=y
 CONFIG_I2C_MV64XXX=y
+CONFIG_I2C_PXA=y
 CONFIG_I2C_QUP=y
 CONFIG_I2C_RK3X=y
+CONFIG_I2C_SH_MOBILE=y
 CONFIG_I2C_TEGRA=y
 CONFIG_I2C_UNIPHIER_F=y
 CONFIG_I2C_RCAR=y
 CONFIG_I2C_CROS_EC_TUNNEL=y
 CONFIG_SPI=y
-CONFIG_SPI_MESON_SPIFC=m
 CONFIG_SPI_BCM2835=m
 CONFIG_SPI_BCM2835AUX=m
+CONFIG_SPI_MESON_SPIFC=m
 CONFIG_SPI_ORION=y
 CONFIG_SPI_PL022=y
 CONFIG_SPI_QUP=y
-CONFIG_SPI_SPIDEV=m
 CONFIG_SPI_S3C64XX=y
+CONFIG_SPI_SPIDEV=m
 CONFIG_SPMI=y
 CONFIG_PINCTRL_SINGLE=y
 CONFIG_PINCTRL_MAX77620=y
@@ -282,32 +282,30 @@ CONFIG_GPIO_PCA953X=y
 CONFIG_GPIO_PCA953X_IRQ=y
 CONFIG_GPIO_MAX77620=y
 CONFIG_POWER_RESET_MSM=y
-CONFIG_BATTERY_BQ27XXX=y
 CONFIG_POWER_RESET_XGENE=y
 CONFIG_POWER_RESET_SYSCON=y
+CONFIG_BATTERY_BQ27XXX=y
+CONFIG_SENSORS_ARM_SCPI=y
 CONFIG_SENSORS_LM90=m
 CONFIG_SENSORS_INA2XX=m
-CONFIG_SENSORS_ARM_SCPI=y
-CONFIG_THERMAL=y
-CONFIG_THERMAL_EMULATION=y
 CONFIG_THERMAL_GOV_POWER_ALLOCATOR=y
 CONFIG_CPU_THERMAL=y
-CONFIG_BCM2835_THERMAL=y
+CONFIG_THERMAL_EMULATION=y
 CONFIG_EXYNOS_THERMAL=y
 CONFIG_WATCHDOG=y
-CONFIG_BCM2835_WDT=y
-CONFIG_RENESAS_WDT=y
 CONFIG_S3C2410_WATCHDOG=y
 CONFIG_MESON_GXBB_WATCHDOG=m
 CONFIG_MESON_WATCHDOG=m
+CONFIG_RENESAS_WDT=y
+CONFIG_BCM2835_WDT=y
+CONFIG_MFD_CROS_EC=y
+CONFIG_MFD_CROS_EC_I2C=y
+CONFIG_MFD_EXYNOS_LPASS=m
+CONFIG_MFD_HI655X_PMIC=y
 CONFIG_MFD_MAX77620=y
-CONFIG_MFD_RK808=y
 CONFIG_MFD_SPMI_PMIC=y
+CONFIG_MFD_RK808=y
 CONFIG_MFD_SEC_CORE=y
-CONFIG_MFD_HI655X_PMIC=y
-CONFIG_REGULATOR=y
-CONFIG_MFD_CROS_EC=y
-CONFIG_MFD_CROS_EC_I2C=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_GPIO=y
 CONFIG_REGULATOR_HI655X=y
@@ -325,18 +323,27 @@ CONFIG_MEDIA_CONTROLLER=y
 CONFIG_VIDEO_V4L2_SUBDEV_API=y
 # CONFIG_DVB_NET is not set
 CONFIG_V4L_MEM2MEM_DRIVERS=y
+CONFIG_VIDEO_SAMSUNG_S5P_JPEG=m
+CONFIG_VIDEO_SAMSUNG_S5P_MFC=m
+CONFIG_VIDEO_SAMSUNG_EXYNOS_GSC=m
 CONFIG_VIDEO_RENESAS_FCP=m
 CONFIG_VIDEO_RENESAS_VSP1=m
 CONFIG_DRM=m
 CONFIG_DRM_NOUVEAU=m
+CONFIG_DRM_EXYNOS=m
+CONFIG_DRM_EXYNOS5433_DECON=y
+CONFIG_DRM_EXYNOS7_DECON=y
+CONFIG_DRM_EXYNOS_DSI=y
+# CONFIG_DRM_EXYNOS_DP is not set
+CONFIG_DRM_EXYNOS_HDMI=y
+CONFIG_DRM_EXYNOS_MIC=y
 CONFIG_DRM_RCAR_DU=m
-CONFIG_DRM_RCAR_HDMI=y
 CONFIG_DRM_RCAR_LVDS=y
 CONFIG_DRM_RCAR_VSP=y
 CONFIG_DRM_TEGRA=m
-CONFIG_DRM_VC4=m
 CONFIG_DRM_PANEL_SIMPLE=m
 CONFIG_DRM_I2C_ADV7511=m
+CONFIG_DRM_VC4=m
 CONFIG_DRM_HISI_KIRIN=m
 CONFIG_DRM_MESON=m
 CONFIG_FB=y
@@ -351,39 +358,37 @@ CONFIG_SOUND=y
 CONFIG_SND=y
 CONFIG_SND_SOC=y
 CONFIG_SND_BCM2835_SOC_I2S=m
-CONFIG_SND_SOC_RCAR=y
 CONFIG_SND_SOC_SAMSUNG=y
+CONFIG_SND_SOC_RCAR=y
 CONFIG_SND_SOC_AK4613=y
 CONFIG_USB=y
 CONFIG_USB_OTG=y
 CONFIG_USB_XHCI_HCD=y
-CONFIG_USB_XHCI_PLATFORM=y
-CONFIG_USB_XHCI_RCAR=y
-CONFIG_USB_EHCI_EXYNOS=y
 CONFIG_USB_XHCI_TEGRA=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_MSM=y
+CONFIG_USB_EHCI_EXYNOS=y
 CONFIG_USB_EHCI_HCD_PLATFORM=y
-CONFIG_USB_OHCI_EXYNOS=y
 CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_EXYNOS=y
 CONFIG_USB_OHCI_HCD_PLATFORM=y
 CONFIG_USB_RENESAS_USBHS=m
 CONFIG_USB_STORAGE=y
-CONFIG_USB_DWC2=y
 CONFIG_USB_DWC3=y
+CONFIG_USB_DWC2=y
 CONFIG_USB_CHIPIDEA=y
 CONFIG_USB_CHIPIDEA_UDC=y
 CONFIG_USB_CHIPIDEA_HOST=y
 CONFIG_USB_ISP1760=y
 CONFIG_USB_HSIC_USB3503=y
 CONFIG_USB_MSM_OTG=y
+CONFIG_USB_QCOM_8X16_PHY=y
 CONFIG_USB_ULPI=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_RENESAS_USBHS_UDC=m
 CONFIG_MMC=y
 CONFIG_MMC_BLOCK_MINORS=32
 CONFIG_MMC_ARMMMCI=y
-CONFIG_MMC_MESON_GX=y
 CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_ACPI=y
 CONFIG_MMC_SDHCI_PLTFM=y
@@ -391,6 +396,7 @@ CONFIG_MMC_SDHCI_OF_ARASAN=y
 CONFIG_MMC_SDHCI_OF_ESDHC=y
 CONFIG_MMC_SDHCI_CADENCE=y
 CONFIG_MMC_SDHCI_TEGRA=y
+CONFIG_MMC_MESON_GX=y
 CONFIG_MMC_SDHCI_MSM=y
 CONFIG_MMC_SPI=y
 CONFIG_MMC_SDHI=y
@@ -399,28 +405,31 @@ CONFIG_MMC_DW_EXYNOS=y
 CONFIG_MMC_DW_K3=y
 CONFIG_MMC_DW_ROCKCHIP=y
 CONFIG_MMC_SUNXI=y
+CONFIG_MMC_BCM2835=y
+CONFIG_MMC_SDHCI_XENON=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_GPIO=y
+CONFIG_LEDS_PWM=y
 CONFIG_LEDS_SYSCON=y
-CONFIG_LEDS_TRIGGERS=y
 CONFIG_LEDS_TRIGGER_HEARTBEAT=y
 CONFIG_LEDS_TRIGGER_CPU=y
+CONFIG_LEDS_TRIGGER_DEFAULT_ON=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_MAX77686=y
+CONFIG_RTC_DRV_RK808=m
 CONFIG_RTC_DRV_S5M=y
 CONFIG_RTC_DRV_DS3232=y
 CONFIG_RTC_DRV_EFI=y
+CONFIG_RTC_DRV_S3C=y
 CONFIG_RTC_DRV_PL031=y
 CONFIG_RTC_DRV_SUN6I=y
-CONFIG_RTC_DRV_RK808=m
 CONFIG_RTC_DRV_TEGRA=y
 CONFIG_RTC_DRV_XGENE=y
-CONFIG_RTC_DRV_S3C=y
 CONFIG_DMADEVICES=y
+CONFIG_DMA_BCM2835=m
 CONFIG_MV_XOR_V2=y
 CONFIG_PL330_DMA=y
-CONFIG_DMA_BCM2835=m
 CONFIG_TEGRA20_APB_DMA=y
 CONFIG_QCOM_BAM_DMA=y
 CONFIG_QCOM_HIDMA_MGMT=y
@@ -433,51 +442,53 @@ CONFIG_VIRTIO_BALLOON=y
 CONFIG_VIRTIO_MMIO=y
 CONFIG_XEN_GNTDEV=y
 CONFIG_XEN_GRANT_DEV_ALLOC=y
+CONFIG_COMMON_CLK_RK808=y
 CONFIG_COMMON_CLK_SCPI=y
 CONFIG_COMMON_CLK_CS2000_CP=y
 CONFIG_COMMON_CLK_S2MPS11=y
-CONFIG_COMMON_CLK_PWM=y
-CONFIG_COMMON_CLK_RK808=y
 CONFIG_CLK_QORIQ=y
+CONFIG_COMMON_CLK_PWM=y
 CONFIG_COMMON_CLK_QCOM=y
+CONFIG_QCOM_CLK_SMD_RPM=y
 CONFIG_MSM_GCC_8916=y
 CONFIG_MSM_GCC_8994=y
 CONFIG_MSM_MMCC_8996=y
 CONFIG_HWSPINLOCK_QCOM=y
-CONFIG_MAILBOX=y
 CONFIG_ARM_MHU=y
 CONFIG_PLATFORM_MHU=y
 CONFIG_BCM2835_MBOX=y
 CONFIG_HI6220_MBOX=y
 CONFIG_ARM_SMMU=y
 CONFIG_ARM_SMMU_V3=y
+CONFIG_RPMSG_QCOM_SMD=y
 CONFIG_RASPBERRYPI_POWER=y
 CONFIG_QCOM_SMEM=y
-CONFIG_QCOM_SMD=y
 CONFIG_QCOM_SMD_RPM=y
+CONFIG_QCOM_SMP2P=y
+CONFIG_QCOM_SMSM=y
 CONFIG_ROCKCHIP_PM_DOMAINS=y
 CONFIG_ARCH_TEGRA_132_SOC=y
 CONFIG_ARCH_TEGRA_210_SOC=y
 CONFIG_ARCH_TEGRA_186_SOC=y
 CONFIG_EXTCON_USB_GPIO=y
+CONFIG_IIO=y
+CONFIG_EXYNOS_ADC=y
 CONFIG_PWM=y
 CONFIG_PWM_BCM2835=m
+CONFIG_PWM_MESON=m
 CONFIG_PWM_ROCKCHIP=y
+CONFIG_PWM_SAMSUNG=y
 CONFIG_PWM_TEGRA=m
-CONFIG_PWM_MESON=m
-CONFIG_COMMON_RESET_HI6220=y
 CONFIG_PHY_RCAR_GEN3_USB2=y
 CONFIG_PHY_HI6220_USB=y
+CONFIG_PHY_SUN4I_USB=y
 CONFIG_PHY_ROCKCHIP_INNO_USB2=y
 CONFIG_PHY_ROCKCHIP_EMMC=y
 CONFIG_PHY_XGENE=y
 CONFIG_PHY_TEGRA_XUSB=y
 CONFIG_ARM_SCPI_PROTOCOL=y
-CONFIG_ACPI=y
-CONFIG_IIO=y
-CONFIG_EXYNOS_ADC=y
-CONFIG_PWM_SAMSUNG=y
 CONFIG_RASPBERRYPI_FIRMWARE=y
+CONFIG_ACPI=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
@@ -491,7 +502,6 @@ CONFIG_FUSE_FS=m
 CONFIG_CUSE=m
 CONFIG_OVERLAY_FS=m
 CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
 CONFIG_HUGETLBFS=y
 CONFIG_CONFIGFS_FS=y
 CONFIG_EFIVAR_FS=y
@@ -525,4 +535,3 @@ CONFIG_CRYPTO_SHA2_ARM64_CE=y
 CONFIG_CRYPTO_GHASH_ARM64_CE=y
 CONFIG_CRYPTO_AES_ARM64_CE_CCM=y
 CONFIG_CRYPTO_AES_ARM64_CE_BLK=y
-# CONFIG_CRYPTO_AES_ARM64_NEON_BLK is not set
index a12f1afc95a391b182b14e33af2f71b905ae6e5c..a7a97a608033570bffe388a6d2f60d25c15d5f4c 100644 (file)
@@ -29,6 +29,7 @@ generic-y += rwsem.h
 generic-y += segment.h
 generic-y += sembuf.h
 generic-y += serial.h
+generic-y += set_memory.h
 generic-y += shmbuf.h
 generic-y += simd.h
 generic-y += sizes.h
index df411f3e083ce7074daedf65c8bb3ed4aed4dc31..ecd9788cd29881074dd04bb9708eddef286677a6 100644 (file)
@@ -62,4 +62,13 @@ alternative_if ARM64_ALT_PAN_NOT_UAO
 alternative_else_nop_endif
        .endm
 
+/*
+ * Remove the address tag from a virtual address, if present.
+ */
+       .macro  clear_address_tag, dst, addr
+       tst     \addr, #(1 << 55)
+       bic     \dst, \addr, #(0xff << 56)
+       csel    \dst, \dst, \addr, eq
+       .endm
+
 #endif
index f819fdcff1accf694cc0ec7428096fe41aef7f89..f5a2d09afb3841bd5ac7d40764ef48b2e108de0d 100644 (file)
@@ -264,7 +264,6 @@ __LL_SC_PREFIX(__cmpxchg_case_##name(volatile void *ptr,            \
        "       st" #rel "xr" #sz "\t%w[tmp], %" #w "[new], %[v]\n"     \
        "       cbnz    %w[tmp], 1b\n"                                  \
        "       " #mb "\n"                                              \
-       "       mov     %" #w "[oldval], %" #w "[old]\n"                \
        "2:"                                                            \
        : [tmp] "=&r" (tmp), [oldval] "=&r" (oldval),                   \
          [v] "+Q" (*(unsigned long *)ptr)                              \
index 7457ce082b5ff06ad6cde7a7935f9d815e2bd256..99fa69c9c3cf3ebf080c7443fb16ac6c11cf234a 100644 (file)
@@ -322,7 +322,7 @@ static inline void atomic64_and(long i, atomic64_t *v)
 #define ATOMIC64_FETCH_OP_AND(name, mb, cl...)                         \
 static inline long atomic64_fetch_and##name(long i, atomic64_t *v)     \
 {                                                                      \
-       register long x0 asm ("w0") = i;                                \
+       register long x0 asm ("x0") = i;                                \
        register atomic64_t *x1 asm ("x1") = v;                         \
                                                                        \
        asm volatile(ARM64_LSE_ATOMIC_INSN(                             \
@@ -394,7 +394,7 @@ ATOMIC64_OP_SUB_RETURN(        , al, "memory")
 #define ATOMIC64_FETCH_OP_SUB(name, mb, cl...)                         \
 static inline long atomic64_fetch_sub##name(long i, atomic64_t *v)     \
 {                                                                      \
-       register long x0 asm ("w0") = i;                                \
+       register long x0 asm ("x0") = i;                                \
        register atomic64_t *x1 asm ("x1") = v;                         \
                                                                        \
        asm volatile(ARM64_LSE_ATOMIC_INSN(                             \
index 4e0497f581a05ea791564badc73ffa7a1f4a0699..0fe7e43b7fbc26bf2f6f2a47354a21943ae56ab9 100644 (file)
 #define __smp_rmb()    dmb(ishld)
 #define __smp_wmb()    dmb(ishst)
 
-#define __smp_store_release(p, v)                                              \
+#define __smp_store_release(p, v)                                      \
 do {                                                                   \
+       union { typeof(*p) __val; char __c[1]; } __u =                  \
+               { .__val = (__force typeof(*p)) (v) };                  \
        compiletime_assert_atomic_type(*p);                             \
        switch (sizeof(*p)) {                                           \
        case 1:                                                         \
                asm volatile ("stlrb %w1, %0"                           \
-                               : "=Q" (*p) : "r" (v) : "memory");      \
+                               : "=Q" (*p)                             \
+                               : "r" (*(__u8 *)__u.__c)                \
+                               : "memory");                            \
                break;                                                  \
        case 2:                                                         \
                asm volatile ("stlrh %w1, %0"                           \
-                               : "=Q" (*p) : "r" (v) : "memory");      \
+                               : "=Q" (*p)                             \
+                               : "r" (*(__u16 *)__u.__c)               \
+                               : "memory");                            \
                break;                                                  \
        case 4:                                                         \
                asm volatile ("stlr %w1, %0"                            \
-                               : "=Q" (*p) : "r" (v) : "memory");      \
+                               : "=Q" (*p)                             \
+                               : "r" (*(__u32 *)__u.__c)               \
+                               : "memory");                            \
                break;                                                  \
        case 8:                                                         \
                asm volatile ("stlr %1, %0"                             \
-                               : "=Q" (*p) : "r" (v) : "memory");      \
+                               : "=Q" (*p)                             \
+                               : "r" (*(__u64 *)__u.__c)               \
+                               : "memory");                            \
                break;                                                  \
        }                                                               \
 } while (0)
index 728f933cef8c90daa98209fb4431fdb265f66ce1..d74a284abdc2f1f39f6b275a7e0818db2c6ae193 100644 (file)
@@ -150,10 +150,6 @@ static inline void flush_cache_vunmap(unsigned long start, unsigned long end)
 {
 }
 
-int set_memory_ro(unsigned long addr, int numpages);
-int set_memory_rw(unsigned long addr, int numpages);
-int set_memory_x(unsigned long addr, int numpages);
-int set_memory_nx(unsigned long addr, int numpages);
 int set_memory_valid(unsigned long addr, unsigned long size, int enable);
 
 #endif
index 91b26d26af8a5f961ed4d8905daffc11be5d72fa..ae852add053d835cdeb98ede5458419dd2958c6a 100644 (file)
@@ -46,7 +46,7 @@ static inline unsigned long __xchg_case_##name(unsigned long x,               \
        "       swp" #acq_lse #rel #sz "\t%" #w "3, %" #w "0, %2\n"     \
                __nops(3)                                               \
        "       " #nop_lse)                                             \
-       : "=&r" (ret), "=&r" (tmp), "+Q" (*(u8 *)ptr)                   \
+       : "=&r" (ret), "=&r" (tmp), "+Q" (*(unsigned long *)ptr)        \
        : "r" (x)                                                       \
        : cl);                                                          \
                                                                        \
index e7f84a7b44658d2f93d642e06e013300693d6a82..428ee1f2468c55959d52cf1cffde922399387b9f 100644 (file)
@@ -115,6 +115,7 @@ struct arm64_cpu_capabilities {
 
 extern DECLARE_BITMAP(cpu_hwcaps, ARM64_NCAPS);
 extern struct static_key_false cpu_hwcap_keys[ARM64_NCAPS];
+extern struct static_key_false arm64_const_caps_ready;
 
 bool this_cpu_has_cap(unsigned int cap);
 
@@ -124,7 +125,7 @@ static inline bool cpu_have_feature(unsigned int num)
 }
 
 /* System capability check for constant caps */
-static inline bool cpus_have_const_cap(int num)
+static inline bool __cpus_have_const_cap(int num)
 {
        if (num >= ARM64_NCAPS)
                return false;
@@ -138,6 +139,14 @@ static inline bool cpus_have_cap(unsigned int num)
        return test_bit(num, cpu_hwcaps);
 }
 
+static inline bool cpus_have_const_cap(int num)
+{
+       if (static_branch_likely(&arm64_const_caps_ready))
+               return __cpus_have_const_cap(num);
+       else
+               return cpus_have_cap(num);
+}
+
 static inline void cpus_set_cap(unsigned int num)
 {
        if (num >= ARM64_NCAPS) {
@@ -145,7 +154,6 @@ static inline void cpus_set_cap(unsigned int num)
                        num, ARM64_NCAPS);
        } else {
                __set_bit(num, cpu_hwcaps);
-               static_branch_enable(&cpu_hwcap_keys[num]);
        }
 }
 
index 0c00c87bb9dd0cf94b4145ad5c2ef1328796c085..35b2e50f17fbfedc220f50c5162d42cec73160b5 100644 (file)
@@ -172,6 +172,16 @@ extern void __iomem *ioremap_cache(phys_addr_t phys_addr, size_t size);
 #define ioremap_wt(addr, size)         __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRE))
 #define iounmap                                __iounmap
 
+/*
+ * PCI configuration space mapping function.
+ *
+ * The PCI specification disallows posted write configuration transactions.
+ * Add an arch specific pci_remap_cfgspace() definition that is implemented
+ * through nGnRnE device memory attribute as recommended by the ARM v8
+ * Architecture reference manual Issue A.k B2.8.2 "Device memory".
+ */
+#define pci_remap_cfgspace(addr, size) __ioremap((addr), (size), __pgprot(PROT_DEVICE_nGnRnE))
+
 /*
  * io{read,write}{16,32,64}be() macros
  */
index f5ea0ba70f077479ea9b2f4b1cb2fd077e9e20e3..fe39e6841326f01c9ae2d933b8048459c2e8ef6e 100644 (file)
@@ -240,6 +240,12 @@ static inline u8 kvm_vcpu_trap_get_fault_type(const struct kvm_vcpu *vcpu)
        return kvm_vcpu_get_hsr(vcpu) & ESR_ELx_FSC_TYPE;
 }
 
+static inline int kvm_vcpu_sys_get_rt(struct kvm_vcpu *vcpu)
+{
+       u32 esr = kvm_vcpu_get_hsr(vcpu);
+       return (esr & ESR_ELx_SYS64_ISS_RT_MASK) >> ESR_ELx_SYS64_ISS_RT_SHIFT;
+}
+
 static inline unsigned long kvm_vcpu_get_mpidr_aff(struct kvm_vcpu *vcpu)
 {
        return vcpu_sys_reg(vcpu, MPIDR_EL1) & MPIDR_HWID_BITMASK;
index 5e19165c5fa8b86002f0308812a0c49199a91b44..1f252a95bc02979cc8c6f01425e26e44f34c1990 100644 (file)
@@ -24,6 +24,7 @@
 
 #include <linux/types.h>
 #include <linux/kvm_types.h>
+#include <asm/cpufeature.h>
 #include <asm/kvm.h>
 #include <asm/kvm_asm.h>
 #include <asm/kvm_mmio.h>
@@ -355,9 +356,12 @@ static inline void __cpu_init_hyp_mode(phys_addr_t pgd_ptr,
                                       unsigned long vector_ptr)
 {
        /*
-        * Call initialization code, and switch to the full blown
-        * HYP code.
+        * Call initialization code, and switch to the full blown HYP code.
+        * If the cpucaps haven't been finalized yet, something has gone very
+        * wrong, and hyp will crash and burn when it uses any
+        * cpus_have_const_cap() wrapper.
         */
+       BUG_ON(!static_branch_likely(&arm64_const_caps_ready));
        __kvm_call_hyp((void *)pgd_ptr, hyp_stack_ptr, vector_ptr);
 }
 
index b9a7ba9ca44c42aef55bf77f8c0df533b9a0ab3b..1fc19744ffe995f01f85a7cbc95c32410f763e94 100644 (file)
@@ -22,6 +22,8 @@
  */
 #define PCI_DMA_BUS_IS_PHYS    (0)
 
+#define ARCH_GENERIC_PCI_MMAP_RESOURCE 1
+
 extern int isa_dma_bridge_buggy;
 
 #ifdef CONFIG_PCI
index ba497172610dbcda77d638a874c8e62c6ad04da5..7b8a04789cef69e161f3956ce42a7d608884698e 100644 (file)
@@ -69,20 +69,21 @@ static inline void set_fs(mm_segment_t fs)
  */
 #define __range_ok(addr, size)                                         \
 ({                                                                     \
+       unsigned long __addr = (unsigned long __force)(addr);           \
        unsigned long flag, roksum;                                     \
        __chk_user_ptr(addr);                                           \
        asm("adds %1, %1, %3; ccmp %1, %4, #2, cc; cset %0, ls"         \
                : "=&r" (flag), "=&r" (roksum)                          \
-               : "1" (addr), "Ir" (size),                              \
+               : "1" (__addr), "Ir" (size),                            \
                  "r" (current_thread_info()->addr_limit)               \
                : "cc");                                                \
        flag;                                                           \
 })
 
 /*
- * When dealing with data aborts or instruction traps we may end up with
- * a tagged userland pointer. Clear the tag to get a sane pointer to pass
- * on to access_ok(), for instance.
+ * When dealing with data aborts, watchpoints, or instruction traps we may end
+ * up with a tagged userland pointer. Clear the tag to get a sane pointer to
+ * pass on to access_ok(), for instance.
  */
 #define untagged_addr(addr)            sign_extend64(addr, 55)
 
@@ -230,7 +231,7 @@ do {                                                                        \
                               (err), ARM64_HAS_UAO);                   \
                break;                                                  \
        case 8:                                                         \
-               __get_user_asm("ldr", "ldtr", "%",  __gu_val, (ptr),    \
+               __get_user_asm("ldr", "ldtr", "%x",  __gu_val, (ptr),   \
                               (err), ARM64_HAS_UAO);                   \
                break;                                                  \
        default:                                                        \
@@ -297,7 +298,7 @@ do {                                                                        \
                               (err), ARM64_HAS_UAO);                   \
                break;                                                  \
        case 8:                                                         \
-               __put_user_asm("str", "sttr", "%", __pu_val, (ptr),     \
+               __put_user_asm("str", "sttr", "%x", __pu_val, (ptr),    \
                               (err), ARM64_HAS_UAO);                   \
                break;                                                  \
        default:                                                        \
index 825b0fe51c2b41643dd38e05dd52f4fe2c48707e..13a97aa2285f7418d18f1396f03bf6281b580a0f 100644 (file)
@@ -2,21 +2,3 @@
 include include/uapi/asm-generic/Kbuild.asm
 
 generic-y += kvm_para.h
-
-header-y += auxvec.h
-header-y += bitsperlong.h
-header-y += byteorder.h
-header-y += fcntl.h
-header-y += hwcap.h
-header-y += kvm_para.h
-header-y += perf_regs.h
-header-y += param.h
-header-y += ptrace.h
-header-y += setup.h
-header-y += sigcontext.h
-header-y += siginfo.h
-header-y += signal.h
-header-y += stat.h
-header-y += statfs.h
-header-y += ucontext.h
-header-y += unistd.h
index 869ee480deed10e8b3fa4f5470ced0548fc748db..70eea2ecc6631cab3d718c3958cd0513a7f7e6a3 100644 (file)
@@ -216,13 +216,17 @@ struct kvm_arch_memory_slot {
 #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
 #define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6
 #define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO  7
+#define KVM_DEV_ARM_VGIC_GRP_ITS_REGS 8
 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT 10
 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \
                        (0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)
 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff
 #define VGIC_LEVEL_INFO_LINE_LEVEL     0
 
-#define   KVM_DEV_ARM_VGIC_CTRL_INIT   0
+#define   KVM_DEV_ARM_VGIC_CTRL_INIT           0
+#define   KVM_DEV_ARM_ITS_SAVE_TABLES           1
+#define   KVM_DEV_ARM_ITS_RESTORE_TABLES        2
+#define   KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES 3
 
 /* Device Control API on vcpu fd */
 #define KVM_ARM_VCPU_PMU_V3_CTRL       0
index 657977e77ec8fa49e55fc9cacc1415db81a7cc2d..f0e6d717885b1fcf3b22f64c10c38f19c25f809d 100644 (file)
@@ -306,7 +306,8 @@ do {                                                                \
        _ASM_EXTABLE(0b, 4b)                                    \
        _ASM_EXTABLE(1b, 4b)                                    \
        : "=&r" (res), "+r" (data), "=&r" (temp), "=&r" (temp2) \
-       : "r" (addr), "i" (-EAGAIN), "i" (-EFAULT),             \
+       : "r" ((unsigned long)addr), "i" (-EAGAIN),             \
+         "i" (-EFAULT),                                        \
          "i" (__SWP_LL_SC_LOOPS)                               \
        : "memory");                                            \
        uaccess_disable();                                      \
index 94b8f7fc33100f85db825a372bf36d6f597934ac..817ce3365e200dfb5f7ff205dadabe72c3490e43 100644 (file)
@@ -985,8 +985,16 @@ void update_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
  */
 void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
 {
-       for (; caps->matches; caps++)
-               if (caps->enable && cpus_have_cap(caps->capability))
+       for (; caps->matches; caps++) {
+               unsigned int num = caps->capability;
+
+               if (!cpus_have_cap(num))
+                       continue;
+
+               /* Ensure cpus_have_const_cap(num) works */
+               static_branch_enable(&cpu_hwcap_keys[num]);
+
+               if (caps->enable) {
                        /*
                         * Use stop_machine() as it schedules the work allowing
                         * us to modify PSTATE, instead of on_each_cpu() which
@@ -994,6 +1002,8 @@ void __init enable_cpu_capabilities(const struct arm64_cpu_capabilities *caps)
                         * we return.
                         */
                        stop_machine(caps->enable, NULL, cpu_online_mask);
+               }
+       }
 }
 
 /*
@@ -1096,6 +1106,14 @@ static void __init setup_feature_capabilities(void)
        enable_cpu_capabilities(arm64_features);
 }
 
+DEFINE_STATIC_KEY_FALSE(arm64_const_caps_ready);
+EXPORT_SYMBOL(arm64_const_caps_ready);
+
+static void __init mark_const_caps_ready(void)
+{
+       static_branch_enable(&arm64_const_caps_ready);
+}
+
 /*
  * Check if the current CPU has a given feature capability.
  * Should be called from non-preemptible context.
@@ -1131,6 +1149,7 @@ void __init setup_cpu_features(void)
        /* Set the CPU feature capabilies */
        setup_feature_capabilities();
        enable_errata_workarounds();
+       mark_const_caps_ready();
        setup_elf_hwcaps(arm64_elf_hwcaps);
 
        if (system_supports_32bit_el0())
index 43512d4d7df219b4b7093927fc1d9107004b6775..b738880350f9e43b8e2f3234210bda153586caf5 100644 (file)
@@ -428,12 +428,13 @@ el1_da:
        /*
         * Data abort handling
         */
-       mrs     x0, far_el1
+       mrs     x3, far_el1
        enable_dbg
        // re-enable interrupts if they were enabled in the aborted context
        tbnz    x23, #7, 1f                     // PSR_I_BIT
        enable_irq
 1:
+       clear_address_tag x0, x3
        mov     x2, sp                          // struct pt_regs
        bl      do_mem_abort
 
@@ -594,7 +595,7 @@ el0_da:
        // enable interrupts before calling the main handler
        enable_dbg_and_irq
        ct_user_exit
-       bic     x0, x26, #(0xff << 56)
+       clear_address_tag x0, x26
        mov     x1, x25
        mov     x2, sp
        bl      do_mem_abort
index 0296e79242402008837da11d97cfe682d711c18e..749f81779420c7bab2ead0d8f5b9a6cf108e6a45 100644 (file)
@@ -36,6 +36,7 @@
 #include <asm/traps.h>
 #include <asm/cputype.h>
 #include <asm/system_misc.h>
+#include <asm/uaccess.h>
 
 /* Breakpoint currently in use for each BRP. */
 static DEFINE_PER_CPU(struct perf_event *, bp_on_reg[ARM_MAX_BRP]);
@@ -721,6 +722,8 @@ static u64 get_distance_from_watchpoint(unsigned long addr, u64 val,
        u64 wp_low, wp_high;
        u32 lens, lene;
 
+       addr = untagged_addr(addr);
+
        lens = __ffs(ctrl->len);
        lene = __fls(ctrl->len);
 
index c9a2ab446dc6fceb4a141fce131937048432da56..f035ff6fb223fb55b3f8b11c48f58f2ee46ac3cf 100644 (file)
 
 void *module_alloc(unsigned long size)
 {
+       gfp_t gfp_mask = GFP_KERNEL;
        void *p;
 
+       /* Silence the initial allocation */
+       if (IS_ENABLED(CONFIG_ARM64_MODULE_PLTS))
+               gfp_mask |= __GFP_NOWARN;
+
        p = __vmalloc_node_range(size, MODULE_ALIGN, module_alloc_base,
                                module_alloc_base + MODULES_VSIZE,
-                               GFP_KERNEL, PAGE_KERNEL_EXEC, 0,
+                               gfp_mask, PAGE_KERNEL_EXEC, 0,
                                NUMA_NO_NODE, __builtin_return_address(0));
 
        if (!p && IS_ENABLED(CONFIG_ARM64_MODULE_PLTS) &&
index bcc79471b38e24cff24b5702a182752ef26583cc..83a1b1ad189f51536af8c4c8dd8c509cb70f9a95 100644 (file)
@@ -877,15 +877,24 @@ static int armv8pmu_set_event_filter(struct hw_perf_event *event,
 
        if (attr->exclude_idle)
                return -EPERM;
-       if (is_kernel_in_hyp_mode() &&
-           attr->exclude_kernel != attr->exclude_hv)
-               return -EINVAL;
+
+       /*
+        * If we're running in hyp mode, then we *are* the hypervisor.
+        * Therefore we ignore exclude_hv in this configuration, since
+        * there's no hypervisor to sample anyway. This is consistent
+        * with other architectures (x86 and Power).
+        */
+       if (is_kernel_in_hyp_mode()) {
+               if (!attr->exclude_kernel)
+                       config_base |= ARMV8_PMU_INCLUDE_EL2;
+       } else {
+               if (attr->exclude_kernel)
+                       config_base |= ARMV8_PMU_EXCLUDE_EL1;
+               if (!attr->exclude_hv)
+                       config_base |= ARMV8_PMU_INCLUDE_EL2;
+       }
        if (attr->exclude_user)
                config_base |= ARMV8_PMU_EXCLUDE_EL0;
-       if (!is_kernel_in_hyp_mode() && attr->exclude_kernel)
-               config_base |= ARMV8_PMU_EXCLUDE_EL1;
-       if (!attr->exclude_hv)
-               config_base |= ARMV8_PMU_INCLUDE_EL2;
 
        /*
         * Install the filter into config_base as this is used to
index d4d6ae02cd558d6d2d7ff6a89db7cc9490e6cccf..0805b44f986a5707d2129e74fd4490f1b3650223 100644 (file)
@@ -443,7 +443,7 @@ int cpu_enable_cache_maint_trap(void *__unused)
 }
 
 #define __user_cache_maint(insn, address, res)                 \
-       if (untagged_addr(address) >= user_addr_max()) {        \
+       if (address >= user_addr_max()) {                       \
                res = -EFAULT;                                  \
        } else {                                                \
                uaccess_ttbr0_enable();                         \
@@ -469,7 +469,7 @@ static void user_cache_maint_handler(unsigned int esr, struct pt_regs *regs)
        int crm = (esr & ESR_ELx_SYS64_ISS_CRM_MASK) >> ESR_ELx_SYS64_ISS_CRM_SHIFT;
        int ret = 0;
 
-       address = pt_regs_read_reg(regs, rt);
+       address = untagged_addr(pt_regs_read_reg(regs, rt));
 
        switch (crm) {
        case ESR_ELx_SYS64_ISS_CRM_DC_CVAU:     /* DC CVAU, gets promoted */
index afd51bebb9c500442ac2de68562b11cb019c3dc3..5d9810086c254defd58046c6a34da6aabfa42fa3 100644 (file)
@@ -7,14 +7,13 @@ CFLAGS_arm.o := -I.
 CFLAGS_mmu.o := -I.
 
 KVM=../../../virt/kvm
-ARM=../../../arch/arm/kvm
 
 obj-$(CONFIG_KVM_ARM_HOST) += kvm.o
 obj-$(CONFIG_KVM_ARM_HOST) += hyp/
 
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o $(KVM)/vfio.o
-kvm-$(CONFIG_KVM_ARM_HOST) += $(ARM)/arm.o $(ARM)/mmu.o $(ARM)/mmio.o
-kvm-$(CONFIG_KVM_ARM_HOST) += $(ARM)/psci.o $(ARM)/perf.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/arm.o $(KVM)/arm/mmu.o $(KVM)/arm/mmio.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/psci.o $(KVM)/arm/perf.o
 
 kvm-$(CONFIG_KVM_ARM_HOST) += inject_fault.o regmap.o
 kvm-$(CONFIG_KVM_ARM_HOST) += hyp.o hyp-init.o handle_exit.o
index aaf42ae8d8c31395d63590289e55798073bc99a4..14c4e3b14bcb6f59a6de55db07de9cc8457be8ec 100644 (file)
@@ -2,6 +2,8 @@
 # Makefile for Kernel-based Virtual Machine module, HYP part
 #
 
+ccflags-y += -fno-stack-protector
+
 KVM=../../../../virt/kvm
 
 obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/vgic-v2-sr.o
index efbe9e8e7a7800eee33eb519fb38c5006b1c821c..0fe27024a2e1a749b2ba08fc3971c10f5ad5adc0 100644 (file)
@@ -1529,8 +1529,8 @@ static int kvm_handle_cp_64(struct kvm_vcpu *vcpu,
 {
        struct sys_reg_params params;
        u32 hsr = kvm_vcpu_get_hsr(vcpu);
-       int Rt = (hsr >> 5) & 0xf;
-       int Rt2 = (hsr >> 10) & 0xf;
+       int Rt = kvm_vcpu_sys_get_rt(vcpu);
+       int Rt2 = (hsr >> 10) & 0x1f;
 
        params.is_aarch32 = true;
        params.is_32bit = false;
@@ -1586,7 +1586,7 @@ static int kvm_handle_cp_32(struct kvm_vcpu *vcpu,
 {
        struct sys_reg_params params;
        u32 hsr = kvm_vcpu_get_hsr(vcpu);
-       int Rt  = (hsr >> 5) & 0xf;
+       int Rt  = kvm_vcpu_sys_get_rt(vcpu);
 
        params.is_aarch32 = true;
        params.is_32bit = true;
@@ -1688,7 +1688,7 @@ int kvm_handle_sys_reg(struct kvm_vcpu *vcpu, struct kvm_run *run)
 {
        struct sys_reg_params params;
        unsigned long esr = kvm_vcpu_get_hsr(vcpu);
-       int Rt = (esr >> 5) & 0x1f;
+       int Rt = kvm_vcpu_sys_get_rt(vcpu);
        int ret;
 
        trace_kvm_handle_sys_reg(esr);
index 4dac4afc95a52f12d58fec7ae37620d0e0b0427b..3216e098c05877178705cdcd659a375e0afec0fd 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/dma-contiguous.h>
 #include <linux/vmalloc.h>
 #include <linux/swiotlb.h>
+#include <linux/pci.h>
 
 #include <asm/cacheflush.h>
 
@@ -879,34 +880,26 @@ static const struct dma_map_ops iommu_dma_ops = {
        .mapping_error = iommu_dma_mapping_error,
 };
 
-/*
- * TODO: Right now __iommu_setup_dma_ops() gets called too early to do
- * everything it needs to - the device is only partially created and the
- * IOMMU driver hasn't seen it yet, so it can't have a group. Thus we
- * need this delayed attachment dance. Once IOMMU probe ordering is sorted
- * to move the arch_setup_dma_ops() call later, all the notifier bits below
- * become unnecessary, and will go away.
- */
-struct iommu_dma_notifier_data {
-       struct list_head list;
-       struct device *dev;
-       const struct iommu_ops *ops;
-       u64 dma_base;
-       u64 size;
-};
-static LIST_HEAD(iommu_dma_masters);
-static DEFINE_MUTEX(iommu_dma_notifier_lock);
+static int __init __iommu_dma_init(void)
+{
+       return iommu_dma_init();
+}
+arch_initcall(__iommu_dma_init);
 
-static bool do_iommu_attach(struct device *dev, const struct iommu_ops *ops,
-                          u64 dma_base, u64 size)
+static void __iommu_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
+                                 const struct iommu_ops *ops)
 {
-       struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
+       struct iommu_domain *domain;
+
+       if (!ops)
+               return;
 
        /*
-        * If the IOMMU driver has the DMA domain support that we require,
-        * then the IOMMU core will have already configured a group for this
-        * device, and allocated the default domain for that group.
+        * The IOMMU core code allocates the default DMA domain, which the
+        * underlying IOMMU driver needs to support via the dma-iommu layer.
         */
+       domain = iommu_get_domain_for_dev(dev);
+
        if (!domain)
                goto out_err;
 
@@ -917,109 +910,11 @@ static bool do_iommu_attach(struct device *dev, const struct iommu_ops *ops,
                dev->dma_ops = &iommu_dma_ops;
        }
 
-       return true;
+       return;
+
 out_err:
-       pr_warn("Failed to set up IOMMU for device %s; retaining platform DMA ops\n",
+        pr_warn("Failed to set up IOMMU for device %s; retaining platform DMA ops\n",
                 dev_name(dev));
-       return false;
-}
-
-static void queue_iommu_attach(struct device *dev, const struct iommu_ops *ops,
-                             u64 dma_base, u64 size)
-{
-       struct iommu_dma_notifier_data *iommudata;
-
-       iommudata = kzalloc(sizeof(*iommudata), GFP_KERNEL);
-       if (!iommudata)
-               return;
-
-       iommudata->dev = dev;
-       iommudata->ops = ops;
-       iommudata->dma_base = dma_base;
-       iommudata->size = size;
-
-       mutex_lock(&iommu_dma_notifier_lock);
-       list_add(&iommudata->list, &iommu_dma_masters);
-       mutex_unlock(&iommu_dma_notifier_lock);
-}
-
-static int __iommu_attach_notifier(struct notifier_block *nb,
-                                  unsigned long action, void *data)
-{
-       struct iommu_dma_notifier_data *master, *tmp;
-
-       if (action != BUS_NOTIFY_BIND_DRIVER)
-               return 0;
-
-       mutex_lock(&iommu_dma_notifier_lock);
-       list_for_each_entry_safe(master, tmp, &iommu_dma_masters, list) {
-               if (data == master->dev && do_iommu_attach(master->dev,
-                               master->ops, master->dma_base, master->size)) {
-                       list_del(&master->list);
-                       kfree(master);
-                       break;
-               }
-       }
-       mutex_unlock(&iommu_dma_notifier_lock);
-       return 0;
-}
-
-static int __init register_iommu_dma_ops_notifier(struct bus_type *bus)
-{
-       struct notifier_block *nb = kzalloc(sizeof(*nb), GFP_KERNEL);
-       int ret;
-
-       if (!nb)
-               return -ENOMEM;
-
-       nb->notifier_call = __iommu_attach_notifier;
-
-       ret = bus_register_notifier(bus, nb);
-       if (ret) {
-               pr_warn("Failed to register DMA domain notifier; IOMMU DMA ops unavailable on bus '%s'\n",
-                       bus->name);
-               kfree(nb);
-       }
-       return ret;
-}
-
-static int __init __iommu_dma_init(void)
-{
-       int ret;
-
-       ret = iommu_dma_init();
-       if (!ret)
-               ret = register_iommu_dma_ops_notifier(&platform_bus_type);
-       if (!ret)
-               ret = register_iommu_dma_ops_notifier(&amba_bustype);
-#ifdef CONFIG_PCI
-       if (!ret)
-               ret = register_iommu_dma_ops_notifier(&pci_bus_type);
-#endif
-       return ret;
-}
-arch_initcall(__iommu_dma_init);
-
-static void __iommu_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
-                                 const struct iommu_ops *ops)
-{
-       struct iommu_group *group;
-
-       if (!ops)
-               return;
-       /*
-        * TODO: As a concession to the future, we're ready to handle being
-        * called both early and late (i.e. after bus_add_device). Once all
-        * the platform bus code is reworked to call us late and the notifier
-        * junk above goes away, move the body of do_iommu_attach here.
-        */
-       group = iommu_group_get(dev);
-       if (group) {
-               do_iommu_attach(dev, ops, dma_base, size);
-               iommu_group_put(group);
-       } else {
-               queue_iommu_attach(dev, ops, dma_base, size);
-       }
 }
 
 void arch_teardown_dma_ops(struct device *dev)
index 3212ee0558f6e0ca3113b4ad9db157911085a768..a682a0a2a0fa4d5db9175256e78100b1afde344a 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/vmalloc.h>
 
 #include <asm/pgtable.h>
+#include <asm/set_memory.h>
 #include <asm/tlbflush.h>
 
 struct page_change_data {
index d68abde52740d7b55f89dea8daf84f3109b0e17c..71f930501ade7cec2d1f230aa638ad3fc9112ee8 100644 (file)
@@ -27,6 +27,7 @@
 #include <asm/byteorder.h>
 #include <asm/cacheflush.h>
 #include <asm/debug-monitors.h>
+#include <asm/set_memory.h>
 
 #include "bpf_jit.h"
 
@@ -252,8 +253,9 @@ static int emit_bpf_tail_call(struct jit_ctx *ctx)
         */
        off = offsetof(struct bpf_array, ptrs);
        emit_a64_mov_i64(tmp, off, ctx);
-       emit(A64_LDR64(tmp, r2, tmp), ctx);
-       emit(A64_LDR64(prg, tmp, r3), ctx);
+       emit(A64_ADD(1, tmp, r2, tmp), ctx);
+       emit(A64_LSL(1, prg, r3, 3), ctx);
+       emit(A64_LDR64(prg, tmp, prg), ctx);
        emit(A64_CBZ(1, prg, jmp_offset), ctx);
 
        /* goto *(prog->bpf_func + prologue_size); */
index 0bd28f77abc35fd0dc47e26e70f3defa90b0341f..b15bf6bc0e94f46f035e8781ffa921060341fe91 100644 (file)
@@ -1,19 +1,2 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
-
-header-y += bfin_sport.h
-header-y += byteorder.h
-header-y += cachectl.h
-header-y += fcntl.h
-header-y += fixed_code.h
-header-y += ioctls.h
-header-y += kvm_para.h
-header-y += poll.h
-header-y += posix_types.h
-header-y += ptrace.h
-header-y += sigcontext.h
-header-y += siginfo.h
-header-y += signal.h
-header-y += stat.h
-header-y += swab.h
-header-y += unistd.h
index e9bc2b2b814740d82e9a4fb9eae800a3bbfe5aad..13a97aa2285f7418d18f1396f03bf6281b580a0f 100644 (file)
@@ -2,11 +2,3 @@
 include include/uapi/asm-generic/Kbuild.asm
 
 generic-y += kvm_para.h
-
-header-y += byteorder.h
-header-y += kvm_para.h
-header-y += ptrace.h
-header-y += setup.h
-header-y += sigcontext.h
-header-y += swab.h
-header-y += unistd.h
index 2735eb7671a5ad9203251fe88726145b3a33a92a..b7cd6b9209a9e19027391931798de6bd1a0eb93e 100644 (file)
@@ -136,7 +136,6 @@ config ETRAX_NANDFLASH
        bool "NAND flash support"
        depends on ETRAX_ARCH_V32
        select MTD_NAND
-       select MTD_NAND_IDS
        help
          This option enables MTD mapping of NAND flash devices.  Needed to use
          NAND flash memories.  If unsure, say Y.
index 212266a2c5d9a50705c5181dd71b81003fc30dc7..394c2a73d5e25bb6cf748a37ddeeb62aa5fed5c2 100644 (file)
@@ -14,28 +14,6 @@ void pcibios_set_master(struct pci_dev *dev)
        pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
 }
 
-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
-                       enum pci_mmap_state mmap_state, int write_combine)
-{
-       unsigned long prot;
-
-       /* Leave vm_pgoff as-is, the PCI space address is the physical
-        * address on this platform.
-        */
-       prot = pgprot_val(vma->vm_page_prot);
-       vma->vm_page_prot = __pgprot(prot);
-
-       /* Write-combine setting is ignored, it is changed via the mtrr
-        * interfaces on this platform.
-        */
-       if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
-                            vma->vm_end - vma->vm_start,
-                            vma->vm_page_prot))
-               return -EAGAIN;
-
-       return 0;
-}
-
 resource_size_t
 pcibios_align_resource(void *data, const struct resource *res,
                       resource_size_t size, resource_size_t align)
diff --git a/arch/cris/boot/dts/include/dt-bindings b/arch/cris/boot/dts/include/dt-bindings
deleted file mode 120000 (symlink)
index 08c00e4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../include/dt-bindings
\ No newline at end of file
diff --git a/arch/cris/include/arch-v10/arch/Kbuild b/arch/cris/include/arch-v10/arch/Kbuild
deleted file mode 100644 (file)
index 1f0fc7a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-# CRISv10 arch
diff --git a/arch/cris/include/arch-v32/arch/Kbuild b/arch/cris/include/arch-v32/arch/Kbuild
deleted file mode 100644 (file)
index 2fd65c7..0000000
+++ /dev/null
@@ -1 +0,0 @@
-# CRISv32 arch
index b1b289df04c77f62575bd5be61968f1a784330fd..6e505332b3e36d165a960e222e9593994c7eaf83 100644 (file)
@@ -42,9 +42,7 @@ struct pci_dev;
 #define PCI_DMA_BUS_IS_PHYS    (1)
 
 #define HAVE_PCI_MMAP
-extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
-                              enum pci_mmap_state mmap_state, int write_combine);
-
+#define ARCH_GENERIC_PCI_MMAP_RESOURCE
 
 #endif /* __KERNEL__ */
 
diff --git a/arch/cris/include/uapi/arch-v10/arch/Kbuild b/arch/cris/include/uapi/arch-v10/arch/Kbuild
deleted file mode 100644 (file)
index 9048c87..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-# UAPI Header export list
-header-y += sv_addr.agh
-header-y += sv_addr_ag.h
-header-y += svinto.h
-header-y += user.h
diff --git a/arch/cris/include/uapi/arch-v32/arch/Kbuild b/arch/cris/include/uapi/arch-v32/arch/Kbuild
deleted file mode 100644 (file)
index 59efffd..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# UAPI Header export list
-header-y += cryptocop.h
-header-y += user.h
index d5564a0ae66adc23b7c42fe31f69ad1f3ac131e6..b15bf6bc0e94f46f035e8781ffa921060341fe91 100644 (file)
@@ -1,44 +1,2 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
-
-header-y += ../arch-v10/arch/
-header-y += ../arch-v32/arch/
-header-y += auxvec.h
-header-y += bitsperlong.h
-header-y += byteorder.h
-header-y += elf.h
-header-y += elf_v10.h
-header-y += elf_v32.h
-header-y += errno.h
-header-y += ethernet.h
-header-y += etraxgpio.h
-header-y += fcntl.h
-header-y += ioctl.h
-header-y += ioctls.h
-header-y += ipcbuf.h
-header-y += mman.h
-header-y += msgbuf.h
-header-y += param.h
-header-y += poll.h
-header-y += posix_types.h
-header-y += ptrace.h
-header-y += ptrace_v10.h
-header-y += ptrace_v32.h
-header-y += resource.h
-header-y += rs485.h
-header-y += sembuf.h
-header-y += setup.h
-header-y += shmbuf.h
-header-y += sigcontext.h
-header-y += siginfo.h
-header-y += signal.h
-header-y += socket.h
-header-y += sockios.h
-header-y += stat.h
-header-y += statfs.h
-header-y += swab.h
-header-y += sync_serial.h
-header-y += termbits.h
-header-y += termios.h
-header-y += types.h
-header-y += unistd.h
index 42a2b33461c042aa867d3392b2a30dfbef98f11a..b15bf6bc0e94f46f035e8781ffa921060341fe91 100644 (file)
@@ -1,35 +1,2 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
-
-header-y += auxvec.h
-header-y += bitsperlong.h
-header-y += byteorder.h
-header-y += errno.h
-header-y += fcntl.h
-header-y += ioctl.h
-header-y += ioctls.h
-header-y += ipcbuf.h
-header-y += kvm_para.h
-header-y += mman.h
-header-y += msgbuf.h
-header-y += param.h
-header-y += poll.h
-header-y += posix_types.h
-header-y += ptrace.h
-header-y += registers.h
-header-y += resource.h
-header-y += sembuf.h
-header-y += setup.h
-header-y += shmbuf.h
-header-y += sigcontext.h
-header-y += siginfo.h
-header-y += signal.h
-header-y += socket.h
-header-y += sockios.h
-header-y += stat.h
-header-y += statfs.h
-header-y += swab.h
-header-y += termbits.h
-header-y += termios.h
-header-y += types.h
-header-y += unistd.h
index 8414293f213a417fd8a8be049409b10966f1c062..20c5b79b55f9bdafb53423488b4ea7761ce0d548 100644 (file)
 #include <asm/thread_info.h>
 #include <asm/gdb-stub.h>
 
-#define DEF_PTREG(sym, reg) \
-        asm volatile("\n->" #sym " %0 offsetof(struct pt_regs, " #reg ")" \
-                    : : "i" (offsetof(struct pt_regs, reg)))
-
-#define DEF_IREG(sym, reg) \
-        asm volatile("\n->" #sym " %0 offsetof(struct user_context, " #reg ")" \
-                    : : "i" (offsetof(struct user_context, reg)))
-
-#define DEF_FREG(sym, reg) \
-        asm volatile("\n->" #sym " %0 offsetof(struct user_context, " #reg ")" \
-                    : : "i" (offsetof(struct user_context, reg)))
-
-#define DEF_0REG(sym, reg) \
-        asm volatile("\n->" #sym " %0 offsetof(struct frv_frame0, " #reg ")" \
-                    : : "i" (offsetof(struct frv_frame0, reg)))
+#define DEF_PTREG(sym, reg) OFFSET(sym, pt_regs, reg)
+#define DEF_IREG(sym, reg) OFFSET(sym, user_context, reg)
+#define DEF_FREG(sym, reg) OFFSET(sym, user_context, reg)
+#define DEF_0REG(sym, reg) OFFSET(sym, frv_frame0, reg)
 
 void foo(void)
 {
index fb6101a5d4f1a5464fa43715475582a07467635c..b15bf6bc0e94f46f035e8781ffa921060341fe91 100644 (file)
@@ -1,30 +1,2 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
-
-header-y += auxvec.h
-header-y += bitsperlong.h
-header-y += errno.h
-header-y += fcntl.h
-header-y += ioctl.h
-header-y += ioctls.h
-header-y += ipcbuf.h
-header-y += kvm_para.h
-header-y += mman.h
-header-y += msgbuf.h
-header-y += param.h
-header-y += poll.h
-header-y += posix_types.h
-header-y += resource.h
-header-y += sembuf.h
-header-y += setup.h
-header-y += shmbuf.h
-header-y += siginfo.h
-header-y += socket.h
-header-y += sockios.h
-header-y += stat.h
-header-y += statfs.h
-header-y += swab.h
-header-y += termbits.h
-header-y += termios.h
-header-y += types.h
-header-y += unistd.h
similarity index 67%
rename from arch/h8300/include/asm/bitsperlong.h
rename to arch/h8300/include/uapi/asm/bitsperlong.h
index e140e46729ac99a05fec1bdbdfc62d3577506dfd..34212608371e9c48874a337f8b8b7c72282063cc 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_H8300_BITS_PER_LONG
-#define __ASM_H8300_BITS_PER_LONG
+#ifndef _UAPI__ASM_H8300_BITS_PER_LONG
+#define _UAPI__ASM_H8300_BITS_PER_LONG
 
 #include <asm-generic/bitsperlong.h>
 
@@ -11,4 +11,4 @@ typedef long          __kernel_ssize_t;
 typedef long           __kernel_ptrdiff_t;
 #endif
 
-#endif /* __ASM_H8300_BITS_PER_LONG */
+#endif /* _UAPI__ASM_H8300_BITS_PER_LONG */
index a2036bfda8aff68d26cabbd5f3c326bec077cf52..6b45ef79eb8fa8dedafd7d1f41e6a3b40e678729 100644 (file)
@@ -1,6 +1,3 @@
-
-header-y += ucontext.h
-
 generic-y += auxvec.h
 generic-y += barrier.h
 generic-y += bug.h
index c31706c38631b75779b0f472667d5f01fe2c0936..b15bf6bc0e94f46f035e8781ffa921060341fe91 100644 (file)
@@ -1,15 +1,2 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
-
-header-y += bitsperlong.h
-header-y += byteorder.h
-header-y += kvm_para.h
-header-y += param.h
-header-y += ptrace.h
-header-y += registers.h
-header-y += setup.h
-header-y += sigcontext.h
-header-y += signal.h
-header-y += swab.h
-header-y += unistd.h
-header-y += user.h
index c0835b0dc72275adb47cae1dbcda19f098809320..6459f2d46200581b2b5288a54aab090cde2d20d1 100644 (file)
@@ -51,8 +51,9 @@ extern unsigned long ia64_max_iommu_merge_mask;
 #define PCI_DMA_BUS_IS_PHYS    (ia64_max_iommu_merge_mask == ~0UL)
 
 #define HAVE_PCI_MMAP
-extern int pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
-                               enum pci_mmap_state mmap_state, int write_combine);
+#define ARCH_GENERIC_PCI_MMAP_RESOURCE
+#define arch_can_pci_mmap_wc() 1
+
 #define HAVE_PCI_LEGACY
 extern int pci_mmap_legacy_page_range(struct pci_bus *bus,
                                      struct vm_area_struct *vma,
index 891002bbb995beefd85a66001fa58999e9da1b26..13a97aa2285f7418d18f1396f03bf6281b580a0f 100644 (file)
@@ -2,48 +2,3 @@
 include include/uapi/asm-generic/Kbuild.asm
 
 generic-y += kvm_para.h
-
-header-y += auxvec.h
-header-y += bitsperlong.h
-header-y += break.h
-header-y += byteorder.h
-header-y += cmpxchg.h
-header-y += errno.h
-header-y += fcntl.h
-header-y += fpu.h
-header-y += gcc_intrin.h
-header-y += ia64regs.h
-header-y += intel_intrin.h
-header-y += intrinsics.h
-header-y += ioctl.h
-header-y += ioctls.h
-header-y += ipcbuf.h
-header-y += kvm_para.h
-header-y += mman.h
-header-y += msgbuf.h
-header-y += param.h
-header-y += perfmon.h
-header-y += perfmon_default_smpl.h
-header-y += poll.h
-header-y += posix_types.h
-header-y += ptrace.h
-header-y += ptrace_offsets.h
-header-y += resource.h
-header-y += rse.h
-header-y += sembuf.h
-header-y += setup.h
-header-y += shmbuf.h
-header-y += sigcontext.h
-header-y += siginfo.h
-header-y += signal.h
-header-y += socket.h
-header-y += sockios.h
-header-y += stat.h
-header-y += statfs.h
-header-y += swab.h
-header-y += termbits.h
-header-y += termios.h
-header-y += types.h
-header-y += ucontext.h
-header-y += unistd.h
-header-y += ustack.h
index 3686d6abafdefd3feb854656d5cf704f89be5340..9edda5466020df4e18bb3c060e07304993c58a1e 100644 (file)
@@ -50,32 +50,10 @@ CFLAGS_traps.o  += -mfixed-range=f2-f5,f16-f31
 # The gate DSO image is built using a special linker script.
 include $(src)/Makefile.gate
 
-# Calculate NR_IRQ = max(IA64_NATIVE_NR_IRQS, XEN_NR_IRQS, ...) based on config
-define sed-y
-       "/^->/{s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; s:->::; p;}"
-endef
-quiet_cmd_nr_irqs = GEN     $@
-define cmd_nr_irqs
-       (set -e; \
-        echo "#ifndef __ASM_NR_IRQS_H__"; \
-        echo "#define __ASM_NR_IRQS_H__"; \
-        echo "/*"; \
-        echo " * DO NOT MODIFY."; \
-        echo " *"; \
-        echo " * This file was generated by Kbuild"; \
-        echo " *"; \
-        echo " */"; \
-        echo ""; \
-        sed -ne $(sed-y) $<; \
-        echo ""; \
-        echo "#endif" ) > $@
-endef
-
 # We use internal kbuild rules to avoid the "is up to date" message from make
 arch/$(SRCARCH)/kernel/nr-irqs.s: arch/$(SRCARCH)/kernel/nr-irqs.c
        $(Q)mkdir -p $(dir $@)
        $(call if_changed_dep,cc_s_c)
 
-include/generated/nr-irqs.h: arch/$(SRCARCH)/kernel/nr-irqs.s
-       $(Q)mkdir -p $(dir $@)
-       $(call cmd,nr_irqs)
+include/generated/nr-irqs.h: arch/$(SRCARCH)/kernel/nr-irqs.s FORCE
+       $(call filechk,offsets,__ASM_NR_IRQS_H__)
index ceeffc50976462812dec9b9f18105052600862f4..a32903ada01645bb9fe1a1d4740d8d8cd33496c8 100644 (file)
@@ -6,7 +6,7 @@ extra-y += gate.so gate-syms.o gate.lds gate.o
 
 CPPFLAGS_gate.lds := -P -C -U$(ARCH)
 
-quiet_cmd_gate = GATE $@
+quiet_cmd_gate = GATE    $@
       cmd_gate = $(CC) -nostdlib $(GATECFLAGS_$(@F)) -Wl,-T,$(filter-out FORCE,$^) -o $@
 
 GATECFLAGS_gate.so = -shared -s -Wl,-soname=linux-gate.so.1 \
index 2955f359e2a7a9019d38ca066015c16d10d806d4..75859a07d75bd6e754a3cec5b2e548be74452c86 100644 (file)
@@ -27,28 +27,6 @@ static int kdump_freeze_monarch;
 static int kdump_on_init = 1;
 static int kdump_on_fatal_mca = 1;
 
-static inline Elf64_Word
-*append_elf_note(Elf64_Word *buf, char *name, unsigned type, void *data,
-               size_t data_len)
-{
-       struct elf_note *note = (struct elf_note *)buf;
-       note->n_namesz = strlen(name) + 1;
-       note->n_descsz = data_len;
-       note->n_type   = type;
-       buf += (sizeof(*note) + 3)/4;
-       memcpy(buf, name, note->n_namesz);
-       buf += (note->n_namesz + 3)/4;
-       memcpy(buf, data, data_len);
-       buf += (data_len + 3)/4;
-       return buf;
-}
-
-static void
-final_note(void *buf)
-{
-       memset(buf, 0, sizeof(struct elf_note));
-}
-
 extern void ia64_dump_cpu_regs(void *);
 
 static DEFINE_PER_CPU(struct elf_prstatus, elf_prstatus);
index 8f6ac2f8ae4c8cebea5cd85d79b11251d7b09979..4068bde623dc3dd40c1dc81ccc021d6fdc6303a2 100644 (file)
@@ -418,52 +418,6 @@ pcibios_align_resource (void *data, const struct resource *res,
        return res->start;
 }
 
-int
-pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
-                    enum pci_mmap_state mmap_state, int write_combine)
-{
-       unsigned long size = vma->vm_end - vma->vm_start;
-       pgprot_t prot;
-
-       /*
-        * I/O space cannot be accessed via normal processor loads and
-        * stores on this platform.
-        */
-       if (mmap_state == pci_mmap_io)
-               /*
-                * XXX we could relax this for I/O spaces for which ACPI
-                * indicates that the space is 1-to-1 mapped.  But at the
-                * moment, we don't support multiple PCI address spaces and
-                * the legacy I/O space is not 1-to-1 mapped, so this is moot.
-                */
-               return -EINVAL;
-
-       if (!valid_mmap_phys_addr_range(vma->vm_pgoff, size))
-               return -EINVAL;
-
-       prot = phys_mem_access_prot(NULL, vma->vm_pgoff, size,
-                                   vma->vm_page_prot);
-
-       /*
-        * If the user requested WC, the kernel uses UC or WC for this region,
-        * and the chipset supports WC, we can use WC. Otherwise, we have to
-        * use the same attribute the kernel uses.
-        */
-       if (write_combine &&
-           ((pgprot_val(prot) & _PAGE_MA_MASK) == _PAGE_MA_UC ||
-            (pgprot_val(prot) & _PAGE_MA_MASK) == _PAGE_MA_WC) &&
-           efi_range_is_wc(vma->vm_start, vma->vm_end - vma->vm_start))
-               vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
-       else
-               vma->vm_page_prot = prot;
-
-       if (remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
-                            vma->vm_end - vma->vm_start, vma->vm_page_prot))
-               return -EAGAIN;
-
-       return 0;
-}
-
 /**
  * ia64_pci_get_legacy_mem - generic legacy mem routine
  * @bus: bus to get legacy memory base address for
index 43937a61d6cf97c58bc46aa2470561390d351ca2..b15bf6bc0e94f46f035e8781ffa921060341fe91 100644 (file)
@@ -1,33 +1,2 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
-
-header-y += auxvec.h
-header-y += bitsperlong.h
-header-y += byteorder.h
-header-y += errno.h
-header-y += fcntl.h
-header-y += ioctl.h
-header-y += ioctls.h
-header-y += ipcbuf.h
-header-y += mman.h
-header-y += msgbuf.h
-header-y += param.h
-header-y += poll.h
-header-y += posix_types.h
-header-y += ptrace.h
-header-y += resource.h
-header-y += sembuf.h
-header-y += setup.h
-header-y += shmbuf.h
-header-y += sigcontext.h
-header-y += siginfo.h
-header-y += signal.h
-header-y += socket.h
-header-y += sockios.h
-header-y += stat.h
-header-y += statfs.h
-header-y += swab.h
-header-y += termbits.h
-header-y += termios.h
-header-y += types.h
-header-y += unistd.h
index 970abaf3303e037184fb8bde424ee67624c0f125..dd5b2c357e953db3c6ecdb1a6f04805517142def 100644 (file)
@@ -776,7 +776,7 @@ muls64_zero:
 # ALGORITHM ***********************************************************        #
 #      In the interest of simplicity, all operands are converted to    #
 # longword size whether the operation is byte, word, or long. The      #
-# bounds are sign extended accordingly. If Rn is a data regsiter, Rn is #
+# bounds are sign extended accordingly. If Rn is a data register, Rn is #
 # also sign extended. If Rn is an address register, it need not be sign #
 # extended since the full register is always used.                     #
 #      The condition codes are set correctly before the final "rts".   #
index b865c1a052ba2c24bc5206f374e9497e4773977a..29a9f8629b9dc9cb9a0b22c7505af02d0687c4f5 100644 (file)
@@ -1876,7 +1876,7 @@ movp_read_err:
 # word, or longword sized operands. Then, in the interest of           #
 # simplicity, all operands are converted to longword size whether the  #
 # operation is byte, word, or long. The bounds are sign extended       #
-# accordingly. If Rn is a data regsiter, Rn is also sign extended. If  #
+# accordingly. If Rn is a data register, Rn is also sign extended. If  #
 # Rn is an address register, it need not be sign extended since the    #
 # full register is always used.                                                #
 #      The comparisons are made and the condition codes calculated.    #
index 6a2d257bdfb2224492f8f901575d17cc9b4f82d7..64368077235aa9f2234cfee5e99df6995c83eed7 100644 (file)
@@ -9,27 +9,3 @@ generic-y += socket.h
 generic-y += sockios.h
 generic-y += termbits.h
 generic-y += termios.h
-
-header-y += a.out.h
-header-y += bootinfo.h
-header-y += bootinfo-amiga.h
-header-y += bootinfo-apollo.h
-header-y += bootinfo-atari.h
-header-y += bootinfo-hp300.h
-header-y += bootinfo-mac.h
-header-y += bootinfo-q40.h
-header-y += bootinfo-vme.h
-header-y += byteorder.h
-header-y += cachectl.h
-header-y += fcntl.h
-header-y += ioctls.h
-header-y += param.h
-header-y += poll.h
-header-y += posix_types.h
-header-y += ptrace.h
-header-y += setup.h
-header-y += sigcontext.h
-header-y += signal.h
-header-y += stat.h
-header-y += swab.h
-header-y += unistd.h
diff --git a/arch/metag/boot/dts/include/dt-bindings b/arch/metag/boot/dts/include/dt-bindings
deleted file mode 120000 (symlink)
index 08c00e4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../include/dt-bindings
\ No newline at end of file
index 5ebc2850690eb4efb9d29266df9cc9a261517338..9c8fbf8fb5aa2c5adbd0a5fc3c44d07666841a17 100644 (file)
 
 #define segment_eq(a, b)       ((a).seg == (b).seg)
 
-#define __kernel_ok (uaccess_kernel())
-/*
- * Explicitly allow NULL pointers here. Parts of the kernel such
- * as readv/writev use access_ok to validate pointers, but want
- * to allow NULL pointers for various reasons. NULL pointers are
- * safe to allow through because the first page is not mappable on
- * Meta.
- *
- * We also wish to avoid letting user code access the system area
- * and the kernel half of the address space.
- */
-#define __user_bad(addr, size) (((addr) > 0 && (addr) < META_MEMORY_BASE) || \
-                               ((addr) > PAGE_OFFSET &&                \
-                                (addr) < LINCORE_BASE))
-
 static inline int __access_ok(unsigned long addr, unsigned long size)
 {
-       return __kernel_ok || !__user_bad(addr, size);
+       /*
+        * Allow access to the user mapped memory area, but not the system area
+        * before it. The check extends to the top of the address space when
+        * kernel access is allowed (there's no real reason to user copy to the
+        * system area in any case).
+        */
+       if (likely(addr >= META_MEMORY_BASE && addr < get_fs().seg &&
+                  size <= get_fs().seg - addr))
+               return true;
+       /*
+        * Explicitly allow NULL pointers here. Parts of the kernel such
+        * as readv/writev use access_ok to validate pointers, but want
+        * to allow NULL pointers for various reasons. NULL pointers are
+        * safe to allow through because the first page is not mappable on
+        * Meta.
+        */
+       if (!addr)
+               return true;
+       /* Allow access to core code memory area... */
+       if (addr >= LINCORE_CODE_BASE && addr <= LINCORE_CODE_LIMIT &&
+           size <= LINCORE_CODE_LIMIT + 1 - addr)
+               return true;
+       /* ... but no other areas. */
+       return false;
 }
 
 #define access_ok(type, addr, size) __access_ok((unsigned long)(addr), \
@@ -113,7 +121,8 @@ extern long __get_user_bad(void);
 
 #define __get_user_nocheck(x, ptr, size)                       \
 ({                                                              \
-       long __gu_err, __gu_val;                                \
+       long __gu_err;                                          \
+       long long __gu_val;                                     \
        __get_user_size(__gu_val, (ptr), (size), __gu_err);     \
        (x) = (__force __typeof__(*(ptr)))__gu_val;             \
        __gu_err;                                               \
@@ -121,7 +130,8 @@ extern long __get_user_bad(void);
 
 #define __get_user_check(x, ptr, size)                                 \
 ({                                                                      \
-       long __gu_err = -EFAULT, __gu_val = 0;                          \
+       long __gu_err = -EFAULT;                                        \
+       long long __gu_val = 0;                                         \
        const __typeof__(*(ptr)) __user *__gu_addr = (ptr);             \
        if (access_ok(VERIFY_READ, __gu_addr, size))                    \
                __get_user_size(__gu_val, __gu_addr, (size), __gu_err); \
@@ -132,6 +142,7 @@ extern long __get_user_bad(void);
 extern unsigned char __get_user_asm_b(const void __user *addr, long *err);
 extern unsigned short __get_user_asm_w(const void __user *addr, long *err);
 extern unsigned int __get_user_asm_d(const void __user *addr, long *err);
+extern unsigned long long __get_user_asm_l(const void __user *addr, long *err);
 
 #define __get_user_size(x, ptr, size, retval)                  \
 do {                                                            \
@@ -143,6 +154,8 @@ do {                                                            \
                x = __get_user_asm_w(ptr, &retval); break;      \
        case 4:                                                 \
                x = __get_user_asm_d(ptr, &retval); break;      \
+       case 8:                                                 \
+               x = __get_user_asm_l(ptr, &retval); break;      \
        default:                                                \
                (x) = __get_user_bad();                         \
        }                                                       \
@@ -161,8 +174,13 @@ do {                                                            \
 extern long __must_check __strncpy_from_user(char *dst, const char __user *src,
                                             long count);
 
-#define strncpy_from_user(dst, src, count) __strncpy_from_user(dst, src, count)
-
+static inline long
+strncpy_from_user(char *dst, const char __user *src, long count)
+{
+       if (!access_ok(VERIFY_READ, src, 1))
+               return -EFAULT;
+       return __strncpy_from_user(dst, src, count);
+}
 /*
  * Return the size of a string (including the ending 0)
  *
index ab78be2b6eb0503f939cc85409d532a3b037b491..b29731ebd7a93b3bd51d42565ccc2b727d0963c2 100644 (file)
@@ -1,14 +1,6 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
-header-y += byteorder.h
-header-y += ech.h
-header-y += ptrace.h
-header-y += sigcontext.h
-header-y += siginfo.h
-header-y += swab.h
-header-y += unistd.h
-
 generic-y += mman.h
 generic-y += resource.h
 generic-y += setup.h
index e8a4ea83cabbccea76c2fd056ffbdccd8d6a8012..c941abdb8f85586bf648c2a6fe53ba9350dcb5f0 100644 (file)
 #define __asm_copy_user_64bit_rapf_loop(                               \
                to, from, ret, n, id, FIXUP)                            \
        asm volatile (                                                  \
-               ".balign 8\n"                                           \
-               "MOV    RAPF, %1\n"                                     \
-               "MSETL  [A0StP++], D0Ar6, D0FrT, D0.5, D0.6, D0.7\n"    \
-               "MOV    D0Ar6, #0\n"                                    \
-               "LSR    D1Ar5, %3, #6\n"                                \
-               "SUB    TXRPT, D1Ar5, #2\n"                             \
-               "MOV    RAPF, %1\n"                                     \
+                       ".balign 8\n"                                   \
+               "       MOV     RAPF, %1\n"                             \
+               "       MSETL   [A0StP++], D0Ar6, D0FrT, D0.5, D0.6, D0.7\n" \
+               "       MOV     D0Ar6, #0\n"                            \
+               "       LSR     D1Ar5, %3, #6\n"                        \
+               "       SUB     TXRPT, D1Ar5, #2\n"                     \
+               "       MOV     RAPF, %1\n"                             \
                "$Lloop"id":\n"                                         \
-               "ADD    RAPF, %1, #64\n"                                \
-               "21:\n"                                                 \
-               "MGETL  D0FrT, D0.5, D0.6, D0.7, [%1++]\n"              \
-               "22:\n"                                                 \
-               "MSETL  [%0++], D0FrT, D0.5, D0.6, D0.7\n"              \
-               "23:\n"                                                 \
-               "SUB    %3, %3, #32\n"                                  \
-               "24:\n"                                                 \
-               "MGETL  D0FrT, D0.5, D0.6, D0.7, [%1++]\n"              \
-               "25:\n"                                                 \
-               "MSETL  [%0++], D0FrT, D0.5, D0.6, D0.7\n"              \
-               "26:\n"                                                 \
-               "SUB    %3, %3, #32\n"                                  \
-               "DCACHE [%1+#-64], D0Ar6\n"                             \
-               "BR     $Lloop"id"\n"                                   \
+               "       ADD     RAPF, %1, #64\n"                        \
+               "21:    MGETL   D0FrT, D0.5, D0.6, D0.7, [%1++]\n"      \
+               "22:    MSETL   [%0++], D0FrT, D0.5, D0.6, D0.7\n"      \
+               "23:    SUB     %3, %3, #32\n"                          \
+               "24:    MGETL   D0FrT, D0.5, D0.6, D0.7, [%1++]\n"      \
+               "25:    MSETL   [%0++], D0FrT, D0.5, D0.6, D0.7\n"      \
+               "26:    SUB     %3, %3, #32\n"                          \
+               "       DCACHE  [%1+#-64], D0Ar6\n"                     \
+               "       BR      $Lloop"id"\n"                           \
                                                                        \
-               "MOV    RAPF, %1\n"                                     \
-               "27:\n"                                                 \
-               "MGETL  D0FrT, D0.5, D0.6, D0.7, [%1++]\n"              \
-               "28:\n"                                                 \
-               "MSETL  [%0++], D0FrT, D0.5, D0.6, D0.7\n"              \
-               "29:\n"                                                 \
-               "SUB    %3, %3, #32\n"                                  \
-               "30:\n"                                                 \
-               "MGETL  D0FrT, D0.5, D0.6, D0.7, [%1++]\n"              \
-               "31:\n"                                                 \
-               "MSETL  [%0++], D0FrT, D0.5, D0.6, D0.7\n"              \
-               "32:\n"                                                 \
-               "SUB    %0, %0, #8\n"                                   \
-               "33:\n"                                                 \
-               "SETL   [%0++], D0.7, D1.7\n"                           \
-               "SUB    %3, %3, #32\n"                                  \
-               "1:"                                                    \
-               "DCACHE [%1+#-64], D0Ar6\n"                             \
-               "GETL    D0Ar6, D1Ar5, [A0StP+#-40]\n"                  \
-               "GETL    D0FrT, D1RtP, [A0StP+#-32]\n"                  \
-               "GETL    D0.5, D1.5, [A0StP+#-24]\n"                    \
-               "GETL    D0.6, D1.6, [A0StP+#-16]\n"                    \
-               "GETL    D0.7, D1.7, [A0StP+#-8]\n"                     \
-               "SUB A0StP, A0StP, #40\n"                               \
+               "       MOV     RAPF, %1\n"                             \
+               "27:    MGETL   D0FrT, D0.5, D0.6, D0.7, [%1++]\n"      \
+               "28:    MSETL   [%0++], D0FrT, D0.5, D0.6, D0.7\n"      \
+               "29:    SUB     %3, %3, #32\n"                          \
+               "30:    MGETL   D0FrT, D0.5, D0.6, D0.7, [%1++]\n"      \
+               "31:    MSETL   [%0++], D0FrT, D0.5, D0.6, D0.7\n"      \
+               "32:    SETL    [%0+#-8], D0.7, D1.7\n"                 \
+               "       SUB     %3, %3, #32\n"                          \
+               "1:     DCACHE  [%1+#-64], D0Ar6\n"                     \
+               "       GETL    D0Ar6, D1Ar5, [A0StP+#-40]\n"           \
+               "       GETL    D0FrT, D1RtP, [A0StP+#-32]\n"           \
+               "       GETL    D0.5, D1.5, [A0StP+#-24]\n"             \
+               "       GETL    D0.6, D1.6, [A0StP+#-16]\n"             \
+               "       GETL    D0.7, D1.7, [A0StP+#-8]\n"              \
+               "       SUB     A0StP, A0StP, #40\n"                    \
                "       .section .fixup,\"ax\"\n"                       \
-               "4:\n"                                                  \
-               "       ADD     %0, %0, #8\n"                           \
-               "3:\n"                                                  \
-               "       MOV     D0Ar2, TXSTATUS\n"                      \
+               "3:     MOV     D0Ar2, TXSTATUS\n"                      \
                "       MOV     D1Ar1, TXSTATUS\n"                      \
                "       AND     D1Ar1, D1Ar1, #0xFFFFF8FF\n"            \
                "       MOV     TXSTATUS, D1Ar1\n"                      \
                        FIXUP                                           \
-               "       MOVT    D0Ar2,#HI(1b)\n"                        \
-               "       JUMP    D0Ar2,#LO(1b)\n"                        \
+               "       MOVT    D0Ar2, #HI(1b)\n"                       \
+               "       JUMP    D0Ar2, #LO(1b)\n"                       \
                "       .previous\n"                                    \
                "       .section __ex_table,\"a\"\n"                    \
                "       .long 21b,3b\n"                                 \
                "       .long 30b,3b\n"                                 \
                "       .long 31b,3b\n"                                 \
                "       .long 32b,3b\n"                                 \
-               "       .long 33b,4b\n"                                 \
                "       .previous\n"                                    \
                : "=r" (to), "=r" (from), "=r" (ret), "=d" (n)          \
                : "0" (to), "1" (from), "2" (ret), "3" (n)              \
 #define __asm_copy_user_32bit_rapf_loop(                               \
                        to,     from, ret, n, id, FIXUP)                \
        asm volatile (                                                  \
-               ".balign 8\n"                                           \
-               "MOV    RAPF, %1\n"                                     \
-               "MSETL  [A0StP++], D0Ar6, D0FrT, D0.5, D0.6, D0.7\n"    \
-               "MOV    D0Ar6, #0\n"                                    \
-               "LSR    D1Ar5, %3, #6\n"                                \
-               "SUB    TXRPT, D1Ar5, #2\n"                             \
-               "MOV    RAPF, %1\n"                                     \
-       "$Lloop"id":\n"                                                 \
-               "ADD    RAPF, %1, #64\n"                                \
-               "21:\n"                                                 \
-               "MGETD  D0FrT, D0.5, D0.6, D0.7, [%1++]\n"              \
-               "22:\n"                                                 \
-               "MSETD  [%0++], D0FrT, D0.5, D0.6, D0.7\n"              \
-               "23:\n"                                                 \
-               "SUB    %3, %3, #16\n"                                  \
-               "24:\n"                                                 \
-               "MGETD  D0FrT, D0.5, D0.6, D0.7, [%1++]\n"              \
-               "25:\n"                                                 \
-               "MSETD  [%0++], D0FrT, D0.5, D0.6, D0.7\n"              \
-               "26:\n"                                                 \
-               "SUB    %3, %3, #16\n"                                  \
-               "27:\n"                                                 \
-               "MGETD  D0FrT, D0.5, D0.6, D0.7, [%1++]\n"              \
-               "28:\n"                                                 \
-               "MSETD  [%0++], D0FrT, D0.5, D0.6, D0.7\n"              \
-               "29:\n"                                                 \
-               "SUB    %3, %3, #16\n"                                  \
-               "30:\n"                                                 \
-               "MGETD  D0FrT, D0.5, D0.6, D0.7, [%1++]\n"              \
-               "31:\n"                                                 \
-               "MSETD  [%0++], D0FrT, D0.5, D0.6, D0.7\n"              \
-               "32:\n"                                                 \
-               "SUB    %3, %3, #16\n"                                  \
-               "DCACHE [%1+#-64], D0Ar6\n"                             \
-               "BR     $Lloop"id"\n"                                   \
+                       ".balign 8\n"                                   \
+               "       MOV     RAPF, %1\n"                             \
+               "       MSETL   [A0StP++], D0Ar6, D0FrT, D0.5, D0.6, D0.7\n" \
+               "       MOV     D0Ar6, #0\n"                            \
+               "       LSR     D1Ar5, %3, #6\n"                        \
+               "       SUB     TXRPT, D1Ar5, #2\n"                     \
+               "       MOV     RAPF, %1\n"                             \
+               "$Lloop"id":\n"                                         \
+               "       ADD     RAPF, %1, #64\n"                        \
+               "21:    MGETD   D0FrT, D0.5, D0.6, D0.7, [%1++]\n"      \
+               "22:    MSETD   [%0++], D0FrT, D0.5, D0.6, D0.7\n"      \
+               "23:    SUB     %3, %3, #16\n"                          \
+               "24:    MGETD   D0FrT, D0.5, D0.6, D0.7, [%1++]\n"      \
+               "25:    MSETD   [%0++], D0FrT, D0.5, D0.6, D0.7\n"      \
+               "26:    SUB     %3, %3, #16\n"                          \
+               "27:    MGETD   D0FrT, D0.5, D0.6, D0.7, [%1++]\n"      \
+               "28:    MSETD   [%0++], D0FrT, D0.5, D0.6, D0.7\n"      \
+               "29:    SUB     %3, %3, #16\n"                          \
+               "30:    MGETD   D0FrT, D0.5, D0.6, D0.7, [%1++]\n"      \
+               "31:    MSETD   [%0++], D0FrT, D0.5, D0.6, D0.7\n"      \
+               "32:    SUB     %3, %3, #16\n"                          \
+               "       DCACHE  [%1+#-64], D0Ar6\n"                     \
+               "       BR      $Lloop"id"\n"                           \
                                                                        \
-               "MOV    RAPF, %1\n"                                     \
-               "33:\n"                                                 \
-               "MGETD  D0FrT, D0.5, D0.6, D0.7, [%1++]\n"              \
-               "34:\n"                                                 \
-               "MSETD  [%0++], D0FrT, D0.5, D0.6, D0.7\n"              \
-               "35:\n"                                                 \
-               "SUB    %3, %3, #16\n"                                  \
-               "36:\n"                                                 \
-               "MGETD  D0FrT, D0.5, D0.6, D0.7, [%1++]\n"              \
-               "37:\n"                                                 \
-               "MSETD  [%0++], D0FrT, D0.5, D0.6, D0.7\n"              \
-               "38:\n"                                                 \
-               "SUB    %3, %3, #16\n"                                  \
-               "39:\n"                                                 \
-               "MGETD  D0FrT, D0.5, D0.6, D0.7, [%1++]\n"              \
-               "40:\n"                                                 \
-               "MSETD  [%0++], D0FrT, D0.5, D0.6, D0.7\n"              \
-               "41:\n"                                                 \
-               "SUB    %3, %3, #16\n"                                  \
-               "42:\n"                                                 \
-               "MGETD  D0FrT, D0.5, D0.6, D0.7, [%1++]\n"              \
-               "43:\n"                                                 \
-               "MSETD  [%0++], D0FrT, D0.5, D0.6, D0.7\n"              \
-               "44:\n"                                                 \
-               "SUB    %0, %0, #4\n"                                   \
-               "45:\n"                                                 \
-               "SETD   [%0++], D0.7\n"                                 \
-               "SUB    %3, %3, #16\n"                                  \
-               "1:"                                                    \
-               "DCACHE [%1+#-64], D0Ar6\n"                             \
-               "GETL    D0Ar6, D1Ar5, [A0StP+#-40]\n"                  \
-               "GETL    D0FrT, D1RtP, [A0StP+#-32]\n"                  \
-               "GETL    D0.5, D1.5, [A0StP+#-24]\n"                    \
-               "GETL    D0.6, D1.6, [A0StP+#-16]\n"                    \
-               "GETL    D0.7, D1.7, [A0StP+#-8]\n"                     \
-               "SUB A0StP, A0StP, #40\n"                               \
+               "       MOV     RAPF, %1\n"                             \
+               "33:    MGETD   D0FrT, D0.5, D0.6, D0.7, [%1++]\n"      \
+               "34:    MSETD   [%0++], D0FrT, D0.5, D0.6, D0.7\n"      \
+               "35:    SUB     %3, %3, #16\n"                          \
+               "36:    MGETD   D0FrT, D0.5, D0.6, D0.7, [%1++]\n"      \
+               "37:    MSETD   [%0++], D0FrT, D0.5, D0.6, D0.7\n"      \
+               "38:    SUB     %3, %3, #16\n"                          \
+               "39:    MGETD   D0FrT, D0.5, D0.6, D0.7, [%1++]\n"      \
+               "40:    MSETD   [%0++], D0FrT, D0.5, D0.6, D0.7\n"      \
+               "41:    SUB     %3, %3, #16\n"                          \
+               "42:    MGETD   D0FrT, D0.5, D0.6, D0.7, [%1++]\n"      \
+               "43:    MSETD   [%0++], D0FrT, D0.5, D0.6, D0.7\n"      \
+               "44:    SETD    [%0+#-4], D0.7\n"                       \
+               "       SUB     %3, %3, #16\n"                          \
+               "1:     DCACHE  [%1+#-64], D0Ar6\n"                     \
+               "       GETL    D0Ar6, D1Ar5, [A0StP+#-40]\n"           \
+               "       GETL    D0FrT, D1RtP, [A0StP+#-32]\n"           \
+               "       GETL    D0.5, D1.5, [A0StP+#-24]\n"             \
+               "       GETL    D0.6, D1.6, [A0StP+#-16]\n"             \
+               "       GETL    D0.7, D1.7, [A0StP+#-8]\n"              \
+               "       SUB A0StP, A0StP, #40\n"                        \
                "       .section .fixup,\"ax\"\n"                       \
-               "4:\n"                                                  \
-               "       ADD             %0, %0, #4\n"                   \
-               "3:\n"                                                  \
-               "       MOV     D0Ar2, TXSTATUS\n"                      \
+               "3:     MOV     D0Ar2, TXSTATUS\n"                      \
                "       MOV     D1Ar1, TXSTATUS\n"                      \
                "       AND     D1Ar1, D1Ar1, #0xFFFFF8FF\n"            \
                "       MOV     TXSTATUS, D1Ar1\n"                      \
                        FIXUP                                           \
-               "       MOVT    D0Ar2,#HI(1b)\n"                        \
-               "       JUMP    D0Ar2,#LO(1b)\n"                        \
+               "       MOVT    D0Ar2, #HI(1b)\n"                       \
+               "       JUMP    D0Ar2, #LO(1b)\n"                       \
                "       .previous\n"                                    \
                "       .section __ex_table,\"a\"\n"                    \
                "       .long 21b,3b\n"                                 \
                "       .long 42b,3b\n"                                 \
                "       .long 43b,3b\n"                                 \
                "       .long 44b,3b\n"                                 \
-               "       .long 45b,4b\n"                                 \
                "       .previous\n"                                    \
                : "=r" (to), "=r" (from), "=r" (ret), "=d" (n)          \
                : "0" (to), "1" (from), "2" (ret), "3" (n)              \
@@ -1094,6 +1044,30 @@ unsigned int __get_user_asm_d(const void __user *addr, long *err)
 }
 EXPORT_SYMBOL(__get_user_asm_d);
 
+unsigned long long __get_user_asm_l(const void __user *addr, long *err)
+{
+       register unsigned long long x asm ("D0Re0") = 0;
+       asm volatile (
+               "       GETL %0,%t0,[%2]\n"
+               "1:\n"
+               "       GETL %0,%t0,[%2]\n"
+               "2:\n"
+               "       .section .fixup,\"ax\"\n"
+               "3:     MOV     D0FrT,%3\n"
+               "       SETD    [%1],D0FrT\n"
+               "       MOVT    D0FrT,#HI(2b)\n"
+               "       JUMP    D0FrT,#LO(2b)\n"
+               "       .previous\n"
+               "       .section __ex_table,\"a\"\n"
+               "       .long 1b,3b\n"
+               "       .previous\n"
+               : "=r" (x)
+               : "r" (err), "r" (addr), "P" (-EFAULT)
+               : "D0FrT");
+       return x;
+}
+EXPORT_SYMBOL(__get_user_asm_l);
+
 long __put_user_asm_b(unsigned int x, void __user *addr)
 {
        register unsigned int err asm ("D0Re0") = 0;
index 91f4255bcb5c16e8daa25faecf377f73a7f27b9c..62ebab90924d358016c174cc19786f0ab53dc657 100644 (file)
@@ -152,6 +152,5 @@ void __init mmu_init(unsigned long mem_end)
 
                p_swapper_pg_dir++;
                addr += PGDIR_SIZE;
-               entry++;
        }
 }
index 2a120bb70e544a9502af6615fe7f65bf1f303a53..efd4983cb6972a2b774950617141b9ace491230f 100644 (file)
@@ -46,12 +46,10 @@ extern int pci_domain_nr(struct pci_bus *bus);
 extern int pci_proc_domain(struct pci_bus *bus);
 
 struct vm_area_struct;
-/* Map a range of PCI memory or I/O space for a device into user space */
-int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
-                       enum pci_mmap_state mmap_state, int write_combine);
 
 /* Tell drivers/pci/proc.c that we have pci_mmap_page_range() */
-#define HAVE_PCI_MMAP  1
+#define HAVE_PCI_MMAP          1
+#define arch_can_pci_mmap_io() 1
 
 extern int pci_legacy_read(struct pci_bus *bus, loff_t port, u32 *val,
                           size_t count);
index 1aac99f87df15841b93241f6bfad81733250b183..2178c78c7c1a6336d4a11c9619de521519245c0e 100644 (file)
@@ -2,35 +2,3 @@
 include include/uapi/asm-generic/Kbuild.asm
 
 generic-y += types.h
-
-header-y += auxvec.h
-header-y += bitsperlong.h
-header-y += byteorder.h
-header-y += elf.h
-header-y += errno.h
-header-y += fcntl.h
-header-y += ioctl.h
-header-y += ioctls.h
-header-y += ipcbuf.h
-header-y += kvm_para.h
-header-y += mman.h
-header-y += msgbuf.h
-header-y += param.h
-header-y += poll.h
-header-y += posix_types.h
-header-y += ptrace.h
-header-y += resource.h
-header-y += sembuf.h
-header-y += setup.h
-header-y += shmbuf.h
-header-y += sigcontext.h
-header-y += siginfo.h
-header-y += signal.h
-header-y += socket.h
-header-y += sockios.h
-header-y += stat.h
-header-y += statfs.h
-header-y += swab.h
-header-y += termbits.h
-header-y += termios.h
-header-y += unistd.h
index 13bc93242c0c571c71dc4afe5a7947a47bd7051d..404fb38d06b7627525998909ebfeac5653996401 100644 (file)
@@ -278,7 +278,7 @@ pgprot_t pci_phys_mem_access_prot(struct file *file,
  *
  * Returns a negative error code on failure, zero on success.
  */
-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+int pci_mmap_page_range(struct pci_dev *dev, int bar, struct vm_area_struct *vma,
                        enum pci_mmap_state mmap_state, int write_combine)
 {
        resource_size_t offset =
index 5c3f688a5232f2690007a8e92a12ba76ae11b4a5..5cef58651db0738b5428d68f5f38dbdb834204e6 100644 (file)
@@ -1,7 +1,9 @@
 # Fail on warnings - also for files referenced in subdirs
 # -Werror can be disabled for specific files using:
 # CFLAGS_<file.o> := -Wno-error
+ifeq ($(W),)
 subdir-ccflags-y := -Werror
+endif
 
 # platform specific definitions
 include arch/mips/Kbuild.platforms
index 4e9ebf65d071f95cf6bd3734664cae3498de1451..2828ecde133d97ae9b03490358b264ba89f4204a 100644 (file)
@@ -46,6 +46,7 @@ config MIPS
        select ARCH_DISCARD_MEMBLOCK
        select GENERIC_SMP_IDLE_THREAD
        select BUILDTIME_EXTABLE_SORT
+       select GENERIC_CPU_AUTOPROBE
        select GENERIC_CLOCKEVENTS
        select GENERIC_SCHED_CLOCK if !CAVIUM_OCTEON_SOC
        select GENERIC_CMOS_UPDATE
@@ -68,6 +69,7 @@ config MIPS
        select HANDLE_DOMAIN_IRQ
        select HAVE_EXIT_THREAD
        select HAVE_REGS_AND_STACK_ACCESS_API
+       select HAVE_COPY_THREAD_TLS
 
 menu "Machine selection"
 
@@ -1039,14 +1041,6 @@ config RWSEM_GENERIC_SPINLOCK
 config RWSEM_XCHGADD_ALGORITHM
        bool
 
-config ARCH_HAS_ILOG2_U32
-       bool
-       default n
-
-config ARCH_HAS_ILOG2_U64
-       bool
-       default n
-
 config GENERIC_HWEIGHT
        bool
        default y
@@ -1372,6 +1366,7 @@ config CPU_LOONGSON3
        select WEAK_ORDERING
        select WEAK_REORDERING_BEYOND_LLSC
        select MIPS_PGD_C0_CONTEXT
+       select MIPS_L1_CACHE_SHIFT_6
        select GPIOLIB
        help
                The Loongson 3 processor implements the MIPS64R2 instruction
@@ -2120,10 +2115,13 @@ config MIPS_VA_BITS_48
        bool "48 bits virtual memory"
        depends on 64BIT
        help
-         Support a maximum at least 48 bits of application virtual memory.
-         Default is 40 bits or less, depending on the CPU.
-         This option result in a small memory overhead for page tables.
-         This option is only supported with 16k and 64k page sizes.
+         Support a maximum at least 48 bits of application virtual
+         memory.  Default is 40 bits or less, depending on the CPU.
+         For page sizes 16k and above, this option results in a small
+         memory overhead for page tables.  For 4k page size, a fourth
+         level of page tables is added which imposes both a memory
+         overhead as well as slower TLB fault handling.
+
          If unsure, say N.
 
 choice
@@ -2133,7 +2131,6 @@ choice
 config PAGE_SIZE_4KB
        bool "4kB"
        depends on !CPU_LOONGSON2 && !CPU_LOONGSON3
-       depends on !MIPS_VA_BITS_48
        help
         This option select the standard 4kB Linux page size.  On some
         R3000-family processors this is the only available page size.  Using
@@ -2982,6 +2979,7 @@ config HAVE_LATENCYTOP_SUPPORT
 
 config PGTABLE_LEVELS
        int
+       default 4 if PAGE_SIZE_4KB && MIPS_VA_BITS_48
        default 3 if 64BIT && !PAGE_SIZE_64KB
        default 2
 
index 7f975b20b20c713e6225d14e3984013f57fe5026..42a97c59200f817e9ea297441ea11edb07a00232 100644 (file)
@@ -82,7 +82,7 @@ config CMDLINE_OVERRIDE
 config SB1XXX_CORELIS
        bool "Corelis Debugger"
        depends on SIBYTE_SB1xxx_SOC
-       select DEBUG_INFO
+       select DEBUG_INFO if !COMPILE_TEST
        help
          Select compile flags that produce code that can be processed by the
          Corelis mksym utility and UDB Emulator.
diff --git a/arch/mips/boot/dts/include/dt-bindings b/arch/mips/boot/dts/include/dt-bindings
deleted file mode 120000 (symlink)
index 08c00e4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../include/dt-bindings
\ No newline at end of file
index c370426a7322f9cca6ce50a03a5fec21fefe75d6..5c0b56203baef0a3f4d804850933a3031990c76c 100644 (file)
@@ -25,15 +25,6 @@ endif # CPU_CAVIUM_OCTEON
 
 if CAVIUM_OCTEON_SOC
 
-config CAVIUM_OCTEON_2ND_KERNEL
-       bool "Build the kernel to be used as a 2nd kernel on the same chip"
-       default "n"
-       help
-         This option configures this kernel to be linked at a different
-         address and use the 2nd uart for output. This allows a kernel built
-         with this option to be run at the same time as one built without this
-         option.
-
 config CAVIUM_OCTEON_LOCK_L2
        bool "Lock often used kernel code in the L2"
        default "y"
index 8a301cb12d68cf7d36b0638df1c480e8df0558ab..45be853700e6a8b1e929ed523dbd54c5610d7360 100644 (file)
@@ -4,8 +4,4 @@
 platform-$(CONFIG_CAVIUM_OCTEON_SOC)   += cavium-octeon/
 cflags-$(CONFIG_CAVIUM_OCTEON_SOC)     +=                              \
                -I$(srctree)/arch/mips/include/asm/mach-cavium-octeon
-ifdef CONFIG_CAVIUM_OCTEON_2ND_KERNEL
-load-$(CONFIG_CAVIUM_OCTEON_SOC)       += 0xffffffff84100000
-else
 load-$(CONFIG_CAVIUM_OCTEON_SOC)       += 0xffffffff81100000
-endif
index ba4753c23b0373436293aca2c904bf85e89e3d52..d18ed5af62f4a974a67cdc82dd890d503af99792 100644 (file)
@@ -152,7 +152,7 @@ static int __cvmx_helper_errata_asx_pass1(int interface, int port,
 }
 
 /**
- * Configure all of the ASX, GMX, and PKO regsiters required
+ * Configure all of the ASX, GMX, and PKO registers required
  * to get RGMII to function on the supplied interface.
  *
  * @interface: PKO Interface to configure (0 or 1)
index 89b5273299aba7ab4b97d1cc3ec86dba3f8ee217..f091c9b70603aa5cf21e7a1da1a5818c383af350 100644 (file)
@@ -4,7 +4,7 @@
  * Contact: support@caviumnetworks.com
  * This file is part of the OCTEON SDK
  *
- * Copyright (c) 2003-2010 Cavium Networks
+ * Copyright (c) 2003-2017 Cavium, Inc.
  *
  * This file is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License, Version 2, as
@@ -239,6 +239,7 @@ uint64_t cvmx_l2c_read_perf(uint32_t counter)
                else {
                        uint64_t counter = 0;
                        int tad;
+
                        for (tad = 0; tad < CVMX_L2C_TADS; tad++)
                                counter += cvmx_read_csr(CVMX_L2C_TADX_PFC0(tad));
                        return counter;
@@ -249,6 +250,7 @@ uint64_t cvmx_l2c_read_perf(uint32_t counter)
                else {
                        uint64_t counter = 0;
                        int tad;
+
                        for (tad = 0; tad < CVMX_L2C_TADS; tad++)
                                counter += cvmx_read_csr(CVMX_L2C_TADX_PFC1(tad));
                        return counter;
@@ -259,6 +261,7 @@ uint64_t cvmx_l2c_read_perf(uint32_t counter)
                else {
                        uint64_t counter = 0;
                        int tad;
+
                        for (tad = 0; tad < CVMX_L2C_TADS; tad++)
                                counter += cvmx_read_csr(CVMX_L2C_TADX_PFC2(tad));
                        return counter;
@@ -270,6 +273,7 @@ uint64_t cvmx_l2c_read_perf(uint32_t counter)
                else {
                        uint64_t counter = 0;
                        int tad;
+
                        for (tad = 0; tad < CVMX_L2C_TADS; tad++)
                                counter += cvmx_read_csr(CVMX_L2C_TADX_PFC3(tad));
                        return counter;
@@ -301,7 +305,7 @@ static void fault_in(uint64_t addr, int len)
         */
        CVMX_DCACHE_INVALIDATE;
        while (len > 0) {
-               ACCESS_ONCE(*ptr);
+               READ_ONCE(*ptr);
                len -= CVMX_CACHE_LINE_SIZE;
                ptr += CVMX_CACHE_LINE_SIZE;
        }
@@ -375,7 +379,9 @@ int cvmx_l2c_lock_line(uint64_t addr)
                if (((union cvmx_l2c_cfg)(cvmx_read_csr(CVMX_L2C_CFG))).s.idxalias) {
                        int alias_shift = CVMX_L2C_IDX_ADDR_SHIFT + 2 * CVMX_L2_SET_BITS - 1;
                        uint64_t addr_tmp = addr ^ (addr & ((1 << alias_shift) - 1)) >> CVMX_L2_SET_BITS;
+
                        lckbase.s.lck_base = addr_tmp >> 7;
+
                } else {
                        lckbase.s.lck_base = addr >> 7;
                }
@@ -435,6 +441,7 @@ void cvmx_l2c_flush(void)
                /* These may look like constants, but they aren't... */
                int assoc_shift = CVMX_L2C_TAG_ADDR_ALIAS_SHIFT;
                int set_shift = CVMX_L2C_IDX_ADDR_SHIFT;
+
                for (set = 0; set < n_set; set++) {
                        for (assoc = 0; assoc < n_assoc; assoc++) {
                                address = CVMX_ADD_SEG(CVMX_MIPS_SPACE_XKPHYS,
@@ -519,89 +526,49 @@ int cvmx_l2c_unlock_mem_region(uint64_t start, uint64_t len)
 union __cvmx_l2c_tag {
        uint64_t u64;
        struct cvmx_l2c_tag_cn50xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved:40;
-               uint64_t V:1;           /* Line valid */
-               uint64_t D:1;           /* Line dirty */
-               uint64_t L:1;           /* Line locked */
-               uint64_t U:1;           /* Use, LRU eviction */
-               uint64_t addr:20;       /* Phys mem addr (33..14) */
-#else
-               uint64_t addr:20;       /* Phys mem addr (33..14) */
-               uint64_t U:1;           /* Use, LRU eviction */
-               uint64_t L:1;           /* Line locked */
-               uint64_t D:1;           /* Line dirty */
-               uint64_t V:1;           /* Line valid */
-               uint64_t reserved:40;
-#endif
+               __BITFIELD_FIELD(uint64_t reserved:40,
+               __BITFIELD_FIELD(uint64_t V:1,          /* Line valid */
+               __BITFIELD_FIELD(uint64_t D:1,          /* Line dirty */
+               __BITFIELD_FIELD(uint64_t L:1,          /* Line locked */
+               __BITFIELD_FIELD(uint64_t U:1,          /* Use, LRU eviction */
+               __BITFIELD_FIELD(uint64_t addr:20,      /* Phys addr (33..14) */
+               ;))))))
        } cn50xx;
        struct cvmx_l2c_tag_cn30xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved:41;
-               uint64_t V:1;           /* Line valid */
-               uint64_t D:1;           /* Line dirty */
-               uint64_t L:1;           /* Line locked */
-               uint64_t U:1;           /* Use, LRU eviction */
-               uint64_t addr:19;       /* Phys mem addr (33..15) */
-#else
-               uint64_t addr:19;       /* Phys mem addr (33..15) */
-               uint64_t U:1;           /* Use, LRU eviction */
-               uint64_t L:1;           /* Line locked */
-               uint64_t D:1;           /* Line dirty */
-               uint64_t V:1;           /* Line valid */
-               uint64_t reserved:41;
-#endif
+               __BITFIELD_FIELD(uint64_t reserved:41,
+               __BITFIELD_FIELD(uint64_t V:1,          /* Line valid */
+               __BITFIELD_FIELD(uint64_t D:1,          /* Line dirty */
+               __BITFIELD_FIELD(uint64_t L:1,          /* Line locked */
+               __BITFIELD_FIELD(uint64_t U:1,          /* Use, LRU eviction */
+               __BITFIELD_FIELD(uint64_t addr:19,      /* Phys addr (33..15) */
+               ;))))))
        } cn30xx;
        struct cvmx_l2c_tag_cn31xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved:42;
-               uint64_t V:1;           /* Line valid */
-               uint64_t D:1;           /* Line dirty */
-               uint64_t L:1;           /* Line locked */
-               uint64_t U:1;           /* Use, LRU eviction */
-               uint64_t addr:18;       /* Phys mem addr (33..16) */
-#else
-               uint64_t addr:18;       /* Phys mem addr (33..16) */
-               uint64_t U:1;           /* Use, LRU eviction */
-               uint64_t L:1;           /* Line locked */
-               uint64_t D:1;           /* Line dirty */
-               uint64_t V:1;           /* Line valid */
-               uint64_t reserved:42;
-#endif
+               __BITFIELD_FIELD(uint64_t reserved:42,
+               __BITFIELD_FIELD(uint64_t V:1,          /* Line valid */
+               __BITFIELD_FIELD(uint64_t D:1,          /* Line dirty */
+               __BITFIELD_FIELD(uint64_t L:1,          /* Line locked */
+               __BITFIELD_FIELD(uint64_t U:1,          /* Use, LRU eviction */
+               __BITFIELD_FIELD(uint64_t addr:18,      /* Phys addr (33..16) */
+               ;))))))
        } cn31xx;
        struct cvmx_l2c_tag_cn38xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved:43;
-               uint64_t V:1;           /* Line valid */
-               uint64_t D:1;           /* Line dirty */
-               uint64_t L:1;           /* Line locked */
-               uint64_t U:1;           /* Use, LRU eviction */
-               uint64_t addr:17;       /* Phys mem addr (33..17) */
-#else
-               uint64_t addr:17;       /* Phys mem addr (33..17) */
-               uint64_t U:1;           /* Use, LRU eviction */
-               uint64_t L:1;           /* Line locked */
-               uint64_t D:1;           /* Line dirty */
-               uint64_t V:1;           /* Line valid */
-               uint64_t reserved:43;
-#endif
+               __BITFIELD_FIELD(uint64_t reserved:43,
+               __BITFIELD_FIELD(uint64_t V:1,          /* Line valid */
+               __BITFIELD_FIELD(uint64_t D:1,          /* Line dirty */
+               __BITFIELD_FIELD(uint64_t L:1,          /* Line locked */
+               __BITFIELD_FIELD(uint64_t U:1,          /* Use, LRU eviction */
+               __BITFIELD_FIELD(uint64_t addr:17,      /* Phys addr (33..17) */
+               ;))))))
        } cn38xx;
        struct cvmx_l2c_tag_cn58xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved:44;
-               uint64_t V:1;           /* Line valid */
-               uint64_t D:1;           /* Line dirty */
-               uint64_t L:1;           /* Line locked */
-               uint64_t U:1;           /* Use, LRU eviction */
-               uint64_t addr:16;       /* Phys mem addr (33..18) */
-#else
-               uint64_t addr:16;       /* Phys mem addr (33..18) */
-               uint64_t U:1;           /* Use, LRU eviction */
-               uint64_t L:1;           /* Line locked */
-               uint64_t D:1;           /* Line dirty */
-               uint64_t V:1;           /* Line valid */
-               uint64_t reserved:44;
-#endif
+               __BITFIELD_FIELD(uint64_t reserved:44,
+               __BITFIELD_FIELD(uint64_t V:1,          /* Line valid */
+               __BITFIELD_FIELD(uint64_t D:1,          /* Line dirty */
+               __BITFIELD_FIELD(uint64_t L:1,          /* Line locked */
+               __BITFIELD_FIELD(uint64_t U:1,          /* Use, LRU eviction */
+               __BITFIELD_FIELD(uint64_t addr:16,      /* Phys addr (33..18) */
+               ;))))))
        } cn58xx;
        struct cvmx_l2c_tag_cn58xx cn56xx;      /* 2048 sets */
        struct cvmx_l2c_tag_cn31xx cn52xx;      /* 512 sets */
@@ -629,8 +596,8 @@ static union __cvmx_l2c_tag __read_l2_tag(uint64_t assoc, uint64_t index)
        union __cvmx_l2c_tag tag_val;
        uint64_t dbg_addr = CVMX_L2C_DBG;
        unsigned long flags;
-
        union cvmx_l2c_dbg debug_val;
+
        debug_val.u64 = 0;
        /*
         * For low core count parts, the core number is always small
@@ -683,8 +650,8 @@ static union __cvmx_l2c_tag __read_l2_tag(uint64_t assoc, uint64_t index)
 union cvmx_l2c_tag cvmx_l2c_get_tag(uint32_t association, uint32_t index)
 {
        union cvmx_l2c_tag tag;
-       tag.u64 = 0;
 
+       tag.u64 = 0;
        if ((int)association >= cvmx_l2c_get_num_assoc()) {
                cvmx_dprintf("ERROR: cvmx_l2c_get_tag association out of range\n");
                return tag;
@@ -767,10 +734,12 @@ uint32_t cvmx_l2c_address_to_index(uint64_t addr)
 
        if (OCTEON_IS_MODEL(OCTEON_CN6XXX)) {
                union cvmx_l2c_ctl l2c_ctl;
+
                l2c_ctl.u64 = cvmx_read_csr(CVMX_L2C_CTL);
                indxalias = !l2c_ctl.s.disidxalias;
        } else {
                union cvmx_l2c_cfg l2c_cfg;
+
                l2c_cfg.u64 = cvmx_read_csr(CVMX_L2C_CFG);
                indxalias = l2c_cfg.s.idxalias;
        }
@@ -778,6 +747,7 @@ uint32_t cvmx_l2c_address_to_index(uint64_t addr)
        if (indxalias) {
                if (OCTEON_IS_MODEL(OCTEON_CN63XX)) {
                        uint32_t a_14_12 = (idx / (CVMX_L2C_MEMBANK_SELECT_SIZE/(1<<CVMX_L2C_IDX_ADDR_SHIFT))) & 0x7;
+
                        idx ^= idx / cvmx_l2c_get_num_sets();
                        idx ^= a_14_12;
                } else {
@@ -801,6 +771,7 @@ int cvmx_l2c_get_cache_size_bytes(void)
 int cvmx_l2c_get_set_bits(void)
 {
        int l2_set_bits;
+
        if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN58XX))
                l2_set_bits = 11;       /* 2048 sets */
        else if (OCTEON_IS_MODEL(OCTEON_CN38XX) || OCTEON_IS_MODEL(OCTEON_CN63XX))
@@ -828,6 +799,7 @@ int cvmx_l2c_get_num_sets(void)
 int cvmx_l2c_get_num_assoc(void)
 {
        int l2_assoc;
+
        if (OCTEON_IS_MODEL(OCTEON_CN56XX) ||
            OCTEON_IS_MODEL(OCTEON_CN52XX) ||
            OCTEON_IS_MODEL(OCTEON_CN58XX) ||
@@ -869,16 +841,17 @@ int cvmx_l2c_get_num_assoc(void)
                else if (mio_fus_dat3.s.l2c_crip == 1)
                        l2_assoc = 12;
        } else {
-               union cvmx_l2d_fus3 val;
-               val.u64 = cvmx_read_csr(CVMX_L2D_FUS3);
+               uint64_t l2d_fus3;
+
+               l2d_fus3 = cvmx_read_csr(CVMX_L2D_FUS3);
                /*
                 * Using shifts here, as bit position names are
                 * different for each model but they all mean the
                 * same.
                 */
-               if ((val.u64 >> 35) & 0x1)
+               if ((l2d_fus3 >> 35) & 0x1)
                        l2_assoc = l2_assoc >> 2;
-               else if ((val.u64 >> 34) & 0x1)
+               else if ((l2d_fus3 >> 34) & 0x1)
                        l2_assoc = l2_assoc >> 1;
        }
        return l2_assoc;
index d08a2bce653cf235cd280c3d499ddce5f64d0b48..341052387b49dbcd15833f0f802c8d71e7e22a00 100644 (file)
@@ -4,7 +4,7 @@
  * Contact: support@caviumnetworks.com
  * This file is part of the OCTEON SDK
  *
- * Copyright (c) 2003-2010 Cavium Networks
+ * Copyright (c) 2003-2017 Cavium, Inc.
  *
  * This file is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License, Version 2, as
@@ -63,16 +63,15 @@ static const char *__init octeon_model_get_string_buffer(uint32_t chip_id,
        char pass[4];
        int clock_mhz;
        const char *suffix;
-       union cvmx_l2d_fus3 fus3;
        int num_cores;
        union cvmx_mio_fus_dat2 fus_dat2;
        union cvmx_mio_fus_dat3 fus_dat3;
        char fuse_model[10];
        uint32_t fuse_data = 0;
+       uint64_t l2d_fus3 = 0;
 
-       fus3.u64 = 0;
        if (OCTEON_IS_MODEL(OCTEON_CN3XXX) || OCTEON_IS_MODEL(OCTEON_CN5XXX))
-               fus3.u64 = cvmx_read_csr(CVMX_L2D_FUS3);
+               l2d_fus3 = (cvmx_read_csr(CVMX_L2D_FUS3) >> 34) & 0x3;
        fus_dat2.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT2);
        fus_dat3.u64 = cvmx_read_csr(CVMX_MIO_FUS_DAT3);
        num_cores = cvmx_octeon_num_cores();
@@ -192,7 +191,7 @@ static const char *__init octeon_model_get_string_buffer(uint32_t chip_id,
        /* Now figure out the family, the first two digits */
        switch ((chip_id >> 8) & 0xff) {
        case 0:         /* CN38XX, CN37XX or CN36XX */
-               if (fus3.cn38xx.crip_512k) {
+               if (l2d_fus3) {
                        /*
                         * For some unknown reason, the 16 core one is
                         * called 37 instead of 36.
@@ -223,7 +222,7 @@ static const char *__init octeon_model_get_string_buffer(uint32_t chip_id,
                }
                break;
        case 1:         /* CN31XX or CN3020 */
-               if ((chip_id & 0x10) || fus3.cn31xx.crip_128k)
+               if ((chip_id & 0x10) || l2d_fus3)
                        family = "30";
                else
                        family = "31";
@@ -246,7 +245,7 @@ static const char *__init octeon_model_get_string_buffer(uint32_t chip_id,
        case 2:         /* CN3010 or CN3005 */
                family = "30";
                /* A chip with half cache is an 05 */
-               if (fus3.cn30xx.crip_64k)
+               if (l2d_fus3)
                        core_model = "05";
                /*
                 * This series of chips didn't follow the standard
@@ -267,7 +266,7 @@ static const char *__init octeon_model_get_string_buffer(uint32_t chip_id,
        case 3:         /* CN58XX */
                family = "58";
                /* Special case. 4 core, half cache (CP with half cache) */
-               if ((num_cores == 4) && fus3.cn58xx.crip_1024k && !strncmp(suffix, "CP", 2))
+               if ((num_cores == 4) && l2d_fus3 && !strncmp(suffix, "CP", 2))
                        core_model = "29";
 
                /* Pass 1 uses different encodings for pass numbers */
@@ -290,7 +289,7 @@ static const char *__init octeon_model_get_string_buffer(uint32_t chip_id,
                break;
        case 4:         /* CN57XX, CN56XX, CN55XX, CN54XX */
                if (fus_dat2.cn56xx.raid_en) {
-                       if (fus3.cn56xx.crip_1024k)
+                       if (l2d_fus3)
                                family = "55";
                        else
                                family = "57";
@@ -309,7 +308,7 @@ static const char *__init octeon_model_get_string_buffer(uint32_t chip_id,
                                if (fus_dat3.cn56xx.bar2_en)
                                        suffix = "NSPB2";
                        }
-                       if (fus3.cn56xx.crip_1024k)
+                       if (l2d_fus3)
                                family = "54";
                        else
                                family = "56";
@@ -319,7 +318,7 @@ static const char *__init octeon_model_get_string_buffer(uint32_t chip_id,
                family = "50";
                break;
        case 7:         /* CN52XX */
-               if (fus3.cn52xx.crip_256k)
+               if (l2d_fus3)
                        family = "51";
                else
                        family = "52";
index 3375e61daa19e5cbb9bb6fddaa8309f41d975303..8505db478904b10855eabf266f75ff9dd93e3699 100644 (file)
@@ -3,71 +3,27 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2004-2016 Cavium Networks
+ * Copyright (C) 2004-2017 Cavium, Inc.
  * Copyright (C) 2008 Wind River Systems
  */
 
-#include <linux/init.h>
-#include <linux/delay.h>
 #include <linux/etherdevice.h>
 #include <linux/of_platform.h>
 #include <linux/of_fdt.h>
 #include <linux/libfdt.h>
-#include <linux/usb/ehci_def.h>
-#include <linux/usb/ehci_pdriver.h>
-#include <linux/usb/ohci_pdriver.h>
 
 #include <asm/octeon/octeon.h>
 #include <asm/octeon/cvmx-helper-board.h>
+
+#ifdef CONFIG_USB
+#include <linux/usb/ehci_def.h>
+#include <linux/usb/ehci_pdriver.h>
+#include <linux/usb/ohci_pdriver.h>
 #include <asm/octeon/cvmx-uctlx-defs.h>
 
 #define CVMX_UAHCX_EHCI_USBCMD (CVMX_ADD_IO_SEG(0x00016F0000000010ull))
 #define CVMX_UAHCX_OHCI_USBCMD (CVMX_ADD_IO_SEG(0x00016F0000000408ull))
 
-/* Octeon Random Number Generator.  */
-static int __init octeon_rng_device_init(void)
-{
-       struct platform_device *pd;
-       int ret = 0;
-
-       struct resource rng_resources[] = {
-               {
-                       .flags  = IORESOURCE_MEM,
-                       .start  = XKPHYS_TO_PHYS(CVMX_RNM_CTL_STATUS),
-                       .end    = XKPHYS_TO_PHYS(CVMX_RNM_CTL_STATUS) + 0xf
-               }, {
-                       .flags  = IORESOURCE_MEM,
-                       .start  = cvmx_build_io_address(8, 0),
-                       .end    = cvmx_build_io_address(8, 0) + 0x7
-               }
-       };
-
-       pd = platform_device_alloc("octeon_rng", -1);
-       if (!pd) {
-               ret = -ENOMEM;
-               goto out;
-       }
-
-       ret = platform_device_add_resources(pd, rng_resources,
-                                           ARRAY_SIZE(rng_resources));
-       if (ret)
-               goto fail;
-
-       ret = platform_device_add(pd);
-       if (ret)
-               goto fail;
-
-       return ret;
-fail:
-       platform_device_put(pd);
-
-out:
-       return ret;
-}
-device_initcall(octeon_rng_device_init);
-
-#ifdef CONFIG_USB
-
 static DEFINE_MUTEX(octeon2_usb_clocks_mutex);
 
 static int octeon2_usb_clock_start_cnt;
@@ -440,8 +396,49 @@ device_initcall(octeon_ohci_device_init);
 
 #endif /* CONFIG_USB */
 
+/* Octeon Random Number Generator.  */
+static int __init octeon_rng_device_init(void)
+{
+       struct platform_device *pd;
+       int ret = 0;
 
-static struct of_device_id __initdata octeon_ids[] = {
+       struct resource rng_resources[] = {
+               {
+                       .flags  = IORESOURCE_MEM,
+                       .start  = XKPHYS_TO_PHYS(CVMX_RNM_CTL_STATUS),
+                       .end    = XKPHYS_TO_PHYS(CVMX_RNM_CTL_STATUS) + 0xf
+               }, {
+                       .flags  = IORESOURCE_MEM,
+                       .start  = cvmx_build_io_address(8, 0),
+                       .end    = cvmx_build_io_address(8, 0) + 0x7
+               }
+       };
+
+       pd = platform_device_alloc("octeon_rng", -1);
+       if (!pd) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       ret = platform_device_add_resources(pd, rng_resources,
+                                           ARRAY_SIZE(rng_resources));
+       if (ret)
+               goto fail;
+
+       ret = platform_device_add(pd);
+       if (ret)
+               goto fail;
+
+       return ret;
+fail:
+       platform_device_put(pd);
+
+out:
+       return ret;
+}
+device_initcall(octeon_rng_device_init);
+
+const struct of_device_id octeon_ids[] __initconst = {
        { .compatible = "simple-bus", },
        { .compatible = "cavium,octeon-6335-uctl", },
        { .compatible = "cavium,octeon-5750-usbn", },
@@ -481,6 +478,7 @@ static void __init octeon_fdt_set_phy(int eth, int phy_addr)
        alt_phy_handle = fdt_getprop(initial_boot_params, eth, "cavium,alt-phy-handle", NULL);
        if (alt_phy_handle) {
                u32 alt_phandle = be32_to_cpup(alt_phy_handle);
+
                alt_phy = fdt_node_offset_by_phandle(initial_boot_params, alt_phandle);
        } else {
                alt_phy = -1;
@@ -579,6 +577,7 @@ static void __init octeon_fdt_rm_ethernet(int node)
        if (phy_handle) {
                u32 ph = be32_to_cpup(phy_handle);
                int p = fdt_node_offset_by_phandle(initial_boot_params, ph);
+
                if (p >= 0)
                        fdt_nop_node(initial_boot_params, p);
        }
@@ -728,6 +727,7 @@ int __init octeon_prune_device_tree(void)
 
        for (i = 0; i < 2; i++) {
                int mgmt;
+
                snprintf(name_buffer, sizeof(name_buffer),
                         "mix%d", i);
                alias_prop = fdt_getprop(initial_boot_params, aliases,
@@ -743,6 +743,7 @@ int __init octeon_prune_device_tree(void)
                                                 name_buffer);
                        } else {
                                int phy_addr = cvmx_helper_board_get_mii_address(CVMX_HELPER_BOARD_MGMT_IPD_PORT + i);
+
                                octeon_fdt_set_phy(mgmt, phy_addr);
                        }
                }
@@ -751,6 +752,7 @@ int __init octeon_prune_device_tree(void)
        pip_path = fdt_getprop(initial_boot_params, aliases, "pip", NULL);
        if (pip_path) {
                int pip = fdt_path_offset(initial_boot_params, pip_path);
+
                if (pip  >= 0)
                        for (i = 0; i <= 4; i++)
                                octeon_fdt_pip_iface(pip, i);
@@ -767,6 +769,7 @@ int __init octeon_prune_device_tree(void)
 
        for (i = 0; i < 2; i++) {
                int i2c;
+
                snprintf(name_buffer, sizeof(name_buffer),
                         "twsi%d", i);
                alias_prop = fdt_getprop(initial_boot_params, aliases,
@@ -797,11 +800,11 @@ int __init octeon_prune_device_tree(void)
 
        for (i = 0; i < 2; i++) {
                int i2c;
+
                snprintf(name_buffer, sizeof(name_buffer),
                         "smi%d", i);
                alias_prop = fdt_getprop(initial_boot_params, aliases,
                                        name_buffer, NULL);
-
                if (alias_prop) {
                        i2c = fdt_path_offset(initial_boot_params, alias_prop);
                        if (i2c < 0)
@@ -824,6 +827,7 @@ int __init octeon_prune_device_tree(void)
 
        for (i = 0; i < 3; i++) {
                int uart;
+
                snprintf(name_buffer, sizeof(name_buffer),
                         "uart%d", i);
                alias_prop = fdt_getprop(initial_boot_params, aliases,
@@ -863,6 +867,7 @@ int __init octeon_prune_device_tree(void)
                int len;
 
                int cf = fdt_path_offset(initial_boot_params, alias_prop);
+
                base_ptr = 0;
                if (octeon_bootinfo->major_version == 1
                        && octeon_bootinfo->minor_version >= 1) {
@@ -912,6 +917,7 @@ int __init octeon_prune_device_tree(void)
                        fdt_nop_property(initial_boot_params, cf, "cavium,dma-engine-handle");
                        if (!is_16bit) {
                                __be32 width = cpu_to_be32(8);
+
                                fdt_setprop_inplace(initial_boot_params, cf,
                                                "cavium,bus-width", &width, sizeof(width));
                        }
@@ -1004,6 +1010,7 @@ end_led:
                ;
        }
 
+#ifdef CONFIG_USB
        /* OHCI/UHCI USB */
        alias_prop = fdt_getprop(initial_boot_params, aliases,
                                 "uctl", NULL);
@@ -1036,6 +1043,7 @@ end_led:
                } else  {
                        __be32 new_f[1];
                        enum cvmx_helper_board_usb_clock_types c;
+
                        c = __cvmx_helper_board_usb_get_clock_type();
                        switch (c) {
                        case USB_CLOCK_TYPE_REF_48:
@@ -1052,6 +1060,7 @@ end_led:
                        }
                }
        }
+#endif
 
        return 0;
 }
index d9dbeb0b165bcd4d6720eb2a82ca2f00af22ba2d..a8034d0dcadeb5ce361bfd23dc737a6f48d6f5b4 100644 (file)
@@ -374,14 +374,8 @@ void octeon_write_lcd(const char *s)
  */
 int octeon_get_boot_uart(void)
 {
-       int uart;
-#ifdef CONFIG_CAVIUM_OCTEON_2ND_KERNEL
-       uart = 1;
-#else
-       uart = (octeon_boot_desc_ptr->flags & OCTEON_BL_FLAG_CONSOLE_UART1) ?
+       return (octeon_boot_desc_ptr->flags & OCTEON_BL_FLAG_CONSOLE_UART1) ?
                1 : 0;
-#endif
-       return uart;
 }
 
 /**
@@ -901,14 +895,10 @@ void __init prom_init(void)
        }
 
        if (strstr(arcs_cmdline, "console=") == NULL) {
-#ifdef CONFIG_CAVIUM_OCTEON_2ND_KERNEL
-               strcat(arcs_cmdline, " console=ttyS0,115200");
-#else
                if (octeon_uart == 1)
                        strcat(arcs_cmdline, " console=ttyS1,115200");
                else
                        strcat(arcs_cmdline, " console=ttyS0,115200");
-#endif
        }
 
        mips_hpt_frequency = octeon_get_clock_rate();
index c95d94c7838bc300987040bb055e1eb597a11331..91aacf2ef26dd9572a2d2e3dac27bce59b253511 100644 (file)
@@ -36,6 +36,8 @@ CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
 CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
 CONFIG_NETFILTER=y
 # CONFIG_WIRELESS is not set
 CONFIG_DEVTMPFS=y
@@ -80,6 +82,7 @@ CONFIG_NFS_V3_ACL=y
 CONFIG_NFS_V4=y
 CONFIG_NFS_V4_1=y
 CONFIG_NFS_V4_2=y
+CONFIG_ROOT_NFS=y
 CONFIG_PRINTK_TIME=y
 CONFIG_DEBUG_INFO=y
 CONFIG_DEBUG_INFO_REDUCED=y
index 4e1761e0a09af73a8e9477e09e0ce34e7a981a0e..d88eb7a6662b35f118e2e71cfb46e0cbe0953aa8 100644 (file)
@@ -88,7 +88,7 @@ void __init which_prom(s32 magic, s32 *prom_vec)
 void __init prom_init(void)
 {
        extern void dec_machine_halt(void);
-       static char cpu_msg[] __initdata =
+       static const char cpu_msg[] __initconst =
                "Sorry, this kernel is compiled for a wrong CPU type!\n";
        s32 argc = fw_arg0;
        s32 *argv = (void *)fw_arg1;
@@ -111,7 +111,7 @@ void __init prom_init(void)
 #if defined(CONFIG_CPU_R3000)
        if ((current_cpu_type() == CPU_R4000SC) ||
            (current_cpu_type() == CPU_R4400SC)) {
-               static char r4k_msg[] __initdata =
+               static const char r4k_msg[] __initconst =
                        "Please recompile with \"CONFIG_CPU_R4x00 = y\".\n";
                printk(cpu_msg);
                printk(r4k_msg);
@@ -122,7 +122,7 @@ void __init prom_init(void)
 #if defined(CONFIG_CPU_R4X00)
        if ((current_cpu_type() == CPU_R3000) ||
            (current_cpu_type() == CPU_R3000A)) {
-               static char r3k_msg[] __initdata =
+               static const char r3k_msg[] __initconst =
                        "Please recompile with \"CONFIG_CPU_R3000 = y\".\n";
                printk(cpu_msg);
                printk(r3k_msg);
index b4db69fbc40ce212a557b235679ec0ebf2208060..fc67947ed6586c2e416b2f6cc588a4445b3761ab 100644 (file)
@@ -9,14 +9,9 @@
 #ifndef _ASM_CACHE_H
 #define _ASM_CACHE_H
 
-#include <kmalloc.h>
-
 #define L1_CACHE_SHIFT         CONFIG_MIPS_L1_CACHE_SHIFT
 #define L1_CACHE_BYTES         (1 << L1_CACHE_SHIFT)
 
-#define SMP_CACHE_SHIFT                L1_CACHE_SHIFT
-#define SMP_CACHE_BYTES                L1_CACHE_BYTES
-
 #define __read_mostly __attribute__((__section__(".data..read_mostly")))
 
 #endif /* _ASM_CACHE_H */
index be3b4c25f3359ad4e37bf013ca73d7ce5f2b9a1f..cd6efb07c9808594c143d16fcc005c2ce9afb0ea 100644 (file)
 #ifndef __ASM_CPU_INFO_H
 #define __ASM_CPU_INFO_H
 
+#include <linux/cache.h>
 #include <linux/types.h>
 
-#include <asm/cache.h>
-
 /*
  * Descriptor for a cache
  */
diff --git a/arch/mips/include/asm/cpufeature.h b/arch/mips/include/asm/cpufeature.h
new file mode 100644 (file)
index 0000000..c63ec05
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * CPU feature definitions for module loading, used by
+ * module_cpu_feature_match(), see uapi/asm/hwcap.h for MIPS CPU features.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#ifndef __ASM_CPUFEATURE_H
+#define __ASM_CPUFEATURE_H
+
+#include <uapi/asm/hwcap.h>
+#include <asm/elf.h>
+
+#define MAX_CPU_FEATURES (8 * sizeof(elf_hwcap))
+
+#define cpu_feature(x)         ilog2(HWCAP_ ## x)
+
+static inline bool cpu_have_feature(unsigned int num)
+{
+       return elf_hwcap & (1UL << num);
+}
+
+#endif /* __ASM_CPUFEATURE_H */
index 98cf40417c5d66aa12389a60ceb1ef5e55d05cd5..d38be668e3381c826db2f92e6430a250891c1513 100644 (file)
@@ -10,8 +10,6 @@
 #ifndef __ASM_MACH_RM200_CPU_FEATURE_OVERRIDES_H
 #define __ASM_MACH_RM200_CPU_FEATURE_OVERRIDES_H
 
-#include <cpu-feature-overrides.h>
-
 #define cpu_has_tlb            1
 #define cpu_has_4kex           1
 #define cpu_has_4k_cache       1
index f89775be76541c179c7f41d7da6d9e30708d8b21..f7a95d7de1409b0995f2d4624e9f5ec80abbdd6f 100644 (file)
@@ -55,7 +55,7 @@ extern int __cvmx_helper_rgmii_probe(int interface);
 extern void cvmx_helper_rgmii_internal_loopback(int port);
 
 /**
- * Configure all of the ASX, GMX, and PKO regsiters required
+ * Configure all of the ASX, GMX, and PKO registers required
  * to get RGMII to function on the supplied interface.
  *
  * @interface: PKO Interface to configure (0 or 1)
index 10262cb6ff50a43f4faa55eb0e370e5175bd4151..d045973ddb336abbe9b54b21a65b4fb1a6c4f5fe 100644 (file)
@@ -4,7 +4,7 @@
  * Contact: support@caviumnetworks.com
  * This file is part of the OCTEON SDK
  *
- * Copyright (c) 2003-2012 Cavium Networks
+ * Copyright (c) 2003-2017 Cavium, Inc.
  *
  * This file is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License, Version 2, as
 #ifndef __CVMX_L2C_DEFS_H__
 #define __CVMX_L2C_DEFS_H__
 
-#define CVMX_L2C_BIG_CTL (CVMX_ADD_IO_SEG(0x0001180080800030ull))
-#define CVMX_L2C_BST (CVMX_ADD_IO_SEG(0x00011800808007F8ull))
-#define CVMX_L2C_BST0 (CVMX_ADD_IO_SEG(0x00011800800007F8ull))
-#define CVMX_L2C_BST1 (CVMX_ADD_IO_SEG(0x00011800800007F0ull))
-#define CVMX_L2C_BST2 (CVMX_ADD_IO_SEG(0x00011800800007E8ull))
-#define CVMX_L2C_BST_MEMX(block_id) (CVMX_ADD_IO_SEG(0x0001180080C007F8ull) + ((block_id) & 3) * 0x40000ull)
-#define CVMX_L2C_BST_TDTX(block_id) (CVMX_ADD_IO_SEG(0x0001180080A007F0ull) + ((block_id) & 3) * 0x40000ull)
-#define CVMX_L2C_BST_TTGX(block_id) (CVMX_ADD_IO_SEG(0x0001180080A007F8ull) + ((block_id) & 3) * 0x40000ull)
+#include <uapi/asm/bitfield.h>
+
+#define CVMX_L2C_DBG (CVMX_ADD_IO_SEG(0x0001180080000030ull))
 #define CVMX_L2C_CFG (CVMX_ADD_IO_SEG(0x0001180080000000ull))
-#define CVMX_L2C_COP0_MAPX(offset) (CVMX_ADD_IO_SEG(0x0001180080940000ull) + ((offset) & 16383) * 8)
 #define CVMX_L2C_CTL (CVMX_ADD_IO_SEG(0x0001180080800000ull))
-#define CVMX_L2C_DBG (CVMX_ADD_IO_SEG(0x0001180080000030ull))
-#define CVMX_L2C_DUT (CVMX_ADD_IO_SEG(0x0001180080000050ull))
-#define CVMX_L2C_DUT_MAPX(offset) (CVMX_ADD_IO_SEG(0x0001180080E00000ull) + ((offset) & 8191) * 8)
-#define CVMX_L2C_ERR_TDTX(block_id) (CVMX_ADD_IO_SEG(0x0001180080A007E0ull) + ((block_id) & 3) * 0x40000ull)
-#define CVMX_L2C_ERR_TTGX(block_id) (CVMX_ADD_IO_SEG(0x0001180080A007E8ull) + ((block_id) & 3) * 0x40000ull)
-#define CVMX_L2C_ERR_VBFX(block_id) (CVMX_ADD_IO_SEG(0x0001180080C007F0ull) + ((block_id) & 3) * 0x40000ull)
-#define CVMX_L2C_ERR_XMC (CVMX_ADD_IO_SEG(0x00011800808007D8ull))
-#define CVMX_L2C_GRPWRR0 (CVMX_ADD_IO_SEG(0x00011800800000C8ull))
-#define CVMX_L2C_GRPWRR1 (CVMX_ADD_IO_SEG(0x00011800800000D0ull))
-#define CVMX_L2C_INT_EN (CVMX_ADD_IO_SEG(0x0001180080000100ull))
-#define CVMX_L2C_INT_ENA (CVMX_ADD_IO_SEG(0x0001180080800020ull))
-#define CVMX_L2C_INT_REG (CVMX_ADD_IO_SEG(0x0001180080800018ull))
-#define CVMX_L2C_INT_STAT (CVMX_ADD_IO_SEG(0x00011800800000F8ull))
-#define CVMX_L2C_IOCX_PFC(block_id) (CVMX_ADD_IO_SEG(0x0001180080800420ull))
-#define CVMX_L2C_IORX_PFC(block_id) (CVMX_ADD_IO_SEG(0x0001180080800428ull))
 #define CVMX_L2C_LCKBASE (CVMX_ADD_IO_SEG(0x0001180080000058ull))
 #define CVMX_L2C_LCKOFF (CVMX_ADD_IO_SEG(0x0001180080000060ull))
-#define CVMX_L2C_LFB0 (CVMX_ADD_IO_SEG(0x0001180080000038ull))
-#define CVMX_L2C_LFB1 (CVMX_ADD_IO_SEG(0x0001180080000040ull))
-#define CVMX_L2C_LFB2 (CVMX_ADD_IO_SEG(0x0001180080000048ull))
-#define CVMX_L2C_LFB3 (CVMX_ADD_IO_SEG(0x00011800800000B8ull))
-#define CVMX_L2C_OOB (CVMX_ADD_IO_SEG(0x00011800800000D8ull))
-#define CVMX_L2C_OOB1 (CVMX_ADD_IO_SEG(0x00011800800000E0ull))
-#define CVMX_L2C_OOB2 (CVMX_ADD_IO_SEG(0x00011800800000E8ull))
-#define CVMX_L2C_OOB3 (CVMX_ADD_IO_SEG(0x00011800800000F0ull))
+#define CVMX_L2C_PFCTL (CVMX_ADD_IO_SEG(0x0001180080000090ull))
+#define CVMX_L2C_PFCX(offset) (CVMX_ADD_IO_SEG(0x0001180080000098ull) +               \
+               ((offset) & 3) * 8)
 #define CVMX_L2C_PFC0 CVMX_L2C_PFCX(0)
 #define CVMX_L2C_PFC1 CVMX_L2C_PFCX(1)
 #define CVMX_L2C_PFC2 CVMX_L2C_PFCX(2)
 #define CVMX_L2C_PFC3 CVMX_L2C_PFCX(3)
-#define CVMX_L2C_PFCTL (CVMX_ADD_IO_SEG(0x0001180080000090ull))
-#define CVMX_L2C_PFCX(offset) (CVMX_ADD_IO_SEG(0x0001180080000098ull) + ((offset) & 3) * 8)
-#define CVMX_L2C_PPGRP (CVMX_ADD_IO_SEG(0x00011800800000C0ull))
-#define CVMX_L2C_QOS_IOBX(offset) (CVMX_ADD_IO_SEG(0x0001180080880200ull) + ((offset) & 1) * 8)
-#define CVMX_L2C_QOS_PPX(offset) (CVMX_ADD_IO_SEG(0x0001180080880000ull) + ((offset) & 31) * 8)
-#define CVMX_L2C_QOS_WGT (CVMX_ADD_IO_SEG(0x0001180080800008ull))
-#define CVMX_L2C_RSCX_PFC(offset) (CVMX_ADD_IO_SEG(0x0001180080800410ull) + ((offset) & 3) * 64)
-#define CVMX_L2C_RSDX_PFC(offset) (CVMX_ADD_IO_SEG(0x0001180080800418ull) + ((offset) & 3) * 64)
 #define CVMX_L2C_SPAR0 (CVMX_ADD_IO_SEG(0x0001180080000068ull))
 #define CVMX_L2C_SPAR1 (CVMX_ADD_IO_SEG(0x0001180080000070ull))
 #define CVMX_L2C_SPAR2 (CVMX_ADD_IO_SEG(0x0001180080000078ull))
 #define CVMX_L2C_SPAR3 (CVMX_ADD_IO_SEG(0x0001180080000080ull))
 #define CVMX_L2C_SPAR4 (CVMX_ADD_IO_SEG(0x0001180080000088ull))
-#define CVMX_L2C_TADX_ECC0(block_id) (CVMX_ADD_IO_SEG(0x0001180080A00018ull) + ((block_id) & 3) * 0x40000ull)
-#define CVMX_L2C_TADX_ECC1(block_id) (CVMX_ADD_IO_SEG(0x0001180080A00020ull) + ((block_id) & 3) * 0x40000ull)
-#define CVMX_L2C_TADX_IEN(block_id) (CVMX_ADD_IO_SEG(0x0001180080A00000ull) + ((block_id) & 3) * 0x40000ull)
-#define CVMX_L2C_TADX_INT(block_id) (CVMX_ADD_IO_SEG(0x0001180080A00028ull) + ((block_id) & 3) * 0x40000ull)
-#define CVMX_L2C_TADX_PFC0(block_id) (CVMX_ADD_IO_SEG(0x0001180080A00400ull) + ((block_id) & 3) * 0x40000ull)
-#define CVMX_L2C_TADX_PFC1(block_id) (CVMX_ADD_IO_SEG(0x0001180080A00408ull) + ((block_id) & 3) * 0x40000ull)
-#define CVMX_L2C_TADX_PFC2(block_id) (CVMX_ADD_IO_SEG(0x0001180080A00410ull) + ((block_id) & 3) * 0x40000ull)
-#define CVMX_L2C_TADX_PFC3(block_id) (CVMX_ADD_IO_SEG(0x0001180080A00418ull) + ((block_id) & 3) * 0x40000ull)
-#define CVMX_L2C_TADX_PRF(block_id) (CVMX_ADD_IO_SEG(0x0001180080A00008ull) + ((block_id) & 3) * 0x40000ull)
-#define CVMX_L2C_TADX_TAG(block_id) (CVMX_ADD_IO_SEG(0x0001180080A00010ull) + ((block_id) & 3) * 0x40000ull)
-#define CVMX_L2C_VER_ID (CVMX_ADD_IO_SEG(0x00011800808007E0ull))
-#define CVMX_L2C_VER_IOB (CVMX_ADD_IO_SEG(0x00011800808007F0ull))
-#define CVMX_L2C_VER_MSC (CVMX_ADD_IO_SEG(0x00011800808007D0ull))
-#define CVMX_L2C_VER_PP (CVMX_ADD_IO_SEG(0x00011800808007E8ull))
-#define CVMX_L2C_VIRTID_IOBX(offset) (CVMX_ADD_IO_SEG(0x00011800808C0200ull) + ((offset) & 1) * 8)
-#define CVMX_L2C_VIRTID_PPX(offset) (CVMX_ADD_IO_SEG(0x00011800808C0000ull) + ((offset) & 31) * 8)
-#define CVMX_L2C_VRT_CTL (CVMX_ADD_IO_SEG(0x0001180080800010ull))
-#define CVMX_L2C_VRT_MEMX(offset) (CVMX_ADD_IO_SEG(0x0001180080900000ull) + ((offset) & 1023) * 8)
-#define CVMX_L2C_WPAR_IOBX(offset) (CVMX_ADD_IO_SEG(0x0001180080840200ull) + ((offset) & 1) * 8)
-#define CVMX_L2C_WPAR_PPX(offset) (CVMX_ADD_IO_SEG(0x0001180080840000ull) + ((offset) & 31) * 8)
-#define CVMX_L2C_XMCX_PFC(offset) (CVMX_ADD_IO_SEG(0x0001180080800400ull) + ((offset) & 3) * 64)
-#define CVMX_L2C_XMC_CMD (CVMX_ADD_IO_SEG(0x0001180080800028ull))
-#define CVMX_L2C_XMDX_PFC(offset) (CVMX_ADD_IO_SEG(0x0001180080800408ull) + ((offset) & 3) * 64)
-
-union cvmx_l2c_big_ctl {
-       uint64_t u64;
-       struct cvmx_l2c_big_ctl_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_8_63:56;
-               uint64_t maxdram:4;
-               uint64_t reserved_1_3:3;
-               uint64_t disable:1;
-#else
-               uint64_t disable:1;
-               uint64_t reserved_1_3:3;
-               uint64_t maxdram:4;
-               uint64_t reserved_8_63:56;
-#endif
-       } s;
-       struct cvmx_l2c_big_ctl_s cn61xx;
-       struct cvmx_l2c_big_ctl_s cn63xx;
-       struct cvmx_l2c_big_ctl_s cn66xx;
-       struct cvmx_l2c_big_ctl_s cn68xx;
-       struct cvmx_l2c_big_ctl_s cn68xxp1;
-       struct cvmx_l2c_big_ctl_s cnf71xx;
-};
-
-union cvmx_l2c_bst {
-       uint64_t u64;
-       struct cvmx_l2c_bst_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t dutfl:32;
-               uint64_t rbffl:4;
-               uint64_t xbffl:4;
-               uint64_t tdpfl:4;
-               uint64_t ioccmdfl:4;
-               uint64_t iocdatfl:4;
-               uint64_t dutresfl:4;
-               uint64_t vrtfl:4;
-               uint64_t tdffl:4;
-#else
-               uint64_t tdffl:4;
-               uint64_t vrtfl:4;
-               uint64_t dutresfl:4;
-               uint64_t iocdatfl:4;
-               uint64_t ioccmdfl:4;
-               uint64_t tdpfl:4;
-               uint64_t xbffl:4;
-               uint64_t rbffl:4;
-               uint64_t dutfl:32;
-#endif
-       } s;
-       struct cvmx_l2c_bst_cn61xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_36_63:28;
-               uint64_t dutfl:4;
-               uint64_t reserved_17_31:15;
-               uint64_t ioccmdfl:1;
-               uint64_t reserved_13_15:3;
-               uint64_t iocdatfl:1;
-               uint64_t reserved_9_11:3;
-               uint64_t dutresfl:1;
-               uint64_t reserved_5_7:3;
-               uint64_t vrtfl:1;
-               uint64_t reserved_1_3:3;
-               uint64_t tdffl:1;
-#else
-               uint64_t tdffl:1;
-               uint64_t reserved_1_3:3;
-               uint64_t vrtfl:1;
-               uint64_t reserved_5_7:3;
-               uint64_t dutresfl:1;
-               uint64_t reserved_9_11:3;
-               uint64_t iocdatfl:1;
-               uint64_t reserved_13_15:3;
-               uint64_t ioccmdfl:1;
-               uint64_t reserved_17_31:15;
-               uint64_t dutfl:4;
-               uint64_t reserved_36_63:28;
-#endif
-       } cn61xx;
-       struct cvmx_l2c_bst_cn63xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_38_63:26;
-               uint64_t dutfl:6;
-               uint64_t reserved_17_31:15;
-               uint64_t ioccmdfl:1;
-               uint64_t reserved_13_15:3;
-               uint64_t iocdatfl:1;
-               uint64_t reserved_9_11:3;
-               uint64_t dutresfl:1;
-               uint64_t reserved_5_7:3;
-               uint64_t vrtfl:1;
-               uint64_t reserved_1_3:3;
-               uint64_t tdffl:1;
-#else
-               uint64_t tdffl:1;
-               uint64_t reserved_1_3:3;
-               uint64_t vrtfl:1;
-               uint64_t reserved_5_7:3;
-               uint64_t dutresfl:1;
-               uint64_t reserved_9_11:3;
-               uint64_t iocdatfl:1;
-               uint64_t reserved_13_15:3;
-               uint64_t ioccmdfl:1;
-               uint64_t reserved_17_31:15;
-               uint64_t dutfl:6;
-               uint64_t reserved_38_63:26;
-#endif
-       } cn63xx;
-       struct cvmx_l2c_bst_cn63xx cn63xxp1;
-       struct cvmx_l2c_bst_cn66xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_42_63:22;
-               uint64_t dutfl:10;
-               uint64_t reserved_17_31:15;
-               uint64_t ioccmdfl:1;
-               uint64_t reserved_13_15:3;
-               uint64_t iocdatfl:1;
-               uint64_t reserved_9_11:3;
-               uint64_t dutresfl:1;
-               uint64_t reserved_5_7:3;
-               uint64_t vrtfl:1;
-               uint64_t reserved_1_3:3;
-               uint64_t tdffl:1;
-#else
-               uint64_t tdffl:1;
-               uint64_t reserved_1_3:3;
-               uint64_t vrtfl:1;
-               uint64_t reserved_5_7:3;
-               uint64_t dutresfl:1;
-               uint64_t reserved_9_11:3;
-               uint64_t iocdatfl:1;
-               uint64_t reserved_13_15:3;
-               uint64_t ioccmdfl:1;
-               uint64_t reserved_17_31:15;
-               uint64_t dutfl:10;
-               uint64_t reserved_42_63:22;
-#endif
-       } cn66xx;
-       struct cvmx_l2c_bst_s cn68xx;
-       struct cvmx_l2c_bst_s cn68xxp1;
-       struct cvmx_l2c_bst_cn61xx cnf71xx;
-};
-
-union cvmx_l2c_bst0 {
-       uint64_t u64;
-       struct cvmx_l2c_bst0_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_24_63:40;
-               uint64_t dtbnk:1;
-               uint64_t wlb_msk:4;
-               uint64_t dtcnt:13;
-               uint64_t dt:1;
-               uint64_t stin_msk:1;
-               uint64_t wlb_dat:4;
-#else
-               uint64_t wlb_dat:4;
-               uint64_t stin_msk:1;
-               uint64_t dt:1;
-               uint64_t dtcnt:13;
-               uint64_t wlb_msk:4;
-               uint64_t dtbnk:1;
-               uint64_t reserved_24_63:40;
-#endif
-       } s;
-       struct cvmx_l2c_bst0_cn30xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_23_63:41;
-               uint64_t wlb_msk:4;
-               uint64_t reserved_15_18:4;
-               uint64_t dtcnt:9;
-               uint64_t dt:1;
-               uint64_t reserved_4_4:1;
-               uint64_t wlb_dat:4;
-#else
-               uint64_t wlb_dat:4;
-               uint64_t reserved_4_4:1;
-               uint64_t dt:1;
-               uint64_t dtcnt:9;
-               uint64_t reserved_15_18:4;
-               uint64_t wlb_msk:4;
-               uint64_t reserved_23_63:41;
-#endif
-       } cn30xx;
-       struct cvmx_l2c_bst0_cn31xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_23_63:41;
-               uint64_t wlb_msk:4;
-               uint64_t reserved_16_18:3;
-               uint64_t dtcnt:10;
-               uint64_t dt:1;
-               uint64_t stin_msk:1;
-               uint64_t wlb_dat:4;
-#else
-               uint64_t wlb_dat:4;
-               uint64_t stin_msk:1;
-               uint64_t dt:1;
-               uint64_t dtcnt:10;
-               uint64_t reserved_16_18:3;
-               uint64_t wlb_msk:4;
-               uint64_t reserved_23_63:41;
-#endif
-       } cn31xx;
-       struct cvmx_l2c_bst0_cn38xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_19_63:45;
-               uint64_t dtcnt:13;
-               uint64_t dt:1;
-               uint64_t stin_msk:1;
-               uint64_t wlb_dat:4;
-#else
-               uint64_t wlb_dat:4;
-               uint64_t stin_msk:1;
-               uint64_t dt:1;
-               uint64_t dtcnt:13;
-               uint64_t reserved_19_63:45;
-#endif
-       } cn38xx;
-       struct cvmx_l2c_bst0_cn38xx cn38xxp2;
-       struct cvmx_l2c_bst0_cn50xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_24_63:40;
-               uint64_t dtbnk:1;
-               uint64_t wlb_msk:4;
-               uint64_t reserved_16_18:3;
-               uint64_t dtcnt:10;
-               uint64_t dt:1;
-               uint64_t stin_msk:1;
-               uint64_t wlb_dat:4;
-#else
-               uint64_t wlb_dat:4;
-               uint64_t stin_msk:1;
-               uint64_t dt:1;
-               uint64_t dtcnt:10;
-               uint64_t reserved_16_18:3;
-               uint64_t wlb_msk:4;
-               uint64_t dtbnk:1;
-               uint64_t reserved_24_63:40;
-#endif
-       } cn50xx;
-       struct cvmx_l2c_bst0_cn50xx cn52xx;
-       struct cvmx_l2c_bst0_cn50xx cn52xxp1;
-       struct cvmx_l2c_bst0_s cn56xx;
-       struct cvmx_l2c_bst0_s cn56xxp1;
-       struct cvmx_l2c_bst0_s cn58xx;
-       struct cvmx_l2c_bst0_s cn58xxp1;
-};
-
-union cvmx_l2c_bst1 {
-       uint64_t u64;
-       struct cvmx_l2c_bst1_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_9_63:55;
-               uint64_t l2t:9;
-#else
-               uint64_t l2t:9;
-               uint64_t reserved_9_63:55;
-#endif
-       } s;
-       struct cvmx_l2c_bst1_cn30xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_16_63:48;
-               uint64_t vwdf:4;
-               uint64_t lrf:2;
-               uint64_t vab_vwcf:1;
-               uint64_t reserved_5_8:4;
-               uint64_t l2t:5;
-#else
-               uint64_t l2t:5;
-               uint64_t reserved_5_8:4;
-               uint64_t vab_vwcf:1;
-               uint64_t lrf:2;
-               uint64_t vwdf:4;
-               uint64_t reserved_16_63:48;
-#endif
-       } cn30xx;
-       struct cvmx_l2c_bst1_cn30xx cn31xx;
-       struct cvmx_l2c_bst1_cn38xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_16_63:48;
-               uint64_t vwdf:4;
-               uint64_t lrf:2;
-               uint64_t vab_vwcf:1;
-               uint64_t l2t:9;
-#else
-               uint64_t l2t:9;
-               uint64_t vab_vwcf:1;
-               uint64_t lrf:2;
-               uint64_t vwdf:4;
-               uint64_t reserved_16_63:48;
-#endif
-       } cn38xx;
-       struct cvmx_l2c_bst1_cn38xx cn38xxp2;
-       struct cvmx_l2c_bst1_cn38xx cn50xx;
-       struct cvmx_l2c_bst1_cn52xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_19_63:45;
-               uint64_t plc2:1;
-               uint64_t plc1:1;
-               uint64_t plc0:1;
-               uint64_t vwdf:4;
-               uint64_t reserved_11_11:1;
-               uint64_t ilc:1;
-               uint64_t vab_vwcf:1;
-               uint64_t l2t:9;
-#else
-               uint64_t l2t:9;
-               uint64_t vab_vwcf:1;
-               uint64_t ilc:1;
-               uint64_t reserved_11_11:1;
-               uint64_t vwdf:4;
-               uint64_t plc0:1;
-               uint64_t plc1:1;
-               uint64_t plc2:1;
-               uint64_t reserved_19_63:45;
-#endif
-       } cn52xx;
-       struct cvmx_l2c_bst1_cn52xx cn52xxp1;
-       struct cvmx_l2c_bst1_cn56xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_24_63:40;
-               uint64_t plc2:1;
-               uint64_t plc1:1;
-               uint64_t plc0:1;
-               uint64_t ilc:1;
-               uint64_t vwdf1:4;
-               uint64_t vwdf0:4;
-               uint64_t vab_vwcf1:1;
-               uint64_t reserved_10_10:1;
-               uint64_t vab_vwcf0:1;
-               uint64_t l2t:9;
-#else
-               uint64_t l2t:9;
-               uint64_t vab_vwcf0:1;
-               uint64_t reserved_10_10:1;
-               uint64_t vab_vwcf1:1;
-               uint64_t vwdf0:4;
-               uint64_t vwdf1:4;
-               uint64_t ilc:1;
-               uint64_t plc0:1;
-               uint64_t plc1:1;
-               uint64_t plc2:1;
-               uint64_t reserved_24_63:40;
-#endif
-       } cn56xx;
-       struct cvmx_l2c_bst1_cn56xx cn56xxp1;
-       struct cvmx_l2c_bst1_cn38xx cn58xx;
-       struct cvmx_l2c_bst1_cn38xx cn58xxp1;
-};
-
-union cvmx_l2c_bst2 {
-       uint64_t u64;
-       struct cvmx_l2c_bst2_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_16_63:48;
-               uint64_t mrb:4;
-               uint64_t reserved_4_11:8;
-               uint64_t ipcbst:1;
-               uint64_t picbst:1;
-               uint64_t xrdmsk:1;
-               uint64_t xrddat:1;
-#else
-               uint64_t xrddat:1;
-               uint64_t xrdmsk:1;
-               uint64_t picbst:1;
-               uint64_t ipcbst:1;
-               uint64_t reserved_4_11:8;
-               uint64_t mrb:4;
-               uint64_t reserved_16_63:48;
-#endif
-       } s;
-       struct cvmx_l2c_bst2_cn30xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_16_63:48;
-               uint64_t mrb:4;
-               uint64_t rmdf:4;
-               uint64_t reserved_4_7:4;
-               uint64_t ipcbst:1;
-               uint64_t reserved_2_2:1;
-               uint64_t xrdmsk:1;
-               uint64_t xrddat:1;
-#else
-               uint64_t xrddat:1;
-               uint64_t xrdmsk:1;
-               uint64_t reserved_2_2:1;
-               uint64_t ipcbst:1;
-               uint64_t reserved_4_7:4;
-               uint64_t rmdf:4;
-               uint64_t mrb:4;
-               uint64_t reserved_16_63:48;
-#endif
-       } cn30xx;
-       struct cvmx_l2c_bst2_cn30xx cn31xx;
-       struct cvmx_l2c_bst2_cn38xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_16_63:48;
-               uint64_t mrb:4;
-               uint64_t rmdf:4;
-               uint64_t rhdf:4;
-               uint64_t ipcbst:1;
-               uint64_t picbst:1;
-               uint64_t xrdmsk:1;
-               uint64_t xrddat:1;
-#else
-               uint64_t xrddat:1;
-               uint64_t xrdmsk:1;
-               uint64_t picbst:1;
-               uint64_t ipcbst:1;
-               uint64_t rhdf:4;
-               uint64_t rmdf:4;
-               uint64_t mrb:4;
-               uint64_t reserved_16_63:48;
-#endif
-       } cn38xx;
-       struct cvmx_l2c_bst2_cn38xx cn38xxp2;
-       struct cvmx_l2c_bst2_cn30xx cn50xx;
-       struct cvmx_l2c_bst2_cn30xx cn52xx;
-       struct cvmx_l2c_bst2_cn30xx cn52xxp1;
-       struct cvmx_l2c_bst2_cn56xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_16_63:48;
-               uint64_t mrb:4;
-               uint64_t rmdb:4;
-               uint64_t rhdb:4;
-               uint64_t ipcbst:1;
-               uint64_t picbst:1;
-               uint64_t xrdmsk:1;
-               uint64_t xrddat:1;
-#else
-               uint64_t xrddat:1;
-               uint64_t xrdmsk:1;
-               uint64_t picbst:1;
-               uint64_t ipcbst:1;
-               uint64_t rhdb:4;
-               uint64_t rmdb:4;
-               uint64_t mrb:4;
-               uint64_t reserved_16_63:48;
-#endif
-       } cn56xx;
-       struct cvmx_l2c_bst2_cn56xx cn56xxp1;
-       struct cvmx_l2c_bst2_cn56xx cn58xx;
-       struct cvmx_l2c_bst2_cn56xx cn58xxp1;
-};
-
-union cvmx_l2c_bst_memx {
-       uint64_t u64;
-       struct cvmx_l2c_bst_memx_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t start_bist:1;
-               uint64_t clear_bist:1;
-               uint64_t reserved_5_61:57;
-               uint64_t rdffl:1;
-               uint64_t vbffl:4;
-#else
-               uint64_t vbffl:4;
-               uint64_t rdffl:1;
-               uint64_t reserved_5_61:57;
-               uint64_t clear_bist:1;
-               uint64_t start_bist:1;
-#endif
-       } s;
-       struct cvmx_l2c_bst_memx_s cn61xx;
-       struct cvmx_l2c_bst_memx_s cn63xx;
-       struct cvmx_l2c_bst_memx_s cn63xxp1;
-       struct cvmx_l2c_bst_memx_s cn66xx;
-       struct cvmx_l2c_bst_memx_s cn68xx;
-       struct cvmx_l2c_bst_memx_s cn68xxp1;
-       struct cvmx_l2c_bst_memx_s cnf71xx;
-};
-
-union cvmx_l2c_bst_tdtx {
-       uint64_t u64;
-       struct cvmx_l2c_bst_tdtx_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t fbfrspfl:8;
-               uint64_t sbffl:8;
-               uint64_t fbffl:8;
-               uint64_t l2dfl:8;
-#else
-               uint64_t l2dfl:8;
-               uint64_t fbffl:8;
-               uint64_t sbffl:8;
-               uint64_t fbfrspfl:8;
-               uint64_t reserved_32_63:32;
-#endif
-       } s;
-       struct cvmx_l2c_bst_tdtx_s cn61xx;
-       struct cvmx_l2c_bst_tdtx_s cn63xx;
-       struct cvmx_l2c_bst_tdtx_cn63xxp1 {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_24_63:40;
-               uint64_t sbffl:8;
-               uint64_t fbffl:8;
-               uint64_t l2dfl:8;
-#else
-               uint64_t l2dfl:8;
-               uint64_t fbffl:8;
-               uint64_t sbffl:8;
-               uint64_t reserved_24_63:40;
-#endif
-       } cn63xxp1;
-       struct cvmx_l2c_bst_tdtx_s cn66xx;
-       struct cvmx_l2c_bst_tdtx_s cn68xx;
-       struct cvmx_l2c_bst_tdtx_s cn68xxp1;
-       struct cvmx_l2c_bst_tdtx_s cnf71xx;
-};
+#define CVMX_L2C_TADX_PFCX(offset, block_id)                                  \
+               (CVMX_ADD_IO_SEG(0x0001180080A00400ull) + (((offset) & 3) +    \
+               ((block_id) & 7) * 0x8000ull) * 8)
+#define CVMX_L2C_TADX_PFC0(block_id) (CVMX_ADD_IO_SEG(0x0001180080A00400ull) + \
+               ((block_id) & 3) * 0x40000ull)
+#define CVMX_L2C_TADX_PFC1(block_id) (CVMX_ADD_IO_SEG(0x0001180080A00408ull) + \
+               ((block_id) & 3) * 0x40000ull)
+#define CVMX_L2C_TADX_PFC2(block_id) (CVMX_ADD_IO_SEG(0x0001180080A00410ull) + \
+               ((block_id) & 3) * 0x40000ull)
+#define CVMX_L2C_TADX_PFC3(block_id) (CVMX_ADD_IO_SEG(0x0001180080A00418ull) + \
+               ((block_id) & 3) * 0x40000ull)
+#define CVMX_L2C_TADX_PRF(offset) (CVMX_ADD_IO_SEG(0x0001180080A00008ull)    + \
+               ((offset) & 7) * 0x40000ull)
+#define CVMX_L2C_TADX_TAG(block_id) (CVMX_ADD_IO_SEG(0x0001180080A00010ull)  + \
+               ((block_id) & 3) * 0x40000ull)
+#define CVMX_L2C_WPAR_IOBX(offset) (CVMX_ADD_IO_SEG(0x0001180080840200ull)   + \
+               ((offset) & 1) * 8)
+#define CVMX_L2C_WPAR_PPX(offset) (CVMX_ADD_IO_SEG(0x0001180080840000ull)    + \
+               ((offset) & 31) * 8)
+#define CVMX_L2D_FUS3 (CVMX_ADD_IO_SEG(0x00011800800007B8ull))
 
-union cvmx_l2c_bst_ttgx {
-       uint64_t u64;
-       struct cvmx_l2c_bst_ttgx_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_17_63:47;
-               uint64_t lrufl:1;
-               uint64_t tagfl:16;
-#else
-               uint64_t tagfl:16;
-               uint64_t lrufl:1;
-               uint64_t reserved_17_63:47;
-#endif
-       } s;
-       struct cvmx_l2c_bst_ttgx_s cn61xx;
-       struct cvmx_l2c_bst_ttgx_s cn63xx;
-       struct cvmx_l2c_bst_ttgx_s cn63xxp1;
-       struct cvmx_l2c_bst_ttgx_s cn66xx;
-       struct cvmx_l2c_bst_ttgx_s cn68xx;
-       struct cvmx_l2c_bst_ttgx_s cn68xxp1;
-       struct cvmx_l2c_bst_ttgx_s cnf71xx;
-};
 
 union cvmx_l2c_cfg {
        uint64_t u64;
        struct cvmx_l2c_cfg_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_20_63:44;
-               uint64_t bstrun:1;
-               uint64_t lbist:1;
-               uint64_t xor_bank:1;
-               uint64_t dpres1:1;
-               uint64_t dpres0:1;
-               uint64_t dfill_dis:1;
-               uint64_t fpexp:4;
-               uint64_t fpempty:1;
-               uint64_t fpen:1;
-               uint64_t idxalias:1;
-               uint64_t mwf_crd:4;
-               uint64_t rsp_arb_mode:1;
-               uint64_t rfb_arb_mode:1;
-               uint64_t lrf_arb_mode:1;
-#else
-               uint64_t lrf_arb_mode:1;
-               uint64_t rfb_arb_mode:1;
-               uint64_t rsp_arb_mode:1;
-               uint64_t mwf_crd:4;
-               uint64_t idxalias:1;
-               uint64_t fpen:1;
-               uint64_t fpempty:1;
-               uint64_t fpexp:4;
-               uint64_t dfill_dis:1;
-               uint64_t dpres0:1;
-               uint64_t dpres1:1;
-               uint64_t xor_bank:1;
-               uint64_t lbist:1;
-               uint64_t bstrun:1;
-               uint64_t reserved_20_63:44;
-#endif
+               __BITFIELD_FIELD(uint64_t reserved_20_63:44,
+               __BITFIELD_FIELD(uint64_t bstrun:1,
+               __BITFIELD_FIELD(uint64_t lbist:1,
+               __BITFIELD_FIELD(uint64_t xor_bank:1,
+               __BITFIELD_FIELD(uint64_t dpres1:1,
+               __BITFIELD_FIELD(uint64_t dpres0:1,
+               __BITFIELD_FIELD(uint64_t dfill_dis:1,
+               __BITFIELD_FIELD(uint64_t fpexp:4,
+               __BITFIELD_FIELD(uint64_t fpempty:1,
+               __BITFIELD_FIELD(uint64_t fpen:1,
+               __BITFIELD_FIELD(uint64_t idxalias:1,
+               __BITFIELD_FIELD(uint64_t mwf_crd:4,
+               __BITFIELD_FIELD(uint64_t rsp_arb_mode:1,
+               __BITFIELD_FIELD(uint64_t rfb_arb_mode:1,
+               __BITFIELD_FIELD(uint64_t lrf_arb_mode:1,
+               ;)))))))))))))))
        } s;
-       struct cvmx_l2c_cfg_cn30xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_14_63:50;
-               uint64_t fpexp:4;
-               uint64_t fpempty:1;
-               uint64_t fpen:1;
-               uint64_t idxalias:1;
-               uint64_t mwf_crd:4;
-               uint64_t rsp_arb_mode:1;
-               uint64_t rfb_arb_mode:1;
-               uint64_t lrf_arb_mode:1;
-#else
-               uint64_t lrf_arb_mode:1;
-               uint64_t rfb_arb_mode:1;
-               uint64_t rsp_arb_mode:1;
-               uint64_t mwf_crd:4;
-               uint64_t idxalias:1;
-               uint64_t fpen:1;
-               uint64_t fpempty:1;
-               uint64_t fpexp:4;
-               uint64_t reserved_14_63:50;
-#endif
-       } cn30xx;
-       struct cvmx_l2c_cfg_cn30xx cn31xx;
-       struct cvmx_l2c_cfg_cn30xx cn38xx;
-       struct cvmx_l2c_cfg_cn30xx cn38xxp2;
-       struct cvmx_l2c_cfg_cn50xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_20_63:44;
-               uint64_t bstrun:1;
-               uint64_t lbist:1;
-               uint64_t reserved_14_17:4;
-               uint64_t fpexp:4;
-               uint64_t fpempty:1;
-               uint64_t fpen:1;
-               uint64_t idxalias:1;
-               uint64_t mwf_crd:4;
-               uint64_t rsp_arb_mode:1;
-               uint64_t rfb_arb_mode:1;
-               uint64_t lrf_arb_mode:1;
-#else
-               uint64_t lrf_arb_mode:1;
-               uint64_t rfb_arb_mode:1;
-               uint64_t rsp_arb_mode:1;
-               uint64_t mwf_crd:4;
-               uint64_t idxalias:1;
-               uint64_t fpen:1;
-               uint64_t fpempty:1;
-               uint64_t fpexp:4;
-               uint64_t reserved_14_17:4;
-               uint64_t lbist:1;
-               uint64_t bstrun:1;
-               uint64_t reserved_20_63:44;
-#endif
-       } cn50xx;
-       struct cvmx_l2c_cfg_cn50xx cn52xx;
-       struct cvmx_l2c_cfg_cn50xx cn52xxp1;
-       struct cvmx_l2c_cfg_s cn56xx;
-       struct cvmx_l2c_cfg_s cn56xxp1;
-       struct cvmx_l2c_cfg_cn58xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_20_63:44;
-               uint64_t bstrun:1;
-               uint64_t lbist:1;
-               uint64_t reserved_15_17:3;
-               uint64_t dfill_dis:1;
-               uint64_t fpexp:4;
-               uint64_t fpempty:1;
-               uint64_t fpen:1;
-               uint64_t idxalias:1;
-               uint64_t mwf_crd:4;
-               uint64_t rsp_arb_mode:1;
-               uint64_t rfb_arb_mode:1;
-               uint64_t lrf_arb_mode:1;
-#else
-               uint64_t lrf_arb_mode:1;
-               uint64_t rfb_arb_mode:1;
-               uint64_t rsp_arb_mode:1;
-               uint64_t mwf_crd:4;
-               uint64_t idxalias:1;
-               uint64_t fpen:1;
-               uint64_t fpempty:1;
-               uint64_t fpexp:4;
-               uint64_t dfill_dis:1;
-               uint64_t reserved_15_17:3;
-               uint64_t lbist:1;
-               uint64_t bstrun:1;
-               uint64_t reserved_20_63:44;
-#endif
-       } cn58xx;
-       struct cvmx_l2c_cfg_cn58xxp1 {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_15_63:49;
-               uint64_t dfill_dis:1;
-               uint64_t fpexp:4;
-               uint64_t fpempty:1;
-               uint64_t fpen:1;
-               uint64_t idxalias:1;
-               uint64_t mwf_crd:4;
-               uint64_t rsp_arb_mode:1;
-               uint64_t rfb_arb_mode:1;
-               uint64_t lrf_arb_mode:1;
-#else
-               uint64_t lrf_arb_mode:1;
-               uint64_t rfb_arb_mode:1;
-               uint64_t rsp_arb_mode:1;
-               uint64_t mwf_crd:4;
-               uint64_t idxalias:1;
-               uint64_t fpen:1;
-               uint64_t fpempty:1;
-               uint64_t fpexp:4;
-               uint64_t dfill_dis:1;
-               uint64_t reserved_15_63:49;
-#endif
-       } cn58xxp1;
-};
-
-union cvmx_l2c_cop0_mapx {
-       uint64_t u64;
-       struct cvmx_l2c_cop0_mapx_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t data:64;
-#else
-               uint64_t data:64;
-#endif
-       } s;
-       struct cvmx_l2c_cop0_mapx_s cn61xx;
-       struct cvmx_l2c_cop0_mapx_s cn63xx;
-       struct cvmx_l2c_cop0_mapx_s cn63xxp1;
-       struct cvmx_l2c_cop0_mapx_s cn66xx;
-       struct cvmx_l2c_cop0_mapx_s cn68xx;
-       struct cvmx_l2c_cop0_mapx_s cn68xxp1;
-       struct cvmx_l2c_cop0_mapx_s cnf71xx;
 };
 
 union cvmx_l2c_ctl {
        uint64_t u64;
        struct cvmx_l2c_ctl_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_30_63:34;
-               uint64_t sepcmt:1;
-               uint64_t rdf_fast:1;
-               uint64_t disstgl2i:1;
-               uint64_t l2dfsbe:1;
-               uint64_t l2dfdbe:1;
-               uint64_t discclk:1;
-               uint64_t maxvab:4;
-               uint64_t maxlfb:4;
-               uint64_t rsp_arb_mode:1;
-               uint64_t xmc_arb_mode:1;
-               uint64_t ef_ena:1;
-               uint64_t ef_cnt:7;
-               uint64_t vab_thresh:4;
-               uint64_t disecc:1;
-               uint64_t disidxalias:1;
-#else
-               uint64_t disidxalias:1;
-               uint64_t disecc:1;
-               uint64_t vab_thresh:4;
-               uint64_t ef_cnt:7;
-               uint64_t ef_ena:1;
-               uint64_t xmc_arb_mode:1;
-               uint64_t rsp_arb_mode:1;
-               uint64_t maxlfb:4;
-               uint64_t maxvab:4;
-               uint64_t discclk:1;
-               uint64_t l2dfdbe:1;
-               uint64_t l2dfsbe:1;
-               uint64_t disstgl2i:1;
-               uint64_t rdf_fast:1;
-               uint64_t sepcmt:1;
-               uint64_t reserved_30_63:34;
-#endif
+               __BITFIELD_FIELD(uint64_t reserved_30_63:34,
+               __BITFIELD_FIELD(uint64_t sepcmt:1,
+               __BITFIELD_FIELD(uint64_t rdf_fast:1,
+               __BITFIELD_FIELD(uint64_t disstgl2i:1,
+               __BITFIELD_FIELD(uint64_t l2dfsbe:1,
+               __BITFIELD_FIELD(uint64_t l2dfdbe:1,
+               __BITFIELD_FIELD(uint64_t discclk:1,
+               __BITFIELD_FIELD(uint64_t maxvab:4,
+               __BITFIELD_FIELD(uint64_t maxlfb:4,
+               __BITFIELD_FIELD(uint64_t rsp_arb_mode:1,
+               __BITFIELD_FIELD(uint64_t xmc_arb_mode:1,
+               __BITFIELD_FIELD(uint64_t ef_ena:1,
+               __BITFIELD_FIELD(uint64_t ef_cnt:7,
+               __BITFIELD_FIELD(uint64_t vab_thresh:4,
+               __BITFIELD_FIELD(uint64_t disecc:1,
+               __BITFIELD_FIELD(uint64_t disidxalias:1,
+               ;))))))))))))))))
        } s;
-       struct cvmx_l2c_ctl_cn61xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_29_63:35;
-               uint64_t rdf_fast:1;
-               uint64_t disstgl2i:1;
-               uint64_t l2dfsbe:1;
-               uint64_t l2dfdbe:1;
-               uint64_t discclk:1;
-               uint64_t maxvab:4;
-               uint64_t maxlfb:4;
-               uint64_t rsp_arb_mode:1;
-               uint64_t xmc_arb_mode:1;
-               uint64_t ef_ena:1;
-               uint64_t ef_cnt:7;
-               uint64_t vab_thresh:4;
-               uint64_t disecc:1;
-               uint64_t disidxalias:1;
-#else
-               uint64_t disidxalias:1;
-               uint64_t disecc:1;
-               uint64_t vab_thresh:4;
-               uint64_t ef_cnt:7;
-               uint64_t ef_ena:1;
-               uint64_t xmc_arb_mode:1;
-               uint64_t rsp_arb_mode:1;
-               uint64_t maxlfb:4;
-               uint64_t maxvab:4;
-               uint64_t discclk:1;
-               uint64_t l2dfdbe:1;
-               uint64_t l2dfsbe:1;
-               uint64_t disstgl2i:1;
-               uint64_t rdf_fast:1;
-               uint64_t reserved_29_63:35;
-#endif
-       } cn61xx;
-       struct cvmx_l2c_ctl_cn63xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_28_63:36;
-               uint64_t disstgl2i:1;
-               uint64_t l2dfsbe:1;
-               uint64_t l2dfdbe:1;
-               uint64_t discclk:1;
-               uint64_t maxvab:4;
-               uint64_t maxlfb:4;
-               uint64_t rsp_arb_mode:1;
-               uint64_t xmc_arb_mode:1;
-               uint64_t ef_ena:1;
-               uint64_t ef_cnt:7;
-               uint64_t vab_thresh:4;
-               uint64_t disecc:1;
-               uint64_t disidxalias:1;
-#else
-               uint64_t disidxalias:1;
-               uint64_t disecc:1;
-               uint64_t vab_thresh:4;
-               uint64_t ef_cnt:7;
-               uint64_t ef_ena:1;
-               uint64_t xmc_arb_mode:1;
-               uint64_t rsp_arb_mode:1;
-               uint64_t maxlfb:4;
-               uint64_t maxvab:4;
-               uint64_t discclk:1;
-               uint64_t l2dfdbe:1;
-               uint64_t l2dfsbe:1;
-               uint64_t disstgl2i:1;
-               uint64_t reserved_28_63:36;
-#endif
-       } cn63xx;
-       struct cvmx_l2c_ctl_cn63xxp1 {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_25_63:39;
-               uint64_t discclk:1;
-               uint64_t maxvab:4;
-               uint64_t maxlfb:4;
-               uint64_t rsp_arb_mode:1;
-               uint64_t xmc_arb_mode:1;
-               uint64_t ef_ena:1;
-               uint64_t ef_cnt:7;
-               uint64_t vab_thresh:4;
-               uint64_t disecc:1;
-               uint64_t disidxalias:1;
-#else
-               uint64_t disidxalias:1;
-               uint64_t disecc:1;
-               uint64_t vab_thresh:4;
-               uint64_t ef_cnt:7;
-               uint64_t ef_ena:1;
-               uint64_t xmc_arb_mode:1;
-               uint64_t rsp_arb_mode:1;
-               uint64_t maxlfb:4;
-               uint64_t maxvab:4;
-               uint64_t discclk:1;
-               uint64_t reserved_25_63:39;
-#endif
-       } cn63xxp1;
-       struct cvmx_l2c_ctl_cn61xx cn66xx;
-       struct cvmx_l2c_ctl_s cn68xx;
-       struct cvmx_l2c_ctl_cn63xx cn68xxp1;
-       struct cvmx_l2c_ctl_cn61xx cnf71xx;
 };
 
 union cvmx_l2c_dbg {
        uint64_t u64;
        struct cvmx_l2c_dbg_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_15_63:49;
-               uint64_t lfb_enum:4;
-               uint64_t lfb_dmp:1;
-               uint64_t ppnum:4;
-               uint64_t set:3;
-               uint64_t finv:1;
-               uint64_t l2d:1;
-               uint64_t l2t:1;
-#else
-               uint64_t l2t:1;
-               uint64_t l2d:1;
-               uint64_t finv:1;
-               uint64_t set:3;
-               uint64_t ppnum:4;
-               uint64_t lfb_dmp:1;
-               uint64_t lfb_enum:4;
-               uint64_t reserved_15_63:49;
-#endif
-       } s;
-       struct cvmx_l2c_dbg_cn30xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_13_63:51;
-               uint64_t lfb_enum:2;
-               uint64_t lfb_dmp:1;
-               uint64_t reserved_7_9:3;
-               uint64_t ppnum:1;
-               uint64_t reserved_5_5:1;
-               uint64_t set:2;
-               uint64_t finv:1;
-               uint64_t l2d:1;
-               uint64_t l2t:1;
-#else
-               uint64_t l2t:1;
-               uint64_t l2d:1;
-               uint64_t finv:1;
-               uint64_t set:2;
-               uint64_t reserved_5_5:1;
-               uint64_t ppnum:1;
-               uint64_t reserved_7_9:3;
-               uint64_t lfb_dmp:1;
-               uint64_t lfb_enum:2;
-               uint64_t reserved_13_63:51;
-#endif
-       } cn30xx;
-       struct cvmx_l2c_dbg_cn31xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_14_63:50;
-               uint64_t lfb_enum:3;
-               uint64_t lfb_dmp:1;
-               uint64_t reserved_7_9:3;
-               uint64_t ppnum:1;
-               uint64_t reserved_5_5:1;
-               uint64_t set:2;
-               uint64_t finv:1;
-               uint64_t l2d:1;
-               uint64_t l2t:1;
-#else
-               uint64_t l2t:1;
-               uint64_t l2d:1;
-               uint64_t finv:1;
-               uint64_t set:2;
-               uint64_t reserved_5_5:1;
-               uint64_t ppnum:1;
-               uint64_t reserved_7_9:3;
-               uint64_t lfb_dmp:1;
-               uint64_t lfb_enum:3;
-               uint64_t reserved_14_63:50;
-#endif
-       } cn31xx;
-       struct cvmx_l2c_dbg_s cn38xx;
-       struct cvmx_l2c_dbg_s cn38xxp2;
-       struct cvmx_l2c_dbg_cn50xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_14_63:50;
-               uint64_t lfb_enum:3;
-               uint64_t lfb_dmp:1;
-               uint64_t reserved_7_9:3;
-               uint64_t ppnum:1;
-               uint64_t set:3;
-               uint64_t finv:1;
-               uint64_t l2d:1;
-               uint64_t l2t:1;
-#else
-               uint64_t l2t:1;
-               uint64_t l2d:1;
-               uint64_t finv:1;
-               uint64_t set:3;
-               uint64_t ppnum:1;
-               uint64_t reserved_7_9:3;
-               uint64_t lfb_dmp:1;
-               uint64_t lfb_enum:3;
-               uint64_t reserved_14_63:50;
-#endif
-       } cn50xx;
-       struct cvmx_l2c_dbg_cn52xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_14_63:50;
-               uint64_t lfb_enum:3;
-               uint64_t lfb_dmp:1;
-               uint64_t reserved_8_9:2;
-               uint64_t ppnum:2;
-               uint64_t set:3;
-               uint64_t finv:1;
-               uint64_t l2d:1;
-               uint64_t l2t:1;
-#else
-               uint64_t l2t:1;
-               uint64_t l2d:1;
-               uint64_t finv:1;
-               uint64_t set:3;
-               uint64_t ppnum:2;
-               uint64_t reserved_8_9:2;
-               uint64_t lfb_dmp:1;
-               uint64_t lfb_enum:3;
-               uint64_t reserved_14_63:50;
-#endif
-       } cn52xx;
-       struct cvmx_l2c_dbg_cn52xx cn52xxp1;
-       struct cvmx_l2c_dbg_s cn56xx;
-       struct cvmx_l2c_dbg_s cn56xxp1;
-       struct cvmx_l2c_dbg_s cn58xx;
-       struct cvmx_l2c_dbg_s cn58xxp1;
-};
-
-union cvmx_l2c_dut {
-       uint64_t u64;
-       struct cvmx_l2c_dut_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t dtena:1;
-               uint64_t reserved_30_30:1;
-               uint64_t dt_vld:1;
-               uint64_t dt_tag:29;
-#else
-               uint64_t dt_tag:29;
-               uint64_t dt_vld:1;
-               uint64_t reserved_30_30:1;
-               uint64_t dtena:1;
-               uint64_t reserved_32_63:32;
-#endif
-       } s;
-       struct cvmx_l2c_dut_s cn30xx;
-       struct cvmx_l2c_dut_s cn31xx;
-       struct cvmx_l2c_dut_s cn38xx;
-       struct cvmx_l2c_dut_s cn38xxp2;
-       struct cvmx_l2c_dut_s cn50xx;
-       struct cvmx_l2c_dut_s cn52xx;
-       struct cvmx_l2c_dut_s cn52xxp1;
-       struct cvmx_l2c_dut_s cn56xx;
-       struct cvmx_l2c_dut_s cn56xxp1;
-       struct cvmx_l2c_dut_s cn58xx;
-       struct cvmx_l2c_dut_s cn58xxp1;
-};
-
-union cvmx_l2c_dut_mapx {
-       uint64_t u64;
-       struct cvmx_l2c_dut_mapx_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_38_63:26;
-               uint64_t tag:28;
-               uint64_t reserved_1_9:9;
-               uint64_t valid:1;
-#else
-               uint64_t valid:1;
-               uint64_t reserved_1_9:9;
-               uint64_t tag:28;
-               uint64_t reserved_38_63:26;
-#endif
-       } s;
-       struct cvmx_l2c_dut_mapx_s cn61xx;
-       struct cvmx_l2c_dut_mapx_s cn63xx;
-       struct cvmx_l2c_dut_mapx_s cn63xxp1;
-       struct cvmx_l2c_dut_mapx_s cn66xx;
-       struct cvmx_l2c_dut_mapx_s cn68xx;
-       struct cvmx_l2c_dut_mapx_s cn68xxp1;
-       struct cvmx_l2c_dut_mapx_s cnf71xx;
-};
-
-union cvmx_l2c_err_tdtx {
-       uint64_t u64;
-       struct cvmx_l2c_err_tdtx_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t dbe:1;
-               uint64_t sbe:1;
-               uint64_t vdbe:1;
-               uint64_t vsbe:1;
-               uint64_t syn:10;
-               uint64_t reserved_22_49:28;
-               uint64_t wayidx:18;
-               uint64_t reserved_2_3:2;
-               uint64_t type:2;
-#else
-               uint64_t type:2;
-               uint64_t reserved_2_3:2;
-               uint64_t wayidx:18;
-               uint64_t reserved_22_49:28;
-               uint64_t syn:10;
-               uint64_t vsbe:1;
-               uint64_t vdbe:1;
-               uint64_t sbe:1;
-               uint64_t dbe:1;
-#endif
-       } s;
-       struct cvmx_l2c_err_tdtx_cn61xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t dbe:1;
-               uint64_t sbe:1;
-               uint64_t vdbe:1;
-               uint64_t vsbe:1;
-               uint64_t syn:10;
-               uint64_t reserved_20_49:30;
-               uint64_t wayidx:16;
-               uint64_t reserved_2_3:2;
-               uint64_t type:2;
-#else
-               uint64_t type:2;
-               uint64_t reserved_2_3:2;
-               uint64_t wayidx:16;
-               uint64_t reserved_20_49:30;
-               uint64_t syn:10;
-               uint64_t vsbe:1;
-               uint64_t vdbe:1;
-               uint64_t sbe:1;
-               uint64_t dbe:1;
-#endif
-       } cn61xx;
-       struct cvmx_l2c_err_tdtx_cn63xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t dbe:1;
-               uint64_t sbe:1;
-               uint64_t vdbe:1;
-               uint64_t vsbe:1;
-               uint64_t syn:10;
-               uint64_t reserved_21_49:29;
-               uint64_t wayidx:17;
-               uint64_t reserved_2_3:2;
-               uint64_t type:2;
-#else
-               uint64_t type:2;
-               uint64_t reserved_2_3:2;
-               uint64_t wayidx:17;
-               uint64_t reserved_21_49:29;
-               uint64_t syn:10;
-               uint64_t vsbe:1;
-               uint64_t vdbe:1;
-               uint64_t sbe:1;
-               uint64_t dbe:1;
-#endif
-       } cn63xx;
-       struct cvmx_l2c_err_tdtx_cn63xx cn63xxp1;
-       struct cvmx_l2c_err_tdtx_cn63xx cn66xx;
-       struct cvmx_l2c_err_tdtx_s cn68xx;
-       struct cvmx_l2c_err_tdtx_s cn68xxp1;
-       struct cvmx_l2c_err_tdtx_cn61xx cnf71xx;
-};
-
-union cvmx_l2c_err_ttgx {
-       uint64_t u64;
-       struct cvmx_l2c_err_ttgx_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t dbe:1;
-               uint64_t sbe:1;
-               uint64_t noway:1;
-               uint64_t reserved_56_60:5;
-               uint64_t syn:6;
-               uint64_t reserved_22_49:28;
-               uint64_t wayidx:15;
-               uint64_t reserved_2_6:5;
-               uint64_t type:2;
-#else
-               uint64_t type:2;
-               uint64_t reserved_2_6:5;
-               uint64_t wayidx:15;
-               uint64_t reserved_22_49:28;
-               uint64_t syn:6;
-               uint64_t reserved_56_60:5;
-               uint64_t noway:1;
-               uint64_t sbe:1;
-               uint64_t dbe:1;
-#endif
-       } s;
-       struct cvmx_l2c_err_ttgx_cn61xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t dbe:1;
-               uint64_t sbe:1;
-               uint64_t noway:1;
-               uint64_t reserved_56_60:5;
-               uint64_t syn:6;
-               uint64_t reserved_20_49:30;
-               uint64_t wayidx:13;
-               uint64_t reserved_2_6:5;
-               uint64_t type:2;
-#else
-               uint64_t type:2;
-               uint64_t reserved_2_6:5;
-               uint64_t wayidx:13;
-               uint64_t reserved_20_49:30;
-               uint64_t syn:6;
-               uint64_t reserved_56_60:5;
-               uint64_t noway:1;
-               uint64_t sbe:1;
-               uint64_t dbe:1;
-#endif
-       } cn61xx;
-       struct cvmx_l2c_err_ttgx_cn63xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t dbe:1;
-               uint64_t sbe:1;
-               uint64_t noway:1;
-               uint64_t reserved_56_60:5;
-               uint64_t syn:6;
-               uint64_t reserved_21_49:29;
-               uint64_t wayidx:14;
-               uint64_t reserved_2_6:5;
-               uint64_t type:2;
-#else
-               uint64_t type:2;
-               uint64_t reserved_2_6:5;
-               uint64_t wayidx:14;
-               uint64_t reserved_21_49:29;
-               uint64_t syn:6;
-               uint64_t reserved_56_60:5;
-               uint64_t noway:1;
-               uint64_t sbe:1;
-               uint64_t dbe:1;
-#endif
-       } cn63xx;
-       struct cvmx_l2c_err_ttgx_cn63xx cn63xxp1;
-       struct cvmx_l2c_err_ttgx_cn63xx cn66xx;
-       struct cvmx_l2c_err_ttgx_s cn68xx;
-       struct cvmx_l2c_err_ttgx_s cn68xxp1;
-       struct cvmx_l2c_err_ttgx_cn61xx cnf71xx;
-};
-
-union cvmx_l2c_err_vbfx {
-       uint64_t u64;
-       struct cvmx_l2c_err_vbfx_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_62_63:2;
-               uint64_t vdbe:1;
-               uint64_t vsbe:1;
-               uint64_t vsyn:10;
-               uint64_t reserved_2_49:48;
-               uint64_t type:2;
-#else
-               uint64_t type:2;
-               uint64_t reserved_2_49:48;
-               uint64_t vsyn:10;
-               uint64_t vsbe:1;
-               uint64_t vdbe:1;
-               uint64_t reserved_62_63:2;
-#endif
-       } s;
-       struct cvmx_l2c_err_vbfx_s cn61xx;
-       struct cvmx_l2c_err_vbfx_s cn63xx;
-       struct cvmx_l2c_err_vbfx_s cn63xxp1;
-       struct cvmx_l2c_err_vbfx_s cn66xx;
-       struct cvmx_l2c_err_vbfx_s cn68xx;
-       struct cvmx_l2c_err_vbfx_s cn68xxp1;
-       struct cvmx_l2c_err_vbfx_s cnf71xx;
-};
-
-union cvmx_l2c_err_xmc {
-       uint64_t u64;
-       struct cvmx_l2c_err_xmc_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t cmd:6;
-               uint64_t reserved_54_57:4;
-               uint64_t sid:6;
-               uint64_t reserved_38_47:10;
-               uint64_t addr:38;
-#else
-               uint64_t addr:38;
-               uint64_t reserved_38_47:10;
-               uint64_t sid:6;
-               uint64_t reserved_54_57:4;
-               uint64_t cmd:6;
-#endif
-       } s;
-       struct cvmx_l2c_err_xmc_cn61xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t cmd:6;
-               uint64_t reserved_52_57:6;
-               uint64_t sid:4;
-               uint64_t reserved_38_47:10;
-               uint64_t addr:38;
-#else
-               uint64_t addr:38;
-               uint64_t reserved_38_47:10;
-               uint64_t sid:4;
-               uint64_t reserved_52_57:6;
-               uint64_t cmd:6;
-#endif
-       } cn61xx;
-       struct cvmx_l2c_err_xmc_cn61xx cn63xx;
-       struct cvmx_l2c_err_xmc_cn61xx cn63xxp1;
-       struct cvmx_l2c_err_xmc_cn66xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t cmd:6;
-               uint64_t reserved_53_57:5;
-               uint64_t sid:5;
-               uint64_t reserved_38_47:10;
-               uint64_t addr:38;
-#else
-               uint64_t addr:38;
-               uint64_t reserved_38_47:10;
-               uint64_t sid:5;
-               uint64_t reserved_53_57:5;
-               uint64_t cmd:6;
-#endif
-       } cn66xx;
-       struct cvmx_l2c_err_xmc_s cn68xx;
-       struct cvmx_l2c_err_xmc_s cn68xxp1;
-       struct cvmx_l2c_err_xmc_cn61xx cnf71xx;
-};
-
-union cvmx_l2c_grpwrr0 {
-       uint64_t u64;
-       struct cvmx_l2c_grpwrr0_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t plc1rmsk:32;
-               uint64_t plc0rmsk:32;
-#else
-               uint64_t plc0rmsk:32;
-               uint64_t plc1rmsk:32;
-#endif
-       } s;
-       struct cvmx_l2c_grpwrr0_s cn52xx;
-       struct cvmx_l2c_grpwrr0_s cn52xxp1;
-       struct cvmx_l2c_grpwrr0_s cn56xx;
-       struct cvmx_l2c_grpwrr0_s cn56xxp1;
-};
-
-union cvmx_l2c_grpwrr1 {
-       uint64_t u64;
-       struct cvmx_l2c_grpwrr1_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t ilcrmsk:32;
-               uint64_t plc2rmsk:32;
-#else
-               uint64_t plc2rmsk:32;
-               uint64_t ilcrmsk:32;
-#endif
-       } s;
-       struct cvmx_l2c_grpwrr1_s cn52xx;
-       struct cvmx_l2c_grpwrr1_s cn52xxp1;
-       struct cvmx_l2c_grpwrr1_s cn56xx;
-       struct cvmx_l2c_grpwrr1_s cn56xxp1;
-};
-
-union cvmx_l2c_int_en {
-       uint64_t u64;
-       struct cvmx_l2c_int_en_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_9_63:55;
-               uint64_t lck2ena:1;
-               uint64_t lckena:1;
-               uint64_t l2ddeden:1;
-               uint64_t l2dsecen:1;
-               uint64_t l2tdeden:1;
-               uint64_t l2tsecen:1;
-               uint64_t oob3en:1;
-               uint64_t oob2en:1;
-               uint64_t oob1en:1;
-#else
-               uint64_t oob1en:1;
-               uint64_t oob2en:1;
-               uint64_t oob3en:1;
-               uint64_t l2tsecen:1;
-               uint64_t l2tdeden:1;
-               uint64_t l2dsecen:1;
-               uint64_t l2ddeden:1;
-               uint64_t lckena:1;
-               uint64_t lck2ena:1;
-               uint64_t reserved_9_63:55;
-#endif
-       } s;
-       struct cvmx_l2c_int_en_s cn52xx;
-       struct cvmx_l2c_int_en_s cn52xxp1;
-       struct cvmx_l2c_int_en_s cn56xx;
-       struct cvmx_l2c_int_en_s cn56xxp1;
-};
-
-union cvmx_l2c_int_ena {
-       uint64_t u64;
-       struct cvmx_l2c_int_ena_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_8_63:56;
-               uint64_t bigrd:1;
-               uint64_t bigwr:1;
-               uint64_t vrtpe:1;
-               uint64_t vrtadrng:1;
-               uint64_t vrtidrng:1;
-               uint64_t vrtwr:1;
-               uint64_t holewr:1;
-               uint64_t holerd:1;
-#else
-               uint64_t holerd:1;
-               uint64_t holewr:1;
-               uint64_t vrtwr:1;
-               uint64_t vrtidrng:1;
-               uint64_t vrtadrng:1;
-               uint64_t vrtpe:1;
-               uint64_t bigwr:1;
-               uint64_t bigrd:1;
-               uint64_t reserved_8_63:56;
-#endif
-       } s;
-       struct cvmx_l2c_int_ena_s cn61xx;
-       struct cvmx_l2c_int_ena_s cn63xx;
-       struct cvmx_l2c_int_ena_cn63xxp1 {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_6_63:58;
-               uint64_t vrtpe:1;
-               uint64_t vrtadrng:1;
-               uint64_t vrtidrng:1;
-               uint64_t vrtwr:1;
-               uint64_t holewr:1;
-               uint64_t holerd:1;
-#else
-               uint64_t holerd:1;
-               uint64_t holewr:1;
-               uint64_t vrtwr:1;
-               uint64_t vrtidrng:1;
-               uint64_t vrtadrng:1;
-               uint64_t vrtpe:1;
-               uint64_t reserved_6_63:58;
-#endif
-       } cn63xxp1;
-       struct cvmx_l2c_int_ena_s cn66xx;
-       struct cvmx_l2c_int_ena_s cn68xx;
-       struct cvmx_l2c_int_ena_s cn68xxp1;
-       struct cvmx_l2c_int_ena_s cnf71xx;
-};
-
-union cvmx_l2c_int_reg {
-       uint64_t u64;
-       struct cvmx_l2c_int_reg_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_20_63:44;
-               uint64_t tad3:1;
-               uint64_t tad2:1;
-               uint64_t tad1:1;
-               uint64_t tad0:1;
-               uint64_t reserved_8_15:8;
-               uint64_t bigrd:1;
-               uint64_t bigwr:1;
-               uint64_t vrtpe:1;
-               uint64_t vrtadrng:1;
-               uint64_t vrtidrng:1;
-               uint64_t vrtwr:1;
-               uint64_t holewr:1;
-               uint64_t holerd:1;
-#else
-               uint64_t holerd:1;
-               uint64_t holewr:1;
-               uint64_t vrtwr:1;
-               uint64_t vrtidrng:1;
-               uint64_t vrtadrng:1;
-               uint64_t vrtpe:1;
-               uint64_t bigwr:1;
-               uint64_t bigrd:1;
-               uint64_t reserved_8_15:8;
-               uint64_t tad0:1;
-               uint64_t tad1:1;
-               uint64_t tad2:1;
-               uint64_t tad3:1;
-               uint64_t reserved_20_63:44;
-#endif
-       } s;
-       struct cvmx_l2c_int_reg_cn61xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_17_63:47;
-               uint64_t tad0:1;
-               uint64_t reserved_8_15:8;
-               uint64_t bigrd:1;
-               uint64_t bigwr:1;
-               uint64_t vrtpe:1;
-               uint64_t vrtadrng:1;
-               uint64_t vrtidrng:1;
-               uint64_t vrtwr:1;
-               uint64_t holewr:1;
-               uint64_t holerd:1;
-#else
-               uint64_t holerd:1;
-               uint64_t holewr:1;
-               uint64_t vrtwr:1;
-               uint64_t vrtidrng:1;
-               uint64_t vrtadrng:1;
-               uint64_t vrtpe:1;
-               uint64_t bigwr:1;
-               uint64_t bigrd:1;
-               uint64_t reserved_8_15:8;
-               uint64_t tad0:1;
-               uint64_t reserved_17_63:47;
-#endif
-       } cn61xx;
-       struct cvmx_l2c_int_reg_cn61xx cn63xx;
-       struct cvmx_l2c_int_reg_cn63xxp1 {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_17_63:47;
-               uint64_t tad0:1;
-               uint64_t reserved_6_15:10;
-               uint64_t vrtpe:1;
-               uint64_t vrtadrng:1;
-               uint64_t vrtidrng:1;
-               uint64_t vrtwr:1;
-               uint64_t holewr:1;
-               uint64_t holerd:1;
-#else
-               uint64_t holerd:1;
-               uint64_t holewr:1;
-               uint64_t vrtwr:1;
-               uint64_t vrtidrng:1;
-               uint64_t vrtadrng:1;
-               uint64_t vrtpe:1;
-               uint64_t reserved_6_15:10;
-               uint64_t tad0:1;
-               uint64_t reserved_17_63:47;
-#endif
-       } cn63xxp1;
-       struct cvmx_l2c_int_reg_cn61xx cn66xx;
-       struct cvmx_l2c_int_reg_s cn68xx;
-       struct cvmx_l2c_int_reg_s cn68xxp1;
-       struct cvmx_l2c_int_reg_cn61xx cnf71xx;
-};
-
-union cvmx_l2c_int_stat {
-       uint64_t u64;
-       struct cvmx_l2c_int_stat_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_9_63:55;
-               uint64_t lck2:1;
-               uint64_t lck:1;
-               uint64_t l2dded:1;
-               uint64_t l2dsec:1;
-               uint64_t l2tded:1;
-               uint64_t l2tsec:1;
-               uint64_t oob3:1;
-               uint64_t oob2:1;
-               uint64_t oob1:1;
-#else
-               uint64_t oob1:1;
-               uint64_t oob2:1;
-               uint64_t oob3:1;
-               uint64_t l2tsec:1;
-               uint64_t l2tded:1;
-               uint64_t l2dsec:1;
-               uint64_t l2dded:1;
-               uint64_t lck:1;
-               uint64_t lck2:1;
-               uint64_t reserved_9_63:55;
-#endif
-       } s;
-       struct cvmx_l2c_int_stat_s cn52xx;
-       struct cvmx_l2c_int_stat_s cn52xxp1;
-       struct cvmx_l2c_int_stat_s cn56xx;
-       struct cvmx_l2c_int_stat_s cn56xxp1;
-};
-
-union cvmx_l2c_iocx_pfc {
-       uint64_t u64;
-       struct cvmx_l2c_iocx_pfc_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t count:64;
-#else
-               uint64_t count:64;
-#endif
-       } s;
-       struct cvmx_l2c_iocx_pfc_s cn61xx;
-       struct cvmx_l2c_iocx_pfc_s cn63xx;
-       struct cvmx_l2c_iocx_pfc_s cn63xxp1;
-       struct cvmx_l2c_iocx_pfc_s cn66xx;
-       struct cvmx_l2c_iocx_pfc_s cn68xx;
-       struct cvmx_l2c_iocx_pfc_s cn68xxp1;
-       struct cvmx_l2c_iocx_pfc_s cnf71xx;
-};
-
-union cvmx_l2c_iorx_pfc {
-       uint64_t u64;
-       struct cvmx_l2c_iorx_pfc_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t count:64;
-#else
-               uint64_t count:64;
-#endif
-       } s;
-       struct cvmx_l2c_iorx_pfc_s cn61xx;
-       struct cvmx_l2c_iorx_pfc_s cn63xx;
-       struct cvmx_l2c_iorx_pfc_s cn63xxp1;
-       struct cvmx_l2c_iorx_pfc_s cn66xx;
-       struct cvmx_l2c_iorx_pfc_s cn68xx;
-       struct cvmx_l2c_iorx_pfc_s cn68xxp1;
-       struct cvmx_l2c_iorx_pfc_s cnf71xx;
-};
-
-union cvmx_l2c_lckbase {
-       uint64_t u64;
-       struct cvmx_l2c_lckbase_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_31_63:33;
-               uint64_t lck_base:27;
-               uint64_t reserved_1_3:3;
-               uint64_t lck_ena:1;
-#else
-               uint64_t lck_ena:1;
-               uint64_t reserved_1_3:3;
-               uint64_t lck_base:27;
-               uint64_t reserved_31_63:33;
-#endif
-       } s;
-       struct cvmx_l2c_lckbase_s cn30xx;
-       struct cvmx_l2c_lckbase_s cn31xx;
-       struct cvmx_l2c_lckbase_s cn38xx;
-       struct cvmx_l2c_lckbase_s cn38xxp2;
-       struct cvmx_l2c_lckbase_s cn50xx;
-       struct cvmx_l2c_lckbase_s cn52xx;
-       struct cvmx_l2c_lckbase_s cn52xxp1;
-       struct cvmx_l2c_lckbase_s cn56xx;
-       struct cvmx_l2c_lckbase_s cn56xxp1;
-       struct cvmx_l2c_lckbase_s cn58xx;
-       struct cvmx_l2c_lckbase_s cn58xxp1;
-};
-
-union cvmx_l2c_lckoff {
-       uint64_t u64;
-       struct cvmx_l2c_lckoff_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_10_63:54;
-               uint64_t lck_offset:10;
-#else
-               uint64_t lck_offset:10;
-               uint64_t reserved_10_63:54;
-#endif
-       } s;
-       struct cvmx_l2c_lckoff_s cn30xx;
-       struct cvmx_l2c_lckoff_s cn31xx;
-       struct cvmx_l2c_lckoff_s cn38xx;
-       struct cvmx_l2c_lckoff_s cn38xxp2;
-       struct cvmx_l2c_lckoff_s cn50xx;
-       struct cvmx_l2c_lckoff_s cn52xx;
-       struct cvmx_l2c_lckoff_s cn52xxp1;
-       struct cvmx_l2c_lckoff_s cn56xx;
-       struct cvmx_l2c_lckoff_s cn56xxp1;
-       struct cvmx_l2c_lckoff_s cn58xx;
-       struct cvmx_l2c_lckoff_s cn58xxp1;
-};
-
-union cvmx_l2c_lfb0 {
-       uint64_t u64;
-       struct cvmx_l2c_lfb0_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t stcpnd:1;
-               uint64_t stpnd:1;
-               uint64_t stinv:1;
-               uint64_t stcfl:1;
-               uint64_t vam:1;
-               uint64_t inxt:4;
-               uint64_t itl:1;
-               uint64_t ihd:1;
-               uint64_t set:3;
-               uint64_t vabnum:4;
-               uint64_t sid:9;
-               uint64_t cmd:4;
-               uint64_t vld:1;
-#else
-               uint64_t vld:1;
-               uint64_t cmd:4;
-               uint64_t sid:9;
-               uint64_t vabnum:4;
-               uint64_t set:3;
-               uint64_t ihd:1;
-               uint64_t itl:1;
-               uint64_t inxt:4;
-               uint64_t vam:1;
-               uint64_t stcfl:1;
-               uint64_t stinv:1;
-               uint64_t stpnd:1;
-               uint64_t stcpnd:1;
-               uint64_t reserved_32_63:32;
-#endif
-       } s;
-       struct cvmx_l2c_lfb0_cn30xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t stcpnd:1;
-               uint64_t stpnd:1;
-               uint64_t stinv:1;
-               uint64_t stcfl:1;
-               uint64_t vam:1;
-               uint64_t reserved_25_26:2;
-               uint64_t inxt:2;
-               uint64_t itl:1;
-               uint64_t ihd:1;
-               uint64_t reserved_20_20:1;
-               uint64_t set:2;
-               uint64_t reserved_16_17:2;
-               uint64_t vabnum:2;
-               uint64_t sid:9;
-               uint64_t cmd:4;
-               uint64_t vld:1;
-#else
-               uint64_t vld:1;
-               uint64_t cmd:4;
-               uint64_t sid:9;
-               uint64_t vabnum:2;
-               uint64_t reserved_16_17:2;
-               uint64_t set:2;
-               uint64_t reserved_20_20:1;
-               uint64_t ihd:1;
-               uint64_t itl:1;
-               uint64_t inxt:2;
-               uint64_t reserved_25_26:2;
-               uint64_t vam:1;
-               uint64_t stcfl:1;
-               uint64_t stinv:1;
-               uint64_t stpnd:1;
-               uint64_t stcpnd:1;
-               uint64_t reserved_32_63:32;
-#endif
-       } cn30xx;
-       struct cvmx_l2c_lfb0_cn31xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t stcpnd:1;
-               uint64_t stpnd:1;
-               uint64_t stinv:1;
-               uint64_t stcfl:1;
-               uint64_t vam:1;
-               uint64_t reserved_26_26:1;
-               uint64_t inxt:3;
-               uint64_t itl:1;
-               uint64_t ihd:1;
-               uint64_t reserved_20_20:1;
-               uint64_t set:2;
-               uint64_t reserved_17_17:1;
-               uint64_t vabnum:3;
-               uint64_t sid:9;
-               uint64_t cmd:4;
-               uint64_t vld:1;
-#else
-               uint64_t vld:1;
-               uint64_t cmd:4;
-               uint64_t sid:9;
-               uint64_t vabnum:3;
-               uint64_t reserved_17_17:1;
-               uint64_t set:2;
-               uint64_t reserved_20_20:1;
-               uint64_t ihd:1;
-               uint64_t itl:1;
-               uint64_t inxt:3;
-               uint64_t reserved_26_26:1;
-               uint64_t vam:1;
-               uint64_t stcfl:1;
-               uint64_t stinv:1;
-               uint64_t stpnd:1;
-               uint64_t stcpnd:1;
-               uint64_t reserved_32_63:32;
-#endif
-       } cn31xx;
-       struct cvmx_l2c_lfb0_s cn38xx;
-       struct cvmx_l2c_lfb0_s cn38xxp2;
-       struct cvmx_l2c_lfb0_cn50xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t stcpnd:1;
-               uint64_t stpnd:1;
-               uint64_t stinv:1;
-               uint64_t stcfl:1;
-               uint64_t vam:1;
-               uint64_t reserved_26_26:1;
-               uint64_t inxt:3;
-               uint64_t itl:1;
-               uint64_t ihd:1;
-               uint64_t set:3;
-               uint64_t reserved_17_17:1;
-               uint64_t vabnum:3;
-               uint64_t sid:9;
-               uint64_t cmd:4;
-               uint64_t vld:1;
-#else
-               uint64_t vld:1;
-               uint64_t cmd:4;
-               uint64_t sid:9;
-               uint64_t vabnum:3;
-               uint64_t reserved_17_17:1;
-               uint64_t set:3;
-               uint64_t ihd:1;
-               uint64_t itl:1;
-               uint64_t inxt:3;
-               uint64_t reserved_26_26:1;
-               uint64_t vam:1;
-               uint64_t stcfl:1;
-               uint64_t stinv:1;
-               uint64_t stpnd:1;
-               uint64_t stcpnd:1;
-               uint64_t reserved_32_63:32;
-#endif
-       } cn50xx;
-       struct cvmx_l2c_lfb0_cn50xx cn52xx;
-       struct cvmx_l2c_lfb0_cn50xx cn52xxp1;
-       struct cvmx_l2c_lfb0_s cn56xx;
-       struct cvmx_l2c_lfb0_s cn56xxp1;
-       struct cvmx_l2c_lfb0_s cn58xx;
-       struct cvmx_l2c_lfb0_s cn58xxp1;
-};
-
-union cvmx_l2c_lfb1 {
-       uint64_t u64;
-       struct cvmx_l2c_lfb1_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_19_63:45;
-               uint64_t dsgoing:1;
-               uint64_t bid:2;
-               uint64_t wtrsp:1;
-               uint64_t wtdw:1;
-               uint64_t wtdq:1;
-               uint64_t wtwhp:1;
-               uint64_t wtwhf:1;
-               uint64_t wtwrm:1;
-               uint64_t wtstm:1;
-               uint64_t wtrda:1;
-               uint64_t wtstdt:1;
-               uint64_t wtstrsp:1;
-               uint64_t wtstrsc:1;
-               uint64_t wtvtm:1;
-               uint64_t wtmfl:1;
-               uint64_t prbrty:1;
-               uint64_t wtprb:1;
-               uint64_t vld:1;
-#else
-               uint64_t vld:1;
-               uint64_t wtprb:1;
-               uint64_t prbrty:1;
-               uint64_t wtmfl:1;
-               uint64_t wtvtm:1;
-               uint64_t wtstrsc:1;
-               uint64_t wtstrsp:1;
-               uint64_t wtstdt:1;
-               uint64_t wtrda:1;
-               uint64_t wtstm:1;
-               uint64_t wtwrm:1;
-               uint64_t wtwhf:1;
-               uint64_t wtwhp:1;
-               uint64_t wtdq:1;
-               uint64_t wtdw:1;
-               uint64_t wtrsp:1;
-               uint64_t bid:2;
-               uint64_t dsgoing:1;
-               uint64_t reserved_19_63:45;
-#endif
-       } s;
-       struct cvmx_l2c_lfb1_s cn30xx;
-       struct cvmx_l2c_lfb1_s cn31xx;
-       struct cvmx_l2c_lfb1_s cn38xx;
-       struct cvmx_l2c_lfb1_s cn38xxp2;
-       struct cvmx_l2c_lfb1_s cn50xx;
-       struct cvmx_l2c_lfb1_s cn52xx;
-       struct cvmx_l2c_lfb1_s cn52xxp1;
-       struct cvmx_l2c_lfb1_s cn56xx;
-       struct cvmx_l2c_lfb1_s cn56xxp1;
-       struct cvmx_l2c_lfb1_s cn58xx;
-       struct cvmx_l2c_lfb1_s cn58xxp1;
-};
-
-union cvmx_l2c_lfb2 {
-       uint64_t u64;
-       struct cvmx_l2c_lfb2_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_0_63:64;
-#else
-               uint64_t reserved_0_63:64;
-#endif
-       } s;
-       struct cvmx_l2c_lfb2_cn30xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_27_63:37;
-               uint64_t lfb_tag:19;
-               uint64_t lfb_idx:8;
-#else
-               uint64_t lfb_idx:8;
-               uint64_t lfb_tag:19;
-               uint64_t reserved_27_63:37;
-#endif
-       } cn30xx;
-       struct cvmx_l2c_lfb2_cn31xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_27_63:37;
-               uint64_t lfb_tag:17;
-               uint64_t lfb_idx:10;
-#else
-               uint64_t lfb_idx:10;
-               uint64_t lfb_tag:17;
-               uint64_t reserved_27_63:37;
-#endif
-       } cn31xx;
-       struct cvmx_l2c_lfb2_cn31xx cn38xx;
-       struct cvmx_l2c_lfb2_cn31xx cn38xxp2;
-       struct cvmx_l2c_lfb2_cn50xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_27_63:37;
-               uint64_t lfb_tag:20;
-               uint64_t lfb_idx:7;
-#else
-               uint64_t lfb_idx:7;
-               uint64_t lfb_tag:20;
-               uint64_t reserved_27_63:37;
-#endif
-       } cn50xx;
-       struct cvmx_l2c_lfb2_cn52xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_27_63:37;
-               uint64_t lfb_tag:18;
-               uint64_t lfb_idx:9;
-#else
-               uint64_t lfb_idx:9;
-               uint64_t lfb_tag:18;
-               uint64_t reserved_27_63:37;
-#endif
-       } cn52xx;
-       struct cvmx_l2c_lfb2_cn52xx cn52xxp1;
-       struct cvmx_l2c_lfb2_cn56xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_27_63:37;
-               uint64_t lfb_tag:16;
-               uint64_t lfb_idx:11;
-#else
-               uint64_t lfb_idx:11;
-               uint64_t lfb_tag:16;
-               uint64_t reserved_27_63:37;
-#endif
-       } cn56xx;
-       struct cvmx_l2c_lfb2_cn56xx cn56xxp1;
-       struct cvmx_l2c_lfb2_cn56xx cn58xx;
-       struct cvmx_l2c_lfb2_cn56xx cn58xxp1;
-};
-
-union cvmx_l2c_lfb3 {
-       uint64_t u64;
-       struct cvmx_l2c_lfb3_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_5_63:59;
-               uint64_t stpartdis:1;
-               uint64_t lfb_hwm:4;
-#else
-               uint64_t lfb_hwm:4;
-               uint64_t stpartdis:1;
-               uint64_t reserved_5_63:59;
-#endif
+               __BITFIELD_FIELD(uint64_t reserved_15_63:49,
+               __BITFIELD_FIELD(uint64_t lfb_enum:4,
+               __BITFIELD_FIELD(uint64_t lfb_dmp:1,
+               __BITFIELD_FIELD(uint64_t ppnum:4,
+               __BITFIELD_FIELD(uint64_t set:3,
+               __BITFIELD_FIELD(uint64_t finv:1,
+               __BITFIELD_FIELD(uint64_t l2d:1,
+               __BITFIELD_FIELD(uint64_t l2t:1,
+               ;))))))))
        } s;
-       struct cvmx_l2c_lfb3_cn30xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_5_63:59;
-               uint64_t stpartdis:1;
-               uint64_t reserved_2_3:2;
-               uint64_t lfb_hwm:2;
-#else
-               uint64_t lfb_hwm:2;
-               uint64_t reserved_2_3:2;
-               uint64_t stpartdis:1;
-               uint64_t reserved_5_63:59;
-#endif
-       } cn30xx;
-       struct cvmx_l2c_lfb3_cn31xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_5_63:59;
-               uint64_t stpartdis:1;
-               uint64_t reserved_3_3:1;
-               uint64_t lfb_hwm:3;
-#else
-               uint64_t lfb_hwm:3;
-               uint64_t reserved_3_3:1;
-               uint64_t stpartdis:1;
-               uint64_t reserved_5_63:59;
-#endif
-       } cn31xx;
-       struct cvmx_l2c_lfb3_s cn38xx;
-       struct cvmx_l2c_lfb3_s cn38xxp2;
-       struct cvmx_l2c_lfb3_cn31xx cn50xx;
-       struct cvmx_l2c_lfb3_cn31xx cn52xx;
-       struct cvmx_l2c_lfb3_cn31xx cn52xxp1;
-       struct cvmx_l2c_lfb3_s cn56xx;
-       struct cvmx_l2c_lfb3_s cn56xxp1;
-       struct cvmx_l2c_lfb3_s cn58xx;
-       struct cvmx_l2c_lfb3_s cn58xxp1;
-};
-
-union cvmx_l2c_oob {
-       uint64_t u64;
-       struct cvmx_l2c_oob_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_2_63:62;
-               uint64_t dwbena:1;
-               uint64_t stena:1;
-#else
-               uint64_t stena:1;
-               uint64_t dwbena:1;
-               uint64_t reserved_2_63:62;
-#endif
-       } s;
-       struct cvmx_l2c_oob_s cn52xx;
-       struct cvmx_l2c_oob_s cn52xxp1;
-       struct cvmx_l2c_oob_s cn56xx;
-       struct cvmx_l2c_oob_s cn56xxp1;
-};
-
-union cvmx_l2c_oob1 {
-       uint64_t u64;
-       struct cvmx_l2c_oob1_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t fadr:27;
-               uint64_t fsrc:1;
-               uint64_t reserved_34_35:2;
-               uint64_t sadr:14;
-               uint64_t reserved_14_19:6;
-               uint64_t size:14;
-#else
-               uint64_t size:14;
-               uint64_t reserved_14_19:6;
-               uint64_t sadr:14;
-               uint64_t reserved_34_35:2;
-               uint64_t fsrc:1;
-               uint64_t fadr:27;
-#endif
-       } s;
-       struct cvmx_l2c_oob1_s cn52xx;
-       struct cvmx_l2c_oob1_s cn52xxp1;
-       struct cvmx_l2c_oob1_s cn56xx;
-       struct cvmx_l2c_oob1_s cn56xxp1;
-};
-
-union cvmx_l2c_oob2 {
-       uint64_t u64;
-       struct cvmx_l2c_oob2_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t fadr:27;
-               uint64_t fsrc:1;
-               uint64_t reserved_34_35:2;
-               uint64_t sadr:14;
-               uint64_t reserved_14_19:6;
-               uint64_t size:14;
-#else
-               uint64_t size:14;
-               uint64_t reserved_14_19:6;
-               uint64_t sadr:14;
-               uint64_t reserved_34_35:2;
-               uint64_t fsrc:1;
-               uint64_t fadr:27;
-#endif
-       } s;
-       struct cvmx_l2c_oob2_s cn52xx;
-       struct cvmx_l2c_oob2_s cn52xxp1;
-       struct cvmx_l2c_oob2_s cn56xx;
-       struct cvmx_l2c_oob2_s cn56xxp1;
-};
-
-union cvmx_l2c_oob3 {
-       uint64_t u64;
-       struct cvmx_l2c_oob3_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t fadr:27;
-               uint64_t fsrc:1;
-               uint64_t reserved_34_35:2;
-               uint64_t sadr:14;
-               uint64_t reserved_14_19:6;
-               uint64_t size:14;
-#else
-               uint64_t size:14;
-               uint64_t reserved_14_19:6;
-               uint64_t sadr:14;
-               uint64_t reserved_34_35:2;
-               uint64_t fsrc:1;
-               uint64_t fadr:27;
-#endif
-       } s;
-       struct cvmx_l2c_oob3_s cn52xx;
-       struct cvmx_l2c_oob3_s cn52xxp1;
-       struct cvmx_l2c_oob3_s cn56xx;
-       struct cvmx_l2c_oob3_s cn56xxp1;
-};
-
-union cvmx_l2c_pfcx {
-       uint64_t u64;
-       struct cvmx_l2c_pfcx_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_36_63:28;
-               uint64_t pfcnt0:36;
-#else
-               uint64_t pfcnt0:36;
-               uint64_t reserved_36_63:28;
-#endif
-       } s;
-       struct cvmx_l2c_pfcx_s cn30xx;
-       struct cvmx_l2c_pfcx_s cn31xx;
-       struct cvmx_l2c_pfcx_s cn38xx;
-       struct cvmx_l2c_pfcx_s cn38xxp2;
-       struct cvmx_l2c_pfcx_s cn50xx;
-       struct cvmx_l2c_pfcx_s cn52xx;
-       struct cvmx_l2c_pfcx_s cn52xxp1;
-       struct cvmx_l2c_pfcx_s cn56xx;
-       struct cvmx_l2c_pfcx_s cn56xxp1;
-       struct cvmx_l2c_pfcx_s cn58xx;
-       struct cvmx_l2c_pfcx_s cn58xxp1;
 };
 
 union cvmx_l2c_pfctl {
        uint64_t u64;
        struct cvmx_l2c_pfctl_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_36_63:28;
-               uint64_t cnt3rdclr:1;
-               uint64_t cnt2rdclr:1;
-               uint64_t cnt1rdclr:1;
-               uint64_t cnt0rdclr:1;
-               uint64_t cnt3ena:1;
-               uint64_t cnt3clr:1;
-               uint64_t cnt3sel:6;
-               uint64_t cnt2ena:1;
-               uint64_t cnt2clr:1;
-               uint64_t cnt2sel:6;
-               uint64_t cnt1ena:1;
-               uint64_t cnt1clr:1;
-               uint64_t cnt1sel:6;
-               uint64_t cnt0ena:1;
-               uint64_t cnt0clr:1;
-               uint64_t cnt0sel:6;
-#else
-               uint64_t cnt0sel:6;
-               uint64_t cnt0clr:1;
-               uint64_t cnt0ena:1;
-               uint64_t cnt1sel:6;
-               uint64_t cnt1clr:1;
-               uint64_t cnt1ena:1;
-               uint64_t cnt2sel:6;
-               uint64_t cnt2clr:1;
-               uint64_t cnt2ena:1;
-               uint64_t cnt3sel:6;
-               uint64_t cnt3clr:1;
-               uint64_t cnt3ena:1;
-               uint64_t cnt0rdclr:1;
-               uint64_t cnt1rdclr:1;
-               uint64_t cnt2rdclr:1;
-               uint64_t cnt3rdclr:1;
-               uint64_t reserved_36_63:28;
-#endif
-       } s;
-       struct cvmx_l2c_pfctl_s cn30xx;
-       struct cvmx_l2c_pfctl_s cn31xx;
-       struct cvmx_l2c_pfctl_s cn38xx;
-       struct cvmx_l2c_pfctl_s cn38xxp2;
-       struct cvmx_l2c_pfctl_s cn50xx;
-       struct cvmx_l2c_pfctl_s cn52xx;
-       struct cvmx_l2c_pfctl_s cn52xxp1;
-       struct cvmx_l2c_pfctl_s cn56xx;
-       struct cvmx_l2c_pfctl_s cn56xxp1;
-       struct cvmx_l2c_pfctl_s cn58xx;
-       struct cvmx_l2c_pfctl_s cn58xxp1;
-};
-
-union cvmx_l2c_ppgrp {
-       uint64_t u64;
-       struct cvmx_l2c_ppgrp_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_24_63:40;
-               uint64_t pp11grp:2;
-               uint64_t pp10grp:2;
-               uint64_t pp9grp:2;
-               uint64_t pp8grp:2;
-               uint64_t pp7grp:2;
-               uint64_t pp6grp:2;
-               uint64_t pp5grp:2;
-               uint64_t pp4grp:2;
-               uint64_t pp3grp:2;
-               uint64_t pp2grp:2;
-               uint64_t pp1grp:2;
-               uint64_t pp0grp:2;
-#else
-               uint64_t pp0grp:2;
-               uint64_t pp1grp:2;
-               uint64_t pp2grp:2;
-               uint64_t pp3grp:2;
-               uint64_t pp4grp:2;
-               uint64_t pp5grp:2;
-               uint64_t pp6grp:2;
-               uint64_t pp7grp:2;
-               uint64_t pp8grp:2;
-               uint64_t pp9grp:2;
-               uint64_t pp10grp:2;
-               uint64_t pp11grp:2;
-               uint64_t reserved_24_63:40;
-#endif
-       } s;
-       struct cvmx_l2c_ppgrp_cn52xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_8_63:56;
-               uint64_t pp3grp:2;
-               uint64_t pp2grp:2;
-               uint64_t pp1grp:2;
-               uint64_t pp0grp:2;
-#else
-               uint64_t pp0grp:2;
-               uint64_t pp1grp:2;
-               uint64_t pp2grp:2;
-               uint64_t pp3grp:2;
-               uint64_t reserved_8_63:56;
-#endif
-       } cn52xx;
-       struct cvmx_l2c_ppgrp_cn52xx cn52xxp1;
-       struct cvmx_l2c_ppgrp_s cn56xx;
-       struct cvmx_l2c_ppgrp_s cn56xxp1;
-};
-
-union cvmx_l2c_qos_iobx {
-       uint64_t u64;
-       struct cvmx_l2c_qos_iobx_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_7_63:57;
-               uint64_t dwblvl:3;
-               uint64_t reserved_3_3:1;
-               uint64_t lvl:3;
-#else
-               uint64_t lvl:3;
-               uint64_t reserved_3_3:1;
-               uint64_t dwblvl:3;
-               uint64_t reserved_7_63:57;
-#endif
-       } s;
-       struct cvmx_l2c_qos_iobx_cn61xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_6_63:58;
-               uint64_t dwblvl:2;
-               uint64_t reserved_2_3:2;
-               uint64_t lvl:2;
-#else
-               uint64_t lvl:2;
-               uint64_t reserved_2_3:2;
-               uint64_t dwblvl:2;
-               uint64_t reserved_6_63:58;
-#endif
-       } cn61xx;
-       struct cvmx_l2c_qos_iobx_cn61xx cn63xx;
-       struct cvmx_l2c_qos_iobx_cn61xx cn63xxp1;
-       struct cvmx_l2c_qos_iobx_cn61xx cn66xx;
-       struct cvmx_l2c_qos_iobx_s cn68xx;
-       struct cvmx_l2c_qos_iobx_s cn68xxp1;
-       struct cvmx_l2c_qos_iobx_cn61xx cnf71xx;
-};
-
-union cvmx_l2c_qos_ppx {
-       uint64_t u64;
-       struct cvmx_l2c_qos_ppx_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_3_63:61;
-               uint64_t lvl:3;
-#else
-               uint64_t lvl:3;
-               uint64_t reserved_3_63:61;
-#endif
-       } s;
-       struct cvmx_l2c_qos_ppx_cn61xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_2_63:62;
-               uint64_t lvl:2;
-#else
-               uint64_t lvl:2;
-               uint64_t reserved_2_63:62;
-#endif
-       } cn61xx;
-       struct cvmx_l2c_qos_ppx_cn61xx cn63xx;
-       struct cvmx_l2c_qos_ppx_cn61xx cn63xxp1;
-       struct cvmx_l2c_qos_ppx_cn61xx cn66xx;
-       struct cvmx_l2c_qos_ppx_s cn68xx;
-       struct cvmx_l2c_qos_ppx_s cn68xxp1;
-       struct cvmx_l2c_qos_ppx_cn61xx cnf71xx;
-};
-
-union cvmx_l2c_qos_wgt {
-       uint64_t u64;
-       struct cvmx_l2c_qos_wgt_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t wgt7:8;
-               uint64_t wgt6:8;
-               uint64_t wgt5:8;
-               uint64_t wgt4:8;
-               uint64_t wgt3:8;
-               uint64_t wgt2:8;
-               uint64_t wgt1:8;
-               uint64_t wgt0:8;
-#else
-               uint64_t wgt0:8;
-               uint64_t wgt1:8;
-               uint64_t wgt2:8;
-               uint64_t wgt3:8;
-               uint64_t wgt4:8;
-               uint64_t wgt5:8;
-               uint64_t wgt6:8;
-               uint64_t wgt7:8;
-#endif
-       } s;
-       struct cvmx_l2c_qos_wgt_cn61xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t wgt3:8;
-               uint64_t wgt2:8;
-               uint64_t wgt1:8;
-               uint64_t wgt0:8;
-#else
-               uint64_t wgt0:8;
-               uint64_t wgt1:8;
-               uint64_t wgt2:8;
-               uint64_t wgt3:8;
-               uint64_t reserved_32_63:32;
-#endif
-       } cn61xx;
-       struct cvmx_l2c_qos_wgt_cn61xx cn63xx;
-       struct cvmx_l2c_qos_wgt_cn61xx cn63xxp1;
-       struct cvmx_l2c_qos_wgt_cn61xx cn66xx;
-       struct cvmx_l2c_qos_wgt_s cn68xx;
-       struct cvmx_l2c_qos_wgt_s cn68xxp1;
-       struct cvmx_l2c_qos_wgt_cn61xx cnf71xx;
-};
-
-union cvmx_l2c_rscx_pfc {
-       uint64_t u64;
-       struct cvmx_l2c_rscx_pfc_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t count:64;
-#else
-               uint64_t count:64;
-#endif
-       } s;
-       struct cvmx_l2c_rscx_pfc_s cn61xx;
-       struct cvmx_l2c_rscx_pfc_s cn63xx;
-       struct cvmx_l2c_rscx_pfc_s cn63xxp1;
-       struct cvmx_l2c_rscx_pfc_s cn66xx;
-       struct cvmx_l2c_rscx_pfc_s cn68xx;
-       struct cvmx_l2c_rscx_pfc_s cn68xxp1;
-       struct cvmx_l2c_rscx_pfc_s cnf71xx;
-};
-
-union cvmx_l2c_rsdx_pfc {
-       uint64_t u64;
-       struct cvmx_l2c_rsdx_pfc_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t count:64;
-#else
-               uint64_t count:64;
-#endif
-       } s;
-       struct cvmx_l2c_rsdx_pfc_s cn61xx;
-       struct cvmx_l2c_rsdx_pfc_s cn63xx;
-       struct cvmx_l2c_rsdx_pfc_s cn63xxp1;
-       struct cvmx_l2c_rsdx_pfc_s cn66xx;
-       struct cvmx_l2c_rsdx_pfc_s cn68xx;
-       struct cvmx_l2c_rsdx_pfc_s cn68xxp1;
-       struct cvmx_l2c_rsdx_pfc_s cnf71xx;
-};
-
-union cvmx_l2c_spar0 {
-       uint64_t u64;
-       struct cvmx_l2c_spar0_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t umsk3:8;
-               uint64_t umsk2:8;
-               uint64_t umsk1:8;
-               uint64_t umsk0:8;
-#else
-               uint64_t umsk0:8;
-               uint64_t umsk1:8;
-               uint64_t umsk2:8;
-               uint64_t umsk3:8;
-               uint64_t reserved_32_63:32;
-#endif
-       } s;
-       struct cvmx_l2c_spar0_cn30xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_4_63:60;
-               uint64_t umsk0:4;
-#else
-               uint64_t umsk0:4;
-               uint64_t reserved_4_63:60;
-#endif
-       } cn30xx;
-       struct cvmx_l2c_spar0_cn31xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_12_63:52;
-               uint64_t umsk1:4;
-               uint64_t reserved_4_7:4;
-               uint64_t umsk0:4;
-#else
-               uint64_t umsk0:4;
-               uint64_t reserved_4_7:4;
-               uint64_t umsk1:4;
-               uint64_t reserved_12_63:52;
-#endif
-       } cn31xx;
-       struct cvmx_l2c_spar0_s cn38xx;
-       struct cvmx_l2c_spar0_s cn38xxp2;
-       struct cvmx_l2c_spar0_cn50xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_16_63:48;
-               uint64_t umsk1:8;
-               uint64_t umsk0:8;
-#else
-               uint64_t umsk0:8;
-               uint64_t umsk1:8;
-               uint64_t reserved_16_63:48;
-#endif
-       } cn50xx;
-       struct cvmx_l2c_spar0_s cn52xx;
-       struct cvmx_l2c_spar0_s cn52xxp1;
-       struct cvmx_l2c_spar0_s cn56xx;
-       struct cvmx_l2c_spar0_s cn56xxp1;
-       struct cvmx_l2c_spar0_s cn58xx;
-       struct cvmx_l2c_spar0_s cn58xxp1;
-};
-
-union cvmx_l2c_spar1 {
-       uint64_t u64;
-       struct cvmx_l2c_spar1_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t umsk7:8;
-               uint64_t umsk6:8;
-               uint64_t umsk5:8;
-               uint64_t umsk4:8;
-#else
-               uint64_t umsk4:8;
-               uint64_t umsk5:8;
-               uint64_t umsk6:8;
-               uint64_t umsk7:8;
-               uint64_t reserved_32_63:32;
-#endif
+               __BITFIELD_FIELD(uint64_t reserved_36_63:28,
+               __BITFIELD_FIELD(uint64_t cnt3rdclr:1,
+               __BITFIELD_FIELD(uint64_t cnt2rdclr:1,
+               __BITFIELD_FIELD(uint64_t cnt1rdclr:1,
+               __BITFIELD_FIELD(uint64_t cnt0rdclr:1,
+               __BITFIELD_FIELD(uint64_t cnt3ena:1,
+               __BITFIELD_FIELD(uint64_t cnt3clr:1,
+               __BITFIELD_FIELD(uint64_t cnt3sel:6,
+               __BITFIELD_FIELD(uint64_t cnt2ena:1,
+               __BITFIELD_FIELD(uint64_t cnt2clr:1,
+               __BITFIELD_FIELD(uint64_t cnt2sel:6,
+               __BITFIELD_FIELD(uint64_t cnt1ena:1,
+               __BITFIELD_FIELD(uint64_t cnt1clr:1,
+               __BITFIELD_FIELD(uint64_t cnt1sel:6,
+               __BITFIELD_FIELD(uint64_t cnt0ena:1,
+               __BITFIELD_FIELD(uint64_t cnt0clr:1,
+               __BITFIELD_FIELD(uint64_t cnt0sel:6,
+               ;)))))))))))))))))
        } s;
-       struct cvmx_l2c_spar1_s cn38xx;
-       struct cvmx_l2c_spar1_s cn38xxp2;
-       struct cvmx_l2c_spar1_s cn56xx;
-       struct cvmx_l2c_spar1_s cn56xxp1;
-       struct cvmx_l2c_spar1_s cn58xx;
-       struct cvmx_l2c_spar1_s cn58xxp1;
-};
-
-union cvmx_l2c_spar2 {
-       uint64_t u64;
-       struct cvmx_l2c_spar2_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t umsk11:8;
-               uint64_t umsk10:8;
-               uint64_t umsk9:8;
-               uint64_t umsk8:8;
-#else
-               uint64_t umsk8:8;
-               uint64_t umsk9:8;
-               uint64_t umsk10:8;
-               uint64_t umsk11:8;
-               uint64_t reserved_32_63:32;
-#endif
-       } s;
-       struct cvmx_l2c_spar2_s cn38xx;
-       struct cvmx_l2c_spar2_s cn38xxp2;
-       struct cvmx_l2c_spar2_s cn56xx;
-       struct cvmx_l2c_spar2_s cn56xxp1;
-       struct cvmx_l2c_spar2_s cn58xx;
-       struct cvmx_l2c_spar2_s cn58xxp1;
-};
-
-union cvmx_l2c_spar3 {
-       uint64_t u64;
-       struct cvmx_l2c_spar3_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t umsk15:8;
-               uint64_t umsk14:8;
-               uint64_t umsk13:8;
-               uint64_t umsk12:8;
-#else
-               uint64_t umsk12:8;
-               uint64_t umsk13:8;
-               uint64_t umsk14:8;
-               uint64_t umsk15:8;
-               uint64_t reserved_32_63:32;
-#endif
-       } s;
-       struct cvmx_l2c_spar3_s cn38xx;
-       struct cvmx_l2c_spar3_s cn38xxp2;
-       struct cvmx_l2c_spar3_s cn58xx;
-       struct cvmx_l2c_spar3_s cn58xxp1;
-};
-
-union cvmx_l2c_spar4 {
-       uint64_t u64;
-       struct cvmx_l2c_spar4_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_8_63:56;
-               uint64_t umskiob:8;
-#else
-               uint64_t umskiob:8;
-               uint64_t reserved_8_63:56;
-#endif
-       } s;
-       struct cvmx_l2c_spar4_cn30xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_4_63:60;
-               uint64_t umskiob:4;
-#else
-               uint64_t umskiob:4;
-               uint64_t reserved_4_63:60;
-#endif
-       } cn30xx;
-       struct cvmx_l2c_spar4_cn30xx cn31xx;
-       struct cvmx_l2c_spar4_s cn38xx;
-       struct cvmx_l2c_spar4_s cn38xxp2;
-       struct cvmx_l2c_spar4_s cn50xx;
-       struct cvmx_l2c_spar4_s cn52xx;
-       struct cvmx_l2c_spar4_s cn52xxp1;
-       struct cvmx_l2c_spar4_s cn56xx;
-       struct cvmx_l2c_spar4_s cn56xxp1;
-       struct cvmx_l2c_spar4_s cn58xx;
-       struct cvmx_l2c_spar4_s cn58xxp1;
-};
-
-union cvmx_l2c_tadx_ecc0 {
-       uint64_t u64;
-       struct cvmx_l2c_tadx_ecc0_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_58_63:6;
-               uint64_t ow3ecc:10;
-               uint64_t reserved_42_47:6;
-               uint64_t ow2ecc:10;
-               uint64_t reserved_26_31:6;
-               uint64_t ow1ecc:10;
-               uint64_t reserved_10_15:6;
-               uint64_t ow0ecc:10;
-#else
-               uint64_t ow0ecc:10;
-               uint64_t reserved_10_15:6;
-               uint64_t ow1ecc:10;
-               uint64_t reserved_26_31:6;
-               uint64_t ow2ecc:10;
-               uint64_t reserved_42_47:6;
-               uint64_t ow3ecc:10;
-               uint64_t reserved_58_63:6;
-#endif
-       } s;
-       struct cvmx_l2c_tadx_ecc0_s cn61xx;
-       struct cvmx_l2c_tadx_ecc0_s cn63xx;
-       struct cvmx_l2c_tadx_ecc0_s cn63xxp1;
-       struct cvmx_l2c_tadx_ecc0_s cn66xx;
-       struct cvmx_l2c_tadx_ecc0_s cn68xx;
-       struct cvmx_l2c_tadx_ecc0_s cn68xxp1;
-       struct cvmx_l2c_tadx_ecc0_s cnf71xx;
-};
-
-union cvmx_l2c_tadx_ecc1 {
-       uint64_t u64;
-       struct cvmx_l2c_tadx_ecc1_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_58_63:6;
-               uint64_t ow7ecc:10;
-               uint64_t reserved_42_47:6;
-               uint64_t ow6ecc:10;
-               uint64_t reserved_26_31:6;
-               uint64_t ow5ecc:10;
-               uint64_t reserved_10_15:6;
-               uint64_t ow4ecc:10;
-#else
-               uint64_t ow4ecc:10;
-               uint64_t reserved_10_15:6;
-               uint64_t ow5ecc:10;
-               uint64_t reserved_26_31:6;
-               uint64_t ow6ecc:10;
-               uint64_t reserved_42_47:6;
-               uint64_t ow7ecc:10;
-               uint64_t reserved_58_63:6;
-#endif
-       } s;
-       struct cvmx_l2c_tadx_ecc1_s cn61xx;
-       struct cvmx_l2c_tadx_ecc1_s cn63xx;
-       struct cvmx_l2c_tadx_ecc1_s cn63xxp1;
-       struct cvmx_l2c_tadx_ecc1_s cn66xx;
-       struct cvmx_l2c_tadx_ecc1_s cn68xx;
-       struct cvmx_l2c_tadx_ecc1_s cn68xxp1;
-       struct cvmx_l2c_tadx_ecc1_s cnf71xx;
-};
-
-union cvmx_l2c_tadx_ien {
-       uint64_t u64;
-       struct cvmx_l2c_tadx_ien_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_9_63:55;
-               uint64_t wrdislmc:1;
-               uint64_t rddislmc:1;
-               uint64_t noway:1;
-               uint64_t vbfdbe:1;
-               uint64_t vbfsbe:1;
-               uint64_t tagdbe:1;
-               uint64_t tagsbe:1;
-               uint64_t l2ddbe:1;
-               uint64_t l2dsbe:1;
-#else
-               uint64_t l2dsbe:1;
-               uint64_t l2ddbe:1;
-               uint64_t tagsbe:1;
-               uint64_t tagdbe:1;
-               uint64_t vbfsbe:1;
-               uint64_t vbfdbe:1;
-               uint64_t noway:1;
-               uint64_t rddislmc:1;
-               uint64_t wrdislmc:1;
-               uint64_t reserved_9_63:55;
-#endif
-       } s;
-       struct cvmx_l2c_tadx_ien_s cn61xx;
-       struct cvmx_l2c_tadx_ien_s cn63xx;
-       struct cvmx_l2c_tadx_ien_cn63xxp1 {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_7_63:57;
-               uint64_t noway:1;
-               uint64_t vbfdbe:1;
-               uint64_t vbfsbe:1;
-               uint64_t tagdbe:1;
-               uint64_t tagsbe:1;
-               uint64_t l2ddbe:1;
-               uint64_t l2dsbe:1;
-#else
-               uint64_t l2dsbe:1;
-               uint64_t l2ddbe:1;
-               uint64_t tagsbe:1;
-               uint64_t tagdbe:1;
-               uint64_t vbfsbe:1;
-               uint64_t vbfdbe:1;
-               uint64_t noway:1;
-               uint64_t reserved_7_63:57;
-#endif
-       } cn63xxp1;
-       struct cvmx_l2c_tadx_ien_s cn66xx;
-       struct cvmx_l2c_tadx_ien_s cn68xx;
-       struct cvmx_l2c_tadx_ien_s cn68xxp1;
-       struct cvmx_l2c_tadx_ien_s cnf71xx;
-};
-
-union cvmx_l2c_tadx_int {
-       uint64_t u64;
-       struct cvmx_l2c_tadx_int_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_9_63:55;
-               uint64_t wrdislmc:1;
-               uint64_t rddislmc:1;
-               uint64_t noway:1;
-               uint64_t vbfdbe:1;
-               uint64_t vbfsbe:1;
-               uint64_t tagdbe:1;
-               uint64_t tagsbe:1;
-               uint64_t l2ddbe:1;
-               uint64_t l2dsbe:1;
-#else
-               uint64_t l2dsbe:1;
-               uint64_t l2ddbe:1;
-               uint64_t tagsbe:1;
-               uint64_t tagdbe:1;
-               uint64_t vbfsbe:1;
-               uint64_t vbfdbe:1;
-               uint64_t noway:1;
-               uint64_t rddislmc:1;
-               uint64_t wrdislmc:1;
-               uint64_t reserved_9_63:55;
-#endif
-       } s;
-       struct cvmx_l2c_tadx_int_s cn61xx;
-       struct cvmx_l2c_tadx_int_s cn63xx;
-       struct cvmx_l2c_tadx_int_s cn66xx;
-       struct cvmx_l2c_tadx_int_s cn68xx;
-       struct cvmx_l2c_tadx_int_s cn68xxp1;
-       struct cvmx_l2c_tadx_int_s cnf71xx;
-};
-
-union cvmx_l2c_tadx_pfc0 {
-       uint64_t u64;
-       struct cvmx_l2c_tadx_pfc0_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t count:64;
-#else
-               uint64_t count:64;
-#endif
-       } s;
-       struct cvmx_l2c_tadx_pfc0_s cn61xx;
-       struct cvmx_l2c_tadx_pfc0_s cn63xx;
-       struct cvmx_l2c_tadx_pfc0_s cn63xxp1;
-       struct cvmx_l2c_tadx_pfc0_s cn66xx;
-       struct cvmx_l2c_tadx_pfc0_s cn68xx;
-       struct cvmx_l2c_tadx_pfc0_s cn68xxp1;
-       struct cvmx_l2c_tadx_pfc0_s cnf71xx;
-};
-
-union cvmx_l2c_tadx_pfc1 {
-       uint64_t u64;
-       struct cvmx_l2c_tadx_pfc1_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t count:64;
-#else
-               uint64_t count:64;
-#endif
-       } s;
-       struct cvmx_l2c_tadx_pfc1_s cn61xx;
-       struct cvmx_l2c_tadx_pfc1_s cn63xx;
-       struct cvmx_l2c_tadx_pfc1_s cn63xxp1;
-       struct cvmx_l2c_tadx_pfc1_s cn66xx;
-       struct cvmx_l2c_tadx_pfc1_s cn68xx;
-       struct cvmx_l2c_tadx_pfc1_s cn68xxp1;
-       struct cvmx_l2c_tadx_pfc1_s cnf71xx;
-};
-
-union cvmx_l2c_tadx_pfc2 {
-       uint64_t u64;
-       struct cvmx_l2c_tadx_pfc2_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t count:64;
-#else
-               uint64_t count:64;
-#endif
-       } s;
-       struct cvmx_l2c_tadx_pfc2_s cn61xx;
-       struct cvmx_l2c_tadx_pfc2_s cn63xx;
-       struct cvmx_l2c_tadx_pfc2_s cn63xxp1;
-       struct cvmx_l2c_tadx_pfc2_s cn66xx;
-       struct cvmx_l2c_tadx_pfc2_s cn68xx;
-       struct cvmx_l2c_tadx_pfc2_s cn68xxp1;
-       struct cvmx_l2c_tadx_pfc2_s cnf71xx;
-};
-
-union cvmx_l2c_tadx_pfc3 {
-       uint64_t u64;
-       struct cvmx_l2c_tadx_pfc3_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t count:64;
-#else
-               uint64_t count:64;
-#endif
-       } s;
-       struct cvmx_l2c_tadx_pfc3_s cn61xx;
-       struct cvmx_l2c_tadx_pfc3_s cn63xx;
-       struct cvmx_l2c_tadx_pfc3_s cn63xxp1;
-       struct cvmx_l2c_tadx_pfc3_s cn66xx;
-       struct cvmx_l2c_tadx_pfc3_s cn68xx;
-       struct cvmx_l2c_tadx_pfc3_s cn68xxp1;
-       struct cvmx_l2c_tadx_pfc3_s cnf71xx;
 };
 
 union cvmx_l2c_tadx_prf {
        uint64_t u64;
        struct cvmx_l2c_tadx_prf_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t cnt3sel:8;
-               uint64_t cnt2sel:8;
-               uint64_t cnt1sel:8;
-               uint64_t cnt0sel:8;
-#else
-               uint64_t cnt0sel:8;
-               uint64_t cnt1sel:8;
-               uint64_t cnt2sel:8;
-               uint64_t cnt3sel:8;
-               uint64_t reserved_32_63:32;
-#endif
+               __BITFIELD_FIELD(uint64_t reserved_32_63:32,
+               __BITFIELD_FIELD(uint64_t cnt3sel:8,
+               __BITFIELD_FIELD(uint64_t cnt2sel:8,
+               __BITFIELD_FIELD(uint64_t cnt1sel:8,
+               __BITFIELD_FIELD(uint64_t cnt0sel:8,
+               ;)))))
        } s;
-       struct cvmx_l2c_tadx_prf_s cn61xx;
-       struct cvmx_l2c_tadx_prf_s cn63xx;
-       struct cvmx_l2c_tadx_prf_s cn63xxp1;
-       struct cvmx_l2c_tadx_prf_s cn66xx;
-       struct cvmx_l2c_tadx_prf_s cn68xx;
-       struct cvmx_l2c_tadx_prf_s cn68xxp1;
-       struct cvmx_l2c_tadx_prf_s cnf71xx;
 };
 
 union cvmx_l2c_tadx_tag {
        uint64_t u64;
        struct cvmx_l2c_tadx_tag_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_46_63:18;
-               uint64_t ecc:6;
-               uint64_t reserved_36_39:4;
-               uint64_t tag:19;
-               uint64_t reserved_4_16:13;
-               uint64_t use:1;
-               uint64_t valid:1;
-               uint64_t dirty:1;
-               uint64_t lock:1;
-#else
-               uint64_t lock:1;
-               uint64_t dirty:1;
-               uint64_t valid:1;
-               uint64_t use:1;
-               uint64_t reserved_4_16:13;
-               uint64_t tag:19;
-               uint64_t reserved_36_39:4;
-               uint64_t ecc:6;
-               uint64_t reserved_46_63:18;
-#endif
-       } s;
-       struct cvmx_l2c_tadx_tag_s cn61xx;
-       struct cvmx_l2c_tadx_tag_s cn63xx;
-       struct cvmx_l2c_tadx_tag_s cn63xxp1;
-       struct cvmx_l2c_tadx_tag_s cn66xx;
-       struct cvmx_l2c_tadx_tag_s cn68xx;
-       struct cvmx_l2c_tadx_tag_s cn68xxp1;
-       struct cvmx_l2c_tadx_tag_s cnf71xx;
-};
-
-union cvmx_l2c_ver_id {
-       uint64_t u64;
-       struct cvmx_l2c_ver_id_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t mask:64;
-#else
-               uint64_t mask:64;
-#endif
-       } s;
-       struct cvmx_l2c_ver_id_s cn61xx;
-       struct cvmx_l2c_ver_id_s cn63xx;
-       struct cvmx_l2c_ver_id_s cn63xxp1;
-       struct cvmx_l2c_ver_id_s cn66xx;
-       struct cvmx_l2c_ver_id_s cn68xx;
-       struct cvmx_l2c_ver_id_s cn68xxp1;
-       struct cvmx_l2c_ver_id_s cnf71xx;
-};
-
-union cvmx_l2c_ver_iob {
-       uint64_t u64;
-       struct cvmx_l2c_ver_iob_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_2_63:62;
-               uint64_t mask:2;
-#else
-               uint64_t mask:2;
-               uint64_t reserved_2_63:62;
-#endif
-       } s;
-       struct cvmx_l2c_ver_iob_cn61xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_1_63:63;
-               uint64_t mask:1;
-#else
-               uint64_t mask:1;
-               uint64_t reserved_1_63:63;
-#endif
-       } cn61xx;
-       struct cvmx_l2c_ver_iob_cn61xx cn63xx;
-       struct cvmx_l2c_ver_iob_cn61xx cn63xxp1;
-       struct cvmx_l2c_ver_iob_cn61xx cn66xx;
-       struct cvmx_l2c_ver_iob_s cn68xx;
-       struct cvmx_l2c_ver_iob_s cn68xxp1;
-       struct cvmx_l2c_ver_iob_cn61xx cnf71xx;
-};
-
-union cvmx_l2c_ver_msc {
-       uint64_t u64;
-       struct cvmx_l2c_ver_msc_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_2_63:62;
-               uint64_t invl2:1;
-               uint64_t dwb:1;
-#else
-               uint64_t dwb:1;
-               uint64_t invl2:1;
-               uint64_t reserved_2_63:62;
-#endif
+               __BITFIELD_FIELD(uint64_t reserved_46_63:18,
+               __BITFIELD_FIELD(uint64_t ecc:6,
+               __BITFIELD_FIELD(uint64_t reserved_36_39:4,
+               __BITFIELD_FIELD(uint64_t tag:19,
+               __BITFIELD_FIELD(uint64_t reserved_4_16:13,
+               __BITFIELD_FIELD(uint64_t use:1,
+               __BITFIELD_FIELD(uint64_t valid:1,
+               __BITFIELD_FIELD(uint64_t dirty:1,
+               __BITFIELD_FIELD(uint64_t lock:1,
+               ;)))))))))
        } s;
-       struct cvmx_l2c_ver_msc_s cn61xx;
-       struct cvmx_l2c_ver_msc_s cn63xx;
-       struct cvmx_l2c_ver_msc_s cn66xx;
-       struct cvmx_l2c_ver_msc_s cn68xx;
-       struct cvmx_l2c_ver_msc_s cn68xxp1;
-       struct cvmx_l2c_ver_msc_s cnf71xx;
 };
 
-union cvmx_l2c_ver_pp {
-       uint64_t u64;
-       struct cvmx_l2c_ver_pp_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t mask:32;
-#else
-               uint64_t mask:32;
-               uint64_t reserved_32_63:32;
-#endif
-       } s;
-       struct cvmx_l2c_ver_pp_cn61xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_4_63:60;
-               uint64_t mask:4;
-#else
-               uint64_t mask:4;
-               uint64_t reserved_4_63:60;
-#endif
-       } cn61xx;
-       struct cvmx_l2c_ver_pp_cn63xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_6_63:58;
-               uint64_t mask:6;
-#else
-               uint64_t mask:6;
-               uint64_t reserved_6_63:58;
-#endif
-       } cn63xx;
-       struct cvmx_l2c_ver_pp_cn63xx cn63xxp1;
-       struct cvmx_l2c_ver_pp_cn66xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_10_63:54;
-               uint64_t mask:10;
-#else
-               uint64_t mask:10;
-               uint64_t reserved_10_63:54;
-#endif
-       } cn66xx;
-       struct cvmx_l2c_ver_pp_s cn68xx;
-       struct cvmx_l2c_ver_pp_s cn68xxp1;
-       struct cvmx_l2c_ver_pp_cn61xx cnf71xx;
-};
-
-union cvmx_l2c_virtid_iobx {
-       uint64_t u64;
-       struct cvmx_l2c_virtid_iobx_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_14_63:50;
-               uint64_t dwbid:6;
-               uint64_t reserved_6_7:2;
-               uint64_t id:6;
-#else
-               uint64_t id:6;
-               uint64_t reserved_6_7:2;
-               uint64_t dwbid:6;
-               uint64_t reserved_14_63:50;
-#endif
-       } s;
-       struct cvmx_l2c_virtid_iobx_s cn61xx;
-       struct cvmx_l2c_virtid_iobx_s cn63xx;
-       struct cvmx_l2c_virtid_iobx_s cn63xxp1;
-       struct cvmx_l2c_virtid_iobx_s cn66xx;
-       struct cvmx_l2c_virtid_iobx_s cn68xx;
-       struct cvmx_l2c_virtid_iobx_s cn68xxp1;
-       struct cvmx_l2c_virtid_iobx_s cnf71xx;
-};
-
-union cvmx_l2c_virtid_ppx {
-       uint64_t u64;
-       struct cvmx_l2c_virtid_ppx_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_6_63:58;
-               uint64_t id:6;
-#else
-               uint64_t id:6;
-               uint64_t reserved_6_63:58;
-#endif
-       } s;
-       struct cvmx_l2c_virtid_ppx_s cn61xx;
-       struct cvmx_l2c_virtid_ppx_s cn63xx;
-       struct cvmx_l2c_virtid_ppx_s cn63xxp1;
-       struct cvmx_l2c_virtid_ppx_s cn66xx;
-       struct cvmx_l2c_virtid_ppx_s cn68xx;
-       struct cvmx_l2c_virtid_ppx_s cn68xxp1;
-       struct cvmx_l2c_virtid_ppx_s cnf71xx;
-};
-
-union cvmx_l2c_vrt_ctl {
-       uint64_t u64;
-       struct cvmx_l2c_vrt_ctl_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_9_63:55;
-               uint64_t ooberr:1;
-               uint64_t reserved_7_7:1;
-               uint64_t memsz:3;
-               uint64_t numid:3;
-               uint64_t enable:1;
-#else
-               uint64_t enable:1;
-               uint64_t numid:3;
-               uint64_t memsz:3;
-               uint64_t reserved_7_7:1;
-               uint64_t ooberr:1;
-               uint64_t reserved_9_63:55;
-#endif
-       } s;
-       struct cvmx_l2c_vrt_ctl_s cn61xx;
-       struct cvmx_l2c_vrt_ctl_s cn63xx;
-       struct cvmx_l2c_vrt_ctl_s cn63xxp1;
-       struct cvmx_l2c_vrt_ctl_s cn66xx;
-       struct cvmx_l2c_vrt_ctl_s cn68xx;
-       struct cvmx_l2c_vrt_ctl_s cn68xxp1;
-       struct cvmx_l2c_vrt_ctl_s cnf71xx;
-};
-
-union cvmx_l2c_vrt_memx {
-       uint64_t u64;
-       struct cvmx_l2c_vrt_memx_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_36_63:28;
-               uint64_t parity:4;
-               uint64_t data:32;
-#else
-               uint64_t data:32;
-               uint64_t parity:4;
-               uint64_t reserved_36_63:28;
-#endif
-       } s;
-       struct cvmx_l2c_vrt_memx_s cn61xx;
-       struct cvmx_l2c_vrt_memx_s cn63xx;
-       struct cvmx_l2c_vrt_memx_s cn63xxp1;
-       struct cvmx_l2c_vrt_memx_s cn66xx;
-       struct cvmx_l2c_vrt_memx_s cn68xx;
-       struct cvmx_l2c_vrt_memx_s cn68xxp1;
-       struct cvmx_l2c_vrt_memx_s cnf71xx;
-};
-
-union cvmx_l2c_wpar_iobx {
-       uint64_t u64;
-       struct cvmx_l2c_wpar_iobx_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_16_63:48;
-               uint64_t mask:16;
-#else
-               uint64_t mask:16;
-               uint64_t reserved_16_63:48;
-#endif
-       } s;
-       struct cvmx_l2c_wpar_iobx_s cn61xx;
-       struct cvmx_l2c_wpar_iobx_s cn63xx;
-       struct cvmx_l2c_wpar_iobx_s cn63xxp1;
-       struct cvmx_l2c_wpar_iobx_s cn66xx;
-       struct cvmx_l2c_wpar_iobx_s cn68xx;
-       struct cvmx_l2c_wpar_iobx_s cn68xxp1;
-       struct cvmx_l2c_wpar_iobx_s cnf71xx;
-};
-
-union cvmx_l2c_wpar_ppx {
-       uint64_t u64;
-       struct cvmx_l2c_wpar_ppx_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_16_63:48;
-               uint64_t mask:16;
-#else
-               uint64_t mask:16;
-               uint64_t reserved_16_63:48;
-#endif
-       } s;
-       struct cvmx_l2c_wpar_ppx_s cn61xx;
-       struct cvmx_l2c_wpar_ppx_s cn63xx;
-       struct cvmx_l2c_wpar_ppx_s cn63xxp1;
-       struct cvmx_l2c_wpar_ppx_s cn66xx;
-       struct cvmx_l2c_wpar_ppx_s cn68xx;
-       struct cvmx_l2c_wpar_ppx_s cn68xxp1;
-       struct cvmx_l2c_wpar_ppx_s cnf71xx;
-};
-
-union cvmx_l2c_xmcx_pfc {
-       uint64_t u64;
-       struct cvmx_l2c_xmcx_pfc_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t count:64;
-#else
-               uint64_t count:64;
-#endif
-       } s;
-       struct cvmx_l2c_xmcx_pfc_s cn61xx;
-       struct cvmx_l2c_xmcx_pfc_s cn63xx;
-       struct cvmx_l2c_xmcx_pfc_s cn63xxp1;
-       struct cvmx_l2c_xmcx_pfc_s cn66xx;
-       struct cvmx_l2c_xmcx_pfc_s cn68xx;
-       struct cvmx_l2c_xmcx_pfc_s cn68xxp1;
-       struct cvmx_l2c_xmcx_pfc_s cnf71xx;
-};
-
-union cvmx_l2c_xmc_cmd {
+union cvmx_l2c_lckbase {
        uint64_t u64;
-       struct cvmx_l2c_xmc_cmd_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t inuse:1;
-               uint64_t cmd:6;
-               uint64_t reserved_38_56:19;
-               uint64_t addr:38;
-#else
-               uint64_t addr:38;
-               uint64_t reserved_38_56:19;
-               uint64_t cmd:6;
-               uint64_t inuse:1;
-#endif
+       struct cvmx_l2c_lckbase_s {
+               __BITFIELD_FIELD(uint64_t reserved_31_63:33,
+               __BITFIELD_FIELD(uint64_t lck_base:27,
+               __BITFIELD_FIELD(uint64_t reserved_1_3:3,
+               __BITFIELD_FIELD(uint64_t lck_ena:1,
+               ;))))
        } s;
-       struct cvmx_l2c_xmc_cmd_s cn61xx;
-       struct cvmx_l2c_xmc_cmd_s cn63xx;
-       struct cvmx_l2c_xmc_cmd_s cn63xxp1;
-       struct cvmx_l2c_xmc_cmd_s cn66xx;
-       struct cvmx_l2c_xmc_cmd_s cn68xx;
-       struct cvmx_l2c_xmc_cmd_s cn68xxp1;
-       struct cvmx_l2c_xmc_cmd_s cnf71xx;
 };
 
-union cvmx_l2c_xmdx_pfc {
+union cvmx_l2c_lckoff {
        uint64_t u64;
-       struct cvmx_l2c_xmdx_pfc_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t count:64;
-#else
-               uint64_t count:64;
-#endif
+       struct cvmx_l2c_lckoff_s {
+               __BITFIELD_FIELD(uint64_t reserved_10_63:54,
+               __BITFIELD_FIELD(uint64_t lck_offset:10,
+               ;))
        } s;
-       struct cvmx_l2c_xmdx_pfc_s cn61xx;
-       struct cvmx_l2c_xmdx_pfc_s cn63xx;
-       struct cvmx_l2c_xmdx_pfc_s cn63xxp1;
-       struct cvmx_l2c_xmdx_pfc_s cn66xx;
-       struct cvmx_l2c_xmdx_pfc_s cn68xx;
-       struct cvmx_l2c_xmdx_pfc_s cn68xxp1;
-       struct cvmx_l2c_xmdx_pfc_s cnf71xx;
 };
 
 #endif
index ddb429210a0e0fb94e008b804129da44e3f61031..02c4479a90c8796d3f6ab4def324400bc2dafe0e 100644 (file)
@@ -4,7 +4,7 @@
  * Contact: support@caviumnetworks.com
  * This file is part of the OCTEON SDK
  *
- * Copyright (c) 2003-2010 Cavium Networks
+ * Copyright (c) 2003-2017 Cavium, Inc.
  *
  * This file is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License, Version 2, as
 #ifndef __CVMX_L2C_H__
 #define __CVMX_L2C_H__
 
-#define CVMX_L2_ASSOC    cvmx_l2c_get_num_assoc()   /* Deprecated macro, use function */
-#define CVMX_L2_SET_BITS  cvmx_l2c_get_set_bits()    /* Deprecated macro, use function */
-#define CVMX_L2_SETS     cvmx_l2c_get_num_sets()    /* Deprecated macro, use function */
+#include <uapi/asm/bitfield.h>
 
+#define CVMX_L2_ASSOC   cvmx_l2c_get_num_assoc()       /* Deprecated macro */
+#define CVMX_L2_SET_BITS cvmx_l2c_get_set_bits()       /* Deprecated macro */
+#define CVMX_L2_SETS    cvmx_l2c_get_num_sets()        /* Deprecated macro */
 
-#define CVMX_L2C_IDX_ADDR_SHIFT 7  /* based on 128 byte cache line size */
+/* Based on 128 byte cache line size */
+#define CVMX_L2C_IDX_ADDR_SHIFT        7
 #define CVMX_L2C_IDX_MASK      (cvmx_l2c_get_num_sets() - 1)
 
 /* Defines for index aliasing computations */
-#define CVMX_L2C_TAG_ADDR_ALIAS_SHIFT (CVMX_L2C_IDX_ADDR_SHIFT + cvmx_l2c_get_set_bits())
+#define CVMX_L2C_TAG_ADDR_ALIAS_SHIFT (CVMX_L2C_IDX_ADDR_SHIFT +              \
+               cvmx_l2c_get_set_bits())
 #define CVMX_L2C_ALIAS_MASK (CVMX_L2C_IDX_MASK << CVMX_L2C_TAG_ADDR_ALIAS_SHIFT)
-#define CVMX_L2C_MEMBANK_SELECT_SIZE  4096
+#define CVMX_L2C_MEMBANK_SELECT_SIZE 4096
 
-/* Defines for Virtualizations, valid only from Octeon II onwards. */
-#define CVMX_L2C_VRT_MAX_VIRTID_ALLOWED ((OCTEON_IS_MODEL(OCTEON_CN63XX)) ? 64 : 0)
-#define CVMX_L2C_VRT_MAX_MEMSZ_ALLOWED ((OCTEON_IS_MODEL(OCTEON_CN63XX)) ? 32 : 0)
+/* Number of L2C Tag-and-data sections (TADs) that are connected to LMC. */
+#define CVMX_L2C_TADS  1
 
 union cvmx_l2c_tag {
        uint64_t u64;
        struct {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved:28;
-               uint64_t V:1;           /* Line valid */
-               uint64_t D:1;           /* Line dirty */
-               uint64_t L:1;           /* Line locked */
-               uint64_t U:1;           /* Use, LRU eviction */
-               uint64_t addr:32;       /* Phys mem (not all bits valid) */
-#else
-               uint64_t addr:32;       /* Phys mem (not all bits valid) */
-               uint64_t U:1;           /* Use, LRU eviction */
-               uint64_t L:1;           /* Line locked */
-               uint64_t D:1;           /* Line dirty */
-               uint64_t V:1;           /* Line valid */
-               uint64_t reserved:28;
-#endif
+               __BITFIELD_FIELD(uint64_t reserved:28,
+               __BITFIELD_FIELD(uint64_t V:1,
+               __BITFIELD_FIELD(uint64_t D:1,
+               __BITFIELD_FIELD(uint64_t L:1,
+               __BITFIELD_FIELD(uint64_t U:1,
+               __BITFIELD_FIELD(uint64_t addr:32,
+               ;))))))
        } s;
 };
 
-/* Number of L2C Tag-and-data sections (TADs) that are connected to LMC. */
-#define CVMX_L2C_TADS  1
-
-  /* L2C Performance Counter events. */
+/* L2C Performance Counter events. */
 enum cvmx_l2c_event {
        CVMX_L2C_EVENT_CYCLES           =  0,
        CVMX_L2C_EVENT_INSTRUCTION_MISS =  1,
@@ -175,7 +166,8 @@ enum cvmx_l2c_tad_event {
  *
  * @note The routine does not clear the counter.
  */
-void cvmx_l2c_config_perf(uint32_t counter, enum cvmx_l2c_event event, uint32_t clear_on_read);
+void cvmx_l2c_config_perf(uint32_t counter, enum cvmx_l2c_event event,
+                         uint32_t clear_on_read);
 
 /**
  * Read the given L2 Cache performance counter. The counter must be configured
@@ -307,8 +299,11 @@ int cvmx_l2c_unlock_mem_region(uint64_t start, uint64_t len);
 union cvmx_l2c_tag cvmx_l2c_get_tag(uint32_t association, uint32_t index);
 
 /* Wrapper providing a deprecated old function name */
-static inline union cvmx_l2c_tag cvmx_get_l2c_tag(uint32_t association, uint32_t index) __attribute__((deprecated));
-static inline union cvmx_l2c_tag cvmx_get_l2c_tag(uint32_t association, uint32_t index)
+static inline union cvmx_l2c_tag cvmx_get_l2c_tag(uint32_t association,
+                                                 uint32_t index)
+                                                 __attribute__((deprecated));
+static inline union cvmx_l2c_tag cvmx_get_l2c_tag(uint32_t association,
+                                                 uint32_t index)
 {
        return cvmx_l2c_get_tag(association, index);
 }
diff --git a/arch/mips/include/asm/octeon/cvmx-l2d-defs.h b/arch/mips/include/asm/octeon/cvmx-l2d-defs.h
deleted file mode 100644 (file)
index 11a4562..0000000
+++ /dev/null
@@ -1,526 +0,0 @@
-/***********************license start***************
- * Author: Cavium Networks
- *
- * Contact: support@caviumnetworks.com
- * This file is part of the OCTEON SDK
- *
- * Copyright (c) 2003-2012 Cavium Networks
- *
- * This file is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, Version 2, as
- * published by the Free Software Foundation.
- *
- * This file is distributed in the hope that it will be useful, but
- * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
- * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
- * NONINFRINGEMENT.  See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this file; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- * or visit http://www.gnu.org/licenses/.
- *
- * This file may also be available under a different license from Cavium.
- * Contact Cavium Networks for more information
- ***********************license end**************************************/
-
-#ifndef __CVMX_L2D_DEFS_H__
-#define __CVMX_L2D_DEFS_H__
-
-#define CVMX_L2D_BST0 (CVMX_ADD_IO_SEG(0x0001180080000780ull))
-#define CVMX_L2D_BST1 (CVMX_ADD_IO_SEG(0x0001180080000788ull))
-#define CVMX_L2D_BST2 (CVMX_ADD_IO_SEG(0x0001180080000790ull))
-#define CVMX_L2D_BST3 (CVMX_ADD_IO_SEG(0x0001180080000798ull))
-#define CVMX_L2D_ERR (CVMX_ADD_IO_SEG(0x0001180080000010ull))
-#define CVMX_L2D_FADR (CVMX_ADD_IO_SEG(0x0001180080000018ull))
-#define CVMX_L2D_FSYN0 (CVMX_ADD_IO_SEG(0x0001180080000020ull))
-#define CVMX_L2D_FSYN1 (CVMX_ADD_IO_SEG(0x0001180080000028ull))
-#define CVMX_L2D_FUS0 (CVMX_ADD_IO_SEG(0x00011800800007A0ull))
-#define CVMX_L2D_FUS1 (CVMX_ADD_IO_SEG(0x00011800800007A8ull))
-#define CVMX_L2D_FUS2 (CVMX_ADD_IO_SEG(0x00011800800007B0ull))
-#define CVMX_L2D_FUS3 (CVMX_ADD_IO_SEG(0x00011800800007B8ull))
-
-union cvmx_l2d_bst0 {
-       uint64_t u64;
-       struct cvmx_l2d_bst0_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_35_63:29;
-               uint64_t ftl:1;
-               uint64_t q0stat:34;
-#else
-               uint64_t q0stat:34;
-               uint64_t ftl:1;
-               uint64_t reserved_35_63:29;
-#endif
-       } s;
-       struct cvmx_l2d_bst0_s cn30xx;
-       struct cvmx_l2d_bst0_s cn31xx;
-       struct cvmx_l2d_bst0_s cn38xx;
-       struct cvmx_l2d_bst0_s cn38xxp2;
-       struct cvmx_l2d_bst0_s cn50xx;
-       struct cvmx_l2d_bst0_s cn52xx;
-       struct cvmx_l2d_bst0_s cn52xxp1;
-       struct cvmx_l2d_bst0_s cn56xx;
-       struct cvmx_l2d_bst0_s cn56xxp1;
-       struct cvmx_l2d_bst0_s cn58xx;
-       struct cvmx_l2d_bst0_s cn58xxp1;
-};
-
-union cvmx_l2d_bst1 {
-       uint64_t u64;
-       struct cvmx_l2d_bst1_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_34_63:30;
-               uint64_t q1stat:34;
-#else
-               uint64_t q1stat:34;
-               uint64_t reserved_34_63:30;
-#endif
-       } s;
-       struct cvmx_l2d_bst1_s cn30xx;
-       struct cvmx_l2d_bst1_s cn31xx;
-       struct cvmx_l2d_bst1_s cn38xx;
-       struct cvmx_l2d_bst1_s cn38xxp2;
-       struct cvmx_l2d_bst1_s cn50xx;
-       struct cvmx_l2d_bst1_s cn52xx;
-       struct cvmx_l2d_bst1_s cn52xxp1;
-       struct cvmx_l2d_bst1_s cn56xx;
-       struct cvmx_l2d_bst1_s cn56xxp1;
-       struct cvmx_l2d_bst1_s cn58xx;
-       struct cvmx_l2d_bst1_s cn58xxp1;
-};
-
-union cvmx_l2d_bst2 {
-       uint64_t u64;
-       struct cvmx_l2d_bst2_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_34_63:30;
-               uint64_t q2stat:34;
-#else
-               uint64_t q2stat:34;
-               uint64_t reserved_34_63:30;
-#endif
-       } s;
-       struct cvmx_l2d_bst2_s cn30xx;
-       struct cvmx_l2d_bst2_s cn31xx;
-       struct cvmx_l2d_bst2_s cn38xx;
-       struct cvmx_l2d_bst2_s cn38xxp2;
-       struct cvmx_l2d_bst2_s cn50xx;
-       struct cvmx_l2d_bst2_s cn52xx;
-       struct cvmx_l2d_bst2_s cn52xxp1;
-       struct cvmx_l2d_bst2_s cn56xx;
-       struct cvmx_l2d_bst2_s cn56xxp1;
-       struct cvmx_l2d_bst2_s cn58xx;
-       struct cvmx_l2d_bst2_s cn58xxp1;
-};
-
-union cvmx_l2d_bst3 {
-       uint64_t u64;
-       struct cvmx_l2d_bst3_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_34_63:30;
-               uint64_t q3stat:34;
-#else
-               uint64_t q3stat:34;
-               uint64_t reserved_34_63:30;
-#endif
-       } s;
-       struct cvmx_l2d_bst3_s cn30xx;
-       struct cvmx_l2d_bst3_s cn31xx;
-       struct cvmx_l2d_bst3_s cn38xx;
-       struct cvmx_l2d_bst3_s cn38xxp2;
-       struct cvmx_l2d_bst3_s cn50xx;
-       struct cvmx_l2d_bst3_s cn52xx;
-       struct cvmx_l2d_bst3_s cn52xxp1;
-       struct cvmx_l2d_bst3_s cn56xx;
-       struct cvmx_l2d_bst3_s cn56xxp1;
-       struct cvmx_l2d_bst3_s cn58xx;
-       struct cvmx_l2d_bst3_s cn58xxp1;
-};
-
-union cvmx_l2d_err {
-       uint64_t u64;
-       struct cvmx_l2d_err_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_6_63:58;
-               uint64_t bmhclsel:1;
-               uint64_t ded_err:1;
-               uint64_t sec_err:1;
-               uint64_t ded_intena:1;
-               uint64_t sec_intena:1;
-               uint64_t ecc_ena:1;
-#else
-               uint64_t ecc_ena:1;
-               uint64_t sec_intena:1;
-               uint64_t ded_intena:1;
-               uint64_t sec_err:1;
-               uint64_t ded_err:1;
-               uint64_t bmhclsel:1;
-               uint64_t reserved_6_63:58;
-#endif
-       } s;
-       struct cvmx_l2d_err_s cn30xx;
-       struct cvmx_l2d_err_s cn31xx;
-       struct cvmx_l2d_err_s cn38xx;
-       struct cvmx_l2d_err_s cn38xxp2;
-       struct cvmx_l2d_err_s cn50xx;
-       struct cvmx_l2d_err_s cn52xx;
-       struct cvmx_l2d_err_s cn52xxp1;
-       struct cvmx_l2d_err_s cn56xx;
-       struct cvmx_l2d_err_s cn56xxp1;
-       struct cvmx_l2d_err_s cn58xx;
-       struct cvmx_l2d_err_s cn58xxp1;
-};
-
-union cvmx_l2d_fadr {
-       uint64_t u64;
-       struct cvmx_l2d_fadr_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_19_63:45;
-               uint64_t fadru:1;
-               uint64_t fowmsk:4;
-               uint64_t fset:3;
-               uint64_t fadr:11;
-#else
-               uint64_t fadr:11;
-               uint64_t fset:3;
-               uint64_t fowmsk:4;
-               uint64_t fadru:1;
-               uint64_t reserved_19_63:45;
-#endif
-       } s;
-       struct cvmx_l2d_fadr_cn30xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_18_63:46;
-               uint64_t fowmsk:4;
-               uint64_t reserved_13_13:1;
-               uint64_t fset:2;
-               uint64_t reserved_9_10:2;
-               uint64_t fadr:9;
-#else
-               uint64_t fadr:9;
-               uint64_t reserved_9_10:2;
-               uint64_t fset:2;
-               uint64_t reserved_13_13:1;
-               uint64_t fowmsk:4;
-               uint64_t reserved_18_63:46;
-#endif
-       } cn30xx;
-       struct cvmx_l2d_fadr_cn31xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_18_63:46;
-               uint64_t fowmsk:4;
-               uint64_t reserved_13_13:1;
-               uint64_t fset:2;
-               uint64_t reserved_10_10:1;
-               uint64_t fadr:10;
-#else
-               uint64_t fadr:10;
-               uint64_t reserved_10_10:1;
-               uint64_t fset:2;
-               uint64_t reserved_13_13:1;
-               uint64_t fowmsk:4;
-               uint64_t reserved_18_63:46;
-#endif
-       } cn31xx;
-       struct cvmx_l2d_fadr_cn38xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_18_63:46;
-               uint64_t fowmsk:4;
-               uint64_t fset:3;
-               uint64_t fadr:11;
-#else
-               uint64_t fadr:11;
-               uint64_t fset:3;
-               uint64_t fowmsk:4;
-               uint64_t reserved_18_63:46;
-#endif
-       } cn38xx;
-       struct cvmx_l2d_fadr_cn38xx cn38xxp2;
-       struct cvmx_l2d_fadr_cn50xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_18_63:46;
-               uint64_t fowmsk:4;
-               uint64_t fset:3;
-               uint64_t reserved_8_10:3;
-               uint64_t fadr:8;
-#else
-               uint64_t fadr:8;
-               uint64_t reserved_8_10:3;
-               uint64_t fset:3;
-               uint64_t fowmsk:4;
-               uint64_t reserved_18_63:46;
-#endif
-       } cn50xx;
-       struct cvmx_l2d_fadr_cn52xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_18_63:46;
-               uint64_t fowmsk:4;
-               uint64_t fset:3;
-               uint64_t reserved_10_10:1;
-               uint64_t fadr:10;
-#else
-               uint64_t fadr:10;
-               uint64_t reserved_10_10:1;
-               uint64_t fset:3;
-               uint64_t fowmsk:4;
-               uint64_t reserved_18_63:46;
-#endif
-       } cn52xx;
-       struct cvmx_l2d_fadr_cn52xx cn52xxp1;
-       struct cvmx_l2d_fadr_s cn56xx;
-       struct cvmx_l2d_fadr_s cn56xxp1;
-       struct cvmx_l2d_fadr_s cn58xx;
-       struct cvmx_l2d_fadr_s cn58xxp1;
-};
-
-union cvmx_l2d_fsyn0 {
-       uint64_t u64;
-       struct cvmx_l2d_fsyn0_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_20_63:44;
-               uint64_t fsyn_ow1:10;
-               uint64_t fsyn_ow0:10;
-#else
-               uint64_t fsyn_ow0:10;
-               uint64_t fsyn_ow1:10;
-               uint64_t reserved_20_63:44;
-#endif
-       } s;
-       struct cvmx_l2d_fsyn0_s cn30xx;
-       struct cvmx_l2d_fsyn0_s cn31xx;
-       struct cvmx_l2d_fsyn0_s cn38xx;
-       struct cvmx_l2d_fsyn0_s cn38xxp2;
-       struct cvmx_l2d_fsyn0_s cn50xx;
-       struct cvmx_l2d_fsyn0_s cn52xx;
-       struct cvmx_l2d_fsyn0_s cn52xxp1;
-       struct cvmx_l2d_fsyn0_s cn56xx;
-       struct cvmx_l2d_fsyn0_s cn56xxp1;
-       struct cvmx_l2d_fsyn0_s cn58xx;
-       struct cvmx_l2d_fsyn0_s cn58xxp1;
-};
-
-union cvmx_l2d_fsyn1 {
-       uint64_t u64;
-       struct cvmx_l2d_fsyn1_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_20_63:44;
-               uint64_t fsyn_ow3:10;
-               uint64_t fsyn_ow2:10;
-#else
-               uint64_t fsyn_ow2:10;
-               uint64_t fsyn_ow3:10;
-               uint64_t reserved_20_63:44;
-#endif
-       } s;
-       struct cvmx_l2d_fsyn1_s cn30xx;
-       struct cvmx_l2d_fsyn1_s cn31xx;
-       struct cvmx_l2d_fsyn1_s cn38xx;
-       struct cvmx_l2d_fsyn1_s cn38xxp2;
-       struct cvmx_l2d_fsyn1_s cn50xx;
-       struct cvmx_l2d_fsyn1_s cn52xx;
-       struct cvmx_l2d_fsyn1_s cn52xxp1;
-       struct cvmx_l2d_fsyn1_s cn56xx;
-       struct cvmx_l2d_fsyn1_s cn56xxp1;
-       struct cvmx_l2d_fsyn1_s cn58xx;
-       struct cvmx_l2d_fsyn1_s cn58xxp1;
-};
-
-union cvmx_l2d_fus0 {
-       uint64_t u64;
-       struct cvmx_l2d_fus0_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_34_63:30;
-               uint64_t q0fus:34;
-#else
-               uint64_t q0fus:34;
-               uint64_t reserved_34_63:30;
-#endif
-       } s;
-       struct cvmx_l2d_fus0_s cn30xx;
-       struct cvmx_l2d_fus0_s cn31xx;
-       struct cvmx_l2d_fus0_s cn38xx;
-       struct cvmx_l2d_fus0_s cn38xxp2;
-       struct cvmx_l2d_fus0_s cn50xx;
-       struct cvmx_l2d_fus0_s cn52xx;
-       struct cvmx_l2d_fus0_s cn52xxp1;
-       struct cvmx_l2d_fus0_s cn56xx;
-       struct cvmx_l2d_fus0_s cn56xxp1;
-       struct cvmx_l2d_fus0_s cn58xx;
-       struct cvmx_l2d_fus0_s cn58xxp1;
-};
-
-union cvmx_l2d_fus1 {
-       uint64_t u64;
-       struct cvmx_l2d_fus1_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_34_63:30;
-               uint64_t q1fus:34;
-#else
-               uint64_t q1fus:34;
-               uint64_t reserved_34_63:30;
-#endif
-       } s;
-       struct cvmx_l2d_fus1_s cn30xx;
-       struct cvmx_l2d_fus1_s cn31xx;
-       struct cvmx_l2d_fus1_s cn38xx;
-       struct cvmx_l2d_fus1_s cn38xxp2;
-       struct cvmx_l2d_fus1_s cn50xx;
-       struct cvmx_l2d_fus1_s cn52xx;
-       struct cvmx_l2d_fus1_s cn52xxp1;
-       struct cvmx_l2d_fus1_s cn56xx;
-       struct cvmx_l2d_fus1_s cn56xxp1;
-       struct cvmx_l2d_fus1_s cn58xx;
-       struct cvmx_l2d_fus1_s cn58xxp1;
-};
-
-union cvmx_l2d_fus2 {
-       uint64_t u64;
-       struct cvmx_l2d_fus2_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_34_63:30;
-               uint64_t q2fus:34;
-#else
-               uint64_t q2fus:34;
-               uint64_t reserved_34_63:30;
-#endif
-       } s;
-       struct cvmx_l2d_fus2_s cn30xx;
-       struct cvmx_l2d_fus2_s cn31xx;
-       struct cvmx_l2d_fus2_s cn38xx;
-       struct cvmx_l2d_fus2_s cn38xxp2;
-       struct cvmx_l2d_fus2_s cn50xx;
-       struct cvmx_l2d_fus2_s cn52xx;
-       struct cvmx_l2d_fus2_s cn52xxp1;
-       struct cvmx_l2d_fus2_s cn56xx;
-       struct cvmx_l2d_fus2_s cn56xxp1;
-       struct cvmx_l2d_fus2_s cn58xx;
-       struct cvmx_l2d_fus2_s cn58xxp1;
-};
-
-union cvmx_l2d_fus3 {
-       uint64_t u64;
-       struct cvmx_l2d_fus3_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_40_63:24;
-               uint64_t ema_ctl:3;
-               uint64_t reserved_34_36:3;
-               uint64_t q3fus:34;
-#else
-               uint64_t q3fus:34;
-               uint64_t reserved_34_36:3;
-               uint64_t ema_ctl:3;
-               uint64_t reserved_40_63:24;
-#endif
-       } s;
-       struct cvmx_l2d_fus3_cn30xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_35_63:29;
-               uint64_t crip_64k:1;
-               uint64_t q3fus:34;
-#else
-               uint64_t q3fus:34;
-               uint64_t crip_64k:1;
-               uint64_t reserved_35_63:29;
-#endif
-       } cn30xx;
-       struct cvmx_l2d_fus3_cn31xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_35_63:29;
-               uint64_t crip_128k:1;
-               uint64_t q3fus:34;
-#else
-               uint64_t q3fus:34;
-               uint64_t crip_128k:1;
-               uint64_t reserved_35_63:29;
-#endif
-       } cn31xx;
-       struct cvmx_l2d_fus3_cn38xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_36_63:28;
-               uint64_t crip_256k:1;
-               uint64_t crip_512k:1;
-               uint64_t q3fus:34;
-#else
-               uint64_t q3fus:34;
-               uint64_t crip_512k:1;
-               uint64_t crip_256k:1;
-               uint64_t reserved_36_63:28;
-#endif
-       } cn38xx;
-       struct cvmx_l2d_fus3_cn38xx cn38xxp2;
-       struct cvmx_l2d_fus3_cn50xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_40_63:24;
-               uint64_t ema_ctl:3;
-               uint64_t reserved_36_36:1;
-               uint64_t crip_32k:1;
-               uint64_t crip_64k:1;
-               uint64_t q3fus:34;
-#else
-               uint64_t q3fus:34;
-               uint64_t crip_64k:1;
-               uint64_t crip_32k:1;
-               uint64_t reserved_36_36:1;
-               uint64_t ema_ctl:3;
-               uint64_t reserved_40_63:24;
-#endif
-       } cn50xx;
-       struct cvmx_l2d_fus3_cn52xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_40_63:24;
-               uint64_t ema_ctl:3;
-               uint64_t reserved_36_36:1;
-               uint64_t crip_128k:1;
-               uint64_t crip_256k:1;
-               uint64_t q3fus:34;
-#else
-               uint64_t q3fus:34;
-               uint64_t crip_256k:1;
-               uint64_t crip_128k:1;
-               uint64_t reserved_36_36:1;
-               uint64_t ema_ctl:3;
-               uint64_t reserved_40_63:24;
-#endif
-       } cn52xx;
-       struct cvmx_l2d_fus3_cn52xx cn52xxp1;
-       struct cvmx_l2d_fus3_cn56xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_40_63:24;
-               uint64_t ema_ctl:3;
-               uint64_t reserved_36_36:1;
-               uint64_t crip_512k:1;
-               uint64_t crip_1024k:1;
-               uint64_t q3fus:34;
-#else
-               uint64_t q3fus:34;
-               uint64_t crip_1024k:1;
-               uint64_t crip_512k:1;
-               uint64_t reserved_36_36:1;
-               uint64_t ema_ctl:3;
-               uint64_t reserved_40_63:24;
-#endif
-       } cn56xx;
-       struct cvmx_l2d_fus3_cn56xx cn56xxp1;
-       struct cvmx_l2d_fus3_cn58xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_39_63:25;
-               uint64_t ema_ctl:2;
-               uint64_t reserved_36_36:1;
-               uint64_t crip_512k:1;
-               uint64_t crip_1024k:1;
-               uint64_t q3fus:34;
-#else
-               uint64_t q3fus:34;
-               uint64_t crip_1024k:1;
-               uint64_t crip_512k:1;
-               uint64_t reserved_36_36:1;
-               uint64_t ema_ctl:2;
-               uint64_t reserved_39_63:25;
-#endif
-       } cn58xx;
-       struct cvmx_l2d_fus3_cn58xx cn58xxp1;
-};
-
-#endif
index 83ce22c080e647a67f90ffdf3f5738b4948dc97a..fe50671fd1bbb9c167cea0da4d152366c0b42dd1 100644 (file)
@@ -4,7 +4,7 @@
  * Contact: support@caviumnetworks.com
  * This file is part of the OCTEON SDK
  *
- * Copyright (c) 2003-2012 Cavium Networks
+ * Copyright (c) 2003-2017 Cavium, Inc.
  *
  * This file is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License, Version 2, as
 #ifndef __CVMX_L2T_DEFS_H__
 #define __CVMX_L2T_DEFS_H__
 
-#define CVMX_L2T_ERR (CVMX_ADD_IO_SEG(0x0001180080000008ull))
+#include <uapi/asm/bitfield.h>
+
+#define CVMX_L2T_ERR   (CVMX_ADD_IO_SEG(0x0001180080000008ull))
+
 
 union cvmx_l2t_err {
        uint64_t u64;
        struct cvmx_l2t_err_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_29_63:35;
-               uint64_t fadru:1;
-               uint64_t lck_intena2:1;
-               uint64_t lckerr2:1;
-               uint64_t lck_intena:1;
-               uint64_t lckerr:1;
-               uint64_t fset:3;
-               uint64_t fadr:10;
-               uint64_t fsyn:6;
-               uint64_t ded_err:1;
-               uint64_t sec_err:1;
-               uint64_t ded_intena:1;
-               uint64_t sec_intena:1;
-               uint64_t ecc_ena:1;
-#else
-               uint64_t ecc_ena:1;
-               uint64_t sec_intena:1;
-               uint64_t ded_intena:1;
-               uint64_t sec_err:1;
-               uint64_t ded_err:1;
-               uint64_t fsyn:6;
-               uint64_t fadr:10;
-               uint64_t fset:3;
-               uint64_t lckerr:1;
-               uint64_t lck_intena:1;
-               uint64_t lckerr2:1;
-               uint64_t lck_intena2:1;
-               uint64_t fadru:1;
-               uint64_t reserved_29_63:35;
-#endif
+               __BITFIELD_FIELD(uint64_t reserved_29_63:35,
+               __BITFIELD_FIELD(uint64_t fadru:1,
+               __BITFIELD_FIELD(uint64_t lck_intena2:1,
+               __BITFIELD_FIELD(uint64_t lckerr2:1,
+               __BITFIELD_FIELD(uint64_t lck_intena:1,
+               __BITFIELD_FIELD(uint64_t lckerr:1,
+               __BITFIELD_FIELD(uint64_t fset:3,
+               __BITFIELD_FIELD(uint64_t fadr:10,
+               __BITFIELD_FIELD(uint64_t fsyn:6,
+               __BITFIELD_FIELD(uint64_t ded_err:1,
+               __BITFIELD_FIELD(uint64_t sec_err:1,
+               __BITFIELD_FIELD(uint64_t ded_intena:1,
+               __BITFIELD_FIELD(uint64_t sec_intena:1,
+               __BITFIELD_FIELD(uint64_t ecc_ena:1,
+               ;))))))))))))))
        } s;
        struct cvmx_l2t_err_cn30xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_28_63:36;
-               uint64_t lck_intena2:1;
-               uint64_t lckerr2:1;
-               uint64_t lck_intena:1;
-               uint64_t lckerr:1;
-               uint64_t reserved_23_23:1;
-               uint64_t fset:2;
-               uint64_t reserved_19_20:2;
-               uint64_t fadr:8;
-               uint64_t fsyn:6;
-               uint64_t ded_err:1;
-               uint64_t sec_err:1;
-               uint64_t ded_intena:1;
-               uint64_t sec_intena:1;
-               uint64_t ecc_ena:1;
-#else
-               uint64_t ecc_ena:1;
-               uint64_t sec_intena:1;
-               uint64_t ded_intena:1;
-               uint64_t sec_err:1;
-               uint64_t ded_err:1;
-               uint64_t fsyn:6;
-               uint64_t fadr:8;
-               uint64_t reserved_19_20:2;
-               uint64_t fset:2;
-               uint64_t reserved_23_23:1;
-               uint64_t lckerr:1;
-               uint64_t lck_intena:1;
-               uint64_t lckerr2:1;
-               uint64_t lck_intena2:1;
-               uint64_t reserved_28_63:36;
-#endif
+               __BITFIELD_FIELD(uint64_t reserved_28_63:36,
+               __BITFIELD_FIELD(uint64_t lck_intena2:1,
+               __BITFIELD_FIELD(uint64_t lckerr2:1,
+               __BITFIELD_FIELD(uint64_t lck_intena:1,
+               __BITFIELD_FIELD(uint64_t lckerr:1,
+               __BITFIELD_FIELD(uint64_t reserved_23_23:1,
+               __BITFIELD_FIELD(uint64_t fset:2,
+               __BITFIELD_FIELD(uint64_t reserved_19_20:2,
+               __BITFIELD_FIELD(uint64_t fadr:8,
+               __BITFIELD_FIELD(uint64_t fsyn:6,
+               __BITFIELD_FIELD(uint64_t ded_err:1,
+               __BITFIELD_FIELD(uint64_t sec_err:1,
+               __BITFIELD_FIELD(uint64_t ded_intena:1,
+               __BITFIELD_FIELD(uint64_t sec_intena:1,
+               __BITFIELD_FIELD(uint64_t ecc_ena:1,
+               ;)))))))))))))))
        } cn30xx;
        struct cvmx_l2t_err_cn31xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_28_63:36;
-               uint64_t lck_intena2:1;
-               uint64_t lckerr2:1;
-               uint64_t lck_intena:1;
-               uint64_t lckerr:1;
-               uint64_t reserved_23_23:1;
-               uint64_t fset:2;
-               uint64_t reserved_20_20:1;
-               uint64_t fadr:9;
-               uint64_t fsyn:6;
-               uint64_t ded_err:1;
-               uint64_t sec_err:1;
-               uint64_t ded_intena:1;
-               uint64_t sec_intena:1;
-               uint64_t ecc_ena:1;
-#else
-               uint64_t ecc_ena:1;
-               uint64_t sec_intena:1;
-               uint64_t ded_intena:1;
-               uint64_t sec_err:1;
-               uint64_t ded_err:1;
-               uint64_t fsyn:6;
-               uint64_t fadr:9;
-               uint64_t reserved_20_20:1;
-               uint64_t fset:2;
-               uint64_t reserved_23_23:1;
-               uint64_t lckerr:1;
-               uint64_t lck_intena:1;
-               uint64_t lckerr2:1;
-               uint64_t lck_intena2:1;
-               uint64_t reserved_28_63:36;
-#endif
+               __BITFIELD_FIELD(uint64_t reserved_28_63:36,
+               __BITFIELD_FIELD(uint64_t lck_intena2:1,
+               __BITFIELD_FIELD(uint64_t lckerr2:1,
+               __BITFIELD_FIELD(uint64_t lck_intena:1,
+               __BITFIELD_FIELD(uint64_t lckerr:1,
+               __BITFIELD_FIELD(uint64_t reserved_23_23:1,
+               __BITFIELD_FIELD(uint64_t fset:2,
+               __BITFIELD_FIELD(uint64_t reserved_20_20:1,
+               __BITFIELD_FIELD(uint64_t fadr:9,
+               __BITFIELD_FIELD(uint64_t fsyn:6,
+               __BITFIELD_FIELD(uint64_t ded_err:1,
+               __BITFIELD_FIELD(uint64_t sec_err:1,
+               __BITFIELD_FIELD(uint64_t ded_intena:1,
+               __BITFIELD_FIELD(uint64_t sec_intena:1,
+               __BITFIELD_FIELD(uint64_t ecc_ena:1,
+               ;)))))))))))))))
        } cn31xx;
        struct cvmx_l2t_err_cn38xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_28_63:36;
-               uint64_t lck_intena2:1;
-               uint64_t lckerr2:1;
-               uint64_t lck_intena:1;
-               uint64_t lckerr:1;
-               uint64_t fset:3;
-               uint64_t fadr:10;
-               uint64_t fsyn:6;
-               uint64_t ded_err:1;
-               uint64_t sec_err:1;
-               uint64_t ded_intena:1;
-               uint64_t sec_intena:1;
-               uint64_t ecc_ena:1;
-#else
-               uint64_t ecc_ena:1;
-               uint64_t sec_intena:1;
-               uint64_t ded_intena:1;
-               uint64_t sec_err:1;
-               uint64_t ded_err:1;
-               uint64_t fsyn:6;
-               uint64_t fadr:10;
-               uint64_t fset:3;
-               uint64_t lckerr:1;
-               uint64_t lck_intena:1;
-               uint64_t lckerr2:1;
-               uint64_t lck_intena2:1;
-               uint64_t reserved_28_63:36;
-#endif
+               __BITFIELD_FIELD(uint64_t reserved_28_63:36,
+               __BITFIELD_FIELD(uint64_t lck_intena2:1,
+               __BITFIELD_FIELD(uint64_t lckerr2:1,
+               __BITFIELD_FIELD(uint64_t lck_intena:1,
+               __BITFIELD_FIELD(uint64_t lckerr:1,
+               __BITFIELD_FIELD(uint64_t fset:3,
+               __BITFIELD_FIELD(uint64_t fadr:10,
+               __BITFIELD_FIELD(uint64_t fsyn:6,
+               __BITFIELD_FIELD(uint64_t ded_err:1,
+               __BITFIELD_FIELD(uint64_t sec_err:1,
+               __BITFIELD_FIELD(uint64_t ded_intena:1,
+               __BITFIELD_FIELD(uint64_t sec_intena:1,
+               __BITFIELD_FIELD(uint64_t ecc_ena:1,
+               ;)))))))))))))
        } cn38xx;
        struct cvmx_l2t_err_cn38xx cn38xxp2;
        struct cvmx_l2t_err_cn50xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_28_63:36;
-               uint64_t lck_intena2:1;
-               uint64_t lckerr2:1;
-               uint64_t lck_intena:1;
-               uint64_t lckerr:1;
-               uint64_t fset:3;
-               uint64_t reserved_18_20:3;
-               uint64_t fadr:7;
-               uint64_t fsyn:6;
-               uint64_t ded_err:1;
-               uint64_t sec_err:1;
-               uint64_t ded_intena:1;
-               uint64_t sec_intena:1;
-               uint64_t ecc_ena:1;
-#else
-               uint64_t ecc_ena:1;
-               uint64_t sec_intena:1;
-               uint64_t ded_intena:1;
-               uint64_t sec_err:1;
-               uint64_t ded_err:1;
-               uint64_t fsyn:6;
-               uint64_t fadr:7;
-               uint64_t reserved_18_20:3;
-               uint64_t fset:3;
-               uint64_t lckerr:1;
-               uint64_t lck_intena:1;
-               uint64_t lckerr2:1;
-               uint64_t lck_intena2:1;
-               uint64_t reserved_28_63:36;
-#endif
+               __BITFIELD_FIELD(uint64_t reserved_28_63:36,
+               __BITFIELD_FIELD(uint64_t lck_intena2:1,
+               __BITFIELD_FIELD(uint64_t lckerr2:1,
+               __BITFIELD_FIELD(uint64_t lck_intena:1,
+               __BITFIELD_FIELD(uint64_t lckerr:1,
+               __BITFIELD_FIELD(uint64_t fset:3,
+               __BITFIELD_FIELD(uint64_t reserved_18_20:3,
+               __BITFIELD_FIELD(uint64_t fadr:7,
+               __BITFIELD_FIELD(uint64_t fsyn:6,
+               __BITFIELD_FIELD(uint64_t ded_err:1,
+               __BITFIELD_FIELD(uint64_t sec_err:1,
+               __BITFIELD_FIELD(uint64_t ded_intena:1,
+               __BITFIELD_FIELD(uint64_t sec_intena:1,
+               __BITFIELD_FIELD(uint64_t ecc_ena:1,
+               ;))))))))))))))
        } cn50xx;
        struct cvmx_l2t_err_cn52xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_28_63:36;
-               uint64_t lck_intena2:1;
-               uint64_t lckerr2:1;
-               uint64_t lck_intena:1;
-               uint64_t lckerr:1;
-               uint64_t fset:3;
-               uint64_t reserved_20_20:1;
-               uint64_t fadr:9;
-               uint64_t fsyn:6;
-               uint64_t ded_err:1;
-               uint64_t sec_err:1;
-               uint64_t ded_intena:1;
-               uint64_t sec_intena:1;
-               uint64_t ecc_ena:1;
-#else
-               uint64_t ecc_ena:1;
-               uint64_t sec_intena:1;
-               uint64_t ded_intena:1;
-               uint64_t sec_err:1;
-               uint64_t ded_err:1;
-               uint64_t fsyn:6;
-               uint64_t fadr:9;
-               uint64_t reserved_20_20:1;
-               uint64_t fset:3;
-               uint64_t lckerr:1;
-               uint64_t lck_intena:1;
-               uint64_t lckerr2:1;
-               uint64_t lck_intena2:1;
-               uint64_t reserved_28_63:36;
-#endif
+               __BITFIELD_FIELD(uint64_t reserved_28_63:36,
+               __BITFIELD_FIELD(uint64_t lck_intena2:1,
+               __BITFIELD_FIELD(uint64_t lckerr2:1,
+               __BITFIELD_FIELD(uint64_t lck_intena:1,
+               __BITFIELD_FIELD(uint64_t lckerr:1,
+               __BITFIELD_FIELD(uint64_t fset:3,
+               __BITFIELD_FIELD(uint64_t reserved_20_20:1,
+               __BITFIELD_FIELD(uint64_t fadr:9,
+               __BITFIELD_FIELD(uint64_t fsyn:6,
+               __BITFIELD_FIELD(uint64_t ded_err:1,
+               __BITFIELD_FIELD(uint64_t sec_err:1,
+               __BITFIELD_FIELD(uint64_t ded_intena:1,
+               __BITFIELD_FIELD(uint64_t sec_intena:1,
+               __BITFIELD_FIELD(uint64_t ecc_ena:1,
+               ;))))))))))))))
        } cn52xx;
        struct cvmx_l2t_err_cn52xx cn52xxp1;
        struct cvmx_l2t_err_s cn56xx;
index 4bce393391e28259f598991f332f7b3c84481e8f..e2dce1acf029e571be9092c60f396deb58f9f155 100644 (file)
@@ -4,7 +4,7 @@
  * Contact: support@caviumnetworks.com
  * This file is part of the OCTEON SDK
  *
- * Copyright (c) 2003-2012 Cavium Networks
+ * Copyright (c) 2003-2017 Cavium, Inc.
  *
  * This file is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License, Version 2, as
 #ifndef __CVMX_PCIERCX_DEFS_H__
 #define __CVMX_PCIERCX_DEFS_H__
 
-#define CVMX_PCIERCX_CFG000(block_id) (0x0000000000000000ull)
+#include <uapi/asm/bitfield.h>
+
 #define CVMX_PCIERCX_CFG001(block_id) (0x0000000000000004ull)
-#define CVMX_PCIERCX_CFG002(block_id) (0x0000000000000008ull)
-#define CVMX_PCIERCX_CFG003(block_id) (0x000000000000000Cull)
-#define CVMX_PCIERCX_CFG004(block_id) (0x0000000000000010ull)
-#define CVMX_PCIERCX_CFG005(block_id) (0x0000000000000014ull)
 #define CVMX_PCIERCX_CFG006(block_id) (0x0000000000000018ull)
-#define CVMX_PCIERCX_CFG007(block_id) (0x000000000000001Cull)
 #define CVMX_PCIERCX_CFG008(block_id) (0x0000000000000020ull)
 #define CVMX_PCIERCX_CFG009(block_id) (0x0000000000000024ull)
 #define CVMX_PCIERCX_CFG010(block_id) (0x0000000000000028ull)
 #define CVMX_PCIERCX_CFG011(block_id) (0x000000000000002Cull)
-#define CVMX_PCIERCX_CFG012(block_id) (0x0000000000000030ull)
-#define CVMX_PCIERCX_CFG013(block_id) (0x0000000000000034ull)
-#define CVMX_PCIERCX_CFG014(block_id) (0x0000000000000038ull)
-#define CVMX_PCIERCX_CFG015(block_id) (0x000000000000003Cull)
-#define CVMX_PCIERCX_CFG016(block_id) (0x0000000000000040ull)
-#define CVMX_PCIERCX_CFG017(block_id) (0x0000000000000044ull)
-#define CVMX_PCIERCX_CFG020(block_id) (0x0000000000000050ull)
-#define CVMX_PCIERCX_CFG021(block_id) (0x0000000000000054ull)
-#define CVMX_PCIERCX_CFG022(block_id) (0x0000000000000058ull)
-#define CVMX_PCIERCX_CFG023(block_id) (0x000000000000005Cull)
-#define CVMX_PCIERCX_CFG028(block_id) (0x0000000000000070ull)
-#define CVMX_PCIERCX_CFG029(block_id) (0x0000000000000074ull)
 #define CVMX_PCIERCX_CFG030(block_id) (0x0000000000000078ull)
 #define CVMX_PCIERCX_CFG031(block_id) (0x000000000000007Cull)
 #define CVMX_PCIERCX_CFG032(block_id) (0x0000000000000080ull)
-#define CVMX_PCIERCX_CFG033(block_id) (0x0000000000000084ull)
 #define CVMX_PCIERCX_CFG034(block_id) (0x0000000000000088ull)
 #define CVMX_PCIERCX_CFG035(block_id) (0x000000000000008Cull)
-#define CVMX_PCIERCX_CFG036(block_id) (0x0000000000000090ull)
-#define CVMX_PCIERCX_CFG037(block_id) (0x0000000000000094ull)
-#define CVMX_PCIERCX_CFG038(block_id) (0x0000000000000098ull)
-#define CVMX_PCIERCX_CFG039(block_id) (0x000000000000009Cull)
 #define CVMX_PCIERCX_CFG040(block_id) (0x00000000000000A0ull)
-#define CVMX_PCIERCX_CFG041(block_id) (0x00000000000000A4ull)
-#define CVMX_PCIERCX_CFG042(block_id) (0x00000000000000A8ull)
-#define CVMX_PCIERCX_CFG064(block_id) (0x0000000000000100ull)
-#define CVMX_PCIERCX_CFG065(block_id) (0x0000000000000104ull)
 #define CVMX_PCIERCX_CFG066(block_id) (0x0000000000000108ull)
-#define CVMX_PCIERCX_CFG067(block_id) (0x000000000000010Cull)
-#define CVMX_PCIERCX_CFG068(block_id) (0x0000000000000110ull)
 #define CVMX_PCIERCX_CFG069(block_id) (0x0000000000000114ull)
 #define CVMX_PCIERCX_CFG070(block_id) (0x0000000000000118ull)
-#define CVMX_PCIERCX_CFG071(block_id) (0x000000000000011Cull)
-#define CVMX_PCIERCX_CFG072(block_id) (0x0000000000000120ull)
-#define CVMX_PCIERCX_CFG073(block_id) (0x0000000000000124ull)
-#define CVMX_PCIERCX_CFG074(block_id) (0x0000000000000128ull)
 #define CVMX_PCIERCX_CFG075(block_id) (0x000000000000012Cull)
-#define CVMX_PCIERCX_CFG076(block_id) (0x0000000000000130ull)
-#define CVMX_PCIERCX_CFG077(block_id) (0x0000000000000134ull)
 #define CVMX_PCIERCX_CFG448(block_id) (0x0000000000000700ull)
-#define CVMX_PCIERCX_CFG449(block_id) (0x0000000000000704ull)
-#define CVMX_PCIERCX_CFG450(block_id) (0x0000000000000708ull)
-#define CVMX_PCIERCX_CFG451(block_id) (0x000000000000070Cull)
 #define CVMX_PCIERCX_CFG452(block_id) (0x0000000000000710ull)
-#define CVMX_PCIERCX_CFG453(block_id) (0x0000000000000714ull)
-#define CVMX_PCIERCX_CFG454(block_id) (0x0000000000000718ull)
 #define CVMX_PCIERCX_CFG455(block_id) (0x000000000000071Cull)
-#define CVMX_PCIERCX_CFG456(block_id) (0x0000000000000720ull)
-#define CVMX_PCIERCX_CFG458(block_id) (0x0000000000000728ull)
-#define CVMX_PCIERCX_CFG459(block_id) (0x000000000000072Cull)
-#define CVMX_PCIERCX_CFG460(block_id) (0x0000000000000730ull)
-#define CVMX_PCIERCX_CFG461(block_id) (0x0000000000000734ull)
-#define CVMX_PCIERCX_CFG462(block_id) (0x0000000000000738ull)
-#define CVMX_PCIERCX_CFG463(block_id) (0x000000000000073Cull)
-#define CVMX_PCIERCX_CFG464(block_id) (0x0000000000000740ull)
-#define CVMX_PCIERCX_CFG465(block_id) (0x0000000000000744ull)
-#define CVMX_PCIERCX_CFG466(block_id) (0x0000000000000748ull)
-#define CVMX_PCIERCX_CFG467(block_id) (0x000000000000074Cull)
-#define CVMX_PCIERCX_CFG468(block_id) (0x0000000000000750ull)
-#define CVMX_PCIERCX_CFG490(block_id) (0x00000000000007A8ull)
-#define CVMX_PCIERCX_CFG491(block_id) (0x00000000000007ACull)
-#define CVMX_PCIERCX_CFG492(block_id) (0x00000000000007B0ull)
 #define CVMX_PCIERCX_CFG515(block_id) (0x000000000000080Cull)
-#define CVMX_PCIERCX_CFG516(block_id) (0x0000000000000810ull)
-#define CVMX_PCIERCX_CFG517(block_id) (0x0000000000000814ull)
-
-union cvmx_pciercx_cfg000 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg000_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t devid:16;
-               uint32_t vendid:16;
-#else
-               uint32_t vendid:16;
-               uint32_t devid:16;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg000_s cn52xx;
-       struct cvmx_pciercx_cfg000_s cn52xxp1;
-       struct cvmx_pciercx_cfg000_s cn56xx;
-       struct cvmx_pciercx_cfg000_s cn56xxp1;
-       struct cvmx_pciercx_cfg000_s cn61xx;
-       struct cvmx_pciercx_cfg000_s cn63xx;
-       struct cvmx_pciercx_cfg000_s cn63xxp1;
-       struct cvmx_pciercx_cfg000_s cn66xx;
-       struct cvmx_pciercx_cfg000_s cn68xx;
-       struct cvmx_pciercx_cfg000_s cn68xxp1;
-       struct cvmx_pciercx_cfg000_s cnf71xx;
-};
 
 union cvmx_pciercx_cfg001 {
        uint32_t u32;
        struct cvmx_pciercx_cfg001_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t dpe:1;
-               uint32_t sse:1;
-               uint32_t rma:1;
-               uint32_t rta:1;
-               uint32_t sta:1;
-               uint32_t devt:2;
-               uint32_t mdpe:1;
-               uint32_t fbb:1;
-               uint32_t reserved_22_22:1;
-               uint32_t m66:1;
-               uint32_t cl:1;
-               uint32_t i_stat:1;
-               uint32_t reserved_11_18:8;
-               uint32_t i_dis:1;
-               uint32_t fbbe:1;
-               uint32_t see:1;
-               uint32_t ids_wcc:1;
-               uint32_t per:1;
-               uint32_t vps:1;
-               uint32_t mwice:1;
-               uint32_t scse:1;
-               uint32_t me:1;
-               uint32_t msae:1;
-               uint32_t isae:1;
-#else
-               uint32_t isae:1;
-               uint32_t msae:1;
-               uint32_t me:1;
-               uint32_t scse:1;
-               uint32_t mwice:1;
-               uint32_t vps:1;
-               uint32_t per:1;
-               uint32_t ids_wcc:1;
-               uint32_t see:1;
-               uint32_t fbbe:1;
-               uint32_t i_dis:1;
-               uint32_t reserved_11_18:8;
-               uint32_t i_stat:1;
-               uint32_t cl:1;
-               uint32_t m66:1;
-               uint32_t reserved_22_22:1;
-               uint32_t fbb:1;
-               uint32_t mdpe:1;
-               uint32_t devt:2;
-               uint32_t sta:1;
-               uint32_t rta:1;
-               uint32_t rma:1;
-               uint32_t sse:1;
-               uint32_t dpe:1;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg001_s cn52xx;
-       struct cvmx_pciercx_cfg001_s cn52xxp1;
-       struct cvmx_pciercx_cfg001_s cn56xx;
-       struct cvmx_pciercx_cfg001_s cn56xxp1;
-       struct cvmx_pciercx_cfg001_s cn61xx;
-       struct cvmx_pciercx_cfg001_s cn63xx;
-       struct cvmx_pciercx_cfg001_s cn63xxp1;
-       struct cvmx_pciercx_cfg001_s cn66xx;
-       struct cvmx_pciercx_cfg001_s cn68xx;
-       struct cvmx_pciercx_cfg001_s cn68xxp1;
-       struct cvmx_pciercx_cfg001_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg002 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg002_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t bcc:8;
-               uint32_t sc:8;
-               uint32_t pi:8;
-               uint32_t rid:8;
-#else
-               uint32_t rid:8;
-               uint32_t pi:8;
-               uint32_t sc:8;
-               uint32_t bcc:8;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg002_s cn52xx;
-       struct cvmx_pciercx_cfg002_s cn52xxp1;
-       struct cvmx_pciercx_cfg002_s cn56xx;
-       struct cvmx_pciercx_cfg002_s cn56xxp1;
-       struct cvmx_pciercx_cfg002_s cn61xx;
-       struct cvmx_pciercx_cfg002_s cn63xx;
-       struct cvmx_pciercx_cfg002_s cn63xxp1;
-       struct cvmx_pciercx_cfg002_s cn66xx;
-       struct cvmx_pciercx_cfg002_s cn68xx;
-       struct cvmx_pciercx_cfg002_s cn68xxp1;
-       struct cvmx_pciercx_cfg002_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg003 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg003_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t bist:8;
-               uint32_t mfd:1;
-               uint32_t chf:7;
-               uint32_t lt:8;
-               uint32_t cls:8;
-#else
-               uint32_t cls:8;
-               uint32_t lt:8;
-               uint32_t chf:7;
-               uint32_t mfd:1;
-               uint32_t bist:8;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg003_s cn52xx;
-       struct cvmx_pciercx_cfg003_s cn52xxp1;
-       struct cvmx_pciercx_cfg003_s cn56xx;
-       struct cvmx_pciercx_cfg003_s cn56xxp1;
-       struct cvmx_pciercx_cfg003_s cn61xx;
-       struct cvmx_pciercx_cfg003_s cn63xx;
-       struct cvmx_pciercx_cfg003_s cn63xxp1;
-       struct cvmx_pciercx_cfg003_s cn66xx;
-       struct cvmx_pciercx_cfg003_s cn68xx;
-       struct cvmx_pciercx_cfg003_s cn68xxp1;
-       struct cvmx_pciercx_cfg003_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg004 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg004_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_0_31:32;
-#else
-               uint32_t reserved_0_31:32;
-#endif
+               __BITFIELD_FIELD(uint32_t dpe:1,
+               __BITFIELD_FIELD(uint32_t sse:1,
+               __BITFIELD_FIELD(uint32_t rma:1,
+               __BITFIELD_FIELD(uint32_t rta:1,
+               __BITFIELD_FIELD(uint32_t sta:1,
+               __BITFIELD_FIELD(uint32_t devt:2,
+               __BITFIELD_FIELD(uint32_t mdpe:1,
+               __BITFIELD_FIELD(uint32_t fbb:1,
+               __BITFIELD_FIELD(uint32_t reserved_22_22:1,
+               __BITFIELD_FIELD(uint32_t m66:1,
+               __BITFIELD_FIELD(uint32_t cl:1,
+               __BITFIELD_FIELD(uint32_t i_stat:1,
+               __BITFIELD_FIELD(uint32_t reserved_11_18:8,
+               __BITFIELD_FIELD(uint32_t i_dis:1,
+               __BITFIELD_FIELD(uint32_t fbbe:1,
+               __BITFIELD_FIELD(uint32_t see:1,
+               __BITFIELD_FIELD(uint32_t ids_wcc:1,
+               __BITFIELD_FIELD(uint32_t per:1,
+               __BITFIELD_FIELD(uint32_t vps:1,
+               __BITFIELD_FIELD(uint32_t mwice:1,
+               __BITFIELD_FIELD(uint32_t scse:1,
+               __BITFIELD_FIELD(uint32_t me:1,
+               __BITFIELD_FIELD(uint32_t msae:1,
+               __BITFIELD_FIELD(uint32_t isae:1,
+               ;))))))))))))))))))))))))
        } s;
-       struct cvmx_pciercx_cfg004_s cn52xx;
-       struct cvmx_pciercx_cfg004_s cn52xxp1;
-       struct cvmx_pciercx_cfg004_s cn56xx;
-       struct cvmx_pciercx_cfg004_s cn56xxp1;
-       struct cvmx_pciercx_cfg004_s cn61xx;
-       struct cvmx_pciercx_cfg004_s cn63xx;
-       struct cvmx_pciercx_cfg004_s cn63xxp1;
-       struct cvmx_pciercx_cfg004_s cn66xx;
-       struct cvmx_pciercx_cfg004_s cn68xx;
-       struct cvmx_pciercx_cfg004_s cn68xxp1;
-       struct cvmx_pciercx_cfg004_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg005 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg005_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_0_31:32;
-#else
-               uint32_t reserved_0_31:32;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg005_s cn52xx;
-       struct cvmx_pciercx_cfg005_s cn52xxp1;
-       struct cvmx_pciercx_cfg005_s cn56xx;
-       struct cvmx_pciercx_cfg005_s cn56xxp1;
-       struct cvmx_pciercx_cfg005_s cn61xx;
-       struct cvmx_pciercx_cfg005_s cn63xx;
-       struct cvmx_pciercx_cfg005_s cn63xxp1;
-       struct cvmx_pciercx_cfg005_s cn66xx;
-       struct cvmx_pciercx_cfg005_s cn68xx;
-       struct cvmx_pciercx_cfg005_s cn68xxp1;
-       struct cvmx_pciercx_cfg005_s cnf71xx;
 };
 
 union cvmx_pciercx_cfg006 {
        uint32_t u32;
        struct cvmx_pciercx_cfg006_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t slt:8;
-               uint32_t subbnum:8;
-               uint32_t sbnum:8;
-               uint32_t pbnum:8;
-#else
-               uint32_t pbnum:8;
-               uint32_t sbnum:8;
-               uint32_t subbnum:8;
-               uint32_t slt:8;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg006_s cn52xx;
-       struct cvmx_pciercx_cfg006_s cn52xxp1;
-       struct cvmx_pciercx_cfg006_s cn56xx;
-       struct cvmx_pciercx_cfg006_s cn56xxp1;
-       struct cvmx_pciercx_cfg006_s cn61xx;
-       struct cvmx_pciercx_cfg006_s cn63xx;
-       struct cvmx_pciercx_cfg006_s cn63xxp1;
-       struct cvmx_pciercx_cfg006_s cn66xx;
-       struct cvmx_pciercx_cfg006_s cn68xx;
-       struct cvmx_pciercx_cfg006_s cn68xxp1;
-       struct cvmx_pciercx_cfg006_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg007 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg007_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t dpe:1;
-               uint32_t sse:1;
-               uint32_t rma:1;
-               uint32_t rta:1;
-               uint32_t sta:1;
-               uint32_t devt:2;
-               uint32_t mdpe:1;
-               uint32_t fbb:1;
-               uint32_t reserved_22_22:1;
-               uint32_t m66:1;
-               uint32_t reserved_16_20:5;
-               uint32_t lio_limi:4;
-               uint32_t reserved_9_11:3;
-               uint32_t io32b:1;
-               uint32_t lio_base:4;
-               uint32_t reserved_1_3:3;
-               uint32_t io32a:1;
-#else
-               uint32_t io32a:1;
-               uint32_t reserved_1_3:3;
-               uint32_t lio_base:4;
-               uint32_t io32b:1;
-               uint32_t reserved_9_11:3;
-               uint32_t lio_limi:4;
-               uint32_t reserved_16_20:5;
-               uint32_t m66:1;
-               uint32_t reserved_22_22:1;
-               uint32_t fbb:1;
-               uint32_t mdpe:1;
-               uint32_t devt:2;
-               uint32_t sta:1;
-               uint32_t rta:1;
-               uint32_t rma:1;
-               uint32_t sse:1;
-               uint32_t dpe:1;
-#endif
+               __BITFIELD_FIELD(uint32_t slt:8,
+               __BITFIELD_FIELD(uint32_t subbnum:8,
+               __BITFIELD_FIELD(uint32_t sbnum:8,
+               __BITFIELD_FIELD(uint32_t pbnum:8,
+               ;))))
        } s;
-       struct cvmx_pciercx_cfg007_s cn52xx;
-       struct cvmx_pciercx_cfg007_s cn52xxp1;
-       struct cvmx_pciercx_cfg007_s cn56xx;
-       struct cvmx_pciercx_cfg007_s cn56xxp1;
-       struct cvmx_pciercx_cfg007_s cn61xx;
-       struct cvmx_pciercx_cfg007_s cn63xx;
-       struct cvmx_pciercx_cfg007_s cn63xxp1;
-       struct cvmx_pciercx_cfg007_s cn66xx;
-       struct cvmx_pciercx_cfg007_s cn68xx;
-       struct cvmx_pciercx_cfg007_s cn68xxp1;
-       struct cvmx_pciercx_cfg007_s cnf71xx;
 };
 
 union cvmx_pciercx_cfg008 {
        uint32_t u32;
        struct cvmx_pciercx_cfg008_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t ml_addr:12;
-               uint32_t reserved_16_19:4;
-               uint32_t mb_addr:12;
-               uint32_t reserved_0_3:4;
-#else
-               uint32_t reserved_0_3:4;
-               uint32_t mb_addr:12;
-               uint32_t reserved_16_19:4;
-               uint32_t ml_addr:12;
-#endif
+               __BITFIELD_FIELD(uint32_t ml_addr:12,
+               __BITFIELD_FIELD(uint32_t reserved_16_19:4,
+               __BITFIELD_FIELD(uint32_t mb_addr:12,
+               __BITFIELD_FIELD(uint32_t reserved_0_3:4,
+               ;))))
        } s;
-       struct cvmx_pciercx_cfg008_s cn52xx;
-       struct cvmx_pciercx_cfg008_s cn52xxp1;
-       struct cvmx_pciercx_cfg008_s cn56xx;
-       struct cvmx_pciercx_cfg008_s cn56xxp1;
-       struct cvmx_pciercx_cfg008_s cn61xx;
-       struct cvmx_pciercx_cfg008_s cn63xx;
-       struct cvmx_pciercx_cfg008_s cn63xxp1;
-       struct cvmx_pciercx_cfg008_s cn66xx;
-       struct cvmx_pciercx_cfg008_s cn68xx;
-       struct cvmx_pciercx_cfg008_s cn68xxp1;
-       struct cvmx_pciercx_cfg008_s cnf71xx;
 };
 
 union cvmx_pciercx_cfg009 {
        uint32_t u32;
        struct cvmx_pciercx_cfg009_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t lmem_limit:12;
-               uint32_t reserved_17_19:3;
-               uint32_t mem64b:1;
-               uint32_t lmem_base:12;
-               uint32_t reserved_1_3:3;
-               uint32_t mem64a:1;
-#else
-               uint32_t mem64a:1;
-               uint32_t reserved_1_3:3;
-               uint32_t lmem_base:12;
-               uint32_t mem64b:1;
-               uint32_t reserved_17_19:3;
-               uint32_t lmem_limit:12;
-#endif
+               __BITFIELD_FIELD(uint32_t lmem_limit:12,
+               __BITFIELD_FIELD(uint32_t reserved_17_19:3,
+               __BITFIELD_FIELD(uint32_t mem64b:1,
+               __BITFIELD_FIELD(uint32_t lmem_base:12,
+               __BITFIELD_FIELD(uint32_t reserved_1_3:3,
+               __BITFIELD_FIELD(uint32_t mem64a:1,
+               ;))))))
        } s;
-       struct cvmx_pciercx_cfg009_s cn52xx;
-       struct cvmx_pciercx_cfg009_s cn52xxp1;
-       struct cvmx_pciercx_cfg009_s cn56xx;
-       struct cvmx_pciercx_cfg009_s cn56xxp1;
-       struct cvmx_pciercx_cfg009_s cn61xx;
-       struct cvmx_pciercx_cfg009_s cn63xx;
-       struct cvmx_pciercx_cfg009_s cn63xxp1;
-       struct cvmx_pciercx_cfg009_s cn66xx;
-       struct cvmx_pciercx_cfg009_s cn68xx;
-       struct cvmx_pciercx_cfg009_s cn68xxp1;
-       struct cvmx_pciercx_cfg009_s cnf71xx;
 };
 
 union cvmx_pciercx_cfg010 {
        uint32_t u32;
        struct cvmx_pciercx_cfg010_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t umem_base:32;
-#else
-               uint32_t umem_base:32;
-#endif
+               uint32_t umem_base;
        } s;
-       struct cvmx_pciercx_cfg010_s cn52xx;
-       struct cvmx_pciercx_cfg010_s cn52xxp1;
-       struct cvmx_pciercx_cfg010_s cn56xx;
-       struct cvmx_pciercx_cfg010_s cn56xxp1;
-       struct cvmx_pciercx_cfg010_s cn61xx;
-       struct cvmx_pciercx_cfg010_s cn63xx;
-       struct cvmx_pciercx_cfg010_s cn63xxp1;
-       struct cvmx_pciercx_cfg010_s cn66xx;
-       struct cvmx_pciercx_cfg010_s cn68xx;
-       struct cvmx_pciercx_cfg010_s cn68xxp1;
-       struct cvmx_pciercx_cfg010_s cnf71xx;
 };
 
 union cvmx_pciercx_cfg011 {
        uint32_t u32;
        struct cvmx_pciercx_cfg011_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t umem_limit:32;
-#else
-               uint32_t umem_limit:32;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg011_s cn52xx;
-       struct cvmx_pciercx_cfg011_s cn52xxp1;
-       struct cvmx_pciercx_cfg011_s cn56xx;
-       struct cvmx_pciercx_cfg011_s cn56xxp1;
-       struct cvmx_pciercx_cfg011_s cn61xx;
-       struct cvmx_pciercx_cfg011_s cn63xx;
-       struct cvmx_pciercx_cfg011_s cn63xxp1;
-       struct cvmx_pciercx_cfg011_s cn66xx;
-       struct cvmx_pciercx_cfg011_s cn68xx;
-       struct cvmx_pciercx_cfg011_s cn68xxp1;
-       struct cvmx_pciercx_cfg011_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg012 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg012_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t uio_limit:16;
-               uint32_t uio_base:16;
-#else
-               uint32_t uio_base:16;
-               uint32_t uio_limit:16;
-#endif
+               uint32_t umem_limit;
        } s;
-       struct cvmx_pciercx_cfg012_s cn52xx;
-       struct cvmx_pciercx_cfg012_s cn52xxp1;
-       struct cvmx_pciercx_cfg012_s cn56xx;
-       struct cvmx_pciercx_cfg012_s cn56xxp1;
-       struct cvmx_pciercx_cfg012_s cn61xx;
-       struct cvmx_pciercx_cfg012_s cn63xx;
-       struct cvmx_pciercx_cfg012_s cn63xxp1;
-       struct cvmx_pciercx_cfg012_s cn66xx;
-       struct cvmx_pciercx_cfg012_s cn68xx;
-       struct cvmx_pciercx_cfg012_s cn68xxp1;
-       struct cvmx_pciercx_cfg012_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg013 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg013_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_8_31:24;
-               uint32_t cp:8;
-#else
-               uint32_t cp:8;
-               uint32_t reserved_8_31:24;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg013_s cn52xx;
-       struct cvmx_pciercx_cfg013_s cn52xxp1;
-       struct cvmx_pciercx_cfg013_s cn56xx;
-       struct cvmx_pciercx_cfg013_s cn56xxp1;
-       struct cvmx_pciercx_cfg013_s cn61xx;
-       struct cvmx_pciercx_cfg013_s cn63xx;
-       struct cvmx_pciercx_cfg013_s cn63xxp1;
-       struct cvmx_pciercx_cfg013_s cn66xx;
-       struct cvmx_pciercx_cfg013_s cn68xx;
-       struct cvmx_pciercx_cfg013_s cn68xxp1;
-       struct cvmx_pciercx_cfg013_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg014 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg014_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_0_31:32;
-#else
-               uint32_t reserved_0_31:32;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg014_s cn52xx;
-       struct cvmx_pciercx_cfg014_s cn52xxp1;
-       struct cvmx_pciercx_cfg014_s cn56xx;
-       struct cvmx_pciercx_cfg014_s cn56xxp1;
-       struct cvmx_pciercx_cfg014_s cn61xx;
-       struct cvmx_pciercx_cfg014_s cn63xx;
-       struct cvmx_pciercx_cfg014_s cn63xxp1;
-       struct cvmx_pciercx_cfg014_s cn66xx;
-       struct cvmx_pciercx_cfg014_s cn68xx;
-       struct cvmx_pciercx_cfg014_s cn68xxp1;
-       struct cvmx_pciercx_cfg014_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg015 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg015_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_28_31:4;
-               uint32_t dtsees:1;
-               uint32_t dts:1;
-               uint32_t sdt:1;
-               uint32_t pdt:1;
-               uint32_t fbbe:1;
-               uint32_t sbrst:1;
-               uint32_t mam:1;
-               uint32_t vga16d:1;
-               uint32_t vgae:1;
-               uint32_t isae:1;
-               uint32_t see:1;
-               uint32_t pere:1;
-               uint32_t inta:8;
-               uint32_t il:8;
-#else
-               uint32_t il:8;
-               uint32_t inta:8;
-               uint32_t pere:1;
-               uint32_t see:1;
-               uint32_t isae:1;
-               uint32_t vgae:1;
-               uint32_t vga16d:1;
-               uint32_t mam:1;
-               uint32_t sbrst:1;
-               uint32_t fbbe:1;
-               uint32_t pdt:1;
-               uint32_t sdt:1;
-               uint32_t dts:1;
-               uint32_t dtsees:1;
-               uint32_t reserved_28_31:4;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg015_s cn52xx;
-       struct cvmx_pciercx_cfg015_s cn52xxp1;
-       struct cvmx_pciercx_cfg015_s cn56xx;
-       struct cvmx_pciercx_cfg015_s cn56xxp1;
-       struct cvmx_pciercx_cfg015_s cn61xx;
-       struct cvmx_pciercx_cfg015_s cn63xx;
-       struct cvmx_pciercx_cfg015_s cn63xxp1;
-       struct cvmx_pciercx_cfg015_s cn66xx;
-       struct cvmx_pciercx_cfg015_s cn68xx;
-       struct cvmx_pciercx_cfg015_s cn68xxp1;
-       struct cvmx_pciercx_cfg015_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg016 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg016_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t pmes:5;
-               uint32_t d2s:1;
-               uint32_t d1s:1;
-               uint32_t auxc:3;
-               uint32_t dsi:1;
-               uint32_t reserved_20_20:1;
-               uint32_t pme_clock:1;
-               uint32_t pmsv:3;
-               uint32_t ncp:8;
-               uint32_t pmcid:8;
-#else
-               uint32_t pmcid:8;
-               uint32_t ncp:8;
-               uint32_t pmsv:3;
-               uint32_t pme_clock:1;
-               uint32_t reserved_20_20:1;
-               uint32_t dsi:1;
-               uint32_t auxc:3;
-               uint32_t d1s:1;
-               uint32_t d2s:1;
-               uint32_t pmes:5;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg016_s cn52xx;
-       struct cvmx_pciercx_cfg016_s cn52xxp1;
-       struct cvmx_pciercx_cfg016_s cn56xx;
-       struct cvmx_pciercx_cfg016_s cn56xxp1;
-       struct cvmx_pciercx_cfg016_s cn61xx;
-       struct cvmx_pciercx_cfg016_s cn63xx;
-       struct cvmx_pciercx_cfg016_s cn63xxp1;
-       struct cvmx_pciercx_cfg016_s cn66xx;
-       struct cvmx_pciercx_cfg016_s cn68xx;
-       struct cvmx_pciercx_cfg016_s cn68xxp1;
-       struct cvmx_pciercx_cfg016_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg017 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg017_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t pmdia:8;
-               uint32_t bpccee:1;
-               uint32_t bd3h:1;
-               uint32_t reserved_16_21:6;
-               uint32_t pmess:1;
-               uint32_t pmedsia:2;
-               uint32_t pmds:4;
-               uint32_t pmeens:1;
-               uint32_t reserved_4_7:4;
-               uint32_t nsr:1;
-               uint32_t reserved_2_2:1;
-               uint32_t ps:2;
-#else
-               uint32_t ps:2;
-               uint32_t reserved_2_2:1;
-               uint32_t nsr:1;
-               uint32_t reserved_4_7:4;
-               uint32_t pmeens:1;
-               uint32_t pmds:4;
-               uint32_t pmedsia:2;
-               uint32_t pmess:1;
-               uint32_t reserved_16_21:6;
-               uint32_t bd3h:1;
-               uint32_t bpccee:1;
-               uint32_t pmdia:8;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg017_s cn52xx;
-       struct cvmx_pciercx_cfg017_s cn52xxp1;
-       struct cvmx_pciercx_cfg017_s cn56xx;
-       struct cvmx_pciercx_cfg017_s cn56xxp1;
-       struct cvmx_pciercx_cfg017_s cn61xx;
-       struct cvmx_pciercx_cfg017_s cn63xx;
-       struct cvmx_pciercx_cfg017_s cn63xxp1;
-       struct cvmx_pciercx_cfg017_s cn66xx;
-       struct cvmx_pciercx_cfg017_s cn68xx;
-       struct cvmx_pciercx_cfg017_s cn68xxp1;
-       struct cvmx_pciercx_cfg017_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg020 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg020_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_25_31:7;
-               uint32_t pvm:1;
-               uint32_t m64:1;
-               uint32_t mme:3;
-               uint32_t mmc:3;
-               uint32_t msien:1;
-               uint32_t ncp:8;
-               uint32_t msicid:8;
-#else
-               uint32_t msicid:8;
-               uint32_t ncp:8;
-               uint32_t msien:1;
-               uint32_t mmc:3;
-               uint32_t mme:3;
-               uint32_t m64:1;
-               uint32_t pvm:1;
-               uint32_t reserved_25_31:7;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg020_cn52xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_24_31:8;
-               uint32_t m64:1;
-               uint32_t mme:3;
-               uint32_t mmc:3;
-               uint32_t msien:1;
-               uint32_t ncp:8;
-               uint32_t msicid:8;
-#else
-               uint32_t msicid:8;
-               uint32_t ncp:8;
-               uint32_t msien:1;
-               uint32_t mmc:3;
-               uint32_t mme:3;
-               uint32_t m64:1;
-               uint32_t reserved_24_31:8;
-#endif
-       } cn52xx;
-       struct cvmx_pciercx_cfg020_cn52xx cn52xxp1;
-       struct cvmx_pciercx_cfg020_cn52xx cn56xx;
-       struct cvmx_pciercx_cfg020_cn52xx cn56xxp1;
-       struct cvmx_pciercx_cfg020_s cn61xx;
-       struct cvmx_pciercx_cfg020_cn52xx cn63xx;
-       struct cvmx_pciercx_cfg020_cn52xx cn63xxp1;
-       struct cvmx_pciercx_cfg020_cn52xx cn66xx;
-       struct cvmx_pciercx_cfg020_cn52xx cn68xx;
-       struct cvmx_pciercx_cfg020_cn52xx cn68xxp1;
-       struct cvmx_pciercx_cfg020_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg021 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg021_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t lmsi:30;
-               uint32_t reserved_0_1:2;
-#else
-               uint32_t reserved_0_1:2;
-               uint32_t lmsi:30;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg021_s cn52xx;
-       struct cvmx_pciercx_cfg021_s cn52xxp1;
-       struct cvmx_pciercx_cfg021_s cn56xx;
-       struct cvmx_pciercx_cfg021_s cn56xxp1;
-       struct cvmx_pciercx_cfg021_s cn61xx;
-       struct cvmx_pciercx_cfg021_s cn63xx;
-       struct cvmx_pciercx_cfg021_s cn63xxp1;
-       struct cvmx_pciercx_cfg021_s cn66xx;
-       struct cvmx_pciercx_cfg021_s cn68xx;
-       struct cvmx_pciercx_cfg021_s cn68xxp1;
-       struct cvmx_pciercx_cfg021_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg022 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg022_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t umsi:32;
-#else
-               uint32_t umsi:32;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg022_s cn52xx;
-       struct cvmx_pciercx_cfg022_s cn52xxp1;
-       struct cvmx_pciercx_cfg022_s cn56xx;
-       struct cvmx_pciercx_cfg022_s cn56xxp1;
-       struct cvmx_pciercx_cfg022_s cn61xx;
-       struct cvmx_pciercx_cfg022_s cn63xx;
-       struct cvmx_pciercx_cfg022_s cn63xxp1;
-       struct cvmx_pciercx_cfg022_s cn66xx;
-       struct cvmx_pciercx_cfg022_s cn68xx;
-       struct cvmx_pciercx_cfg022_s cn68xxp1;
-       struct cvmx_pciercx_cfg022_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg023 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg023_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_16_31:16;
-               uint32_t msimd:16;
-#else
-               uint32_t msimd:16;
-               uint32_t reserved_16_31:16;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg023_s cn52xx;
-       struct cvmx_pciercx_cfg023_s cn52xxp1;
-       struct cvmx_pciercx_cfg023_s cn56xx;
-       struct cvmx_pciercx_cfg023_s cn56xxp1;
-       struct cvmx_pciercx_cfg023_s cn61xx;
-       struct cvmx_pciercx_cfg023_s cn63xx;
-       struct cvmx_pciercx_cfg023_s cn63xxp1;
-       struct cvmx_pciercx_cfg023_s cn66xx;
-       struct cvmx_pciercx_cfg023_s cn68xx;
-       struct cvmx_pciercx_cfg023_s cn68xxp1;
-       struct cvmx_pciercx_cfg023_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg028 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg028_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_30_31:2;
-               uint32_t imn:5;
-               uint32_t si:1;
-               uint32_t dpt:4;
-               uint32_t pciecv:4;
-               uint32_t ncp:8;
-               uint32_t pcieid:8;
-#else
-               uint32_t pcieid:8;
-               uint32_t ncp:8;
-               uint32_t pciecv:4;
-               uint32_t dpt:4;
-               uint32_t si:1;
-               uint32_t imn:5;
-               uint32_t reserved_30_31:2;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg028_s cn52xx;
-       struct cvmx_pciercx_cfg028_s cn52xxp1;
-       struct cvmx_pciercx_cfg028_s cn56xx;
-       struct cvmx_pciercx_cfg028_s cn56xxp1;
-       struct cvmx_pciercx_cfg028_s cn61xx;
-       struct cvmx_pciercx_cfg028_s cn63xx;
-       struct cvmx_pciercx_cfg028_s cn63xxp1;
-       struct cvmx_pciercx_cfg028_s cn66xx;
-       struct cvmx_pciercx_cfg028_s cn68xx;
-       struct cvmx_pciercx_cfg028_s cn68xxp1;
-       struct cvmx_pciercx_cfg028_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg029 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg029_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_28_31:4;
-               uint32_t cspls:2;
-               uint32_t csplv:8;
-               uint32_t reserved_16_17:2;
-               uint32_t rber:1;
-               uint32_t reserved_12_14:3;
-               uint32_t el1al:3;
-               uint32_t el0al:3;
-               uint32_t etfs:1;
-               uint32_t pfs:2;
-               uint32_t mpss:3;
-#else
-               uint32_t mpss:3;
-               uint32_t pfs:2;
-               uint32_t etfs:1;
-               uint32_t el0al:3;
-               uint32_t el1al:3;
-               uint32_t reserved_12_14:3;
-               uint32_t rber:1;
-               uint32_t reserved_16_17:2;
-               uint32_t csplv:8;
-               uint32_t cspls:2;
-               uint32_t reserved_28_31:4;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg029_s cn52xx;
-       struct cvmx_pciercx_cfg029_s cn52xxp1;
-       struct cvmx_pciercx_cfg029_s cn56xx;
-       struct cvmx_pciercx_cfg029_s cn56xxp1;
-       struct cvmx_pciercx_cfg029_s cn61xx;
-       struct cvmx_pciercx_cfg029_s cn63xx;
-       struct cvmx_pciercx_cfg029_s cn63xxp1;
-       struct cvmx_pciercx_cfg029_s cn66xx;
-       struct cvmx_pciercx_cfg029_s cn68xx;
-       struct cvmx_pciercx_cfg029_s cn68xxp1;
-       struct cvmx_pciercx_cfg029_s cnf71xx;
 };
 
 union cvmx_pciercx_cfg030 {
        uint32_t u32;
        struct cvmx_pciercx_cfg030_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_22_31:10;
-               uint32_t tp:1;
-               uint32_t ap_d:1;
-               uint32_t ur_d:1;
-               uint32_t fe_d:1;
-               uint32_t nfe_d:1;
-               uint32_t ce_d:1;
-               uint32_t reserved_15_15:1;
-               uint32_t mrrs:3;
-               uint32_t ns_en:1;
-               uint32_t ap_en:1;
-               uint32_t pf_en:1;
-               uint32_t etf_en:1;
-               uint32_t mps:3;
-               uint32_t ro_en:1;
-               uint32_t ur_en:1;
-               uint32_t fe_en:1;
-               uint32_t nfe_en:1;
-               uint32_t ce_en:1;
-#else
-               uint32_t ce_en:1;
-               uint32_t nfe_en:1;
-               uint32_t fe_en:1;
-               uint32_t ur_en:1;
-               uint32_t ro_en:1;
-               uint32_t mps:3;
-               uint32_t etf_en:1;
-               uint32_t pf_en:1;
-               uint32_t ap_en:1;
-               uint32_t ns_en:1;
-               uint32_t mrrs:3;
-               uint32_t reserved_15_15:1;
-               uint32_t ce_d:1;
-               uint32_t nfe_d:1;
-               uint32_t fe_d:1;
-               uint32_t ur_d:1;
-               uint32_t ap_d:1;
-               uint32_t tp:1;
-               uint32_t reserved_22_31:10;
-#endif
+               __BITFIELD_FIELD(uint32_t reserved_22_31:10,
+               __BITFIELD_FIELD(uint32_t tp:1,
+               __BITFIELD_FIELD(uint32_t ap_d:1,
+               __BITFIELD_FIELD(uint32_t ur_d:1,
+               __BITFIELD_FIELD(uint32_t fe_d:1,
+               __BITFIELD_FIELD(uint32_t nfe_d:1,
+               __BITFIELD_FIELD(uint32_t ce_d:1,
+               __BITFIELD_FIELD(uint32_t reserved_15_15:1,
+               __BITFIELD_FIELD(uint32_t mrrs:3,
+               __BITFIELD_FIELD(uint32_t ns_en:1,
+               __BITFIELD_FIELD(uint32_t ap_en:1,
+               __BITFIELD_FIELD(uint32_t pf_en:1,
+               __BITFIELD_FIELD(uint32_t etf_en:1,
+               __BITFIELD_FIELD(uint32_t mps:3,
+               __BITFIELD_FIELD(uint32_t ro_en:1,
+               __BITFIELD_FIELD(uint32_t ur_en:1,
+               __BITFIELD_FIELD(uint32_t fe_en:1,
+               __BITFIELD_FIELD(uint32_t nfe_en:1,
+               __BITFIELD_FIELD(uint32_t ce_en:1,
+               ;)))))))))))))))))))
        } s;
-       struct cvmx_pciercx_cfg030_s cn52xx;
-       struct cvmx_pciercx_cfg030_s cn52xxp1;
-       struct cvmx_pciercx_cfg030_s cn56xx;
-       struct cvmx_pciercx_cfg030_s cn56xxp1;
-       struct cvmx_pciercx_cfg030_s cn61xx;
-       struct cvmx_pciercx_cfg030_s cn63xx;
-       struct cvmx_pciercx_cfg030_s cn63xxp1;
-       struct cvmx_pciercx_cfg030_s cn66xx;
-       struct cvmx_pciercx_cfg030_s cn68xx;
-       struct cvmx_pciercx_cfg030_s cn68xxp1;
-       struct cvmx_pciercx_cfg030_s cnf71xx;
 };
 
 union cvmx_pciercx_cfg031 {
        uint32_t u32;
        struct cvmx_pciercx_cfg031_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t pnum:8;
-               uint32_t reserved_23_23:1;
-               uint32_t aspm:1;
-               uint32_t lbnc:1;
-               uint32_t dllarc:1;
-               uint32_t sderc:1;
-               uint32_t cpm:1;
-               uint32_t l1el:3;
-               uint32_t l0el:3;
-               uint32_t aslpms:2;
-               uint32_t mlw:6;
-               uint32_t mls:4;
-#else
-               uint32_t mls:4;
-               uint32_t mlw:6;
-               uint32_t aslpms:2;
-               uint32_t l0el:3;
-               uint32_t l1el:3;
-               uint32_t cpm:1;
-               uint32_t sderc:1;
-               uint32_t dllarc:1;
-               uint32_t lbnc:1;
-               uint32_t aspm:1;
-               uint32_t reserved_23_23:1;
-               uint32_t pnum:8;
-#endif
+               __BITFIELD_FIELD(uint32_t pnum:8,
+               __BITFIELD_FIELD(uint32_t reserved_23_23:1,
+               __BITFIELD_FIELD(uint32_t aspm:1,
+               __BITFIELD_FIELD(uint32_t lbnc:1,
+               __BITFIELD_FIELD(uint32_t dllarc:1,
+               __BITFIELD_FIELD(uint32_t sderc:1,
+               __BITFIELD_FIELD(uint32_t cpm:1,
+               __BITFIELD_FIELD(uint32_t l1el:3,
+               __BITFIELD_FIELD(uint32_t l0el:3,
+               __BITFIELD_FIELD(uint32_t aslpms:2,
+               __BITFIELD_FIELD(uint32_t mlw:6,
+               __BITFIELD_FIELD(uint32_t mls:4,
+               ;))))))))))))
        } s;
-       struct cvmx_pciercx_cfg031_cn52xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t pnum:8;
-               uint32_t reserved_22_23:2;
-               uint32_t lbnc:1;
-               uint32_t dllarc:1;
-               uint32_t sderc:1;
-               uint32_t cpm:1;
-               uint32_t l1el:3;
-               uint32_t l0el:3;
-               uint32_t aslpms:2;
-               uint32_t mlw:6;
-               uint32_t mls:4;
-#else
-               uint32_t mls:4;
-               uint32_t mlw:6;
-               uint32_t aslpms:2;
-               uint32_t l0el:3;
-               uint32_t l1el:3;
-               uint32_t cpm:1;
-               uint32_t sderc:1;
-               uint32_t dllarc:1;
-               uint32_t lbnc:1;
-               uint32_t reserved_22_23:2;
-               uint32_t pnum:8;
-#endif
-       } cn52xx;
-       struct cvmx_pciercx_cfg031_cn52xx cn52xxp1;
-       struct cvmx_pciercx_cfg031_cn52xx cn56xx;
-       struct cvmx_pciercx_cfg031_cn52xx cn56xxp1;
-       struct cvmx_pciercx_cfg031_s cn61xx;
-       struct cvmx_pciercx_cfg031_cn52xx cn63xx;
-       struct cvmx_pciercx_cfg031_cn52xx cn63xxp1;
-       struct cvmx_pciercx_cfg031_s cn66xx;
-       struct cvmx_pciercx_cfg031_s cn68xx;
-       struct cvmx_pciercx_cfg031_cn52xx cn68xxp1;
-       struct cvmx_pciercx_cfg031_s cnf71xx;
 };
 
 union cvmx_pciercx_cfg032 {
        uint32_t u32;
        struct cvmx_pciercx_cfg032_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t lab:1;
-               uint32_t lbm:1;
-               uint32_t dlla:1;
-               uint32_t scc:1;
-               uint32_t lt:1;
-               uint32_t reserved_26_26:1;
-               uint32_t nlw:6;
-               uint32_t ls:4;
-               uint32_t reserved_12_15:4;
-               uint32_t lab_int_enb:1;
-               uint32_t lbm_int_enb:1;
-               uint32_t hawd:1;
-               uint32_t ecpm:1;
-               uint32_t es:1;
-               uint32_t ccc:1;
-               uint32_t rl:1;
-               uint32_t ld:1;
-               uint32_t rcb:1;
-               uint32_t reserved_2_2:1;
-               uint32_t aslpc:2;
-#else
-               uint32_t aslpc:2;
-               uint32_t reserved_2_2:1;
-               uint32_t rcb:1;
-               uint32_t ld:1;
-               uint32_t rl:1;
-               uint32_t ccc:1;
-               uint32_t es:1;
-               uint32_t ecpm:1;
-               uint32_t hawd:1;
-               uint32_t lbm_int_enb:1;
-               uint32_t lab_int_enb:1;
-               uint32_t reserved_12_15:4;
-               uint32_t ls:4;
-               uint32_t nlw:6;
-               uint32_t reserved_26_26:1;
-               uint32_t lt:1;
-               uint32_t scc:1;
-               uint32_t dlla:1;
-               uint32_t lbm:1;
-               uint32_t lab:1;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg032_s cn52xx;
-       struct cvmx_pciercx_cfg032_s cn52xxp1;
-       struct cvmx_pciercx_cfg032_s cn56xx;
-       struct cvmx_pciercx_cfg032_s cn56xxp1;
-       struct cvmx_pciercx_cfg032_s cn61xx;
-       struct cvmx_pciercx_cfg032_s cn63xx;
-       struct cvmx_pciercx_cfg032_s cn63xxp1;
-       struct cvmx_pciercx_cfg032_s cn66xx;
-       struct cvmx_pciercx_cfg032_s cn68xx;
-       struct cvmx_pciercx_cfg032_s cn68xxp1;
-       struct cvmx_pciercx_cfg032_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg033 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg033_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t ps_num:13;
-               uint32_t nccs:1;
-               uint32_t emip:1;
-               uint32_t sp_ls:2;
-               uint32_t sp_lv:8;
-               uint32_t hp_c:1;
-               uint32_t hp_s:1;
-               uint32_t pip:1;
-               uint32_t aip:1;
-               uint32_t mrlsp:1;
-               uint32_t pcp:1;
-               uint32_t abp:1;
-#else
-               uint32_t abp:1;
-               uint32_t pcp:1;
-               uint32_t mrlsp:1;
-               uint32_t aip:1;
-               uint32_t pip:1;
-               uint32_t hp_s:1;
-               uint32_t hp_c:1;
-               uint32_t sp_lv:8;
-               uint32_t sp_ls:2;
-               uint32_t emip:1;
-               uint32_t nccs:1;
-               uint32_t ps_num:13;
-#endif
+               __BITFIELD_FIELD(uint32_t lab:1,
+               __BITFIELD_FIELD(uint32_t lbm:1,
+               __BITFIELD_FIELD(uint32_t dlla:1,
+               __BITFIELD_FIELD(uint32_t scc:1,
+               __BITFIELD_FIELD(uint32_t lt:1,
+               __BITFIELD_FIELD(uint32_t reserved_26_26:1,
+               __BITFIELD_FIELD(uint32_t nlw:6,
+               __BITFIELD_FIELD(uint32_t ls:4,
+               __BITFIELD_FIELD(uint32_t reserved_12_15:4,
+               __BITFIELD_FIELD(uint32_t lab_int_enb:1,
+               __BITFIELD_FIELD(uint32_t lbm_int_enb:1,
+               __BITFIELD_FIELD(uint32_t hawd:1,
+               __BITFIELD_FIELD(uint32_t ecpm:1,
+               __BITFIELD_FIELD(uint32_t es:1,
+               __BITFIELD_FIELD(uint32_t ccc:1,
+               __BITFIELD_FIELD(uint32_t rl:1,
+               __BITFIELD_FIELD(uint32_t ld:1,
+               __BITFIELD_FIELD(uint32_t rcb:1,
+               __BITFIELD_FIELD(uint32_t reserved_2_2:1,
+               __BITFIELD_FIELD(uint32_t aslpc:2,
+               ;))))))))))))))))))))
        } s;
-       struct cvmx_pciercx_cfg033_s cn52xx;
-       struct cvmx_pciercx_cfg033_s cn52xxp1;
-       struct cvmx_pciercx_cfg033_s cn56xx;
-       struct cvmx_pciercx_cfg033_s cn56xxp1;
-       struct cvmx_pciercx_cfg033_s cn61xx;
-       struct cvmx_pciercx_cfg033_s cn63xx;
-       struct cvmx_pciercx_cfg033_s cn63xxp1;
-       struct cvmx_pciercx_cfg033_s cn66xx;
-       struct cvmx_pciercx_cfg033_s cn68xx;
-       struct cvmx_pciercx_cfg033_s cn68xxp1;
-       struct cvmx_pciercx_cfg033_s cnf71xx;
 };
 
 union cvmx_pciercx_cfg034 {
        uint32_t u32;
        struct cvmx_pciercx_cfg034_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_25_31:7;
-               uint32_t dlls_c:1;
-               uint32_t emis:1;
-               uint32_t pds:1;
-               uint32_t mrlss:1;
-               uint32_t ccint_d:1;
-               uint32_t pd_c:1;
-               uint32_t mrls_c:1;
-               uint32_t pf_d:1;
-               uint32_t abp_d:1;
-               uint32_t reserved_13_15:3;
-               uint32_t dlls_en:1;
-               uint32_t emic:1;
-               uint32_t pcc:1;
-               uint32_t pic:2;
-               uint32_t aic:2;
-               uint32_t hpint_en:1;
-               uint32_t ccint_en:1;
-               uint32_t pd_en:1;
-               uint32_t mrls_en:1;
-               uint32_t pf_en:1;
-               uint32_t abp_en:1;
-#else
-               uint32_t abp_en:1;
-               uint32_t pf_en:1;
-               uint32_t mrls_en:1;
-               uint32_t pd_en:1;
-               uint32_t ccint_en:1;
-               uint32_t hpint_en:1;
-               uint32_t aic:2;
-               uint32_t pic:2;
-               uint32_t pcc:1;
-               uint32_t emic:1;
-               uint32_t dlls_en:1;
-               uint32_t reserved_13_15:3;
-               uint32_t abp_d:1;
-               uint32_t pf_d:1;
-               uint32_t mrls_c:1;
-               uint32_t pd_c:1;
-               uint32_t ccint_d:1;
-               uint32_t mrlss:1;
-               uint32_t pds:1;
-               uint32_t emis:1;
-               uint32_t dlls_c:1;
-               uint32_t reserved_25_31:7;
-#endif
+               __BITFIELD_FIELD(uint32_t reserved_25_31:7,
+               __BITFIELD_FIELD(uint32_t dlls_c:1,
+               __BITFIELD_FIELD(uint32_t emis:1,
+               __BITFIELD_FIELD(uint32_t pds:1,
+               __BITFIELD_FIELD(uint32_t mrlss:1,
+               __BITFIELD_FIELD(uint32_t ccint_d:1,
+               __BITFIELD_FIELD(uint32_t pd_c:1,
+               __BITFIELD_FIELD(uint32_t mrls_c:1,
+               __BITFIELD_FIELD(uint32_t pf_d:1,
+               __BITFIELD_FIELD(uint32_t abp_d:1,
+               __BITFIELD_FIELD(uint32_t reserved_13_15:3,
+               __BITFIELD_FIELD(uint32_t dlls_en:1,
+               __BITFIELD_FIELD(uint32_t emic:1,
+               __BITFIELD_FIELD(uint32_t pcc:1,
+               __BITFIELD_FIELD(uint32_t pic:1,
+               __BITFIELD_FIELD(uint32_t aic:1,
+               __BITFIELD_FIELD(uint32_t hpint_en:1,
+               __BITFIELD_FIELD(uint32_t ccint_en:1,
+               __BITFIELD_FIELD(uint32_t pd_en:1,
+               __BITFIELD_FIELD(uint32_t mrls_en:1,
+               __BITFIELD_FIELD(uint32_t pf_en:1,
+               __BITFIELD_FIELD(uint32_t abp_en:1,
+               ;))))))))))))))))))))))
        } s;
-       struct cvmx_pciercx_cfg034_s cn52xx;
-       struct cvmx_pciercx_cfg034_s cn52xxp1;
-       struct cvmx_pciercx_cfg034_s cn56xx;
-       struct cvmx_pciercx_cfg034_s cn56xxp1;
-       struct cvmx_pciercx_cfg034_s cn61xx;
-       struct cvmx_pciercx_cfg034_s cn63xx;
-       struct cvmx_pciercx_cfg034_s cn63xxp1;
-       struct cvmx_pciercx_cfg034_s cn66xx;
-       struct cvmx_pciercx_cfg034_s cn68xx;
-       struct cvmx_pciercx_cfg034_s cn68xxp1;
-       struct cvmx_pciercx_cfg034_s cnf71xx;
 };
 
 union cvmx_pciercx_cfg035 {
        uint32_t u32;
        struct cvmx_pciercx_cfg035_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_17_31:15;
-               uint32_t crssv:1;
-               uint32_t reserved_5_15:11;
-               uint32_t crssve:1;
-               uint32_t pmeie:1;
-               uint32_t sefee:1;
-               uint32_t senfee:1;
-               uint32_t secee:1;
-#else
-               uint32_t secee:1;
-               uint32_t senfee:1;
-               uint32_t sefee:1;
-               uint32_t pmeie:1;
-               uint32_t crssve:1;
-               uint32_t reserved_5_15:11;
-               uint32_t crssv:1;
-               uint32_t reserved_17_31:15;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg035_s cn52xx;
-       struct cvmx_pciercx_cfg035_s cn52xxp1;
-       struct cvmx_pciercx_cfg035_s cn56xx;
-       struct cvmx_pciercx_cfg035_s cn56xxp1;
-       struct cvmx_pciercx_cfg035_s cn61xx;
-       struct cvmx_pciercx_cfg035_s cn63xx;
-       struct cvmx_pciercx_cfg035_s cn63xxp1;
-       struct cvmx_pciercx_cfg035_s cn66xx;
-       struct cvmx_pciercx_cfg035_s cn68xx;
-       struct cvmx_pciercx_cfg035_s cn68xxp1;
-       struct cvmx_pciercx_cfg035_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg036 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg036_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_18_31:14;
-               uint32_t pme_pend:1;
-               uint32_t pme_stat:1;
-               uint32_t pme_rid:16;
-#else
-               uint32_t pme_rid:16;
-               uint32_t pme_stat:1;
-               uint32_t pme_pend:1;
-               uint32_t reserved_18_31:14;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg036_s cn52xx;
-       struct cvmx_pciercx_cfg036_s cn52xxp1;
-       struct cvmx_pciercx_cfg036_s cn56xx;
-       struct cvmx_pciercx_cfg036_s cn56xxp1;
-       struct cvmx_pciercx_cfg036_s cn61xx;
-       struct cvmx_pciercx_cfg036_s cn63xx;
-       struct cvmx_pciercx_cfg036_s cn63xxp1;
-       struct cvmx_pciercx_cfg036_s cn66xx;
-       struct cvmx_pciercx_cfg036_s cn68xx;
-       struct cvmx_pciercx_cfg036_s cn68xxp1;
-       struct cvmx_pciercx_cfg036_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg037 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg037_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_20_31:12;
-               uint32_t obffs:2;
-               uint32_t reserved_12_17:6;
-               uint32_t ltrs:1;
-               uint32_t noroprpr:1;
-               uint32_t atom128s:1;
-               uint32_t atom64s:1;
-               uint32_t atom32s:1;
-               uint32_t atom_ops:1;
-               uint32_t reserved_5_5:1;
-               uint32_t ctds:1;
-               uint32_t ctrs:4;
-#else
-               uint32_t ctrs:4;
-               uint32_t ctds:1;
-               uint32_t reserved_5_5:1;
-               uint32_t atom_ops:1;
-               uint32_t atom32s:1;
-               uint32_t atom64s:1;
-               uint32_t atom128s:1;
-               uint32_t noroprpr:1;
-               uint32_t ltrs:1;
-               uint32_t reserved_12_17:6;
-               uint32_t obffs:2;
-               uint32_t reserved_20_31:12;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg037_cn52xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_5_31:27;
-               uint32_t ctds:1;
-               uint32_t ctrs:4;
-#else
-               uint32_t ctrs:4;
-               uint32_t ctds:1;
-               uint32_t reserved_5_31:27;
-#endif
-       } cn52xx;
-       struct cvmx_pciercx_cfg037_cn52xx cn52xxp1;
-       struct cvmx_pciercx_cfg037_cn52xx cn56xx;
-       struct cvmx_pciercx_cfg037_cn52xx cn56xxp1;
-       struct cvmx_pciercx_cfg037_cn61xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_14_31:18;
-               uint32_t tph:2;
-               uint32_t reserved_11_11:1;
-               uint32_t noroprpr:1;
-               uint32_t atom128s:1;
-               uint32_t atom64s:1;
-               uint32_t atom32s:1;
-               uint32_t atom_ops:1;
-               uint32_t ari_fw:1;
-               uint32_t ctds:1;
-               uint32_t ctrs:4;
-#else
-               uint32_t ctrs:4;
-               uint32_t ctds:1;
-               uint32_t ari_fw:1;
-               uint32_t atom_ops:1;
-               uint32_t atom32s:1;
-               uint32_t atom64s:1;
-               uint32_t atom128s:1;
-               uint32_t noroprpr:1;
-               uint32_t reserved_11_11:1;
-               uint32_t tph:2;
-               uint32_t reserved_14_31:18;
-#endif
-       } cn61xx;
-       struct cvmx_pciercx_cfg037_cn52xx cn63xx;
-       struct cvmx_pciercx_cfg037_cn52xx cn63xxp1;
-       struct cvmx_pciercx_cfg037_cn66xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_14_31:18;
-               uint32_t tph:2;
-               uint32_t reserved_11_11:1;
-               uint32_t noroprpr:1;
-               uint32_t atom128s:1;
-               uint32_t atom64s:1;
-               uint32_t atom32s:1;
-               uint32_t atom_ops:1;
-               uint32_t ari:1;
-               uint32_t ctds:1;
-               uint32_t ctrs:4;
-#else
-               uint32_t ctrs:4;
-               uint32_t ctds:1;
-               uint32_t ari:1;
-               uint32_t atom_ops:1;
-               uint32_t atom32s:1;
-               uint32_t atom64s:1;
-               uint32_t atom128s:1;
-               uint32_t noroprpr:1;
-               uint32_t reserved_11_11:1;
-               uint32_t tph:2;
-               uint32_t reserved_14_31:18;
-#endif
-       } cn66xx;
-       struct cvmx_pciercx_cfg037_cn66xx cn68xx;
-       struct cvmx_pciercx_cfg037_cn66xx cn68xxp1;
-       struct cvmx_pciercx_cfg037_cnf71xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_20_31:12;
-               uint32_t obffs:2;
-               uint32_t reserved_14_17:4;
-               uint32_t tphs:2;
-               uint32_t ltrs:1;
-               uint32_t noroprpr:1;
-               uint32_t atom128s:1;
-               uint32_t atom64s:1;
-               uint32_t atom32s:1;
-               uint32_t atom_ops:1;
-               uint32_t ari_fw:1;
-               uint32_t ctds:1;
-               uint32_t ctrs:4;
-#else
-               uint32_t ctrs:4;
-               uint32_t ctds:1;
-               uint32_t ari_fw:1;
-               uint32_t atom_ops:1;
-               uint32_t atom32s:1;
-               uint32_t atom64s:1;
-               uint32_t atom128s:1;
-               uint32_t noroprpr:1;
-               uint32_t ltrs:1;
-               uint32_t tphs:2;
-               uint32_t reserved_14_17:4;
-               uint32_t obffs:2;
-               uint32_t reserved_20_31:12;
-#endif
-       } cnf71xx;
-};
-
-union cvmx_pciercx_cfg038 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg038_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_15_31:17;
-               uint32_t obffe:2;
-               uint32_t reserved_11_12:2;
-               uint32_t ltre:1;
-               uint32_t id0_cp:1;
-               uint32_t id0_rq:1;
-               uint32_t atom_op_eb:1;
-               uint32_t atom_op:1;
-               uint32_t ari:1;
-               uint32_t ctd:1;
-               uint32_t ctv:4;
-#else
-               uint32_t ctv:4;
-               uint32_t ctd:1;
-               uint32_t ari:1;
-               uint32_t atom_op:1;
-               uint32_t atom_op_eb:1;
-               uint32_t id0_rq:1;
-               uint32_t id0_cp:1;
-               uint32_t ltre:1;
-               uint32_t reserved_11_12:2;
-               uint32_t obffe:2;
-               uint32_t reserved_15_31:17;
-#endif
+               __BITFIELD_FIELD(uint32_t reserved_17_31:15,
+               __BITFIELD_FIELD(uint32_t crssv:1,
+               __BITFIELD_FIELD(uint32_t reserved_5_15:11,
+               __BITFIELD_FIELD(uint32_t crssve:1,
+               __BITFIELD_FIELD(uint32_t pmeie:1,
+               __BITFIELD_FIELD(uint32_t sefee:1,
+               __BITFIELD_FIELD(uint32_t senfee:1,
+               __BITFIELD_FIELD(uint32_t secee:1,
+               ;))))))))
        } s;
-       struct cvmx_pciercx_cfg038_cn52xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_5_31:27;
-               uint32_t ctd:1;
-               uint32_t ctv:4;
-#else
-               uint32_t ctv:4;
-               uint32_t ctd:1;
-               uint32_t reserved_5_31:27;
-#endif
-       } cn52xx;
-       struct cvmx_pciercx_cfg038_cn52xx cn52xxp1;
-       struct cvmx_pciercx_cfg038_cn52xx cn56xx;
-       struct cvmx_pciercx_cfg038_cn52xx cn56xxp1;
-       struct cvmx_pciercx_cfg038_cn61xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_10_31:22;
-               uint32_t id0_cp:1;
-               uint32_t id0_rq:1;
-               uint32_t atom_op_eb:1;
-               uint32_t atom_op:1;
-               uint32_t ari:1;
-               uint32_t ctd:1;
-               uint32_t ctv:4;
-#else
-               uint32_t ctv:4;
-               uint32_t ctd:1;
-               uint32_t ari:1;
-               uint32_t atom_op:1;
-               uint32_t atom_op_eb:1;
-               uint32_t id0_rq:1;
-               uint32_t id0_cp:1;
-               uint32_t reserved_10_31:22;
-#endif
-       } cn61xx;
-       struct cvmx_pciercx_cfg038_cn52xx cn63xx;
-       struct cvmx_pciercx_cfg038_cn52xx cn63xxp1;
-       struct cvmx_pciercx_cfg038_cn61xx cn66xx;
-       struct cvmx_pciercx_cfg038_cn61xx cn68xx;
-       struct cvmx_pciercx_cfg038_cn61xx cn68xxp1;
-       struct cvmx_pciercx_cfg038_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg039 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg039_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_9_31:23;
-               uint32_t cls:1;
-               uint32_t slsv:7;
-               uint32_t reserved_0_0:1;
-#else
-               uint32_t reserved_0_0:1;
-               uint32_t slsv:7;
-               uint32_t cls:1;
-               uint32_t reserved_9_31:23;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg039_cn52xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_0_31:32;
-#else
-               uint32_t reserved_0_31:32;
-#endif
-       } cn52xx;
-       struct cvmx_pciercx_cfg039_cn52xx cn52xxp1;
-       struct cvmx_pciercx_cfg039_cn52xx cn56xx;
-       struct cvmx_pciercx_cfg039_cn52xx cn56xxp1;
-       struct cvmx_pciercx_cfg039_s cn61xx;
-       struct cvmx_pciercx_cfg039_s cn63xx;
-       struct cvmx_pciercx_cfg039_cn52xx cn63xxp1;
-       struct cvmx_pciercx_cfg039_s cn66xx;
-       struct cvmx_pciercx_cfg039_s cn68xx;
-       struct cvmx_pciercx_cfg039_s cn68xxp1;
-       struct cvmx_pciercx_cfg039_s cnf71xx;
 };
 
 union cvmx_pciercx_cfg040 {
        uint32_t u32;
        struct cvmx_pciercx_cfg040_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_17_31:15;
-               uint32_t cdl:1;
-               uint32_t reserved_13_15:3;
-               uint32_t cde:1;
-               uint32_t csos:1;
-               uint32_t emc:1;
-               uint32_t tm:3;
-               uint32_t sde:1;
-               uint32_t hasd:1;
-               uint32_t ec:1;
-               uint32_t tls:4;
-#else
-               uint32_t tls:4;
-               uint32_t ec:1;
-               uint32_t hasd:1;
-               uint32_t sde:1;
-               uint32_t tm:3;
-               uint32_t emc:1;
-               uint32_t csos:1;
-               uint32_t cde:1;
-               uint32_t reserved_13_15:3;
-               uint32_t cdl:1;
-               uint32_t reserved_17_31:15;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg040_cn52xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_0_31:32;
-#else
-               uint32_t reserved_0_31:32;
-#endif
-       } cn52xx;
-       struct cvmx_pciercx_cfg040_cn52xx cn52xxp1;
-       struct cvmx_pciercx_cfg040_cn52xx cn56xx;
-       struct cvmx_pciercx_cfg040_cn52xx cn56xxp1;
-       struct cvmx_pciercx_cfg040_s cn61xx;
-       struct cvmx_pciercx_cfg040_s cn63xx;
-       struct cvmx_pciercx_cfg040_s cn63xxp1;
-       struct cvmx_pciercx_cfg040_s cn66xx;
-       struct cvmx_pciercx_cfg040_s cn68xx;
-       struct cvmx_pciercx_cfg040_s cn68xxp1;
-       struct cvmx_pciercx_cfg040_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg041 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg041_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_0_31:32;
-#else
-               uint32_t reserved_0_31:32;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg041_s cn52xx;
-       struct cvmx_pciercx_cfg041_s cn52xxp1;
-       struct cvmx_pciercx_cfg041_s cn56xx;
-       struct cvmx_pciercx_cfg041_s cn56xxp1;
-       struct cvmx_pciercx_cfg041_s cn61xx;
-       struct cvmx_pciercx_cfg041_s cn63xx;
-       struct cvmx_pciercx_cfg041_s cn63xxp1;
-       struct cvmx_pciercx_cfg041_s cn66xx;
-       struct cvmx_pciercx_cfg041_s cn68xx;
-       struct cvmx_pciercx_cfg041_s cn68xxp1;
-       struct cvmx_pciercx_cfg041_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg042 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg042_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_0_31:32;
-#else
-               uint32_t reserved_0_31:32;
-#endif
+               __BITFIELD_FIELD(uint32_t reserved_22_31:10,
+               __BITFIELD_FIELD(uint32_t ler:1,
+               __BITFIELD_FIELD(uint32_t ep3s:1,
+               __BITFIELD_FIELD(uint32_t ep2s:1,
+               __BITFIELD_FIELD(uint32_t ep1s:1,
+               __BITFIELD_FIELD(uint32_t eqc:1,
+               __BITFIELD_FIELD(uint32_t cdl:1,
+               __BITFIELD_FIELD(uint32_t cde:4,
+               __BITFIELD_FIELD(uint32_t csos:1,
+               __BITFIELD_FIELD(uint32_t emc:1,
+               __BITFIELD_FIELD(uint32_t tm:3,
+               __BITFIELD_FIELD(uint32_t sde:1,
+               __BITFIELD_FIELD(uint32_t hasd:1,
+               __BITFIELD_FIELD(uint32_t ec:1,
+               __BITFIELD_FIELD(uint32_t tls:4,
+               ;)))))))))))))))
        } s;
-       struct cvmx_pciercx_cfg042_s cn52xx;
-       struct cvmx_pciercx_cfg042_s cn52xxp1;
-       struct cvmx_pciercx_cfg042_s cn56xx;
-       struct cvmx_pciercx_cfg042_s cn56xxp1;
-       struct cvmx_pciercx_cfg042_s cn61xx;
-       struct cvmx_pciercx_cfg042_s cn63xx;
-       struct cvmx_pciercx_cfg042_s cn63xxp1;
-       struct cvmx_pciercx_cfg042_s cn66xx;
-       struct cvmx_pciercx_cfg042_s cn68xx;
-       struct cvmx_pciercx_cfg042_s cn68xxp1;
-       struct cvmx_pciercx_cfg042_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg064 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg064_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t nco:12;
-               uint32_t cv:4;
-               uint32_t pcieec:16;
-#else
-               uint32_t pcieec:16;
-               uint32_t cv:4;
-               uint32_t nco:12;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg064_s cn52xx;
-       struct cvmx_pciercx_cfg064_s cn52xxp1;
-       struct cvmx_pciercx_cfg064_s cn56xx;
-       struct cvmx_pciercx_cfg064_s cn56xxp1;
-       struct cvmx_pciercx_cfg064_s cn61xx;
-       struct cvmx_pciercx_cfg064_s cn63xx;
-       struct cvmx_pciercx_cfg064_s cn63xxp1;
-       struct cvmx_pciercx_cfg064_s cn66xx;
-       struct cvmx_pciercx_cfg064_s cn68xx;
-       struct cvmx_pciercx_cfg064_s cn68xxp1;
-       struct cvmx_pciercx_cfg064_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg065 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg065_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_25_31:7;
-               uint32_t uatombs:1;
-               uint32_t reserved_23_23:1;
-               uint32_t ucies:1;
-               uint32_t reserved_21_21:1;
-               uint32_t ures:1;
-               uint32_t ecrces:1;
-               uint32_t mtlps:1;
-               uint32_t ros:1;
-               uint32_t ucs:1;
-               uint32_t cas:1;
-               uint32_t cts:1;
-               uint32_t fcpes:1;
-               uint32_t ptlps:1;
-               uint32_t reserved_6_11:6;
-               uint32_t sdes:1;
-               uint32_t dlpes:1;
-               uint32_t reserved_0_3:4;
-#else
-               uint32_t reserved_0_3:4;
-               uint32_t dlpes:1;
-               uint32_t sdes:1;
-               uint32_t reserved_6_11:6;
-               uint32_t ptlps:1;
-               uint32_t fcpes:1;
-               uint32_t cts:1;
-               uint32_t cas:1;
-               uint32_t ucs:1;
-               uint32_t ros:1;
-               uint32_t mtlps:1;
-               uint32_t ecrces:1;
-               uint32_t ures:1;
-               uint32_t reserved_21_21:1;
-               uint32_t ucies:1;
-               uint32_t reserved_23_23:1;
-               uint32_t uatombs:1;
-               uint32_t reserved_25_31:7;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg065_cn52xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_21_31:11;
-               uint32_t ures:1;
-               uint32_t ecrces:1;
-               uint32_t mtlps:1;
-               uint32_t ros:1;
-               uint32_t ucs:1;
-               uint32_t cas:1;
-               uint32_t cts:1;
-               uint32_t fcpes:1;
-               uint32_t ptlps:1;
-               uint32_t reserved_6_11:6;
-               uint32_t sdes:1;
-               uint32_t dlpes:1;
-               uint32_t reserved_0_3:4;
-#else
-               uint32_t reserved_0_3:4;
-               uint32_t dlpes:1;
-               uint32_t sdes:1;
-               uint32_t reserved_6_11:6;
-               uint32_t ptlps:1;
-               uint32_t fcpes:1;
-               uint32_t cts:1;
-               uint32_t cas:1;
-               uint32_t ucs:1;
-               uint32_t ros:1;
-               uint32_t mtlps:1;
-               uint32_t ecrces:1;
-               uint32_t ures:1;
-               uint32_t reserved_21_31:11;
-#endif
-       } cn52xx;
-       struct cvmx_pciercx_cfg065_cn52xx cn52xxp1;
-       struct cvmx_pciercx_cfg065_cn52xx cn56xx;
-       struct cvmx_pciercx_cfg065_cn52xx cn56xxp1;
-       struct cvmx_pciercx_cfg065_cn61xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_25_31:7;
-               uint32_t uatombs:1;
-               uint32_t reserved_21_23:3;
-               uint32_t ures:1;
-               uint32_t ecrces:1;
-               uint32_t mtlps:1;
-               uint32_t ros:1;
-               uint32_t ucs:1;
-               uint32_t cas:1;
-               uint32_t cts:1;
-               uint32_t fcpes:1;
-               uint32_t ptlps:1;
-               uint32_t reserved_6_11:6;
-               uint32_t sdes:1;
-               uint32_t dlpes:1;
-               uint32_t reserved_0_3:4;
-#else
-               uint32_t reserved_0_3:4;
-               uint32_t dlpes:1;
-               uint32_t sdes:1;
-               uint32_t reserved_6_11:6;
-               uint32_t ptlps:1;
-               uint32_t fcpes:1;
-               uint32_t cts:1;
-               uint32_t cas:1;
-               uint32_t ucs:1;
-               uint32_t ros:1;
-               uint32_t mtlps:1;
-               uint32_t ecrces:1;
-               uint32_t ures:1;
-               uint32_t reserved_21_23:3;
-               uint32_t uatombs:1;
-               uint32_t reserved_25_31:7;
-#endif
-       } cn61xx;
-       struct cvmx_pciercx_cfg065_cn52xx cn63xx;
-       struct cvmx_pciercx_cfg065_cn52xx cn63xxp1;
-       struct cvmx_pciercx_cfg065_cn61xx cn66xx;
-       struct cvmx_pciercx_cfg065_cn61xx cn68xx;
-       struct cvmx_pciercx_cfg065_cn52xx cn68xxp1;
-       struct cvmx_pciercx_cfg065_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg066 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg066_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_25_31:7;
-               uint32_t uatombm:1;
-               uint32_t reserved_23_23:1;
-               uint32_t uciem:1;
-               uint32_t reserved_21_21:1;
-               uint32_t urem:1;
-               uint32_t ecrcem:1;
-               uint32_t mtlpm:1;
-               uint32_t rom:1;
-               uint32_t ucm:1;
-               uint32_t cam:1;
-               uint32_t ctm:1;
-               uint32_t fcpem:1;
-               uint32_t ptlpm:1;
-               uint32_t reserved_6_11:6;
-               uint32_t sdem:1;
-               uint32_t dlpem:1;
-               uint32_t reserved_0_3:4;
-#else
-               uint32_t reserved_0_3:4;
-               uint32_t dlpem:1;
-               uint32_t sdem:1;
-               uint32_t reserved_6_11:6;
-               uint32_t ptlpm:1;
-               uint32_t fcpem:1;
-               uint32_t ctm:1;
-               uint32_t cam:1;
-               uint32_t ucm:1;
-               uint32_t rom:1;
-               uint32_t mtlpm:1;
-               uint32_t ecrcem:1;
-               uint32_t urem:1;
-               uint32_t reserved_21_21:1;
-               uint32_t uciem:1;
-               uint32_t reserved_23_23:1;
-               uint32_t uatombm:1;
-               uint32_t reserved_25_31:7;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg066_cn52xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_21_31:11;
-               uint32_t urem:1;
-               uint32_t ecrcem:1;
-               uint32_t mtlpm:1;
-               uint32_t rom:1;
-               uint32_t ucm:1;
-               uint32_t cam:1;
-               uint32_t ctm:1;
-               uint32_t fcpem:1;
-               uint32_t ptlpm:1;
-               uint32_t reserved_6_11:6;
-               uint32_t sdem:1;
-               uint32_t dlpem:1;
-               uint32_t reserved_0_3:4;
-#else
-               uint32_t reserved_0_3:4;
-               uint32_t dlpem:1;
-               uint32_t sdem:1;
-               uint32_t reserved_6_11:6;
-               uint32_t ptlpm:1;
-               uint32_t fcpem:1;
-               uint32_t ctm:1;
-               uint32_t cam:1;
-               uint32_t ucm:1;
-               uint32_t rom:1;
-               uint32_t mtlpm:1;
-               uint32_t ecrcem:1;
-               uint32_t urem:1;
-               uint32_t reserved_21_31:11;
-#endif
-       } cn52xx;
-       struct cvmx_pciercx_cfg066_cn52xx cn52xxp1;
-       struct cvmx_pciercx_cfg066_cn52xx cn56xx;
-       struct cvmx_pciercx_cfg066_cn52xx cn56xxp1;
-       struct cvmx_pciercx_cfg066_cn61xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_25_31:7;
-               uint32_t uatombm:1;
-               uint32_t reserved_21_23:3;
-               uint32_t urem:1;
-               uint32_t ecrcem:1;
-               uint32_t mtlpm:1;
-               uint32_t rom:1;
-               uint32_t ucm:1;
-               uint32_t cam:1;
-               uint32_t ctm:1;
-               uint32_t fcpem:1;
-               uint32_t ptlpm:1;
-               uint32_t reserved_6_11:6;
-               uint32_t sdem:1;
-               uint32_t dlpem:1;
-               uint32_t reserved_0_3:4;
-#else
-               uint32_t reserved_0_3:4;
-               uint32_t dlpem:1;
-               uint32_t sdem:1;
-               uint32_t reserved_6_11:6;
-               uint32_t ptlpm:1;
-               uint32_t fcpem:1;
-               uint32_t ctm:1;
-               uint32_t cam:1;
-               uint32_t ucm:1;
-               uint32_t rom:1;
-               uint32_t mtlpm:1;
-               uint32_t ecrcem:1;
-               uint32_t urem:1;
-               uint32_t reserved_21_23:3;
-               uint32_t uatombm:1;
-               uint32_t reserved_25_31:7;
-#endif
-       } cn61xx;
-       struct cvmx_pciercx_cfg066_cn52xx cn63xx;
-       struct cvmx_pciercx_cfg066_cn52xx cn63xxp1;
-       struct cvmx_pciercx_cfg066_cn61xx cn66xx;
-       struct cvmx_pciercx_cfg066_cn61xx cn68xx;
-       struct cvmx_pciercx_cfg066_cn52xx cn68xxp1;
-       struct cvmx_pciercx_cfg066_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg067 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg067_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_25_31:7;
-               uint32_t uatombs:1;
-               uint32_t reserved_23_23:1;
-               uint32_t ucies:1;
-               uint32_t reserved_21_21:1;
-               uint32_t ures:1;
-               uint32_t ecrces:1;
-               uint32_t mtlps:1;
-               uint32_t ros:1;
-               uint32_t ucs:1;
-               uint32_t cas:1;
-               uint32_t cts:1;
-               uint32_t fcpes:1;
-               uint32_t ptlps:1;
-               uint32_t reserved_6_11:6;
-               uint32_t sdes:1;
-               uint32_t dlpes:1;
-               uint32_t reserved_0_3:4;
-#else
-               uint32_t reserved_0_3:4;
-               uint32_t dlpes:1;
-               uint32_t sdes:1;
-               uint32_t reserved_6_11:6;
-               uint32_t ptlps:1;
-               uint32_t fcpes:1;
-               uint32_t cts:1;
-               uint32_t cas:1;
-               uint32_t ucs:1;
-               uint32_t ros:1;
-               uint32_t mtlps:1;
-               uint32_t ecrces:1;
-               uint32_t ures:1;
-               uint32_t reserved_21_21:1;
-               uint32_t ucies:1;
-               uint32_t reserved_23_23:1;
-               uint32_t uatombs:1;
-               uint32_t reserved_25_31:7;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg067_cn52xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_21_31:11;
-               uint32_t ures:1;
-               uint32_t ecrces:1;
-               uint32_t mtlps:1;
-               uint32_t ros:1;
-               uint32_t ucs:1;
-               uint32_t cas:1;
-               uint32_t cts:1;
-               uint32_t fcpes:1;
-               uint32_t ptlps:1;
-               uint32_t reserved_6_11:6;
-               uint32_t sdes:1;
-               uint32_t dlpes:1;
-               uint32_t reserved_0_3:4;
-#else
-               uint32_t reserved_0_3:4;
-               uint32_t dlpes:1;
-               uint32_t sdes:1;
-               uint32_t reserved_6_11:6;
-               uint32_t ptlps:1;
-               uint32_t fcpes:1;
-               uint32_t cts:1;
-               uint32_t cas:1;
-               uint32_t ucs:1;
-               uint32_t ros:1;
-               uint32_t mtlps:1;
-               uint32_t ecrces:1;
-               uint32_t ures:1;
-               uint32_t reserved_21_31:11;
-#endif
-       } cn52xx;
-       struct cvmx_pciercx_cfg067_cn52xx cn52xxp1;
-       struct cvmx_pciercx_cfg067_cn52xx cn56xx;
-       struct cvmx_pciercx_cfg067_cn52xx cn56xxp1;
-       struct cvmx_pciercx_cfg067_cn61xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_25_31:7;
-               uint32_t uatombs:1;
-               uint32_t reserved_21_23:3;
-               uint32_t ures:1;
-               uint32_t ecrces:1;
-               uint32_t mtlps:1;
-               uint32_t ros:1;
-               uint32_t ucs:1;
-               uint32_t cas:1;
-               uint32_t cts:1;
-               uint32_t fcpes:1;
-               uint32_t ptlps:1;
-               uint32_t reserved_6_11:6;
-               uint32_t sdes:1;
-               uint32_t dlpes:1;
-               uint32_t reserved_0_3:4;
-#else
-               uint32_t reserved_0_3:4;
-               uint32_t dlpes:1;
-               uint32_t sdes:1;
-               uint32_t reserved_6_11:6;
-               uint32_t ptlps:1;
-               uint32_t fcpes:1;
-               uint32_t cts:1;
-               uint32_t cas:1;
-               uint32_t ucs:1;
-               uint32_t ros:1;
-               uint32_t mtlps:1;
-               uint32_t ecrces:1;
-               uint32_t ures:1;
-               uint32_t reserved_21_23:3;
-               uint32_t uatombs:1;
-               uint32_t reserved_25_31:7;
-#endif
-       } cn61xx;
-       struct cvmx_pciercx_cfg067_cn52xx cn63xx;
-       struct cvmx_pciercx_cfg067_cn52xx cn63xxp1;
-       struct cvmx_pciercx_cfg067_cn61xx cn66xx;
-       struct cvmx_pciercx_cfg067_cn61xx cn68xx;
-       struct cvmx_pciercx_cfg067_cn52xx cn68xxp1;
-       struct cvmx_pciercx_cfg067_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg068 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg068_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_15_31:17;
-               uint32_t cies:1;
-               uint32_t anfes:1;
-               uint32_t rtts:1;
-               uint32_t reserved_9_11:3;
-               uint32_t rnrs:1;
-               uint32_t bdllps:1;
-               uint32_t btlps:1;
-               uint32_t reserved_1_5:5;
-               uint32_t res:1;
-#else
-               uint32_t res:1;
-               uint32_t reserved_1_5:5;
-               uint32_t btlps:1;
-               uint32_t bdllps:1;
-               uint32_t rnrs:1;
-               uint32_t reserved_9_11:3;
-               uint32_t rtts:1;
-               uint32_t anfes:1;
-               uint32_t cies:1;
-               uint32_t reserved_15_31:17;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg068_cn52xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_14_31:18;
-               uint32_t anfes:1;
-               uint32_t rtts:1;
-               uint32_t reserved_9_11:3;
-               uint32_t rnrs:1;
-               uint32_t bdllps:1;
-               uint32_t btlps:1;
-               uint32_t reserved_1_5:5;
-               uint32_t res:1;
-#else
-               uint32_t res:1;
-               uint32_t reserved_1_5:5;
-               uint32_t btlps:1;
-               uint32_t bdllps:1;
-               uint32_t rnrs:1;
-               uint32_t reserved_9_11:3;
-               uint32_t rtts:1;
-               uint32_t anfes:1;
-               uint32_t reserved_14_31:18;
-#endif
-       } cn52xx;
-       struct cvmx_pciercx_cfg068_cn52xx cn52xxp1;
-       struct cvmx_pciercx_cfg068_cn52xx cn56xx;
-       struct cvmx_pciercx_cfg068_cn52xx cn56xxp1;
-       struct cvmx_pciercx_cfg068_cn52xx cn61xx;
-       struct cvmx_pciercx_cfg068_cn52xx cn63xx;
-       struct cvmx_pciercx_cfg068_cn52xx cn63xxp1;
-       struct cvmx_pciercx_cfg068_cn52xx cn66xx;
-       struct cvmx_pciercx_cfg068_cn52xx cn68xx;
-       struct cvmx_pciercx_cfg068_cn52xx cn68xxp1;
-       struct cvmx_pciercx_cfg068_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg069 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg069_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_15_31:17;
-               uint32_t ciem:1;
-               uint32_t anfem:1;
-               uint32_t rttm:1;
-               uint32_t reserved_9_11:3;
-               uint32_t rnrm:1;
-               uint32_t bdllpm:1;
-               uint32_t btlpm:1;
-               uint32_t reserved_1_5:5;
-               uint32_t rem:1;
-#else
-               uint32_t rem:1;
-               uint32_t reserved_1_5:5;
-               uint32_t btlpm:1;
-               uint32_t bdllpm:1;
-               uint32_t rnrm:1;
-               uint32_t reserved_9_11:3;
-               uint32_t rttm:1;
-               uint32_t anfem:1;
-               uint32_t ciem:1;
-               uint32_t reserved_15_31:17;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg069_cn52xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_14_31:18;
-               uint32_t anfem:1;
-               uint32_t rttm:1;
-               uint32_t reserved_9_11:3;
-               uint32_t rnrm:1;
-               uint32_t bdllpm:1;
-               uint32_t btlpm:1;
-               uint32_t reserved_1_5:5;
-               uint32_t rem:1;
-#else
-               uint32_t rem:1;
-               uint32_t reserved_1_5:5;
-               uint32_t btlpm:1;
-               uint32_t bdllpm:1;
-               uint32_t rnrm:1;
-               uint32_t reserved_9_11:3;
-               uint32_t rttm:1;
-               uint32_t anfem:1;
-               uint32_t reserved_14_31:18;
-#endif
-       } cn52xx;
-       struct cvmx_pciercx_cfg069_cn52xx cn52xxp1;
-       struct cvmx_pciercx_cfg069_cn52xx cn56xx;
-       struct cvmx_pciercx_cfg069_cn52xx cn56xxp1;
-       struct cvmx_pciercx_cfg069_cn52xx cn61xx;
-       struct cvmx_pciercx_cfg069_cn52xx cn63xx;
-       struct cvmx_pciercx_cfg069_cn52xx cn63xxp1;
-       struct cvmx_pciercx_cfg069_cn52xx cn66xx;
-       struct cvmx_pciercx_cfg069_cn52xx cn68xx;
-       struct cvmx_pciercx_cfg069_cn52xx cn68xxp1;
-       struct cvmx_pciercx_cfg069_s cnf71xx;
 };
 
 union cvmx_pciercx_cfg070 {
        uint32_t u32;
        struct cvmx_pciercx_cfg070_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_9_31:23;
-               uint32_t ce:1;
-               uint32_t cc:1;
-               uint32_t ge:1;
-               uint32_t gc:1;
-               uint32_t fep:5;
-#else
-               uint32_t fep:5;
-               uint32_t gc:1;
-               uint32_t ge:1;
-               uint32_t cc:1;
-               uint32_t ce:1;
-               uint32_t reserved_9_31:23;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg070_s cn52xx;
-       struct cvmx_pciercx_cfg070_s cn52xxp1;
-       struct cvmx_pciercx_cfg070_s cn56xx;
-       struct cvmx_pciercx_cfg070_s cn56xxp1;
-       struct cvmx_pciercx_cfg070_s cn61xx;
-       struct cvmx_pciercx_cfg070_s cn63xx;
-       struct cvmx_pciercx_cfg070_s cn63xxp1;
-       struct cvmx_pciercx_cfg070_s cn66xx;
-       struct cvmx_pciercx_cfg070_s cn68xx;
-       struct cvmx_pciercx_cfg070_s cn68xxp1;
-       struct cvmx_pciercx_cfg070_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg071 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg071_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t dword1:32;
-#else
-               uint32_t dword1:32;
-#endif
+               __BITFIELD_FIELD(uint32_t reserved_12_31:20,
+               __BITFIELD_FIELD(uint32_t tplp:1,
+               __BITFIELD_FIELD(uint32_t reserved_9_10:2,
+               __BITFIELD_FIELD(uint32_t ce:1,
+               __BITFIELD_FIELD(uint32_t cc:1,
+               __BITFIELD_FIELD(uint32_t ge:1,
+               __BITFIELD_FIELD(uint32_t gc:1,
+               __BITFIELD_FIELD(uint32_t fep:5,
+               ;))))))))
        } s;
-       struct cvmx_pciercx_cfg071_s cn52xx;
-       struct cvmx_pciercx_cfg071_s cn52xxp1;
-       struct cvmx_pciercx_cfg071_s cn56xx;
-       struct cvmx_pciercx_cfg071_s cn56xxp1;
-       struct cvmx_pciercx_cfg071_s cn61xx;
-       struct cvmx_pciercx_cfg071_s cn63xx;
-       struct cvmx_pciercx_cfg071_s cn63xxp1;
-       struct cvmx_pciercx_cfg071_s cn66xx;
-       struct cvmx_pciercx_cfg071_s cn68xx;
-       struct cvmx_pciercx_cfg071_s cn68xxp1;
-       struct cvmx_pciercx_cfg071_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg072 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg072_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t dword2:32;
-#else
-               uint32_t dword2:32;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg072_s cn52xx;
-       struct cvmx_pciercx_cfg072_s cn52xxp1;
-       struct cvmx_pciercx_cfg072_s cn56xx;
-       struct cvmx_pciercx_cfg072_s cn56xxp1;
-       struct cvmx_pciercx_cfg072_s cn61xx;
-       struct cvmx_pciercx_cfg072_s cn63xx;
-       struct cvmx_pciercx_cfg072_s cn63xxp1;
-       struct cvmx_pciercx_cfg072_s cn66xx;
-       struct cvmx_pciercx_cfg072_s cn68xx;
-       struct cvmx_pciercx_cfg072_s cn68xxp1;
-       struct cvmx_pciercx_cfg072_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg073 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg073_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t dword3:32;
-#else
-               uint32_t dword3:32;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg073_s cn52xx;
-       struct cvmx_pciercx_cfg073_s cn52xxp1;
-       struct cvmx_pciercx_cfg073_s cn56xx;
-       struct cvmx_pciercx_cfg073_s cn56xxp1;
-       struct cvmx_pciercx_cfg073_s cn61xx;
-       struct cvmx_pciercx_cfg073_s cn63xx;
-       struct cvmx_pciercx_cfg073_s cn63xxp1;
-       struct cvmx_pciercx_cfg073_s cn66xx;
-       struct cvmx_pciercx_cfg073_s cn68xx;
-       struct cvmx_pciercx_cfg073_s cn68xxp1;
-       struct cvmx_pciercx_cfg073_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg074 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg074_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t dword4:32;
-#else
-               uint32_t dword4:32;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg074_s cn52xx;
-       struct cvmx_pciercx_cfg074_s cn52xxp1;
-       struct cvmx_pciercx_cfg074_s cn56xx;
-       struct cvmx_pciercx_cfg074_s cn56xxp1;
-       struct cvmx_pciercx_cfg074_s cn61xx;
-       struct cvmx_pciercx_cfg074_s cn63xx;
-       struct cvmx_pciercx_cfg074_s cn63xxp1;
-       struct cvmx_pciercx_cfg074_s cn66xx;
-       struct cvmx_pciercx_cfg074_s cn68xx;
-       struct cvmx_pciercx_cfg074_s cn68xxp1;
-       struct cvmx_pciercx_cfg074_s cnf71xx;
 };
 
 union cvmx_pciercx_cfg075 {
        uint32_t u32;
        struct cvmx_pciercx_cfg075_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_3_31:29;
-               uint32_t fere:1;
-               uint32_t nfere:1;
-               uint32_t cere:1;
-#else
-               uint32_t cere:1;
-               uint32_t nfere:1;
-               uint32_t fere:1;
-               uint32_t reserved_3_31:29;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg075_s cn52xx;
-       struct cvmx_pciercx_cfg075_s cn52xxp1;
-       struct cvmx_pciercx_cfg075_s cn56xx;
-       struct cvmx_pciercx_cfg075_s cn56xxp1;
-       struct cvmx_pciercx_cfg075_s cn61xx;
-       struct cvmx_pciercx_cfg075_s cn63xx;
-       struct cvmx_pciercx_cfg075_s cn63xxp1;
-       struct cvmx_pciercx_cfg075_s cn66xx;
-       struct cvmx_pciercx_cfg075_s cn68xx;
-       struct cvmx_pciercx_cfg075_s cn68xxp1;
-       struct cvmx_pciercx_cfg075_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg076 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg076_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t aeimn:5;
-               uint32_t reserved_7_26:20;
-               uint32_t femr:1;
-               uint32_t nfemr:1;
-               uint32_t fuf:1;
-               uint32_t multi_efnfr:1;
-               uint32_t efnfr:1;
-               uint32_t multi_ecr:1;
-               uint32_t ecr:1;
-#else
-               uint32_t ecr:1;
-               uint32_t multi_ecr:1;
-               uint32_t efnfr:1;
-               uint32_t multi_efnfr:1;
-               uint32_t fuf:1;
-               uint32_t nfemr:1;
-               uint32_t femr:1;
-               uint32_t reserved_7_26:20;
-               uint32_t aeimn:5;
-#endif
+               __BITFIELD_FIELD(uint32_t reserved_3_31:29,
+               __BITFIELD_FIELD(uint32_t fere:1,
+               __BITFIELD_FIELD(uint32_t nfere:1,
+               __BITFIELD_FIELD(uint32_t cere:1,
+               ;))))
        } s;
-       struct cvmx_pciercx_cfg076_s cn52xx;
-       struct cvmx_pciercx_cfg076_s cn52xxp1;
-       struct cvmx_pciercx_cfg076_s cn56xx;
-       struct cvmx_pciercx_cfg076_s cn56xxp1;
-       struct cvmx_pciercx_cfg076_s cn61xx;
-       struct cvmx_pciercx_cfg076_s cn63xx;
-       struct cvmx_pciercx_cfg076_s cn63xxp1;
-       struct cvmx_pciercx_cfg076_s cn66xx;
-       struct cvmx_pciercx_cfg076_s cn68xx;
-       struct cvmx_pciercx_cfg076_s cn68xxp1;
-       struct cvmx_pciercx_cfg076_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg077 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg077_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t efnfsi:16;
-               uint32_t ecsi:16;
-#else
-               uint32_t ecsi:16;
-               uint32_t efnfsi:16;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg077_s cn52xx;
-       struct cvmx_pciercx_cfg077_s cn52xxp1;
-       struct cvmx_pciercx_cfg077_s cn56xx;
-       struct cvmx_pciercx_cfg077_s cn56xxp1;
-       struct cvmx_pciercx_cfg077_s cn61xx;
-       struct cvmx_pciercx_cfg077_s cn63xx;
-       struct cvmx_pciercx_cfg077_s cn63xxp1;
-       struct cvmx_pciercx_cfg077_s cn66xx;
-       struct cvmx_pciercx_cfg077_s cn68xx;
-       struct cvmx_pciercx_cfg077_s cn68xxp1;
-       struct cvmx_pciercx_cfg077_s cnf71xx;
 };
 
 union cvmx_pciercx_cfg448 {
        uint32_t u32;
        struct cvmx_pciercx_cfg448_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t rtl:16;
-               uint32_t rtltl:16;
-#else
-               uint32_t rtltl:16;
-               uint32_t rtl:16;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg448_s cn52xx;
-       struct cvmx_pciercx_cfg448_s cn52xxp1;
-       struct cvmx_pciercx_cfg448_s cn56xx;
-       struct cvmx_pciercx_cfg448_s cn56xxp1;
-       struct cvmx_pciercx_cfg448_s cn61xx;
-       struct cvmx_pciercx_cfg448_s cn63xx;
-       struct cvmx_pciercx_cfg448_s cn63xxp1;
-       struct cvmx_pciercx_cfg448_s cn66xx;
-       struct cvmx_pciercx_cfg448_s cn68xx;
-       struct cvmx_pciercx_cfg448_s cn68xxp1;
-       struct cvmx_pciercx_cfg448_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg449 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg449_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t omr:32;
-#else
-               uint32_t omr:32;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg449_s cn52xx;
-       struct cvmx_pciercx_cfg449_s cn52xxp1;
-       struct cvmx_pciercx_cfg449_s cn56xx;
-       struct cvmx_pciercx_cfg449_s cn56xxp1;
-       struct cvmx_pciercx_cfg449_s cn61xx;
-       struct cvmx_pciercx_cfg449_s cn63xx;
-       struct cvmx_pciercx_cfg449_s cn63xxp1;
-       struct cvmx_pciercx_cfg449_s cn66xx;
-       struct cvmx_pciercx_cfg449_s cn68xx;
-       struct cvmx_pciercx_cfg449_s cn68xxp1;
-       struct cvmx_pciercx_cfg449_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg450 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg450_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t lpec:8;
-               uint32_t reserved_22_23:2;
-               uint32_t link_state:6;
-               uint32_t force_link:1;
-               uint32_t reserved_8_14:7;
-               uint32_t link_num:8;
-#else
-               uint32_t link_num:8;
-               uint32_t reserved_8_14:7;
-               uint32_t force_link:1;
-               uint32_t link_state:6;
-               uint32_t reserved_22_23:2;
-               uint32_t lpec:8;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg450_s cn52xx;
-       struct cvmx_pciercx_cfg450_s cn52xxp1;
-       struct cvmx_pciercx_cfg450_s cn56xx;
-       struct cvmx_pciercx_cfg450_s cn56xxp1;
-       struct cvmx_pciercx_cfg450_s cn61xx;
-       struct cvmx_pciercx_cfg450_s cn63xx;
-       struct cvmx_pciercx_cfg450_s cn63xxp1;
-       struct cvmx_pciercx_cfg450_s cn66xx;
-       struct cvmx_pciercx_cfg450_s cn68xx;
-       struct cvmx_pciercx_cfg450_s cn68xxp1;
-       struct cvmx_pciercx_cfg450_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg451 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg451_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_31_31:1;
-               uint32_t easpml1:1;
-               uint32_t l1el:3;
-               uint32_t l0el:3;
-               uint32_t n_fts_cc:8;
-               uint32_t n_fts:8;
-               uint32_t ack_freq:8;
-#else
-               uint32_t ack_freq:8;
-               uint32_t n_fts:8;
-               uint32_t n_fts_cc:8;
-               uint32_t l0el:3;
-               uint32_t l1el:3;
-               uint32_t easpml1:1;
-               uint32_t reserved_31_31:1;
-#endif
+               __BITFIELD_FIELD(uint32_t rtl:16,
+               __BITFIELD_FIELD(uint32_t rtltl:16,
+               ;))
        } s;
-       struct cvmx_pciercx_cfg451_cn52xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_30_31:2;
-               uint32_t l1el:3;
-               uint32_t l0el:3;
-               uint32_t n_fts_cc:8;
-               uint32_t n_fts:8;
-               uint32_t ack_freq:8;
-#else
-               uint32_t ack_freq:8;
-               uint32_t n_fts:8;
-               uint32_t n_fts_cc:8;
-               uint32_t l0el:3;
-               uint32_t l1el:3;
-               uint32_t reserved_30_31:2;
-#endif
-       } cn52xx;
-       struct cvmx_pciercx_cfg451_cn52xx cn52xxp1;
-       struct cvmx_pciercx_cfg451_cn52xx cn56xx;
-       struct cvmx_pciercx_cfg451_cn52xx cn56xxp1;
-       struct cvmx_pciercx_cfg451_s cn61xx;
-       struct cvmx_pciercx_cfg451_cn52xx cn63xx;
-       struct cvmx_pciercx_cfg451_cn52xx cn63xxp1;
-       struct cvmx_pciercx_cfg451_s cn66xx;
-       struct cvmx_pciercx_cfg451_s cn68xx;
-       struct cvmx_pciercx_cfg451_s cn68xxp1;
-       struct cvmx_pciercx_cfg451_s cnf71xx;
 };
 
 union cvmx_pciercx_cfg452 {
        uint32_t u32;
        struct cvmx_pciercx_cfg452_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_26_31:6;
-               uint32_t eccrc:1;
-               uint32_t reserved_22_24:3;
-               uint32_t lme:6;
-               uint32_t reserved_8_15:8;
-               uint32_t flm:1;
-               uint32_t reserved_6_6:1;
-               uint32_t dllle:1;
-               uint32_t reserved_4_4:1;
-               uint32_t ra:1;
-               uint32_t le:1;
-               uint32_t sd:1;
-               uint32_t omr:1;
-#else
-               uint32_t omr:1;
-               uint32_t sd:1;
-               uint32_t le:1;
-               uint32_t ra:1;
-               uint32_t reserved_4_4:1;
-               uint32_t dllle:1;
-               uint32_t reserved_6_6:1;
-               uint32_t flm:1;
-               uint32_t reserved_8_15:8;
-               uint32_t lme:6;
-               uint32_t reserved_22_24:3;
-               uint32_t eccrc:1;
-               uint32_t reserved_26_31:6;
-#endif
+               __BITFIELD_FIELD(uint32_t reserved_26_31:6,
+               __BITFIELD_FIELD(uint32_t eccrc:1,
+               __BITFIELD_FIELD(uint32_t reserved_22_24:3,
+               __BITFIELD_FIELD(uint32_t lme:6,
+               __BITFIELD_FIELD(uint32_t reserved_12_15:4,
+               __BITFIELD_FIELD(uint32_t link_rate:4,
+               __BITFIELD_FIELD(uint32_t flm:1,
+               __BITFIELD_FIELD(uint32_t reserved_6_6:1,
+               __BITFIELD_FIELD(uint32_t dllle:1,
+               __BITFIELD_FIELD(uint32_t reserved_4_4:1,
+               __BITFIELD_FIELD(uint32_t ra:1,
+               __BITFIELD_FIELD(uint32_t le:1,
+               __BITFIELD_FIELD(uint32_t sd:1,
+               __BITFIELD_FIELD(uint32_t omr:1,
+               ;))))))))))))))
        } s;
-       struct cvmx_pciercx_cfg452_s cn52xx;
-       struct cvmx_pciercx_cfg452_s cn52xxp1;
-       struct cvmx_pciercx_cfg452_s cn56xx;
-       struct cvmx_pciercx_cfg452_s cn56xxp1;
-       struct cvmx_pciercx_cfg452_cn61xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_22_31:10;
-               uint32_t lme:6;
-               uint32_t reserved_8_15:8;
-               uint32_t flm:1;
-               uint32_t reserved_6_6:1;
-               uint32_t dllle:1;
-               uint32_t reserved_4_4:1;
-               uint32_t ra:1;
-               uint32_t le:1;
-               uint32_t sd:1;
-               uint32_t omr:1;
-#else
-               uint32_t omr:1;
-               uint32_t sd:1;
-               uint32_t le:1;
-               uint32_t ra:1;
-               uint32_t reserved_4_4:1;
-               uint32_t dllle:1;
-               uint32_t reserved_6_6:1;
-               uint32_t flm:1;
-               uint32_t reserved_8_15:8;
-               uint32_t lme:6;
-               uint32_t reserved_22_31:10;
-#endif
-       } cn61xx;
-       struct cvmx_pciercx_cfg452_s cn63xx;
-       struct cvmx_pciercx_cfg452_s cn63xxp1;
-       struct cvmx_pciercx_cfg452_cn61xx cn66xx;
-       struct cvmx_pciercx_cfg452_cn61xx cn68xx;
-       struct cvmx_pciercx_cfg452_cn61xx cn68xxp1;
-       struct cvmx_pciercx_cfg452_cn61xx cnf71xx;
-};
-
-union cvmx_pciercx_cfg453 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg453_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t dlld:1;
-               uint32_t reserved_26_30:5;
-               uint32_t ack_nak:1;
-               uint32_t fcd:1;
-               uint32_t ilst:24;
-#else
-               uint32_t ilst:24;
-               uint32_t fcd:1;
-               uint32_t ack_nak:1;
-               uint32_t reserved_26_30:5;
-               uint32_t dlld:1;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg453_s cn52xx;
-       struct cvmx_pciercx_cfg453_s cn52xxp1;
-       struct cvmx_pciercx_cfg453_s cn56xx;
-       struct cvmx_pciercx_cfg453_s cn56xxp1;
-       struct cvmx_pciercx_cfg453_s cn61xx;
-       struct cvmx_pciercx_cfg453_s cn63xx;
-       struct cvmx_pciercx_cfg453_s cn63xxp1;
-       struct cvmx_pciercx_cfg453_s cn66xx;
-       struct cvmx_pciercx_cfg453_s cn68xx;
-       struct cvmx_pciercx_cfg453_s cn68xxp1;
-       struct cvmx_pciercx_cfg453_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg454 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg454_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t cx_nfunc:3;
-               uint32_t tmfcwt:5;
-               uint32_t tmanlt:5;
-               uint32_t tmrt:5;
-               uint32_t reserved_11_13:3;
-               uint32_t nskps:3;
-               uint32_t reserved_0_7:8;
-#else
-               uint32_t reserved_0_7:8;
-               uint32_t nskps:3;
-               uint32_t reserved_11_13:3;
-               uint32_t tmrt:5;
-               uint32_t tmanlt:5;
-               uint32_t tmfcwt:5;
-               uint32_t cx_nfunc:3;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg454_cn52xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_29_31:3;
-               uint32_t tmfcwt:5;
-               uint32_t tmanlt:5;
-               uint32_t tmrt:5;
-               uint32_t reserved_11_13:3;
-               uint32_t nskps:3;
-               uint32_t reserved_4_7:4;
-               uint32_t ntss:4;
-#else
-               uint32_t ntss:4;
-               uint32_t reserved_4_7:4;
-               uint32_t nskps:3;
-               uint32_t reserved_11_13:3;
-               uint32_t tmrt:5;
-               uint32_t tmanlt:5;
-               uint32_t tmfcwt:5;
-               uint32_t reserved_29_31:3;
-#endif
-       } cn52xx;
-       struct cvmx_pciercx_cfg454_cn52xx cn52xxp1;
-       struct cvmx_pciercx_cfg454_cn52xx cn56xx;
-       struct cvmx_pciercx_cfg454_cn52xx cn56xxp1;
-       struct cvmx_pciercx_cfg454_cn61xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t cx_nfunc:3;
-               uint32_t tmfcwt:5;
-               uint32_t tmanlt:5;
-               uint32_t tmrt:5;
-               uint32_t reserved_8_13:6;
-               uint32_t mfuncn:8;
-#else
-               uint32_t mfuncn:8;
-               uint32_t reserved_8_13:6;
-               uint32_t tmrt:5;
-               uint32_t tmanlt:5;
-               uint32_t tmfcwt:5;
-               uint32_t cx_nfunc:3;
-#endif
-       } cn61xx;
-       struct cvmx_pciercx_cfg454_cn52xx cn63xx;
-       struct cvmx_pciercx_cfg454_cn52xx cn63xxp1;
-       struct cvmx_pciercx_cfg454_cn61xx cn66xx;
-       struct cvmx_pciercx_cfg454_cn61xx cn68xx;
-       struct cvmx_pciercx_cfg454_cn52xx cn68xxp1;
-       struct cvmx_pciercx_cfg454_cn61xx cnf71xx;
 };
 
 union cvmx_pciercx_cfg455 {
        uint32_t u32;
        struct cvmx_pciercx_cfg455_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t m_cfg0_filt:1;
-               uint32_t m_io_filt:1;
-               uint32_t msg_ctrl:1;
-               uint32_t m_cpl_ecrc_filt:1;
-               uint32_t m_ecrc_filt:1;
-               uint32_t m_cpl_len_err:1;
-               uint32_t m_cpl_attr_err:1;
-               uint32_t m_cpl_tc_err:1;
-               uint32_t m_cpl_fun_err:1;
-               uint32_t m_cpl_rid_err:1;
-               uint32_t m_cpl_tag_err:1;
-               uint32_t m_lk_filt:1;
-               uint32_t m_cfg1_filt:1;
-               uint32_t m_bar_match:1;
-               uint32_t m_pois_filt:1;
-               uint32_t m_fun:1;
-               uint32_t dfcwt:1;
-               uint32_t reserved_11_14:4;
-               uint32_t skpiv:11;
-#else
-               uint32_t skpiv:11;
-               uint32_t reserved_11_14:4;
-               uint32_t dfcwt:1;
-               uint32_t m_fun:1;
-               uint32_t m_pois_filt:1;
-               uint32_t m_bar_match:1;
-               uint32_t m_cfg1_filt:1;
-               uint32_t m_lk_filt:1;
-               uint32_t m_cpl_tag_err:1;
-               uint32_t m_cpl_rid_err:1;
-               uint32_t m_cpl_fun_err:1;
-               uint32_t m_cpl_tc_err:1;
-               uint32_t m_cpl_attr_err:1;
-               uint32_t m_cpl_len_err:1;
-               uint32_t m_ecrc_filt:1;
-               uint32_t m_cpl_ecrc_filt:1;
-               uint32_t msg_ctrl:1;
-               uint32_t m_io_filt:1;
-               uint32_t m_cfg0_filt:1;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg455_s cn52xx;
-       struct cvmx_pciercx_cfg455_s cn52xxp1;
-       struct cvmx_pciercx_cfg455_s cn56xx;
-       struct cvmx_pciercx_cfg455_s cn56xxp1;
-       struct cvmx_pciercx_cfg455_s cn61xx;
-       struct cvmx_pciercx_cfg455_s cn63xx;
-       struct cvmx_pciercx_cfg455_s cn63xxp1;
-       struct cvmx_pciercx_cfg455_s cn66xx;
-       struct cvmx_pciercx_cfg455_s cn68xx;
-       struct cvmx_pciercx_cfg455_s cn68xxp1;
-       struct cvmx_pciercx_cfg455_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg456 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg456_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_4_31:28;
-               uint32_t m_handle_flush:1;
-               uint32_t m_dabort_4ucpl:1;
-               uint32_t m_vend1_drp:1;
-               uint32_t m_vend0_drp:1;
-#else
-               uint32_t m_vend0_drp:1;
-               uint32_t m_vend1_drp:1;
-               uint32_t m_dabort_4ucpl:1;
-               uint32_t m_handle_flush:1;
-               uint32_t reserved_4_31:28;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg456_cn52xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_2_31:30;
-               uint32_t m_vend1_drp:1;
-               uint32_t m_vend0_drp:1;
-#else
-               uint32_t m_vend0_drp:1;
-               uint32_t m_vend1_drp:1;
-               uint32_t reserved_2_31:30;
-#endif
-       } cn52xx;
-       struct cvmx_pciercx_cfg456_cn52xx cn52xxp1;
-       struct cvmx_pciercx_cfg456_cn52xx cn56xx;
-       struct cvmx_pciercx_cfg456_cn52xx cn56xxp1;
-       struct cvmx_pciercx_cfg456_s cn61xx;
-       struct cvmx_pciercx_cfg456_cn52xx cn63xx;
-       struct cvmx_pciercx_cfg456_cn52xx cn63xxp1;
-       struct cvmx_pciercx_cfg456_s cn66xx;
-       struct cvmx_pciercx_cfg456_s cn68xx;
-       struct cvmx_pciercx_cfg456_cn52xx cn68xxp1;
-       struct cvmx_pciercx_cfg456_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg458 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg458_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t dbg_info_l32:32;
-#else
-               uint32_t dbg_info_l32:32;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg458_s cn52xx;
-       struct cvmx_pciercx_cfg458_s cn52xxp1;
-       struct cvmx_pciercx_cfg458_s cn56xx;
-       struct cvmx_pciercx_cfg458_s cn56xxp1;
-       struct cvmx_pciercx_cfg458_s cn61xx;
-       struct cvmx_pciercx_cfg458_s cn63xx;
-       struct cvmx_pciercx_cfg458_s cn63xxp1;
-       struct cvmx_pciercx_cfg458_s cn66xx;
-       struct cvmx_pciercx_cfg458_s cn68xx;
-       struct cvmx_pciercx_cfg458_s cn68xxp1;
-       struct cvmx_pciercx_cfg458_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg459 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg459_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t dbg_info_u32:32;
-#else
-               uint32_t dbg_info_u32:32;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg459_s cn52xx;
-       struct cvmx_pciercx_cfg459_s cn52xxp1;
-       struct cvmx_pciercx_cfg459_s cn56xx;
-       struct cvmx_pciercx_cfg459_s cn56xxp1;
-       struct cvmx_pciercx_cfg459_s cn61xx;
-       struct cvmx_pciercx_cfg459_s cn63xx;
-       struct cvmx_pciercx_cfg459_s cn63xxp1;
-       struct cvmx_pciercx_cfg459_s cn66xx;
-       struct cvmx_pciercx_cfg459_s cn68xx;
-       struct cvmx_pciercx_cfg459_s cn68xxp1;
-       struct cvmx_pciercx_cfg459_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg460 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg460_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_20_31:12;
-               uint32_t tphfcc:8;
-               uint32_t tpdfcc:12;
-#else
-               uint32_t tpdfcc:12;
-               uint32_t tphfcc:8;
-               uint32_t reserved_20_31:12;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg460_s cn52xx;
-       struct cvmx_pciercx_cfg460_s cn52xxp1;
-       struct cvmx_pciercx_cfg460_s cn56xx;
-       struct cvmx_pciercx_cfg460_s cn56xxp1;
-       struct cvmx_pciercx_cfg460_s cn61xx;
-       struct cvmx_pciercx_cfg460_s cn63xx;
-       struct cvmx_pciercx_cfg460_s cn63xxp1;
-       struct cvmx_pciercx_cfg460_s cn66xx;
-       struct cvmx_pciercx_cfg460_s cn68xx;
-       struct cvmx_pciercx_cfg460_s cn68xxp1;
-       struct cvmx_pciercx_cfg460_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg461 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg461_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_20_31:12;
-               uint32_t tchfcc:8;
-               uint32_t tcdfcc:12;
-#else
-               uint32_t tcdfcc:12;
-               uint32_t tchfcc:8;
-               uint32_t reserved_20_31:12;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg461_s cn52xx;
-       struct cvmx_pciercx_cfg461_s cn52xxp1;
-       struct cvmx_pciercx_cfg461_s cn56xx;
-       struct cvmx_pciercx_cfg461_s cn56xxp1;
-       struct cvmx_pciercx_cfg461_s cn61xx;
-       struct cvmx_pciercx_cfg461_s cn63xx;
-       struct cvmx_pciercx_cfg461_s cn63xxp1;
-       struct cvmx_pciercx_cfg461_s cn66xx;
-       struct cvmx_pciercx_cfg461_s cn68xx;
-       struct cvmx_pciercx_cfg461_s cn68xxp1;
-       struct cvmx_pciercx_cfg461_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg462 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg462_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_20_31:12;
-               uint32_t tchfcc:8;
-               uint32_t tcdfcc:12;
-#else
-               uint32_t tcdfcc:12;
-               uint32_t tchfcc:8;
-               uint32_t reserved_20_31:12;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg462_s cn52xx;
-       struct cvmx_pciercx_cfg462_s cn52xxp1;
-       struct cvmx_pciercx_cfg462_s cn56xx;
-       struct cvmx_pciercx_cfg462_s cn56xxp1;
-       struct cvmx_pciercx_cfg462_s cn61xx;
-       struct cvmx_pciercx_cfg462_s cn63xx;
-       struct cvmx_pciercx_cfg462_s cn63xxp1;
-       struct cvmx_pciercx_cfg462_s cn66xx;
-       struct cvmx_pciercx_cfg462_s cn68xx;
-       struct cvmx_pciercx_cfg462_s cn68xxp1;
-       struct cvmx_pciercx_cfg462_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg463 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg463_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_3_31:29;
-               uint32_t rqne:1;
-               uint32_t trbne:1;
-               uint32_t rtlpfccnr:1;
-#else
-               uint32_t rtlpfccnr:1;
-               uint32_t trbne:1;
-               uint32_t rqne:1;
-               uint32_t reserved_3_31:29;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg463_s cn52xx;
-       struct cvmx_pciercx_cfg463_s cn52xxp1;
-       struct cvmx_pciercx_cfg463_s cn56xx;
-       struct cvmx_pciercx_cfg463_s cn56xxp1;
-       struct cvmx_pciercx_cfg463_s cn61xx;
-       struct cvmx_pciercx_cfg463_s cn63xx;
-       struct cvmx_pciercx_cfg463_s cn63xxp1;
-       struct cvmx_pciercx_cfg463_s cn66xx;
-       struct cvmx_pciercx_cfg463_s cn68xx;
-       struct cvmx_pciercx_cfg463_s cn68xxp1;
-       struct cvmx_pciercx_cfg463_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg464 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg464_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t wrr_vc3:8;
-               uint32_t wrr_vc2:8;
-               uint32_t wrr_vc1:8;
-               uint32_t wrr_vc0:8;
-#else
-               uint32_t wrr_vc0:8;
-               uint32_t wrr_vc1:8;
-               uint32_t wrr_vc2:8;
-               uint32_t wrr_vc3:8;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg464_s cn52xx;
-       struct cvmx_pciercx_cfg464_s cn52xxp1;
-       struct cvmx_pciercx_cfg464_s cn56xx;
-       struct cvmx_pciercx_cfg464_s cn56xxp1;
-       struct cvmx_pciercx_cfg464_s cn61xx;
-       struct cvmx_pciercx_cfg464_s cn63xx;
-       struct cvmx_pciercx_cfg464_s cn63xxp1;
-       struct cvmx_pciercx_cfg464_s cn66xx;
-       struct cvmx_pciercx_cfg464_s cn68xx;
-       struct cvmx_pciercx_cfg464_s cn68xxp1;
-       struct cvmx_pciercx_cfg464_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg465 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg465_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t wrr_vc7:8;
-               uint32_t wrr_vc6:8;
-               uint32_t wrr_vc5:8;
-               uint32_t wrr_vc4:8;
-#else
-               uint32_t wrr_vc4:8;
-               uint32_t wrr_vc5:8;
-               uint32_t wrr_vc6:8;
-               uint32_t wrr_vc7:8;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg465_s cn52xx;
-       struct cvmx_pciercx_cfg465_s cn52xxp1;
-       struct cvmx_pciercx_cfg465_s cn56xx;
-       struct cvmx_pciercx_cfg465_s cn56xxp1;
-       struct cvmx_pciercx_cfg465_s cn61xx;
-       struct cvmx_pciercx_cfg465_s cn63xx;
-       struct cvmx_pciercx_cfg465_s cn63xxp1;
-       struct cvmx_pciercx_cfg465_s cn66xx;
-       struct cvmx_pciercx_cfg465_s cn68xx;
-       struct cvmx_pciercx_cfg465_s cn68xxp1;
-       struct cvmx_pciercx_cfg465_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg466 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg466_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t rx_queue_order:1;
-               uint32_t type_ordering:1;
-               uint32_t reserved_24_29:6;
-               uint32_t queue_mode:3;
-               uint32_t reserved_20_20:1;
-               uint32_t header_credits:8;
-               uint32_t data_credits:12;
-#else
-               uint32_t data_credits:12;
-               uint32_t header_credits:8;
-               uint32_t reserved_20_20:1;
-               uint32_t queue_mode:3;
-               uint32_t reserved_24_29:6;
-               uint32_t type_ordering:1;
-               uint32_t rx_queue_order:1;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg466_s cn52xx;
-       struct cvmx_pciercx_cfg466_s cn52xxp1;
-       struct cvmx_pciercx_cfg466_s cn56xx;
-       struct cvmx_pciercx_cfg466_s cn56xxp1;
-       struct cvmx_pciercx_cfg466_s cn61xx;
-       struct cvmx_pciercx_cfg466_s cn63xx;
-       struct cvmx_pciercx_cfg466_s cn63xxp1;
-       struct cvmx_pciercx_cfg466_s cn66xx;
-       struct cvmx_pciercx_cfg466_s cn68xx;
-       struct cvmx_pciercx_cfg466_s cn68xxp1;
-       struct cvmx_pciercx_cfg466_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg467 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg467_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_24_31:8;
-               uint32_t queue_mode:3;
-               uint32_t reserved_20_20:1;
-               uint32_t header_credits:8;
-               uint32_t data_credits:12;
-#else
-               uint32_t data_credits:12;
-               uint32_t header_credits:8;
-               uint32_t reserved_20_20:1;
-               uint32_t queue_mode:3;
-               uint32_t reserved_24_31:8;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg467_s cn52xx;
-       struct cvmx_pciercx_cfg467_s cn52xxp1;
-       struct cvmx_pciercx_cfg467_s cn56xx;
-       struct cvmx_pciercx_cfg467_s cn56xxp1;
-       struct cvmx_pciercx_cfg467_s cn61xx;
-       struct cvmx_pciercx_cfg467_s cn63xx;
-       struct cvmx_pciercx_cfg467_s cn63xxp1;
-       struct cvmx_pciercx_cfg467_s cn66xx;
-       struct cvmx_pciercx_cfg467_s cn68xx;
-       struct cvmx_pciercx_cfg467_s cn68xxp1;
-       struct cvmx_pciercx_cfg467_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg468 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg468_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_24_31:8;
-               uint32_t queue_mode:3;
-               uint32_t reserved_20_20:1;
-               uint32_t header_credits:8;
-               uint32_t data_credits:12;
-#else
-               uint32_t data_credits:12;
-               uint32_t header_credits:8;
-               uint32_t reserved_20_20:1;
-               uint32_t queue_mode:3;
-               uint32_t reserved_24_31:8;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg468_s cn52xx;
-       struct cvmx_pciercx_cfg468_s cn52xxp1;
-       struct cvmx_pciercx_cfg468_s cn56xx;
-       struct cvmx_pciercx_cfg468_s cn56xxp1;
-       struct cvmx_pciercx_cfg468_s cn61xx;
-       struct cvmx_pciercx_cfg468_s cn63xx;
-       struct cvmx_pciercx_cfg468_s cn63xxp1;
-       struct cvmx_pciercx_cfg468_s cn66xx;
-       struct cvmx_pciercx_cfg468_s cn68xx;
-       struct cvmx_pciercx_cfg468_s cn68xxp1;
-       struct cvmx_pciercx_cfg468_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg490 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg490_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_26_31:6;
-               uint32_t header_depth:10;
-               uint32_t reserved_14_15:2;
-               uint32_t data_depth:14;
-#else
-               uint32_t data_depth:14;
-               uint32_t reserved_14_15:2;
-               uint32_t header_depth:10;
-               uint32_t reserved_26_31:6;
-#endif
+               __BITFIELD_FIELD(uint32_t m_cfg0_filt:1,
+               __BITFIELD_FIELD(uint32_t m_io_filt:1,
+               __BITFIELD_FIELD(uint32_t msg_ctrl:1,
+               __BITFIELD_FIELD(uint32_t m_cpl_ecrc_filt:1,
+               __BITFIELD_FIELD(uint32_t m_ecrc_filt:1,
+               __BITFIELD_FIELD(uint32_t m_cpl_len_err:1,
+               __BITFIELD_FIELD(uint32_t m_cpl_attr_err:1,
+               __BITFIELD_FIELD(uint32_t m_cpl_tc_err:1,
+               __BITFIELD_FIELD(uint32_t m_cpl_fun_err:1,
+               __BITFIELD_FIELD(uint32_t m_cpl_rid_err:1,
+               __BITFIELD_FIELD(uint32_t m_cpl_tag_err:1,
+               __BITFIELD_FIELD(uint32_t m_lk_filt:1,
+               __BITFIELD_FIELD(uint32_t m_cfg1_filt:1,
+               __BITFIELD_FIELD(uint32_t m_bar_match:1,
+               __BITFIELD_FIELD(uint32_t m_pois_filt:1,
+               __BITFIELD_FIELD(uint32_t m_fun:1,
+               __BITFIELD_FIELD(uint32_t dfcwt:1,
+               __BITFIELD_FIELD(uint32_t reserved_11_14:4,
+               __BITFIELD_FIELD(uint32_t skpiv:11,
+               ;)))))))))))))))))))
        } s;
-       struct cvmx_pciercx_cfg490_s cn52xx;
-       struct cvmx_pciercx_cfg490_s cn52xxp1;
-       struct cvmx_pciercx_cfg490_s cn56xx;
-       struct cvmx_pciercx_cfg490_s cn56xxp1;
-       struct cvmx_pciercx_cfg490_s cn61xx;
-       struct cvmx_pciercx_cfg490_s cn63xx;
-       struct cvmx_pciercx_cfg490_s cn63xxp1;
-       struct cvmx_pciercx_cfg490_s cn66xx;
-       struct cvmx_pciercx_cfg490_s cn68xx;
-       struct cvmx_pciercx_cfg490_s cn68xxp1;
-       struct cvmx_pciercx_cfg490_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg491 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg491_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_26_31:6;
-               uint32_t header_depth:10;
-               uint32_t reserved_14_15:2;
-               uint32_t data_depth:14;
-#else
-               uint32_t data_depth:14;
-               uint32_t reserved_14_15:2;
-               uint32_t header_depth:10;
-               uint32_t reserved_26_31:6;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg491_s cn52xx;
-       struct cvmx_pciercx_cfg491_s cn52xxp1;
-       struct cvmx_pciercx_cfg491_s cn56xx;
-       struct cvmx_pciercx_cfg491_s cn56xxp1;
-       struct cvmx_pciercx_cfg491_s cn61xx;
-       struct cvmx_pciercx_cfg491_s cn63xx;
-       struct cvmx_pciercx_cfg491_s cn63xxp1;
-       struct cvmx_pciercx_cfg491_s cn66xx;
-       struct cvmx_pciercx_cfg491_s cn68xx;
-       struct cvmx_pciercx_cfg491_s cn68xxp1;
-       struct cvmx_pciercx_cfg491_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg492 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg492_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_26_31:6;
-               uint32_t header_depth:10;
-               uint32_t reserved_14_15:2;
-               uint32_t data_depth:14;
-#else
-               uint32_t data_depth:14;
-               uint32_t reserved_14_15:2;
-               uint32_t header_depth:10;
-               uint32_t reserved_26_31:6;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg492_s cn52xx;
-       struct cvmx_pciercx_cfg492_s cn52xxp1;
-       struct cvmx_pciercx_cfg492_s cn56xx;
-       struct cvmx_pciercx_cfg492_s cn56xxp1;
-       struct cvmx_pciercx_cfg492_s cn61xx;
-       struct cvmx_pciercx_cfg492_s cn63xx;
-       struct cvmx_pciercx_cfg492_s cn63xxp1;
-       struct cvmx_pciercx_cfg492_s cn66xx;
-       struct cvmx_pciercx_cfg492_s cn68xx;
-       struct cvmx_pciercx_cfg492_s cn68xxp1;
-       struct cvmx_pciercx_cfg492_s cnf71xx;
 };
 
 union cvmx_pciercx_cfg515 {
        uint32_t u32;
        struct cvmx_pciercx_cfg515_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t reserved_21_31:11;
-               uint32_t s_d_e:1;
-               uint32_t ctcrb:1;
-               uint32_t cpyts:1;
-               uint32_t dsc:1;
-               uint32_t le:9;
-               uint32_t n_fts:8;
-#else
-               uint32_t n_fts:8;
-               uint32_t le:9;
-               uint32_t dsc:1;
-               uint32_t cpyts:1;
-               uint32_t ctcrb:1;
-               uint32_t s_d_e:1;
-               uint32_t reserved_21_31:11;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg515_s cn61xx;
-       struct cvmx_pciercx_cfg515_s cn63xx;
-       struct cvmx_pciercx_cfg515_s cn63xxp1;
-       struct cvmx_pciercx_cfg515_s cn66xx;
-       struct cvmx_pciercx_cfg515_s cn68xx;
-       struct cvmx_pciercx_cfg515_s cn68xxp1;
-       struct cvmx_pciercx_cfg515_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg516 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg516_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t phy_stat:32;
-#else
-               uint32_t phy_stat:32;
-#endif
-       } s;
-       struct cvmx_pciercx_cfg516_s cn52xx;
-       struct cvmx_pciercx_cfg516_s cn52xxp1;
-       struct cvmx_pciercx_cfg516_s cn56xx;
-       struct cvmx_pciercx_cfg516_s cn56xxp1;
-       struct cvmx_pciercx_cfg516_s cn61xx;
-       struct cvmx_pciercx_cfg516_s cn63xx;
-       struct cvmx_pciercx_cfg516_s cn63xxp1;
-       struct cvmx_pciercx_cfg516_s cn66xx;
-       struct cvmx_pciercx_cfg516_s cn68xx;
-       struct cvmx_pciercx_cfg516_s cn68xxp1;
-       struct cvmx_pciercx_cfg516_s cnf71xx;
-};
-
-union cvmx_pciercx_cfg517 {
-       uint32_t u32;
-       struct cvmx_pciercx_cfg517_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint32_t phy_ctrl:32;
-#else
-               uint32_t phy_ctrl:32;
-#endif
+               __BITFIELD_FIELD(uint32_t reserved_21_31:11,
+               __BITFIELD_FIELD(uint32_t s_d_e:1,
+               __BITFIELD_FIELD(uint32_t ctcrb:1,
+               __BITFIELD_FIELD(uint32_t cpyts:1,
+               __BITFIELD_FIELD(uint32_t dsc:1,
+               __BITFIELD_FIELD(uint32_t le:9,
+               __BITFIELD_FIELD(uint32_t n_fts:8,
+               ;)))))))
        } s;
-       struct cvmx_pciercx_cfg517_s cn52xx;
-       struct cvmx_pciercx_cfg517_s cn52xxp1;
-       struct cvmx_pciercx_cfg517_s cn56xx;
-       struct cvmx_pciercx_cfg517_s cn56xxp1;
-       struct cvmx_pciercx_cfg517_s cn61xx;
-       struct cvmx_pciercx_cfg517_s cn63xx;
-       struct cvmx_pciercx_cfg517_s cn63xxp1;
-       struct cvmx_pciercx_cfg517_s cn66xx;
-       struct cvmx_pciercx_cfg517_s cn68xx;
-       struct cvmx_pciercx_cfg517_s cn68xxp1;
-       struct cvmx_pciercx_cfg517_s cnf71xx;
 };
 
 #endif
index e697c2f52a62228689a2a21662c21b95cc1fbd43..52cf96ea43e5dfdba220101d5f1f6eef64875148 100644 (file)
@@ -4,7 +4,7 @@
  * Contact: support@caviumnetworks.com
  * This file is part of the OCTEON SDK
  *
- * Copyright (c) 2003-2012 Cavium Networks
+ * Copyright (c) 2003-2017 Cavium, Inc.
  *
  * This file is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License, Version 2, as
 #ifndef __CVMX_SLI_DEFS_H__
 #define __CVMX_SLI_DEFS_H__
 
-#define CVMX_SLI_BIST_STATUS (0x0000000000000580ull)
-#define CVMX_SLI_CTL_PORTX(offset) (0x0000000000000050ull + ((offset) & 3) * 16)
-#define CVMX_SLI_CTL_STATUS (0x0000000000000570ull)
-#define CVMX_SLI_DATA_OUT_CNT (0x00000000000005F0ull)
-#define CVMX_SLI_DBG_DATA (0x0000000000000310ull)
-#define CVMX_SLI_DBG_SELECT (0x0000000000000300ull)
-#define CVMX_SLI_DMAX_CNT(offset) (0x0000000000000400ull + ((offset) & 1) * 16)
-#define CVMX_SLI_DMAX_INT_LEVEL(offset) (0x00000000000003E0ull + ((offset) & 1) * 16)
-#define CVMX_SLI_DMAX_TIM(offset) (0x0000000000000420ull + ((offset) & 1) * 16)
-#define CVMX_SLI_INT_ENB_CIU (0x0000000000003CD0ull)
-#define CVMX_SLI_INT_ENB_PORTX(offset) (0x0000000000000340ull + ((offset) & 1) * 16)
-#define CVMX_SLI_INT_SUM (0x0000000000000330ull)
-#define CVMX_SLI_LAST_WIN_RDATA0 (0x0000000000000600ull)
-#define CVMX_SLI_LAST_WIN_RDATA1 (0x0000000000000610ull)
-#define CVMX_SLI_LAST_WIN_RDATA2 (0x00000000000006C0ull)
-#define CVMX_SLI_LAST_WIN_RDATA3 (0x00000000000006D0ull)
-#define CVMX_SLI_MAC_CREDIT_CNT (0x0000000000003D70ull)
-#define CVMX_SLI_MAC_CREDIT_CNT2 (0x0000000000003E10ull)
-#define CVMX_SLI_MAC_NUMBER (0x0000000000003E00ull)
-#define CVMX_SLI_MEM_ACCESS_CTL (0x00000000000002F0ull)
-#define CVMX_SLI_MEM_ACCESS_SUBIDX(offset) (0x00000000000000E0ull + ((offset) & 31) * 16 - 16*12)
-#define CVMX_SLI_MSI_ENB0 (0x0000000000003C50ull)
-#define CVMX_SLI_MSI_ENB1 (0x0000000000003C60ull)
-#define CVMX_SLI_MSI_ENB2 (0x0000000000003C70ull)
-#define CVMX_SLI_MSI_ENB3 (0x0000000000003C80ull)
-#define CVMX_SLI_MSI_RCV0 (0x0000000000003C10ull)
-#define CVMX_SLI_MSI_RCV1 (0x0000000000003C20ull)
-#define CVMX_SLI_MSI_RCV2 (0x0000000000003C30ull)
-#define CVMX_SLI_MSI_RCV3 (0x0000000000003C40ull)
-#define CVMX_SLI_MSI_RD_MAP (0x0000000000003CA0ull)
-#define CVMX_SLI_MSI_W1C_ENB0 (0x0000000000003CF0ull)
-#define CVMX_SLI_MSI_W1C_ENB1 (0x0000000000003D00ull)
-#define CVMX_SLI_MSI_W1C_ENB2 (0x0000000000003D10ull)
-#define CVMX_SLI_MSI_W1C_ENB3 (0x0000000000003D20ull)
-#define CVMX_SLI_MSI_W1S_ENB0 (0x0000000000003D30ull)
-#define CVMX_SLI_MSI_W1S_ENB1 (0x0000000000003D40ull)
-#define CVMX_SLI_MSI_W1S_ENB2 (0x0000000000003D50ull)
-#define CVMX_SLI_MSI_W1S_ENB3 (0x0000000000003D60ull)
-#define CVMX_SLI_MSI_WR_MAP (0x0000000000003C90ull)
-#define CVMX_SLI_PCIE_MSI_RCV (0x0000000000003CB0ull)
-#define CVMX_SLI_PCIE_MSI_RCV_B1 (0x0000000000000650ull)
-#define CVMX_SLI_PCIE_MSI_RCV_B2 (0x0000000000000660ull)
-#define CVMX_SLI_PCIE_MSI_RCV_B3 (0x0000000000000670ull)
-#define CVMX_SLI_PKTX_CNTS(offset) (0x0000000000002400ull + ((offset) & 31) * 16)
-#define CVMX_SLI_PKTX_INSTR_BADDR(offset) (0x0000000000002800ull + ((offset) & 31) * 16)
-#define CVMX_SLI_PKTX_INSTR_BAOFF_DBELL(offset) (0x0000000000002C00ull + ((offset) & 31) * 16)
-#define CVMX_SLI_PKTX_INSTR_FIFO_RSIZE(offset) (0x0000000000003000ull + ((offset) & 31) * 16)
-#define CVMX_SLI_PKTX_INSTR_HEADER(offset) (0x0000000000003400ull + ((offset) & 31) * 16)
-#define CVMX_SLI_PKTX_IN_BP(offset) (0x0000000000003800ull + ((offset) & 31) * 16)
-#define CVMX_SLI_PKTX_OUT_SIZE(offset) (0x0000000000000C00ull + ((offset) & 31) * 16)
-#define CVMX_SLI_PKTX_SLIST_BADDR(offset) (0x0000000000001400ull + ((offset) & 31) * 16)
-#define CVMX_SLI_PKTX_SLIST_BAOFF_DBELL(offset) (0x0000000000001800ull + ((offset) & 31) * 16)
-#define CVMX_SLI_PKTX_SLIST_FIFO_RSIZE(offset) (0x0000000000001C00ull + ((offset) & 31) * 16)
-#define CVMX_SLI_PKT_CNT_INT (0x0000000000001130ull)
-#define CVMX_SLI_PKT_CNT_INT_ENB (0x0000000000001150ull)
-#define CVMX_SLI_PKT_CTL (0x0000000000001220ull)
-#define CVMX_SLI_PKT_DATA_OUT_ES (0x00000000000010B0ull)
-#define CVMX_SLI_PKT_DATA_OUT_NS (0x00000000000010A0ull)
-#define CVMX_SLI_PKT_DATA_OUT_ROR (0x0000000000001090ull)
-#define CVMX_SLI_PKT_DPADDR (0x0000000000001080ull)
-#define CVMX_SLI_PKT_INPUT_CONTROL (0x0000000000001170ull)
-#define CVMX_SLI_PKT_INSTR_ENB (0x0000000000001000ull)
-#define CVMX_SLI_PKT_INSTR_RD_SIZE (0x00000000000011A0ull)
-#define CVMX_SLI_PKT_INSTR_SIZE (0x0000000000001020ull)
-#define CVMX_SLI_PKT_INT_LEVELS (0x0000000000001120ull)
-#define CVMX_SLI_PKT_IN_BP (0x0000000000001210ull)
-#define CVMX_SLI_PKT_IN_DONEX_CNTS(offset) (0x0000000000002000ull + ((offset) & 31) * 16)
-#define CVMX_SLI_PKT_IN_INSTR_COUNTS (0x0000000000001200ull)
-#define CVMX_SLI_PKT_IN_PCIE_PORT (0x00000000000011B0ull)
-#define CVMX_SLI_PKT_IPTR (0x0000000000001070ull)
-#define CVMX_SLI_PKT_OUTPUT_WMARK (0x0000000000001180ull)
-#define CVMX_SLI_PKT_OUT_BMODE (0x00000000000010D0ull)
-#define CVMX_SLI_PKT_OUT_BP_EN (0x0000000000001240ull)
-#define CVMX_SLI_PKT_OUT_ENB (0x0000000000001010ull)
-#define CVMX_SLI_PKT_PCIE_PORT (0x00000000000010E0ull)
-#define CVMX_SLI_PKT_PORT_IN_RST (0x00000000000011F0ull)
-#define CVMX_SLI_PKT_SLIST_ES (0x0000000000001050ull)
-#define CVMX_SLI_PKT_SLIST_NS (0x0000000000001040ull)
-#define CVMX_SLI_PKT_SLIST_ROR (0x0000000000001030ull)
-#define CVMX_SLI_PKT_TIME_INT (0x0000000000001140ull)
-#define CVMX_SLI_PKT_TIME_INT_ENB (0x0000000000001160ull)
-#define CVMX_SLI_PORTX_PKIND(offset) (0x0000000000000800ull + ((offset) & 31) * 16)
-#define CVMX_SLI_S2M_PORTX_CTL(offset) (0x0000000000003D80ull + ((offset) & 3) * 16)
-#define CVMX_SLI_SCRATCH_1 (0x00000000000003C0ull)
-#define CVMX_SLI_SCRATCH_2 (0x00000000000003D0ull)
-#define CVMX_SLI_STATE1 (0x0000000000000620ull)
-#define CVMX_SLI_STATE2 (0x0000000000000630ull)
-#define CVMX_SLI_STATE3 (0x0000000000000640ull)
-#define CVMX_SLI_TX_PIPE (0x0000000000001230ull)
-#define CVMX_SLI_WINDOW_CTL (0x00000000000002E0ull)
-#define CVMX_SLI_WIN_RD_ADDR (0x0000000000000010ull)
-#define CVMX_SLI_WIN_RD_DATA (0x0000000000000040ull)
-#define CVMX_SLI_WIN_WR_ADDR (0x0000000000000000ull)
-#define CVMX_SLI_WIN_WR_DATA (0x0000000000000020ull)
-#define CVMX_SLI_WIN_WR_MASK (0x0000000000000030ull)
+#include <uapi/asm/bitfield.h>
+
+#define CVMX_SLI_PCIE_MSI_RCV CVMX_SLI_PCIE_MSI_RCV_FUNC()
+static inline uint64_t CVMX_SLI_PCIE_MSI_RCV_FUNC(void)
+{
+       switch (cvmx_get_octeon_family()) {
+       case OCTEON_CNF71XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CN61XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CN63XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CN66XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CN68XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CN70XX & OCTEON_FAMILY_MASK:
+               return 0x0000000000003CB0ull;
+       case OCTEON_CNF75XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CN73XX & OCTEON_FAMILY_MASK:
+       case OCTEON_CN78XX & OCTEON_FAMILY_MASK:
+               if (OCTEON_IS_MODEL(OCTEON_CN78XX_PASS1_X))
+                       return 0x0000000000003CB0ull;
+       default:
+               return 0x0000000000023CB0ull;
+       }
+}
 
-union cvmx_sli_bist_status {
-       uint64_t u64;
-       struct cvmx_sli_bist_status_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t ncb_req:1;
-               uint64_t n2p0_c:1;
-               uint64_t n2p0_o:1;
-               uint64_t n2p1_c:1;
-               uint64_t n2p1_o:1;
-               uint64_t cpl_p0:1;
-               uint64_t cpl_p1:1;
-               uint64_t reserved_19_24:6;
-               uint64_t p2n0_c0:1;
-               uint64_t p2n0_c1:1;
-               uint64_t p2n0_n:1;
-               uint64_t p2n0_p0:1;
-               uint64_t p2n0_p1:1;
-               uint64_t p2n1_c0:1;
-               uint64_t p2n1_c1:1;
-               uint64_t p2n1_n:1;
-               uint64_t p2n1_p0:1;
-               uint64_t p2n1_p1:1;
-               uint64_t reserved_6_8:3;
-               uint64_t dsi1_1:1;
-               uint64_t dsi1_0:1;
-               uint64_t dsi0_1:1;
-               uint64_t dsi0_0:1;
-               uint64_t msi:1;
-               uint64_t ncb_cmd:1;
-#else
-               uint64_t ncb_cmd:1;
-               uint64_t msi:1;
-               uint64_t dsi0_0:1;
-               uint64_t dsi0_1:1;
-               uint64_t dsi1_0:1;
-               uint64_t dsi1_1:1;
-               uint64_t reserved_6_8:3;
-               uint64_t p2n1_p1:1;
-               uint64_t p2n1_p0:1;
-               uint64_t p2n1_n:1;
-               uint64_t p2n1_c1:1;
-               uint64_t p2n1_c0:1;
-               uint64_t p2n0_p1:1;
-               uint64_t p2n0_p0:1;
-               uint64_t p2n0_n:1;
-               uint64_t p2n0_c1:1;
-               uint64_t p2n0_c0:1;
-               uint64_t reserved_19_24:6;
-               uint64_t cpl_p1:1;
-               uint64_t cpl_p0:1;
-               uint64_t n2p1_o:1;
-               uint64_t n2p1_c:1;
-               uint64_t n2p0_o:1;
-               uint64_t n2p0_c:1;
-               uint64_t ncb_req:1;
-               uint64_t reserved_32_63:32;
-#endif
-       } s;
-       struct cvmx_sli_bist_status_cn61xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_31_63:33;
-               uint64_t n2p0_c:1;
-               uint64_t n2p0_o:1;
-               uint64_t reserved_27_28:2;
-               uint64_t cpl_p0:1;
-               uint64_t cpl_p1:1;
-               uint64_t reserved_19_24:6;
-               uint64_t p2n0_c0:1;
-               uint64_t p2n0_c1:1;
-               uint64_t p2n0_n:1;
-               uint64_t p2n0_p0:1;
-               uint64_t p2n0_p1:1;
-               uint64_t p2n1_c0:1;
-               uint64_t p2n1_c1:1;
-               uint64_t p2n1_n:1;
-               uint64_t p2n1_p0:1;
-               uint64_t p2n1_p1:1;
-               uint64_t reserved_6_8:3;
-               uint64_t dsi1_1:1;
-               uint64_t dsi1_0:1;
-               uint64_t dsi0_1:1;
-               uint64_t dsi0_0:1;
-               uint64_t msi:1;
-               uint64_t ncb_cmd:1;
-#else
-               uint64_t ncb_cmd:1;
-               uint64_t msi:1;
-               uint64_t dsi0_0:1;
-               uint64_t dsi0_1:1;
-               uint64_t dsi1_0:1;
-               uint64_t dsi1_1:1;
-               uint64_t reserved_6_8:3;
-               uint64_t p2n1_p1:1;
-               uint64_t p2n1_p0:1;
-               uint64_t p2n1_n:1;
-               uint64_t p2n1_c1:1;
-               uint64_t p2n1_c0:1;
-               uint64_t p2n0_p1:1;
-               uint64_t p2n0_p0:1;
-               uint64_t p2n0_n:1;
-               uint64_t p2n0_c1:1;
-               uint64_t p2n0_c0:1;
-               uint64_t reserved_19_24:6;
-               uint64_t cpl_p1:1;
-               uint64_t cpl_p0:1;
-               uint64_t reserved_27_28:2;
-               uint64_t n2p0_o:1;
-               uint64_t n2p0_c:1;
-               uint64_t reserved_31_63:33;
-#endif
-       } cn61xx;
-       struct cvmx_sli_bist_status_cn63xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_31_63:33;
-               uint64_t n2p0_c:1;
-               uint64_t n2p0_o:1;
-               uint64_t n2p1_c:1;
-               uint64_t n2p1_o:1;
-               uint64_t cpl_p0:1;
-               uint64_t cpl_p1:1;
-               uint64_t reserved_19_24:6;
-               uint64_t p2n0_c0:1;
-               uint64_t p2n0_c1:1;
-               uint64_t p2n0_n:1;
-               uint64_t p2n0_p0:1;
-               uint64_t p2n0_p1:1;
-               uint64_t p2n1_c0:1;
-               uint64_t p2n1_c1:1;
-               uint64_t p2n1_n:1;
-               uint64_t p2n1_p0:1;
-               uint64_t p2n1_p1:1;
-               uint64_t reserved_6_8:3;
-               uint64_t dsi1_1:1;
-               uint64_t dsi1_0:1;
-               uint64_t dsi0_1:1;
-               uint64_t dsi0_0:1;
-               uint64_t msi:1;
-               uint64_t ncb_cmd:1;
-#else
-               uint64_t ncb_cmd:1;
-               uint64_t msi:1;
-               uint64_t dsi0_0:1;
-               uint64_t dsi0_1:1;
-               uint64_t dsi1_0:1;
-               uint64_t dsi1_1:1;
-               uint64_t reserved_6_8:3;
-               uint64_t p2n1_p1:1;
-               uint64_t p2n1_p0:1;
-               uint64_t p2n1_n:1;
-               uint64_t p2n1_c1:1;
-               uint64_t p2n1_c0:1;
-               uint64_t p2n0_p1:1;
-               uint64_t p2n0_p0:1;
-               uint64_t p2n0_n:1;
-               uint64_t p2n0_c1:1;
-               uint64_t p2n0_c0:1;
-               uint64_t reserved_19_24:6;
-               uint64_t cpl_p1:1;
-               uint64_t cpl_p0:1;
-               uint64_t n2p1_o:1;
-               uint64_t n2p1_c:1;
-               uint64_t n2p0_o:1;
-               uint64_t n2p0_c:1;
-               uint64_t reserved_31_63:33;
-#endif
-       } cn63xx;
-       struct cvmx_sli_bist_status_cn63xx cn63xxp1;
-       struct cvmx_sli_bist_status_cn61xx cn66xx;
-       struct cvmx_sli_bist_status_s cn68xx;
-       struct cvmx_sli_bist_status_s cn68xxp1;
-       struct cvmx_sli_bist_status_cn61xx cnf71xx;
-};
 
 union cvmx_sli_ctl_portx {
        uint64_t u64;
        struct cvmx_sli_ctl_portx_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_22_63:42;
-               uint64_t intd:1;
-               uint64_t intc:1;
-               uint64_t intb:1;
-               uint64_t inta:1;
-               uint64_t dis_port:1;
-               uint64_t waitl_com:1;
-               uint64_t intd_map:2;
-               uint64_t intc_map:2;
-               uint64_t intb_map:2;
-               uint64_t inta_map:2;
-               uint64_t ctlp_ro:1;
-               uint64_t reserved_6_6:1;
-               uint64_t ptlp_ro:1;
-               uint64_t reserved_1_4:4;
-               uint64_t wait_com:1;
-#else
-               uint64_t wait_com:1;
-               uint64_t reserved_1_4:4;
-               uint64_t ptlp_ro:1;
-               uint64_t reserved_6_6:1;
-               uint64_t ctlp_ro:1;
-               uint64_t inta_map:2;
-               uint64_t intb_map:2;
-               uint64_t intc_map:2;
-               uint64_t intd_map:2;
-               uint64_t waitl_com:1;
-               uint64_t dis_port:1;
-               uint64_t inta:1;
-               uint64_t intb:1;
-               uint64_t intc:1;
-               uint64_t intd:1;
-               uint64_t reserved_22_63:42;
-#endif
-       } s;
-       struct cvmx_sli_ctl_portx_s cn61xx;
-       struct cvmx_sli_ctl_portx_s cn63xx;
-       struct cvmx_sli_ctl_portx_s cn63xxp1;
-       struct cvmx_sli_ctl_portx_s cn66xx;
-       struct cvmx_sli_ctl_portx_s cn68xx;
-       struct cvmx_sli_ctl_portx_s cn68xxp1;
-       struct cvmx_sli_ctl_portx_s cnf71xx;
-};
-
-union cvmx_sli_ctl_status {
-       uint64_t u64;
-       struct cvmx_sli_ctl_status_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_20_63:44;
-               uint64_t p1_ntags:6;
-               uint64_t p0_ntags:6;
-               uint64_t chip_rev:8;
-#else
-               uint64_t chip_rev:8;
-               uint64_t p0_ntags:6;
-               uint64_t p1_ntags:6;
-               uint64_t reserved_20_63:44;
-#endif
-       } s;
-       struct cvmx_sli_ctl_status_cn61xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_14_63:50;
-               uint64_t p0_ntags:6;
-               uint64_t chip_rev:8;
-#else
-               uint64_t chip_rev:8;
-               uint64_t p0_ntags:6;
-               uint64_t reserved_14_63:50;
-#endif
-       } cn61xx;
-       struct cvmx_sli_ctl_status_s cn63xx;
-       struct cvmx_sli_ctl_status_s cn63xxp1;
-       struct cvmx_sli_ctl_status_cn61xx cn66xx;
-       struct cvmx_sli_ctl_status_s cn68xx;
-       struct cvmx_sli_ctl_status_s cn68xxp1;
-       struct cvmx_sli_ctl_status_cn61xx cnf71xx;
-};
-
-union cvmx_sli_data_out_cnt {
-       uint64_t u64;
-       struct cvmx_sli_data_out_cnt_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_44_63:20;
-               uint64_t p1_ucnt:16;
-               uint64_t p1_fcnt:6;
-               uint64_t p0_ucnt:16;
-               uint64_t p0_fcnt:6;
-#else
-               uint64_t p0_fcnt:6;
-               uint64_t p0_ucnt:16;
-               uint64_t p1_fcnt:6;
-               uint64_t p1_ucnt:16;
-               uint64_t reserved_44_63:20;
-#endif
-       } s;
-       struct cvmx_sli_data_out_cnt_s cn61xx;
-       struct cvmx_sli_data_out_cnt_s cn63xx;
-       struct cvmx_sli_data_out_cnt_s cn63xxp1;
-       struct cvmx_sli_data_out_cnt_s cn66xx;
-       struct cvmx_sli_data_out_cnt_s cn68xx;
-       struct cvmx_sli_data_out_cnt_s cn68xxp1;
-       struct cvmx_sli_data_out_cnt_s cnf71xx;
-};
-
-union cvmx_sli_dbg_data {
-       uint64_t u64;
-       struct cvmx_sli_dbg_data_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_18_63:46;
-               uint64_t dsel_ext:1;
-               uint64_t data:17;
-#else
-               uint64_t data:17;
-               uint64_t dsel_ext:1;
-               uint64_t reserved_18_63:46;
-#endif
-       } s;
-       struct cvmx_sli_dbg_data_s cn61xx;
-       struct cvmx_sli_dbg_data_s cn63xx;
-       struct cvmx_sli_dbg_data_s cn63xxp1;
-       struct cvmx_sli_dbg_data_s cn66xx;
-       struct cvmx_sli_dbg_data_s cn68xx;
-       struct cvmx_sli_dbg_data_s cn68xxp1;
-       struct cvmx_sli_dbg_data_s cnf71xx;
-};
-
-union cvmx_sli_dbg_select {
-       uint64_t u64;
-       struct cvmx_sli_dbg_select_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_33_63:31;
-               uint64_t adbg_sel:1;
-               uint64_t dbg_sel:32;
-#else
-               uint64_t dbg_sel:32;
-               uint64_t adbg_sel:1;
-               uint64_t reserved_33_63:31;
-#endif
-       } s;
-       struct cvmx_sli_dbg_select_s cn61xx;
-       struct cvmx_sli_dbg_select_s cn63xx;
-       struct cvmx_sli_dbg_select_s cn63xxp1;
-       struct cvmx_sli_dbg_select_s cn66xx;
-       struct cvmx_sli_dbg_select_s cn68xx;
-       struct cvmx_sli_dbg_select_s cn68xxp1;
-       struct cvmx_sli_dbg_select_s cnf71xx;
-};
-
-union cvmx_sli_dmax_cnt {
-       uint64_t u64;
-       struct cvmx_sli_dmax_cnt_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t cnt:32;
-#else
-               uint64_t cnt:32;
-               uint64_t reserved_32_63:32;
-#endif
-       } s;
-       struct cvmx_sli_dmax_cnt_s cn61xx;
-       struct cvmx_sli_dmax_cnt_s cn63xx;
-       struct cvmx_sli_dmax_cnt_s cn63xxp1;
-       struct cvmx_sli_dmax_cnt_s cn66xx;
-       struct cvmx_sli_dmax_cnt_s cn68xx;
-       struct cvmx_sli_dmax_cnt_s cn68xxp1;
-       struct cvmx_sli_dmax_cnt_s cnf71xx;
-};
-
-union cvmx_sli_dmax_int_level {
-       uint64_t u64;
-       struct cvmx_sli_dmax_int_level_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t time:32;
-               uint64_t cnt:32;
-#else
-               uint64_t cnt:32;
-               uint64_t time:32;
-#endif
-       } s;
-       struct cvmx_sli_dmax_int_level_s cn61xx;
-       struct cvmx_sli_dmax_int_level_s cn63xx;
-       struct cvmx_sli_dmax_int_level_s cn63xxp1;
-       struct cvmx_sli_dmax_int_level_s cn66xx;
-       struct cvmx_sli_dmax_int_level_s cn68xx;
-       struct cvmx_sli_dmax_int_level_s cn68xxp1;
-       struct cvmx_sli_dmax_int_level_s cnf71xx;
-};
-
-union cvmx_sli_dmax_tim {
-       uint64_t u64;
-       struct cvmx_sli_dmax_tim_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t tim:32;
-#else
-               uint64_t tim:32;
-               uint64_t reserved_32_63:32;
-#endif
-       } s;
-       struct cvmx_sli_dmax_tim_s cn61xx;
-       struct cvmx_sli_dmax_tim_s cn63xx;
-       struct cvmx_sli_dmax_tim_s cn63xxp1;
-       struct cvmx_sli_dmax_tim_s cn66xx;
-       struct cvmx_sli_dmax_tim_s cn68xx;
-       struct cvmx_sli_dmax_tim_s cn68xxp1;
-       struct cvmx_sli_dmax_tim_s cnf71xx;
-};
-
-union cvmx_sli_int_enb_ciu {
-       uint64_t u64;
-       struct cvmx_sli_int_enb_ciu_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_62_63:2;
-               uint64_t pipe_err:1;
-               uint64_t ill_pad:1;
-               uint64_t sprt3_err:1;
-               uint64_t sprt2_err:1;
-               uint64_t sprt1_err:1;
-               uint64_t sprt0_err:1;
-               uint64_t pins_err:1;
-               uint64_t pop_err:1;
-               uint64_t pdi_err:1;
-               uint64_t pgl_err:1;
-               uint64_t pin_bp:1;
-               uint64_t pout_err:1;
-               uint64_t psldbof:1;
-               uint64_t pidbof:1;
-               uint64_t reserved_38_47:10;
-               uint64_t dtime:2;
-               uint64_t dcnt:2;
-               uint64_t dmafi:2;
-               uint64_t reserved_28_31:4;
-               uint64_t m3_un_wi:1;
-               uint64_t m3_un_b0:1;
-               uint64_t m3_up_wi:1;
-               uint64_t m3_up_b0:1;
-               uint64_t m2_un_wi:1;
-               uint64_t m2_un_b0:1;
-               uint64_t m2_up_wi:1;
-               uint64_t m2_up_b0:1;
-               uint64_t reserved_18_19:2;
-               uint64_t mio_int1:1;
-               uint64_t mio_int0:1;
-               uint64_t m1_un_wi:1;
-               uint64_t m1_un_b0:1;
-               uint64_t m1_up_wi:1;
-               uint64_t m1_up_b0:1;
-               uint64_t m0_un_wi:1;
-               uint64_t m0_un_b0:1;
-               uint64_t m0_up_wi:1;
-               uint64_t m0_up_b0:1;
-               uint64_t reserved_6_7:2;
-               uint64_t ptime:1;
-               uint64_t pcnt:1;
-               uint64_t iob2big:1;
-               uint64_t bar0_to:1;
-               uint64_t reserved_1_1:1;
-               uint64_t rml_to:1;
-#else
-               uint64_t rml_to:1;
-               uint64_t reserved_1_1:1;
-               uint64_t bar0_to:1;
-               uint64_t iob2big:1;
-               uint64_t pcnt:1;
-               uint64_t ptime:1;
-               uint64_t reserved_6_7:2;
-               uint64_t m0_up_b0:1;
-               uint64_t m0_up_wi:1;
-               uint64_t m0_un_b0:1;
-               uint64_t m0_un_wi:1;
-               uint64_t m1_up_b0:1;
-               uint64_t m1_up_wi:1;
-               uint64_t m1_un_b0:1;
-               uint64_t m1_un_wi:1;
-               uint64_t mio_int0:1;
-               uint64_t mio_int1:1;
-               uint64_t reserved_18_19:2;
-               uint64_t m2_up_b0:1;
-               uint64_t m2_up_wi:1;
-               uint64_t m2_un_b0:1;
-               uint64_t m2_un_wi:1;
-               uint64_t m3_up_b0:1;
-               uint64_t m3_up_wi:1;
-               uint64_t m3_un_b0:1;
-               uint64_t m3_un_wi:1;
-               uint64_t reserved_28_31:4;
-               uint64_t dmafi:2;
-               uint64_t dcnt:2;
-               uint64_t dtime:2;
-               uint64_t reserved_38_47:10;
-               uint64_t pidbof:1;
-               uint64_t psldbof:1;
-               uint64_t pout_err:1;
-               uint64_t pin_bp:1;
-               uint64_t pgl_err:1;
-               uint64_t pdi_err:1;
-               uint64_t pop_err:1;
-               uint64_t pins_err:1;
-               uint64_t sprt0_err:1;
-               uint64_t sprt1_err:1;
-               uint64_t sprt2_err:1;
-               uint64_t sprt3_err:1;
-               uint64_t ill_pad:1;
-               uint64_t pipe_err:1;
-               uint64_t reserved_62_63:2;
-#endif
-       } s;
-       struct cvmx_sli_int_enb_ciu_cn61xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_61_63:3;
-               uint64_t ill_pad:1;
-               uint64_t sprt3_err:1;
-               uint64_t sprt2_err:1;
-               uint64_t sprt1_err:1;
-               uint64_t sprt0_err:1;
-               uint64_t pins_err:1;
-               uint64_t pop_err:1;
-               uint64_t pdi_err:1;
-               uint64_t pgl_err:1;
-               uint64_t pin_bp:1;
-               uint64_t pout_err:1;
-               uint64_t psldbof:1;
-               uint64_t pidbof:1;
-               uint64_t reserved_38_47:10;
-               uint64_t dtime:2;
-               uint64_t dcnt:2;
-               uint64_t dmafi:2;
-               uint64_t reserved_28_31:4;
-               uint64_t m3_un_wi:1;
-               uint64_t m3_un_b0:1;
-               uint64_t m3_up_wi:1;
-               uint64_t m3_up_b0:1;
-               uint64_t m2_un_wi:1;
-               uint64_t m2_un_b0:1;
-               uint64_t m2_up_wi:1;
-               uint64_t m2_up_b0:1;
-               uint64_t reserved_18_19:2;
-               uint64_t mio_int1:1;
-               uint64_t mio_int0:1;
-               uint64_t m1_un_wi:1;
-               uint64_t m1_un_b0:1;
-               uint64_t m1_up_wi:1;
-               uint64_t m1_up_b0:1;
-               uint64_t m0_un_wi:1;
-               uint64_t m0_un_b0:1;
-               uint64_t m0_up_wi:1;
-               uint64_t m0_up_b0:1;
-               uint64_t reserved_6_7:2;
-               uint64_t ptime:1;
-               uint64_t pcnt:1;
-               uint64_t iob2big:1;
-               uint64_t bar0_to:1;
-               uint64_t reserved_1_1:1;
-               uint64_t rml_to:1;
-#else
-               uint64_t rml_to:1;
-               uint64_t reserved_1_1:1;
-               uint64_t bar0_to:1;
-               uint64_t iob2big:1;
-               uint64_t pcnt:1;
-               uint64_t ptime:1;
-               uint64_t reserved_6_7:2;
-               uint64_t m0_up_b0:1;
-               uint64_t m0_up_wi:1;
-               uint64_t m0_un_b0:1;
-               uint64_t m0_un_wi:1;
-               uint64_t m1_up_b0:1;
-               uint64_t m1_up_wi:1;
-               uint64_t m1_un_b0:1;
-               uint64_t m1_un_wi:1;
-               uint64_t mio_int0:1;
-               uint64_t mio_int1:1;
-               uint64_t reserved_18_19:2;
-               uint64_t m2_up_b0:1;
-               uint64_t m2_up_wi:1;
-               uint64_t m2_un_b0:1;
-               uint64_t m2_un_wi:1;
-               uint64_t m3_up_b0:1;
-               uint64_t m3_up_wi:1;
-               uint64_t m3_un_b0:1;
-               uint64_t m3_un_wi:1;
-               uint64_t reserved_28_31:4;
-               uint64_t dmafi:2;
-               uint64_t dcnt:2;
-               uint64_t dtime:2;
-               uint64_t reserved_38_47:10;
-               uint64_t pidbof:1;
-               uint64_t psldbof:1;
-               uint64_t pout_err:1;
-               uint64_t pin_bp:1;
-               uint64_t pgl_err:1;
-               uint64_t pdi_err:1;
-               uint64_t pop_err:1;
-               uint64_t pins_err:1;
-               uint64_t sprt0_err:1;
-               uint64_t sprt1_err:1;
-               uint64_t sprt2_err:1;
-               uint64_t sprt3_err:1;
-               uint64_t ill_pad:1;
-               uint64_t reserved_61_63:3;
-#endif
-       } cn61xx;
-       struct cvmx_sli_int_enb_ciu_cn63xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_61_63:3;
-               uint64_t ill_pad:1;
-               uint64_t reserved_58_59:2;
-               uint64_t sprt1_err:1;
-               uint64_t sprt0_err:1;
-               uint64_t pins_err:1;
-               uint64_t pop_err:1;
-               uint64_t pdi_err:1;
-               uint64_t pgl_err:1;
-               uint64_t pin_bp:1;
-               uint64_t pout_err:1;
-               uint64_t psldbof:1;
-               uint64_t pidbof:1;
-               uint64_t reserved_38_47:10;
-               uint64_t dtime:2;
-               uint64_t dcnt:2;
-               uint64_t dmafi:2;
-               uint64_t reserved_18_31:14;
-               uint64_t mio_int1:1;
-               uint64_t mio_int0:1;
-               uint64_t m1_un_wi:1;
-               uint64_t m1_un_b0:1;
-               uint64_t m1_up_wi:1;
-               uint64_t m1_up_b0:1;
-               uint64_t m0_un_wi:1;
-               uint64_t m0_un_b0:1;
-               uint64_t m0_up_wi:1;
-               uint64_t m0_up_b0:1;
-               uint64_t reserved_6_7:2;
-               uint64_t ptime:1;
-               uint64_t pcnt:1;
-               uint64_t iob2big:1;
-               uint64_t bar0_to:1;
-               uint64_t reserved_1_1:1;
-               uint64_t rml_to:1;
-#else
-               uint64_t rml_to:1;
-               uint64_t reserved_1_1:1;
-               uint64_t bar0_to:1;
-               uint64_t iob2big:1;
-               uint64_t pcnt:1;
-               uint64_t ptime:1;
-               uint64_t reserved_6_7:2;
-               uint64_t m0_up_b0:1;
-               uint64_t m0_up_wi:1;
-               uint64_t m0_un_b0:1;
-               uint64_t m0_un_wi:1;
-               uint64_t m1_up_b0:1;
-               uint64_t m1_up_wi:1;
-               uint64_t m1_un_b0:1;
-               uint64_t m1_un_wi:1;
-               uint64_t mio_int0:1;
-               uint64_t mio_int1:1;
-               uint64_t reserved_18_31:14;
-               uint64_t dmafi:2;
-               uint64_t dcnt:2;
-               uint64_t dtime:2;
-               uint64_t reserved_38_47:10;
-               uint64_t pidbof:1;
-               uint64_t psldbof:1;
-               uint64_t pout_err:1;
-               uint64_t pin_bp:1;
-               uint64_t pgl_err:1;
-               uint64_t pdi_err:1;
-               uint64_t pop_err:1;
-               uint64_t pins_err:1;
-               uint64_t sprt0_err:1;
-               uint64_t sprt1_err:1;
-               uint64_t reserved_58_59:2;
-               uint64_t ill_pad:1;
-               uint64_t reserved_61_63:3;
-#endif
-       } cn63xx;
-       struct cvmx_sli_int_enb_ciu_cn63xx cn63xxp1;
-       struct cvmx_sli_int_enb_ciu_cn61xx cn66xx;
-       struct cvmx_sli_int_enb_ciu_cn68xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_62_63:2;
-               uint64_t pipe_err:1;
-               uint64_t ill_pad:1;
-               uint64_t reserved_58_59:2;
-               uint64_t sprt1_err:1;
-               uint64_t sprt0_err:1;
-               uint64_t pins_err:1;
-               uint64_t pop_err:1;
-               uint64_t pdi_err:1;
-               uint64_t pgl_err:1;
-               uint64_t reserved_51_51:1;
-               uint64_t pout_err:1;
-               uint64_t psldbof:1;
-               uint64_t pidbof:1;
-               uint64_t reserved_38_47:10;
-               uint64_t dtime:2;
-               uint64_t dcnt:2;
-               uint64_t dmafi:2;
-               uint64_t reserved_18_31:14;
-               uint64_t mio_int1:1;
-               uint64_t mio_int0:1;
-               uint64_t m1_un_wi:1;
-               uint64_t m1_un_b0:1;
-               uint64_t m1_up_wi:1;
-               uint64_t m1_up_b0:1;
-               uint64_t m0_un_wi:1;
-               uint64_t m0_un_b0:1;
-               uint64_t m0_up_wi:1;
-               uint64_t m0_up_b0:1;
-               uint64_t reserved_6_7:2;
-               uint64_t ptime:1;
-               uint64_t pcnt:1;
-               uint64_t iob2big:1;
-               uint64_t bar0_to:1;
-               uint64_t reserved_1_1:1;
-               uint64_t rml_to:1;
-#else
-               uint64_t rml_to:1;
-               uint64_t reserved_1_1:1;
-               uint64_t bar0_to:1;
-               uint64_t iob2big:1;
-               uint64_t pcnt:1;
-               uint64_t ptime:1;
-               uint64_t reserved_6_7:2;
-               uint64_t m0_up_b0:1;
-               uint64_t m0_up_wi:1;
-               uint64_t m0_un_b0:1;
-               uint64_t m0_un_wi:1;
-               uint64_t m1_up_b0:1;
-               uint64_t m1_up_wi:1;
-               uint64_t m1_un_b0:1;
-               uint64_t m1_un_wi:1;
-               uint64_t mio_int0:1;
-               uint64_t mio_int1:1;
-               uint64_t reserved_18_31:14;
-               uint64_t dmafi:2;
-               uint64_t dcnt:2;
-               uint64_t dtime:2;
-               uint64_t reserved_38_47:10;
-               uint64_t pidbof:1;
-               uint64_t psldbof:1;
-               uint64_t pout_err:1;
-               uint64_t reserved_51_51:1;
-               uint64_t pgl_err:1;
-               uint64_t pdi_err:1;
-               uint64_t pop_err:1;
-               uint64_t pins_err:1;
-               uint64_t sprt0_err:1;
-               uint64_t sprt1_err:1;
-               uint64_t reserved_58_59:2;
-               uint64_t ill_pad:1;
-               uint64_t pipe_err:1;
-               uint64_t reserved_62_63:2;
-#endif
-       } cn68xx;
-       struct cvmx_sli_int_enb_ciu_cn68xx cn68xxp1;
-       struct cvmx_sli_int_enb_ciu_cn61xx cnf71xx;
-};
-
-union cvmx_sli_int_enb_portx {
-       uint64_t u64;
-       struct cvmx_sli_int_enb_portx_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_62_63:2;
-               uint64_t pipe_err:1;
-               uint64_t ill_pad:1;
-               uint64_t sprt3_err:1;
-               uint64_t sprt2_err:1;
-               uint64_t sprt1_err:1;
-               uint64_t sprt0_err:1;
-               uint64_t pins_err:1;
-               uint64_t pop_err:1;
-               uint64_t pdi_err:1;
-               uint64_t pgl_err:1;
-               uint64_t pin_bp:1;
-               uint64_t pout_err:1;
-               uint64_t psldbof:1;
-               uint64_t pidbof:1;
-               uint64_t reserved_38_47:10;
-               uint64_t dtime:2;
-               uint64_t dcnt:2;
-               uint64_t dmafi:2;
-               uint64_t reserved_28_31:4;
-               uint64_t m3_un_wi:1;
-               uint64_t m3_un_b0:1;
-               uint64_t m3_up_wi:1;
-               uint64_t m3_up_b0:1;
-               uint64_t m2_un_wi:1;
-               uint64_t m2_un_b0:1;
-               uint64_t m2_up_wi:1;
-               uint64_t m2_up_b0:1;
-               uint64_t mac1_int:1;
-               uint64_t mac0_int:1;
-               uint64_t mio_int1:1;
-               uint64_t mio_int0:1;
-               uint64_t m1_un_wi:1;
-               uint64_t m1_un_b0:1;
-               uint64_t m1_up_wi:1;
-               uint64_t m1_up_b0:1;
-               uint64_t m0_un_wi:1;
-               uint64_t m0_un_b0:1;
-               uint64_t m0_up_wi:1;
-               uint64_t m0_up_b0:1;
-               uint64_t reserved_6_7:2;
-               uint64_t ptime:1;
-               uint64_t pcnt:1;
-               uint64_t iob2big:1;
-               uint64_t bar0_to:1;
-               uint64_t reserved_1_1:1;
-               uint64_t rml_to:1;
-#else
-               uint64_t rml_to:1;
-               uint64_t reserved_1_1:1;
-               uint64_t bar0_to:1;
-               uint64_t iob2big:1;
-               uint64_t pcnt:1;
-               uint64_t ptime:1;
-               uint64_t reserved_6_7:2;
-               uint64_t m0_up_b0:1;
-               uint64_t m0_up_wi:1;
-               uint64_t m0_un_b0:1;
-               uint64_t m0_un_wi:1;
-               uint64_t m1_up_b0:1;
-               uint64_t m1_up_wi:1;
-               uint64_t m1_un_b0:1;
-               uint64_t m1_un_wi:1;
-               uint64_t mio_int0:1;
-               uint64_t mio_int1:1;
-               uint64_t mac0_int:1;
-               uint64_t mac1_int:1;
-               uint64_t m2_up_b0:1;
-               uint64_t m2_up_wi:1;
-               uint64_t m2_un_b0:1;
-               uint64_t m2_un_wi:1;
-               uint64_t m3_up_b0:1;
-               uint64_t m3_up_wi:1;
-               uint64_t m3_un_b0:1;
-               uint64_t m3_un_wi:1;
-               uint64_t reserved_28_31:4;
-               uint64_t dmafi:2;
-               uint64_t dcnt:2;
-               uint64_t dtime:2;
-               uint64_t reserved_38_47:10;
-               uint64_t pidbof:1;
-               uint64_t psldbof:1;
-               uint64_t pout_err:1;
-               uint64_t pin_bp:1;
-               uint64_t pgl_err:1;
-               uint64_t pdi_err:1;
-               uint64_t pop_err:1;
-               uint64_t pins_err:1;
-               uint64_t sprt0_err:1;
-               uint64_t sprt1_err:1;
-               uint64_t sprt2_err:1;
-               uint64_t sprt3_err:1;
-               uint64_t ill_pad:1;
-               uint64_t pipe_err:1;
-               uint64_t reserved_62_63:2;
-#endif
-       } s;
-       struct cvmx_sli_int_enb_portx_cn61xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_61_63:3;
-               uint64_t ill_pad:1;
-               uint64_t sprt3_err:1;
-               uint64_t sprt2_err:1;
-               uint64_t sprt1_err:1;
-               uint64_t sprt0_err:1;
-               uint64_t pins_err:1;
-               uint64_t pop_err:1;
-               uint64_t pdi_err:1;
-               uint64_t pgl_err:1;
-               uint64_t pin_bp:1;
-               uint64_t pout_err:1;
-               uint64_t psldbof:1;
-               uint64_t pidbof:1;
-               uint64_t reserved_38_47:10;
-               uint64_t dtime:2;
-               uint64_t dcnt:2;
-               uint64_t dmafi:2;
-               uint64_t reserved_28_31:4;
-               uint64_t m3_un_wi:1;
-               uint64_t m3_un_b0:1;
-               uint64_t m3_up_wi:1;
-               uint64_t m3_up_b0:1;
-               uint64_t m2_un_wi:1;
-               uint64_t m2_un_b0:1;
-               uint64_t m2_up_wi:1;
-               uint64_t m2_up_b0:1;
-               uint64_t mac1_int:1;
-               uint64_t mac0_int:1;
-               uint64_t mio_int1:1;
-               uint64_t mio_int0:1;
-               uint64_t m1_un_wi:1;
-               uint64_t m1_un_b0:1;
-               uint64_t m1_up_wi:1;
-               uint64_t m1_up_b0:1;
-               uint64_t m0_un_wi:1;
-               uint64_t m0_un_b0:1;
-               uint64_t m0_up_wi:1;
-               uint64_t m0_up_b0:1;
-               uint64_t reserved_6_7:2;
-               uint64_t ptime:1;
-               uint64_t pcnt:1;
-               uint64_t iob2big:1;
-               uint64_t bar0_to:1;
-               uint64_t reserved_1_1:1;
-               uint64_t rml_to:1;
-#else
-               uint64_t rml_to:1;
-               uint64_t reserved_1_1:1;
-               uint64_t bar0_to:1;
-               uint64_t iob2big:1;
-               uint64_t pcnt:1;
-               uint64_t ptime:1;
-               uint64_t reserved_6_7:2;
-               uint64_t m0_up_b0:1;
-               uint64_t m0_up_wi:1;
-               uint64_t m0_un_b0:1;
-               uint64_t m0_un_wi:1;
-               uint64_t m1_up_b0:1;
-               uint64_t m1_up_wi:1;
-               uint64_t m1_un_b0:1;
-               uint64_t m1_un_wi:1;
-               uint64_t mio_int0:1;
-               uint64_t mio_int1:1;
-               uint64_t mac0_int:1;
-               uint64_t mac1_int:1;
-               uint64_t m2_up_b0:1;
-               uint64_t m2_up_wi:1;
-               uint64_t m2_un_b0:1;
-               uint64_t m2_un_wi:1;
-               uint64_t m3_up_b0:1;
-               uint64_t m3_up_wi:1;
-               uint64_t m3_un_b0:1;
-               uint64_t m3_un_wi:1;
-               uint64_t reserved_28_31:4;
-               uint64_t dmafi:2;
-               uint64_t dcnt:2;
-               uint64_t dtime:2;
-               uint64_t reserved_38_47:10;
-               uint64_t pidbof:1;
-               uint64_t psldbof:1;
-               uint64_t pout_err:1;
-               uint64_t pin_bp:1;
-               uint64_t pgl_err:1;
-               uint64_t pdi_err:1;
-               uint64_t pop_err:1;
-               uint64_t pins_err:1;
-               uint64_t sprt0_err:1;
-               uint64_t sprt1_err:1;
-               uint64_t sprt2_err:1;
-               uint64_t sprt3_err:1;
-               uint64_t ill_pad:1;
-               uint64_t reserved_61_63:3;
-#endif
-       } cn61xx;
-       struct cvmx_sli_int_enb_portx_cn63xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_61_63:3;
-               uint64_t ill_pad:1;
-               uint64_t reserved_58_59:2;
-               uint64_t sprt1_err:1;
-               uint64_t sprt0_err:1;
-               uint64_t pins_err:1;
-               uint64_t pop_err:1;
-               uint64_t pdi_err:1;
-               uint64_t pgl_err:1;
-               uint64_t pin_bp:1;
-               uint64_t pout_err:1;
-               uint64_t psldbof:1;
-               uint64_t pidbof:1;
-               uint64_t reserved_38_47:10;
-               uint64_t dtime:2;
-               uint64_t dcnt:2;
-               uint64_t dmafi:2;
-               uint64_t reserved_20_31:12;
-               uint64_t mac1_int:1;
-               uint64_t mac0_int:1;
-               uint64_t mio_int1:1;
-               uint64_t mio_int0:1;
-               uint64_t m1_un_wi:1;
-               uint64_t m1_un_b0:1;
-               uint64_t m1_up_wi:1;
-               uint64_t m1_up_b0:1;
-               uint64_t m0_un_wi:1;
-               uint64_t m0_un_b0:1;
-               uint64_t m0_up_wi:1;
-               uint64_t m0_up_b0:1;
-               uint64_t reserved_6_7:2;
-               uint64_t ptime:1;
-               uint64_t pcnt:1;
-               uint64_t iob2big:1;
-               uint64_t bar0_to:1;
-               uint64_t reserved_1_1:1;
-               uint64_t rml_to:1;
-#else
-               uint64_t rml_to:1;
-               uint64_t reserved_1_1:1;
-               uint64_t bar0_to:1;
-               uint64_t iob2big:1;
-               uint64_t pcnt:1;
-               uint64_t ptime:1;
-               uint64_t reserved_6_7:2;
-               uint64_t m0_up_b0:1;
-               uint64_t m0_up_wi:1;
-               uint64_t m0_un_b0:1;
-               uint64_t m0_un_wi:1;
-               uint64_t m1_up_b0:1;
-               uint64_t m1_up_wi:1;
-               uint64_t m1_un_b0:1;
-               uint64_t m1_un_wi:1;
-               uint64_t mio_int0:1;
-               uint64_t mio_int1:1;
-               uint64_t mac0_int:1;
-               uint64_t mac1_int:1;
-               uint64_t reserved_20_31:12;
-               uint64_t dmafi:2;
-               uint64_t dcnt:2;
-               uint64_t dtime:2;
-               uint64_t reserved_38_47:10;
-               uint64_t pidbof:1;
-               uint64_t psldbof:1;
-               uint64_t pout_err:1;
-               uint64_t pin_bp:1;
-               uint64_t pgl_err:1;
-               uint64_t pdi_err:1;
-               uint64_t pop_err:1;
-               uint64_t pins_err:1;
-               uint64_t sprt0_err:1;
-               uint64_t sprt1_err:1;
-               uint64_t reserved_58_59:2;
-               uint64_t ill_pad:1;
-               uint64_t reserved_61_63:3;
-#endif
-       } cn63xx;
-       struct cvmx_sli_int_enb_portx_cn63xx cn63xxp1;
-       struct cvmx_sli_int_enb_portx_cn61xx cn66xx;
-       struct cvmx_sli_int_enb_portx_cn68xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_62_63:2;
-               uint64_t pipe_err:1;
-               uint64_t ill_pad:1;
-               uint64_t reserved_58_59:2;
-               uint64_t sprt1_err:1;
-               uint64_t sprt0_err:1;
-               uint64_t pins_err:1;
-               uint64_t pop_err:1;
-               uint64_t pdi_err:1;
-               uint64_t pgl_err:1;
-               uint64_t reserved_51_51:1;
-               uint64_t pout_err:1;
-               uint64_t psldbof:1;
-               uint64_t pidbof:1;
-               uint64_t reserved_38_47:10;
-               uint64_t dtime:2;
-               uint64_t dcnt:2;
-               uint64_t dmafi:2;
-               uint64_t reserved_20_31:12;
-               uint64_t mac1_int:1;
-               uint64_t mac0_int:1;
-               uint64_t mio_int1:1;
-               uint64_t mio_int0:1;
-               uint64_t m1_un_wi:1;
-               uint64_t m1_un_b0:1;
-               uint64_t m1_up_wi:1;
-               uint64_t m1_up_b0:1;
-               uint64_t m0_un_wi:1;
-               uint64_t m0_un_b0:1;
-               uint64_t m0_up_wi:1;
-               uint64_t m0_up_b0:1;
-               uint64_t reserved_6_7:2;
-               uint64_t ptime:1;
-               uint64_t pcnt:1;
-               uint64_t iob2big:1;
-               uint64_t bar0_to:1;
-               uint64_t reserved_1_1:1;
-               uint64_t rml_to:1;
-#else
-               uint64_t rml_to:1;
-               uint64_t reserved_1_1:1;
-               uint64_t bar0_to:1;
-               uint64_t iob2big:1;
-               uint64_t pcnt:1;
-               uint64_t ptime:1;
-               uint64_t reserved_6_7:2;
-               uint64_t m0_up_b0:1;
-               uint64_t m0_up_wi:1;
-               uint64_t m0_un_b0:1;
-               uint64_t m0_un_wi:1;
-               uint64_t m1_up_b0:1;
-               uint64_t m1_up_wi:1;
-               uint64_t m1_un_b0:1;
-               uint64_t m1_un_wi:1;
-               uint64_t mio_int0:1;
-               uint64_t mio_int1:1;
-               uint64_t mac0_int:1;
-               uint64_t mac1_int:1;
-               uint64_t reserved_20_31:12;
-               uint64_t dmafi:2;
-               uint64_t dcnt:2;
-               uint64_t dtime:2;
-               uint64_t reserved_38_47:10;
-               uint64_t pidbof:1;
-               uint64_t psldbof:1;
-               uint64_t pout_err:1;
-               uint64_t reserved_51_51:1;
-               uint64_t pgl_err:1;
-               uint64_t pdi_err:1;
-               uint64_t pop_err:1;
-               uint64_t pins_err:1;
-               uint64_t sprt0_err:1;
-               uint64_t sprt1_err:1;
-               uint64_t reserved_58_59:2;
-               uint64_t ill_pad:1;
-               uint64_t pipe_err:1;
-               uint64_t reserved_62_63:2;
-#endif
-       } cn68xx;
-       struct cvmx_sli_int_enb_portx_cn68xx cn68xxp1;
-       struct cvmx_sli_int_enb_portx_cn61xx cnf71xx;
-};
-
-union cvmx_sli_int_sum {
-       uint64_t u64;
-       struct cvmx_sli_int_sum_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_62_63:2;
-               uint64_t pipe_err:1;
-               uint64_t ill_pad:1;
-               uint64_t sprt3_err:1;
-               uint64_t sprt2_err:1;
-               uint64_t sprt1_err:1;
-               uint64_t sprt0_err:1;
-               uint64_t pins_err:1;
-               uint64_t pop_err:1;
-               uint64_t pdi_err:1;
-               uint64_t pgl_err:1;
-               uint64_t pin_bp:1;
-               uint64_t pout_err:1;
-               uint64_t psldbof:1;
-               uint64_t pidbof:1;
-               uint64_t reserved_38_47:10;
-               uint64_t dtime:2;
-               uint64_t dcnt:2;
-               uint64_t dmafi:2;
-               uint64_t reserved_28_31:4;
-               uint64_t m3_un_wi:1;
-               uint64_t m3_un_b0:1;
-               uint64_t m3_up_wi:1;
-               uint64_t m3_up_b0:1;
-               uint64_t m2_un_wi:1;
-               uint64_t m2_un_b0:1;
-               uint64_t m2_up_wi:1;
-               uint64_t m2_up_b0:1;
-               uint64_t mac1_int:1;
-               uint64_t mac0_int:1;
-               uint64_t mio_int1:1;
-               uint64_t mio_int0:1;
-               uint64_t m1_un_wi:1;
-               uint64_t m1_un_b0:1;
-               uint64_t m1_up_wi:1;
-               uint64_t m1_up_b0:1;
-               uint64_t m0_un_wi:1;
-               uint64_t m0_un_b0:1;
-               uint64_t m0_up_wi:1;
-               uint64_t m0_up_b0:1;
-               uint64_t reserved_6_7:2;
-               uint64_t ptime:1;
-               uint64_t pcnt:1;
-               uint64_t iob2big:1;
-               uint64_t bar0_to:1;
-               uint64_t reserved_1_1:1;
-               uint64_t rml_to:1;
-#else
-               uint64_t rml_to:1;
-               uint64_t reserved_1_1:1;
-               uint64_t bar0_to:1;
-               uint64_t iob2big:1;
-               uint64_t pcnt:1;
-               uint64_t ptime:1;
-               uint64_t reserved_6_7:2;
-               uint64_t m0_up_b0:1;
-               uint64_t m0_up_wi:1;
-               uint64_t m0_un_b0:1;
-               uint64_t m0_un_wi:1;
-               uint64_t m1_up_b0:1;
-               uint64_t m1_up_wi:1;
-               uint64_t m1_un_b0:1;
-               uint64_t m1_un_wi:1;
-               uint64_t mio_int0:1;
-               uint64_t mio_int1:1;
-               uint64_t mac0_int:1;
-               uint64_t mac1_int:1;
-               uint64_t m2_up_b0:1;
-               uint64_t m2_up_wi:1;
-               uint64_t m2_un_b0:1;
-               uint64_t m2_un_wi:1;
-               uint64_t m3_up_b0:1;
-               uint64_t m3_up_wi:1;
-               uint64_t m3_un_b0:1;
-               uint64_t m3_un_wi:1;
-               uint64_t reserved_28_31:4;
-               uint64_t dmafi:2;
-               uint64_t dcnt:2;
-               uint64_t dtime:2;
-               uint64_t reserved_38_47:10;
-               uint64_t pidbof:1;
-               uint64_t psldbof:1;
-               uint64_t pout_err:1;
-               uint64_t pin_bp:1;
-               uint64_t pgl_err:1;
-               uint64_t pdi_err:1;
-               uint64_t pop_err:1;
-               uint64_t pins_err:1;
-               uint64_t sprt0_err:1;
-               uint64_t sprt1_err:1;
-               uint64_t sprt2_err:1;
-               uint64_t sprt3_err:1;
-               uint64_t ill_pad:1;
-               uint64_t pipe_err:1;
-               uint64_t reserved_62_63:2;
-#endif
-       } s;
-       struct cvmx_sli_int_sum_cn61xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_61_63:3;
-               uint64_t ill_pad:1;
-               uint64_t sprt3_err:1;
-               uint64_t sprt2_err:1;
-               uint64_t sprt1_err:1;
-               uint64_t sprt0_err:1;
-               uint64_t pins_err:1;
-               uint64_t pop_err:1;
-               uint64_t pdi_err:1;
-               uint64_t pgl_err:1;
-               uint64_t pin_bp:1;
-               uint64_t pout_err:1;
-               uint64_t psldbof:1;
-               uint64_t pidbof:1;
-               uint64_t reserved_38_47:10;
-               uint64_t dtime:2;
-               uint64_t dcnt:2;
-               uint64_t dmafi:2;
-               uint64_t reserved_28_31:4;
-               uint64_t m3_un_wi:1;
-               uint64_t m3_un_b0:1;
-               uint64_t m3_up_wi:1;
-               uint64_t m3_up_b0:1;
-               uint64_t m2_un_wi:1;
-               uint64_t m2_un_b0:1;
-               uint64_t m2_up_wi:1;
-               uint64_t m2_up_b0:1;
-               uint64_t mac1_int:1;
-               uint64_t mac0_int:1;
-               uint64_t mio_int1:1;
-               uint64_t mio_int0:1;
-               uint64_t m1_un_wi:1;
-               uint64_t m1_un_b0:1;
-               uint64_t m1_up_wi:1;
-               uint64_t m1_up_b0:1;
-               uint64_t m0_un_wi:1;
-               uint64_t m0_un_b0:1;
-               uint64_t m0_up_wi:1;
-               uint64_t m0_up_b0:1;
-               uint64_t reserved_6_7:2;
-               uint64_t ptime:1;
-               uint64_t pcnt:1;
-               uint64_t iob2big:1;
-               uint64_t bar0_to:1;
-               uint64_t reserved_1_1:1;
-               uint64_t rml_to:1;
-#else
-               uint64_t rml_to:1;
-               uint64_t reserved_1_1:1;
-               uint64_t bar0_to:1;
-               uint64_t iob2big:1;
-               uint64_t pcnt:1;
-               uint64_t ptime:1;
-               uint64_t reserved_6_7:2;
-               uint64_t m0_up_b0:1;
-               uint64_t m0_up_wi:1;
-               uint64_t m0_un_b0:1;
-               uint64_t m0_un_wi:1;
-               uint64_t m1_up_b0:1;
-               uint64_t m1_up_wi:1;
-               uint64_t m1_un_b0:1;
-               uint64_t m1_un_wi:1;
-               uint64_t mio_int0:1;
-               uint64_t mio_int1:1;
-               uint64_t mac0_int:1;
-               uint64_t mac1_int:1;
-               uint64_t m2_up_b0:1;
-               uint64_t m2_up_wi:1;
-               uint64_t m2_un_b0:1;
-               uint64_t m2_un_wi:1;
-               uint64_t m3_up_b0:1;
-               uint64_t m3_up_wi:1;
-               uint64_t m3_un_b0:1;
-               uint64_t m3_un_wi:1;
-               uint64_t reserved_28_31:4;
-               uint64_t dmafi:2;
-               uint64_t dcnt:2;
-               uint64_t dtime:2;
-               uint64_t reserved_38_47:10;
-               uint64_t pidbof:1;
-               uint64_t psldbof:1;
-               uint64_t pout_err:1;
-               uint64_t pin_bp:1;
-               uint64_t pgl_err:1;
-               uint64_t pdi_err:1;
-               uint64_t pop_err:1;
-               uint64_t pins_err:1;
-               uint64_t sprt0_err:1;
-               uint64_t sprt1_err:1;
-               uint64_t sprt2_err:1;
-               uint64_t sprt3_err:1;
-               uint64_t ill_pad:1;
-               uint64_t reserved_61_63:3;
-#endif
-       } cn61xx;
-       struct cvmx_sli_int_sum_cn63xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_61_63:3;
-               uint64_t ill_pad:1;
-               uint64_t reserved_58_59:2;
-               uint64_t sprt1_err:1;
-               uint64_t sprt0_err:1;
-               uint64_t pins_err:1;
-               uint64_t pop_err:1;
-               uint64_t pdi_err:1;
-               uint64_t pgl_err:1;
-               uint64_t pin_bp:1;
-               uint64_t pout_err:1;
-               uint64_t psldbof:1;
-               uint64_t pidbof:1;
-               uint64_t reserved_38_47:10;
-               uint64_t dtime:2;
-               uint64_t dcnt:2;
-               uint64_t dmafi:2;
-               uint64_t reserved_20_31:12;
-               uint64_t mac1_int:1;
-               uint64_t mac0_int:1;
-               uint64_t mio_int1:1;
-               uint64_t mio_int0:1;
-               uint64_t m1_un_wi:1;
-               uint64_t m1_un_b0:1;
-               uint64_t m1_up_wi:1;
-               uint64_t m1_up_b0:1;
-               uint64_t m0_un_wi:1;
-               uint64_t m0_un_b0:1;
-               uint64_t m0_up_wi:1;
-               uint64_t m0_up_b0:1;
-               uint64_t reserved_6_7:2;
-               uint64_t ptime:1;
-               uint64_t pcnt:1;
-               uint64_t iob2big:1;
-               uint64_t bar0_to:1;
-               uint64_t reserved_1_1:1;
-               uint64_t rml_to:1;
-#else
-               uint64_t rml_to:1;
-               uint64_t reserved_1_1:1;
-               uint64_t bar0_to:1;
-               uint64_t iob2big:1;
-               uint64_t pcnt:1;
-               uint64_t ptime:1;
-               uint64_t reserved_6_7:2;
-               uint64_t m0_up_b0:1;
-               uint64_t m0_up_wi:1;
-               uint64_t m0_un_b0:1;
-               uint64_t m0_un_wi:1;
-               uint64_t m1_up_b0:1;
-               uint64_t m1_up_wi:1;
-               uint64_t m1_un_b0:1;
-               uint64_t m1_un_wi:1;
-               uint64_t mio_int0:1;
-               uint64_t mio_int1:1;
-               uint64_t mac0_int:1;
-               uint64_t mac1_int:1;
-               uint64_t reserved_20_31:12;
-               uint64_t dmafi:2;
-               uint64_t dcnt:2;
-               uint64_t dtime:2;
-               uint64_t reserved_38_47:10;
-               uint64_t pidbof:1;
-               uint64_t psldbof:1;
-               uint64_t pout_err:1;
-               uint64_t pin_bp:1;
-               uint64_t pgl_err:1;
-               uint64_t pdi_err:1;
-               uint64_t pop_err:1;
-               uint64_t pins_err:1;
-               uint64_t sprt0_err:1;
-               uint64_t sprt1_err:1;
-               uint64_t reserved_58_59:2;
-               uint64_t ill_pad:1;
-               uint64_t reserved_61_63:3;
-#endif
-       } cn63xx;
-       struct cvmx_sli_int_sum_cn63xx cn63xxp1;
-       struct cvmx_sli_int_sum_cn61xx cn66xx;
-       struct cvmx_sli_int_sum_cn68xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_62_63:2;
-               uint64_t pipe_err:1;
-               uint64_t ill_pad:1;
-               uint64_t reserved_58_59:2;
-               uint64_t sprt1_err:1;
-               uint64_t sprt0_err:1;
-               uint64_t pins_err:1;
-               uint64_t pop_err:1;
-               uint64_t pdi_err:1;
-               uint64_t pgl_err:1;
-               uint64_t reserved_51_51:1;
-               uint64_t pout_err:1;
-               uint64_t psldbof:1;
-               uint64_t pidbof:1;
-               uint64_t reserved_38_47:10;
-               uint64_t dtime:2;
-               uint64_t dcnt:2;
-               uint64_t dmafi:2;
-               uint64_t reserved_20_31:12;
-               uint64_t mac1_int:1;
-               uint64_t mac0_int:1;
-               uint64_t mio_int1:1;
-               uint64_t mio_int0:1;
-               uint64_t m1_un_wi:1;
-               uint64_t m1_un_b0:1;
-               uint64_t m1_up_wi:1;
-               uint64_t m1_up_b0:1;
-               uint64_t m0_un_wi:1;
-               uint64_t m0_un_b0:1;
-               uint64_t m0_up_wi:1;
-               uint64_t m0_up_b0:1;
-               uint64_t reserved_6_7:2;
-               uint64_t ptime:1;
-               uint64_t pcnt:1;
-               uint64_t iob2big:1;
-               uint64_t bar0_to:1;
-               uint64_t reserved_1_1:1;
-               uint64_t rml_to:1;
-#else
-               uint64_t rml_to:1;
-               uint64_t reserved_1_1:1;
-               uint64_t bar0_to:1;
-               uint64_t iob2big:1;
-               uint64_t pcnt:1;
-               uint64_t ptime:1;
-               uint64_t reserved_6_7:2;
-               uint64_t m0_up_b0:1;
-               uint64_t m0_up_wi:1;
-               uint64_t m0_un_b0:1;
-               uint64_t m0_un_wi:1;
-               uint64_t m1_up_b0:1;
-               uint64_t m1_up_wi:1;
-               uint64_t m1_un_b0:1;
-               uint64_t m1_un_wi:1;
-               uint64_t mio_int0:1;
-               uint64_t mio_int1:1;
-               uint64_t mac0_int:1;
-               uint64_t mac1_int:1;
-               uint64_t reserved_20_31:12;
-               uint64_t dmafi:2;
-               uint64_t dcnt:2;
-               uint64_t dtime:2;
-               uint64_t reserved_38_47:10;
-               uint64_t pidbof:1;
-               uint64_t psldbof:1;
-               uint64_t pout_err:1;
-               uint64_t reserved_51_51:1;
-               uint64_t pgl_err:1;
-               uint64_t pdi_err:1;
-               uint64_t pop_err:1;
-               uint64_t pins_err:1;
-               uint64_t sprt0_err:1;
-               uint64_t sprt1_err:1;
-               uint64_t reserved_58_59:2;
-               uint64_t ill_pad:1;
-               uint64_t pipe_err:1;
-               uint64_t reserved_62_63:2;
-#endif
-       } cn68xx;
-       struct cvmx_sli_int_sum_cn68xx cn68xxp1;
-       struct cvmx_sli_int_sum_cn61xx cnf71xx;
-};
-
-union cvmx_sli_last_win_rdata0 {
-       uint64_t u64;
-       struct cvmx_sli_last_win_rdata0_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t data:64;
-#else
-               uint64_t data:64;
-#endif
+               __BITFIELD_FIELD(uint64_t reserved_22_63:42,
+               __BITFIELD_FIELD(uint64_t intd:1,
+               __BITFIELD_FIELD(uint64_t intc:1,
+               __BITFIELD_FIELD(uint64_t intb:1,
+               __BITFIELD_FIELD(uint64_t inta:1,
+               __BITFIELD_FIELD(uint64_t dis_port:1,
+               __BITFIELD_FIELD(uint64_t waitl_com:1,
+               __BITFIELD_FIELD(uint64_t intd_map:2,
+               __BITFIELD_FIELD(uint64_t intc_map:2,
+               __BITFIELD_FIELD(uint64_t intb_map:2,
+               __BITFIELD_FIELD(uint64_t inta_map:2,
+               __BITFIELD_FIELD(uint64_t ctlp_ro:1,
+               __BITFIELD_FIELD(uint64_t reserved_6_6:1,
+               __BITFIELD_FIELD(uint64_t ptlp_ro:1,
+               __BITFIELD_FIELD(uint64_t reserved_1_4:4,
+               __BITFIELD_FIELD(uint64_t wait_com:1,
+               ;))))))))))))))))
        } s;
-       struct cvmx_sli_last_win_rdata0_s cn61xx;
-       struct cvmx_sli_last_win_rdata0_s cn63xx;
-       struct cvmx_sli_last_win_rdata0_s cn63xxp1;
-       struct cvmx_sli_last_win_rdata0_s cn66xx;
-       struct cvmx_sli_last_win_rdata0_s cn68xx;
-       struct cvmx_sli_last_win_rdata0_s cn68xxp1;
-       struct cvmx_sli_last_win_rdata0_s cnf71xx;
-};
-
-union cvmx_sli_last_win_rdata1 {
-       uint64_t u64;
-       struct cvmx_sli_last_win_rdata1_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t data:64;
-#else
-               uint64_t data:64;
-#endif
-       } s;
-       struct cvmx_sli_last_win_rdata1_s cn61xx;
-       struct cvmx_sli_last_win_rdata1_s cn63xx;
-       struct cvmx_sli_last_win_rdata1_s cn63xxp1;
-       struct cvmx_sli_last_win_rdata1_s cn66xx;
-       struct cvmx_sli_last_win_rdata1_s cn68xx;
-       struct cvmx_sli_last_win_rdata1_s cn68xxp1;
-       struct cvmx_sli_last_win_rdata1_s cnf71xx;
-};
-
-union cvmx_sli_last_win_rdata2 {
-       uint64_t u64;
-       struct cvmx_sli_last_win_rdata2_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t data:64;
-#else
-               uint64_t data:64;
-#endif
-       } s;
-       struct cvmx_sli_last_win_rdata2_s cn61xx;
-       struct cvmx_sli_last_win_rdata2_s cn66xx;
-       struct cvmx_sli_last_win_rdata2_s cnf71xx;
-};
-
-union cvmx_sli_last_win_rdata3 {
-       uint64_t u64;
-       struct cvmx_sli_last_win_rdata3_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t data:64;
-#else
-               uint64_t data:64;
-#endif
-       } s;
-       struct cvmx_sli_last_win_rdata3_s cn61xx;
-       struct cvmx_sli_last_win_rdata3_s cn66xx;
-       struct cvmx_sli_last_win_rdata3_s cnf71xx;
-};
-
-union cvmx_sli_mac_credit_cnt {
-       uint64_t u64;
-       struct cvmx_sli_mac_credit_cnt_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_54_63:10;
-               uint64_t p1_c_d:1;
-               uint64_t p1_n_d:1;
-               uint64_t p1_p_d:1;
-               uint64_t p0_c_d:1;
-               uint64_t p0_n_d:1;
-               uint64_t p0_p_d:1;
-               uint64_t p1_ccnt:8;
-               uint64_t p1_ncnt:8;
-               uint64_t p1_pcnt:8;
-               uint64_t p0_ccnt:8;
-               uint64_t p0_ncnt:8;
-               uint64_t p0_pcnt:8;
-#else
-               uint64_t p0_pcnt:8;
-               uint64_t p0_ncnt:8;
-               uint64_t p0_ccnt:8;
-               uint64_t p1_pcnt:8;
-               uint64_t p1_ncnt:8;
-               uint64_t p1_ccnt:8;
-               uint64_t p0_p_d:1;
-               uint64_t p0_n_d:1;
-               uint64_t p0_c_d:1;
-               uint64_t p1_p_d:1;
-               uint64_t p1_n_d:1;
-               uint64_t p1_c_d:1;
-               uint64_t reserved_54_63:10;
-#endif
-       } s;
-       struct cvmx_sli_mac_credit_cnt_s cn61xx;
-       struct cvmx_sli_mac_credit_cnt_s cn63xx;
-       struct cvmx_sli_mac_credit_cnt_cn63xxp1 {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_48_63:16;
-               uint64_t p1_ccnt:8;
-               uint64_t p1_ncnt:8;
-               uint64_t p1_pcnt:8;
-               uint64_t p0_ccnt:8;
-               uint64_t p0_ncnt:8;
-               uint64_t p0_pcnt:8;
-#else
-               uint64_t p0_pcnt:8;
-               uint64_t p0_ncnt:8;
-               uint64_t p0_ccnt:8;
-               uint64_t p1_pcnt:8;
-               uint64_t p1_ncnt:8;
-               uint64_t p1_ccnt:8;
-               uint64_t reserved_48_63:16;
-#endif
-       } cn63xxp1;
-       struct cvmx_sli_mac_credit_cnt_s cn66xx;
-       struct cvmx_sli_mac_credit_cnt_s cn68xx;
-       struct cvmx_sli_mac_credit_cnt_s cn68xxp1;
-       struct cvmx_sli_mac_credit_cnt_s cnf71xx;
-};
-
-union cvmx_sli_mac_credit_cnt2 {
-       uint64_t u64;
-       struct cvmx_sli_mac_credit_cnt2_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_54_63:10;
-               uint64_t p3_c_d:1;
-               uint64_t p3_n_d:1;
-               uint64_t p3_p_d:1;
-               uint64_t p2_c_d:1;
-               uint64_t p2_n_d:1;
-               uint64_t p2_p_d:1;
-               uint64_t p3_ccnt:8;
-               uint64_t p3_ncnt:8;
-               uint64_t p3_pcnt:8;
-               uint64_t p2_ccnt:8;
-               uint64_t p2_ncnt:8;
-               uint64_t p2_pcnt:8;
-#else
-               uint64_t p2_pcnt:8;
-               uint64_t p2_ncnt:8;
-               uint64_t p2_ccnt:8;
-               uint64_t p3_pcnt:8;
-               uint64_t p3_ncnt:8;
-               uint64_t p3_ccnt:8;
-               uint64_t p2_p_d:1;
-               uint64_t p2_n_d:1;
-               uint64_t p2_c_d:1;
-               uint64_t p3_p_d:1;
-               uint64_t p3_n_d:1;
-               uint64_t p3_c_d:1;
-               uint64_t reserved_54_63:10;
-#endif
-       } s;
-       struct cvmx_sli_mac_credit_cnt2_s cn61xx;
-       struct cvmx_sli_mac_credit_cnt2_s cn66xx;
-       struct cvmx_sli_mac_credit_cnt2_s cnf71xx;
-};
-
-union cvmx_sli_mac_number {
-       uint64_t u64;
-       struct cvmx_sli_mac_number_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_9_63:55;
-               uint64_t a_mode:1;
-               uint64_t num:8;
-#else
-               uint64_t num:8;
-               uint64_t a_mode:1;
-               uint64_t reserved_9_63:55;
-#endif
-       } s;
-       struct cvmx_sli_mac_number_s cn61xx;
-       struct cvmx_sli_mac_number_cn63xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_8_63:56;
-               uint64_t num:8;
-#else
-               uint64_t num:8;
-               uint64_t reserved_8_63:56;
-#endif
-       } cn63xx;
-       struct cvmx_sli_mac_number_s cn66xx;
-       struct cvmx_sli_mac_number_cn63xx cn68xx;
-       struct cvmx_sli_mac_number_cn63xx cn68xxp1;
-       struct cvmx_sli_mac_number_s cnf71xx;
 };
 
 union cvmx_sli_mem_access_ctl {
        uint64_t u64;
        struct cvmx_sli_mem_access_ctl_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_14_63:50;
-               uint64_t max_word:4;
-               uint64_t timer:10;
-#else
-               uint64_t timer:10;
-               uint64_t max_word:4;
-               uint64_t reserved_14_63:50;
-#endif
-       } s;
-       struct cvmx_sli_mem_access_ctl_s cn61xx;
-       struct cvmx_sli_mem_access_ctl_s cn63xx;
-       struct cvmx_sli_mem_access_ctl_s cn63xxp1;
-       struct cvmx_sli_mem_access_ctl_s cn66xx;
-       struct cvmx_sli_mem_access_ctl_s cn68xx;
-       struct cvmx_sli_mem_access_ctl_s cn68xxp1;
-       struct cvmx_sli_mem_access_ctl_s cnf71xx;
-};
-
-union cvmx_sli_mem_access_subidx {
-       uint64_t u64;
-       struct cvmx_sli_mem_access_subidx_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_43_63:21;
-               uint64_t zero:1;
-               uint64_t port:3;
-               uint64_t nmerge:1;
-               uint64_t esr:2;
-               uint64_t esw:2;
-               uint64_t wtype:2;
-               uint64_t rtype:2;
-               uint64_t reserved_0_29:30;
-#else
-               uint64_t reserved_0_29:30;
-               uint64_t rtype:2;
-               uint64_t wtype:2;
-               uint64_t esw:2;
-               uint64_t esr:2;
-               uint64_t nmerge:1;
-               uint64_t port:3;
-               uint64_t zero:1;
-               uint64_t reserved_43_63:21;
-#endif
-       } s;
-       struct cvmx_sli_mem_access_subidx_cn61xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_43_63:21;
-               uint64_t zero:1;
-               uint64_t port:3;
-               uint64_t nmerge:1;
-               uint64_t esr:2;
-               uint64_t esw:2;
-               uint64_t wtype:2;
-               uint64_t rtype:2;
-               uint64_t ba:30;
-#else
-               uint64_t ba:30;
-               uint64_t rtype:2;
-               uint64_t wtype:2;
-               uint64_t esw:2;
-               uint64_t esr:2;
-               uint64_t nmerge:1;
-               uint64_t port:3;
-               uint64_t zero:1;
-               uint64_t reserved_43_63:21;
-#endif
-       } cn61xx;
-       struct cvmx_sli_mem_access_subidx_cn61xx cn63xx;
-       struct cvmx_sli_mem_access_subidx_cn61xx cn63xxp1;
-       struct cvmx_sli_mem_access_subidx_cn61xx cn66xx;
-       struct cvmx_sli_mem_access_subidx_cn68xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_43_63:21;
-               uint64_t zero:1;
-               uint64_t port:3;
-               uint64_t nmerge:1;
-               uint64_t esr:2;
-               uint64_t esw:2;
-               uint64_t wtype:2;
-               uint64_t rtype:2;
-               uint64_t ba:28;
-               uint64_t reserved_0_1:2;
-#else
-               uint64_t reserved_0_1:2;
-               uint64_t ba:28;
-               uint64_t rtype:2;
-               uint64_t wtype:2;
-               uint64_t esw:2;
-               uint64_t esr:2;
-               uint64_t nmerge:1;
-               uint64_t port:3;
-               uint64_t zero:1;
-               uint64_t reserved_43_63:21;
-#endif
-       } cn68xx;
-       struct cvmx_sli_mem_access_subidx_cn68xx cn68xxp1;
-       struct cvmx_sli_mem_access_subidx_cn61xx cnf71xx;
-};
-
-union cvmx_sli_msi_enb0 {
-       uint64_t u64;
-       struct cvmx_sli_msi_enb0_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t enb:64;
-#else
-               uint64_t enb:64;
-#endif
-       } s;
-       struct cvmx_sli_msi_enb0_s cn61xx;
-       struct cvmx_sli_msi_enb0_s cn63xx;
-       struct cvmx_sli_msi_enb0_s cn63xxp1;
-       struct cvmx_sli_msi_enb0_s cn66xx;
-       struct cvmx_sli_msi_enb0_s cn68xx;
-       struct cvmx_sli_msi_enb0_s cn68xxp1;
-       struct cvmx_sli_msi_enb0_s cnf71xx;
-};
-
-union cvmx_sli_msi_enb1 {
-       uint64_t u64;
-       struct cvmx_sli_msi_enb1_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t enb:64;
-#else
-               uint64_t enb:64;
-#endif
-       } s;
-       struct cvmx_sli_msi_enb1_s cn61xx;
-       struct cvmx_sli_msi_enb1_s cn63xx;
-       struct cvmx_sli_msi_enb1_s cn63xxp1;
-       struct cvmx_sli_msi_enb1_s cn66xx;
-       struct cvmx_sli_msi_enb1_s cn68xx;
-       struct cvmx_sli_msi_enb1_s cn68xxp1;
-       struct cvmx_sli_msi_enb1_s cnf71xx;
-};
-
-union cvmx_sli_msi_enb2 {
-       uint64_t u64;
-       struct cvmx_sli_msi_enb2_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t enb:64;
-#else
-               uint64_t enb:64;
-#endif
-       } s;
-       struct cvmx_sli_msi_enb2_s cn61xx;
-       struct cvmx_sli_msi_enb2_s cn63xx;
-       struct cvmx_sli_msi_enb2_s cn63xxp1;
-       struct cvmx_sli_msi_enb2_s cn66xx;
-       struct cvmx_sli_msi_enb2_s cn68xx;
-       struct cvmx_sli_msi_enb2_s cn68xxp1;
-       struct cvmx_sli_msi_enb2_s cnf71xx;
-};
-
-union cvmx_sli_msi_enb3 {
-       uint64_t u64;
-       struct cvmx_sli_msi_enb3_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t enb:64;
-#else
-               uint64_t enb:64;
-#endif
-       } s;
-       struct cvmx_sli_msi_enb3_s cn61xx;
-       struct cvmx_sli_msi_enb3_s cn63xx;
-       struct cvmx_sli_msi_enb3_s cn63xxp1;
-       struct cvmx_sli_msi_enb3_s cn66xx;
-       struct cvmx_sli_msi_enb3_s cn68xx;
-       struct cvmx_sli_msi_enb3_s cn68xxp1;
-       struct cvmx_sli_msi_enb3_s cnf71xx;
-};
-
-union cvmx_sli_msi_rcv0 {
-       uint64_t u64;
-       struct cvmx_sli_msi_rcv0_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t intr:64;
-#else
-               uint64_t intr:64;
-#endif
-       } s;
-       struct cvmx_sli_msi_rcv0_s cn61xx;
-       struct cvmx_sli_msi_rcv0_s cn63xx;
-       struct cvmx_sli_msi_rcv0_s cn63xxp1;
-       struct cvmx_sli_msi_rcv0_s cn66xx;
-       struct cvmx_sli_msi_rcv0_s cn68xx;
-       struct cvmx_sli_msi_rcv0_s cn68xxp1;
-       struct cvmx_sli_msi_rcv0_s cnf71xx;
-};
-
-union cvmx_sli_msi_rcv1 {
-       uint64_t u64;
-       struct cvmx_sli_msi_rcv1_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t intr:64;
-#else
-               uint64_t intr:64;
-#endif
-       } s;
-       struct cvmx_sli_msi_rcv1_s cn61xx;
-       struct cvmx_sli_msi_rcv1_s cn63xx;
-       struct cvmx_sli_msi_rcv1_s cn63xxp1;
-       struct cvmx_sli_msi_rcv1_s cn66xx;
-       struct cvmx_sli_msi_rcv1_s cn68xx;
-       struct cvmx_sli_msi_rcv1_s cn68xxp1;
-       struct cvmx_sli_msi_rcv1_s cnf71xx;
-};
-
-union cvmx_sli_msi_rcv2 {
-       uint64_t u64;
-       struct cvmx_sli_msi_rcv2_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t intr:64;
-#else
-               uint64_t intr:64;
-#endif
-       } s;
-       struct cvmx_sli_msi_rcv2_s cn61xx;
-       struct cvmx_sli_msi_rcv2_s cn63xx;
-       struct cvmx_sli_msi_rcv2_s cn63xxp1;
-       struct cvmx_sli_msi_rcv2_s cn66xx;
-       struct cvmx_sli_msi_rcv2_s cn68xx;
-       struct cvmx_sli_msi_rcv2_s cn68xxp1;
-       struct cvmx_sli_msi_rcv2_s cnf71xx;
-};
-
-union cvmx_sli_msi_rcv3 {
-       uint64_t u64;
-       struct cvmx_sli_msi_rcv3_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t intr:64;
-#else
-               uint64_t intr:64;
-#endif
-       } s;
-       struct cvmx_sli_msi_rcv3_s cn61xx;
-       struct cvmx_sli_msi_rcv3_s cn63xx;
-       struct cvmx_sli_msi_rcv3_s cn63xxp1;
-       struct cvmx_sli_msi_rcv3_s cn66xx;
-       struct cvmx_sli_msi_rcv3_s cn68xx;
-       struct cvmx_sli_msi_rcv3_s cn68xxp1;
-       struct cvmx_sli_msi_rcv3_s cnf71xx;
-};
-
-union cvmx_sli_msi_rd_map {
-       uint64_t u64;
-       struct cvmx_sli_msi_rd_map_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_16_63:48;
-               uint64_t rd_int:8;
-               uint64_t msi_int:8;
-#else
-               uint64_t msi_int:8;
-               uint64_t rd_int:8;
-               uint64_t reserved_16_63:48;
-#endif
-       } s;
-       struct cvmx_sli_msi_rd_map_s cn61xx;
-       struct cvmx_sli_msi_rd_map_s cn63xx;
-       struct cvmx_sli_msi_rd_map_s cn63xxp1;
-       struct cvmx_sli_msi_rd_map_s cn66xx;
-       struct cvmx_sli_msi_rd_map_s cn68xx;
-       struct cvmx_sli_msi_rd_map_s cn68xxp1;
-       struct cvmx_sli_msi_rd_map_s cnf71xx;
-};
-
-union cvmx_sli_msi_w1c_enb0 {
-       uint64_t u64;
-       struct cvmx_sli_msi_w1c_enb0_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t clr:64;
-#else
-               uint64_t clr:64;
-#endif
-       } s;
-       struct cvmx_sli_msi_w1c_enb0_s cn61xx;
-       struct cvmx_sli_msi_w1c_enb0_s cn63xx;
-       struct cvmx_sli_msi_w1c_enb0_s cn63xxp1;
-       struct cvmx_sli_msi_w1c_enb0_s cn66xx;
-       struct cvmx_sli_msi_w1c_enb0_s cn68xx;
-       struct cvmx_sli_msi_w1c_enb0_s cn68xxp1;
-       struct cvmx_sli_msi_w1c_enb0_s cnf71xx;
-};
-
-union cvmx_sli_msi_w1c_enb1 {
-       uint64_t u64;
-       struct cvmx_sli_msi_w1c_enb1_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t clr:64;
-#else
-               uint64_t clr:64;
-#endif
-       } s;
-       struct cvmx_sli_msi_w1c_enb1_s cn61xx;
-       struct cvmx_sli_msi_w1c_enb1_s cn63xx;
-       struct cvmx_sli_msi_w1c_enb1_s cn63xxp1;
-       struct cvmx_sli_msi_w1c_enb1_s cn66xx;
-       struct cvmx_sli_msi_w1c_enb1_s cn68xx;
-       struct cvmx_sli_msi_w1c_enb1_s cn68xxp1;
-       struct cvmx_sli_msi_w1c_enb1_s cnf71xx;
-};
-
-union cvmx_sli_msi_w1c_enb2 {
-       uint64_t u64;
-       struct cvmx_sli_msi_w1c_enb2_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t clr:64;
-#else
-               uint64_t clr:64;
-#endif
-       } s;
-       struct cvmx_sli_msi_w1c_enb2_s cn61xx;
-       struct cvmx_sli_msi_w1c_enb2_s cn63xx;
-       struct cvmx_sli_msi_w1c_enb2_s cn63xxp1;
-       struct cvmx_sli_msi_w1c_enb2_s cn66xx;
-       struct cvmx_sli_msi_w1c_enb2_s cn68xx;
-       struct cvmx_sli_msi_w1c_enb2_s cn68xxp1;
-       struct cvmx_sli_msi_w1c_enb2_s cnf71xx;
-};
-
-union cvmx_sli_msi_w1c_enb3 {
-       uint64_t u64;
-       struct cvmx_sli_msi_w1c_enb3_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t clr:64;
-#else
-               uint64_t clr:64;
-#endif
-       } s;
-       struct cvmx_sli_msi_w1c_enb3_s cn61xx;
-       struct cvmx_sli_msi_w1c_enb3_s cn63xx;
-       struct cvmx_sli_msi_w1c_enb3_s cn63xxp1;
-       struct cvmx_sli_msi_w1c_enb3_s cn66xx;
-       struct cvmx_sli_msi_w1c_enb3_s cn68xx;
-       struct cvmx_sli_msi_w1c_enb3_s cn68xxp1;
-       struct cvmx_sli_msi_w1c_enb3_s cnf71xx;
-};
-
-union cvmx_sli_msi_w1s_enb0 {
-       uint64_t u64;
-       struct cvmx_sli_msi_w1s_enb0_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t set:64;
-#else
-               uint64_t set:64;
-#endif
-       } s;
-       struct cvmx_sli_msi_w1s_enb0_s cn61xx;
-       struct cvmx_sli_msi_w1s_enb0_s cn63xx;
-       struct cvmx_sli_msi_w1s_enb0_s cn63xxp1;
-       struct cvmx_sli_msi_w1s_enb0_s cn66xx;
-       struct cvmx_sli_msi_w1s_enb0_s cn68xx;
-       struct cvmx_sli_msi_w1s_enb0_s cn68xxp1;
-       struct cvmx_sli_msi_w1s_enb0_s cnf71xx;
-};
-
-union cvmx_sli_msi_w1s_enb1 {
-       uint64_t u64;
-       struct cvmx_sli_msi_w1s_enb1_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t set:64;
-#else
-               uint64_t set:64;
-#endif
-       } s;
-       struct cvmx_sli_msi_w1s_enb1_s cn61xx;
-       struct cvmx_sli_msi_w1s_enb1_s cn63xx;
-       struct cvmx_sli_msi_w1s_enb1_s cn63xxp1;
-       struct cvmx_sli_msi_w1s_enb1_s cn66xx;
-       struct cvmx_sli_msi_w1s_enb1_s cn68xx;
-       struct cvmx_sli_msi_w1s_enb1_s cn68xxp1;
-       struct cvmx_sli_msi_w1s_enb1_s cnf71xx;
-};
-
-union cvmx_sli_msi_w1s_enb2 {
-       uint64_t u64;
-       struct cvmx_sli_msi_w1s_enb2_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t set:64;
-#else
-               uint64_t set:64;
-#endif
-       } s;
-       struct cvmx_sli_msi_w1s_enb2_s cn61xx;
-       struct cvmx_sli_msi_w1s_enb2_s cn63xx;
-       struct cvmx_sli_msi_w1s_enb2_s cn63xxp1;
-       struct cvmx_sli_msi_w1s_enb2_s cn66xx;
-       struct cvmx_sli_msi_w1s_enb2_s cn68xx;
-       struct cvmx_sli_msi_w1s_enb2_s cn68xxp1;
-       struct cvmx_sli_msi_w1s_enb2_s cnf71xx;
-};
-
-union cvmx_sli_msi_w1s_enb3 {
-       uint64_t u64;
-       struct cvmx_sli_msi_w1s_enb3_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t set:64;
-#else
-               uint64_t set:64;
-#endif
-       } s;
-       struct cvmx_sli_msi_w1s_enb3_s cn61xx;
-       struct cvmx_sli_msi_w1s_enb3_s cn63xx;
-       struct cvmx_sli_msi_w1s_enb3_s cn63xxp1;
-       struct cvmx_sli_msi_w1s_enb3_s cn66xx;
-       struct cvmx_sli_msi_w1s_enb3_s cn68xx;
-       struct cvmx_sli_msi_w1s_enb3_s cn68xxp1;
-       struct cvmx_sli_msi_w1s_enb3_s cnf71xx;
-};
-
-union cvmx_sli_msi_wr_map {
-       uint64_t u64;
-       struct cvmx_sli_msi_wr_map_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_16_63:48;
-               uint64_t ciu_int:8;
-               uint64_t msi_int:8;
-#else
-               uint64_t msi_int:8;
-               uint64_t ciu_int:8;
-               uint64_t reserved_16_63:48;
-#endif
-       } s;
-       struct cvmx_sli_msi_wr_map_s cn61xx;
-       struct cvmx_sli_msi_wr_map_s cn63xx;
-       struct cvmx_sli_msi_wr_map_s cn63xxp1;
-       struct cvmx_sli_msi_wr_map_s cn66xx;
-       struct cvmx_sli_msi_wr_map_s cn68xx;
-       struct cvmx_sli_msi_wr_map_s cn68xxp1;
-       struct cvmx_sli_msi_wr_map_s cnf71xx;
-};
-
-union cvmx_sli_pcie_msi_rcv {
-       uint64_t u64;
-       struct cvmx_sli_pcie_msi_rcv_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_8_63:56;
-               uint64_t intr:8;
-#else
-               uint64_t intr:8;
-               uint64_t reserved_8_63:56;
-#endif
-       } s;
-       struct cvmx_sli_pcie_msi_rcv_s cn61xx;
-       struct cvmx_sli_pcie_msi_rcv_s cn63xx;
-       struct cvmx_sli_pcie_msi_rcv_s cn63xxp1;
-       struct cvmx_sli_pcie_msi_rcv_s cn66xx;
-       struct cvmx_sli_pcie_msi_rcv_s cn68xx;
-       struct cvmx_sli_pcie_msi_rcv_s cn68xxp1;
-       struct cvmx_sli_pcie_msi_rcv_s cnf71xx;
-};
-
-union cvmx_sli_pcie_msi_rcv_b1 {
-       uint64_t u64;
-       struct cvmx_sli_pcie_msi_rcv_b1_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_16_63:48;
-               uint64_t intr:8;
-               uint64_t reserved_0_7:8;
-#else
-               uint64_t reserved_0_7:8;
-               uint64_t intr:8;
-               uint64_t reserved_16_63:48;
-#endif
-       } s;
-       struct cvmx_sli_pcie_msi_rcv_b1_s cn61xx;
-       struct cvmx_sli_pcie_msi_rcv_b1_s cn63xx;
-       struct cvmx_sli_pcie_msi_rcv_b1_s cn63xxp1;
-       struct cvmx_sli_pcie_msi_rcv_b1_s cn66xx;
-       struct cvmx_sli_pcie_msi_rcv_b1_s cn68xx;
-       struct cvmx_sli_pcie_msi_rcv_b1_s cn68xxp1;
-       struct cvmx_sli_pcie_msi_rcv_b1_s cnf71xx;
-};
-
-union cvmx_sli_pcie_msi_rcv_b2 {
-       uint64_t u64;
-       struct cvmx_sli_pcie_msi_rcv_b2_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_24_63:40;
-               uint64_t intr:8;
-               uint64_t reserved_0_15:16;
-#else
-               uint64_t reserved_0_15:16;
-               uint64_t intr:8;
-               uint64_t reserved_24_63:40;
-#endif
-       } s;
-       struct cvmx_sli_pcie_msi_rcv_b2_s cn61xx;
-       struct cvmx_sli_pcie_msi_rcv_b2_s cn63xx;
-       struct cvmx_sli_pcie_msi_rcv_b2_s cn63xxp1;
-       struct cvmx_sli_pcie_msi_rcv_b2_s cn66xx;
-       struct cvmx_sli_pcie_msi_rcv_b2_s cn68xx;
-       struct cvmx_sli_pcie_msi_rcv_b2_s cn68xxp1;
-       struct cvmx_sli_pcie_msi_rcv_b2_s cnf71xx;
-};
-
-union cvmx_sli_pcie_msi_rcv_b3 {
-       uint64_t u64;
-       struct cvmx_sli_pcie_msi_rcv_b3_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t intr:8;
-               uint64_t reserved_0_23:24;
-#else
-               uint64_t reserved_0_23:24;
-               uint64_t intr:8;
-               uint64_t reserved_32_63:32;
-#endif
-       } s;
-       struct cvmx_sli_pcie_msi_rcv_b3_s cn61xx;
-       struct cvmx_sli_pcie_msi_rcv_b3_s cn63xx;
-       struct cvmx_sli_pcie_msi_rcv_b3_s cn63xxp1;
-       struct cvmx_sli_pcie_msi_rcv_b3_s cn66xx;
-       struct cvmx_sli_pcie_msi_rcv_b3_s cn68xx;
-       struct cvmx_sli_pcie_msi_rcv_b3_s cn68xxp1;
-       struct cvmx_sli_pcie_msi_rcv_b3_s cnf71xx;
-};
-
-union cvmx_sli_pktx_cnts {
-       uint64_t u64;
-       struct cvmx_sli_pktx_cnts_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_54_63:10;
-               uint64_t timer:22;
-               uint64_t cnt:32;
-#else
-               uint64_t cnt:32;
-               uint64_t timer:22;
-               uint64_t reserved_54_63:10;
-#endif
-       } s;
-       struct cvmx_sli_pktx_cnts_s cn61xx;
-       struct cvmx_sli_pktx_cnts_s cn63xx;
-       struct cvmx_sli_pktx_cnts_s cn63xxp1;
-       struct cvmx_sli_pktx_cnts_s cn66xx;
-       struct cvmx_sli_pktx_cnts_s cn68xx;
-       struct cvmx_sli_pktx_cnts_s cn68xxp1;
-       struct cvmx_sli_pktx_cnts_s cnf71xx;
-};
-
-union cvmx_sli_pktx_in_bp {
-       uint64_t u64;
-       struct cvmx_sli_pktx_in_bp_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t wmark:32;
-               uint64_t cnt:32;
-#else
-               uint64_t cnt:32;
-               uint64_t wmark:32;
-#endif
-       } s;
-       struct cvmx_sli_pktx_in_bp_s cn61xx;
-       struct cvmx_sli_pktx_in_bp_s cn63xx;
-       struct cvmx_sli_pktx_in_bp_s cn63xxp1;
-       struct cvmx_sli_pktx_in_bp_s cn66xx;
-       struct cvmx_sli_pktx_in_bp_s cnf71xx;
-};
-
-union cvmx_sli_pktx_instr_baddr {
-       uint64_t u64;
-       struct cvmx_sli_pktx_instr_baddr_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t addr:61;
-               uint64_t reserved_0_2:3;
-#else
-               uint64_t reserved_0_2:3;
-               uint64_t addr:61;
-#endif
+               __BITFIELD_FIELD(uint64_t reserved_14_63:50,
+               __BITFIELD_FIELD(uint64_t max_word:4,
+               __BITFIELD_FIELD(uint64_t timer:10,
+               ;)))
        } s;
-       struct cvmx_sli_pktx_instr_baddr_s cn61xx;
-       struct cvmx_sli_pktx_instr_baddr_s cn63xx;
-       struct cvmx_sli_pktx_instr_baddr_s cn63xxp1;
-       struct cvmx_sli_pktx_instr_baddr_s cn66xx;
-       struct cvmx_sli_pktx_instr_baddr_s cn68xx;
-       struct cvmx_sli_pktx_instr_baddr_s cn68xxp1;
-       struct cvmx_sli_pktx_instr_baddr_s cnf71xx;
-};
-
-union cvmx_sli_pktx_instr_baoff_dbell {
-       uint64_t u64;
-       struct cvmx_sli_pktx_instr_baoff_dbell_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t aoff:32;
-               uint64_t dbell:32;
-#else
-               uint64_t dbell:32;
-               uint64_t aoff:32;
-#endif
-       } s;
-       struct cvmx_sli_pktx_instr_baoff_dbell_s cn61xx;
-       struct cvmx_sli_pktx_instr_baoff_dbell_s cn63xx;
-       struct cvmx_sli_pktx_instr_baoff_dbell_s cn63xxp1;
-       struct cvmx_sli_pktx_instr_baoff_dbell_s cn66xx;
-       struct cvmx_sli_pktx_instr_baoff_dbell_s cn68xx;
-       struct cvmx_sli_pktx_instr_baoff_dbell_s cn68xxp1;
-       struct cvmx_sli_pktx_instr_baoff_dbell_s cnf71xx;
-};
-
-union cvmx_sli_pktx_instr_fifo_rsize {
-       uint64_t u64;
-       struct cvmx_sli_pktx_instr_fifo_rsize_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t max:9;
-               uint64_t rrp:9;
-               uint64_t wrp:9;
-               uint64_t fcnt:5;
-               uint64_t rsize:32;
-#else
-               uint64_t rsize:32;
-               uint64_t fcnt:5;
-               uint64_t wrp:9;
-               uint64_t rrp:9;
-               uint64_t max:9;
-#endif
-       } s;
-       struct cvmx_sli_pktx_instr_fifo_rsize_s cn61xx;
-       struct cvmx_sli_pktx_instr_fifo_rsize_s cn63xx;
-       struct cvmx_sli_pktx_instr_fifo_rsize_s cn63xxp1;
-       struct cvmx_sli_pktx_instr_fifo_rsize_s cn66xx;
-       struct cvmx_sli_pktx_instr_fifo_rsize_s cn68xx;
-       struct cvmx_sli_pktx_instr_fifo_rsize_s cn68xxp1;
-       struct cvmx_sli_pktx_instr_fifo_rsize_s cnf71xx;
-};
-
-union cvmx_sli_pktx_instr_header {
-       uint64_t u64;
-       struct cvmx_sli_pktx_instr_header_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_44_63:20;
-               uint64_t pbp:1;
-               uint64_t reserved_38_42:5;
-               uint64_t rparmode:2;
-               uint64_t reserved_35_35:1;
-               uint64_t rskp_len:7;
-               uint64_t rngrpext:2;
-               uint64_t rnqos:1;
-               uint64_t rngrp:1;
-               uint64_t rntt:1;
-               uint64_t rntag:1;
-               uint64_t use_ihdr:1;
-               uint64_t reserved_16_20:5;
-               uint64_t par_mode:2;
-               uint64_t reserved_13_13:1;
-               uint64_t skp_len:7;
-               uint64_t ngrpext:2;
-               uint64_t nqos:1;
-               uint64_t ngrp:1;
-               uint64_t ntt:1;
-               uint64_t ntag:1;
-#else
-               uint64_t ntag:1;
-               uint64_t ntt:1;
-               uint64_t ngrp:1;
-               uint64_t nqos:1;
-               uint64_t ngrpext:2;
-               uint64_t skp_len:7;
-               uint64_t reserved_13_13:1;
-               uint64_t par_mode:2;
-               uint64_t reserved_16_20:5;
-               uint64_t use_ihdr:1;
-               uint64_t rntag:1;
-               uint64_t rntt:1;
-               uint64_t rngrp:1;
-               uint64_t rnqos:1;
-               uint64_t rngrpext:2;
-               uint64_t rskp_len:7;
-               uint64_t reserved_35_35:1;
-               uint64_t rparmode:2;
-               uint64_t reserved_38_42:5;
-               uint64_t pbp:1;
-               uint64_t reserved_44_63:20;
-#endif
-       } s;
-       struct cvmx_sli_pktx_instr_header_cn61xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_44_63:20;
-               uint64_t pbp:1;
-               uint64_t reserved_38_42:5;
-               uint64_t rparmode:2;
-               uint64_t reserved_35_35:1;
-               uint64_t rskp_len:7;
-               uint64_t reserved_26_27:2;
-               uint64_t rnqos:1;
-               uint64_t rngrp:1;
-               uint64_t rntt:1;
-               uint64_t rntag:1;
-               uint64_t use_ihdr:1;
-               uint64_t reserved_16_20:5;
-               uint64_t par_mode:2;
-               uint64_t reserved_13_13:1;
-               uint64_t skp_len:7;
-               uint64_t reserved_4_5:2;
-               uint64_t nqos:1;
-               uint64_t ngrp:1;
-               uint64_t ntt:1;
-               uint64_t ntag:1;
-#else
-               uint64_t ntag:1;
-               uint64_t ntt:1;
-               uint64_t ngrp:1;
-               uint64_t nqos:1;
-               uint64_t reserved_4_5:2;
-               uint64_t skp_len:7;
-               uint64_t reserved_13_13:1;
-               uint64_t par_mode:2;
-               uint64_t reserved_16_20:5;
-               uint64_t use_ihdr:1;
-               uint64_t rntag:1;
-               uint64_t rntt:1;
-               uint64_t rngrp:1;
-               uint64_t rnqos:1;
-               uint64_t reserved_26_27:2;
-               uint64_t rskp_len:7;
-               uint64_t reserved_35_35:1;
-               uint64_t rparmode:2;
-               uint64_t reserved_38_42:5;
-               uint64_t pbp:1;
-               uint64_t reserved_44_63:20;
-#endif
-       } cn61xx;
-       struct cvmx_sli_pktx_instr_header_cn61xx cn63xx;
-       struct cvmx_sli_pktx_instr_header_cn61xx cn63xxp1;
-       struct cvmx_sli_pktx_instr_header_cn61xx cn66xx;
-       struct cvmx_sli_pktx_instr_header_s cn68xx;
-       struct cvmx_sli_pktx_instr_header_cn61xx cn68xxp1;
-       struct cvmx_sli_pktx_instr_header_cn61xx cnf71xx;
-};
-
-union cvmx_sli_pktx_out_size {
-       uint64_t u64;
-       struct cvmx_sli_pktx_out_size_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_23_63:41;
-               uint64_t isize:7;
-               uint64_t bsize:16;
-#else
-               uint64_t bsize:16;
-               uint64_t isize:7;
-               uint64_t reserved_23_63:41;
-#endif
-       } s;
-       struct cvmx_sli_pktx_out_size_s cn61xx;
-       struct cvmx_sli_pktx_out_size_s cn63xx;
-       struct cvmx_sli_pktx_out_size_s cn63xxp1;
-       struct cvmx_sli_pktx_out_size_s cn66xx;
-       struct cvmx_sli_pktx_out_size_s cn68xx;
-       struct cvmx_sli_pktx_out_size_s cn68xxp1;
-       struct cvmx_sli_pktx_out_size_s cnf71xx;
-};
-
-union cvmx_sli_pktx_slist_baddr {
-       uint64_t u64;
-       struct cvmx_sli_pktx_slist_baddr_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t addr:60;
-               uint64_t reserved_0_3:4;
-#else
-               uint64_t reserved_0_3:4;
-               uint64_t addr:60;
-#endif
-       } s;
-       struct cvmx_sli_pktx_slist_baddr_s cn61xx;
-       struct cvmx_sli_pktx_slist_baddr_s cn63xx;
-       struct cvmx_sli_pktx_slist_baddr_s cn63xxp1;
-       struct cvmx_sli_pktx_slist_baddr_s cn66xx;
-       struct cvmx_sli_pktx_slist_baddr_s cn68xx;
-       struct cvmx_sli_pktx_slist_baddr_s cn68xxp1;
-       struct cvmx_sli_pktx_slist_baddr_s cnf71xx;
-};
-
-union cvmx_sli_pktx_slist_baoff_dbell {
-       uint64_t u64;
-       struct cvmx_sli_pktx_slist_baoff_dbell_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t aoff:32;
-               uint64_t dbell:32;
-#else
-               uint64_t dbell:32;
-               uint64_t aoff:32;
-#endif
-       } s;
-       struct cvmx_sli_pktx_slist_baoff_dbell_s cn61xx;
-       struct cvmx_sli_pktx_slist_baoff_dbell_s cn63xx;
-       struct cvmx_sli_pktx_slist_baoff_dbell_s cn63xxp1;
-       struct cvmx_sli_pktx_slist_baoff_dbell_s cn66xx;
-       struct cvmx_sli_pktx_slist_baoff_dbell_s cn68xx;
-       struct cvmx_sli_pktx_slist_baoff_dbell_s cn68xxp1;
-       struct cvmx_sli_pktx_slist_baoff_dbell_s cnf71xx;
-};
-
-union cvmx_sli_pktx_slist_fifo_rsize {
-       uint64_t u64;
-       struct cvmx_sli_pktx_slist_fifo_rsize_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t rsize:32;
-#else
-               uint64_t rsize:32;
-               uint64_t reserved_32_63:32;
-#endif
-       } s;
-       struct cvmx_sli_pktx_slist_fifo_rsize_s cn61xx;
-       struct cvmx_sli_pktx_slist_fifo_rsize_s cn63xx;
-       struct cvmx_sli_pktx_slist_fifo_rsize_s cn63xxp1;
-       struct cvmx_sli_pktx_slist_fifo_rsize_s cn66xx;
-       struct cvmx_sli_pktx_slist_fifo_rsize_s cn68xx;
-       struct cvmx_sli_pktx_slist_fifo_rsize_s cn68xxp1;
-       struct cvmx_sli_pktx_slist_fifo_rsize_s cnf71xx;
-};
-
-union cvmx_sli_pkt_cnt_int {
-       uint64_t u64;
-       struct cvmx_sli_pkt_cnt_int_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t port:32;
-#else
-               uint64_t port:32;
-               uint64_t reserved_32_63:32;
-#endif
-       } s;
-       struct cvmx_sli_pkt_cnt_int_s cn61xx;
-       struct cvmx_sli_pkt_cnt_int_s cn63xx;
-       struct cvmx_sli_pkt_cnt_int_s cn63xxp1;
-       struct cvmx_sli_pkt_cnt_int_s cn66xx;
-       struct cvmx_sli_pkt_cnt_int_s cn68xx;
-       struct cvmx_sli_pkt_cnt_int_s cn68xxp1;
-       struct cvmx_sli_pkt_cnt_int_s cnf71xx;
-};
-
-union cvmx_sli_pkt_cnt_int_enb {
-       uint64_t u64;
-       struct cvmx_sli_pkt_cnt_int_enb_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t port:32;
-#else
-               uint64_t port:32;
-               uint64_t reserved_32_63:32;
-#endif
-       } s;
-       struct cvmx_sli_pkt_cnt_int_enb_s cn61xx;
-       struct cvmx_sli_pkt_cnt_int_enb_s cn63xx;
-       struct cvmx_sli_pkt_cnt_int_enb_s cn63xxp1;
-       struct cvmx_sli_pkt_cnt_int_enb_s cn66xx;
-       struct cvmx_sli_pkt_cnt_int_enb_s cn68xx;
-       struct cvmx_sli_pkt_cnt_int_enb_s cn68xxp1;
-       struct cvmx_sli_pkt_cnt_int_enb_s cnf71xx;
-};
-
-union cvmx_sli_pkt_ctl {
-       uint64_t u64;
-       struct cvmx_sli_pkt_ctl_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_5_63:59;
-               uint64_t ring_en:1;
-               uint64_t pkt_bp:4;
-#else
-               uint64_t pkt_bp:4;
-               uint64_t ring_en:1;
-               uint64_t reserved_5_63:59;
-#endif
-       } s;
-       struct cvmx_sli_pkt_ctl_s cn61xx;
-       struct cvmx_sli_pkt_ctl_s cn63xx;
-       struct cvmx_sli_pkt_ctl_s cn63xxp1;
-       struct cvmx_sli_pkt_ctl_s cn66xx;
-       struct cvmx_sli_pkt_ctl_s cn68xx;
-       struct cvmx_sli_pkt_ctl_s cn68xxp1;
-       struct cvmx_sli_pkt_ctl_s cnf71xx;
-};
-
-union cvmx_sli_pkt_data_out_es {
-       uint64_t u64;
-       struct cvmx_sli_pkt_data_out_es_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t es:64;
-#else
-               uint64_t es:64;
-#endif
-       } s;
-       struct cvmx_sli_pkt_data_out_es_s cn61xx;
-       struct cvmx_sli_pkt_data_out_es_s cn63xx;
-       struct cvmx_sli_pkt_data_out_es_s cn63xxp1;
-       struct cvmx_sli_pkt_data_out_es_s cn66xx;
-       struct cvmx_sli_pkt_data_out_es_s cn68xx;
-       struct cvmx_sli_pkt_data_out_es_s cn68xxp1;
-       struct cvmx_sli_pkt_data_out_es_s cnf71xx;
-};
-
-union cvmx_sli_pkt_data_out_ns {
-       uint64_t u64;
-       struct cvmx_sli_pkt_data_out_ns_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t nsr:32;
-#else
-               uint64_t nsr:32;
-               uint64_t reserved_32_63:32;
-#endif
-       } s;
-       struct cvmx_sli_pkt_data_out_ns_s cn61xx;
-       struct cvmx_sli_pkt_data_out_ns_s cn63xx;
-       struct cvmx_sli_pkt_data_out_ns_s cn63xxp1;
-       struct cvmx_sli_pkt_data_out_ns_s cn66xx;
-       struct cvmx_sli_pkt_data_out_ns_s cn68xx;
-       struct cvmx_sli_pkt_data_out_ns_s cn68xxp1;
-       struct cvmx_sli_pkt_data_out_ns_s cnf71xx;
-};
-
-union cvmx_sli_pkt_data_out_ror {
-       uint64_t u64;
-       struct cvmx_sli_pkt_data_out_ror_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t ror:32;
-#else
-               uint64_t ror:32;
-               uint64_t reserved_32_63:32;
-#endif
-       } s;
-       struct cvmx_sli_pkt_data_out_ror_s cn61xx;
-       struct cvmx_sli_pkt_data_out_ror_s cn63xx;
-       struct cvmx_sli_pkt_data_out_ror_s cn63xxp1;
-       struct cvmx_sli_pkt_data_out_ror_s cn66xx;
-       struct cvmx_sli_pkt_data_out_ror_s cn68xx;
-       struct cvmx_sli_pkt_data_out_ror_s cn68xxp1;
-       struct cvmx_sli_pkt_data_out_ror_s cnf71xx;
-};
-
-union cvmx_sli_pkt_dpaddr {
-       uint64_t u64;
-       struct cvmx_sli_pkt_dpaddr_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t dptr:32;
-#else
-               uint64_t dptr:32;
-               uint64_t reserved_32_63:32;
-#endif
-       } s;
-       struct cvmx_sli_pkt_dpaddr_s cn61xx;
-       struct cvmx_sli_pkt_dpaddr_s cn63xx;
-       struct cvmx_sli_pkt_dpaddr_s cn63xxp1;
-       struct cvmx_sli_pkt_dpaddr_s cn66xx;
-       struct cvmx_sli_pkt_dpaddr_s cn68xx;
-       struct cvmx_sli_pkt_dpaddr_s cn68xxp1;
-       struct cvmx_sli_pkt_dpaddr_s cnf71xx;
-};
-
-union cvmx_sli_pkt_in_bp {
-       uint64_t u64;
-       struct cvmx_sli_pkt_in_bp_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t bp:32;
-#else
-               uint64_t bp:32;
-               uint64_t reserved_32_63:32;
-#endif
-       } s;
-       struct cvmx_sli_pkt_in_bp_s cn61xx;
-       struct cvmx_sli_pkt_in_bp_s cn63xx;
-       struct cvmx_sli_pkt_in_bp_s cn63xxp1;
-       struct cvmx_sli_pkt_in_bp_s cn66xx;
-       struct cvmx_sli_pkt_in_bp_s cnf71xx;
-};
-
-union cvmx_sli_pkt_in_donex_cnts {
-       uint64_t u64;
-       struct cvmx_sli_pkt_in_donex_cnts_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t cnt:32;
-#else
-               uint64_t cnt:32;
-               uint64_t reserved_32_63:32;
-#endif
-       } s;
-       struct cvmx_sli_pkt_in_donex_cnts_s cn61xx;
-       struct cvmx_sli_pkt_in_donex_cnts_s cn63xx;
-       struct cvmx_sli_pkt_in_donex_cnts_s cn63xxp1;
-       struct cvmx_sli_pkt_in_donex_cnts_s cn66xx;
-       struct cvmx_sli_pkt_in_donex_cnts_s cn68xx;
-       struct cvmx_sli_pkt_in_donex_cnts_s cn68xxp1;
-       struct cvmx_sli_pkt_in_donex_cnts_s cnf71xx;
-};
-
-union cvmx_sli_pkt_in_instr_counts {
-       uint64_t u64;
-       struct cvmx_sli_pkt_in_instr_counts_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t wr_cnt:32;
-               uint64_t rd_cnt:32;
-#else
-               uint64_t rd_cnt:32;
-               uint64_t wr_cnt:32;
-#endif
-       } s;
-       struct cvmx_sli_pkt_in_instr_counts_s cn61xx;
-       struct cvmx_sli_pkt_in_instr_counts_s cn63xx;
-       struct cvmx_sli_pkt_in_instr_counts_s cn63xxp1;
-       struct cvmx_sli_pkt_in_instr_counts_s cn66xx;
-       struct cvmx_sli_pkt_in_instr_counts_s cn68xx;
-       struct cvmx_sli_pkt_in_instr_counts_s cn68xxp1;
-       struct cvmx_sli_pkt_in_instr_counts_s cnf71xx;
-};
-
-union cvmx_sli_pkt_in_pcie_port {
-       uint64_t u64;
-       struct cvmx_sli_pkt_in_pcie_port_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t pp:64;
-#else
-               uint64_t pp:64;
-#endif
-       } s;
-       struct cvmx_sli_pkt_in_pcie_port_s cn61xx;
-       struct cvmx_sli_pkt_in_pcie_port_s cn63xx;
-       struct cvmx_sli_pkt_in_pcie_port_s cn63xxp1;
-       struct cvmx_sli_pkt_in_pcie_port_s cn66xx;
-       struct cvmx_sli_pkt_in_pcie_port_s cn68xx;
-       struct cvmx_sli_pkt_in_pcie_port_s cn68xxp1;
-       struct cvmx_sli_pkt_in_pcie_port_s cnf71xx;
-};
-
-union cvmx_sli_pkt_input_control {
-       uint64_t u64;
-       struct cvmx_sli_pkt_input_control_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t prd_erst:1;
-               uint64_t prd_rds:7;
-               uint64_t gii_erst:1;
-               uint64_t gii_rds:7;
-               uint64_t reserved_41_47:7;
-               uint64_t prc_idle:1;
-               uint64_t reserved_24_39:16;
-               uint64_t pin_rst:1;
-               uint64_t pkt_rr:1;
-               uint64_t pbp_dhi:13;
-               uint64_t d_nsr:1;
-               uint64_t d_esr:2;
-               uint64_t d_ror:1;
-               uint64_t use_csr:1;
-               uint64_t nsr:1;
-               uint64_t esr:2;
-               uint64_t ror:1;
-#else
-               uint64_t ror:1;
-               uint64_t esr:2;
-               uint64_t nsr:1;
-               uint64_t use_csr:1;
-               uint64_t d_ror:1;
-               uint64_t d_esr:2;
-               uint64_t d_nsr:1;
-               uint64_t pbp_dhi:13;
-               uint64_t pkt_rr:1;
-               uint64_t pin_rst:1;
-               uint64_t reserved_24_39:16;
-               uint64_t prc_idle:1;
-               uint64_t reserved_41_47:7;
-               uint64_t gii_rds:7;
-               uint64_t gii_erst:1;
-               uint64_t prd_rds:7;
-               uint64_t prd_erst:1;
-#endif
-       } s;
-       struct cvmx_sli_pkt_input_control_s cn61xx;
-       struct cvmx_sli_pkt_input_control_cn63xx {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_23_63:41;
-               uint64_t pkt_rr:1;
-               uint64_t pbp_dhi:13;
-               uint64_t d_nsr:1;
-               uint64_t d_esr:2;
-               uint64_t d_ror:1;
-               uint64_t use_csr:1;
-               uint64_t nsr:1;
-               uint64_t esr:2;
-               uint64_t ror:1;
-#else
-               uint64_t ror:1;
-               uint64_t esr:2;
-               uint64_t nsr:1;
-               uint64_t use_csr:1;
-               uint64_t d_ror:1;
-               uint64_t d_esr:2;
-               uint64_t d_nsr:1;
-               uint64_t pbp_dhi:13;
-               uint64_t pkt_rr:1;
-               uint64_t reserved_23_63:41;
-#endif
-       } cn63xx;
-       struct cvmx_sli_pkt_input_control_cn63xx cn63xxp1;
-       struct cvmx_sli_pkt_input_control_s cn66xx;
-       struct cvmx_sli_pkt_input_control_s cn68xx;
-       struct cvmx_sli_pkt_input_control_s cn68xxp1;
-       struct cvmx_sli_pkt_input_control_s cnf71xx;
-};
-
-union cvmx_sli_pkt_instr_enb {
-       uint64_t u64;
-       struct cvmx_sli_pkt_instr_enb_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t enb:32;
-#else
-               uint64_t enb:32;
-               uint64_t reserved_32_63:32;
-#endif
-       } s;
-       struct cvmx_sli_pkt_instr_enb_s cn61xx;
-       struct cvmx_sli_pkt_instr_enb_s cn63xx;
-       struct cvmx_sli_pkt_instr_enb_s cn63xxp1;
-       struct cvmx_sli_pkt_instr_enb_s cn66xx;
-       struct cvmx_sli_pkt_instr_enb_s cn68xx;
-       struct cvmx_sli_pkt_instr_enb_s cn68xxp1;
-       struct cvmx_sli_pkt_instr_enb_s cnf71xx;
-};
-
-union cvmx_sli_pkt_instr_rd_size {
-       uint64_t u64;
-       struct cvmx_sli_pkt_instr_rd_size_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t rdsize:64;
-#else
-               uint64_t rdsize:64;
-#endif
-       } s;
-       struct cvmx_sli_pkt_instr_rd_size_s cn61xx;
-       struct cvmx_sli_pkt_instr_rd_size_s cn63xx;
-       struct cvmx_sli_pkt_instr_rd_size_s cn63xxp1;
-       struct cvmx_sli_pkt_instr_rd_size_s cn66xx;
-       struct cvmx_sli_pkt_instr_rd_size_s cn68xx;
-       struct cvmx_sli_pkt_instr_rd_size_s cn68xxp1;
-       struct cvmx_sli_pkt_instr_rd_size_s cnf71xx;
-};
-
-union cvmx_sli_pkt_instr_size {
-       uint64_t u64;
-       struct cvmx_sli_pkt_instr_size_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t is_64b:32;
-#else
-               uint64_t is_64b:32;
-               uint64_t reserved_32_63:32;
-#endif
-       } s;
-       struct cvmx_sli_pkt_instr_size_s cn61xx;
-       struct cvmx_sli_pkt_instr_size_s cn63xx;
-       struct cvmx_sli_pkt_instr_size_s cn63xxp1;
-       struct cvmx_sli_pkt_instr_size_s cn66xx;
-       struct cvmx_sli_pkt_instr_size_s cn68xx;
-       struct cvmx_sli_pkt_instr_size_s cn68xxp1;
-       struct cvmx_sli_pkt_instr_size_s cnf71xx;
-};
-
-union cvmx_sli_pkt_int_levels {
-       uint64_t u64;
-       struct cvmx_sli_pkt_int_levels_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_54_63:10;
-               uint64_t time:22;
-               uint64_t cnt:32;
-#else
-               uint64_t cnt:32;
-               uint64_t time:22;
-               uint64_t reserved_54_63:10;
-#endif
-       } s;
-       struct cvmx_sli_pkt_int_levels_s cn61xx;
-       struct cvmx_sli_pkt_int_levels_s cn63xx;
-       struct cvmx_sli_pkt_int_levels_s cn63xxp1;
-       struct cvmx_sli_pkt_int_levels_s cn66xx;
-       struct cvmx_sli_pkt_int_levels_s cn68xx;
-       struct cvmx_sli_pkt_int_levels_s cn68xxp1;
-       struct cvmx_sli_pkt_int_levels_s cnf71xx;
-};
-
-union cvmx_sli_pkt_iptr {
-       uint64_t u64;
-       struct cvmx_sli_pkt_iptr_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t iptr:32;
-#else
-               uint64_t iptr:32;
-               uint64_t reserved_32_63:32;
-#endif
-       } s;
-       struct cvmx_sli_pkt_iptr_s cn61xx;
-       struct cvmx_sli_pkt_iptr_s cn63xx;
-       struct cvmx_sli_pkt_iptr_s cn63xxp1;
-       struct cvmx_sli_pkt_iptr_s cn66xx;
-       struct cvmx_sli_pkt_iptr_s cn68xx;
-       struct cvmx_sli_pkt_iptr_s cn68xxp1;
-       struct cvmx_sli_pkt_iptr_s cnf71xx;
-};
-
-union cvmx_sli_pkt_out_bmode {
-       uint64_t u64;
-       struct cvmx_sli_pkt_out_bmode_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t bmode:32;
-#else
-               uint64_t bmode:32;
-               uint64_t reserved_32_63:32;
-#endif
-       } s;
-       struct cvmx_sli_pkt_out_bmode_s cn61xx;
-       struct cvmx_sli_pkt_out_bmode_s cn63xx;
-       struct cvmx_sli_pkt_out_bmode_s cn63xxp1;
-       struct cvmx_sli_pkt_out_bmode_s cn66xx;
-       struct cvmx_sli_pkt_out_bmode_s cn68xx;
-       struct cvmx_sli_pkt_out_bmode_s cn68xxp1;
-       struct cvmx_sli_pkt_out_bmode_s cnf71xx;
-};
-
-union cvmx_sli_pkt_out_bp_en {
-       uint64_t u64;
-       struct cvmx_sli_pkt_out_bp_en_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t bp_en:32;
-#else
-               uint64_t bp_en:32;
-               uint64_t reserved_32_63:32;
-#endif
-       } s;
-       struct cvmx_sli_pkt_out_bp_en_s cn68xx;
-       struct cvmx_sli_pkt_out_bp_en_s cn68xxp1;
-};
-
-union cvmx_sli_pkt_out_enb {
-       uint64_t u64;
-       struct cvmx_sli_pkt_out_enb_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t enb:32;
-#else
-               uint64_t enb:32;
-               uint64_t reserved_32_63:32;
-#endif
-       } s;
-       struct cvmx_sli_pkt_out_enb_s cn61xx;
-       struct cvmx_sli_pkt_out_enb_s cn63xx;
-       struct cvmx_sli_pkt_out_enb_s cn63xxp1;
-       struct cvmx_sli_pkt_out_enb_s cn66xx;
-       struct cvmx_sli_pkt_out_enb_s cn68xx;
-       struct cvmx_sli_pkt_out_enb_s cn68xxp1;
-       struct cvmx_sli_pkt_out_enb_s cnf71xx;
-};
-
-union cvmx_sli_pkt_output_wmark {
-       uint64_t u64;
-       struct cvmx_sli_pkt_output_wmark_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t wmark:32;
-#else
-               uint64_t wmark:32;
-               uint64_t reserved_32_63:32;
-#endif
-       } s;
-       struct cvmx_sli_pkt_output_wmark_s cn61xx;
-       struct cvmx_sli_pkt_output_wmark_s cn63xx;
-       struct cvmx_sli_pkt_output_wmark_s cn63xxp1;
-       struct cvmx_sli_pkt_output_wmark_s cn66xx;
-       struct cvmx_sli_pkt_output_wmark_s cn68xx;
-       struct cvmx_sli_pkt_output_wmark_s cn68xxp1;
-       struct cvmx_sli_pkt_output_wmark_s cnf71xx;
-};
-
-union cvmx_sli_pkt_pcie_port {
-       uint64_t u64;
-       struct cvmx_sli_pkt_pcie_port_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t pp:64;
-#else
-               uint64_t pp:64;
-#endif
-       } s;
-       struct cvmx_sli_pkt_pcie_port_s cn61xx;
-       struct cvmx_sli_pkt_pcie_port_s cn63xx;
-       struct cvmx_sli_pkt_pcie_port_s cn63xxp1;
-       struct cvmx_sli_pkt_pcie_port_s cn66xx;
-       struct cvmx_sli_pkt_pcie_port_s cn68xx;
-       struct cvmx_sli_pkt_pcie_port_s cn68xxp1;
-       struct cvmx_sli_pkt_pcie_port_s cnf71xx;
-};
-
-union cvmx_sli_pkt_port_in_rst {
-       uint64_t u64;
-       struct cvmx_sli_pkt_port_in_rst_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t in_rst:32;
-               uint64_t out_rst:32;
-#else
-               uint64_t out_rst:32;
-               uint64_t in_rst:32;
-#endif
-       } s;
-       struct cvmx_sli_pkt_port_in_rst_s cn61xx;
-       struct cvmx_sli_pkt_port_in_rst_s cn63xx;
-       struct cvmx_sli_pkt_port_in_rst_s cn63xxp1;
-       struct cvmx_sli_pkt_port_in_rst_s cn66xx;
-       struct cvmx_sli_pkt_port_in_rst_s cn68xx;
-       struct cvmx_sli_pkt_port_in_rst_s cn68xxp1;
-       struct cvmx_sli_pkt_port_in_rst_s cnf71xx;
-};
-
-union cvmx_sli_pkt_slist_es {
-       uint64_t u64;
-       struct cvmx_sli_pkt_slist_es_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t es:64;
-#else
-               uint64_t es:64;
-#endif
-       } s;
-       struct cvmx_sli_pkt_slist_es_s cn61xx;
-       struct cvmx_sli_pkt_slist_es_s cn63xx;
-       struct cvmx_sli_pkt_slist_es_s cn63xxp1;
-       struct cvmx_sli_pkt_slist_es_s cn66xx;
-       struct cvmx_sli_pkt_slist_es_s cn68xx;
-       struct cvmx_sli_pkt_slist_es_s cn68xxp1;
-       struct cvmx_sli_pkt_slist_es_s cnf71xx;
-};
-
-union cvmx_sli_pkt_slist_ns {
-       uint64_t u64;
-       struct cvmx_sli_pkt_slist_ns_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t nsr:32;
-#else
-               uint64_t nsr:32;
-               uint64_t reserved_32_63:32;
-#endif
-       } s;
-       struct cvmx_sli_pkt_slist_ns_s cn61xx;
-       struct cvmx_sli_pkt_slist_ns_s cn63xx;
-       struct cvmx_sli_pkt_slist_ns_s cn63xxp1;
-       struct cvmx_sli_pkt_slist_ns_s cn66xx;
-       struct cvmx_sli_pkt_slist_ns_s cn68xx;
-       struct cvmx_sli_pkt_slist_ns_s cn68xxp1;
-       struct cvmx_sli_pkt_slist_ns_s cnf71xx;
-};
-
-union cvmx_sli_pkt_slist_ror {
-       uint64_t u64;
-       struct cvmx_sli_pkt_slist_ror_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t ror:32;
-#else
-               uint64_t ror:32;
-               uint64_t reserved_32_63:32;
-#endif
-       } s;
-       struct cvmx_sli_pkt_slist_ror_s cn61xx;
-       struct cvmx_sli_pkt_slist_ror_s cn63xx;
-       struct cvmx_sli_pkt_slist_ror_s cn63xxp1;
-       struct cvmx_sli_pkt_slist_ror_s cn66xx;
-       struct cvmx_sli_pkt_slist_ror_s cn68xx;
-       struct cvmx_sli_pkt_slist_ror_s cn68xxp1;
-       struct cvmx_sli_pkt_slist_ror_s cnf71xx;
-};
-
-union cvmx_sli_pkt_time_int {
-       uint64_t u64;
-       struct cvmx_sli_pkt_time_int_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t port:32;
-#else
-               uint64_t port:32;
-               uint64_t reserved_32_63:32;
-#endif
-       } s;
-       struct cvmx_sli_pkt_time_int_s cn61xx;
-       struct cvmx_sli_pkt_time_int_s cn63xx;
-       struct cvmx_sli_pkt_time_int_s cn63xxp1;
-       struct cvmx_sli_pkt_time_int_s cn66xx;
-       struct cvmx_sli_pkt_time_int_s cn68xx;
-       struct cvmx_sli_pkt_time_int_s cn68xxp1;
-       struct cvmx_sli_pkt_time_int_s cnf71xx;
-};
-
-union cvmx_sli_pkt_time_int_enb {
-       uint64_t u64;
-       struct cvmx_sli_pkt_time_int_enb_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t port:32;
-#else
-               uint64_t port:32;
-               uint64_t reserved_32_63:32;
-#endif
-       } s;
-       struct cvmx_sli_pkt_time_int_enb_s cn61xx;
-       struct cvmx_sli_pkt_time_int_enb_s cn63xx;
-       struct cvmx_sli_pkt_time_int_enb_s cn63xxp1;
-       struct cvmx_sli_pkt_time_int_enb_s cn66xx;
-       struct cvmx_sli_pkt_time_int_enb_s cn68xx;
-       struct cvmx_sli_pkt_time_int_enb_s cn68xxp1;
-       struct cvmx_sli_pkt_time_int_enb_s cnf71xx;
-};
-
-union cvmx_sli_portx_pkind {
-       uint64_t u64;
-       struct cvmx_sli_portx_pkind_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_25_63:39;
-               uint64_t rpk_enb:1;
-               uint64_t reserved_22_23:2;
-               uint64_t pkindr:6;
-               uint64_t reserved_14_15:2;
-               uint64_t bpkind:6;
-               uint64_t reserved_6_7:2;
-               uint64_t pkind:6;
-#else
-               uint64_t pkind:6;
-               uint64_t reserved_6_7:2;
-               uint64_t bpkind:6;
-               uint64_t reserved_14_15:2;
-               uint64_t pkindr:6;
-               uint64_t reserved_22_23:2;
-               uint64_t rpk_enb:1;
-               uint64_t reserved_25_63:39;
-#endif
-       } s;
-       struct cvmx_sli_portx_pkind_s cn68xx;
-       struct cvmx_sli_portx_pkind_cn68xxp1 {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_14_63:50;
-               uint64_t bpkind:6;
-               uint64_t reserved_6_7:2;
-               uint64_t pkind:6;
-#else
-               uint64_t pkind:6;
-               uint64_t reserved_6_7:2;
-               uint64_t bpkind:6;
-               uint64_t reserved_14_63:50;
-#endif
-       } cn68xxp1;
 };
 
 union cvmx_sli_s2m_portx_ctl {
        uint64_t u64;
        struct cvmx_sli_s2m_portx_ctl_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_5_63:59;
-               uint64_t wind_d:1;
-               uint64_t bar0_d:1;
-               uint64_t mrrs:3;
-#else
-               uint64_t mrrs:3;
-               uint64_t bar0_d:1;
-               uint64_t wind_d:1;
-               uint64_t reserved_5_63:59;
-#endif
-       } s;
-       struct cvmx_sli_s2m_portx_ctl_s cn61xx;
-       struct cvmx_sli_s2m_portx_ctl_s cn63xx;
-       struct cvmx_sli_s2m_portx_ctl_s cn63xxp1;
-       struct cvmx_sli_s2m_portx_ctl_s cn66xx;
-       struct cvmx_sli_s2m_portx_ctl_s cn68xx;
-       struct cvmx_sli_s2m_portx_ctl_s cn68xxp1;
-       struct cvmx_sli_s2m_portx_ctl_s cnf71xx;
-};
-
-union cvmx_sli_scratch_1 {
-       uint64_t u64;
-       struct cvmx_sli_scratch_1_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t data:64;
-#else
-               uint64_t data:64;
-#endif
-       } s;
-       struct cvmx_sli_scratch_1_s cn61xx;
-       struct cvmx_sli_scratch_1_s cn63xx;
-       struct cvmx_sli_scratch_1_s cn63xxp1;
-       struct cvmx_sli_scratch_1_s cn66xx;
-       struct cvmx_sli_scratch_1_s cn68xx;
-       struct cvmx_sli_scratch_1_s cn68xxp1;
-       struct cvmx_sli_scratch_1_s cnf71xx;
-};
-
-union cvmx_sli_scratch_2 {
-       uint64_t u64;
-       struct cvmx_sli_scratch_2_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t data:64;
-#else
-               uint64_t data:64;
-#endif
-       } s;
-       struct cvmx_sli_scratch_2_s cn61xx;
-       struct cvmx_sli_scratch_2_s cn63xx;
-       struct cvmx_sli_scratch_2_s cn63xxp1;
-       struct cvmx_sli_scratch_2_s cn66xx;
-       struct cvmx_sli_scratch_2_s cn68xx;
-       struct cvmx_sli_scratch_2_s cn68xxp1;
-       struct cvmx_sli_scratch_2_s cnf71xx;
-};
-
-union cvmx_sli_state1 {
-       uint64_t u64;
-       struct cvmx_sli_state1_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t cpl1:12;
-               uint64_t cpl0:12;
-               uint64_t arb:1;
-               uint64_t csr:39;
-#else
-               uint64_t csr:39;
-               uint64_t arb:1;
-               uint64_t cpl0:12;
-               uint64_t cpl1:12;
-#endif
-       } s;
-       struct cvmx_sli_state1_s cn61xx;
-       struct cvmx_sli_state1_s cn63xx;
-       struct cvmx_sli_state1_s cn63xxp1;
-       struct cvmx_sli_state1_s cn66xx;
-       struct cvmx_sli_state1_s cn68xx;
-       struct cvmx_sli_state1_s cn68xxp1;
-       struct cvmx_sli_state1_s cnf71xx;
-};
-
-union cvmx_sli_state2 {
-       uint64_t u64;
-       struct cvmx_sli_state2_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_56_63:8;
-               uint64_t nnp1:8;
-               uint64_t reserved_47_47:1;
-               uint64_t rac:1;
-               uint64_t csm1:15;
-               uint64_t csm0:15;
-               uint64_t nnp0:8;
-               uint64_t nnd:8;
-#else
-               uint64_t nnd:8;
-               uint64_t nnp0:8;
-               uint64_t csm0:15;
-               uint64_t csm1:15;
-               uint64_t rac:1;
-               uint64_t reserved_47_47:1;
-               uint64_t nnp1:8;
-               uint64_t reserved_56_63:8;
-#endif
-       } s;
-       struct cvmx_sli_state2_s cn61xx;
-       struct cvmx_sli_state2_s cn63xx;
-       struct cvmx_sli_state2_s cn63xxp1;
-       struct cvmx_sli_state2_s cn66xx;
-       struct cvmx_sli_state2_s cn68xx;
-       struct cvmx_sli_state2_s cn68xxp1;
-       struct cvmx_sli_state2_s cnf71xx;
-};
-
-union cvmx_sli_state3 {
-       uint64_t u64;
-       struct cvmx_sli_state3_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_56_63:8;
-               uint64_t psm1:15;
-               uint64_t psm0:15;
-               uint64_t nsm1:13;
-               uint64_t nsm0:13;
-#else
-               uint64_t nsm0:13;
-               uint64_t nsm1:13;
-               uint64_t psm0:15;
-               uint64_t psm1:15;
-               uint64_t reserved_56_63:8;
-#endif
-       } s;
-       struct cvmx_sli_state3_s cn61xx;
-       struct cvmx_sli_state3_s cn63xx;
-       struct cvmx_sli_state3_s cn63xxp1;
-       struct cvmx_sli_state3_s cn66xx;
-       struct cvmx_sli_state3_s cn68xx;
-       struct cvmx_sli_state3_s cn68xxp1;
-       struct cvmx_sli_state3_s cnf71xx;
-};
-
-union cvmx_sli_tx_pipe {
-       uint64_t u64;
-       struct cvmx_sli_tx_pipe_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_24_63:40;
-               uint64_t nump:8;
-               uint64_t reserved_7_15:9;
-               uint64_t base:7;
-#else
-               uint64_t base:7;
-               uint64_t reserved_7_15:9;
-               uint64_t nump:8;
-               uint64_t reserved_24_63:40;
-#endif
+               __BITFIELD_FIELD(uint64_t reserved_5_63:59,
+               __BITFIELD_FIELD(uint64_t wind_d:1,
+               __BITFIELD_FIELD(uint64_t bar0_d:1,
+               __BITFIELD_FIELD(uint64_t mrrs:3,
+               ;))))
        } s;
-       struct cvmx_sli_tx_pipe_s cn68xx;
-       struct cvmx_sli_tx_pipe_s cn68xxp1;
 };
 
-union cvmx_sli_win_rd_addr {
-       uint64_t u64;
-       struct cvmx_sli_win_rd_addr_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_51_63:13;
-               uint64_t ld_cmd:2;
-               uint64_t iobit:1;
-               uint64_t rd_addr:48;
-#else
-               uint64_t rd_addr:48;
-               uint64_t iobit:1;
-               uint64_t ld_cmd:2;
-               uint64_t reserved_51_63:13;
-#endif
-       } s;
-       struct cvmx_sli_win_rd_addr_s cn61xx;
-       struct cvmx_sli_win_rd_addr_s cn63xx;
-       struct cvmx_sli_win_rd_addr_s cn63xxp1;
-       struct cvmx_sli_win_rd_addr_s cn66xx;
-       struct cvmx_sli_win_rd_addr_s cn68xx;
-       struct cvmx_sli_win_rd_addr_s cn68xxp1;
-       struct cvmx_sli_win_rd_addr_s cnf71xx;
-};
-
-union cvmx_sli_win_rd_data {
-       uint64_t u64;
-       struct cvmx_sli_win_rd_data_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t rd_data:64;
-#else
-               uint64_t rd_data:64;
-#endif
-       } s;
-       struct cvmx_sli_win_rd_data_s cn61xx;
-       struct cvmx_sli_win_rd_data_s cn63xx;
-       struct cvmx_sli_win_rd_data_s cn63xxp1;
-       struct cvmx_sli_win_rd_data_s cn66xx;
-       struct cvmx_sli_win_rd_data_s cn68xx;
-       struct cvmx_sli_win_rd_data_s cn68xxp1;
-       struct cvmx_sli_win_rd_data_s cnf71xx;
-};
-
-union cvmx_sli_win_wr_addr {
-       uint64_t u64;
-       struct cvmx_sli_win_wr_addr_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_49_63:15;
-               uint64_t iobit:1;
-               uint64_t wr_addr:45;
-               uint64_t reserved_0_2:3;
-#else
-               uint64_t reserved_0_2:3;
-               uint64_t wr_addr:45;
-               uint64_t iobit:1;
-               uint64_t reserved_49_63:15;
-#endif
-       } s;
-       struct cvmx_sli_win_wr_addr_s cn61xx;
-       struct cvmx_sli_win_wr_addr_s cn63xx;
-       struct cvmx_sli_win_wr_addr_s cn63xxp1;
-       struct cvmx_sli_win_wr_addr_s cn66xx;
-       struct cvmx_sli_win_wr_addr_s cn68xx;
-       struct cvmx_sli_win_wr_addr_s cn68xxp1;
-       struct cvmx_sli_win_wr_addr_s cnf71xx;
-};
-
-union cvmx_sli_win_wr_data {
-       uint64_t u64;
-       struct cvmx_sli_win_wr_data_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t wr_data:64;
-#else
-               uint64_t wr_data:64;
-#endif
-       } s;
-       struct cvmx_sli_win_wr_data_s cn61xx;
-       struct cvmx_sli_win_wr_data_s cn63xx;
-       struct cvmx_sli_win_wr_data_s cn63xxp1;
-       struct cvmx_sli_win_wr_data_s cn66xx;
-       struct cvmx_sli_win_wr_data_s cn68xx;
-       struct cvmx_sli_win_wr_data_s cn68xxp1;
-       struct cvmx_sli_win_wr_data_s cnf71xx;
-};
-
-union cvmx_sli_win_wr_mask {
-       uint64_t u64;
-       struct cvmx_sli_win_wr_mask_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_8_63:56;
-               uint64_t wr_mask:8;
-#else
-               uint64_t wr_mask:8;
-               uint64_t reserved_8_63:56;
-#endif
-       } s;
-       struct cvmx_sli_win_wr_mask_s cn61xx;
-       struct cvmx_sli_win_wr_mask_s cn63xx;
-       struct cvmx_sli_win_wr_mask_s cn63xxp1;
-       struct cvmx_sli_win_wr_mask_s cn66xx;
-       struct cvmx_sli_win_wr_mask_s cn68xx;
-       struct cvmx_sli_win_wr_mask_s cn68xxp1;
-       struct cvmx_sli_win_wr_mask_s cnf71xx;
-};
-
-union cvmx_sli_window_ctl {
+union cvmx_sli_mem_access_subidx {
        uint64_t u64;
-       struct cvmx_sli_window_ctl_s {
-#ifdef __BIG_ENDIAN_BITFIELD
-               uint64_t reserved_32_63:32;
-               uint64_t time:32;
-#else
-               uint64_t time:32;
-               uint64_t reserved_32_63:32;
-#endif
+       struct cvmx_sli_mem_access_subidx_s {
+               __BITFIELD_FIELD(uint64_t reserved_43_63:21,
+               __BITFIELD_FIELD(uint64_t zero:1,
+               __BITFIELD_FIELD(uint64_t port:3,
+               __BITFIELD_FIELD(uint64_t nmerge:1,
+               __BITFIELD_FIELD(uint64_t esr:2,
+               __BITFIELD_FIELD(uint64_t esw:2,
+               __BITFIELD_FIELD(uint64_t wtype:2,
+               __BITFIELD_FIELD(uint64_t rtype:2,
+               __BITFIELD_FIELD(uint64_t ba:30,
+               ;)))))))))
        } s;
-       struct cvmx_sli_window_ctl_s cn61xx;
-       struct cvmx_sli_window_ctl_s cn63xx;
-       struct cvmx_sli_window_ctl_s cn63xxp1;
-       struct cvmx_sli_window_ctl_s cn66xx;
-       struct cvmx_sli_window_ctl_s cn68xx;
-       struct cvmx_sli_window_ctl_s cn68xxp1;
-       struct cvmx_sli_window_ctl_s cnf71xx;
+       struct cvmx_sli_mem_access_subidx_cn68xx {
+               __BITFIELD_FIELD(uint64_t reserved_43_63:21,
+               __BITFIELD_FIELD(uint64_t zero:1,
+               __BITFIELD_FIELD(uint64_t port:3,
+               __BITFIELD_FIELD(uint64_t nmerge:1,
+               __BITFIELD_FIELD(uint64_t esr:2,
+               __BITFIELD_FIELD(uint64_t esw:2,
+               __BITFIELD_FIELD(uint64_t wtype:2,
+               __BITFIELD_FIELD(uint64_t rtype:2,
+               __BITFIELD_FIELD(uint64_t ba:28,
+               __BITFIELD_FIELD(uint64_t reserved_0_1:2,
+               ;))))))))))
+       } cn68xx;
 };
 
 #endif
index 2530e8731c8abd09cf4e438156c43881da60494f..9742202f2a326c45c504de6d77b51eb523421c0c 100644 (file)
@@ -4,7 +4,7 @@
  * Contact: support@caviumnetworks.com
  * This file is part of the OCTEON SDK
  *
- * Copyright (c) 2003-2008 Cavium Networks
+ * Copyright (c) 2003-2017 Cavium, Inc.
  *
  * This file is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License, Version 2, as
@@ -62,7 +62,6 @@ enum cvmx_mips_space {
 #include <asm/octeon/cvmx-iob-defs.h>
 #include <asm/octeon/cvmx-ipd-defs.h>
 #include <asm/octeon/cvmx-l2c-defs.h>
-#include <asm/octeon/cvmx-l2d-defs.h>
 #include <asm/octeon/cvmx-l2t-defs.h>
 #include <asm/octeon/cvmx-led-defs.h>
 #include <asm/octeon/cvmx-mio-defs.h>
index 30d1129d86248444fc7065fe99bd26c8f5111d0e..1000c1b4c875af4f0d34286c94ab49613569e90a 100644 (file)
@@ -110,10 +110,7 @@ extern unsigned long PCIBIOS_MIN_MEM;
 extern void pcibios_set_master(struct pci_dev *dev);
 
 #define HAVE_PCI_MMAP
-
-extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
-       enum pci_mmap_state mmap_state, int write_combine);
-
+#define ARCH_GENERIC_PCI_MMAP_RESOURCE
 #define HAVE_ARCH_PCI_RESOURCE_TO_USER
 
 /*
index a8705f6c81808f786076d93909d3a34fc2f637d5..a1bdb1ea523479c62d4b3f38206910276339699d 100644 (file)
@@ -110,6 +110,32 @@ static inline void pmd_free(struct mm_struct *mm, pmd_t *pmd)
 
 #endif
 
+#ifndef __PAGETABLE_PUD_FOLDED
+
+static inline pud_t *pud_alloc_one(struct mm_struct *mm, unsigned long address)
+{
+       pud_t *pud;
+
+       pud = (pud_t *) __get_free_pages(GFP_KERNEL|__GFP_REPEAT, PUD_ORDER);
+       if (pud)
+               pud_init((unsigned long)pud, (unsigned long)invalid_pmd_table);
+       return pud;
+}
+
+static inline void pud_free(struct mm_struct *mm, pud_t *pud)
+{
+       free_pages((unsigned long)pud, PUD_ORDER);
+}
+
+static inline void pgd_populate(struct mm_struct *mm, pgd_t *pgd, pud_t *pud)
+{
+       set_pgd(pgd, __pgd((unsigned long)pud));
+}
+
+#define __pud_free_tlb(tlb, x, addr)   pud_free((tlb)->mm, x)
+
+#endif /* __PAGETABLE_PUD_FOLDED */
+
 #define check_pgt_cache()      do { } while (0)
 
 extern void pagetable_init(void);
index 130a2a6c153156bd311e6646bbfd3b92fc6f7228..67fe6dc5211c027a76af9aa54615c6ba53002e5b 100644 (file)
@@ -20,7 +20,7 @@
 #define __ARCH_USE_5LEVEL_HACK
 #if defined(CONFIG_PAGE_SIZE_64KB) && !defined(CONFIG_MIPS_VA_BITS_48)
 #include <asm-generic/pgtable-nopmd.h>
-#else
+#elif !(defined(CONFIG_PAGE_SIZE_4KB) && defined(CONFIG_MIPS_VA_BITS_48))
 #include <asm-generic/pgtable-nopud.h>
 #endif
 
 #define PMD_SIZE       (1UL << PMD_SHIFT)
 #define PMD_MASK       (~(PMD_SIZE-1))
 
+# ifdef __PAGETABLE_PUD_FOLDED
+# define PGDIR_SHIFT   (PMD_SHIFT + (PAGE_SHIFT + PMD_ORDER - 3))
+# endif
+#endif
 
-#define PGDIR_SHIFT    (PMD_SHIFT + (PAGE_SHIFT + PMD_ORDER - 3))
+#ifndef __PAGETABLE_PUD_FOLDED
+#define PUD_SHIFT      (PMD_SHIFT + (PAGE_SHIFT + PMD_ORDER - 3))
+#define PUD_SIZE       (1UL << PUD_SHIFT)
+#define PUD_MASK       (~(PUD_SIZE-1))
+#define PGDIR_SHIFT    (PUD_SHIFT + (PAGE_SHIFT + PUD_ORDER - 3))
 #endif
+
 #define PGDIR_SIZE     (1UL << PGDIR_SHIFT)
 #define PGDIR_MASK     (~(PGDIR_SIZE-1))
 
  * of virtual address space.
  */
 #ifdef CONFIG_PAGE_SIZE_4KB
-#define PGD_ORDER              1
-#define PUD_ORDER              aieeee_attempt_to_allocate_pud
+# ifdef CONFIG_MIPS_VA_BITS_48
+#  define PGD_ORDER            0
+#  define PUD_ORDER            0
+# else
+#  define PGD_ORDER            1
+#  define PUD_ORDER            aieeee_attempt_to_allocate_pud
+# endif
 #define PMD_ORDER              0
 #define PTE_ORDER              0
 #endif
 #endif
 
 #define PTRS_PER_PGD   ((PAGE_SIZE << PGD_ORDER) / sizeof(pgd_t))
+#ifndef __PAGETABLE_PUD_FOLDED
+#define PTRS_PER_PUD   ((PAGE_SIZE << PUD_ORDER) / sizeof(pud_t))
+#endif
 #ifndef __PAGETABLE_PMD_FOLDED
 #define PTRS_PER_PMD   ((PAGE_SIZE << PMD_ORDER) / sizeof(pmd_t))
 #endif
 #define VMALLOC_START          (MAP_BASE + (2 * PAGE_SIZE))
 #define VMALLOC_END    \
        (MAP_BASE + \
-        min(PTRS_PER_PGD * PTRS_PER_PMD * PTRS_PER_PTE * PAGE_SIZE, \
+        min(PTRS_PER_PGD * PTRS_PER_PUD * PTRS_PER_PMD * PTRS_PER_PTE * PAGE_SIZE, \
             (1UL << cpu_vmbits)) - (1UL << 32))
 
 #if defined(CONFIG_MODULES) && defined(KBUILD_64BIT_SYM32) && \
 #define pmd_ERROR(e) \
        printk("%s:%d: bad pmd %016lx.\n", __FILE__, __LINE__, pmd_val(e))
 #endif
+#ifndef __PAGETABLE_PUD_FOLDED
+#define pud_ERROR(e) \
+       printk("%s:%d: bad pud %016lx.\n", __FILE__, __LINE__, pud_val(e))
+#endif
 #define pgd_ERROR(e) \
        printk("%s:%d: bad pgd %016lx.\n", __FILE__, __LINE__, pgd_val(e))
 
 extern pte_t invalid_pte_table[PTRS_PER_PTE];
 extern pte_t empty_bad_page_table[PTRS_PER_PTE];
 
+#ifndef __PAGETABLE_PUD_FOLDED
+/*
+ * For 4-level pagetables we defines these ourselves, for 3-level the
+ * definitions are below, for 2-level the
+ * definitions are supplied by <asm-generic/pgtable-nopmd.h>.
+ */
+typedef struct { unsigned long pud; } pud_t;
+#define pud_val(x)     ((x).pud)
+#define __pud(x)       ((pud_t) { (x) })
+
+extern pud_t invalid_pud_table[PTRS_PER_PUD];
+
+/*
+ * Empty pgd entries point to the invalid_pud_table.
+ */
+static inline int pgd_none(pgd_t pgd)
+{
+       return pgd_val(pgd) == (unsigned long)invalid_pud_table;
+}
+
+static inline int pgd_bad(pgd_t pgd)
+{
+       if (unlikely(pgd_val(pgd) & ~PAGE_MASK))
+               return 1;
+
+       return 0;
+}
+
+static inline int pgd_present(pgd_t pgd)
+{
+       return pgd_val(pgd) != (unsigned long)invalid_pud_table;
+}
+
+static inline void pgd_clear(pgd_t *pgdp)
+{
+       pgd_val(*pgdp) = (unsigned long)invalid_pud_table;
+}
+
+#define pud_index(address)     (((address) >> PUD_SHIFT) & (PTRS_PER_PUD - 1))
+
+static inline unsigned long pgd_page_vaddr(pgd_t pgd)
+{
+       return pgd_val(pgd);
+}
+
+static inline pud_t *pud_offset(pgd_t *pgd, unsigned long address)
+{
+       return (pud_t *)pgd_page_vaddr(*pgd) + pud_index(address);
+}
+
+static inline void set_pgd(pgd_t *pgd, pgd_t pgdval)
+{
+       *pgd = pgdval;
+}
+
+#endif
 
 #ifndef __PAGETABLE_PMD_FOLDED
 /*
@@ -281,6 +358,7 @@ static inline pmd_t *pmd_offset(pud_t * pud, unsigned long address)
  * Initialize a new pgd / pmd table with invalid pointers.
  */
 extern void pgd_init(unsigned long page);
+extern void pud_init(unsigned long page, unsigned long pagetable);
 extern void pmd_init(unsigned long page, unsigned long pagetable);
 
 /*
index e9a9e2ade1d216db0d0260b2a796b50b334518e3..3748f4d120a5a1ec0414ca338edf283b47d3561b 100644 (file)
 #define UASM_EXPORT_SYMBOL(sym)
 #endif
 
-#define _UASM_ISA_CLASSIC      0
-#define _UASM_ISA_MICROMIPS    1
-
-#ifndef UASM_ISA
-#ifdef CONFIG_CPU_MICROMIPS
-#define UASM_ISA       _UASM_ISA_MICROMIPS
-#else
-#define UASM_ISA       _UASM_ISA_CLASSIC
-#endif
-#endif
-
-#if (UASM_ISA == _UASM_ISA_CLASSIC)
-#ifdef CONFIG_CPU_MICROMIPS
-#define ISAOPC(op)     CL_uasm_i##op
-#define ISAFUNC(x)     CL_##x
-#else
-#define ISAOPC(op)     uasm_i##op
-#define ISAFUNC(x)     x
-#endif
-#elif (UASM_ISA == _UASM_ISA_MICROMIPS)
-#ifdef CONFIG_CPU_MICROMIPS
-#define ISAOPC(op)     uasm_i##op
-#define ISAFUNC(x)     x
-#else
-#define ISAOPC(op)     MM_uasm_i##op
-#define ISAFUNC(x)     MM_##x
-#endif
-#else
-#error Unsupported micro-assembler ISA!!!
-#endif
-
 #define Ip_u1u2u3(op)                                                  \
-void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c)
+void uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c)
 
 #define Ip_u2u1u3(op)                                                  \
-void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c)
+void uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c)
 
 #define Ip_u3u2u1(op)                                                  \
-void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c)
+void uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c)
 
 #define Ip_u3u1u2(op)                                                  \
-void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c)
+void uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c)
 
 #define Ip_u1u2s3(op)                                                  \
-void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, signed int c)
+void uasm_i##op(u32 **buf, unsigned int a, unsigned int b, signed int c)
 
 #define Ip_u2s3u1(op)                                                  \
-void ISAOPC(op)(u32 **buf, unsigned int a, signed int b, unsigned int c)
+void uasm_i##op(u32 **buf, unsigned int a, signed int b, unsigned int c)
 
 #define Ip_s3s1s2(op)                                                  \
-void ISAOPC(op)(u32 **buf, int a, int b, int c)
+void uasm_i##op(u32 **buf, int a, int b, int c)
 
 #define Ip_u2u1s3(op)                                                  \
-void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, signed int c)
+void uasm_i##op(u32 **buf, unsigned int a, unsigned int b, signed int c)
 
 #define Ip_u2u1msbu3(op)                                               \
-void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b, unsigned int c, \
+void uasm_i##op(u32 **buf, unsigned int a, unsigned int b, unsigned int c, \
           unsigned int d)
 
 #define Ip_u1u2(op)                                                    \
-void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b)
+void uasm_i##op(u32 **buf, unsigned int a, unsigned int b)
 
 #define Ip_u2u1(op)                                                    \
-void ISAOPC(op)(u32 **buf, unsigned int a, unsigned int b)
+void uasm_i##op(u32 **buf, unsigned int a, unsigned int b)
 
 #define Ip_u1s2(op)                                                    \
-void ISAOPC(op)(u32 **buf, unsigned int a, signed int b)
+void uasm_i##op(u32 **buf, unsigned int a, signed int b)
 
-#define Ip_u1(op) void ISAOPC(op)(u32 **buf, unsigned int a)
+#define Ip_u1(op) void uasm_i##op(u32 **buf, unsigned int a)
 
-#define Ip_0(op) void ISAOPC(op)(u32 **buf)
+#define Ip_0(op) void uasm_i##op(u32 **buf)
 
 Ip_u2u1s3(_addiu);
 Ip_u3u1u2(_addu);
@@ -138,6 +107,7 @@ Ip_u2s3u1(_lb);
 Ip_u2s3u1(_ld);
 Ip_u3u1u2(_ldx);
 Ip_u2s3u1(_lh);
+Ip_u2s3u1(_lhu);
 Ip_u2s3u1(_ll);
 Ip_u2s3u1(_lld);
 Ip_u1s2(_lui);
@@ -190,20 +160,20 @@ struct uasm_label {
        int lab;
 };
 
-void ISAFUNC(uasm_build_label)(struct uasm_label **lab, u32 *addr,
+void uasm_build_label(struct uasm_label **lab, u32 *addr,
                        int lid);
 #ifdef CONFIG_64BIT
-int ISAFUNC(uasm_in_compat_space_p)(long addr);
+int uasm_in_compat_space_p(long addr);
 #endif
-int ISAFUNC(uasm_rel_hi)(long val);
-int ISAFUNC(uasm_rel_lo)(long val);
-void ISAFUNC(UASM_i_LA_mostly)(u32 **buf, unsigned int rs, long addr);
-void ISAFUNC(UASM_i_LA)(u32 **buf, unsigned int rs, long addr);
+int uasm_rel_hi(long val);
+int uasm_rel_lo(long val);
+void UASM_i_LA_mostly(u32 **buf, unsigned int rs, long addr);
+void UASM_i_LA(u32 **buf, unsigned int rs, long addr);
 
 #define UASM_L_LA(lb)                                                  \
-static inline void ISAFUNC(uasm_l##lb)(struct uasm_label **lab, u32 *addr) \
+static inline void uasm_l##lb(struct uasm_label **lab, u32 *addr)      \
 {                                                                      \
-       ISAFUNC(uasm_build_label)(lab, addr, label##lb);                \
+       uasm_build_label(lab, addr, label##lb);                         \
 }
 
 /* convenience macros for instructions */
@@ -255,27 +225,27 @@ static inline void uasm_i_drotr_safe(u32 **p, unsigned int a1,
                                     unsigned int a2, unsigned int a3)
 {
        if (a3 < 32)
-               ISAOPC(_drotr)(p, a1, a2, a3);
+               uasm_i_drotr(p, a1, a2, a3);
        else
-               ISAOPC(_drotr32)(p, a1, a2, a3 - 32);
+               uasm_i_drotr32(p, a1, a2, a3 - 32);
 }
 
 static inline void uasm_i_dsll_safe(u32 **p, unsigned int a1,
                                    unsigned int a2, unsigned int a3)
 {
        if (a3 < 32)
-               ISAOPC(_dsll)(p, a1, a2, a3);
+               uasm_i_dsll(p, a1, a2, a3);
        else
-               ISAOPC(_dsll32)(p, a1, a2, a3 - 32);
+               uasm_i_dsll32(p, a1, a2, a3 - 32);
 }
 
 static inline void uasm_i_dsrl_safe(u32 **p, unsigned int a1,
                                    unsigned int a2, unsigned int a3)
 {
        if (a3 < 32)
-               ISAOPC(_dsrl)(p, a1, a2, a3);
+               uasm_i_dsrl(p, a1, a2, a3);
        else
-               ISAOPC(_dsrl32)(p, a1, a2, a3 - 32);
+               uasm_i_dsrl32(p, a1, a2, a3 - 32);
 }
 
 /* Handle relocations. */
index f2cf4146114679253195769bab10b859f41026d6..a0266feba9e6d996d5469ed18fd23df081a2ab38 100644 (file)
@@ -2,40 +2,3 @@
 include include/uapi/asm-generic/Kbuild.asm
 
 generic-y += ipcbuf.h
-
-header-y += auxvec.h
-header-y += bitfield.h
-header-y += bitsperlong.h
-header-y += break.h
-header-y += byteorder.h
-header-y += cachectl.h
-header-y += errno.h
-header-y += fcntl.h
-header-y += inst.h
-header-y += ioctl.h
-header-y += ioctls.h
-header-y += kvm_para.h
-header-y += mman.h
-header-y += msgbuf.h
-header-y += param.h
-header-y += poll.h
-header-y += posix_types.h
-header-y += ptrace.h
-header-y += resource.h
-header-y += sembuf.h
-header-y += setup.h
-header-y += sgidefs.h
-header-y += shmbuf.h
-header-y += sigcontext.h
-header-y += siginfo.h
-header-y += signal.h
-header-y += socket.h
-header-y += sockios.h
-header-y += stat.h
-header-y += statfs.h
-header-y += swab.h
-header-y += sysmips.h
-header-y += termbits.h
-header-y += termios.h
-header-y += types.h
-header-y += unistd.h
index 3382892544f064c63692110b724906fb9f0f9d23..1aba27786bd5ae6cc38784c0f05f196745e1cd3d 100644 (file)
@@ -34,6 +34,7 @@
 
 /* Hardware capabilities */
 unsigned int elf_hwcap __read_mostly;
+EXPORT_SYMBOL_GPL(elf_hwcap);
 
 /*
  * Get the FPU Implementation/Revision.
@@ -1955,6 +1956,12 @@ void cpu_probe(void)
        struct cpuinfo_mips *c = &current_cpu_data;
        unsigned int cpu = smp_processor_id();
 
+       /*
+        * Set a default elf platform, cpu probe may later
+        * overwrite it with a more precise value
+        */
+       set_elf_platform(cpu, "mips");
+
        c->processor_id = PRID_IMP_UNKNOWN;
        c->fpu_id       = FPIR_IMP_NONE;
        c->cputype      = CPU_UNKNOWN;
index 550e7d03090a18fc9cafd8d2ed77ffd89d927a3d..ae64c8f56a8c788450876bd368bc6dba8cab54a7 100644 (file)
@@ -1096,10 +1096,20 @@ repeat:
                }
                break;
 
-       case beql_op:
-       case bnel_op:
        case blezl_op:
        case bgtzl_op:
+               /*
+                * For BLEZL and BGTZL, rt field must be set to 0. If this
+                * is not the case, this may be an encoding of a MIPS R6
+                * instruction, so return to CPU execution if this occurs
+                */
+               if (MIPSInst_RT(inst)) {
+                       err = SIGILL;
+                       break;
+               }
+               /* fall through */
+       case beql_op:
+       case bnel_op:
                if (delay_slot(regs)) {
                        err = SIGILL;
                        break;
@@ -2329,6 +2339,8 @@ static int mipsr2_stats_clear_show(struct seq_file *s, void *unused)
        __this_cpu_write((mipsr2bremustats).bgezl, 0);
        __this_cpu_write((mipsr2bremustats).bltzll, 0);
        __this_cpu_write((mipsr2bremustats).bgezll, 0);
+       __this_cpu_write((mipsr2bremustats).bltzall, 0);
+       __this_cpu_write((mipsr2bremustats).bgezall, 0);
        __this_cpu_write((mipsr2bremustats).bltzal, 0);
        __this_cpu_write((mipsr2bremustats).bgezal, 0);
        __this_cpu_write((mipsr2bremustats).beql, 0);
index 9452b02ce0797e7ac890d1785f50907d9e747b5d..313a88b2973f673f0fac0998c36517fd2139504b 100644 (file)
@@ -618,7 +618,7 @@ static int mipspmu_event_init(struct perf_event *event)
                return -ENOENT;
        }
 
-       if (event->cpu >= nr_cpumask_bits ||
+       if ((unsigned int)event->cpu >= nr_cpumask_bits ||
            (event->cpu >= 0 && !cpu_online(event->cpu)))
                return -ENODEV;
 
index b68e10fc453d113dbdc67f11f2a7e59cb582d5a1..918d4c73e951d7815fc4063322c9ed8e493afb9f 100644 (file)
@@ -114,8 +114,8 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
 /*
  * Copy architecture-specific thread state
  */
-int copy_thread(unsigned long clone_flags, unsigned long usp,
-       unsigned long kthread_arg, struct task_struct *p)
+int copy_thread_tls(unsigned long clone_flags, unsigned long usp,
+       unsigned long kthread_arg, struct task_struct *p, unsigned long tls)
 {
        struct thread_info *ti = task_thread_info(p);
        struct pt_regs *childregs, *regs = current_pt_regs();
@@ -176,7 +176,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
        atomic_set(&p->thread.bd_emu_frame, BD_EMUFRAME_NONE);
 
        if (clone_flags & CLONE_SETTLS)
-               ti->tp_value = regs->regs[7];
+               ti->tp_value = tls;
 
        return 0;
 }
index 758577861523059a3e2e1f83e947121df094877a..7b386d54fd656cd6a2789fe79a72466ee8b0695b 100644 (file)
 /* preprocessor replaces the fp in ".set fp=64" with $30 otherwise */
 #undef fp
 
-/*
- * Offset to the current process status flags, the first 32 bytes of the
- * stack are not used.
- */
-#define ST_OFF (_THREAD_SIZE - 32 - PT_SIZE + PT_STATUS)
-
 #ifndef USE_ALTERNATE_RESUME_IMPL
 /*
  * task_struct *resume(task_struct *prev, task_struct *next,
index 795b4aaf89277be344e2e3e512a3642fb3085f5a..36954ddd0b9f5f4bb4dfe140484af61588476c13 100644 (file)
@@ -8,6 +8,7 @@
  * option) any later version.
  */
 
+#include <linux/cpu.h>
 #include <linux/delay.h>
 #include <linux/io.h>
 #include <linux/irqchip/mips-gic.h>
@@ -408,7 +409,6 @@ static int cps_cpu_disable(void)
        return 0;
 }
 
-static DECLARE_COMPLETION(cpu_death_chosen);
 static unsigned cpu_death_sibling;
 static enum {
        CPU_DEATH_HALT,
@@ -443,7 +443,7 @@ void play_dead(void)
        }
 
        /* This CPU has chosen its way out */
-       complete(&cpu_death_chosen);
+       (void)cpu_report_death();
 
        if (cpu_death == CPU_DEATH_HALT) {
                vpe_id = cpu_vpe_id(&cpu_data[cpu]);
@@ -492,8 +492,7 @@ static void cps_cpu_die(unsigned int cpu)
        int err;
 
        /* Wait for the cpu to choose its way out */
-       if (!wait_for_completion_timeout(&cpu_death_chosen,
-                                        msecs_to_jiffies(5000))) {
+       if (!cpu_wait_death(cpu, 5)) {
                pr_err("CPU%u: didn't offline\n", cpu);
                return;
        }
index e398cbc3d7767d50287d4c1e267b4e3e990efa4e..ed6b4df583ea0d420e9db7c75267fa419a4c4c8f 100644 (file)
@@ -83,6 +83,8 @@ static unsigned int __init smvp_vpe_init(unsigned int tc, unsigned int mvpconf0,
        if (tc != 0)
                smvp_copy_vpe_config();
 
+       cpu_data[ncpu].vpe_id = tc;
+
        return ncpu;
 }
 
@@ -114,49 +116,6 @@ static void __init smvp_tc_init(unsigned int tc, unsigned int mvpconf0)
        write_tc_c0_tchalt(TCHALT_H);
 }
 
-static void vsmp_send_ipi_single(int cpu, unsigned int action)
-{
-       int i;
-       unsigned long flags;
-       int vpflags;
-
-#ifdef CONFIG_MIPS_GIC
-       if (gic_present) {
-               mips_smp_send_ipi_single(cpu, action);
-               return;
-       }
-#endif
-       local_irq_save(flags);
-
-       vpflags = dvpe();       /* can't access the other CPU's registers whilst MVPE enabled */
-
-       switch (action) {
-       case SMP_CALL_FUNCTION:
-               i = C_SW1;
-               break;
-
-       case SMP_RESCHEDULE_YOURSELF:
-       default:
-               i = C_SW0;
-               break;
-       }
-
-       /* 1:1 mapping of vpe and tc... */
-       settc(cpu);
-       write_vpe_c0_cause(read_vpe_c0_cause() | i);
-       evpe(vpflags);
-
-       local_irq_restore(flags);
-}
-
-static void vsmp_send_ipi_mask(const struct cpumask *mask, unsigned int action)
-{
-       unsigned int i;
-
-       for_each_cpu(i, mask)
-               vsmp_send_ipi_single(i, action);
-}
-
 static void vsmp_init_secondary(void)
 {
 #ifdef CONFIG_MIPS_GIC
@@ -281,8 +240,8 @@ static void __init vsmp_prepare_cpus(unsigned int max_cpus)
 }
 
 struct plat_smp_ops vsmp_smp_ops = {
-       .send_ipi_single        = vsmp_send_ipi_single,
-       .send_ipi_mask          = vsmp_send_ipi_mask,
+       .send_ipi_single        = mips_smp_send_ipi_single,
+       .send_ipi_mask          = mips_smp_send_ipi_mask,
        .init_secondary         = vsmp_init_secondary,
        .smp_finish             = vsmp_smp_finish,
        .boot_secondary         = vsmp_boot_secondary,
index 6e71130549eae58140d1d4875da570f67bbf9854..aba1afb64b620a9922482ca12576e287463a511f 100644 (file)
@@ -261,16 +261,20 @@ int mips_smp_ipi_allocate(const struct cpumask *mask)
                ipidomain = irq_find_matching_host(NULL, DOMAIN_BUS_IPI);
 
        /*
-        * There are systems which only use IPI domains some of the time,
-        * depending upon configuration we don't know until runtime. An
-        * example is Malta where we may compile in support for GIC & the
-        * MT ASE, but run on a system which has multiple VPEs in a single
-        * core and doesn't include a GIC. Until all IPI implementations
-        * have been converted to use IPI domains the best we can do here
-        * is to return & hope some other code sets up the IPIs.
+        * There are systems which use IPI IRQ domains, but only have one
+        * registered when some runtime condition is met. For example a Malta
+        * kernel may include support for GIC & CPU interrupt controller IPI
+        * IRQ domains, but if run on a system with no GIC & no MT ASE then
+        * neither will be supported or registered.
+        *
+        * We only have a problem if we're actually using multiple CPUs so fail
+        * loudly if that is the case. Otherwise simply return, skipping IPI
+        * setup, if we're running with only a single CPU.
         */
-       if (!ipidomain)
+       if (!ipidomain) {
+               BUG_ON(num_present_cpus() > 1);
                return 0;
+       }
 
        virq = irq_reserve_ipi(ipidomain, mask);
        BUG_ON(!virq);
index b49e7bf9f95023fe5837b7d7ed317693ef8ac0a2..9681b5877140112393f414356f110ea74a53a6a1 100644 (file)
@@ -2256,8 +2256,8 @@ void set_handler(unsigned long offset, void *addr, unsigned long size)
        local_flush_icache_range(ebase + offset, ebase + offset + size);
 }
 
-static char panic_null_cerr[] =
-       "Trying to set NULL cache error exception handler";
+static const char panic_null_cerr[] =
+       "Trying to set NULL cache error exception handler\n";
 
 /*
  * Install uncached CPU exception handler.
index 0ddf3698b85dac2ebf8bc03e1bf8a089258b8b41..33728b7af4267b26902781ef2691a064536c49dd 100644 (file)
@@ -274,47 +274,6 @@ static void ltq_hw_irq_handler(struct irq_desc *desc)
        ltq_hw_irqdispatch(irq_desc_get_irq(desc) - 2);
 }
 
-#ifdef CONFIG_MIPS_MT_SMP
-void __init arch_init_ipiirq(int irq, struct irqaction *action)
-{
-       setup_irq(irq, action);
-       irq_set_handler(irq, handle_percpu_irq);
-}
-
-static void ltq_sw0_irqdispatch(void)
-{
-       do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ);
-}
-
-static void ltq_sw1_irqdispatch(void)
-{
-       do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ);
-}
-static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
-{
-       scheduler_ipi();
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
-{
-       generic_smp_call_function_interrupt();
-       return IRQ_HANDLED;
-}
-
-static struct irqaction irq_resched = {
-       .handler        = ipi_resched_interrupt,
-       .flags          = IRQF_PERCPU,
-       .name           = "IPI_resched"
-};
-
-static struct irqaction irq_call = {
-       .handler        = ipi_call_interrupt,
-       .flags          = IRQF_PERCPU,
-       .name           = "IPI_call"
-};
-#endif
-
 asmlinkage void plat_irq_dispatch(void)
 {
        unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
@@ -402,17 +361,6 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
                (MAX_IM * INT_NUM_IM_OFFSET) + MIPS_CPU_IRQ_CASCADE,
                &irq_domain_ops, 0);
 
-#if defined(CONFIG_MIPS_MT_SMP)
-       if (cpu_has_vint) {
-               pr_info("Setting up IPI vectored interrupts\n");
-               set_vi_handler(MIPS_CPU_IPI_RESCHED_IRQ, ltq_sw0_irqdispatch);
-               set_vi_handler(MIPS_CPU_IPI_CALL_IRQ, ltq_sw1_irqdispatch);
-       }
-       arch_init_ipiirq(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ,
-               &irq_resched);
-       arch_init_ipiirq(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ, &irq_call);
-#endif
-
 #ifndef CONFIG_MIPS_MT_SMP
        set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 |
                IE_IRQ3 | IE_IRQ4 | IE_IRQ5);
index a298ac93edcc01c00c3b05abc52d5b57340dbf79..f12fde10c8ad352b36c3be27ae8e021f6203b915 100644 (file)
@@ -439,6 +439,8 @@ int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
        union mips_instruction insn = (union mips_instruction)dec_insn.insn;
        unsigned int fcr31;
        unsigned int bit = 0;
+       unsigned int bit0;
+       union fpureg *fpr;
 
        switch (insn.i_format.opcode) {
        case spec_op:
@@ -706,14 +708,14 @@ int isBranchInstr(struct pt_regs *regs, struct mm_decoded_insn dec_insn,
                    ((insn.i_format.rs == bc1eqz_op) ||
                     (insn.i_format.rs == bc1nez_op))) {
                        bit = 0;
+                       fpr = &current->thread.fpu.fpr[insn.i_format.rt];
+                       bit0 = get_fpr32(fpr, 0) & 0x1;
                        switch (insn.i_format.rs) {
                        case bc1eqz_op:
-                               if (get_fpr32(&current->thread.fpu.fpr[insn.i_format.rt], 0) & 0x1)
-                                   bit = 1;
+                               bit = bit0 == 0;
                                break;
                        case bc1nez_op:
-                               if (!(get_fpr32(&current->thread.fpu.fpr[insn.i_format.rt], 0) & 0x1))
-                                   bit = 1;
+                               bit = bit0 != 0;
                                break;
                        }
                        if (bit)
index 3bef306cdfdbb85917ef390ac1696897532124e1..4f8f5bf46977a3c134ce47df543a3e8a540226f2 100644 (file)
@@ -267,19 +267,19 @@ do_sigbus:
        /* Kernel mode? Handle exceptions or die */
        if (!user_mode(regs))
                goto no_context;
-       else
+
        /*
         * Send a sigbus, regardless of whether we were in kernel
         * or user mode.
         */
 #if 0
-               printk("do_page_fault() #3: sending SIGBUS to %s for "
-                      "invalid %s\n%0*lx (epc == %0*lx, ra == %0*lx)\n",
-                      tsk->comm,
-                      write ? "write access to" : "read access from",
-                      field, address,
-                      field, (unsigned long) regs->cp0_epc,
-                      field, (unsigned long) regs->regs[31]);
+       printk("do_page_fault() #3: sending SIGBUS to %s for "
+              "invalid %s\n%0*lx (epc == %0*lx, ra == %0*lx)\n",
+              tsk->comm,
+              write ? "write access to" : "read access from",
+              field, address,
+              field, (unsigned long) regs->cp0_epc,
+              field, (unsigned long) regs->regs[31]);
 #endif
        current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f;
        tsk->thread.cp0_badvaddr = address;
index 3ca20283b31eaf3e9a35a165fe59ed298c5691e2..8ce2983a701526a5f1bdfd243ad61d8b80375b1d 100644 (file)
@@ -537,6 +537,9 @@ unsigned long pgd_current[NR_CPUS];
  * it in the linker script.
  */
 pgd_t swapper_pg_dir[_PTRS_PER_PGD] __section(.bss..swapper_pg_dir);
+#ifndef __PAGETABLE_PUD_FOLDED
+pud_t invalid_pud_table[PTRS_PER_PUD] __page_aligned_bss;
+#endif
 #ifndef __PAGETABLE_PMD_FOLDED
 pmd_t invalid_pmd_table[PTRS_PER_PMD] __page_aligned_bss;
 EXPORT_SYMBOL_GPL(invalid_pmd_table);
index 0ae7b28b4db5d992c11a79e05c76b39cb9a41dcf..6fd6e96fdebb61e3616bd80fe6c33870152d56ed 100644 (file)
@@ -19,10 +19,12 @@ void pgd_init(unsigned long page)
        unsigned long *p, *end;
        unsigned long entry;
 
-#ifdef __PAGETABLE_PMD_FOLDED
-       entry = (unsigned long)invalid_pte_table;
-#else
+#if !defined(__PAGETABLE_PUD_FOLDED)
+       entry = (unsigned long)invalid_pud_table;
+#elif !defined(__PAGETABLE_PMD_FOLDED)
        entry = (unsigned long)invalid_pmd_table;
+#else
+       entry = (unsigned long)invalid_pte_table;
 #endif
 
        p = (unsigned long *) page;
@@ -64,6 +66,28 @@ void pmd_init(unsigned long addr, unsigned long pagetable)
 EXPORT_SYMBOL_GPL(pmd_init);
 #endif
 
+#ifndef __PAGETABLE_PUD_FOLDED
+void pud_init(unsigned long addr, unsigned long pagetable)
+{
+       unsigned long *p, *end;
+
+       p = (unsigned long *)addr;
+       end = p + PTRS_PER_PUD;
+
+       do {
+               p[0] = pagetable;
+               p[1] = pagetable;
+               p[2] = pagetable;
+               p[3] = pagetable;
+               p[4] = pagetable;
+               p += 8;
+               p[-3] = pagetable;
+               p[-2] = pagetable;
+               p[-1] = pagetable;
+       } while (p != end);
+}
+#endif
+
 pmd_t mk_pmd(struct page *page, pgprot_t prot)
 {
        pmd_t pmd;
@@ -87,6 +111,9 @@ void __init pagetable_init(void)
 
        /* Initialize the entire pgd.  */
        pgd_init((unsigned long)swapper_pg_dir);
+#ifndef __PAGETABLE_PUD_FOLDED
+       pud_init((unsigned long)invalid_pud_table, (unsigned long)invalid_pmd_table);
+#endif
 #ifndef __PAGETABLE_PMD_FOLDED
        pmd_init((unsigned long)invalid_pmd_table, (unsigned long)invalid_pte_table);
 #endif
index 4f642e07c2b198b3c9e46e3bc9f64bbe2bcb6606..ed1c5297547afb322344175bfab02b89a3fd0080 100644 (file)
@@ -865,6 +865,13 @@ void build_get_pmde64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
 
        uasm_i_andi(p, tmp, tmp, (PTRS_PER_PGD - 1)<<3);
        uasm_i_daddu(p, ptr, ptr, tmp); /* add in pgd offset */
+#ifndef __PAGETABLE_PUD_FOLDED
+       uasm_i_dmfc0(p, tmp, C0_BADVADDR); /* get faulting address */
+       uasm_i_ld(p, ptr, 0, ptr); /* get pud pointer */
+       uasm_i_dsrl_safe(p, tmp, tmp, PUD_SHIFT - 3); /* get pud offset in bytes */
+       uasm_i_andi(p, tmp, tmp, (PTRS_PER_PUD - 1) << 3);
+       uasm_i_daddu(p, ptr, ptr, tmp); /* add in pud offset */
+#endif
 #ifndef __PAGETABLE_PMD_FOLDED
        uasm_i_dmfc0(p, tmp, C0_BADVADDR); /* get faulting address */
        uasm_i_ld(p, ptr, 0, ptr); /* get pmd pointer */
@@ -1184,6 +1191,21 @@ build_fast_tlb_refill_handler (u32 **p, struct uasm_label **l,
                uasm_i_ld(p, LOC_PTEP, 0, ptr); /* get pmd pointer */
        }
 
+#ifndef __PAGETABLE_PUD_FOLDED
+       /* get pud offset in bytes */
+       uasm_i_dsrl_safe(p, scratch, tmp, PUD_SHIFT - 3);
+       uasm_i_andi(p, scratch, scratch, (PTRS_PER_PUD - 1) << 3);
+
+       if (use_lwx_insns()) {
+               UASM_i_LWX(p, ptr, scratch, ptr);
+       } else {
+               uasm_i_daddu(p, ptr, ptr, scratch); /* add in pmd offset */
+               UASM_i_LW(p, ptr, 0, ptr);
+       }
+       /* ptr contains a pointer to PMD entry */
+       /* tmp contains the address */
+#endif
+
 #ifndef __PAGETABLE_PMD_FOLDED
        /* get pmd offset in bytes */
        uasm_i_dsrl_safe(p, scratch, tmp, PMD_SHIFT - 3);
index 763d3f1edb8a4a90cd99728c0310d23e4f873daa..2277499fe6aec3276a117c353cb02f9fc907f545 100644 (file)
@@ -103,6 +103,7 @@ static struct insn insn_table[] = {
        { insn_ld,  M(ld_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
        { insn_ldx, M(spec3_op, 0, 0, 0, ldx_op, lx_op), RS | RT | RD },
        { insn_lh,  M(lh_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
+       { insn_lhu,  M(lhu_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
 #ifndef CONFIG_CPU_MIPSR6
        { insn_lld,  M(lld_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
        { insn_ll,  M(ll_op, 0, 0, 0, 0, 0),  RS | RT | SIMM },
index a82970442b8a4f575a3ea8a42b98840295c6d817..730363b59baca9da210188177d93a74bdc93fbf8 100644 (file)
@@ -61,7 +61,7 @@ enum opcode {
        insn_sllv, insn_slt, insn_sltiu, insn_sltu, insn_sra, insn_srl,
        insn_srlv, insn_subu, insn_sw, insn_sync, insn_syscall, insn_tlbp,
        insn_tlbr, insn_tlbwi, insn_tlbwr, insn_wait, insn_wsbh, insn_xor,
-       insn_xori, insn_yield, insn_lddir, insn_ldpte,
+       insn_xori, insn_yield, insn_lddir, insn_ldpte, insn_lhu,
 };
 
 struct insn {
@@ -297,6 +297,7 @@ I_u1(_jr)
 I_u2s3u1(_lb)
 I_u2s3u1(_ld)
 I_u2s3u1(_lh)
+I_u2s3u1(_lhu)
 I_u2s3u1(_ll)
 I_u2s3u1(_lld)
 I_u1s2(_lui)
@@ -349,7 +350,7 @@ I_u2u1u3(_lddir)
 
 #ifdef CONFIG_CPU_CAVIUM_OCTEON
 #include <asm/octeon/octeon.h>
-void ISAFUNC(uasm_i_pref)(u32 **buf, unsigned int a, signed int b,
+void uasm_i_pref(u32 **buf, unsigned int a, signed int b,
                            unsigned int c)
 {
        if (CAVIUM_OCTEON_DCACHE_PREFETCH_WAR && a <= 24 && a != 5)
@@ -361,26 +362,26 @@ void ISAFUNC(uasm_i_pref)(u32 **buf, unsigned int a, signed int b,
        else
                build_insn(buf, insn_pref, c, a, b);
 }
-UASM_EXPORT_SYMBOL(ISAFUNC(uasm_i_pref));
+UASM_EXPORT_SYMBOL(uasm_i_pref);
 #else
 I_u2s3u1(_pref)
 #endif
 
 /* Handle labels. */
-void ISAFUNC(uasm_build_label)(struct uasm_label **lab, u32 *addr, int lid)
+void uasm_build_label(struct uasm_label **lab, u32 *addr, int lid)
 {
        (*lab)->addr = addr;
        (*lab)->lab = lid;
        (*lab)++;
 }
-UASM_EXPORT_SYMBOL(ISAFUNC(uasm_build_label));
+UASM_EXPORT_SYMBOL(uasm_build_label);
 
-int ISAFUNC(uasm_in_compat_space_p)(long addr)
+int uasm_in_compat_space_p(long addr)
 {
        /* Is this address in 32bit compat space? */
        return addr == (int)addr;
 }
-UASM_EXPORT_SYMBOL(ISAFUNC(uasm_in_compat_space_p));
+UASM_EXPORT_SYMBOL(uasm_in_compat_space_p);
 
 static int uasm_rel_highest(long val)
 {
@@ -400,64 +401,64 @@ static int uasm_rel_higher(long val)
 #endif
 }
 
-int ISAFUNC(uasm_rel_hi)(long val)
+int uasm_rel_hi(long val)
 {
        return ((((val + 0x8000L) >> 16) & 0xffff) ^ 0x8000) - 0x8000;
 }
-UASM_EXPORT_SYMBOL(ISAFUNC(uasm_rel_hi));
+UASM_EXPORT_SYMBOL(uasm_rel_hi);
 
-int ISAFUNC(uasm_rel_lo)(long val)
+int uasm_rel_lo(long val)
 {
        return ((val & 0xffff) ^ 0x8000) - 0x8000;
 }
-UASM_EXPORT_SYMBOL(ISAFUNC(uasm_rel_lo));
+UASM_EXPORT_SYMBOL(uasm_rel_lo);
 
-void ISAFUNC(UASM_i_LA_mostly)(u32 **buf, unsigned int rs, long addr)
+void UASM_i_LA_mostly(u32 **buf, unsigned int rs, long addr)
 {
-       if (!ISAFUNC(uasm_in_compat_space_p)(addr)) {
-               ISAFUNC(uasm_i_lui)(buf, rs, uasm_rel_highest(addr));
+       if (!uasm_in_compat_space_p(addr)) {
+               uasm_i_lui(buf, rs, uasm_rel_highest(addr));
                if (uasm_rel_higher(addr))
-                       ISAFUNC(uasm_i_daddiu)(buf, rs, rs, uasm_rel_higher(addr));
-               if (ISAFUNC(uasm_rel_hi(addr))) {
-                       ISAFUNC(uasm_i_dsll)(buf, rs, rs, 16);
-                       ISAFUNC(uasm_i_daddiu)(buf, rs, rs,
-                                       ISAFUNC(uasm_rel_hi)(addr));
-                       ISAFUNC(uasm_i_dsll)(buf, rs, rs, 16);
+                       uasm_i_daddiu(buf, rs, rs, uasm_rel_higher(addr));
+               if (uasm_rel_hi(addr)) {
+                       uasm_i_dsll(buf, rs, rs, 16);
+                       uasm_i_daddiu(buf, rs, rs,
+                                       uasm_rel_hi(addr));
+                       uasm_i_dsll(buf, rs, rs, 16);
                } else
-                       ISAFUNC(uasm_i_dsll32)(buf, rs, rs, 0);
+                       uasm_i_dsll32(buf, rs, rs, 0);
        } else
-               ISAFUNC(uasm_i_lui)(buf, rs, ISAFUNC(uasm_rel_hi(addr)));
+               uasm_i_lui(buf, rs, uasm_rel_hi(addr));
 }
-UASM_EXPORT_SYMBOL(ISAFUNC(UASM_i_LA_mostly));
+UASM_EXPORT_SYMBOL(UASM_i_LA_mostly);
 
-void ISAFUNC(UASM_i_LA)(u32 **buf, unsigned int rs, long addr)
+void UASM_i_LA(u32 **buf, unsigned int rs, long addr)
 {
-       ISAFUNC(UASM_i_LA_mostly)(buf, rs, addr);
-       if (ISAFUNC(uasm_rel_lo(addr))) {
-               if (!ISAFUNC(uasm_in_compat_space_p)(addr))
-                       ISAFUNC(uasm_i_daddiu)(buf, rs, rs,
-                                       ISAFUNC(uasm_rel_lo(addr)));
+       UASM_i_LA_mostly(buf, rs, addr);
+       if (uasm_rel_lo(addr)) {
+               if (!uasm_in_compat_space_p(addr))
+                       uasm_i_daddiu(buf, rs, rs,
+                                       uasm_rel_lo(addr));
                else
-                       ISAFUNC(uasm_i_addiu)(buf, rs, rs,
-                                       ISAFUNC(uasm_rel_lo(addr)));
+                       uasm_i_addiu(buf, rs, rs,
+                                       uasm_rel_lo(addr));
        }
 }
-UASM_EXPORT_SYMBOL(ISAFUNC(UASM_i_LA));
+UASM_EXPORT_SYMBOL(UASM_i_LA);
 
 /* Handle relocations. */
-void ISAFUNC(uasm_r_mips_pc16)(struct uasm_reloc **rel, u32 *addr, int lid)
+void uasm_r_mips_pc16(struct uasm_reloc **rel, u32 *addr, int lid)
 {
        (*rel)->addr = addr;
        (*rel)->type = R_MIPS_PC16;
        (*rel)->lab = lid;
        (*rel)++;
 }
-UASM_EXPORT_SYMBOL(ISAFUNC(uasm_r_mips_pc16));
+UASM_EXPORT_SYMBOL(uasm_r_mips_pc16);
 
 static inline void __resolve_relocs(struct uasm_reloc *rel,
                                    struct uasm_label *lab);
 
-void ISAFUNC(uasm_resolve_relocs)(struct uasm_reloc *rel,
+void uasm_resolve_relocs(struct uasm_reloc *rel,
                                  struct uasm_label *lab)
 {
        struct uasm_label *l;
@@ -467,39 +468,39 @@ void ISAFUNC(uasm_resolve_relocs)(struct uasm_reloc *rel,
                        if (rel->lab == l->lab)
                                __resolve_relocs(rel, l);
 }
-UASM_EXPORT_SYMBOL(ISAFUNC(uasm_resolve_relocs));
+UASM_EXPORT_SYMBOL(uasm_resolve_relocs);
 
-void ISAFUNC(uasm_move_relocs)(struct uasm_reloc *rel, u32 *first, u32 *end,
+void uasm_move_relocs(struct uasm_reloc *rel, u32 *first, u32 *end,
                               long off)
 {
        for (; rel->lab != UASM_LABEL_INVALID; rel++)
                if (rel->addr >= first && rel->addr < end)
                        rel->addr += off;
 }
-UASM_EXPORT_SYMBOL(ISAFUNC(uasm_move_relocs));
+UASM_EXPORT_SYMBOL(uasm_move_relocs);
 
-void ISAFUNC(uasm_move_labels)(struct uasm_label *lab, u32 *first, u32 *end,
+void uasm_move_labels(struct uasm_label *lab, u32 *first, u32 *end,
                               long off)
 {
        for (; lab->lab != UASM_LABEL_INVALID; lab++)
                if (lab->addr >= first && lab->addr < end)
                        lab->addr += off;
 }
-UASM_EXPORT_SYMBOL(ISAFUNC(uasm_move_labels));
+UASM_EXPORT_SYMBOL(uasm_move_labels);
 
-void ISAFUNC(uasm_copy_handler)(struct uasm_reloc *rel, struct uasm_label *lab,
+void uasm_copy_handler(struct uasm_reloc *rel, struct uasm_label *lab,
                                u32 *first, u32 *end, u32 *target)
 {
        long off = (long)(target - first);
 
        memcpy(target, first, (end - first) * sizeof(u32));
 
-       ISAFUNC(uasm_move_relocs(rel, first, end, off));
-       ISAFUNC(uasm_move_labels(lab, first, end, off));
+       uasm_move_relocs(rel, first, end, off);
+       uasm_move_labels(lab, first, end, off);
 }
-UASM_EXPORT_SYMBOL(ISAFUNC(uasm_copy_handler));
+UASM_EXPORT_SYMBOL(uasm_copy_handler);
 
-int ISAFUNC(uasm_insn_has_bdelay)(struct uasm_reloc *rel, u32 *addr)
+int uasm_insn_has_bdelay(struct uasm_reloc *rel, u32 *addr)
 {
        for (; rel->lab != UASM_LABEL_INVALID; rel++) {
                if (rel->addr == addr
@@ -510,92 +511,92 @@ int ISAFUNC(uasm_insn_has_bdelay)(struct uasm_reloc *rel, u32 *addr)
 
        return 0;
 }
-UASM_EXPORT_SYMBOL(ISAFUNC(uasm_insn_has_bdelay));
+UASM_EXPORT_SYMBOL(uasm_insn_has_bdelay);
 
 /* Convenience functions for labeled branches. */
-void ISAFUNC(uasm_il_bltz)(u32 **p, struct uasm_reloc **r, unsigned int reg,
+void uasm_il_bltz(u32 **p, struct uasm_reloc **r, unsigned int reg,
                           int lid)
 {
        uasm_r_mips_pc16(r, *p, lid);
-       ISAFUNC(uasm_i_bltz)(p, reg, 0);
+       uasm_i_bltz(p, reg, 0);
 }
-UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bltz));
+UASM_EXPORT_SYMBOL(uasm_il_bltz);
 
-void ISAFUNC(uasm_il_b)(u32 **p, struct uasm_reloc **r, int lid)
+void uasm_il_b(u32 **p, struct uasm_reloc **r, int lid)
 {
        uasm_r_mips_pc16(r, *p, lid);
-       ISAFUNC(uasm_i_b)(p, 0);
+       uasm_i_b(p, 0);
 }
-UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_b));
+UASM_EXPORT_SYMBOL(uasm_il_b);
 
-void ISAFUNC(uasm_il_beq)(u32 **p, struct uasm_reloc **r, unsigned int r1,
+void uasm_il_beq(u32 **p, struct uasm_reloc **r, unsigned int r1,
                          unsigned int r2, int lid)
 {
        uasm_r_mips_pc16(r, *p, lid);
-       ISAFUNC(uasm_i_beq)(p, r1, r2, 0);
+       uasm_i_beq(p, r1, r2, 0);
 }
-UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_beq));
+UASM_EXPORT_SYMBOL(uasm_il_beq);
 
-void ISAFUNC(uasm_il_beqz)(u32 **p, struct uasm_reloc **r, unsigned int reg,
+void uasm_il_beqz(u32 **p, struct uasm_reloc **r, unsigned int reg,
                           int lid)
 {
        uasm_r_mips_pc16(r, *p, lid);
-       ISAFUNC(uasm_i_beqz)(p, reg, 0);
+       uasm_i_beqz(p, reg, 0);
 }
-UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_beqz));
+UASM_EXPORT_SYMBOL(uasm_il_beqz);
 
-void ISAFUNC(uasm_il_beqzl)(u32 **p, struct uasm_reloc **r, unsigned int reg,
+void uasm_il_beqzl(u32 **p, struct uasm_reloc **r, unsigned int reg,
                            int lid)
 {
        uasm_r_mips_pc16(r, *p, lid);
-       ISAFUNC(uasm_i_beqzl)(p, reg, 0);
+       uasm_i_beqzl(p, reg, 0);
 }
-UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_beqzl));
+UASM_EXPORT_SYMBOL(uasm_il_beqzl);
 
-void ISAFUNC(uasm_il_bne)(u32 **p, struct uasm_reloc **r, unsigned int reg1,
+void uasm_il_bne(u32 **p, struct uasm_reloc **r, unsigned int reg1,
                          unsigned int reg2, int lid)
 {
        uasm_r_mips_pc16(r, *p, lid);
-       ISAFUNC(uasm_i_bne)(p, reg1, reg2, 0);
+       uasm_i_bne(p, reg1, reg2, 0);
 }
-UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bne));
+UASM_EXPORT_SYMBOL(uasm_il_bne);
 
-void ISAFUNC(uasm_il_bnez)(u32 **p, struct uasm_reloc **r, unsigned int reg,
+void uasm_il_bnez(u32 **p, struct uasm_reloc **r, unsigned int reg,
                           int lid)
 {
        uasm_r_mips_pc16(r, *p, lid);
-       ISAFUNC(uasm_i_bnez)(p, reg, 0);
+       uasm_i_bnez(p, reg, 0);
 }
-UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bnez));
+UASM_EXPORT_SYMBOL(uasm_il_bnez);
 
-void ISAFUNC(uasm_il_bgezl)(u32 **p, struct uasm_reloc **r, unsigned int reg,
+void uasm_il_bgezl(u32 **p, struct uasm_reloc **r, unsigned int reg,
                            int lid)
 {
        uasm_r_mips_pc16(r, *p, lid);
-       ISAFUNC(uasm_i_bgezl)(p, reg, 0);
+       uasm_i_bgezl(p, reg, 0);
 }
-UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bgezl));
+UASM_EXPORT_SYMBOL(uasm_il_bgezl);
 
-void ISAFUNC(uasm_il_bgez)(u32 **p, struct uasm_reloc **r, unsigned int reg,
+void uasm_il_bgez(u32 **p, struct uasm_reloc **r, unsigned int reg,
                           int lid)
 {
        uasm_r_mips_pc16(r, *p, lid);
-       ISAFUNC(uasm_i_bgez)(p, reg, 0);
+       uasm_i_bgez(p, reg, 0);
 }
-UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bgez));
+UASM_EXPORT_SYMBOL(uasm_il_bgez);
 
-void ISAFUNC(uasm_il_bbit0)(u32 **p, struct uasm_reloc **r, unsigned int reg,
+void uasm_il_bbit0(u32 **p, struct uasm_reloc **r, unsigned int reg,
                            unsigned int bit, int lid)
 {
        uasm_r_mips_pc16(r, *p, lid);
-       ISAFUNC(uasm_i_bbit0)(p, reg, bit, 0);
+       uasm_i_bbit0(p, reg, bit, 0);
 }
-UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bbit0));
+UASM_EXPORT_SYMBOL(uasm_il_bbit0);
 
-void ISAFUNC(uasm_il_bbit1)(u32 **p, struct uasm_reloc **r, unsigned int reg,
+void uasm_il_bbit1(u32 **p, struct uasm_reloc **r, unsigned int reg,
                            unsigned int bit, int lid)
 {
        uasm_r_mips_pc16(r, *p, lid);
-       ISAFUNC(uasm_i_bbit1)(p, reg, bit, 0);
+       uasm_i_bbit1(p, reg, bit, 0);
 }
-UASM_EXPORT_SYMBOL(ISAFUNC(uasm_il_bbit1));
+UASM_EXPORT_SYMBOL(uasm_il_bbit1);
index 54f56d5a96c46ec8c3b2b1a6e8bcdc06dbf5e02a..b0f9b188e83359d18073e08e5ec3dd3105155d51 100644 (file)
@@ -145,56 +145,6 @@ static irqreturn_t corehi_handler(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-#ifdef CONFIG_MIPS_MT_SMP
-
-#define MIPS_CPU_IPI_RESCHED_IRQ 0     /* SW int 0 for resched */
-#define C_RESCHED C_SW0
-#define MIPS_CPU_IPI_CALL_IRQ 1                /* SW int 1 for resched */
-#define C_CALL C_SW1
-static int cpu_ipi_resched_irq, cpu_ipi_call_irq;
-
-static void ipi_resched_dispatch(void)
-{
-       do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_RESCHED_IRQ);
-}
-
-static void ipi_call_dispatch(void)
-{
-       do_IRQ(MIPS_CPU_IRQ_BASE + MIPS_CPU_IPI_CALL_IRQ);
-}
-
-static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
-{
-#ifdef CONFIG_MIPS_VPE_APSP_API_CMP
-       if (aprp_hook)
-               aprp_hook();
-#endif
-
-       scheduler_ipi();
-
-       return IRQ_HANDLED;
-}
-
-static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
-{
-       generic_smp_call_function_interrupt();
-
-       return IRQ_HANDLED;
-}
-
-static struct irqaction irq_resched = {
-       .handler        = ipi_resched_interrupt,
-       .flags          = IRQF_PERCPU,
-       .name           = "IPI_resched"
-};
-
-static struct irqaction irq_call = {
-       .handler        = ipi_call_interrupt,
-       .flags          = IRQF_PERCPU,
-       .name           = "IPI_call"
-};
-#endif /* CONFIG_MIPS_MT_SMP */
-
 static struct irqaction corehi_irqaction = {
        .handler = corehi_handler,
        .name = "CoreHi",
@@ -222,12 +172,6 @@ static msc_irqmap_t msc_eicirqmap[] __initdata = {
 
 static int msc_nr_eicirqs __initdata = ARRAY_SIZE(msc_eicirqmap);
 
-void __init arch_init_ipiirq(int irq, struct irqaction *action)
-{
-       setup_irq(irq, action);
-       irq_set_handler(irq, handle_percpu_irq);
-}
-
 void __init arch_init_irq(void)
 {
        int corehi_irq;
@@ -273,30 +217,11 @@ void __init arch_init_irq(void)
 
        if (gic_present) {
                corehi_irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_COREHI;
+       } else if (cpu_has_veic) {
+               set_vi_handler(MSC01E_INT_COREHI, corehi_irqdispatch);
+               corehi_irq = MSC01E_INT_BASE + MSC01E_INT_COREHI;
        } else {
-#if defined(CONFIG_MIPS_MT_SMP)
-               /* set up ipi interrupts */
-               if (cpu_has_veic) {
-                       set_vi_handler (MSC01E_INT_SW0, ipi_resched_dispatch);
-                       set_vi_handler (MSC01E_INT_SW1, ipi_call_dispatch);
-                       cpu_ipi_resched_irq = MSC01E_INT_SW0;
-                       cpu_ipi_call_irq = MSC01E_INT_SW1;
-               } else {
-                       cpu_ipi_resched_irq = MIPS_CPU_IRQ_BASE +
-                               MIPS_CPU_IPI_RESCHED_IRQ;
-                       cpu_ipi_call_irq = MIPS_CPU_IRQ_BASE +
-                               MIPS_CPU_IPI_CALL_IRQ;
-               }
-               arch_init_ipiirq(cpu_ipi_resched_irq, &irq_resched);
-               arch_init_ipiirq(cpu_ipi_call_irq, &irq_call);
-#endif
-               if (cpu_has_veic) {
-                       set_vi_handler(MSC01E_INT_COREHI,
-                                      corehi_irqdispatch);
-                       corehi_irq = MSC01E_INT_BASE + MSC01E_INT_COREHI;
-               } else {
-                       corehi_irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_COREHI;
-               }
+               corehi_irq = MIPS_CPU_IRQ_BASE + MIPSCPU_INT_COREHI;
        }
 
        setup_irq(corehi_irq, &corehi_irqaction);
index 49a2e2226fee84f2a284373a427b5fe155bf261d..44b925005dd37c78d8c85a814bef8ed69c927522 100644 (file)
@@ -365,6 +365,12 @@ static inline void emit_half_load(unsigned int reg, unsigned int base,
        emit_instr(ctx, lh, reg, offset, base);
 }
 
+static inline void emit_half_load_unsigned(unsigned int reg, unsigned int base,
+                                          unsigned int offset, struct jit_ctx *ctx)
+{
+       emit_instr(ctx, lhu, reg, offset, base);
+}
+
 static inline void emit_mul(unsigned int dst, unsigned int src1,
                            unsigned int src2, struct jit_ctx *ctx)
 {
@@ -526,7 +532,8 @@ static void save_bpf_jit_regs(struct jit_ctx *ctx, unsigned offset)
        u32 sflags, tmp_flags;
 
        /* Adjust the stack pointer */
-       emit_stack_offset(-align_sp(offset), ctx);
+       if (offset)
+               emit_stack_offset(-align_sp(offset), ctx);
 
        tmp_flags = sflags = ctx->flags >> SEEN_SREG_SFT;
        /* sflags is essentially a bitmap */
@@ -578,7 +585,8 @@ static void restore_bpf_jit_regs(struct jit_ctx *ctx,
                emit_load_stack_reg(r_ra, r_sp, real_off, ctx);
 
        /* Restore the sp and discard the scrach memory */
-       emit_stack_offset(align_sp(offset), ctx);
+       if (offset)
+               emit_stack_offset(align_sp(offset), ctx);
 }
 
 static unsigned int get_stack_depth(struct jit_ctx *ctx)
@@ -625,8 +633,14 @@ static void build_prologue(struct jit_ctx *ctx)
        if (ctx->flags & SEEN_X)
                emit_jit_reg_move(r_X, r_zero, ctx);
 
-       /* Do not leak kernel data to userspace */
-       if (bpf_needs_clear_a(&ctx->skf->insns[0]))
+       /*
+        * Do not leak kernel data to userspace, we only need to clear
+        * r_A if it is ever used.  In fact if it is never used, we
+        * will not save/restore it, so clearing it in this case would
+        * corrupt the state of the caller.
+        */
+       if (bpf_needs_clear_a(&ctx->skf->insns[0]) &&
+           (ctx->flags & SEEN_A))
                emit_jit_reg_move(r_A, r_zero, ctx);
 }
 
@@ -1112,6 +1126,8 @@ jmp_cmp:
                        break;
                case BPF_ANC | SKF_AD_IFINDEX:
                        /* A = skb->dev->ifindex */
+               case BPF_ANC | SKF_AD_HATYPE:
+                       /* A = skb->dev->type */
                        ctx->flags |= SEEN_SKB | SEEN_A;
                        off = offsetof(struct sk_buff, dev);
                        /* Load *dev pointer */
@@ -1120,10 +1136,15 @@ jmp_cmp:
                        emit_bcond(MIPS_COND_EQ, r_s0, r_zero,
                                   b_imm(prog->len, ctx), ctx);
                        emit_reg_move(r_ret, r_zero, ctx);
-                       BUILD_BUG_ON(FIELD_SIZEOF(struct net_device,
-                                                 ifindex) != 4);
-                       off = offsetof(struct net_device, ifindex);
-                       emit_load(r_A, r_s0, off, ctx);
+                       if (code == (BPF_ANC | SKF_AD_IFINDEX)) {
+                               BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, ifindex) != 4);
+                               off = offsetof(struct net_device, ifindex);
+                               emit_load(r_A, r_s0, off, ctx);
+                       } else { /* (code == (BPF_ANC | SKF_AD_HATYPE) */
+                               BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, type) != 2);
+                               off = offsetof(struct net_device, type);
+                               emit_half_load_unsigned(r_A, r_s0, off, ctx);
+                       }
                        break;
                case BPF_ANC | SKF_AD_MARK:
                        ctx->flags |= SEEN_SKB | SEEN_A;
@@ -1143,7 +1164,7 @@ jmp_cmp:
                        BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff,
                                                  vlan_tci) != 2);
                        off = offsetof(struct sk_buff, vlan_tci);
-                       emit_half_load(r_s0, r_skb, off, ctx);
+                       emit_half_load_unsigned(r_s0, r_skb, off, ctx);
                        if (code == (BPF_ANC | SKF_AD_VLAN_TAG)) {
                                emit_andi(r_A, r_s0, (u16)~VLAN_TAG_PRESENT, ctx);
                        } else {
@@ -1170,7 +1191,7 @@ jmp_cmp:
                        BUILD_BUG_ON(offsetof(struct sk_buff,
                                              queue_mapping) > 0xff);
                        off = offsetof(struct sk_buff, queue_mapping);
-                       emit_half_load(r_A, r_skb, off, ctx);
+                       emit_half_load_unsigned(r_A, r_skb, off, ctx);
                        break;
                default:
                        pr_debug("%s: Unhandled opcode: 0x%02x\n", __FILE__,
index 5d2e0c8d29c0bd0003bae3f7337edbcab5a403c4..88a2075305d1c1d71d09c7e3860367609b81ca04 100644 (file)
@@ -90,18 +90,14 @@ FEXPORT(sk_load_half_positive)
        is_offset_in_header(2, half)
        /* Offset within header boundaries */
        PTR_ADDU t1, $r_skb_data, offset
-       .set    reorder
-       lh      $r_A, 0(t1)
-       .set    noreorder
+       lhu     $r_A, 0(t1)
 #ifdef CONFIG_CPU_LITTLE_ENDIAN
 # if defined(__mips_isa_rev) && (__mips_isa_rev >= 2)
-       wsbh    t0, $r_A
-       seh     $r_A, t0
+       wsbh    $r_A, $r_A
 # else
-       sll     t0, $r_A, 24
-       andi    t1, $r_A, 0xff00
-       sra     t0, t0, 16
-       srl     t1, t1, 8
+       sll     t0, $r_A, 8
+       srl     t1, $r_A, 8
+       andi    t0, t0, 0xff00
        or      $r_A, t0, t1
 # endif
 #endif
@@ -115,7 +111,7 @@ FEXPORT(sk_load_byte_positive)
        is_offset_in_header(1, byte)
        /* Offset within header boundaries */
        PTR_ADDU t1, $r_skb_data, offset
-       lb      $r_A, 0(t1)
+       lbu     $r_A, 0(t1)
        jr      $r_ra
         move   $r_ret, zero
        END(sk_load_byte)
@@ -139,6 +135,11 @@ FEXPORT(sk_load_byte_positive)
  * (void *to) is returned in r_s0
  *
  */
+#ifdef CONFIG_CPU_LITTLE_ENDIAN
+#define DS_OFFSET(SIZE) (4 * SZREG)
+#else
+#define DS_OFFSET(SIZE) ((4 * SZREG) + (4 - SIZE))
+#endif
 #define bpf_slow_path_common(SIZE)                             \
        /* Quick check. Are we within reasonable boundaries? */ \
        LONG_ADDIU      $r_s1, $r_skb_len, -SIZE;               \
@@ -150,7 +151,7 @@ FEXPORT(sk_load_byte_positive)
        PTR_LA          t0, skb_copy_bits;                      \
        PTR_S           $r_ra, (5 * SZREG)($r_sp);              \
        /* Assign low slot to a2 */                             \
-       move            a2, $r_sp;                              \
+       PTR_ADDIU       a2, $r_sp, DS_OFFSET(SIZE);             \
        jalr            t0;                                     \
        /* Reset our destination slot (DS but it's ok) */       \
         INT_S          zero, (4 * SZREG)($r_sp);               \
index f6325fa657fb6538dbbc512d53254cf611b60aa1..bd67ac74fe2d3420509a03647a20856341bb70c8 100644 (file)
@@ -57,27 +57,3 @@ void pci_resource_to_user(const struct pci_dev *dev, int bar,
        *start = fixup_bigphys_addr(rsrc->start, size);
        *end = rsrc->start + size;
 }
-
-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
-                       enum pci_mmap_state mmap_state, int write_combine)
-{
-       unsigned long prot;
-
-       /*
-        * I/O space can be accessed via normal processor loads and stores on
-        * this platform but for now we elect not to do this and portable
-        * drivers should not do this anyway.
-        */
-       if (mmap_state == pci_mmap_io)
-               return -EINVAL;
-
-       /*
-        * Ignore write-combine; for now only return uncached mappings.
-        */
-       prot = pgprot_val(vma->vm_page_prot);
-       prot = (prot & ~_CACHE_MASK) | _CACHE_UNCACHED;
-       vma->vm_page_prot = __pgprot(prot);
-
-       return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
-               vma->vm_end - vma->vm_start, vma->vm_page_prot);
-}
index 9f672ceb089b9086b1fadcd0a3a487d2307beb69..ad3584dbc9d72bc1d0b845a1089ce41cec494737 100644 (file)
@@ -679,7 +679,7 @@ static void __cvmx_increment_ba(union cvmx_sli_mem_access_subidx *pmas)
        if (OCTEON_IS_MODEL(OCTEON_CN68XX))
                pmas->cn68xx.ba++;
        else
-               pmas->cn63xx.ba++;
+               pmas->s.ba++;
 }
 
 /**
@@ -1351,7 +1351,7 @@ static int __cvmx_pcie_rc_initialize_gen2(int pcie_port)
        if (OCTEON_IS_MODEL(OCTEON_CN68XX))
                mem_access_subid.cn68xx.ba = 0;
        else
-               mem_access_subid.cn63xx.ba = 0;
+               mem_access_subid.s.ba = 0;
 
        /*
         * Setup mem access 12-15 for port 0, 16-19 for port 1,
index a05246cbf54cfe852ff288202b9cbec972e4ebbc..2035aaec8514f51c835988d69743afe61e3c0418 100644 (file)
@@ -36,6 +36,7 @@ unsigned int soc_pass;
 unsigned int soc_type;
 EXPORT_SYMBOL(soc_type);
 unsigned int periph_rev;
+EXPORT_SYMBOL_GPL(periph_rev);
 unsigned int zbbus_mhz;
 EXPORT_SYMBOL(zbbus_mhz);
 
index 90e43782342b6e0691fd7369186e83e758b68f6f..aa7713adfa58fa79d5f2dcb00f420d2e02b43fc8 100644 (file)
@@ -34,6 +34,7 @@ unsigned int soc_pass;
 unsigned int soc_type;
 EXPORT_SYMBOL(soc_type);
 unsigned int periph_rev;
+EXPORT_SYMBOL_GPL(periph_rev);
 unsigned int zbbus_mhz;
 EXPORT_SYMBOL(zbbus_mhz);
 
index 51159fff025ab8fad129efdd6adba0f99c38db25..d27654902f28bd5bd8f7b4acae66f744041d8700 100644 (file)
@@ -74,9 +74,7 @@ static inline int pci_controller_num(struct pci_dev *dev)
 }
 
 #define HAVE_PCI_MMAP
-extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
-                              enum pci_mmap_state mmap_state,
-                              int write_combine);
+#define ARCH_GENERIC_PCI_MMAP_RESOURCE
 
 #endif /* __KERNEL__ */
 
index 040178cdb3eb9816f3d50769fee272e802becf9b..b15bf6bc0e94f46f035e8781ffa921060341fe91 100644 (file)
@@ -1,34 +1,2 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
-
-header-y += auxvec.h
-header-y += bitsperlong.h
-header-y += byteorder.h
-header-y += errno.h
-header-y += fcntl.h
-header-y += ioctl.h
-header-y += ioctls.h
-header-y += ipcbuf.h
-header-y += kvm_para.h
-header-y += mman.h
-header-y += msgbuf.h
-header-y += param.h
-header-y += poll.h
-header-y += posix_types.h
-header-y += ptrace.h
-header-y += resource.h
-header-y += sembuf.h
-header-y += setup.h
-header-y += shmbuf.h
-header-y += sigcontext.h
-header-y += siginfo.h
-header-y += signal.h
-header-y += socket.h
-header-y += sockios.h
-header-y += stat.h
-header-y += statfs.h
-header-y += swab.h
-header-y += termbits.h
-header-y += termios.h
-header-y += types.h
-header-y += unistd.h
index b7ab8378964ce5e9ca55acdd869d249f18a3d49b..e0f4617c0c7a90ad1077f9037b9dbbc3fd85b543 100644 (file)
@@ -210,26 +210,3 @@ void __init pcibios_resource_survey(void)
        pcibios_allocate_resources(0);
        pcibios_allocate_resources(1);
 }
-
-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
-                       enum pci_mmap_state mmap_state, int write_combine)
-{
-       unsigned long prot;
-
-       /* Leave vm_pgoff as-is, the PCI space address is the physical
-        * address on this platform.
-        */
-       vma->vm_flags |= VM_LOCKED;
-
-       prot = pgprot_val(vma->vm_page_prot);
-       prot &= ~_PAGE_CACHE;
-       vma->vm_page_prot = __pgprot(prot);
-
-       /* Write-combine setting is ignored */
-       if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
-                              vma->vm_end - vma->vm_start,
-                              vma->vm_page_prot))
-               return -EAGAIN;
-
-       return 0;
-}
index 51a56c8b04b451ce140a5708b4d5ca57bc7a6404..a72d5f0de69207ab01fb772f13fceed2d6cc9286 100644 (file)
@@ -6,6 +6,8 @@ config NIOS2
        select GENERIC_CPU_DEVICES
        select GENERIC_IRQ_PROBE
        select GENERIC_IRQ_SHOW
+       select GENERIC_STRNCPY_FROM_USER
+       select GENERIC_STRNLEN_USER
        select HAVE_ARCH_TRACEHOOK
        select HAVE_ARCH_KGDB
        select IRQ_DOMAIN
index 2fd08cbfdddb2a724db5685d0b7df86d6fe4d9bc..55105220370ce1c1688614ad29a1921c1226d24e 100644 (file)
@@ -18,7 +18,6 @@ config EARLY_PRINTK
        bool "Activate early kernel debugging"
        default y
        select SERIAL_CORE_CONSOLE
-       depends on SERIAL_ALTERA_JTAGUART_CONSOLE || SERIAL_ALTERA_UART_CONSOLE
        help
          Enable early printk on console
          This is useful for kernel debugging when your machine crashes very
index e74afc12d5163259c200e0280a382f64355d0196..8673a79dca9c6cef030158cff20e0c3d89208d1b 100644 (file)
@@ -22,10 +22,15 @@ export MMU
 
 LIBGCC         := $(shell $(CC) $(KBUILD_CFLAGS) $(KCFLAGS) -print-libgcc-file-name)
 
+KBUILD_AFLAGS += -march=r$(CONFIG_NIOS2_ARCH_REVISION)
+
 KBUILD_CFLAGS += -pipe -D__linux__ -D__ELF__
+KBUILD_CFLAGS += -march=r$(CONFIG_NIOS2_ARCH_REVISION)
 KBUILD_CFLAGS += $(if $(CONFIG_NIOS2_HW_MUL_SUPPORT),-mhw-mul,-mno-hw-mul)
 KBUILD_CFLAGS += $(if $(CONFIG_NIOS2_HW_MULX_SUPPORT),-mhw-mulx,-mno-hw-mulx)
 KBUILD_CFLAGS += $(if $(CONFIG_NIOS2_HW_DIV_SUPPORT),-mhw-div,-mno-hw-div)
+KBUILD_CFLAGS += $(if $(CONFIG_NIOS2_BMX_SUPPORT),-mbmx,-mno-bmx)
+KBUILD_CFLAGS += $(if $(CONFIG_NIOS2_CDX_SUPPORT),-mcdx,-mno-cdx)
 KBUILD_CFLAGS += $(if $(CONFIG_NIOS2_FPU_SUPPORT),-mcustom-fpu-cfg=60-1,)
 
 KBUILD_CFLAGS += -fno-optimize-sibling-calls
diff --git a/arch/nios2/boot/.gitignore b/arch/nios2/boot/.gitignore
new file mode 100644 (file)
index 0000000..109279c
--- /dev/null
@@ -0,0 +1,2 @@
+*.dtb
+vmImage
index f362b2224ee7e13d327838c5bec7e5f91d97e22f..4bb4dc1b52e92c0cea2a1c33103e3418841381aa 100644 (file)
        };
 
        chosen {
-               bootargs = "debug console=ttyS0,115200";
+               bootargs = "debug earlycon console=ttyS0,115200";
+               stdout-path = &a_16550_uart_0;
        };
 };
index 87e70f2b463ff68b109cb66cc8fc4917c0004373..727dbb333f60f43dcccbf90d168993f5a1d8ef93 100644 (file)
@@ -6,6 +6,7 @@ generic-y += bitsperlong.h
 generic-y += bug.h
 generic-y += bugs.h
 generic-y += clkdev.h
+generic-y += cmpxchg.h
 generic-y += current.h
 generic-y += device.h
 generic-y += div64.h
index 52abba973dc2adab1b56d70fd06486dacba0f336..55e383c173f776f35826d4d5d70b5af41f552a46 100644 (file)
@@ -46,7 +46,9 @@ extern void copy_from_user_page(struct vm_area_struct *vma, struct page *page,
 extern void flush_dcache_range(unsigned long start, unsigned long end);
 extern void invalidate_dcache_range(unsigned long start, unsigned long end);
 
-#define flush_dcache_mmap_lock(mapping)                do { } while (0)
-#define flush_dcache_mmap_unlock(mapping)      do { } while (0)
+#define flush_dcache_mmap_lock(mapping) \
+       spin_lock_irq(&(mapping)->tree_lock)
+#define flush_dcache_mmap_unlock(mapping) \
+       spin_unlock_irq(&(mapping)->tree_lock)
 
 #endif /* _ASM_NIOS2_CACHEFLUSH_H */
diff --git a/arch/nios2/include/asm/cmpxchg.h b/arch/nios2/include/asm/cmpxchg.h
deleted file mode 100644 (file)
index a7978f1..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright (C) 2004 Microtronix Datacom Ltd.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#ifndef _ASM_NIOS2_CMPXCHG_H
-#define _ASM_NIOS2_CMPXCHG_H
-
-#include <asm-generic/cmpxchg.h>
-
-#endif /* _ASM_NIOS2_CMPXCHG_H */
index 348bb228fec90e40245b357e3f53a10641a354c5..dbdaf96f28d47381bbef1216958a43f702ae0311 100644 (file)
@@ -29,6 +29,8 @@ struct cpuinfo {
        bool has_div;
        bool has_mul;
        bool has_mulx;
+       bool has_bmx;
+       bool has_cdx;
 
        /* CPU caches */
        u32 icache_line_size;
index dcbf8cf1a34491bf62d076f2e50ff6876d7993f3..ac9bff248e6db53fa21504a545bf389ab4c2e9da 100644 (file)
@@ -30,8 +30,6 @@ extern char fast_handler_end[];
 
 extern void pagetable_init(void);
 
-extern void setup_early_printk(void);
-
 #endif/* __KERNEL__ */
 #endif /* __ASSEMBLY__ */
 
index 727bd9504899c07d4915a8e9c30afbc2817b4c28..dfa3c7cb30b47cf3b8acd981af49d658d3adb3a8 100644 (file)
@@ -42,6 +42,8 @@
 
 # define __EX_TABLE_SECTION    ".section __ex_table,\"a\"\n"
 
+#define user_addr_max() (uaccess_kernel() ? ~0UL : TASK_SIZE)
+
 /*
  * Zero Userspace
  */
@@ -81,8 +83,9 @@ raw_copy_to_user(void __user *to, const void *from, unsigned long n);
 #define INLINE_COPY_TO_USER
 
 extern long strncpy_from_user(char *__to, const char __user *__from,
-                               long __len);
-extern long strnlen_user(const char __user *s, long n);
+                             long __len);
+extern __must_check long strlen_user(const char __user *str);
+extern __must_check long strnlen_user(const char __user *s, long n);
 
 /* Optimized macros */
 #define __get_user_asm(val, insn, addr, err)                           \
index e0bb972a50d7425b3f422605ab64bbc82c428cc0..374bd123329f015adfcc295178d68f80a9d7678a 100644 (file)
@@ -1,5 +1,5 @@
+# UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
-header-y += elf.h
-
+generic-y += setup.h
 generic-y += ucontext.h
diff --git a/arch/nios2/kernel/.gitignore b/arch/nios2/kernel/.gitignore
new file mode 100644 (file)
index 0000000..c5f676c
--- /dev/null
@@ -0,0 +1 @@
+vmlinux.lds
index 1aae257036575ada177ab257dcd68bb7cc3fce42..06d07432b38d1904cf186e29dae0d4b2345721a2 100644 (file)
@@ -20,7 +20,6 @@ obj-y += syscall_table.o
 obj-y  += time.o
 obj-y  += traps.o
 
-obj-$(CONFIG_EARLY_PRINTK)             += early_printk.o
 obj-$(CONFIG_KGDB)                     += kgdb.o
 obj-$(CONFIG_MODULES)                  += module.o
 obj-$(CONFIG_NIOS2_ALIGNMENT_TRAP)     += misaligned.o
index 1cccc36877bc43a6d257be257a1f8573c686c82b..93207718bb221067e32eb77a164464b75cff5d7f 100644 (file)
@@ -67,6 +67,8 @@ void __init setup_cpuinfo(void)
        cpuinfo.has_div = of_property_read_bool(cpu, "altr,has-div");
        cpuinfo.has_mul = of_property_read_bool(cpu, "altr,has-mul");
        cpuinfo.has_mulx = of_property_read_bool(cpu, "altr,has-mulx");
+       cpuinfo.has_bmx = of_property_read_bool(cpu, "altr,has-bmx");
+       cpuinfo.has_cdx = of_property_read_bool(cpu, "altr,has-cdx");
        cpuinfo.mmu = of_property_read_bool(cpu, "altr,has-mmu");
 
        if (IS_ENABLED(CONFIG_NIOS2_HW_DIV_SUPPORT) && !cpuinfo.has_div)
@@ -78,6 +80,12 @@ void __init setup_cpuinfo(void)
        if (IS_ENABLED(CONFIG_NIOS2_HW_MULX_SUPPORT) && !cpuinfo.has_mulx)
                err_cpu("MULX");
 
+       if (IS_ENABLED(CONFIG_NIOS2_BMX_SUPPORT) && !cpuinfo.has_bmx)
+               err_cpu("BMX");
+
+       if (IS_ENABLED(CONFIG_NIOS2_CDX_SUPPORT) && !cpuinfo.has_cdx)
+               err_cpu("CDX");
+
        cpuinfo.tlb_num_ways = fcpu(cpu, "altr,tlb-num-ways");
        if (!cpuinfo.tlb_num_ways)
                panic("altr,tlb-num-ways can't be 0. Please check your hardware "
@@ -125,12 +133,14 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 
        seq_printf(m,
                   "CPU:\t\tNios II/%s\n"
+                  "REV:\t\t%i\n"
                   "MMU:\t\t%s\n"
                   "FPU:\t\tnone\n"
                   "Clocking:\t%u.%02u MHz\n"
                   "BogoMips:\t%lu.%02lu\n"
                   "Calibration:\t%lu loops\n",
                   cpuinfo.cpu_impl,
+                  CONFIG_NIOS2_ARCH_REVISION,
                   cpuinfo.mmu ? "present" : "none",
                   clockfreq / 1000000, (clockfreq / 100000) % 10,
                   (loops_per_jiffy * HZ) / 500000,
@@ -141,10 +151,14 @@ static int show_cpuinfo(struct seq_file *m, void *v)
                   "HW:\n"
                   " MUL:\t\t%s\n"
                   " MULX:\t\t%s\n"
-                  " DIV:\t\t%s\n",
+                  " DIV:\t\t%s\n"
+                  " BMX:\t\t%s\n"
+                  " CDX:\t\t%s\n",
                   cpuinfo.has_mul ? "yes" : "no",
                   cpuinfo.has_mulx ? "yes" : "no",
-                  cpuinfo.has_div ? "yes" : "no");
+                  cpuinfo.has_div ? "yes" : "no",
+                  cpuinfo.has_bmx ? "yes" : "no",
+                  cpuinfo.has_cdx ? "yes" : "no");
 
        seq_printf(m,
                   "Icache:\t\t%ukB, line length: %u\n",
diff --git a/arch/nios2/kernel/early_printk.c b/arch/nios2/kernel/early_printk.c
deleted file mode 100644 (file)
index c08e4c1..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Early printk for Nios2.
- *
- * Copyright (C) 2015, Altera Corporation
- * Copyright (C) 2010, Tobias Klauser <tklauser@distanz.ch>
- * Copyright (C) 2009, Wind River Systems Inc
- *   Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License. See the file "COPYING" in the main directory of this archive
- * for more details.
- */
-
-#include <linux/console.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/io.h>
-
-#include <asm/prom.h>
-
-static unsigned long base_addr;
-
-#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE)
-
-#define ALTERA_JTAGUART_DATA_REG               0
-#define ALTERA_JTAGUART_CONTROL_REG            4
-#define ALTERA_JTAGUART_CONTROL_WSPACE_MSK     0xFFFF0000
-#define ALTERA_JTAGUART_CONTROL_AC_MSK         0x00000400
-
-#define JUART_GET_CR() \
-       __builtin_ldwio((void *)(base_addr + ALTERA_JTAGUART_CONTROL_REG))
-#define JUART_SET_CR(v) \
-       __builtin_stwio((void *)(base_addr + ALTERA_JTAGUART_CONTROL_REG), v)
-#define JUART_SET_TX(v) \
-       __builtin_stwio((void *)(base_addr + ALTERA_JTAGUART_DATA_REG), v)
-
-static void early_console_write(struct console *con, const char *s, unsigned n)
-{
-       unsigned long status;
-
-       while (n-- && *s) {
-               while (((status = JUART_GET_CR())
-                               & ALTERA_JTAGUART_CONTROL_WSPACE_MSK) == 0) {
-#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS)
-                       if ((status & ALTERA_JTAGUART_CONTROL_AC_MSK) == 0)
-                               return; /* no connection activity */
-#endif
-               }
-               JUART_SET_TX(*s);
-               s++;
-       }
-}
-
-#elif defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE)
-
-#define ALTERA_UART_TXDATA_REG         4
-#define ALTERA_UART_STATUS_REG         8
-#define ALTERA_UART_STATUS_TRDY                0x0040
-
-#define UART_GET_SR() \
-       __builtin_ldwio((void *)(base_addr + ALTERA_UART_STATUS_REG))
-#define UART_SET_TX(v) \
-       __builtin_stwio((void *)(base_addr + ALTERA_UART_TXDATA_REG), v)
-
-static void early_console_putc(char c)
-{
-       while (!(UART_GET_SR() & ALTERA_UART_STATUS_TRDY))
-               ;
-
-       UART_SET_TX(c);
-}
-
-static void early_console_write(struct console *con, const char *s, unsigned n)
-{
-       while (n-- && *s) {
-               early_console_putc(*s);
-               if (*s == '\n')
-                       early_console_putc('\r');
-               s++;
-       }
-}
-
-#else
-# error Neither SERIAL_ALTERA_JTAGUART_CONSOLE nor SERIAL_ALTERA_UART_CONSOLE \
-selected
-#endif
-
-static struct console early_console_prom = {
-       .name   = "early",
-       .write  = early_console_write,
-       .flags  = CON_PRINTBUFFER | CON_BOOT,
-       .index  = -1
-};
-
-void __init setup_early_printk(void)
-{
-#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE) ||  \
-       defined(CONFIG_SERIAL_ALTERA_UART_CONSOLE)
-       base_addr = of_early_console();
-#else
-       base_addr = 0;
-#endif
-
-       if (!base_addr)
-               return;
-
-#if defined(CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE_BYPASS)
-       /* Clear activity bit so BYPASS doesn't stall if we've used JTAG for
-        * downloading the kernel. This might cause early data to be lost even
-        * if the JTAG terminal is running.
-        */
-       JUART_SET_CR(JUART_GET_CR() | ALTERA_JTAGUART_CONTROL_AC_MSK);
-#endif
-
-       early_console = &early_console_prom;
-       register_console(early_console);
-       pr_info("early_console initialized at 0x%08lx\n", base_addr);
-}
index f5b74ae69b5b331bc237399b43448b3b66521329..6c833a9d4eab8dc979b84b72d7ce1d15ed0fb9a5 100644 (file)
@@ -67,7 +67,7 @@ static int irq_map(struct irq_domain *h, unsigned int virq,
        return 0;
 }
 
-static struct irq_domain_ops irq_ops = {
+static const struct irq_domain_ops irq_ops = {
        .map    = irq_map,
        .xlate  = irq_domain_xlate_onecell,
 };
index 3901b80d442021e17e96e29f33cea2b1c28ec345..6688576b3a473fbb0791f97c455478c87533274a 100644 (file)
@@ -30,7 +30,6 @@
 #include <linux/of_fdt.h>
 #include <linux/io.h>
 
-#include <asm/prom.h>
 #include <asm/sections.h>
 
 void __init early_init_dt_add_memory_arch(u64 base, u64 size)
@@ -71,51 +70,3 @@ void __init early_init_devtree(void *params)
 
        early_init_dt_scan(params);
 }
-
-#ifdef CONFIG_EARLY_PRINTK
-static int __init early_init_dt_scan_serial(unsigned long node,
-                       const char *uname, int depth, void *data)
-{
-       u64 *addr64 = (u64 *) data;
-       const char *p;
-
-       /* only consider serial nodes */
-       if (strncmp(uname, "serial", 6) != 0)
-               return 0;
-
-       p = of_get_flat_dt_prop(node, "compatible", NULL);
-       if (!p)
-               return 0;
-
-       /*
-        * We found an altera_jtaguart but it wasn't configured for console, so
-        * skip it.
-        */
-#ifndef CONFIG_SERIAL_ALTERA_JTAGUART_CONSOLE
-       if (strncmp(p, "altr,juart", 10) == 0)
-               return 0;
-#endif
-
-       /*
-        * Same for altera_uart.
-        */
-#ifndef CONFIG_SERIAL_ALTERA_UART_CONSOLE
-       if (strncmp(p, "altr,uart", 9) == 0)
-               return 0;
-#endif
-
-       *addr64 = of_flat_dt_translate_address(node);
-
-       return *addr64 == OF_BAD_ADDR ? 0 : 1;
-}
-
-unsigned long __init of_early_console(void)
-{
-       u64 base = 0;
-
-       if (of_scan_flat_dt(early_init_dt_scan_serial, &base))
-               return (u32)ioremap(base, 32);
-       else
-               return 0;
-}
-#endif /* CONFIG_EARLY_PRINTK */
index 6044d9be28b4493323d362162e7e5ec6c56e1f33..926a02b17b31f36df84655176aa5757f3b13a4a9 100644 (file)
@@ -137,6 +137,8 @@ asmlinkage void __init nios2_boot_init(unsigned r4, unsigned r5, unsigned r6,
                strncpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
 #endif
 #endif
+
+       parse_early_param();
 }
 
 void __init setup_arch(char **cmdline_p)
@@ -145,10 +147,6 @@ void __init setup_arch(char **cmdline_p)
 
        console_verbose();
 
-#ifdef CONFIG_EARLY_PRINTK
-       setup_early_printk();
-#endif
-
        memory_start = PAGE_ALIGN((unsigned long)__pa(_end));
        memory_end = (unsigned long) CONFIG_NIOS2_MEM_BASE + memory_size;
 
index 80498331776624c15aa297db1d6b99856e0ca736..34f10af8ea4028a865506c4a6b479d2bf633a1a5 100644 (file)
@@ -128,36 +128,3 @@ asm(
        ".word 12b,13b\n"
        ".previous\n");
 EXPORT_SYMBOL(raw_copy_to_user);
-
-long strncpy_from_user(char *__to, const char __user *__from, long __len)
-{
-       int l = strnlen_user(__from, __len);
-       int is_zt = 1;
-
-       if (l > __len) {
-               is_zt = 0;
-               l = __len;
-       }
-
-       if (l == 0 || copy_from_user(__to, __from, l))
-               return -EFAULT;
-
-       if (is_zt)
-               l--;
-       return l;
-}
-
-long strnlen_user(const char __user *s, long n)
-{
-       long i;
-
-       for (i = 0; i < n; i++) {
-               char c;
-
-               if (get_user(c, s + i) == -EFAULT)
-                       return 0;
-               if (c == 0)
-                       return i + 1;
-       }
-       return n + 1;
-}
index d3e5df9fb36bd139a4a7e93840ae974181a8e2d8..74c1aaf588b8bf9870e4c7fc2925274ec4af1c00 100644 (file)
@@ -52,6 +52,14 @@ config NIOS2_DTB_SOURCE
 
 comment "Nios II instructions"
 
+config NIOS2_ARCH_REVISION
+       int "Select Nios II architecture revision"
+       range 1 2
+       default 1
+       help
+         Select between Nios II R1 and Nios II R2 . The architectures
+         are binary incompatible. Default is R1 .
+
 config NIOS2_HW_MUL_SUPPORT
        bool "Enable MUL instruction"
        default n
@@ -73,6 +81,24 @@ config NIOS2_HW_DIV_SUPPORT
          Set to true if you configured the Nios II to include the DIV
          instruction.  Enables the -mhw-div compiler flag.
 
+config NIOS2_BMX_SUPPORT
+       bool "Enable BMX instructions"
+       depends on NIOS2_ARCH_REVISION = 2
+       default n
+       help
+         Set to true if you configured the Nios II R2 to include
+         the BMX Bit Manipulation Extension instructions. Enables
+         the -mbmx compiler flag.
+
+config NIOS2_CDX_SUPPORT
+       bool "Enable CDX instructions"
+       depends on NIOS2_ARCH_REVISION = 2
+       default n
+       help
+         Set to true if you configured the Nios II R2 to include
+         the CDX Bit Manipulation Extension instructions. Enables
+         the -mcdx compiler flag.
+
 config NIOS2_FPU_SUPPORT
        bool "Custom floating point instr support"
        default n
index df8e2f7bc7dd96f7d45cb76d937b53539a7c0b2b..fdbcf0bf44a4f3e56487b533347f96477b76aa4d 100644 (file)
@@ -1,6 +1,3 @@
-
-header-y += ucontext.h
-
 generic-y += auxvec.h
 generic-y += barrier.h
 generic-y += bitsperlong.h
index 80761eb82b5fd8d272f354eefc7299c7c3406a0a..b15bf6bc0e94f46f035e8781ffa921060341fe91 100644 (file)
@@ -1,10 +1,2 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
-
-header-y += byteorder.h
-header-y += elf.h
-header-y += kvm_para.h
-header-y += param.h
-header-y += ptrace.h
-header-y += sigcontext.h
-header-y += unistd.h
index defebd956585495bf4b33117989bf05dd8699685..1de1a3f412ec142514d76bbb0edfda171fb0f510 100644 (file)
@@ -200,8 +200,6 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
 }
 
 #define HAVE_PCI_MMAP
-
-extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
-       enum pci_mmap_state mmap_state, int write_combine);
+#define ARCH_GENERIC_PCI_MMAP_RESOURCE
 
 #endif /* __ASM_PARISC_PCI_H */
index 348356c99514f0cdfb8876b9f22c0464ab8e3734..3971c60a7e7ff6f987cd36b705ddbf49cce5af7c 100644 (file)
@@ -2,31 +2,3 @@
 include include/uapi/asm-generic/Kbuild.asm
 
 generic-y += resource.h
-
-header-y += bitsperlong.h
-header-y += byteorder.h
-header-y += errno.h
-header-y += fcntl.h
-header-y += ioctl.h
-header-y += ioctls.h
-header-y += ipcbuf.h
-header-y += mman.h
-header-y += msgbuf.h
-header-y += pdc.h
-header-y += posix_types.h
-header-y += ptrace.h
-header-y += sembuf.h
-header-y += setup.h
-header-y += shmbuf.h
-header-y += sigcontext.h
-header-y += siginfo.h
-header-y += signal.h
-header-y += socket.h
-header-y += sockios.h
-header-y += stat.h
-header-y += statfs.h
-header-y += swab.h
-header-y += termbits.h
-header-y += termios.h
-header-y += types.h
-header-y += unistd.h
index ad4cb1613c57a56552e32d795d5d83fdffd99672..a4fd296c958e8e14f13a913aca50510b11eb49b7 100644 (file)
@@ -1369,7 +1369,7 @@ nadtlb_nullify:
 
        /* 
                When there is no translation for the probe address then we
-               must nullify the insn and return zero in the target regsiter.
+               must nullify the insn and return zero in the target register.
                This will indicate to the calling code that it does not have 
                write/read privileges to this address.
 
index c66c943d93224f342cb71c97bd6a690bf8fb225b..f1a76935a3149495c8a65faeee8028295c24e559 100644 (file)
@@ -218,7 +218,7 @@ void *module_alloc(unsigned long size)
         * easier than trying to map the text, data, init_text and
         * init_data correctly */
        return __vmalloc_node_range(size, 1, VMALLOC_START, VMALLOC_END,
-                                   GFP_KERNEL | __GFP_HIGHMEM,
+                                   GFP_KERNEL,
                                    PAGE_KERNEL_RWX, 0, NUMA_NO_NODE,
                                    __builtin_return_address(0));
 }
index 0903c6abd7a4ce4ebc5fc6652740656483465e6f..13ee3569959acf7bf0a161fe2ae8beca32533740 100644 (file)
@@ -227,34 +227,6 @@ resource_size_t pcibios_align_resource(void *data, const struct resource *res,
        return start;
 }
 
-
-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
-                       enum pci_mmap_state mmap_state, int write_combine)
-{
-       unsigned long prot;
-
-       /*
-        * I/O space can be accessed via normal processor loads and stores on
-        * this platform but for now we elect not to do this and portable
-        * drivers should not do this anyway.
-        */
-       if (mmap_state == pci_mmap_io)
-               return -EINVAL;
-
-       if (write_combine)
-               return -EINVAL;
-
-       /*
-        * Ignore write-combine; for now only return uncached mappings.
-        */
-       prot = pgprot_val(vma->vm_page_prot);
-       prot |= _PAGE_NO_CACHE;
-       vma->vm_page_prot = __pgprot(prot);
-
-       return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
-               vma->vm_end - vma->vm_start, vma->vm_page_prot);
-}
-
 /*
  * A driver is enabling the device.  We make sure that all the appropriate
  * bits are set to allow the device to operate as the driver is expecting.
index f07f727cbfd211cdf29375cd6ad3faa7012b0652..f7c8f9972f618109209e4892512ed903f6b865f3 100644 (file)
@@ -146,6 +146,7 @@ config PPC
        select ARCH_USE_BUILTIN_BSWAP
        select ARCH_USE_CMPXCHG_LOCKREF         if PPC64
        select ARCH_WANT_IPC_PARSE_VERSION
+       select ARCH_WEAK_RELEASE_ACQUIRE
        select BINFMT_ELF
        select BUILDTIME_EXTABLE_SORT
        select CLONE_BACKWARDS
@@ -379,6 +380,22 @@ source "arch/powerpc/platforms/Kconfig"
 
 menu "Kernel options"
 
+config PPC_DT_CPU_FTRS
+       bool "Device-tree based CPU feature discovery & setup"
+       depends on PPC_BOOK3S_64
+       default n
+       help
+         This enables code to use a new device tree binding for describing CPU
+         compatibility and features. Saying Y here will attempt to use the new
+         binding if the firmware provides it. Currently only the skiboot
+         firmware provides this binding.
+         If you're not sure say Y.
+
+config PPC_CPUFEATURES_ENABLE_UNKNOWN
+       bool "cpufeatures pass through unknown features to guest/userspace"
+       depends on PPC_DT_CPU_FTRS
+       default y
+
 config HIGHMEM
        bool "High memory support"
        depends on PPC32
@@ -571,21 +588,23 @@ config RELOCATABLE_TEST
          relocation code.
 
 config CRASH_DUMP
-       bool "Build a kdump crash kernel"
+       bool "Build a dump capture kernel"
        depends on PPC64 || 6xx || FSL_BOOKE || (44x && !SMP)
        select RELOCATABLE if PPC64 || 44x || FSL_BOOKE
        help
-         Build a kernel suitable for use as a kdump capture kernel.
+         Build a kernel suitable for use as a dump capture kernel.
          The same kernel binary can be used as production kernel and dump
          capture kernel.
 
 config FA_DUMP
        bool "Firmware-assisted dump"
-       depends on PPC64 && PPC_RTAS && CRASH_DUMP && KEXEC_CORE
+       depends on PPC64 && PPC_RTAS
+       select CRASH_CORE
+       select CRASH_DUMP
        help
          A robust mechanism to get reliable kernel crash dump with
          assistance from firmware. This approach does not use kexec,
-         instead firmware assists in booting the kdump kernel
+         instead firmware assists in booting the capture kernel
          while preserving memory contents. Firmware-assisted dump
          is meant to be a kdump replacement offering robustness and
          speed not possible without system firmware assistance.
index 3c22d64b2de974a1ee8e8894ae3fd40c1a41551d..eccfcc88afae00cca95ef578dc576c1d2e72dfa1 100644 (file)
@@ -7,7 +7,7 @@
 PHONY := __archpost
 __archpost:
 
-include include/config/auto.conf
+-include include/config/auto.conf
 include scripts/Kbuild.include
 
 quiet_cmd_relocs_check = CHKREL  $@
diff --git a/arch/powerpc/boot/dts/include/dt-bindings b/arch/powerpc/boot/dts/include/dt-bindings
deleted file mode 120000 (symlink)
index 08c00e4..0000000
+++ /dev/null
@@ -1 +0,0 @@
-../../../../../include/dt-bindings
\ No newline at end of file
index 214219dff87c47cbd68bb48337ff44a876812204..9732837aaae85cdaf92d5c8551d47562ca58409d 100644 (file)
@@ -2,9 +2,9 @@
 #define _ASM_POWERPC_BOOK3S_64_HASH_64K_H
 
 #define H_PTE_INDEX_SIZE  8
-#define H_PMD_INDEX_SIZE  5
-#define H_PUD_INDEX_SIZE  5
-#define H_PGD_INDEX_SIZE  15
+#define H_PMD_INDEX_SIZE  10
+#define H_PUD_INDEX_SIZE  7
+#define H_PGD_INDEX_SIZE  8
 
 /*
  * 64k aligned address free up few of the lower bits of RPN for us
index 8ee4211ca0c6fb107cbf693c05fac5a987532822..14ad37865000f163c78ac727672bb0d85a45df40 100644 (file)
@@ -560,6 +560,8 @@ typedef struct risc_timer_pram {
 #define CPM_PIN_SECONDARY 2
 #define CPM_PIN_GPIO      4
 #define CPM_PIN_OPENDRAIN 8
+#define CPM_PIN_FALLEDGE  16
+#define CPM_PIN_ANYEDGE   0
 
 enum cpm_port {
        CPM_PORTA,
index 6e834caa37206a476792823463e81ac4c9617f9c..0d1df02bf99d3e4257bac057d6921318a80d10b2 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef __ASM_POWERPC_CPUFEATURES_H
-#define __ASM_POWERPC_CPUFEATURES_H
+#ifndef __ASM_POWERPC_CPU_HAS_FEATURE_H
+#define __ASM_POWERPC_CPU_HAS_FEATURE_H
 
 #ifndef __ASSEMBLY__
 
@@ -52,4 +52,4 @@ static inline bool cpu_has_feature(unsigned long feature)
 #endif
 
 #endif /* __ASSEMBLY__ */
-#endif /* __ASM_POWERPC_CPUFEATURE_H */
+#endif /* __ASM_POWERPC_CPU_HAS_FEATURE_H */
index 1f6847b107e48104a51922773d86bdb28b89d663..c2d509584a98070accd6be62519fa992e5bc1f3f 100644 (file)
@@ -118,7 +118,9 @@ extern struct cpu_spec              *cur_cpu_spec;
 
 extern unsigned int __start___ftr_fixup, __stop___ftr_fixup;
 
+extern void set_cur_cpu_spec(struct cpu_spec *s);
 extern struct cpu_spec *identify_cpu(unsigned long offset, unsigned int pvr);
+extern void identify_cpu_name(unsigned int pvr);
 extern void do_feature_fixups(unsigned long value, void *fixup_start,
                              void *fixup_end);
 
diff --git a/arch/powerpc/include/asm/dt_cpu_ftrs.h b/arch/powerpc/include/asm/dt_cpu_ftrs.h
new file mode 100644 (file)
index 0000000..7a34fc1
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef __ASM_POWERPC_DT_CPU_FTRS_H
+#define __ASM_POWERPC_DT_CPU_FTRS_H
+
+/*
+ *  Copyright 2017, IBM Corporation
+ *  cpufeatures is the new way to discover CPU features with /cpus/features
+ *  devicetree. This supersedes PVR based discovery ("cputable"), and older
+ *  device tree feature advertisement.
+ */
+
+#include <linux/types.h>
+#include <asm/asm-compat.h>
+#include <asm/feature-fixups.h>
+#include <uapi/asm/cputable.h>
+
+#ifdef CONFIG_PPC_DT_CPU_FTRS
+bool dt_cpu_ftrs_init(void *fdt);
+void dt_cpu_ftrs_scan(void);
+bool dt_cpu_ftrs_in_use(void);
+#else
+static inline bool dt_cpu_ftrs_init(void *fdt) { return false; }
+static inline void dt_cpu_ftrs_scan(void) { }
+static inline bool dt_cpu_ftrs_in_use(void) { return false; }
+#endif
+
+#endif /* __ASM_POWERPC_DT_CPU_FTRS_H */
index 0031806475f0f1b22645336d427bfee9fd9b0462..60b91084f33c7083caa3accc9d3aaf14c19417c7 100644 (file)
@@ -73,6 +73,8 @@
        reg_entry++;                                                    \
 })
 
+extern int crashing_cpu;
+
 /* Kernel Dump section info */
 struct fadump_section {
        __be32  request_flag;
index 0593d9479f74ecaa61b73b21bbf76477fff1b356..b148496ffe36da31c81f18020a783798c9e8c1c3 100644 (file)
@@ -111,6 +111,8 @@ struct kvmppc_host_state {
        struct kvm_vcpu *kvm_vcpu;
        struct kvmppc_vcore *kvm_vcore;
        void __iomem *xics_phys;
+       void __iomem *xive_tima_phys;
+       void __iomem *xive_tima_virt;
        u32 saved_xirr;
        u64 dabr;
        u64 host_mmcr[7];       /* MMCR 0,1,A, SIAR, SDAR, MMCR2, SIER */
index 77c60826d1456c1d63c4df46eba0a7ad14c3bab0..9c51ac4b8f3699d256b4a33bd75e2466b856fc3f 100644 (file)
@@ -210,6 +210,12 @@ struct kvmppc_spapr_tce_table {
 /* XICS components, defined in book3s_xics.c */
 struct kvmppc_xics;
 struct kvmppc_icp;
+extern struct kvm_device_ops kvm_xics_ops;
+
+/* XIVE components, defined in book3s_xive.c */
+struct kvmppc_xive;
+struct kvmppc_xive_vcpu;
+extern struct kvm_device_ops kvm_xive_ops;
 
 struct kvmppc_passthru_irqmap;
 
@@ -298,6 +304,7 @@ struct kvm_arch {
 #endif
 #ifdef CONFIG_KVM_XICS
        struct kvmppc_xics *xics;
+       struct kvmppc_xive *xive;
        struct kvmppc_passthru_irqmap *pimap;
 #endif
        struct kvmppc_ops *kvm_ops;
@@ -427,7 +434,7 @@ struct kvmppc_passthru_irqmap {
 
 #define KVMPPC_IRQ_DEFAULT     0
 #define KVMPPC_IRQ_MPIC                1
-#define KVMPPC_IRQ_XICS                2
+#define KVMPPC_IRQ_XICS                2 /* Includes a XIVE option */
 
 #define MMIO_HPTE_CACHE_SIZE   4
 
@@ -454,6 +461,21 @@ struct mmio_hpte_cache {
 
 struct openpic;
 
+/* W0 and W1 of a XIVE thread management context */
+union xive_tma_w01 {
+       struct {
+               u8      nsr;
+               u8      cppr;
+               u8      ipb;
+               u8      lsmfb;
+               u8      ack;
+               u8      inc;
+               u8      age;
+               u8      pipr;
+       };
+       __be64 w01;
+};
+
 struct kvm_vcpu_arch {
        ulong host_stack;
        u32 host_pid;
@@ -714,6 +736,10 @@ struct kvm_vcpu_arch {
        struct openpic *mpic;   /* KVM_IRQ_MPIC */
 #ifdef CONFIG_KVM_XICS
        struct kvmppc_icp *icp; /* XICS presentation controller */
+       struct kvmppc_xive_vcpu *xive_vcpu; /* XIVE virtual CPU data */
+       __be32 xive_cam_word;    /* Cooked W2 in proper endian with valid bit */
+       u32 xive_pushed;         /* Is the VP pushed on the physical CPU ? */
+       union xive_tma_w01 xive_saved_state; /* W0..1 of XIVE thread state */
 #endif
 
 #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
index 76e940a3c145188a51f26335296ca045d7b48770..e0d88c38602b8fb85a4d1419354b2385750466b7 100644 (file)
@@ -240,6 +240,7 @@ int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq);
 extern int kvm_vm_ioctl_rtas_define_token(struct kvm *kvm, void __user *argp);
 extern int kvmppc_rtas_hcall(struct kvm_vcpu *vcpu);
 extern void kvmppc_rtas_tokens_free(struct kvm *kvm);
+
 extern int kvmppc_xics_set_xive(struct kvm *kvm, u32 irq, u32 server,
                                u32 priority);
 extern int kvmppc_xics_get_xive(struct kvm *kvm, u32 irq, u32 *server,
@@ -428,6 +429,14 @@ static inline void kvmppc_set_xics_phys(int cpu, unsigned long addr)
        paca[cpu].kvm_hstate.xics_phys = (void __iomem *)addr;
 }
 
+static inline void kvmppc_set_xive_tima(int cpu,
+                                       unsigned long phys_addr,
+                                       void __iomem *virt_addr)
+{
+       paca[cpu].kvm_hstate.xive_tima_phys = (void __iomem *)phys_addr;
+       paca[cpu].kvm_hstate.xive_tima_virt = virt_addr;
+}
+
 static inline u32 kvmppc_get_xics_latch(void)
 {
        u32 xirr;
@@ -458,6 +467,11 @@ static inline void __init kvm_cma_reserve(void)
 static inline void kvmppc_set_xics_phys(int cpu, unsigned long addr)
 {}
 
+static inline void kvmppc_set_xive_tima(int cpu,
+                                       unsigned long phys_addr,
+                                       void __iomem *virt_addr)
+{}
+
 static inline u32 kvmppc_get_xics_latch(void)
 {
        return 0;
@@ -508,6 +522,10 @@ extern long kvmppc_deliver_irq_passthru(struct kvm_vcpu *vcpu, __be32 xirr,
                                        struct kvmppc_irq_map *irq_map,
                                        struct kvmppc_passthru_irqmap *pimap,
                                        bool *again);
+
+extern int kvmppc_xics_set_irq(struct kvm *kvm, int irq_source_id, u32 irq,
+                              int level, bool line_status);
+
 extern int h_ipi_redirect;
 #else
 static inline struct kvmppc_passthru_irqmap *kvmppc_get_passthru_irqmap(
@@ -525,6 +543,60 @@ static inline int kvmppc_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd)
        { return 0; }
 #endif
 
+#ifdef CONFIG_KVM_XIVE
+/*
+ * Below the first "xive" is the "eXternal Interrupt Virtualization Engine"
+ * ie. P9 new interrupt controller, while the second "xive" is the legacy
+ * "eXternal Interrupt Vector Entry" which is the configuration of an
+ * interrupt on the "xics" interrupt controller on P8 and earlier. Those
+ * two function consume or produce a legacy "XIVE" state from the
+ * new "XIVE" interrupt controller.
+ */
+extern int kvmppc_xive_set_xive(struct kvm *kvm, u32 irq, u32 server,
+                               u32 priority);
+extern int kvmppc_xive_get_xive(struct kvm *kvm, u32 irq, u32 *server,
+                               u32 *priority);
+extern int kvmppc_xive_int_on(struct kvm *kvm, u32 irq);
+extern int kvmppc_xive_int_off(struct kvm *kvm, u32 irq);
+extern void kvmppc_xive_init_module(void);
+extern void kvmppc_xive_exit_module(void);
+
+extern int kvmppc_xive_connect_vcpu(struct kvm_device *dev,
+                                   struct kvm_vcpu *vcpu, u32 cpu);
+extern void kvmppc_xive_cleanup_vcpu(struct kvm_vcpu *vcpu);
+extern int kvmppc_xive_set_mapped(struct kvm *kvm, unsigned long guest_irq,
+                                 struct irq_desc *host_desc);
+extern int kvmppc_xive_clr_mapped(struct kvm *kvm, unsigned long guest_irq,
+                                 struct irq_desc *host_desc);
+extern u64 kvmppc_xive_get_icp(struct kvm_vcpu *vcpu);
+extern int kvmppc_xive_set_icp(struct kvm_vcpu *vcpu, u64 icpval);
+
+extern int kvmppc_xive_set_irq(struct kvm *kvm, int irq_source_id, u32 irq,
+                              int level, bool line_status);
+#else
+static inline int kvmppc_xive_set_xive(struct kvm *kvm, u32 irq, u32 server,
+                                      u32 priority) { return -1; }
+static inline int kvmppc_xive_get_xive(struct kvm *kvm, u32 irq, u32 *server,
+                                      u32 *priority) { return -1; }
+static inline int kvmppc_xive_int_on(struct kvm *kvm, u32 irq) { return -1; }
+static inline int kvmppc_xive_int_off(struct kvm *kvm, u32 irq) { return -1; }
+static inline void kvmppc_xive_init_module(void) { }
+static inline void kvmppc_xive_exit_module(void) { }
+
+static inline int kvmppc_xive_connect_vcpu(struct kvm_device *dev,
+                                          struct kvm_vcpu *vcpu, u32 cpu) { return -EBUSY; }
+static inline void kvmppc_xive_cleanup_vcpu(struct kvm_vcpu *vcpu) { }
+static inline int kvmppc_xive_set_mapped(struct kvm *kvm, unsigned long guest_irq,
+                                        struct irq_desc *host_desc) { return -ENODEV; }
+static inline int kvmppc_xive_clr_mapped(struct kvm *kvm, unsigned long guest_irq,
+                                        struct irq_desc *host_desc) { return -ENODEV; }
+static inline u64 kvmppc_xive_get_icp(struct kvm_vcpu *vcpu) { return 0; }
+static inline int kvmppc_xive_set_icp(struct kvm_vcpu *vcpu, u64 icpval) { return -ENOENT; }
+
+static inline int kvmppc_xive_set_irq(struct kvm *kvm, int irq_source_id, u32 irq,
+                                     int level, bool line_status) { return -ENODEV; }
+#endif /* CONFIG_KVM_XIVE */
+
 /*
  * Prototypes for functions called only from assembler code.
  * Having prototypes reduces sparse errors.
@@ -562,6 +634,8 @@ long kvmppc_h_clear_mod(struct kvm_vcpu *vcpu, unsigned long flags,
 long kvmppc_hpte_hv_fault(struct kvm_vcpu *vcpu, unsigned long addr,
                           unsigned long slb_v, unsigned int status, bool data);
 unsigned long kvmppc_rm_h_xirr(struct kvm_vcpu *vcpu);
+unsigned long kvmppc_rm_h_xirr_x(struct kvm_vcpu *vcpu);
+unsigned long kvmppc_rm_h_ipoll(struct kvm_vcpu *vcpu, unsigned long server);
 int kvmppc_rm_h_ipi(struct kvm_vcpu *vcpu, unsigned long server,
                     unsigned long mfrr);
 int kvmppc_rm_h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr);
index 5011b69107a720b5a52cb4e80ba13019f2757d6b..f90b22c722e1861663a90ee88f23ec6fad49852e 100644 (file)
@@ -173,6 +173,8 @@ struct machdep_calls {
        /* Called after scan and before resource survey */
        void (*pcibios_fixup_phb)(struct pci_controller *hose);
 
+       resource_size_t (*pcibios_default_alignment)(void);
+
 #ifdef CONFIG_PCI_IOV
        void (*pcibios_fixup_sriov)(struct pci_dev *pdev);
        resource_size_t (*pcibios_iov_resource_alignment)(struct pci_dev *, int resno);
index 53885512b8d31b12acec28dc3ba6688e57fb9615..6c0132c7212f8ea484805c9a9f72b682b79f6a39 100644 (file)
 #include <asm-generic/module.h>
 
 
+#ifdef CC_USING_MPROFILE_KERNEL
+#define MODULE_ARCH_VERMAGIC   "mprofile-kernel"
+#endif
+
 #ifndef __powerpc64__
 /*
  * Thanks to Paul M for explaining this.
index 2a32483c7b6cd5db8bab609891a5fbb3ad1f7844..8da5d4c1cab2b6d52a297117c6e6b27221d941c6 100644 (file)
@@ -132,7 +132,19 @@ extern long long virt_phys_offset;
 #define virt_to_pfn(kaddr)     (__pa(kaddr) >> PAGE_SHIFT)
 #define virt_to_page(kaddr)    pfn_to_page(virt_to_pfn(kaddr))
 #define pfn_to_kaddr(pfn)      __va((pfn) << PAGE_SHIFT)
+
+#ifdef CONFIG_PPC_BOOK3S_64
+/*
+ * On hash the vmalloc and other regions alias to the kernel region when passed
+ * through __pa(), which virt_to_pfn() uses. That means virt_addr_valid() can
+ * return true for some vmalloc addresses, which is incorrect. So explicitly
+ * check that the address is in the kernel region.
+ */
+#define virt_addr_valid(kaddr) (REGION_ID(kaddr) == KERNEL_REGION_ID && \
+                               pfn_valid(virt_to_pfn(kaddr)))
+#else
 #define virt_addr_valid(kaddr) pfn_valid(virt_to_pfn(kaddr))
+#endif
 
 /*
  * On Book-E parts we need __va to parse the device tree and we can't
index 93eded8d38431eaf34fc7e2d0e2da9279088dce9..c8975dac535fc7ea907bc7577b13aee8fd989a8a 100644 (file)
@@ -77,12 +77,11 @@ extern int pci_domain_nr(struct pci_bus *bus);
 extern int pci_proc_domain(struct pci_bus *bus);
 
 struct vm_area_struct;
-/* Map a range of PCI memory or I/O space for a device into user space */
-int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
-                       enum pci_mmap_state mmap_state, int write_combine);
 
-/* Tell drivers/pci/proc.c that we have pci_mmap_page_range() */
-#define HAVE_PCI_MMAP  1
+/* Tell drivers/pci/proc.c that we have pci_mmap_page_range() and it does WC */
+#define HAVE_PCI_MMAP          1
+#define arch_can_pci_mmap_io() 1
+#define arch_can_pci_mmap_wc() 1
 
 extern int pci_legacy_read(struct pci_bus *bus, loff_t port, u32 *val,
                           size_t count);
index a4b1d8d6b793319ea062e74a2bdcbd3b434405ab..a2123f291ab0c5c8dc13cc9364c3a12848a4bb2c 100644 (file)
@@ -151,8 +151,13 @@ void release_thread(struct task_struct *);
 
 #ifdef __powerpc64__
 
+#ifdef CONFIG_PPC_BOOK3S_64
 /* Limit stack to 128TB */
 #define STACK_TOP_USER64 TASK_SIZE_128TB
+#else
+#define STACK_TOP_USER64 TASK_SIZE_USER64
+#endif
+
 #define STACK_TOP_USER32 TASK_SIZE_USER32
 
 #define STACK_TOP (is_32bit_task() ? \
index d4f653c9259a29745dbbcb5f451d7a48e55d9bcf..7e50e47375d63f8cdd11ba710cf18f5f0e442deb 100644 (file)
 #define PVR_POWER8E    0x004B
 #define PVR_POWER8NVL  0x004C
 #define PVR_POWER8     0x004D
+#define PVR_POWER9     0x004E
 #define PVR_BE         0x0070
 #define PVR_PA6T       0x0090
 
index 3cdbeaeac397e1bfafd74a2cea21b934ba3561a0..c8a822acf962ab95d3ef36c37abe70cc82f1c76e 100644 (file)
@@ -99,7 +99,6 @@ struct xive_q {
 #define XIVE_ESB_SET_PQ_01     0xd00
 #define XIVE_ESB_SET_PQ_10     0xe00
 #define XIVE_ESB_SET_PQ_11     0xf00
-#define XIVE_ESB_MASK          XIVE_ESB_SET_PQ_01
 
 #define XIVE_ESB_VAL_P         0x2
 #define XIVE_ESB_VAL_Q         0x1
@@ -136,11 +135,11 @@ extern int xive_native_configure_queue(u32 vp_id, struct xive_q *q, u8 prio,
                                       __be32 *qpage, u32 order, bool can_escalate);
 extern void xive_native_disable_queue(u32 vp_id, struct xive_q *q, u8 prio);
 
-extern bool __xive_irq_trigger(struct xive_irq_data *xd);
-extern bool __xive_irq_retrigger(struct xive_irq_data *xd);
-extern void xive_do_source_eoi(u32 hw_irq, struct xive_irq_data *xd);
-
+extern void xive_native_sync_source(u32 hw_irq);
 extern bool is_xive_irq(struct irq_chip *chip);
+extern int xive_native_enable_vp(u32 vp_id);
+extern int xive_native_disable_vp(u32 vp_id);
+extern int xive_native_get_vp_info(u32 vp_id, u32 *out_cam_id, u32 *out_chip_id);
 
 #else
 
index dab3717e3ea09db41c4db172aa675f27059843fc..b15bf6bc0e94f46f035e8781ffa921060341fe91 100644 (file)
@@ -1,47 +1,2 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
-
-header-y += auxvec.h
-header-y += bitsperlong.h
-header-y += bootx.h
-header-y += byteorder.h
-header-y += cputable.h
-header-y += eeh.h
-header-y += elf.h
-header-y += epapr_hcalls.h
-header-y += errno.h
-header-y += fcntl.h
-header-y += ioctl.h
-header-y += ioctls.h
-header-y += ipcbuf.h
-header-y += kvm.h
-header-y += kvm_para.h
-header-y += mman.h
-header-y += msgbuf.h
-header-y += nvram.h
-header-y += opal-prd.h
-header-y += param.h
-header-y += perf_event.h
-header-y += poll.h
-header-y += posix_types.h
-header-y += ps3fb.h
-header-y += ptrace.h
-header-y += resource.h
-header-y += sembuf.h
-header-y += setup.h
-header-y += shmbuf.h
-header-y += sigcontext.h
-header-y += siginfo.h
-header-y += signal.h
-header-y += socket.h
-header-y += sockios.h
-header-y += spu_info.h
-header-y += stat.h
-header-y += statfs.h
-header-y += swab.h
-header-y += termbits.h
-header-y += termios.h
-header-y += tm.h
-header-y += types.h
-header-y += ucontext.h
-header-y += unistd.h
index f63c96cd360863ac312aca929475de7629695169..3e7ce86d5c1330986289a72b0c38ea2686f6d6e6 100644 (file)
 #define PPC_FEATURE2_ARCH_3_00         0x00800000 /* ISA 3.00 */
 #define PPC_FEATURE2_HAS_IEEE128       0x00400000 /* VSX IEEE Binary Float 128-bit */
 
+/*
+ * IMPORTANT!
+ * All future PPC_FEATURE definitions should be allocated in cooperation with
+ * OPAL / skiboot firmware, in accordance with the ibm,powerpc-cpu-features
+ * device tree binding.
+ */
+
 #endif /* _UAPI__ASM_POWERPC_CPUTABLE_H */
index b9db46ae545bad7c2aab4e8566892ddb2a4ef481..e132902e1f1485797a49ba363ae3c039f45194a1 100644 (file)
@@ -56,6 +56,7 @@ obj-$(CONFIG_PPC_RTAS)                += rtas.o rtas-rtc.o $(rtaspci-y-y)
 obj-$(CONFIG_PPC_RTAS_DAEMON)  += rtasd.o
 obj-$(CONFIG_RTAS_FLASH)       += rtas_flash.o
 obj-$(CONFIG_RTAS_PROC)                += rtas-proc.o
+obj-$(CONFIG_PPC_DT_CPU_FTRS)  += dt_cpu_ftrs.o
 obj-$(CONFIG_EEH)              += eeh.o eeh_pe.o eeh_dev.o eeh_cache.o \
                                  eeh_driver.o eeh_event.o eeh_sysfs.o
 obj-$(CONFIG_GENERIC_TBSYNC)   += smp-tbsync.o
index 439c257dec4a3542380030ec5368521db801fbd5..709e23425317c8effa41c6531ea724fe96d5b471 100644 (file)
@@ -634,6 +634,8 @@ int main(void)
        HSTATE_FIELD(HSTATE_KVM_VCPU, kvm_vcpu);
        HSTATE_FIELD(HSTATE_KVM_VCORE, kvm_vcore);
        HSTATE_FIELD(HSTATE_XICS_PHYS, xics_phys);
+       HSTATE_FIELD(HSTATE_XIVE_TIMA_PHYS, xive_tima_phys);
+       HSTATE_FIELD(HSTATE_XIVE_TIMA_VIRT, xive_tima_virt);
        HSTATE_FIELD(HSTATE_SAVED_XIRR, saved_xirr);
        HSTATE_FIELD(HSTATE_HOST_IPI, host_ipi);
        HSTATE_FIELD(HSTATE_PTID, ptid);
@@ -719,6 +721,14 @@ int main(void)
        OFFSET(VCPU_HOST_MAS6, kvm_vcpu, arch.host_mas6);
 #endif
 
+#ifdef CONFIG_KVM_XICS
+       DEFINE(VCPU_XIVE_SAVED_STATE, offsetof(struct kvm_vcpu,
+                                              arch.xive_saved_state));
+       DEFINE(VCPU_XIVE_CAM_WORD, offsetof(struct kvm_vcpu,
+                                           arch.xive_cam_word));
+       DEFINE(VCPU_XIVE_PUSHED, offsetof(struct kvm_vcpu, arch.xive_pushed));
+#endif
+
 #ifdef CONFIG_KVM_EXIT_TIMING
        OFFSET(VCPU_TIMING_EXIT_TBU, kvm_vcpu, arch.timing_exit.tv32.tbu);
        OFFSET(VCPU_TIMING_EXIT_TBL, kvm_vcpu, arch.timing_exit.tv32.tbl);
index e79b9daa873c1874485021676426ea47196a5a68..9b3e88b1a9c83b041d9bd84ce9d17fdc87aaeaf7 100644 (file)
@@ -23,7 +23,9 @@
 #include <asm/mmu.h>
 #include <asm/setup.h>
 
-struct cpu_spec* cur_cpu_spec = NULL;
+static struct cpu_spec the_cpu_spec __read_mostly;
+
+struct cpu_spec* cur_cpu_spec __read_mostly = NULL;
 EXPORT_SYMBOL(cur_cpu_spec);
 
 /* The platform string corresponding to the real PVR */
@@ -2179,7 +2181,15 @@ static struct cpu_spec __initdata cpu_specs[] = {
 #endif /* CONFIG_E500 */
 };
 
-static struct cpu_spec the_cpu_spec;
+void __init set_cur_cpu_spec(struct cpu_spec *s)
+{
+       struct cpu_spec *t = &the_cpu_spec;
+
+       t = PTRRELOC(t);
+       *t = *s;
+
+       *PTRRELOC(&cur_cpu_spec) = &the_cpu_spec;
+}
 
 static struct cpu_spec * __init setup_cpu_spec(unsigned long offset,
                                               struct cpu_spec *s)
@@ -2266,6 +2276,29 @@ struct cpu_spec * __init identify_cpu(unsigned long offset, unsigned int pvr)
        return NULL;
 }
 
+/*
+ * Used by cpufeatures to get the name for CPUs with a PVR table.
+ * If they don't hae a PVR table, cpufeatures gets the name from
+ * cpu device-tree node.
+ */
+void __init identify_cpu_name(unsigned int pvr)
+{
+       struct cpu_spec *s = cpu_specs;
+       struct cpu_spec *t = &the_cpu_spec;
+       int i;
+
+       s = PTRRELOC(s);
+       t = PTRRELOC(t);
+
+       for (i = 0; i < ARRAY_SIZE(cpu_specs); i++,s++) {
+               if ((pvr & s->pvr_mask) == s->pvr_value) {
+                       t->cpu_name = s->cpu_name;
+                       return;
+               }
+       }
+}
+
+
 #ifdef CONFIG_JUMP_LABEL_FEATURE_CHECKS
 struct static_key_true cpu_feature_keys[NUM_CPU_FTR_KEYS] = {
                        [0 ... NUM_CPU_FTR_KEYS - 1] = STATIC_KEY_TRUE_INIT
index 47b63de81f9bf6a1894c4268cc37351e6d275ca4..cbabb5adccd958d66442f4af17d701225bc81ef8 100644 (file)
@@ -43,8 +43,6 @@
 #define IPI_TIMEOUT            10000
 #define REAL_MODE_TIMEOUT      10000
 
-/* This keeps a track of which one is the crashing cpu. */
-int crashing_cpu = -1;
 static int time_to_dump;
 
 #define CRASH_HANDLER_MAX 3
diff --git a/arch/powerpc/kernel/dt_cpu_ftrs.c b/arch/powerpc/kernel/dt_cpu_ftrs.c
new file mode 100644 (file)
index 0000000..fcc7588
--- /dev/null
@@ -0,0 +1,1031 @@
+/*
+ * Copyright 2017, Nicholas Piggin, IBM Corporation
+ * Licensed under GPLv2.
+ */
+
+#define pr_fmt(fmt) "dt-cpu-ftrs: " fmt
+
+#include <linux/export.h>
+#include <linux/init.h>
+#include <linux/jump_label.h>
+#include <linux/memblock.h>
+#include <linux/printk.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/threads.h>
+
+#include <asm/cputable.h>
+#include <asm/dt_cpu_ftrs.h>
+#include <asm/mmu.h>
+#include <asm/oprofile_impl.h>
+#include <asm/prom.h>
+#include <asm/setup.h>
+
+
+/* Device-tree visible constants follow */
+#define ISA_V2_07B      2070
+#define ISA_V3_0B       3000
+
+#define USABLE_PR               (1U << 0)
+#define USABLE_OS               (1U << 1)
+#define USABLE_HV               (1U << 2)
+
+#define HV_SUPPORT_HFSCR        (1U << 0)
+#define OS_SUPPORT_FSCR         (1U << 0)
+
+/* For parsing, we define all bits set as "NONE" case */
+#define HV_SUPPORT_NONE                0xffffffffU
+#define OS_SUPPORT_NONE                0xffffffffU
+
+struct dt_cpu_feature {
+       const char *name;
+       uint32_t isa;
+       uint32_t usable_privilege;
+       uint32_t hv_support;
+       uint32_t os_support;
+       uint32_t hfscr_bit_nr;
+       uint32_t fscr_bit_nr;
+       uint32_t hwcap_bit_nr;
+       /* fdt parsing */
+       unsigned long node;
+       int enabled;
+       int disabled;
+};
+
+#define CPU_FTRS_BASE \
+          (CPU_FTR_USE_TB | \
+           CPU_FTR_LWSYNC | \
+           CPU_FTR_FPU_UNAVAILABLE |\
+           CPU_FTR_NODSISRALIGN |\
+           CPU_FTR_NOEXECUTE |\
+           CPU_FTR_COHERENT_ICACHE | \
+           CPU_FTR_STCX_CHECKS_ADDRESS |\
+           CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
+           CPU_FTR_DAWR | \
+           CPU_FTR_ARCH_206 |\
+           CPU_FTR_ARCH_207S)
+
+#define MMU_FTRS_HASH_BASE (MMU_FTRS_POWER8)
+
+#define COMMON_USER_BASE       (PPC_FEATURE_32 | PPC_FEATURE_64 | \
+                                PPC_FEATURE_ARCH_2_06 |\
+                                PPC_FEATURE_ICACHE_SNOOP)
+#define COMMON_USER2_BASE      (PPC_FEATURE2_ARCH_2_07 | \
+                                PPC_FEATURE2_ISEL)
+/*
+ * Set up the base CPU
+ */
+
+extern void __flush_tlb_power8(unsigned int action);
+extern void __flush_tlb_power9(unsigned int action);
+extern long __machine_check_early_realmode_p8(struct pt_regs *regs);
+extern long __machine_check_early_realmode_p9(struct pt_regs *regs);
+
+static int hv_mode;
+
+static struct {
+       u64     lpcr;
+       u64     hfscr;
+       u64     fscr;
+} system_registers;
+
+static void (*init_pmu_registers)(void);
+
+static void cpufeatures_flush_tlb(void)
+{
+       unsigned long rb;
+       unsigned int i, num_sets;
+
+       /*
+        * This is a temporary measure to keep equivalent TLB flush as the
+        * cputable based setup code.
+        */
+       switch (PVR_VER(mfspr(SPRN_PVR))) {
+       case PVR_POWER8:
+       case PVR_POWER8E:
+       case PVR_POWER8NVL:
+               num_sets = POWER8_TLB_SETS;
+               break;
+       case PVR_POWER9:
+               num_sets = POWER9_TLB_SETS_HASH;
+               break;
+       default:
+               num_sets = 1;
+               pr_err("unknown CPU version for boot TLB flush\n");
+               break;
+       }
+
+       asm volatile("ptesync" : : : "memory");
+       rb = TLBIEL_INVAL_SET;
+       for (i = 0; i < num_sets; i++) {
+               asm volatile("tlbiel %0" : : "r" (rb));
+               rb += 1 << TLBIEL_INVAL_SET_SHIFT;
+       }
+       asm volatile("ptesync" : : : "memory");
+}
+
+static void __restore_cpu_cpufeatures(void)
+{
+       /*
+        * LPCR is restored by the power on engine already. It can be changed
+        * after early init e.g., by radix enable, and we have no unified API
+        * for saving and restoring such SPRs.
+        *
+        * This ->restore hook should really be removed from idle and register
+        * restore moved directly into the idle restore code, because this code
+        * doesn't know how idle is implemented or what it needs restored here.
+        *
+        * The best we can do to accommodate secondary boot and idle restore
+        * for now is "or" LPCR with existing.
+        */
+
+       mtspr(SPRN_LPCR, system_registers.lpcr | mfspr(SPRN_LPCR));
+       if (hv_mode) {
+               mtspr(SPRN_LPID, 0);
+               mtspr(SPRN_HFSCR, system_registers.hfscr);
+       }
+       mtspr(SPRN_FSCR, system_registers.fscr);
+
+       if (init_pmu_registers)
+               init_pmu_registers();
+
+       cpufeatures_flush_tlb();
+}
+
+static char dt_cpu_name[64];
+
+static struct cpu_spec __initdata base_cpu_spec = {
+       .cpu_name               = NULL,
+       .cpu_features           = CPU_FTRS_BASE,
+       .cpu_user_features      = COMMON_USER_BASE,
+       .cpu_user_features2     = COMMON_USER2_BASE,
+       .mmu_features           = 0,
+       .icache_bsize           = 32, /* minimum block size, fixed by */
+       .dcache_bsize           = 32, /* cache info init.             */
+       .num_pmcs               = 0,
+       .pmc_type               = PPC_PMC_DEFAULT,
+       .oprofile_cpu_type      = NULL,
+       .oprofile_type          = PPC_OPROFILE_INVALID,
+       .cpu_setup              = NULL,
+       .cpu_restore            = __restore_cpu_cpufeatures,
+       .flush_tlb              = NULL,
+       .machine_check_early    = NULL,
+       .platform               = NULL,
+};
+
+static void __init cpufeatures_setup_cpu(void)
+{
+       set_cur_cpu_spec(&base_cpu_spec);
+
+       cur_cpu_spec->pvr_mask = -1;
+       cur_cpu_spec->pvr_value = mfspr(SPRN_PVR);
+
+       /* Initialize the base environment -- clear FSCR/HFSCR.  */
+       hv_mode = !!(mfmsr() & MSR_HV);
+       if (hv_mode) {
+               /* CPU_FTR_HVMODE is used early in PACA setup */
+               cur_cpu_spec->cpu_features |= CPU_FTR_HVMODE;
+               mtspr(SPRN_HFSCR, 0);
+       }
+       mtspr(SPRN_FSCR, 0);
+
+       /*
+        * LPCR does not get cleared, to match behaviour with secondaries
+        * in __restore_cpu_cpufeatures. Once the idle code is fixed, this
+        * could clear LPCR too.
+        */
+}
+
+static int __init feat_try_enable_unknown(struct dt_cpu_feature *f)
+{
+       if (f->hv_support == HV_SUPPORT_NONE) {
+       } else if (f->hv_support & HV_SUPPORT_HFSCR) {
+               u64 hfscr = mfspr(SPRN_HFSCR);
+               hfscr |= 1UL << f->hfscr_bit_nr;
+               mtspr(SPRN_HFSCR, hfscr);
+       } else {
+               /* Does not have a known recipe */
+               return 0;
+       }
+
+       if (f->os_support == OS_SUPPORT_NONE) {
+       } else if (f->os_support & OS_SUPPORT_FSCR) {
+               u64 fscr = mfspr(SPRN_FSCR);
+               fscr |= 1UL << f->fscr_bit_nr;
+               mtspr(SPRN_FSCR, fscr);
+       } else {
+               /* Does not have a known recipe */
+               return 0;
+       }
+
+       if ((f->usable_privilege & USABLE_PR) && (f->hwcap_bit_nr != -1)) {
+               uint32_t word = f->hwcap_bit_nr / 32;
+               uint32_t bit = f->hwcap_bit_nr % 32;
+
+               if (word == 0)
+                       cur_cpu_spec->cpu_user_features |= 1U << bit;
+               else if (word == 1)
+                       cur_cpu_spec->cpu_user_features2 |= 1U << bit;
+               else
+                       pr_err("%s could not advertise to user (no hwcap bits)\n", f->name);
+       }
+
+       return 1;
+}
+
+static int __init feat_enable(struct dt_cpu_feature *f)
+{
+       if (f->hv_support != HV_SUPPORT_NONE) {
+               if (f->hfscr_bit_nr != -1) {
+                       u64 hfscr = mfspr(SPRN_HFSCR);
+                       hfscr |= 1UL << f->hfscr_bit_nr;
+                       mtspr(SPRN_HFSCR, hfscr);
+               }
+       }
+
+       if (f->os_support != OS_SUPPORT_NONE) {
+               if (f->fscr_bit_nr != -1) {
+                       u64 fscr = mfspr(SPRN_FSCR);
+                       fscr |= 1UL << f->fscr_bit_nr;
+                       mtspr(SPRN_FSCR, fscr);
+               }
+       }
+
+       if ((f->usable_privilege & USABLE_PR) && (f->hwcap_bit_nr != -1)) {
+               uint32_t word = f->hwcap_bit_nr / 32;
+               uint32_t bit = f->hwcap_bit_nr % 32;
+
+               if (word == 0)
+                       cur_cpu_spec->cpu_user_features |= 1U << bit;
+               else if (word == 1)
+                       cur_cpu_spec->cpu_user_features2 |= 1U << bit;
+               else
+                       pr_err("CPU feature: %s could not advertise to user (no hwcap bits)\n", f->name);
+       }
+
+       return 1;
+}
+
+static int __init feat_disable(struct dt_cpu_feature *f)
+{
+       return 0;
+}
+
+static int __init feat_enable_hv(struct dt_cpu_feature *f)
+{
+       u64 lpcr;
+
+       if (!hv_mode) {
+               pr_err("CPU feature hypervisor present in device tree but HV mode not enabled in the CPU. Ignoring.\n");
+               return 0;
+       }
+
+       mtspr(SPRN_LPID, 0);
+
+       lpcr = mfspr(SPRN_LPCR);
+       lpcr &=  ~LPCR_LPES0; /* HV external interrupts */
+       mtspr(SPRN_LPCR, lpcr);
+
+       cur_cpu_spec->cpu_features |= CPU_FTR_HVMODE;
+
+       return 1;
+}
+
+static int __init feat_enable_le(struct dt_cpu_feature *f)
+{
+       cur_cpu_spec->cpu_user_features |= PPC_FEATURE_TRUE_LE;
+       return 1;
+}
+
+static int __init feat_enable_smt(struct dt_cpu_feature *f)
+{
+       cur_cpu_spec->cpu_features |= CPU_FTR_SMT;
+       cur_cpu_spec->cpu_user_features |= PPC_FEATURE_SMT;
+       return 1;
+}
+
+static int __init feat_enable_idle_nap(struct dt_cpu_feature *f)
+{
+       u64 lpcr;
+
+       /* Set PECE wakeup modes for ISA 207 */
+       lpcr = mfspr(SPRN_LPCR);
+       lpcr |=  LPCR_PECE0;
+       lpcr |=  LPCR_PECE1;
+       lpcr |=  LPCR_PECE2;
+       mtspr(SPRN_LPCR, lpcr);
+
+       return 1;
+}
+
+static int __init feat_enable_align_dsisr(struct dt_cpu_feature *f)
+{
+       cur_cpu_spec->cpu_features &= ~CPU_FTR_NODSISRALIGN;
+
+       return 1;
+}
+
+static int __init feat_enable_idle_stop(struct dt_cpu_feature *f)
+{
+       u64 lpcr;
+
+       /* Set PECE wakeup modes for ISAv3.0B */
+       lpcr = mfspr(SPRN_LPCR);
+       lpcr |=  LPCR_PECE0;
+       lpcr |=  LPCR_PECE1;
+       lpcr |=  LPCR_PECE2;
+       mtspr(SPRN_LPCR, lpcr);
+
+       return 1;
+}
+
+static int __init feat_enable_mmu_hash(struct dt_cpu_feature *f)
+{
+       u64 lpcr;
+
+       lpcr = mfspr(SPRN_LPCR);
+       lpcr &= ~LPCR_ISL;
+
+       /* VRMASD */
+       lpcr |= LPCR_VPM0;
+       lpcr &= ~LPCR_VPM1;
+       lpcr |= 0x10UL << LPCR_VRMASD_SH; /* L=1 LP=00 */
+       mtspr(SPRN_LPCR, lpcr);
+
+       cur_cpu_spec->mmu_features |= MMU_FTRS_HASH_BASE;
+       cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_MMU;
+
+       return 1;
+}
+
+static int __init feat_enable_mmu_hash_v3(struct dt_cpu_feature *f)
+{
+       u64 lpcr;
+
+       lpcr = mfspr(SPRN_LPCR);
+       lpcr &= ~LPCR_ISL;
+       mtspr(SPRN_LPCR, lpcr);
+
+       cur_cpu_spec->mmu_features |= MMU_FTRS_HASH_BASE;
+       cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_MMU;
+
+       return 1;
+}
+
+
+static int __init feat_enable_mmu_radix(struct dt_cpu_feature *f)
+{
+#ifdef CONFIG_PPC_RADIX_MMU
+       cur_cpu_spec->mmu_features |= MMU_FTR_TYPE_RADIX;
+       cur_cpu_spec->mmu_features |= MMU_FTRS_HASH_BASE;
+       cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_MMU;
+
+       return 1;
+#endif
+       return 0;
+}
+
+static int __init feat_enable_dscr(struct dt_cpu_feature *f)
+{
+       u64 lpcr;
+
+       feat_enable(f);
+
+       lpcr = mfspr(SPRN_LPCR);
+       lpcr &= ~LPCR_DPFD;
+       lpcr |=  (4UL << LPCR_DPFD_SH);
+       mtspr(SPRN_LPCR, lpcr);
+
+       return 1;
+}
+
+static void hfscr_pmu_enable(void)
+{
+       u64 hfscr = mfspr(SPRN_HFSCR);
+       hfscr |= PPC_BIT(60);
+       mtspr(SPRN_HFSCR, hfscr);
+}
+
+static void init_pmu_power8(void)
+{
+       if (hv_mode) {
+               mtspr(SPRN_MMCRC, 0);
+               mtspr(SPRN_MMCRH, 0);
+       }
+
+       mtspr(SPRN_MMCRA, 0);
+       mtspr(SPRN_MMCR0, 0);
+       mtspr(SPRN_MMCR1, 0);
+       mtspr(SPRN_MMCR2, 0);
+       mtspr(SPRN_MMCRS, 0);
+}
+
+static int __init feat_enable_mce_power8(struct dt_cpu_feature *f)
+{
+       cur_cpu_spec->platform = "power8";
+       cur_cpu_spec->flush_tlb = __flush_tlb_power8;
+       cur_cpu_spec->machine_check_early = __machine_check_early_realmode_p8;
+
+       return 1;
+}
+
+static int __init feat_enable_pmu_power8(struct dt_cpu_feature *f)
+{
+       hfscr_pmu_enable();
+
+       init_pmu_power8();
+       init_pmu_registers = init_pmu_power8;
+
+       cur_cpu_spec->cpu_features |= CPU_FTR_MMCRA;
+       cur_cpu_spec->cpu_user_features |= PPC_FEATURE_PSERIES_PERFMON_COMPAT;
+       if (pvr_version_is(PVR_POWER8E))
+               cur_cpu_spec->cpu_features |= CPU_FTR_PMAO_BUG;
+
+       cur_cpu_spec->num_pmcs          = 6;
+       cur_cpu_spec->pmc_type          = PPC_PMC_IBM;
+       cur_cpu_spec->oprofile_cpu_type = "ppc64/power8";
+
+       return 1;
+}
+
+static void init_pmu_power9(void)
+{
+       if (hv_mode)
+               mtspr(SPRN_MMCRC, 0);
+
+       mtspr(SPRN_MMCRA, 0);
+       mtspr(SPRN_MMCR0, 0);
+       mtspr(SPRN_MMCR1, 0);
+       mtspr(SPRN_MMCR2, 0);
+}
+
+static int __init feat_enable_mce_power9(struct dt_cpu_feature *f)
+{
+       cur_cpu_spec->platform = "power9";
+       cur_cpu_spec->flush_tlb = __flush_tlb_power9;
+       cur_cpu_spec->machine_check_early = __machine_check_early_realmode_p9;
+
+       return 1;
+}
+
+static int __init feat_enable_pmu_power9(struct dt_cpu_feature *f)
+{
+       hfscr_pmu_enable();
+
+       init_pmu_power9();
+       init_pmu_registers = init_pmu_power9;
+
+       cur_cpu_spec->cpu_features |= CPU_FTR_MMCRA;
+       cur_cpu_spec->cpu_user_features |= PPC_FEATURE_PSERIES_PERFMON_COMPAT;
+
+       cur_cpu_spec->num_pmcs          = 6;
+       cur_cpu_spec->pmc_type          = PPC_PMC_IBM;
+       cur_cpu_spec->oprofile_cpu_type = "ppc64/power9";
+
+       return 1;
+}
+
+static int __init feat_enable_tm(struct dt_cpu_feature *f)
+{
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+       feat_enable(f);
+       cur_cpu_spec->cpu_user_features2 |= PPC_FEATURE2_HTM_NOSC;
+       return 1;
+#endif
+       return 0;
+}
+
+static int __init feat_enable_fp(struct dt_cpu_feature *f)
+{
+       feat_enable(f);
+       cur_cpu_spec->cpu_features &= ~CPU_FTR_FPU_UNAVAILABLE;
+
+       return 1;
+}
+
+static int __init feat_enable_vector(struct dt_cpu_feature *f)
+{
+#ifdef CONFIG_ALTIVEC
+       feat_enable(f);
+       cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC;
+       cur_cpu_spec->cpu_features |= CPU_FTR_VMX_COPY;
+       cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC;
+
+       return 1;
+#endif
+       return 0;
+}
+
+static int __init feat_enable_vsx(struct dt_cpu_feature *f)
+{
+#ifdef CONFIG_VSX
+       feat_enable(f);
+       cur_cpu_spec->cpu_features |= CPU_FTR_VSX;
+       cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_VSX;
+
+       return 1;
+#endif
+       return 0;
+}
+
+static int __init feat_enable_purr(struct dt_cpu_feature *f)
+{
+       cur_cpu_spec->cpu_features |= CPU_FTR_PURR | CPU_FTR_SPURR;
+
+       return 1;
+}
+
+static int __init feat_enable_ebb(struct dt_cpu_feature *f)
+{
+       /*
+        * PPC_FEATURE2_EBB is enabled in PMU init code because it has
+        * historically been related to the PMU facility. This may have
+        * to be decoupled if EBB becomes more generic. For now, follow
+        * existing convention.
+        */
+       f->hwcap_bit_nr = -1;
+       feat_enable(f);
+
+       return 1;
+}
+
+static int __init feat_enable_dbell(struct dt_cpu_feature *f)
+{
+       u64 lpcr;
+
+       /* P9 has an HFSCR for privileged state */
+       feat_enable(f);
+
+       cur_cpu_spec->cpu_features |= CPU_FTR_DBELL;
+
+       lpcr = mfspr(SPRN_LPCR);
+       lpcr |=  LPCR_PECEDH; /* hyp doorbell wakeup */
+       mtspr(SPRN_LPCR, lpcr);
+
+       return 1;
+}
+
+static int __init feat_enable_hvi(struct dt_cpu_feature *f)
+{
+       u64 lpcr;
+
+       /*
+        * POWER9 XIVE interrupts including in OPAL XICS compatibility
+        * are always delivered as hypervisor virtualization interrupts (HVI)
+        * rather than EE.
+        *
+        * However LPES0 is not set here, in the chance that an EE does get
+        * delivered to the host somehow, the EE handler would not expect it
+        * to be delivered in LPES0 mode (e.g., using SRR[01]). This could
+        * happen if there is a bug in interrupt controller code, or IC is
+        * misconfigured in systemsim.
+        */
+
+       lpcr = mfspr(SPRN_LPCR);
+       lpcr |= LPCR_HVICE;     /* enable hvi interrupts */
+       lpcr |= LPCR_HEIC;      /* disable ee interrupts when MSR_HV */
+       lpcr |= LPCR_PECE_HVEE; /* hvi can wake from stop */
+       mtspr(SPRN_LPCR, lpcr);
+
+       return 1;
+}
+
+static int __init feat_enable_large_ci(struct dt_cpu_feature *f)
+{
+       cur_cpu_spec->mmu_features |= MMU_FTR_CI_LARGE_PAGE;
+
+       return 1;
+}
+
+struct dt_cpu_feature_match {
+       const char *name;
+       int (*enable)(struct dt_cpu_feature *f);
+       u64 cpu_ftr_bit_mask;
+};
+
+static struct dt_cpu_feature_match __initdata
+               dt_cpu_feature_match_table[] = {
+       {"hypervisor", feat_enable_hv, 0},
+       {"big-endian", feat_enable, 0},
+       {"little-endian", feat_enable_le, CPU_FTR_REAL_LE},
+       {"smt", feat_enable_smt, 0},
+       {"interrupt-facilities", feat_enable, 0},
+       {"timer-facilities", feat_enable, 0},
+       {"timer-facilities-v3", feat_enable, 0},
+       {"debug-facilities", feat_enable, 0},
+       {"come-from-address-register", feat_enable, CPU_FTR_CFAR},
+       {"branch-tracing", feat_enable, 0},
+       {"floating-point", feat_enable_fp, 0},
+       {"vector", feat_enable_vector, 0},
+       {"vector-scalar", feat_enable_vsx, 0},
+       {"vector-scalar-v3", feat_enable, 0},
+       {"decimal-floating-point", feat_enable, 0},
+       {"decimal-integer", feat_enable, 0},
+       {"quadword-load-store", feat_enable, 0},
+       {"vector-crypto", feat_enable, 0},
+       {"mmu-hash", feat_enable_mmu_hash, 0},
+       {"mmu-radix", feat_enable_mmu_radix, 0},
+       {"mmu-hash-v3", feat_enable_mmu_hash_v3, 0},
+       {"virtual-page-class-key-protection", feat_enable, 0},
+       {"transactional-memory", feat_enable_tm, CPU_FTR_TM},
+       {"transactional-memory-v3", feat_enable_tm, 0},
+       {"idle-nap", feat_enable_idle_nap, 0},
+       {"alignment-interrupt-dsisr", feat_enable_align_dsisr, 0},
+       {"idle-stop", feat_enable_idle_stop, 0},
+       {"machine-check-power8", feat_enable_mce_power8, 0},
+       {"performance-monitor-power8", feat_enable_pmu_power8, 0},
+       {"data-stream-control-register", feat_enable_dscr, CPU_FTR_DSCR},
+       {"event-based-branch", feat_enable_ebb, 0},
+       {"target-address-register", feat_enable, 0},
+       {"branch-history-rolling-buffer", feat_enable, 0},
+       {"control-register", feat_enable, CPU_FTR_CTRL},
+       {"processor-control-facility", feat_enable_dbell, CPU_FTR_DBELL},
+       {"processor-control-facility-v3", feat_enable_dbell, CPU_FTR_DBELL},
+       {"processor-utilization-of-resources-register", feat_enable_purr, 0},
+       {"subcore", feat_enable, CPU_FTR_SUBCORE},
+       {"no-execute", feat_enable, 0},
+       {"strong-access-ordering", feat_enable, CPU_FTR_SAO},
+       {"cache-inhibited-large-page", feat_enable_large_ci, 0},
+       {"coprocessor-icswx", feat_enable, CPU_FTR_ICSWX},
+       {"hypervisor-virtualization-interrupt", feat_enable_hvi, 0},
+       {"program-priority-register", feat_enable, CPU_FTR_HAS_PPR},
+       {"wait", feat_enable, 0},
+       {"atomic-memory-operations", feat_enable, 0},
+       {"branch-v3", feat_enable, 0},
+       {"copy-paste", feat_enable, 0},
+       {"decimal-floating-point-v3", feat_enable, 0},
+       {"decimal-integer-v3", feat_enable, 0},
+       {"fixed-point-v3", feat_enable, 0},
+       {"floating-point-v3", feat_enable, 0},
+       {"group-start-register", feat_enable, 0},
+       {"pc-relative-addressing", feat_enable, 0},
+       {"machine-check-power9", feat_enable_mce_power9, 0},
+       {"performance-monitor-power9", feat_enable_pmu_power9, 0},
+       {"event-based-branch-v3", feat_enable, 0},
+       {"random-number-generator", feat_enable, 0},
+       {"system-call-vectored", feat_disable, 0},
+       {"trace-interrupt-v3", feat_enable, 0},
+       {"vector-v3", feat_enable, 0},
+       {"vector-binary128", feat_enable, 0},
+       {"vector-binary16", feat_enable, 0},
+       {"wait-v3", feat_enable, 0},
+};
+
+/* XXX: how to configure this? Default + boot time? */
+#ifdef CONFIG_PPC_CPUFEATURES_ENABLE_UNKNOWN
+#define CPU_FEATURE_ENABLE_UNKNOWN 1
+#else
+#define CPU_FEATURE_ENABLE_UNKNOWN 0
+#endif
+
+static void __init cpufeatures_setup_start(u32 isa)
+{
+       pr_info("setup for ISA %d\n", isa);
+
+       if (isa >= 3000) {
+               cur_cpu_spec->cpu_features |= CPU_FTR_ARCH_300;
+               cur_cpu_spec->cpu_user_features2 |= PPC_FEATURE2_ARCH_3_00;
+       }
+}
+
+static bool __init cpufeatures_process_feature(struct dt_cpu_feature *f)
+{
+       const struct dt_cpu_feature_match *m;
+       bool known = false;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(dt_cpu_feature_match_table); i++) {
+               m = &dt_cpu_feature_match_table[i];
+               if (!strcmp(f->name, m->name)) {
+                       known = true;
+                       if (m->enable(f))
+                               break;
+
+                       pr_info("not enabling: %s (disabled or unsupported by kernel)\n",
+                               f->name);
+                       return false;
+               }
+       }
+
+       if (!known && CPU_FEATURE_ENABLE_UNKNOWN) {
+               if (!feat_try_enable_unknown(f)) {
+                       pr_info("not enabling: %s (unknown and unsupported by kernel)\n",
+                               f->name);
+                       return false;
+               }
+       }
+
+       if (m->cpu_ftr_bit_mask)
+               cur_cpu_spec->cpu_features |= m->cpu_ftr_bit_mask;
+
+       if (known)
+               pr_debug("enabling: %s\n", f->name);
+       else
+               pr_debug("enabling: %s (unknown)\n", f->name);
+
+       return true;
+}
+
+static __init void cpufeatures_cpu_quirks(void)
+{
+       int version = mfspr(SPRN_PVR);
+
+       /*
+        * Not all quirks can be derived from the cpufeatures device tree.
+        */
+       if ((version & 0xffffff00) == 0x004e0100)
+               cur_cpu_spec->cpu_features |= CPU_FTR_POWER9_DD1;
+}
+
+static void __init cpufeatures_setup_finished(void)
+{
+       cpufeatures_cpu_quirks();
+
+       if (hv_mode && !(cur_cpu_spec->cpu_features & CPU_FTR_HVMODE)) {
+               pr_err("hypervisor not present in device tree but HV mode is enabled in the CPU. Enabling.\n");
+               cur_cpu_spec->cpu_features |= CPU_FTR_HVMODE;
+       }
+
+       system_registers.lpcr = mfspr(SPRN_LPCR);
+       system_registers.hfscr = mfspr(SPRN_HFSCR);
+       system_registers.fscr = mfspr(SPRN_FSCR);
+
+       cpufeatures_flush_tlb();
+
+       pr_info("final cpu/mmu features = 0x%016lx 0x%08x\n",
+               cur_cpu_spec->cpu_features, cur_cpu_spec->mmu_features);
+}
+
+static int __init fdt_find_cpu_features(unsigned long node, const char *uname,
+                                       int depth, void *data)
+{
+       if (of_flat_dt_is_compatible(node, "ibm,powerpc-cpu-features")
+           && of_get_flat_dt_prop(node, "isa", NULL))
+               return 1;
+
+       return 0;
+}
+
+static bool __initdata using_dt_cpu_ftrs = false;
+
+bool __init dt_cpu_ftrs_in_use(void)
+{
+       return using_dt_cpu_ftrs;
+}
+
+bool __init dt_cpu_ftrs_init(void *fdt)
+{
+       /* Setup and verify the FDT, if it fails we just bail */
+       if (!early_init_dt_verify(fdt))
+               return false;
+
+       if (!of_scan_flat_dt(fdt_find_cpu_features, NULL))
+               return false;
+
+       cpufeatures_setup_cpu();
+
+       using_dt_cpu_ftrs = true;
+       return true;
+}
+
+static int nr_dt_cpu_features;
+static struct dt_cpu_feature *dt_cpu_features;
+
+static int __init process_cpufeatures_node(unsigned long node,
+                                         const char *uname, int i)
+{
+       const __be32 *prop;
+       struct dt_cpu_feature *f;
+       int len;
+
+       f = &dt_cpu_features[i];
+       memset(f, 0, sizeof(struct dt_cpu_feature));
+
+       f->node = node;
+
+       f->name = uname;
+
+       prop = of_get_flat_dt_prop(node, "isa", &len);
+       if (!prop) {
+               pr_warn("%s: missing isa property\n", uname);
+               return 0;
+       }
+       f->isa = be32_to_cpup(prop);
+
+       prop = of_get_flat_dt_prop(node, "usable-privilege", &len);
+       if (!prop) {
+               pr_warn("%s: missing usable-privilege property", uname);
+               return 0;
+       }
+       f->usable_privilege = be32_to_cpup(prop);
+
+       prop = of_get_flat_dt_prop(node, "hv-support", &len);
+       if (prop)
+               f->hv_support = be32_to_cpup(prop);
+       else
+               f->hv_support = HV_SUPPORT_NONE;
+
+       prop = of_get_flat_dt_prop(node, "os-support", &len);
+       if (prop)
+               f->os_support = be32_to_cpup(prop);
+       else
+               f->os_support = OS_SUPPORT_NONE;
+
+       prop = of_get_flat_dt_prop(node, "hfscr-bit-nr", &len);
+       if (prop)
+               f->hfscr_bit_nr = be32_to_cpup(prop);
+       else
+               f->hfscr_bit_nr = -1;
+       prop = of_get_flat_dt_prop(node, "fscr-bit-nr", &len);
+       if (prop)
+               f->fscr_bit_nr = be32_to_cpup(prop);
+       else
+               f->fscr_bit_nr = -1;
+       prop = of_get_flat_dt_prop(node, "hwcap-bit-nr", &len);
+       if (prop)
+               f->hwcap_bit_nr = be32_to_cpup(prop);
+       else
+               f->hwcap_bit_nr = -1;
+
+       if (f->usable_privilege & USABLE_HV) {
+               if (!(mfmsr() & MSR_HV)) {
+                       pr_warn("%s: HV feature passed to guest\n", uname);
+                       return 0;
+               }
+
+               if (f->hv_support == HV_SUPPORT_NONE && f->hfscr_bit_nr != -1) {
+                       pr_warn("%s: unwanted hfscr_bit_nr\n", uname);
+                       return 0;
+               }
+
+               if (f->hv_support == HV_SUPPORT_HFSCR) {
+                       if (f->hfscr_bit_nr == -1) {
+                               pr_warn("%s: missing hfscr_bit_nr\n", uname);
+                               return 0;
+                       }
+               }
+       } else {
+               if (f->hv_support != HV_SUPPORT_NONE || f->hfscr_bit_nr != -1) {
+                       pr_warn("%s: unwanted hv_support/hfscr_bit_nr\n", uname);
+                       return 0;
+               }
+       }
+
+       if (f->usable_privilege & USABLE_OS) {
+               if (f->os_support == OS_SUPPORT_NONE && f->fscr_bit_nr != -1) {
+                       pr_warn("%s: unwanted fscr_bit_nr\n", uname);
+                       return 0;
+               }
+
+               if (f->os_support == OS_SUPPORT_FSCR) {
+                       if (f->fscr_bit_nr == -1) {
+                               pr_warn("%s: missing fscr_bit_nr\n", uname);
+                               return 0;
+                       }
+               }
+       } else {
+               if (f->os_support != OS_SUPPORT_NONE || f->fscr_bit_nr != -1) {
+                       pr_warn("%s: unwanted os_support/fscr_bit_nr\n", uname);
+                       return 0;
+               }
+       }
+
+       if (!(f->usable_privilege & USABLE_PR)) {
+               if (f->hwcap_bit_nr != -1) {
+                       pr_warn("%s: unwanted hwcap_bit_nr\n", uname);
+                       return 0;
+               }
+       }
+
+       /* Do all the independent features in the first pass */
+       if (!of_get_flat_dt_prop(node, "dependencies", &len)) {
+               if (cpufeatures_process_feature(f))
+                       f->enabled = 1;
+               else
+                       f->disabled = 1;
+       }
+
+       return 0;
+}
+
+static void __init cpufeatures_deps_enable(struct dt_cpu_feature *f)
+{
+       const __be32 *prop;
+       int len;
+       int nr_deps;
+       int i;
+
+       if (f->enabled || f->disabled)
+               return;
+
+       prop = of_get_flat_dt_prop(f->node, "dependencies", &len);
+       if (!prop) {
+               pr_warn("%s: missing dependencies property", f->name);
+               return;
+       }
+
+       nr_deps = len / sizeof(int);
+
+       for (i = 0; i < nr_deps; i++) {
+               unsigned long phandle = be32_to_cpu(prop[i]);
+               int j;
+
+               for (j = 0; j < nr_dt_cpu_features; j++) {
+                       struct dt_cpu_feature *d = &dt_cpu_features[j];
+
+                       if (of_get_flat_dt_phandle(d->node) == phandle) {
+                               cpufeatures_deps_enable(d);
+                               if (d->disabled) {
+                                       f->disabled = 1;
+                                       return;
+                               }
+                       }
+               }
+       }
+
+       if (cpufeatures_process_feature(f))
+               f->enabled = 1;
+       else
+               f->disabled = 1;
+}
+
+static int __init scan_cpufeatures_subnodes(unsigned long node,
+                                         const char *uname,
+                                         void *data)
+{
+       int *count = data;
+
+       process_cpufeatures_node(node, uname, *count);
+
+       (*count)++;
+
+       return 0;
+}
+
+static int __init count_cpufeatures_subnodes(unsigned long node,
+                                         const char *uname,
+                                         void *data)
+{
+       int *count = data;
+
+       (*count)++;
+
+       return 0;
+}
+
+static int __init dt_cpu_ftrs_scan_callback(unsigned long node, const char
+                                           *uname, int depth, void *data)
+{
+       const __be32 *prop;
+       int count, i;
+       u32 isa;
+
+       /* We are scanning "ibm,powerpc-cpu-features" nodes only */
+       if (!of_flat_dt_is_compatible(node, "ibm,powerpc-cpu-features"))
+               return 0;
+
+       prop = of_get_flat_dt_prop(node, "isa", NULL);
+       if (!prop)
+               /* We checked before, "can't happen" */
+               return 0;
+
+       isa = be32_to_cpup(prop);
+
+       /* Count and allocate space for cpu features */
+       of_scan_flat_dt_subnodes(node, count_cpufeatures_subnodes,
+                                               &nr_dt_cpu_features);
+       dt_cpu_features = __va(
+               memblock_alloc(sizeof(struct dt_cpu_feature)*
+                               nr_dt_cpu_features, PAGE_SIZE));
+
+       cpufeatures_setup_start(isa);
+
+       /* Scan nodes into dt_cpu_features and enable those without deps  */
+       count = 0;
+       of_scan_flat_dt_subnodes(node, scan_cpufeatures_subnodes, &count);
+
+       /* Recursive enable remaining features with dependencies */
+       for (i = 0; i < nr_dt_cpu_features; i++) {
+               struct dt_cpu_feature *f = &dt_cpu_features[i];
+
+               cpufeatures_deps_enable(f);
+       }
+
+       prop = of_get_flat_dt_prop(node, "display-name", NULL);
+       if (prop && strlen((char *)prop) != 0) {
+               strlcpy(dt_cpu_name, (char *)prop, sizeof(dt_cpu_name));
+               cur_cpu_spec->cpu_name = dt_cpu_name;
+       }
+
+       cpufeatures_setup_finished();
+
+       memblock_free(__pa(dt_cpu_features),
+                       sizeof(struct dt_cpu_feature)*nr_dt_cpu_features);
+
+       return 0;
+}
+
+void __init dt_cpu_ftrs_scan(void)
+{
+       of_scan_flat_dt(dt_cpu_ftrs_scan_callback, NULL);
+}
index 45b453e4d0c87bf62c9100461bc33fb165f29931..acd8ca76233e871658bdb2b948d2652d273e0357 100644 (file)
@@ -735,8 +735,14 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
        andis.  r15,r14,(DBSR_IC|DBSR_BT)@h
        beq+    1f
 
+#ifdef CONFIG_RELOCATABLE
+       ld      r15,PACATOC(r13)
+       ld      r14,interrupt_base_book3e@got(r15)
+       ld      r15,__end_interrupts@got(r15)
+#else
        LOAD_REG_IMMEDIATE(r14,interrupt_base_book3e)
        LOAD_REG_IMMEDIATE(r15,__end_interrupts)
+#endif
        cmpld   cr0,r10,r14
        cmpld   cr1,r10,r15
        blt+    cr0,1f
@@ -799,8 +805,14 @@ kernel_dbg_exc:
        andis.  r15,r14,(DBSR_IC|DBSR_BT)@h
        beq+    1f
 
+#ifdef CONFIG_RELOCATABLE
+       ld      r15,PACATOC(r13)
+       ld      r14,interrupt_base_book3e@got(r15)
+       ld      r15,__end_interrupts@got(r15)
+#else
        LOAD_REG_IMMEDIATE(r14,interrupt_base_book3e)
        LOAD_REG_IMMEDIATE(r15,__end_interrupts)
+#endif
        cmpld   cr0,r10,r14
        cmpld   cr1,r10,r15
        blt+    cr0,1f
index a9312b52fe6fdc5336e82cdd55f5f86b2729c6e3..ae418b85c17c4bce805227a82350d322259cf06e 100644 (file)
@@ -391,9 +391,7 @@ EXC_COMMON_BEGIN(machine_check_handle_early)
         */
        BEGIN_FTR_SECTION
        rlwinm. r11,r12,47-31,30,31
-       beq-    4f
-       BRANCH_TO_COMMON(r10, machine_check_idle_common)
-4:
+       bne     machine_check_idle_common
        END_FTR_SECTION_IFSET(CPU_FTR_HVMODE | CPU_FTR_ARCH_206)
 #endif
 
index 243dbef7e9265c47a4fd9efc1bf5b087deea2cf7..466569e26278694c8ceea17509a99ec04c4ea68b 100644 (file)
@@ -209,14 +209,20 @@ static unsigned long init_fadump_mem_struct(struct fadump_mem_struct *fdm,
  */
 static inline unsigned long fadump_calculate_reserve_size(void)
 {
-       unsigned long size;
+       int ret;
+       unsigned long long base, size;
 
        /*
-        * Check if the size is specified through fadump_reserve_mem= cmdline
-        * option. If yes, then use that.
+        * Check if the size is specified through crashkernel= cmdline
+        * option. If yes, then use that but ignore base as fadump
+        * reserves memory at end of RAM.
         */
-       if (fw_dump.reserve_bootvar)
+       ret = parse_crashkernel(boot_command_line, memblock_phys_mem_size(),
+                               &size, &base);
+       if (ret == 0 && size > 0) {
+               fw_dump.reserve_bootvar = (unsigned long)size;
                return fw_dump.reserve_bootvar;
+       }
 
        /* divide by 20 to get 5% of value */
        size = memblock_end_of_DRAM() / 20;
@@ -371,15 +377,6 @@ static int __init early_fadump_param(char *p)
 }
 early_param("fadump", early_fadump_param);
 
-/* Look for fadump_reserve_mem= cmdline option */
-static int __init early_fadump_reserve_mem(char *p)
-{
-       if (p)
-               fw_dump.reserve_bootvar = memparse(p, &p);
-       return 0;
-}
-early_param("fadump_reserve_mem", early_fadump_reserve_mem);
-
 static void register_fw_dump(struct fadump_mem_struct *fdm)
 {
        int rc;
@@ -527,34 +524,6 @@ fadump_read_registers(struct fadump_reg_entry *reg_entry, struct pt_regs *regs)
        return reg_entry;
 }
 
-static u32 *fadump_append_elf_note(u32 *buf, char *name, unsigned type,
-                                               void *data, size_t data_len)
-{
-       struct elf_note note;
-
-       note.n_namesz = strlen(name) + 1;
-       note.n_descsz = data_len;
-       note.n_type   = type;
-       memcpy(buf, &note, sizeof(note));
-       buf += (sizeof(note) + 3)/4;
-       memcpy(buf, name, note.n_namesz);
-       buf += (note.n_namesz + 3)/4;
-       memcpy(buf, data, note.n_descsz);
-       buf += (note.n_descsz + 3)/4;
-
-       return buf;
-}
-
-static void fadump_final_note(u32 *buf)
-{
-       struct elf_note note;
-
-       note.n_namesz = 0;
-       note.n_descsz = 0;
-       note.n_type   = 0;
-       memcpy(buf, &note, sizeof(note));
-}
-
 static u32 *fadump_regs_to_elf_notes(u32 *buf, struct pt_regs *regs)
 {
        struct elf_prstatus prstatus;
@@ -565,8 +534,8 @@ static u32 *fadump_regs_to_elf_notes(u32 *buf, struct pt_regs *regs)
         * prstatus.pr_pid = ????
         */
        elf_core_copy_kernel_regs(&prstatus.pr_reg, regs);
-       buf = fadump_append_elf_note(buf, KEXEC_CORE_NOTE_NAME, NT_PRSTATUS,
-                               &prstatus, sizeof(prstatus));
+       buf = append_elf_note(buf, CRASH_CORE_NOTE_NAME, NT_PRSTATUS,
+                             &prstatus, sizeof(prstatus));
        return buf;
 }
 
@@ -707,7 +676,7 @@ static int __init fadump_build_cpu_notes(const struct fadump_mem_struct *fdm)
                        note_buf = fadump_regs_to_elf_notes(note_buf, &regs);
                }
        }
-       fadump_final_note(note_buf);
+       final_note(note_buf);
 
        if (fdh) {
                pr_debug("Updating elfcore header (%llx) with cpu notes\n",
index 07d4e0ad60db5b1a1f2cd5da08763a3acea7ea3b..4898d676dcaef1d02600c5c75ef13ceca1fc8c69 100644 (file)
@@ -416,7 +416,7 @@ power9_dd1_recover_paca:
         * which needs to be restored from the stack.
         */
        li      r3, 1
-       stb     r0,PACA_NAPSTATELOST(r13)
+       stb     r3,PACA_NAPSTATELOST(r13)
        blr
 
 /*
index 160ae0fa7d0d15152011b111134784107287e7bb..fc4343514bed8b0f05a88e64caf0285c44ee8ea0 100644 (file)
@@ -305,16 +305,17 @@ int kprobe_handler(struct pt_regs *regs)
                        save_previous_kprobe(kcb);
                        set_current_kprobe(p, regs, kcb);
                        kprobes_inc_nmissed_count(p);
-                       prepare_singlestep(p, regs);
                        kcb->kprobe_status = KPROBE_REENTER;
                        if (p->ainsn.boostable >= 0) {
                                ret = try_to_emulate(p, regs);
 
                                if (ret > 0) {
                                        restore_previous_kprobe(kcb);
+                                       preempt_enable_no_resched();
                                        return 1;
                                }
                        }
+                       prepare_singlestep(p, regs);
                        return 1;
                } else {
                        if (*addr != BREAKPOINT_INSTRUCTION) {
index ffda24a38dda278d2ffabf387cd0b1b6256cc652..341a7469cab84a14bf06db6984b58716933d6aa6 100644 (file)
@@ -233,6 +233,14 @@ void pcibios_reset_secondary_bus(struct pci_dev *dev)
        pci_reset_secondary_bus(dev);
 }
 
+resource_size_t pcibios_default_alignment(void)
+{
+       if (ppc_md.pcibios_default_alignment)
+               return ppc_md.pcibios_default_alignment();
+
+       return 0;
+}
+
 #ifdef CONFIG_PCI_IOV
 resource_size_t pcibios_iov_resource_alignment(struct pci_dev *pdev, int resno)
 {
@@ -513,7 +521,8 @@ pgprot_t pci_phys_mem_access_prot(struct file *file,
  *
  * Returns a negative error code on failure, zero on success.
  */
-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+int pci_mmap_page_range(struct pci_dev *dev, int bar,
+                       struct vm_area_struct *vma,
                        enum pci_mmap_state mmap_state, int write_combine)
 {
        resource_size_t offset =
index d645da302bf22f46c046bcb3912bbdd51186c416..baae104b16c7ba9f7cdf4a305ab5227ebf002467 100644 (file)
@@ -864,6 +864,25 @@ static void tm_reclaim_thread(struct thread_struct *thr,
        if (!MSR_TM_SUSPENDED(mfmsr()))
                return;
 
+       /*
+        * If we are in a transaction and FP is off then we can't have
+        * used FP inside that transaction. Hence the checkpointed
+        * state is the same as the live state. We need to copy the
+        * live state to the checkpointed state so that when the
+        * transaction is restored, the checkpointed state is correct
+        * and the aborted transaction sees the correct state. We use
+        * ckpt_regs.msr here as that's what tm_reclaim will use to
+        * determine if it's going to write the checkpointed state or
+        * not. So either this will write the checkpointed registers,
+        * or reclaim will. Similarly for VMX.
+        */
+       if ((thr->ckpt_regs.msr & MSR_FP) == 0)
+               memcpy(&thr->ckfp_state, &thr->fp_state,
+                      sizeof(struct thread_fp_state));
+       if ((thr->ckpt_regs.msr & MSR_VEC) == 0)
+               memcpy(&thr->ckvr_state, &thr->vr_state,
+                      sizeof(struct thread_vr_state));
+
        giveup_all(container_of(thr, struct task_struct, thread));
 
        tm_reclaim(thr, thr->ckpt_regs.msr, cause);
index d2f0afeae5a0cd24ead16ba9e94b8ff95e621c57..40c4887c27b613d73bc420b4aca34cee406325a8 100644 (file)
@@ -57,6 +57,7 @@
 #include <asm/fadump.h>
 #include <asm/epapr_hcalls.h>
 #include <asm/firmware.h>
+#include <asm/dt_cpu_ftrs.h>
 
 #include <mm/mmu_decl.h>
 
@@ -375,23 +376,31 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
         * A POWER6 partition in "POWER6 architected" mode
         * uses the 0x0f000002 PVR value; in POWER5+ mode
         * it uses 0x0f000001.
+        *
+        * If we're using device tree CPU feature discovery then we don't
+        * support the cpu-version property, and it's the responsibility of the
+        * firmware/hypervisor to provide the correct feature set for the
+        * architecture level via the ibm,powerpc-cpu-features binding.
         */
-       prop = of_get_flat_dt_prop(node, "cpu-version", NULL);
-       if (prop && (be32_to_cpup(prop) & 0xff000000) == 0x0f000000)
-               identify_cpu(0, be32_to_cpup(prop));
+       if (!dt_cpu_ftrs_in_use()) {
+               prop = of_get_flat_dt_prop(node, "cpu-version", NULL);
+               if (prop && (be32_to_cpup(prop) & 0xff000000) == 0x0f000000)
+                       identify_cpu(0, be32_to_cpup(prop));
 
-       identical_pvr_fixup(node);
+               check_cpu_feature_properties(node);
+               check_cpu_pa_features(node);
+       }
 
-       check_cpu_feature_properties(node);
-       check_cpu_pa_features(node);
+       identical_pvr_fixup(node);
        init_mmu_slb_size(node);
 
 #ifdef CONFIG_PPC64
-       if (nthreads > 1)
-               cur_cpu_spec->cpu_features |= CPU_FTR_SMT;
-       else
+       if (nthreads == 1)
                cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT;
+       else if (!dt_cpu_ftrs_in_use())
+               cur_cpu_spec->cpu_features |= CPU_FTR_SMT;
 #endif
+
        return 0;
 }
 
@@ -721,6 +730,8 @@ void __init early_init_devtree(void *params)
 
        DBG("Scanning CPUs ...\n");
 
+       dt_cpu_ftrs_scan();
+
        /* Retrieve CPU related informations from the flat tree
         * (altivec support, boot CPU ID, ...)
         */
index 5c10b5925ac22d29322e50f246f622354f717914..71dcda91755d51a2e5705f29308239e7e9c7e506 100644 (file)
@@ -125,6 +125,11 @@ int ppc_do_canonicalize_irqs;
 EXPORT_SYMBOL(ppc_do_canonicalize_irqs);
 #endif
 
+#ifdef CONFIG_CRASH_CORE
+/* This keeps a track of which one is the crashing cpu. */
+int crashing_cpu = -1;
+#endif
+
 /* also used by kexec */
 void machine_shutdown(void)
 {
@@ -256,7 +261,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
        seq_printf(m, "processor\t: %lu\n", cpu_id);
        seq_printf(m, "cpu\t\t: ");
 
-       if (cur_cpu_spec->pvr_mask)
+       if (cur_cpu_spec->pvr_mask && cur_cpu_spec->cpu_name)
                seq_printf(m, "%s", cur_cpu_spec->cpu_name);
        else
                seq_printf(m, "unknown (%08x)", pvr);
index 0d4dcaeaafcb4d0b8396f06ba8cc93e4a30e5d0b..f35ff9dea4fb4607459c10d42a29c47f2984e613 100644 (file)
@@ -49,6 +49,7 @@
 #include <asm/paca.h>
 #include <asm/time.h>
 #include <asm/cputable.h>
+#include <asm/dt_cpu_ftrs.h>
 #include <asm/sections.h>
 #include <asm/btext.h>
 #include <asm/nvram.h>
@@ -274,8 +275,10 @@ void __init early_setup(unsigned long dt_ptr)
 
        /* -------- printk is _NOT_ safe to use here ! ------- */
 
-       /* Identify CPU type */
-       identify_cpu(0, mfspr(SPRN_PVR));
+       /* Try new device tree based feature discovery ... */
+       if (!dt_cpu_ftrs_init(__va(dt_ptr)))
+               /* Otherwise use the old style CPU table */
+               identify_cpu(0, mfspr(SPRN_PVR));
 
        /* Assume we're on cpu 0 for now. Don't write to the paca yet! */
        initialise_paca(&boot_paca, 0);
@@ -541,6 +544,9 @@ void __init initialize_cache_info(void)
        dcache_bsize = ppc64_caches.l1d.block_size;
        icache_bsize = ppc64_caches.l1i.block_size;
 
+       cur_cpu_spec->dcache_bsize = dcache_bsize;
+       cur_cpu_spec->icache_bsize = icache_bsize;
+
        DBG(" <- initialize_cache_info()\n");
 }
 
index 65a471de96de2bfe7b743b497ec396f008849826..0c52cb5d43f52bdba5008ccade5edfd2b4fee5f4 100644 (file)
@@ -67,7 +67,7 @@ config KVM_BOOK3S_64
        select KVM_BOOK3S_64_HANDLER
        select KVM
        select KVM_BOOK3S_PR_POSSIBLE if !KVM_BOOK3S_HV_POSSIBLE
-       select SPAPR_TCE_IOMMU if IOMMU_SUPPORT
+       select SPAPR_TCE_IOMMU if IOMMU_SUPPORT && (PPC_SERIES || PPC_POWERNV)
        ---help---
          Support running unmodified book3s_64 and book3s_32 guest kernels
          in virtual machines on book3s_64 host processors.
@@ -197,6 +197,11 @@ config KVM_XICS
          Specification) interrupt controller architecture used on
          IBM POWER (pSeries) servers.
 
+config KVM_XIVE
+       bool
+       default y
+       depends on KVM_XICS && PPC_XIVE_NATIVE && KVM_BOOK3S_HV_POSSIBLE
+
 source drivers/vhost/Kconfig
 
 endif # VIRTUALIZATION
index b87ccde2137adafada5461881b798a11c1411685..381a6ec0ff3b72ab085834fc14a35e853b237fc6 100644 (file)
@@ -46,7 +46,7 @@ kvm-e500mc-objs := \
        e500_emulate.o
 kvm-objs-$(CONFIG_KVM_E500MC) := $(kvm-e500mc-objs)
 
-kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HANDLER) := \
+kvm-book3s_64-builtin-objs-$(CONFIG_SPAPR_TCE_IOMMU) := \
        book3s_64_vio_hv.o
 
 kvm-pr-y := \
@@ -74,7 +74,7 @@ kvm-hv-y += \
        book3s_64_mmu_radix.o
 
 kvm-book3s_64-builtin-xics-objs-$(CONFIG_KVM_XICS) := \
-       book3s_hv_rm_xics.o
+       book3s_hv_rm_xics.o book3s_hv_rm_xive.o
 
 ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
 kvm-book3s_64-builtin-objs-$(CONFIG_KVM_BOOK3S_64_HANDLER) += \
@@ -89,10 +89,12 @@ endif
 kvm-book3s_64-objs-$(CONFIG_KVM_XICS) += \
        book3s_xics.o
 
+kvm-book3s_64-objs-$(CONFIG_KVM_XIVE) += book3s_xive.o
+kvm-book3s_64-objs-$(CONFIG_SPAPR_TCE_IOMMU) += book3s_64_vio.o
+
 kvm-book3s_64-module-objs := \
        $(common-objs-y) \
        book3s.o \
-       book3s_64_vio.o \
        book3s_rtas.o \
        $(kvm-book3s_64-objs-y)
 
index 8c4d7e9d27d29c408049b9c01867c343c0f95577..72d977e309523f9c1720f32da241b29ad6e24755 100644 (file)
@@ -35,6 +35,7 @@
 #include <asm/kvm_book3s.h>
 #include <asm/mmu_context.h>
 #include <asm/page.h>
+#include <asm/xive.h>
 
 #include "book3s.h"
 #include "trace.h"
@@ -596,11 +597,14 @@ int kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id,
                        break;
 #ifdef CONFIG_KVM_XICS
                case KVM_REG_PPC_ICP_STATE:
-                       if (!vcpu->arch.icp) {
+                       if (!vcpu->arch.icp && !vcpu->arch.xive_vcpu) {
                                r = -ENXIO;
                                break;
                        }
-                       *val = get_reg_val(id, kvmppc_xics_get_icp(vcpu));
+                       if (xive_enabled())
+                               *val = get_reg_val(id, kvmppc_xive_get_icp(vcpu));
+                       else
+                               *val = get_reg_val(id, kvmppc_xics_get_icp(vcpu));
                        break;
 #endif /* CONFIG_KVM_XICS */
                case KVM_REG_PPC_FSCR:
@@ -666,12 +670,14 @@ int kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id,
 #endif /* CONFIG_VSX */
 #ifdef CONFIG_KVM_XICS
                case KVM_REG_PPC_ICP_STATE:
-                       if (!vcpu->arch.icp) {
+                       if (!vcpu->arch.icp && !vcpu->arch.xive_vcpu) {
                                r = -ENXIO;
                                break;
                        }
-                       r = kvmppc_xics_set_icp(vcpu,
-                                               set_reg_val(id, *val));
+                       if (xive_enabled())
+                               r = kvmppc_xive_set_icp(vcpu, set_reg_val(id, *val));
+                       else
+                               r = kvmppc_xics_set_icp(vcpu, set_reg_val(id, *val));
                        break;
 #endif /* CONFIG_KVM_XICS */
                case KVM_REG_PPC_FSCR:
@@ -942,6 +948,50 @@ int kvmppc_book3s_hcall_implemented(struct kvm *kvm, unsigned long hcall)
        return kvm->arch.kvm_ops->hcall_implemented(hcall);
 }
 
+#ifdef CONFIG_KVM_XICS
+int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level,
+               bool line_status)
+{
+       if (xive_enabled())
+               return kvmppc_xive_set_irq(kvm, irq_source_id, irq, level,
+                                          line_status);
+       else
+               return kvmppc_xics_set_irq(kvm, irq_source_id, irq, level,
+                                          line_status);
+}
+
+int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *irq_entry,
+                             struct kvm *kvm, int irq_source_id,
+                             int level, bool line_status)
+{
+       return kvm_set_irq(kvm, irq_source_id, irq_entry->gsi,
+                          level, line_status);
+}
+static int kvmppc_book3s_set_irq(struct kvm_kernel_irq_routing_entry *e,
+                                struct kvm *kvm, int irq_source_id, int level,
+                                bool line_status)
+{
+       return kvm_set_irq(kvm, irq_source_id, e->gsi, level, line_status);
+}
+
+int kvm_irq_map_gsi(struct kvm *kvm,
+                   struct kvm_kernel_irq_routing_entry *entries, int gsi)
+{
+       entries->gsi = gsi;
+       entries->type = KVM_IRQ_ROUTING_IRQCHIP;
+       entries->set = kvmppc_book3s_set_irq;
+       entries->irqchip.irqchip = 0;
+       entries->irqchip.pin = gsi;
+       return 1;
+}
+
+int kvm_irq_map_chip_pin(struct kvm *kvm, unsigned irqchip, unsigned pin)
+{
+       return pin;
+}
+
+#endif /* CONFIG_KVM_XICS */
+
 static int kvmppc_book3s_init(void)
 {
        int r;
@@ -952,12 +1002,25 @@ static int kvmppc_book3s_init(void)
 #ifdef CONFIG_KVM_BOOK3S_32_HANDLER
        r = kvmppc_book3s_init_pr();
 #endif
-       return r;
 
+#ifdef CONFIG_KVM_XICS
+#ifdef CONFIG_KVM_XIVE
+       if (xive_enabled()) {
+               kvmppc_xive_init_module();
+               kvm_register_device_ops(&kvm_xive_ops, KVM_DEV_TYPE_XICS);
+       } else
+#endif
+               kvm_register_device_ops(&kvm_xics_ops, KVM_DEV_TYPE_XICS);
+#endif
+       return r;
 }
 
 static void kvmppc_book3s_exit(void)
 {
+#ifdef CONFIG_KVM_XICS
+       if (xive_enabled())
+               kvmppc_xive_exit_module();
+#endif
 #ifdef CONFIG_KVM_BOOK3S_32_HANDLER
        kvmppc_book3s_exit_pr();
 #endif
index eda0a8f6fae8eba29b5b04c28fe49e7f9d605d45..3adfd2f5301c686762007e496717d453c258d37c 100644 (file)
@@ -301,6 +301,10 @@ long kvmppc_rm_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
        /* udbg_printf("H_PUT_TCE(): liobn=0x%lx ioba=0x%lx, tce=0x%lx\n", */
        /*          liobn, ioba, tce); */
 
+       /* For radix, we might be in virtual mode, so punt */
+       if (kvm_is_radix(vcpu->kvm))
+               return H_TOO_HARD;
+
        stt = kvmppc_find_table(vcpu->kvm, liobn);
        if (!stt)
                return H_TOO_HARD;
@@ -381,6 +385,10 @@ long kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu,
        bool prereg = false;
        struct kvmppc_spapr_tce_iommu_table *stit;
 
+       /* For radix, we might be in virtual mode, so punt */
+       if (kvm_is_radix(vcpu->kvm))
+               return H_TOO_HARD;
+
        stt = kvmppc_find_table(vcpu->kvm, liobn);
        if (!stt)
                return H_TOO_HARD;
@@ -491,6 +499,10 @@ long kvmppc_rm_h_stuff_tce(struct kvm_vcpu *vcpu,
        long i, ret;
        struct kvmppc_spapr_tce_iommu_table *stit;
 
+       /* For radix, we might be in virtual mode, so punt */
+       if (kvm_is_radix(vcpu->kvm))
+               return H_TOO_HARD;
+
        stt = kvmppc_find_table(vcpu->kvm, liobn);
        if (!stt)
                return H_TOO_HARD;
@@ -527,6 +539,7 @@ long kvmppc_rm_h_stuff_tce(struct kvm_vcpu *vcpu,
        return H_SUCCESS;
 }
 
+/* This can be called in either virtual mode or real mode */
 long kvmppc_h_get_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
                      unsigned long ioba)
 {
index 549dd6070dee8888c6e2b220bafa33bf3dbd0c98..42b7a4fd57d9a557f8278a9f9a8c228f2758a1e8 100644 (file)
@@ -67,6 +67,7 @@
 #include <asm/mmu.h>
 #include <asm/opal.h>
 #include <asm/xics.h>
+#include <asm/xive.h>
 
 #include "book3s.h"
 
@@ -837,6 +838,10 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
        case H_IPOLL:
        case H_XIRR_X:
                if (kvmppc_xics_enabled(vcpu)) {
+                       if (xive_enabled()) {
+                               ret = H_NOT_AVAILABLE;
+                               return RESUME_GUEST;
+                       }
                        ret = kvmppc_xics_hcall(vcpu, req);
                        break;
                }
@@ -2947,8 +2952,12 @@ static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu)
                        r = kvmppc_book3s_hv_page_fault(run, vcpu,
                                vcpu->arch.fault_dar, vcpu->arch.fault_dsisr);
                        srcu_read_unlock(&vcpu->kvm->srcu, srcu_idx);
-               } else if (r == RESUME_PASSTHROUGH)
-                       r = kvmppc_xics_rm_complete(vcpu, 0);
+               } else if (r == RESUME_PASSTHROUGH) {
+                       if (WARN_ON(xive_enabled()))
+                               r = H_SUCCESS;
+                       else
+                               r = kvmppc_xics_rm_complete(vcpu, 0);
+               }
        } while (is_kvmppc_resume_guest(r));
 
  out:
@@ -3400,10 +3409,20 @@ static int kvmppc_core_init_vm_hv(struct kvm *kvm)
        /*
         * On POWER9, VPM0 bit is reserved (VPM0=1 behaviour is assumed)
         * Set HVICE bit to enable hypervisor virtualization interrupts.
+        * Set HEIC to prevent OS interrupts to go to hypervisor (should
+        * be unnecessary but better safe than sorry in case we re-enable
+        * EE in HV mode with this LPCR still set)
         */
        if (cpu_has_feature(CPU_FTR_ARCH_300)) {
                lpcr &= ~LPCR_VPM0;
-               lpcr |= LPCR_HVICE;
+               lpcr |= LPCR_HVICE | LPCR_HEIC;
+
+               /*
+                * If xive is enabled, we route 0x500 interrupts directly
+                * to the guest.
+                */
+               if (xive_enabled())
+                       lpcr |= LPCR_LPES;
        }
 
        /*
@@ -3533,7 +3552,7 @@ static int kvmppc_set_passthru_irq(struct kvm *kvm, int host_irq, int guest_gsi)
        struct kvmppc_irq_map *irq_map;
        struct kvmppc_passthru_irqmap *pimap;
        struct irq_chip *chip;
-       int i;
+       int i, rc = 0;
 
        if (!kvm_irq_bypass)
                return 1;
@@ -3558,10 +3577,10 @@ static int kvmppc_set_passthru_irq(struct kvm *kvm, int host_irq, int guest_gsi)
        /*
         * For now, we only support interrupts for which the EOI operation
         * is an OPAL call followed by a write to XIRR, since that's
-        * what our real-mode EOI code does.
+        * what our real-mode EOI code does, or a XIVE interrupt
         */
        chip = irq_data_get_irq_chip(&desc->irq_data);
-       if (!chip || !is_pnv_opal_msi(chip)) {
+       if (!chip || !(is_pnv_opal_msi(chip) || is_xive_irq(chip))) {
                pr_warn("kvmppc_set_passthru_irq_hv: Could not assign IRQ map for (%d,%d)\n",
                        host_irq, guest_gsi);
                mutex_unlock(&kvm->lock);
@@ -3603,7 +3622,12 @@ static int kvmppc_set_passthru_irq(struct kvm *kvm, int host_irq, int guest_gsi)
        if (i == pimap->n_mapped)
                pimap->n_mapped++;
 
-       kvmppc_xics_set_mapped(kvm, guest_gsi, desc->irq_data.hwirq);
+       if (xive_enabled())
+               rc = kvmppc_xive_set_mapped(kvm, guest_gsi, desc);
+       else
+               kvmppc_xics_set_mapped(kvm, guest_gsi, desc->irq_data.hwirq);
+       if (rc)
+               irq_map->r_hwirq = 0;
 
        mutex_unlock(&kvm->lock);
 
@@ -3614,7 +3638,7 @@ static int kvmppc_clr_passthru_irq(struct kvm *kvm, int host_irq, int guest_gsi)
 {
        struct irq_desc *desc;
        struct kvmppc_passthru_irqmap *pimap;
-       int i;
+       int i, rc = 0;
 
        if (!kvm_irq_bypass)
                return 0;
@@ -3639,9 +3663,12 @@ static int kvmppc_clr_passthru_irq(struct kvm *kvm, int host_irq, int guest_gsi)
                return -ENODEV;
        }
 
-       kvmppc_xics_clr_mapped(kvm, guest_gsi, pimap->mapped[i].r_hwirq);
+       if (xive_enabled())
+               rc = kvmppc_xive_clr_mapped(kvm, guest_gsi, pimap->mapped[i].desc);
+       else
+               kvmppc_xics_clr_mapped(kvm, guest_gsi, pimap->mapped[i].r_hwirq);
 
-       /* invalidate the entry */
+       /* invalidate the entry (what do do on error from the above ?) */
        pimap->mapped[i].r_hwirq = 0;
 
        /*
@@ -3650,7 +3677,7 @@ static int kvmppc_clr_passthru_irq(struct kvm *kvm, int host_irq, int guest_gsi)
         */
  unlock:
        mutex_unlock(&kvm->lock);
-       return 0;
+       return rc;
 }
 
 static int kvmppc_irq_bypass_add_producer_hv(struct irq_bypass_consumer *cons,
@@ -3928,7 +3955,7 @@ static int kvmppc_book3s_init_hv(void)
         * indirectly, via OPAL.
         */
 #ifdef CONFIG_SMP
-       if (!get_paca()->kvm_hstate.xics_phys) {
+       if (!xive_enabled() && !local_paca->kvm_hstate.xics_phys) {
                struct device_node *np;
 
                np = of_find_compatible_node(NULL, NULL, "ibm,opal-intc");
index 9c71c72e65ce8153d5816d2a75e68285d3d53997..ee4c2558c3058717da1f6299fd6a0e0aebc75360 100644 (file)
 
 #define KVM_CMA_CHUNK_ORDER    18
 
+#include "book3s_xics.h"
+#include "book3s_xive.h"
+
+/*
+ * The XIVE module will populate these when it loads
+ */
+unsigned long (*__xive_vm_h_xirr)(struct kvm_vcpu *vcpu);
+unsigned long (*__xive_vm_h_ipoll)(struct kvm_vcpu *vcpu, unsigned long server);
+int (*__xive_vm_h_ipi)(struct kvm_vcpu *vcpu, unsigned long server,
+                      unsigned long mfrr);
+int (*__xive_vm_h_cppr)(struct kvm_vcpu *vcpu, unsigned long cppr);
+int (*__xive_vm_h_eoi)(struct kvm_vcpu *vcpu, unsigned long xirr);
+EXPORT_SYMBOL_GPL(__xive_vm_h_xirr);
+EXPORT_SYMBOL_GPL(__xive_vm_h_ipoll);
+EXPORT_SYMBOL_GPL(__xive_vm_h_ipi);
+EXPORT_SYMBOL_GPL(__xive_vm_h_cppr);
+EXPORT_SYMBOL_GPL(__xive_vm_h_eoi);
+
 /*
  * Hash page table alignment on newer cpus(CPU_FTR_ARCH_206)
  * should be power of 2.
@@ -189,7 +207,14 @@ EXPORT_SYMBOL_GPL(kvmppc_hwrng_present);
 
 long kvmppc_h_random(struct kvm_vcpu *vcpu)
 {
-       if (powernv_get_random_real_mode(&vcpu->arch.gpr[4]))
+       int r;
+
+       /* Only need to do the expensive mfmsr() on radix */
+       if (kvm_is_radix(vcpu->kvm) && (mfmsr() & MSR_IR))
+               r = powernv_get_random_long(&vcpu->arch.gpr[4]);
+       else
+               r = powernv_get_random_real_mode(&vcpu->arch.gpr[4]);
+       if (r)
                return H_SUCCESS;
 
        return H_HARDWARE;
@@ -211,6 +236,7 @@ void kvmhv_rm_send_ipi(int cpu)
                __asm__ __volatile__ (PPC_MSGSND(%0) : : "r" (msg));
                return;
        }
+
        /* On POWER8 for IPIs to threads in the same core, use msgsnd. */
        if (cpu_has_feature(CPU_FTR_ARCH_207S) &&
            cpu_first_thread_sibling(cpu) ==
@@ -407,6 +433,9 @@ static long kvmppc_read_one_intr(bool *again)
        u8 host_ipi;
        int64_t rc;
 
+       if (xive_enabled())
+               return 1;
+
        /* see if a host IPI is pending */
        host_ipi = local_paca->kvm_hstate.host_ipi;
        if (host_ipi)
@@ -491,3 +520,84 @@ static long kvmppc_read_one_intr(bool *again)
 
        return kvmppc_check_passthru(xisr, xirr, again);
 }
+
+#ifdef CONFIG_KVM_XICS
+static inline bool is_rm(void)
+{
+       return !(mfmsr() & MSR_DR);
+}
+
+unsigned long kvmppc_rm_h_xirr(struct kvm_vcpu *vcpu)
+{
+       if (xive_enabled()) {
+               if (is_rm())
+                       return xive_rm_h_xirr(vcpu);
+               if (unlikely(!__xive_vm_h_xirr))
+                       return H_NOT_AVAILABLE;
+               return __xive_vm_h_xirr(vcpu);
+       } else
+               return xics_rm_h_xirr(vcpu);
+}
+
+unsigned long kvmppc_rm_h_xirr_x(struct kvm_vcpu *vcpu)
+{
+       vcpu->arch.gpr[5] = get_tb();
+       if (xive_enabled()) {
+               if (is_rm())
+                       return xive_rm_h_xirr(vcpu);
+               if (unlikely(!__xive_vm_h_xirr))
+                       return H_NOT_AVAILABLE;
+               return __xive_vm_h_xirr(vcpu);
+       } else
+               return xics_rm_h_xirr(vcpu);
+}
+
+unsigned long kvmppc_rm_h_ipoll(struct kvm_vcpu *vcpu, unsigned long server)
+{
+       if (xive_enabled()) {
+               if (is_rm())
+                       return xive_rm_h_ipoll(vcpu, server);
+               if (unlikely(!__xive_vm_h_ipoll))
+                       return H_NOT_AVAILABLE;
+               return __xive_vm_h_ipoll(vcpu, server);
+       } else
+               return H_TOO_HARD;
+}
+
+int kvmppc_rm_h_ipi(struct kvm_vcpu *vcpu, unsigned long server,
+                   unsigned long mfrr)
+{
+       if (xive_enabled()) {
+               if (is_rm())
+                       return xive_rm_h_ipi(vcpu, server, mfrr);
+               if (unlikely(!__xive_vm_h_ipi))
+                       return H_NOT_AVAILABLE;
+               return __xive_vm_h_ipi(vcpu, server, mfrr);
+       } else
+               return xics_rm_h_ipi(vcpu, server, mfrr);
+}
+
+int kvmppc_rm_h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr)
+{
+       if (xive_enabled()) {
+               if (is_rm())
+                       return xive_rm_h_cppr(vcpu, cppr);
+               if (unlikely(!__xive_vm_h_cppr))
+                       return H_NOT_AVAILABLE;
+               return __xive_vm_h_cppr(vcpu, cppr);
+       } else
+               return xics_rm_h_cppr(vcpu, cppr);
+}
+
+int kvmppc_rm_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr)
+{
+       if (xive_enabled()) {
+               if (is_rm())
+                       return xive_rm_h_eoi(vcpu, xirr);
+               if (unlikely(!__xive_vm_h_eoi))
+                       return H_NOT_AVAILABLE;
+               return __xive_vm_h_eoi(vcpu, xirr);
+       } else
+               return xics_rm_h_eoi(vcpu, xirr);
+}
+#endif /* CONFIG_KVM_XICS */
index ffde4507ddfd0629305ffaf0afccc0fdc7cd3749..2a862618f072b63ee27915be5ab43468bcffbb2f 100644 (file)
@@ -484,7 +484,7 @@ static void icp_rm_down_cppr(struct kvmppc_xics *xics, struct kvmppc_icp *icp,
 }
 
 
-unsigned long kvmppc_rm_h_xirr(struct kvm_vcpu *vcpu)
+unsigned long xics_rm_h_xirr(struct kvm_vcpu *vcpu)
 {
        union kvmppc_icp_state old_state, new_state;
        struct kvmppc_xics *xics = vcpu->kvm->arch.xics;
@@ -522,8 +522,8 @@ unsigned long kvmppc_rm_h_xirr(struct kvm_vcpu *vcpu)
        return check_too_hard(xics, icp);
 }
 
-int kvmppc_rm_h_ipi(struct kvm_vcpu *vcpu, unsigned long server,
-                   unsigned long mfrr)
+int xics_rm_h_ipi(struct kvm_vcpu *vcpu, unsigned long server,
+                 unsigned long mfrr)
 {
        union kvmppc_icp_state old_state, new_state;
        struct kvmppc_xics *xics = vcpu->kvm->arch.xics;
@@ -609,7 +609,7 @@ int kvmppc_rm_h_ipi(struct kvm_vcpu *vcpu, unsigned long server,
        return check_too_hard(xics, this_icp);
 }
 
-int kvmppc_rm_h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr)
+int xics_rm_h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr)
 {
        union kvmppc_icp_state old_state, new_state;
        struct kvmppc_xics *xics = vcpu->kvm->arch.xics;
@@ -729,7 +729,7 @@ static int ics_rm_eoi(struct kvm_vcpu *vcpu, u32 irq)
        return check_too_hard(xics, icp);
 }
 
-int kvmppc_rm_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr)
+int xics_rm_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr)
 {
        struct kvmppc_xics *xics = vcpu->kvm->arch.xics;
        struct kvmppc_icp *icp = vcpu->arch.icp;
diff --git a/arch/powerpc/kvm/book3s_hv_rm_xive.c b/arch/powerpc/kvm/book3s_hv_rm_xive.c
new file mode 100644 (file)
index 0000000..abf5f01
--- /dev/null
@@ -0,0 +1,47 @@
+#include <linux/kernel.h>
+#include <linux/kvm_host.h>
+#include <linux/err.h>
+#include <linux/kernel_stat.h>
+
+#include <asm/kvm_book3s.h>
+#include <asm/kvm_ppc.h>
+#include <asm/hvcall.h>
+#include <asm/xics.h>
+#include <asm/debug.h>
+#include <asm/synch.h>
+#include <asm/cputhreads.h>
+#include <asm/pgtable.h>
+#include <asm/ppc-opcode.h>
+#include <asm/pnv-pci.h>
+#include <asm/opal.h>
+#include <asm/smp.h>
+#include <asm/asm-prototypes.h>
+#include <asm/xive.h>
+#include <asm/xive-regs.h>
+
+#include "book3s_xive.h"
+
+/* XXX */
+#include <asm/udbg.h>
+//#define DBG(fmt...) udbg_printf(fmt)
+#define DBG(fmt...) do { } while(0)
+
+static inline void __iomem *get_tima_phys(void)
+{
+       return local_paca->kvm_hstate.xive_tima_phys;
+}
+
+#undef XIVE_RUNTIME_CHECKS
+#define X_PFX xive_rm_
+#define X_STATIC
+#define X_STAT_PFX stat_rm_
+#define __x_tima               get_tima_phys()
+#define __x_eoi_page(xd)       ((void __iomem *)((xd)->eoi_page))
+#define __x_trig_page(xd)      ((void __iomem *)((xd)->trig_page))
+#define __x_readb      __raw_rm_readb
+#define __x_writeb     __raw_rm_writeb
+#define __x_readw      __raw_rm_readw
+#define __x_readq      __raw_rm_readq
+#define __x_writeq     __raw_rm_writeq
+
+#include "book3s_xive_template.c"
index 7c6477d1840aab488cbec7ffe813696fd63f861f..bdb3f76ceb6b9ff0e25e5b3b56c3be48dd6f65cc 100644 (file)
@@ -30,6 +30,7 @@
 #include <asm/book3s/64/mmu-hash.h>
 #include <asm/tm.h>
 #include <asm/opal.h>
+#include <asm/xive-regs.h>
 
 #define VCPU_GPRS_TM(reg) (((reg) * ULONG_SIZE) + VCPU_GPR_TM)
 
@@ -970,6 +971,23 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300)
        cmpwi   r3, 512         /* 1 microsecond */
        blt     hdec_soon
 
+#ifdef CONFIG_KVM_XICS
+       /* We are entering the guest on that thread, push VCPU to XIVE */
+       ld      r10, HSTATE_XIVE_TIMA_PHYS(r13)
+       cmpldi  cr0, r10, r0
+       beq     no_xive
+       ld      r11, VCPU_XIVE_SAVED_STATE(r4)
+       li      r9, TM_QW1_OS
+       stdcix  r11,r9,r10
+       eieio
+       lwz     r11, VCPU_XIVE_CAM_WORD(r4)
+       li      r9, TM_QW1_OS + TM_WORD2
+       stwcix  r11,r9,r10
+       li      r9, 1
+       stw     r9, VCPU_XIVE_PUSHED(r4)
+no_xive:
+#endif /* CONFIG_KVM_XICS */
+
 deliver_guest_interrupt:
        ld      r6, VCPU_CTR(r4)
        ld      r7, VCPU_XER(r4)
@@ -1307,6 +1325,42 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
        blt     deliver_guest_interrupt
 
 guest_exit_cont:               /* r9 = vcpu, r12 = trap, r13 = paca */
+#ifdef CONFIG_KVM_XICS
+       /* We are exiting, pull the VP from the XIVE */
+       lwz     r0, VCPU_XIVE_PUSHED(r9)
+       cmpwi   cr0, r0, 0
+       beq     1f
+       li      r7, TM_SPC_PULL_OS_CTX
+       li      r6, TM_QW1_OS
+       mfmsr   r0
+       andi.   r0, r0, MSR_IR          /* in real mode? */
+       beq     2f
+       ld      r10, HSTATE_XIVE_TIMA_VIRT(r13)
+       cmpldi  cr0, r10, 0
+       beq     1f
+       /* First load to pull the context, we ignore the value */
+       lwzx    r11, r7, r10
+       eieio
+       /* Second load to recover the context state (Words 0 and 1) */
+       ldx     r11, r6, r10
+       b       3f
+2:     ld      r10, HSTATE_XIVE_TIMA_PHYS(r13)
+       cmpldi  cr0, r10, 0
+       beq     1f
+       /* First load to pull the context, we ignore the value */
+       lwzcix  r11, r7, r10
+       eieio
+       /* Second load to recover the context state (Words 0 and 1) */
+       ldcix   r11, r6, r10
+3:     std     r11, VCPU_XIVE_SAVED_STATE(r9)
+       /* Fixup some of the state for the next load */
+       li      r10, 0
+       li      r0, 0xff
+       stw     r10, VCPU_XIVE_PUSHED(r9)
+       stb     r10, (VCPU_XIVE_SAVED_STATE+3)(r9)
+       stb     r0, (VCPU_XIVE_SAVED_STATE+4)(r9)
+1:
+#endif /* CONFIG_KVM_XICS */
        /* Save more register state  */
        mfdar   r6
        mfdsisr r7
@@ -2011,7 +2065,7 @@ hcall_real_table:
        .long   DOTSYM(kvmppc_rm_h_eoi) - hcall_real_table
        .long   DOTSYM(kvmppc_rm_h_cppr) - hcall_real_table
        .long   DOTSYM(kvmppc_rm_h_ipi) - hcall_real_table
-       .long   0               /* 0x70 - H_IPOLL */
+       .long   DOTSYM(kvmppc_rm_h_ipoll) - hcall_real_table
        .long   DOTSYM(kvmppc_rm_h_xirr) - hcall_real_table
 #else
        .long   0               /* 0x64 - H_EOI */
@@ -2181,7 +2235,11 @@ hcall_real_table:
        .long   0               /* 0x2f0 */
        .long   0               /* 0x2f4 */
        .long   0               /* 0x2f8 */
-       .long   0               /* 0x2fc */
+#ifdef CONFIG_KVM_XICS
+       .long   DOTSYM(kvmppc_rm_h_xirr_x) - hcall_real_table
+#else
+       .long   0               /* 0x2fc - H_XIRR_X*/
+#endif
        .long   DOTSYM(kvmppc_h_random) - hcall_real_table
        .globl  hcall_real_table_end
 hcall_real_table_end:
index bcbeeb62dd13e9eafb9d0b8e4c6ece982627db85..8a4205fa774fe552a8a7f72b90b9c28dfb1ed0e5 100644 (file)
@@ -50,7 +50,9 @@ static int kvmppc_h_pr_enter(struct kvm_vcpu *vcpu)
        pteg_addr = get_pteg_addr(vcpu, pte_index);
 
        mutex_lock(&vcpu->kvm->arch.hpt_mutex);
-       copy_from_user(pteg, (void __user *)pteg_addr, sizeof(pteg));
+       ret = H_FUNCTION;
+       if (copy_from_user(pteg, (void __user *)pteg_addr, sizeof(pteg)))
+               goto done;
        hpte = pteg;
 
        ret = H_PTEG_FULL;
@@ -71,7 +73,9 @@ static int kvmppc_h_pr_enter(struct kvm_vcpu *vcpu)
        hpte[0] = cpu_to_be64(kvmppc_get_gpr(vcpu, 6));
        hpte[1] = cpu_to_be64(kvmppc_get_gpr(vcpu, 7));
        pteg_addr += i * HPTE_SIZE;
-       copy_to_user((void __user *)pteg_addr, hpte, HPTE_SIZE);
+       ret = H_FUNCTION;
+       if (copy_to_user((void __user *)pteg_addr, hpte, HPTE_SIZE))
+               goto done;
        kvmppc_set_gpr(vcpu, 4, pte_index | i);
        ret = H_SUCCESS;
 
@@ -93,7 +97,9 @@ static int kvmppc_h_pr_remove(struct kvm_vcpu *vcpu)
 
        pteg = get_pteg_addr(vcpu, pte_index);
        mutex_lock(&vcpu->kvm->arch.hpt_mutex);
-       copy_from_user(pte, (void __user *)pteg, sizeof(pte));
+       ret = H_FUNCTION;
+       if (copy_from_user(pte, (void __user *)pteg, sizeof(pte)))
+               goto done;
        pte[0] = be64_to_cpu((__force __be64)pte[0]);
        pte[1] = be64_to_cpu((__force __be64)pte[1]);
 
@@ -103,7 +109,9 @@ static int kvmppc_h_pr_remove(struct kvm_vcpu *vcpu)
            ((flags & H_ANDCOND) && (pte[0] & avpn) != 0))
                goto done;
 
-       copy_to_user((void __user *)pteg, &v, sizeof(v));
+       ret = H_FUNCTION;
+       if (copy_to_user((void __user *)pteg, &v, sizeof(v)))
+               goto done;
 
        rb = compute_tlbie_rb(pte[0], pte[1], pte_index);
        vcpu->arch.mmu.tlbie(vcpu, rb, rb & 1 ? true : false);
@@ -171,7 +179,10 @@ static int kvmppc_h_pr_bulk_remove(struct kvm_vcpu *vcpu)
                }
 
                pteg = get_pteg_addr(vcpu, tsh & H_BULK_REMOVE_PTEX);
-               copy_from_user(pte, (void __user *)pteg, sizeof(pte));
+               if (copy_from_user(pte, (void __user *)pteg, sizeof(pte))) {
+                       ret = H_FUNCTION;
+                       break;
+               }
                pte[0] = be64_to_cpu((__force __be64)pte[0]);
                pte[1] = be64_to_cpu((__force __be64)pte[1]);
 
@@ -184,7 +195,10 @@ static int kvmppc_h_pr_bulk_remove(struct kvm_vcpu *vcpu)
                        tsh |= H_BULK_REMOVE_NOT_FOUND;
                } else {
                        /* Splat the pteg in (userland) hpt */
-                       copy_to_user((void __user *)pteg, &v, sizeof(v));
+                       if (copy_to_user((void __user *)pteg, &v, sizeof(v))) {
+                               ret = H_FUNCTION;
+                               break;
+                       }
 
                        rb = compute_tlbie_rb(pte[0], pte[1],
                                              tsh & H_BULK_REMOVE_PTEX);
@@ -211,7 +225,9 @@ static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu)
 
        pteg = get_pteg_addr(vcpu, pte_index);
        mutex_lock(&vcpu->kvm->arch.hpt_mutex);
-       copy_from_user(pte, (void __user *)pteg, sizeof(pte));
+       ret = H_FUNCTION;
+       if (copy_from_user(pte, (void __user *)pteg, sizeof(pte)))
+               goto done;
        pte[0] = be64_to_cpu((__force __be64)pte[0]);
        pte[1] = be64_to_cpu((__force __be64)pte[1]);
 
@@ -234,7 +250,9 @@ static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu)
        vcpu->arch.mmu.tlbie(vcpu, rb, rb & 1 ? true : false);
        pte[0] = (__force u64)cpu_to_be64(pte[0]);
        pte[1] = (__force u64)cpu_to_be64(pte[1]);
-       copy_to_user((void __user *)pteg, pte, sizeof(pte));
+       ret = H_FUNCTION;
+       if (copy_to_user((void __user *)pteg, pte, sizeof(pte)))
+               goto done;
        ret = H_SUCCESS;
 
  done:
@@ -244,36 +262,37 @@ static int kvmppc_h_pr_protect(struct kvm_vcpu *vcpu)
        return EMULATE_DONE;
 }
 
-static int kvmppc_h_pr_put_tce(struct kvm_vcpu *vcpu)
+static int kvmppc_h_pr_logical_ci_load(struct kvm_vcpu *vcpu)
 {
-       unsigned long liobn = kvmppc_get_gpr(vcpu, 4);
-       unsigned long ioba = kvmppc_get_gpr(vcpu, 5);
-       unsigned long tce = kvmppc_get_gpr(vcpu, 6);
        long rc;
 
-       rc = kvmppc_h_put_tce(vcpu, liobn, ioba, tce);
+       rc = kvmppc_h_logical_ci_load(vcpu);
        if (rc == H_TOO_HARD)
                return EMULATE_FAIL;
        kvmppc_set_gpr(vcpu, 3, rc);
        return EMULATE_DONE;
 }
 
-static int kvmppc_h_pr_logical_ci_load(struct kvm_vcpu *vcpu)
+static int kvmppc_h_pr_logical_ci_store(struct kvm_vcpu *vcpu)
 {
        long rc;
 
-       rc = kvmppc_h_logical_ci_load(vcpu);
+       rc = kvmppc_h_logical_ci_store(vcpu);
        if (rc == H_TOO_HARD)
                return EMULATE_FAIL;
        kvmppc_set_gpr(vcpu, 3, rc);
        return EMULATE_DONE;
 }
 
-static int kvmppc_h_pr_logical_ci_store(struct kvm_vcpu *vcpu)
+#ifdef CONFIG_SPAPR_TCE_IOMMU
+static int kvmppc_h_pr_put_tce(struct kvm_vcpu *vcpu)
 {
+       unsigned long liobn = kvmppc_get_gpr(vcpu, 4);
+       unsigned long ioba = kvmppc_get_gpr(vcpu, 5);
+       unsigned long tce = kvmppc_get_gpr(vcpu, 6);
        long rc;
 
-       rc = kvmppc_h_logical_ci_store(vcpu);
+       rc = kvmppc_h_put_tce(vcpu, liobn, ioba, tce);
        if (rc == H_TOO_HARD)
                return EMULATE_FAIL;
        kvmppc_set_gpr(vcpu, 3, rc);
@@ -311,6 +330,23 @@ static int kvmppc_h_pr_stuff_tce(struct kvm_vcpu *vcpu)
        return EMULATE_DONE;
 }
 
+#else /* CONFIG_SPAPR_TCE_IOMMU */
+static int kvmppc_h_pr_put_tce(struct kvm_vcpu *vcpu)
+{
+       return EMULATE_FAIL;
+}
+
+static int kvmppc_h_pr_put_tce_indirect(struct kvm_vcpu *vcpu)
+{
+       return EMULATE_FAIL;
+}
+
+static int kvmppc_h_pr_stuff_tce(struct kvm_vcpu *vcpu)
+{
+       return EMULATE_FAIL;
+}
+#endif /* CONFIG_SPAPR_TCE_IOMMU */
+
 static int kvmppc_h_pr_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd)
 {
        long rc = kvmppc_xics_hcall(vcpu, cmd);
index 20528701835bf8c081d680ee52492ce7109187ab..2d3b2b1cc272b0989858bfb4e945567ddef96369 100644 (file)
@@ -16,6 +16,7 @@
 #include <asm/kvm_ppc.h>
 #include <asm/hvcall.h>
 #include <asm/rtas.h>
+#include <asm/xive.h>
 
 #ifdef CONFIG_KVM_XICS
 static void kvm_rtas_set_xive(struct kvm_vcpu *vcpu, struct rtas_args *args)
@@ -32,7 +33,10 @@ static void kvm_rtas_set_xive(struct kvm_vcpu *vcpu, struct rtas_args *args)
        server = be32_to_cpu(args->args[1]);
        priority = be32_to_cpu(args->args[2]);
 
-       rc = kvmppc_xics_set_xive(vcpu->kvm, irq, server, priority);
+       if (xive_enabled())
+               rc = kvmppc_xive_set_xive(vcpu->kvm, irq, server, priority);
+       else
+               rc = kvmppc_xics_set_xive(vcpu->kvm, irq, server, priority);
        if (rc)
                rc = -3;
 out:
@@ -52,7 +56,10 @@ static void kvm_rtas_get_xive(struct kvm_vcpu *vcpu, struct rtas_args *args)
        irq = be32_to_cpu(args->args[0]);
 
        server = priority = 0;
-       rc = kvmppc_xics_get_xive(vcpu->kvm, irq, &server, &priority);
+       if (xive_enabled())
+               rc = kvmppc_xive_get_xive(vcpu->kvm, irq, &server, &priority);
+       else
+               rc = kvmppc_xics_get_xive(vcpu->kvm, irq, &server, &priority);
        if (rc) {
                rc = -3;
                goto out;
@@ -76,7 +83,10 @@ static void kvm_rtas_int_off(struct kvm_vcpu *vcpu, struct rtas_args *args)
 
        irq = be32_to_cpu(args->args[0]);
 
-       rc = kvmppc_xics_int_off(vcpu->kvm, irq);
+       if (xive_enabled())
+               rc = kvmppc_xive_int_off(vcpu->kvm, irq);
+       else
+               rc = kvmppc_xics_int_off(vcpu->kvm, irq);
        if (rc)
                rc = -3;
 out:
@@ -95,7 +105,10 @@ static void kvm_rtas_int_on(struct kvm_vcpu *vcpu, struct rtas_args *args)
 
        irq = be32_to_cpu(args->args[0]);
 
-       rc = kvmppc_xics_int_on(vcpu->kvm, irq);
+       if (xive_enabled())
+               rc = kvmppc_xive_int_on(vcpu->kvm, irq);
+       else
+               rc = kvmppc_xics_int_on(vcpu->kvm, irq);
        if (rc)
                rc = -3;
 out:
index 459b72cb617aa3478cb6ac4c13a1d99ace6ada41..d329b2add7e2f007e7a24a24cd57b8ffa2b2ebfe 100644 (file)
@@ -1306,8 +1306,8 @@ static int xics_set_source(struct kvmppc_xics *xics, long irq, u64 addr)
        return 0;
 }
 
-int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level,
-               bool line_status)
+int kvmppc_xics_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level,
+                       bool line_status)
 {
        struct kvmppc_xics *xics = kvm->arch.xics;
 
@@ -1316,14 +1316,6 @@ int kvm_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level,
        return ics_deliver_irq(xics, irq, level);
 }
 
-int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *irq_entry,
-                             struct kvm *kvm, int irq_source_id,
-                             int level, bool line_status)
-{
-       return kvm_set_irq(kvm, irq_source_id, irq_entry->gsi,
-                          level, line_status);
-}
-
 static int xics_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
 {
        struct kvmppc_xics *xics = dev->private;
@@ -1457,29 +1449,6 @@ void kvmppc_xics_free_icp(struct kvm_vcpu *vcpu)
        vcpu->arch.irq_type = KVMPPC_IRQ_DEFAULT;
 }
 
-static int xics_set_irq(struct kvm_kernel_irq_routing_entry *e,
-                       struct kvm *kvm, int irq_source_id, int level,
-                       bool line_status)
-{
-       return kvm_set_irq(kvm, irq_source_id, e->gsi, level, line_status);
-}
-
-int kvm_irq_map_gsi(struct kvm *kvm,
-                   struct kvm_kernel_irq_routing_entry *entries, int gsi)
-{
-       entries->gsi = gsi;
-       entries->type = KVM_IRQ_ROUTING_IRQCHIP;
-       entries->set = xics_set_irq;
-       entries->irqchip.irqchip = 0;
-       entries->irqchip.pin = gsi;
-       return 1;
-}
-
-int kvm_irq_map_chip_pin(struct kvm *kvm, unsigned irqchip, unsigned pin)
-{
-       return pin;
-}
-
 void kvmppc_xics_set_mapped(struct kvm *kvm, unsigned long irq,
                            unsigned long host_irq)
 {
index ec5474cf70c633e00ce0ca47cb116a74470a658f..453c9e518c191a4cfbbd2cdfe3bda0233d0cd851 100644 (file)
@@ -10,6 +10,7 @@
 #ifndef _KVM_PPC_BOOK3S_XICS_H
 #define _KVM_PPC_BOOK3S_XICS_H
 
+#ifdef CONFIG_KVM_XICS
 /*
  * We use a two-level tree to store interrupt source information.
  * There are up to 1024 ICS nodes, each of which can represent
@@ -144,5 +145,11 @@ static inline struct kvmppc_ics *kvmppc_xics_find_ics(struct kvmppc_xics *xics,
        return ics;
 }
 
+extern unsigned long xics_rm_h_xirr(struct kvm_vcpu *vcpu);
+extern int xics_rm_h_ipi(struct kvm_vcpu *vcpu, unsigned long server,
+                        unsigned long mfrr);
+extern int xics_rm_h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr);
+extern int xics_rm_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr);
 
+#endif /* CONFIG_KVM_XICS */
 #endif /* _KVM_PPC_BOOK3S_XICS_H */
diff --git a/arch/powerpc/kvm/book3s_xive.c b/arch/powerpc/kvm/book3s_xive.c
new file mode 100644 (file)
index 0000000..ffe1da9
--- /dev/null
@@ -0,0 +1,1894 @@
+/*
+ * Copyright 2017 Benjamin Herrenschmidt, IBM Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ */
+
+#define pr_fmt(fmt) "xive-kvm: " fmt
+
+#include <linux/kernel.h>
+#include <linux/kvm_host.h>
+#include <linux/err.h>
+#include <linux/gfp.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/percpu.h>
+#include <linux/cpumask.h>
+#include <asm/uaccess.h>
+#include <asm/kvm_book3s.h>
+#include <asm/kvm_ppc.h>
+#include <asm/hvcall.h>
+#include <asm/xics.h>
+#include <asm/xive.h>
+#include <asm/xive-regs.h>
+#include <asm/debug.h>
+#include <asm/debugfs.h>
+#include <asm/time.h>
+#include <asm/opal.h>
+
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+
+#include "book3s_xive.h"
+
+
+/*
+ * Virtual mode variants of the hcalls for use on radix/radix
+ * with AIL. They require the VCPU's VP to be "pushed"
+ *
+ * We still instanciate them here because we use some of the
+ * generated utility functions as well in this file.
+ */
+#define XIVE_RUNTIME_CHECKS
+#define X_PFX xive_vm_
+#define X_STATIC static
+#define X_STAT_PFX stat_vm_
+#define __x_tima               xive_tima
+#define __x_eoi_page(xd)       ((void __iomem *)((xd)->eoi_mmio))
+#define __x_trig_page(xd)      ((void __iomem *)((xd)->trig_mmio))
+#define __x_readb      __raw_readb
+#define __x_writeb     __raw_writeb
+#define __x_readw      __raw_readw
+#define __x_readq      __raw_readq
+#define __x_writeq     __raw_writeq
+
+#include "book3s_xive_template.c"
+
+/*
+ * We leave a gap of a couple of interrupts in the queue to
+ * account for the IPI and additional safety guard.
+ */
+#define XIVE_Q_GAP     2
+
+/*
+ * This is a simple trigger for a generic XIVE IRQ. This must
+ * only be called for interrupts that support a trigger page
+ */
+static bool xive_irq_trigger(struct xive_irq_data *xd)
+{
+       /* This should be only for MSIs */
+       if (WARN_ON(xd->flags & XIVE_IRQ_FLAG_LSI))
+               return false;
+
+       /* Those interrupts should always have a trigger page */
+       if (WARN_ON(!xd->trig_mmio))
+               return false;
+
+       out_be64(xd->trig_mmio, 0);
+
+       return true;
+}
+
+static irqreturn_t xive_esc_irq(int irq, void *data)
+{
+       struct kvm_vcpu *vcpu = data;
+
+       /* We use the existing H_PROD mechanism to wake up the target */
+       vcpu->arch.prodded = 1;
+       smp_mb();
+       if (vcpu->arch.ceded)
+               kvmppc_fast_vcpu_kick(vcpu);
+
+       return IRQ_HANDLED;
+}
+
+static int xive_attach_escalation(struct kvm_vcpu *vcpu, u8 prio)
+{
+       struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
+       struct xive_q *q = &xc->queues[prio];
+       char *name = NULL;
+       int rc;
+
+       /* Already there ? */
+       if (xc->esc_virq[prio])
+               return 0;
+
+       /* Hook up the escalation interrupt */
+       xc->esc_virq[prio] = irq_create_mapping(NULL, q->esc_irq);
+       if (!xc->esc_virq[prio]) {
+               pr_err("Failed to map escalation interrupt for queue %d of VCPU %d\n",
+                      prio, xc->server_num);
+               return -EIO;
+       }
+
+       /*
+        * Future improvement: start with them disabled
+        * and handle DD2 and later scheme of merged escalation
+        * interrupts
+        */
+       name = kasprintf(GFP_KERNEL, "kvm-%d-%d-%d",
+                        vcpu->kvm->arch.lpid, xc->server_num, prio);
+       if (!name) {
+               pr_err("Failed to allocate escalation irq name for queue %d of VCPU %d\n",
+                      prio, xc->server_num);
+               rc = -ENOMEM;
+               goto error;
+       }
+       rc = request_irq(xc->esc_virq[prio], xive_esc_irq,
+                        IRQF_NO_THREAD, name, vcpu);
+       if (rc) {
+               pr_err("Failed to request escalation interrupt for queue %d of VCPU %d\n",
+                      prio, xc->server_num);
+               goto error;
+       }
+       xc->esc_virq_names[prio] = name;
+       return 0;
+error:
+       irq_dispose_mapping(xc->esc_virq[prio]);
+       xc->esc_virq[prio] = 0;
+       kfree(name);
+       return rc;
+}
+
+static int xive_provision_queue(struct kvm_vcpu *vcpu, u8 prio)
+{
+       struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
+       struct kvmppc_xive *xive = xc->xive;
+       struct xive_q *q =  &xc->queues[prio];
+       void *qpage;
+       int rc;
+
+       if (WARN_ON(q->qpage))
+               return 0;
+
+       /* Allocate the queue and retrieve infos on current node for now */
+       qpage = (__be32 *)__get_free_pages(GFP_KERNEL, xive->q_page_order);
+       if (!qpage) {
+               pr_err("Failed to allocate queue %d for VCPU %d\n",
+                      prio, xc->server_num);
+               return -ENOMEM;;
+       }
+       memset(qpage, 0, 1 << xive->q_order);
+
+       /*
+        * Reconfigure the queue. This will set q->qpage only once the
+        * queue is fully configured. This is a requirement for prio 0
+        * as we will stop doing EOIs for every IPI as soon as we observe
+        * qpage being non-NULL, and instead will only EOI when we receive
+        * corresponding queue 0 entries
+        */
+       rc = xive_native_configure_queue(xc->vp_id, q, prio, qpage,
+                                        xive->q_order, true);
+       if (rc)
+               pr_err("Failed to configure queue %d for VCPU %d\n",
+                      prio, xc->server_num);
+       return rc;
+}
+
+/* Called with kvm_lock held */
+static int xive_check_provisioning(struct kvm *kvm, u8 prio)
+{
+       struct kvmppc_xive *xive = kvm->arch.xive;
+       struct kvm_vcpu *vcpu;
+       int i, rc;
+
+       lockdep_assert_held(&kvm->lock);
+
+       /* Already provisioned ? */
+       if (xive->qmap & (1 << prio))
+               return 0;
+
+       pr_devel("Provisioning prio... %d\n", prio);
+
+       /* Provision each VCPU and enable escalations */
+       kvm_for_each_vcpu(i, vcpu, kvm) {
+               if (!vcpu->arch.xive_vcpu)
+                       continue;
+               rc = xive_provision_queue(vcpu, prio);
+               if (rc == 0)
+                       xive_attach_escalation(vcpu, prio);
+               if (rc)
+                       return rc;
+       }
+
+       /* Order previous stores and mark it as provisioned */
+       mb();
+       xive->qmap |= (1 << prio);
+       return 0;
+}
+
+static void xive_inc_q_pending(struct kvm *kvm, u32 server, u8 prio)
+{
+       struct kvm_vcpu *vcpu;
+       struct kvmppc_xive_vcpu *xc;
+       struct xive_q *q;
+
+       /* Locate target server */
+       vcpu = kvmppc_xive_find_server(kvm, server);
+       if (!vcpu) {
+               pr_warn("%s: Can't find server %d\n", __func__, server);
+               return;
+       }
+       xc = vcpu->arch.xive_vcpu;
+       if (WARN_ON(!xc))
+               return;
+
+       q = &xc->queues[prio];
+       atomic_inc(&q->pending_count);
+}
+
+static int xive_try_pick_queue(struct kvm_vcpu *vcpu, u8 prio)
+{
+       struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
+       struct xive_q *q;
+       u32 max;
+
+       if (WARN_ON(!xc))
+               return -ENXIO;
+       if (!xc->valid)
+               return -ENXIO;
+
+       q = &xc->queues[prio];
+       if (WARN_ON(!q->qpage))
+               return -ENXIO;
+
+       /* Calculate max number of interrupts in that queue. */
+       max = (q->msk + 1) - XIVE_Q_GAP;
+       return atomic_add_unless(&q->count, 1, max) ? 0 : -EBUSY;
+}
+
+static int xive_select_target(struct kvm *kvm, u32 *server, u8 prio)
+{
+       struct kvm_vcpu *vcpu;
+       int i, rc;
+
+       /* Locate target server */
+       vcpu = kvmppc_xive_find_server(kvm, *server);
+       if (!vcpu) {
+               pr_devel("Can't find server %d\n", *server);
+               return -EINVAL;
+       }
+
+       pr_devel("Finding irq target on 0x%x/%d...\n", *server, prio);
+
+       /* Try pick it */
+       rc = xive_try_pick_queue(vcpu, prio);
+       if (rc == 0)
+               return rc;
+
+       pr_devel(" .. failed, looking up candidate...\n");
+
+       /* Failed, pick another VCPU */
+       kvm_for_each_vcpu(i, vcpu, kvm) {
+               if (!vcpu->arch.xive_vcpu)
+                       continue;
+               rc = xive_try_pick_queue(vcpu, prio);
+               if (rc == 0) {
+                       *server = vcpu->arch.xive_vcpu->server_num;
+                       pr_devel("  found on 0x%x/%d\n", *server, prio);
+                       return rc;
+               }
+       }
+       pr_devel("  no available target !\n");
+
+       /* No available target ! */
+       return -EBUSY;
+}
+
+static u8 xive_lock_and_mask(struct kvmppc_xive *xive,
+                            struct kvmppc_xive_src_block *sb,
+                            struct kvmppc_xive_irq_state *state)
+{
+       struct xive_irq_data *xd;
+       u32 hw_num;
+       u8 old_prio;
+       u64 val;
+
+       /*
+        * Take the lock, set masked, try again if racing
+        * with H_EOI
+        */
+       for (;;) {
+               arch_spin_lock(&sb->lock);
+               old_prio = state->guest_priority;
+               state->guest_priority = MASKED;
+               mb();
+               if (!state->in_eoi)
+                       break;
+               state->guest_priority = old_prio;
+               arch_spin_unlock(&sb->lock);
+       }
+
+       /* No change ? Bail */
+       if (old_prio == MASKED)
+               return old_prio;
+
+       /* Get the right irq */
+       kvmppc_xive_select_irq(state, &hw_num, &xd);
+
+       /*
+        * If the interrupt is marked as needing masking via
+        * firmware, we do it here. Firmware masking however
+        * is "lossy", it won't return the old p and q bits
+        * and won't set the interrupt to a state where it will
+        * record queued ones. If this is an issue we should do
+        * lazy masking instead.
+        *
+        * For now, we work around this in unmask by forcing
+        * an interrupt whenever we unmask a non-LSI via FW
+        * (if ever).
+        */
+       if (xd->flags & OPAL_XIVE_IRQ_MASK_VIA_FW) {
+               xive_native_configure_irq(hw_num,
+                                         xive->vp_base + state->act_server,
+                                         MASKED, state->number);
+               /* set old_p so we can track if an H_EOI was done */
+               state->old_p = true;
+               state->old_q = false;
+       } else {
+               /* Set PQ to 10, return old P and old Q and remember them */
+               val = xive_vm_esb_load(xd, XIVE_ESB_SET_PQ_10);
+               state->old_p = !!(val & 2);
+               state->old_q = !!(val & 1);
+
+               /*
+                * Synchronize hardware to sensure the queues are updated
+                * when masking
+                */
+               xive_native_sync_source(hw_num);
+       }
+
+       return old_prio;
+}
+
+static void xive_lock_for_unmask(struct kvmppc_xive_src_block *sb,
+                                struct kvmppc_xive_irq_state *state)
+{
+       /*
+        * Take the lock try again if racing with H_EOI
+        */
+       for (;;) {
+               arch_spin_lock(&sb->lock);
+               if (!state->in_eoi)
+                       break;
+               arch_spin_unlock(&sb->lock);
+       }
+}
+
+static void xive_finish_unmask(struct kvmppc_xive *xive,
+                              struct kvmppc_xive_src_block *sb,
+                              struct kvmppc_xive_irq_state *state,
+                              u8 prio)
+{
+       struct xive_irq_data *xd;
+       u32 hw_num;
+
+       /* If we aren't changing a thing, move on */
+       if (state->guest_priority != MASKED)
+               goto bail;
+
+       /* Get the right irq */
+       kvmppc_xive_select_irq(state, &hw_num, &xd);
+
+       /*
+        * See command in xive_lock_and_mask() concerning masking
+        * via firmware.
+        */
+       if (xd->flags & OPAL_XIVE_IRQ_MASK_VIA_FW) {
+               xive_native_configure_irq(hw_num,
+                                         xive->vp_base + state->act_server,
+                                         state->act_priority, state->number);
+               /* If an EOI is needed, do it here */
+               if (!state->old_p)
+                       xive_vm_source_eoi(hw_num, xd);
+               /* If this is not an LSI, force a trigger */
+               if (!(xd->flags & OPAL_XIVE_IRQ_LSI))
+                       xive_irq_trigger(xd);
+               goto bail;
+       }
+
+       /* Old Q set, set PQ to 11 */
+       if (state->old_q)
+               xive_vm_esb_load(xd, XIVE_ESB_SET_PQ_11);
+
+       /*
+        * If not old P, then perform an "effective" EOI,
+        * on the source. This will handle the cases where
+        * FW EOI is needed.
+        */
+       if (!state->old_p)
+               xive_vm_source_eoi(hw_num, xd);
+
+       /* Synchronize ordering and mark unmasked */
+       mb();
+bail:
+       state->guest_priority = prio;
+}
+
+/*
+ * Target an interrupt to a given server/prio, this will fallback
+ * to another server if necessary and perform the HW targetting
+ * updates as needed
+ *
+ * NOTE: Must be called with the state lock held
+ */
+static int xive_target_interrupt(struct kvm *kvm,
+                                struct kvmppc_xive_irq_state *state,
+                                u32 server, u8 prio)
+{
+       struct kvmppc_xive *xive = kvm->arch.xive;
+       u32 hw_num;
+       int rc;
+
+       /*
+        * This will return a tentative server and actual
+        * priority. The count for that new target will have
+        * already been incremented.
+        */
+       rc = xive_select_target(kvm, &server, prio);
+
+       /*
+        * We failed to find a target ? Not much we can do
+        * at least until we support the GIQ.
+        */
+       if (rc)
+               return rc;
+
+       /*
+        * Increment the old queue pending count if there
+        * was one so that the old queue count gets adjusted later
+        * when observed to be empty.
+        */
+       if (state->act_priority != MASKED)
+               xive_inc_q_pending(kvm,
+                                  state->act_server,
+                                  state->act_priority);
+       /*
+        * Update state and HW
+        */
+       state->act_priority = prio;
+       state->act_server = server;
+
+       /* Get the right irq */
+       kvmppc_xive_select_irq(state, &hw_num, NULL);
+
+       return xive_native_configure_irq(hw_num,
+                                        xive->vp_base + server,
+                                        prio, state->number);
+}
+
+/*
+ * Targetting rules: In order to avoid losing track of
+ * pending interrupts accross mask and unmask, which would
+ * allow queue overflows, we implement the following rules:
+ *
+ *  - Unless it was never enabled (or we run out of capacity)
+ *    an interrupt is always targetted at a valid server/queue
+ *    pair even when "masked" by the guest. This pair tends to
+ *    be the last one used but it can be changed under some
+ *    circumstances. That allows us to separate targetting
+ *    from masking, we only handle accounting during (re)targetting,
+ *    this also allows us to let an interrupt drain into its target
+ *    queue after masking, avoiding complex schemes to remove
+ *    interrupts out of remote processor queues.
+ *
+ *  - When masking, we set PQ to 10 and save the previous value
+ *    of P and Q.
+ *
+ *  - When unmasking, if saved Q was set, we set PQ to 11
+ *    otherwise we leave PQ to the HW state which will be either
+ *    10 if nothing happened or 11 if the interrupt fired while
+ *    masked. Effectively we are OR'ing the previous Q into the
+ *    HW Q.
+ *
+ *    Then if saved P is clear, we do an effective EOI (Q->P->Trigger)
+ *    which will unmask the interrupt and shoot a new one if Q was
+ *    set.
+ *
+ *    Otherwise (saved P is set) we leave PQ unchanged (so 10 or 11,
+ *    effectively meaning an H_EOI from the guest is still expected
+ *    for that interrupt).
+ *
+ *  - If H_EOI occurs while masked, we clear the saved P.
+ *
+ *  - When changing target, we account on the new target and
+ *    increment a separate "pending" counter on the old one.
+ *    This pending counter will be used to decrement the old
+ *    target's count when its queue has been observed empty.
+ */
+
+int kvmppc_xive_set_xive(struct kvm *kvm, u32 irq, u32 server,
+                        u32 priority)
+{
+       struct kvmppc_xive *xive = kvm->arch.xive;
+       struct kvmppc_xive_src_block *sb;
+       struct kvmppc_xive_irq_state *state;
+       u8 new_act_prio;
+       int rc = 0;
+       u16 idx;
+
+       if (!xive)
+               return -ENODEV;
+
+       pr_devel("set_xive ! irq 0x%x server 0x%x prio %d\n",
+                irq, server, priority);
+
+       /* First, check provisioning of queues */
+       if (priority != MASKED)
+               rc = xive_check_provisioning(xive->kvm,
+                             xive_prio_from_guest(priority));
+       if (rc) {
+               pr_devel("  provisioning failure %d !\n", rc);
+               return rc;
+       }
+
+       sb = kvmppc_xive_find_source(xive, irq, &idx);
+       if (!sb)
+               return -EINVAL;
+       state = &sb->irq_state[idx];
+
+       /*
+        * We first handle masking/unmasking since the locking
+        * might need to be retried due to EOIs, we'll handle
+        * targetting changes later. These functions will return
+        * with the SB lock held.
+        *
+        * xive_lock_and_mask() will also set state->guest_priority
+        * but won't otherwise change other fields of the state.
+        *
+        * xive_lock_for_unmask will not actually unmask, this will
+        * be done later by xive_finish_unmask() once the targetting
+        * has been done, so we don't try to unmask an interrupt
+        * that hasn't yet been targetted.
+        */
+       if (priority == MASKED)
+               xive_lock_and_mask(xive, sb, state);
+       else
+               xive_lock_for_unmask(sb, state);
+
+
+       /*
+        * Then we handle targetting.
+        *
+        * First calculate a new "actual priority"
+        */
+       new_act_prio = state->act_priority;
+       if (priority != MASKED)
+               new_act_prio = xive_prio_from_guest(priority);
+
+       pr_devel(" new_act_prio=%x act_server=%x act_prio=%x\n",
+                new_act_prio, state->act_server, state->act_priority);
+
+       /*
+        * Then check if we actually need to change anything,
+        *
+        * The condition for re-targetting the interrupt is that
+        * we have a valid new priority (new_act_prio is not 0xff)
+        * and either the server or the priority changed.
+        *
+        * Note: If act_priority was ff and the new priority is
+        *       also ff, we don't do anything and leave the interrupt
+        *       untargetted. An attempt of doing an int_on on an
+        *       untargetted interrupt will fail. If that is a problem
+        *       we could initialize interrupts with valid default
+        */
+
+       if (new_act_prio != MASKED &&
+           (state->act_server != server ||
+            state->act_priority != new_act_prio))
+               rc = xive_target_interrupt(kvm, state, server, new_act_prio);
+
+       /*
+        * Perform the final unmasking of the interrupt source
+        * if necessary
+        */
+       if (priority != MASKED)
+               xive_finish_unmask(xive, sb, state, priority);
+
+       /*
+        * Finally Update saved_priority to match. Only int_on/off
+        * set this field to a different value.
+        */
+       state->saved_priority = priority;
+
+       arch_spin_unlock(&sb->lock);
+       return rc;
+}
+
+int kvmppc_xive_get_xive(struct kvm *kvm, u32 irq, u32 *server,
+                        u32 *priority)
+{
+       struct kvmppc_xive *xive = kvm->arch.xive;
+       struct kvmppc_xive_src_block *sb;
+       struct kvmppc_xive_irq_state *state;
+       u16 idx;
+
+       if (!xive)
+               return -ENODEV;
+
+       sb = kvmppc_xive_find_source(xive, irq, &idx);
+       if (!sb)
+               return -EINVAL;
+       state = &sb->irq_state[idx];
+       arch_spin_lock(&sb->lock);
+       *server = state->guest_server;
+       *priority = state->guest_priority;
+       arch_spin_unlock(&sb->lock);
+
+       return 0;
+}
+
+int kvmppc_xive_int_on(struct kvm *kvm, u32 irq)
+{
+       struct kvmppc_xive *xive = kvm->arch.xive;
+       struct kvmppc_xive_src_block *sb;
+       struct kvmppc_xive_irq_state *state;
+       u16 idx;
+
+       if (!xive)
+               return -ENODEV;
+
+       sb = kvmppc_xive_find_source(xive, irq, &idx);
+       if (!sb)
+               return -EINVAL;
+       state = &sb->irq_state[idx];
+
+       pr_devel("int_on(irq=0x%x)\n", irq);
+
+       /*
+        * Check if interrupt was not targetted
+        */
+       if (state->act_priority == MASKED) {
+               pr_devel("int_on on untargetted interrupt\n");
+               return -EINVAL;
+       }
+
+       /* If saved_priority is 0xff, do nothing */
+       if (state->saved_priority == MASKED)
+               return 0;
+
+       /*
+        * Lock and unmask it.
+        */
+       xive_lock_for_unmask(sb, state);
+       xive_finish_unmask(xive, sb, state, state->saved_priority);
+       arch_spin_unlock(&sb->lock);
+
+       return 0;
+}
+
+int kvmppc_xive_int_off(struct kvm *kvm, u32 irq)
+{
+       struct kvmppc_xive *xive = kvm->arch.xive;
+       struct kvmppc_xive_src_block *sb;
+       struct kvmppc_xive_irq_state *state;
+       u16 idx;
+
+       if (!xive)
+               return -ENODEV;
+
+       sb = kvmppc_xive_find_source(xive, irq, &idx);
+       if (!sb)
+               return -EINVAL;
+       state = &sb->irq_state[idx];
+
+       pr_devel("int_off(irq=0x%x)\n", irq);
+
+       /*
+        * Lock and mask
+        */
+       state->saved_priority = xive_lock_and_mask(xive, sb, state);
+       arch_spin_unlock(&sb->lock);
+
+       return 0;
+}
+
+static bool xive_restore_pending_irq(struct kvmppc_xive *xive, u32 irq)
+{
+       struct kvmppc_xive_src_block *sb;
+       struct kvmppc_xive_irq_state *state;
+       u16 idx;
+
+       sb = kvmppc_xive_find_source(xive, irq, &idx);
+       if (!sb)
+               return false;
+       state = &sb->irq_state[idx];
+       if (!state->valid)
+               return false;
+
+       /*
+        * Trigger the IPI. This assumes we never restore a pass-through
+        * interrupt which should be safe enough
+        */
+       xive_irq_trigger(&state->ipi_data);
+
+       return true;
+}
+
+u64 kvmppc_xive_get_icp(struct kvm_vcpu *vcpu)
+{
+       struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
+
+       if (!xc)
+               return 0;
+
+       /* Return the per-cpu state for state saving/migration */
+       return (u64)xc->cppr << KVM_REG_PPC_ICP_CPPR_SHIFT |
+              (u64)xc->mfrr << KVM_REG_PPC_ICP_MFRR_SHIFT;
+}
+
+int kvmppc_xive_set_icp(struct kvm_vcpu *vcpu, u64 icpval)
+{
+       struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
+       struct kvmppc_xive *xive = vcpu->kvm->arch.xive;
+       u8 cppr, mfrr;
+       u32 xisr;
+
+       if (!xc || !xive)
+               return -ENOENT;
+
+       /* Grab individual state fields. We don't use pending_pri */
+       cppr = icpval >> KVM_REG_PPC_ICP_CPPR_SHIFT;
+       xisr = (icpval >> KVM_REG_PPC_ICP_XISR_SHIFT) &
+               KVM_REG_PPC_ICP_XISR_MASK;
+       mfrr = icpval >> KVM_REG_PPC_ICP_MFRR_SHIFT;
+
+       pr_devel("set_icp vcpu %d cppr=0x%x mfrr=0x%x xisr=0x%x\n",
+                xc->server_num, cppr, mfrr, xisr);
+
+       /*
+        * We can't update the state of a "pushed" VCPU, but that
+        * shouldn't happen.
+        */
+       if (WARN_ON(vcpu->arch.xive_pushed))
+               return -EIO;
+
+       /* Update VCPU HW saved state */
+       vcpu->arch.xive_saved_state.cppr = cppr;
+       xc->hw_cppr = xc->cppr = cppr;
+
+       /*
+        * Update MFRR state. If it's not 0xff, we mark the VCPU as
+        * having a pending MFRR change, which will re-evaluate the
+        * target. The VCPU will thus potentially get a spurious
+        * interrupt but that's not a big deal.
+        */
+       xc->mfrr = mfrr;
+       if (mfrr < cppr)
+               xive_irq_trigger(&xc->vp_ipi_data);
+
+       /*
+        * Now saved XIRR is "interesting". It means there's something in
+        * the legacy "1 element" queue... for an IPI we simply ignore it,
+        * as the MFRR restore will handle that. For anything else we need
+        * to force a resend of the source.
+        * However the source may not have been setup yet. If that's the
+        * case, we keep that info and increment a counter in the xive to
+        * tell subsequent xive_set_source() to go look.
+        */
+       if (xisr > XICS_IPI && !xive_restore_pending_irq(xive, xisr)) {
+               xc->delayed_irq = xisr;
+               xive->delayed_irqs++;
+               pr_devel("  xisr restore delayed\n");
+       }
+
+       return 0;
+}
+
+int kvmppc_xive_set_mapped(struct kvm *kvm, unsigned long guest_irq,
+                          struct irq_desc *host_desc)
+{
+       struct kvmppc_xive *xive = kvm->arch.xive;
+       struct kvmppc_xive_src_block *sb;
+       struct kvmppc_xive_irq_state *state;
+       struct irq_data *host_data = irq_desc_get_irq_data(host_desc);
+       unsigned int host_irq = irq_desc_get_irq(host_desc);
+       unsigned int hw_irq = (unsigned int)irqd_to_hwirq(host_data);
+       u16 idx;
+       u8 prio;
+       int rc;
+
+       if (!xive)
+               return -ENODEV;
+
+       pr_devel("set_mapped girq 0x%lx host HW irq 0x%x...\n",guest_irq, hw_irq);
+
+       sb = kvmppc_xive_find_source(xive, guest_irq, &idx);
+       if (!sb)
+               return -EINVAL;
+       state = &sb->irq_state[idx];
+
+       /*
+        * Mark the passed-through interrupt as going to a VCPU,
+        * this will prevent further EOIs and similar operations
+        * from the XIVE code. It will also mask the interrupt
+        * to either PQ=10 or 11 state, the latter if the interrupt
+        * is pending. This will allow us to unmask or retrigger it
+        * after routing it to the guest with a simple EOI.
+        *
+        * The "state" argument is a "token", all it needs is to be
+        * non-NULL to switch to passed-through or NULL for the
+        * other way around. We may not yet have an actual VCPU
+        * target here and we don't really care.
+        */
+       rc = irq_set_vcpu_affinity(host_irq, state);
+       if (rc) {
+               pr_err("Failed to set VCPU affinity for irq %d\n", host_irq);
+               return rc;
+       }
+
+       /*
+        * Mask and read state of IPI. We need to know if its P bit
+        * is set as that means it's potentially already using a
+        * queue entry in the target
+        */
+       prio = xive_lock_and_mask(xive, sb, state);
+       pr_devel(" old IPI prio %02x P:%d Q:%d\n", prio,
+                state->old_p, state->old_q);
+
+       /* Turn the IPI hard off */
+       xive_vm_esb_load(&state->ipi_data, XIVE_ESB_SET_PQ_01);
+
+       /* Grab info about irq */
+       state->pt_number = hw_irq;
+       state->pt_data = irq_data_get_irq_handler_data(host_data);
+
+       /*
+        * Configure the IRQ to match the existing configuration of
+        * the IPI if it was already targetted. Otherwise this will
+        * mask the interrupt in a lossy way (act_priority is 0xff)
+        * which is fine for a never started interrupt.
+        */
+       xive_native_configure_irq(hw_irq,
+                                 xive->vp_base + state->act_server,
+                                 state->act_priority, state->number);
+
+       /*
+        * We do an EOI to enable the interrupt (and retrigger if needed)
+        * if the guest has the interrupt unmasked and the P bit was *not*
+        * set in the IPI. If it was set, we know a slot may still be in
+        * use in the target queue thus we have to wait for a guest
+        * originated EOI
+        */
+       if (prio != MASKED && !state->old_p)
+               xive_vm_source_eoi(hw_irq, state->pt_data);
+
+       /* Clear old_p/old_q as they are no longer relevant */
+       state->old_p = state->old_q = false;
+
+       /* Restore guest prio (unlocks EOI) */
+       mb();
+       state->guest_priority = prio;
+       arch_spin_unlock(&sb->lock);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(kvmppc_xive_set_mapped);
+
+int kvmppc_xive_clr_mapped(struct kvm *kvm, unsigned long guest_irq,
+                          struct irq_desc *host_desc)
+{
+       struct kvmppc_xive *xive = kvm->arch.xive;
+       struct kvmppc_xive_src_block *sb;
+       struct kvmppc_xive_irq_state *state;
+       unsigned int host_irq = irq_desc_get_irq(host_desc);
+       u16 idx;
+       u8 prio;
+       int rc;
+
+       if (!xive)
+               return -ENODEV;
+
+       pr_devel("clr_mapped girq 0x%lx...\n", guest_irq);
+
+       sb = kvmppc_xive_find_source(xive, guest_irq, &idx);
+       if (!sb)
+               return -EINVAL;
+       state = &sb->irq_state[idx];
+
+       /*
+        * Mask and read state of IRQ. We need to know if its P bit
+        * is set as that means it's potentially already using a
+        * queue entry in the target
+        */
+       prio = xive_lock_and_mask(xive, sb, state);
+       pr_devel(" old IRQ prio %02x P:%d Q:%d\n", prio,
+                state->old_p, state->old_q);
+
+       /*
+        * If old_p is set, the interrupt is pending, we switch it to
+        * PQ=11. This will force a resend in the host so the interrupt
+        * isn't lost to whatver host driver may pick it up
+        */
+       if (state->old_p)
+               xive_vm_esb_load(state->pt_data, XIVE_ESB_SET_PQ_11);
+
+       /* Release the passed-through interrupt to the host */
+       rc = irq_set_vcpu_affinity(host_irq, NULL);
+       if (rc) {
+               pr_err("Failed to clr VCPU affinity for irq %d\n", host_irq);
+               return rc;
+       }
+
+       /* Forget about the IRQ */
+       state->pt_number = 0;
+       state->pt_data = NULL;
+
+       /* Reconfigure the IPI */
+       xive_native_configure_irq(state->ipi_number,
+                                 xive->vp_base + state->act_server,
+                                 state->act_priority, state->number);
+
+       /*
+        * If old_p is set (we have a queue entry potentially
+        * occupied) or the interrupt is masked, we set the IPI
+        * to PQ=10 state. Otherwise we just re-enable it (PQ=00).
+        */
+       if (prio == MASKED || state->old_p)
+               xive_vm_esb_load(&state->ipi_data, XIVE_ESB_SET_PQ_10);
+       else
+               xive_vm_esb_load(&state->ipi_data, XIVE_ESB_SET_PQ_00);
+
+       /* Restore guest prio (unlocks EOI) */
+       mb();
+       state->guest_priority = prio;
+       arch_spin_unlock(&sb->lock);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(kvmppc_xive_clr_mapped);
+
+static void kvmppc_xive_disable_vcpu_interrupts(struct kvm_vcpu *vcpu)
+{
+       struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
+       struct kvm *kvm = vcpu->kvm;
+       struct kvmppc_xive *xive = kvm->arch.xive;
+       int i, j;
+
+       for (i = 0; i <= xive->max_sbid; i++) {
+               struct kvmppc_xive_src_block *sb = xive->src_blocks[i];
+
+               if (!sb)
+                       continue;
+               for (j = 0; j < KVMPPC_XICS_IRQ_PER_ICS; j++) {
+                       struct kvmppc_xive_irq_state *state = &sb->irq_state[j];
+
+                       if (!state->valid)
+                               continue;
+                       if (state->act_priority == MASKED)
+                               continue;
+                       if (state->act_server != xc->server_num)
+                               continue;
+
+                       /* Clean it up */
+                       arch_spin_lock(&sb->lock);
+                       state->act_priority = MASKED;
+                       xive_vm_esb_load(&state->ipi_data, XIVE_ESB_SET_PQ_01);
+                       xive_native_configure_irq(state->ipi_number, 0, MASKED, 0);
+                       if (state->pt_number) {
+                               xive_vm_esb_load(state->pt_data, XIVE_ESB_SET_PQ_01);
+                               xive_native_configure_irq(state->pt_number, 0, MASKED, 0);
+                       }
+                       arch_spin_unlock(&sb->lock);
+               }
+       }
+}
+
+void kvmppc_xive_cleanup_vcpu(struct kvm_vcpu *vcpu)
+{
+       struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
+       struct kvmppc_xive *xive = xc->xive;
+       int i;
+
+       pr_devel("cleanup_vcpu(cpu=%d)\n", xc->server_num);
+
+       /* Ensure no interrupt is still routed to that VP */
+       xc->valid = false;
+       kvmppc_xive_disable_vcpu_interrupts(vcpu);
+
+       /* Mask the VP IPI */
+       xive_vm_esb_load(&xc->vp_ipi_data, XIVE_ESB_SET_PQ_01);
+
+       /* Disable the VP */
+       xive_native_disable_vp(xc->vp_id);
+
+       /* Free the queues & associated interrupts */
+       for (i = 0; i < KVMPPC_XIVE_Q_COUNT; i++) {
+               struct xive_q *q = &xc->queues[i];
+
+               /* Free the escalation irq */
+               if (xc->esc_virq[i]) {
+                       free_irq(xc->esc_virq[i], vcpu);
+                       irq_dispose_mapping(xc->esc_virq[i]);
+                       kfree(xc->esc_virq_names[i]);
+               }
+               /* Free the queue */
+               xive_native_disable_queue(xc->vp_id, q, i);
+               if (q->qpage) {
+                       free_pages((unsigned long)q->qpage,
+                                  xive->q_page_order);
+                       q->qpage = NULL;
+               }
+       }
+
+       /* Free the IPI */
+       if (xc->vp_ipi) {
+               xive_cleanup_irq_data(&xc->vp_ipi_data);
+               xive_native_free_irq(xc->vp_ipi);
+       }
+       /* Free the VP */
+       kfree(xc);
+}
+
+int kvmppc_xive_connect_vcpu(struct kvm_device *dev,
+                            struct kvm_vcpu *vcpu, u32 cpu)
+{
+       struct kvmppc_xive *xive = dev->private;
+       struct kvmppc_xive_vcpu *xc;
+       int i, r = -EBUSY;
+
+       pr_devel("connect_vcpu(cpu=%d)\n", cpu);
+
+       if (dev->ops != &kvm_xive_ops) {
+               pr_devel("Wrong ops !\n");
+               return -EPERM;
+       }
+       if (xive->kvm != vcpu->kvm)
+               return -EPERM;
+       if (vcpu->arch.irq_type)
+               return -EBUSY;
+       if (kvmppc_xive_find_server(vcpu->kvm, cpu)) {
+               pr_devel("Duplicate !\n");
+               return -EEXIST;
+       }
+       if (cpu >= KVM_MAX_VCPUS) {
+               pr_devel("Out of bounds !\n");
+               return -EINVAL;
+       }
+       xc = kzalloc(sizeof(*xc), GFP_KERNEL);
+       if (!xc)
+               return -ENOMEM;
+
+       /* We need to synchronize with queue provisioning */
+       mutex_lock(&vcpu->kvm->lock);
+       vcpu->arch.xive_vcpu = xc;
+       xc->xive = xive;
+       xc->vcpu = vcpu;
+       xc->server_num = cpu;
+       xc->vp_id = xive->vp_base + cpu;
+       xc->mfrr = 0xff;
+       xc->valid = true;
+
+       r = xive_native_get_vp_info(xc->vp_id, &xc->vp_cam, &xc->vp_chip_id);
+       if (r)
+               goto bail;
+
+       /* Configure VCPU fields for use by assembly push/pull */
+       vcpu->arch.xive_saved_state.w01 = cpu_to_be64(0xff000000);
+       vcpu->arch.xive_cam_word = cpu_to_be32(xc->vp_cam | TM_QW1W2_VO);
+
+       /* Allocate IPI */
+       xc->vp_ipi = xive_native_alloc_irq();
+       if (!xc->vp_ipi) {
+               r = -EIO;
+               goto bail;
+       }
+       pr_devel(" IPI=0x%x\n", xc->vp_ipi);
+
+       r = xive_native_populate_irq_data(xc->vp_ipi, &xc->vp_ipi_data);
+       if (r)
+               goto bail;
+
+       /*
+        * Initialize queues. Initially we set them all for no queueing
+        * and we enable escalation for queue 0 only which we'll use for
+        * our mfrr change notifications. If the VCPU is hot-plugged, we
+        * do handle provisioning however.
+        */
+       for (i = 0; i < KVMPPC_XIVE_Q_COUNT; i++) {
+               struct xive_q *q = &xc->queues[i];
+
+               /* Is queue already enabled ? Provision it */
+               if (xive->qmap & (1 << i)) {
+                       r = xive_provision_queue(vcpu, i);
+                       if (r == 0)
+                               xive_attach_escalation(vcpu, i);
+                       if (r)
+                               goto bail;
+               } else {
+                       r = xive_native_configure_queue(xc->vp_id,
+                                                       q, i, NULL, 0, true);
+                       if (r) {
+                               pr_err("Failed to configure queue %d for VCPU %d\n",
+                                      i, cpu);
+                               goto bail;
+                       }
+               }
+       }
+
+       /* If not done above, attach priority 0 escalation */
+       r = xive_attach_escalation(vcpu, 0);
+       if (r)
+               goto bail;
+
+       /* Enable the VP */
+       r = xive_native_enable_vp(xc->vp_id);
+       if (r)
+               goto bail;
+
+       /* Route the IPI */
+       r = xive_native_configure_irq(xc->vp_ipi, xc->vp_id, 0, XICS_IPI);
+       if (!r)
+               xive_vm_esb_load(&xc->vp_ipi_data, XIVE_ESB_SET_PQ_00);
+
+bail:
+       mutex_unlock(&vcpu->kvm->lock);
+       if (r) {
+               kvmppc_xive_cleanup_vcpu(vcpu);
+               return r;
+       }
+
+       vcpu->arch.irq_type = KVMPPC_IRQ_XICS;
+       return 0;
+}
+
+/*
+ * Scanning of queues before/after migration save
+ */
+static void xive_pre_save_set_queued(struct kvmppc_xive *xive, u32 irq)
+{
+       struct kvmppc_xive_src_block *sb;
+       struct kvmppc_xive_irq_state *state;
+       u16 idx;
+
+       sb = kvmppc_xive_find_source(xive, irq, &idx);
+       if (!sb)
+               return;
+
+       state = &sb->irq_state[idx];
+
+       /* Some sanity checking */
+       if (!state->valid) {
+               pr_err("invalid irq 0x%x in cpu queue!\n", irq);
+               return;
+       }
+
+       /*
+        * If the interrupt is in a queue it should have P set.
+        * We warn so that gets reported. A backtrace isn't useful
+        * so no need to use a WARN_ON.
+        */
+       if (!state->saved_p)
+               pr_err("Interrupt 0x%x is marked in a queue but P not set !\n", irq);
+
+       /* Set flag */
+       state->in_queue = true;
+}
+
+static void xive_pre_save_mask_irq(struct kvmppc_xive *xive,
+                                  struct kvmppc_xive_src_block *sb,
+                                  u32 irq)
+{
+       struct kvmppc_xive_irq_state *state = &sb->irq_state[irq];
+
+       if (!state->valid)
+               return;
+
+       /* Mask and save state, this will also sync HW queues */
+       state->saved_scan_prio = xive_lock_and_mask(xive, sb, state);
+
+       /* Transfer P and Q */
+       state->saved_p = state->old_p;
+       state->saved_q = state->old_q;
+
+       /* Unlock */
+       arch_spin_unlock(&sb->lock);
+}
+
+static void xive_pre_save_unmask_irq(struct kvmppc_xive *xive,
+                                    struct kvmppc_xive_src_block *sb,
+                                    u32 irq)
+{
+       struct kvmppc_xive_irq_state *state = &sb->irq_state[irq];
+
+       if (!state->valid)
+               return;
+
+       /*
+        * Lock / exclude EOI (not technically necessary if the
+        * guest isn't running concurrently. If this becomes a
+        * performance issue we can probably remove the lock.
+        */
+       xive_lock_for_unmask(sb, state);
+
+       /* Restore mask/prio if it wasn't masked */
+       if (state->saved_scan_prio != MASKED)
+               xive_finish_unmask(xive, sb, state, state->saved_scan_prio);
+
+       /* Unlock */
+       arch_spin_unlock(&sb->lock);
+}
+
+static void xive_pre_save_queue(struct kvmppc_xive *xive, struct xive_q *q)
+{
+       u32 idx = q->idx;
+       u32 toggle = q->toggle;
+       u32 irq;
+
+       do {
+               irq = __xive_read_eq(q->qpage, q->msk, &idx, &toggle);
+               if (irq > XICS_IPI)
+                       xive_pre_save_set_queued(xive, irq);
+       } while(irq);
+}
+
+static void xive_pre_save_scan(struct kvmppc_xive *xive)
+{
+       struct kvm_vcpu *vcpu = NULL;
+       int i, j;
+
+       /*
+        * See comment in xive_get_source() about how this
+        * work. Collect a stable state for all interrupts
+        */
+       for (i = 0; i <= xive->max_sbid; i++) {
+               struct kvmppc_xive_src_block *sb = xive->src_blocks[i];
+               if (!sb)
+                       continue;
+               for (j = 0;  j < KVMPPC_XICS_IRQ_PER_ICS; j++)
+                       xive_pre_save_mask_irq(xive, sb, j);
+       }
+
+       /* Then scan the queues and update the "in_queue" flag */
+       kvm_for_each_vcpu(i, vcpu, xive->kvm) {
+               struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
+               if (!xc)
+                       continue;
+               for (j = 0; j < KVMPPC_XIVE_Q_COUNT; j++) {
+                       if (xc->queues[i].qpage)
+                               xive_pre_save_queue(xive, &xc->queues[i]);
+               }
+       }
+
+       /* Finally restore interrupt states */
+       for (i = 0; i <= xive->max_sbid; i++) {
+               struct kvmppc_xive_src_block *sb = xive->src_blocks[i];
+               if (!sb)
+                       continue;
+               for (j = 0;  j < KVMPPC_XICS_IRQ_PER_ICS; j++)
+                       xive_pre_save_unmask_irq(xive, sb, j);
+       }
+}
+
+static void xive_post_save_scan(struct kvmppc_xive *xive)
+{
+       u32 i, j;
+
+       /* Clear all the in_queue flags */
+       for (i = 0; i <= xive->max_sbid; i++) {
+               struct kvmppc_xive_src_block *sb = xive->src_blocks[i];
+               if (!sb)
+                       continue;
+               for (j = 0;  j < KVMPPC_XICS_IRQ_PER_ICS; j++)
+                       sb->irq_state[j].in_queue = false;
+       }
+
+       /* Next get_source() will do a new scan */
+       xive->saved_src_count = 0;
+}
+
+/*
+ * This returns the source configuration and state to user space.
+ */
+static int xive_get_source(struct kvmppc_xive *xive, long irq, u64 addr)
+{
+       struct kvmppc_xive_src_block *sb;
+       struct kvmppc_xive_irq_state *state;
+       u64 __user *ubufp = (u64 __user *) addr;
+       u64 val, prio;
+       u16 idx;
+
+       sb = kvmppc_xive_find_source(xive, irq, &idx);
+       if (!sb)
+               return -ENOENT;
+
+       state = &sb->irq_state[idx];
+
+       if (!state->valid)
+               return -ENOENT;
+
+       pr_devel("get_source(%ld)...\n", irq);
+
+       /*
+        * So to properly save the state into something that looks like a
+        * XICS migration stream we cannot treat interrupts individually.
+        *
+        * We need, instead, mask them all (& save their previous PQ state)
+        * to get a stable state in the HW, then sync them to ensure that
+        * any interrupt that had already fired hits its queue, and finally
+        * scan all the queues to collect which interrupts are still present
+        * in the queues, so we can set the "pending" flag on them and
+        * they can be resent on restore.
+        *
+        * So we do it all when the "first" interrupt gets saved, all the
+        * state is collected at that point, the rest of xive_get_source()
+        * will merely collect and convert that state to the expected
+        * userspace bit mask.
+        */
+       if (xive->saved_src_count == 0)
+               xive_pre_save_scan(xive);
+       xive->saved_src_count++;
+
+       /* Convert saved state into something compatible with xics */
+       val = state->guest_server;
+       prio = state->saved_scan_prio;
+
+       if (prio == MASKED) {
+               val |= KVM_XICS_MASKED;
+               prio = state->saved_priority;
+       }
+       val |= prio << KVM_XICS_PRIORITY_SHIFT;
+       if (state->lsi) {
+               val |= KVM_XICS_LEVEL_SENSITIVE;
+               if (state->saved_p)
+                       val |= KVM_XICS_PENDING;
+       } else {
+               if (state->saved_p)
+                       val |= KVM_XICS_PRESENTED;
+
+               if (state->saved_q)
+                       val |= KVM_XICS_QUEUED;
+
+               /*
+                * We mark it pending (which will attempt a re-delivery)
+                * if we are in a queue *or* we were masked and had
+                * Q set which is equivalent to the XICS "masked pending"
+                * state
+                */
+               if (state->in_queue || (prio == MASKED && state->saved_q))
+                       val |= KVM_XICS_PENDING;
+       }
+
+       /*
+        * If that was the last interrupt saved, reset the
+        * in_queue flags
+        */
+       if (xive->saved_src_count == xive->src_count)
+               xive_post_save_scan(xive);
+
+       /* Copy the result to userspace */
+       if (put_user(val, ubufp))
+               return -EFAULT;
+
+       return 0;
+}
+
+static struct kvmppc_xive_src_block *xive_create_src_block(struct kvmppc_xive *xive,
+                                                          int irq)
+{
+       struct kvm *kvm = xive->kvm;
+       struct kvmppc_xive_src_block *sb;
+       int i, bid;
+
+       bid = irq >> KVMPPC_XICS_ICS_SHIFT;
+
+       mutex_lock(&kvm->lock);
+
+       /* block already exists - somebody else got here first */
+       if (xive->src_blocks[bid])
+               goto out;
+
+       /* Create the ICS */
+       sb = kzalloc(sizeof(*sb), GFP_KERNEL);
+       if (!sb)
+               goto out;
+
+       sb->id = bid;
+
+       for (i = 0; i < KVMPPC_XICS_IRQ_PER_ICS; i++) {
+               sb->irq_state[i].number = (bid << KVMPPC_XICS_ICS_SHIFT) | i;
+               sb->irq_state[i].guest_priority = MASKED;
+               sb->irq_state[i].saved_priority = MASKED;
+               sb->irq_state[i].act_priority = MASKED;
+       }
+       smp_wmb();
+       xive->src_blocks[bid] = sb;
+
+       if (bid > xive->max_sbid)
+               xive->max_sbid = bid;
+
+out:
+       mutex_unlock(&kvm->lock);
+       return xive->src_blocks[bid];
+}
+
+static bool xive_check_delayed_irq(struct kvmppc_xive *xive, u32 irq)
+{
+       struct kvm *kvm = xive->kvm;
+       struct kvm_vcpu *vcpu = NULL;
+       int i;
+
+       kvm_for_each_vcpu(i, vcpu, kvm) {
+               struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
+
+               if (!xc)
+                       continue;
+
+               if (xc->delayed_irq == irq) {
+                       xc->delayed_irq = 0;
+                       xive->delayed_irqs--;
+                       return true;
+               }
+       }
+       return false;
+}
+
+static int xive_set_source(struct kvmppc_xive *xive, long irq, u64 addr)
+{
+       struct kvmppc_xive_src_block *sb;
+       struct kvmppc_xive_irq_state *state;
+       u64 __user *ubufp = (u64 __user *) addr;
+       u16 idx;
+       u64 val;
+       u8 act_prio, guest_prio;
+       u32 server;
+       int rc = 0;
+
+       if (irq < KVMPPC_XICS_FIRST_IRQ || irq >= KVMPPC_XICS_NR_IRQS)
+               return -ENOENT;
+
+       pr_devel("set_source(irq=0x%lx)\n", irq);
+
+       /* Find the source */
+       sb = kvmppc_xive_find_source(xive, irq, &idx);
+       if (!sb) {
+               pr_devel("No source, creating source block...\n");
+               sb = xive_create_src_block(xive, irq);
+               if (!sb) {
+                       pr_devel("Failed to create block...\n");
+                       return -ENOMEM;
+               }
+       }
+       state = &sb->irq_state[idx];
+
+       /* Read user passed data */
+       if (get_user(val, ubufp)) {
+               pr_devel("fault getting user info !\n");
+               return -EFAULT;
+       }
+
+       server = val & KVM_XICS_DESTINATION_MASK;
+       guest_prio = val >> KVM_XICS_PRIORITY_SHIFT;
+
+       pr_devel("  val=0x016%llx (server=0x%x, guest_prio=%d)\n",
+                val, server, guest_prio);
+       /*
+        * If the source doesn't already have an IPI, allocate
+        * one and get the corresponding data
+        */
+       if (!state->ipi_number) {
+               state->ipi_number = xive_native_alloc_irq();
+               if (state->ipi_number == 0) {
+                       pr_devel("Failed to allocate IPI !\n");
+                       return -ENOMEM;
+               }
+               xive_native_populate_irq_data(state->ipi_number, &state->ipi_data);
+               pr_devel(" src_ipi=0x%x\n", state->ipi_number);
+       }
+
+       /*
+        * We use lock_and_mask() to set us in the right masked
+        * state. We will override that state from the saved state
+        * further down, but this will handle the cases of interrupts
+        * that need FW masking. We set the initial guest_priority to
+        * 0 before calling it to ensure it actually performs the masking.
+        */
+       state->guest_priority = 0;
+       xive_lock_and_mask(xive, sb, state);
+
+       /*
+        * Now, we select a target if we have one. If we don't we
+        * leave the interrupt untargetted. It means that an interrupt
+        * can become "untargetted" accross migration if it was masked
+        * by set_xive() but there is little we can do about it.
+        */
+
+       /* First convert prio and mark interrupt as untargetted */
+       act_prio = xive_prio_from_guest(guest_prio);
+       state->act_priority = MASKED;
+       state->guest_server = server;
+
+       /*
+        * We need to drop the lock due to the mutex below. Hopefully
+        * nothing is touching that interrupt yet since it hasn't been
+        * advertized to a running guest yet
+        */
+       arch_spin_unlock(&sb->lock);
+
+       /* If we have a priority target the interrupt */
+       if (act_prio != MASKED) {
+               /* First, check provisioning of queues */
+               mutex_lock(&xive->kvm->lock);
+               rc = xive_check_provisioning(xive->kvm, act_prio);
+               mutex_unlock(&xive->kvm->lock);
+
+               /* Target interrupt */
+               if (rc == 0)
+                       rc = xive_target_interrupt(xive->kvm, state,
+                                                  server, act_prio);
+               /*
+                * If provisioning or targetting failed, leave it
+                * alone and masked. It will remain disabled until
+                * the guest re-targets it.
+                */
+       }
+
+       /*
+        * Find out if this was a delayed irq stashed in an ICP,
+        * in which case, treat it as pending
+        */
+       if (xive->delayed_irqs && xive_check_delayed_irq(xive, irq)) {
+               val |= KVM_XICS_PENDING;
+               pr_devel("  Found delayed ! forcing PENDING !\n");
+       }
+
+       /* Cleanup the SW state */
+       state->old_p = false;
+       state->old_q = false;
+       state->lsi = false;
+       state->asserted = false;
+
+       /* Restore LSI state */
+       if (val & KVM_XICS_LEVEL_SENSITIVE) {
+               state->lsi = true;
+               if (val & KVM_XICS_PENDING)
+                       state->asserted = true;
+               pr_devel("  LSI ! Asserted=%d\n", state->asserted);
+       }
+
+       /*
+        * Restore P and Q. If the interrupt was pending, we
+        * force both P and Q, which will trigger a resend.
+        *
+        * That means that a guest that had both an interrupt
+        * pending (queued) and Q set will restore with only
+        * one instance of that interrupt instead of 2, but that
+        * is perfectly fine as coalescing interrupts that haven't
+        * been presented yet is always allowed.
+        */
+       if (val & KVM_XICS_PRESENTED || val & KVM_XICS_PENDING)
+               state->old_p = true;
+       if (val & KVM_XICS_QUEUED || val & KVM_XICS_PENDING)
+               state->old_q = true;
+
+       pr_devel("  P=%d, Q=%d\n", state->old_p, state->old_q);
+
+       /*
+        * If the interrupt was unmasked, update guest priority and
+        * perform the appropriate state transition and do a
+        * re-trigger if necessary.
+        */
+       if (val & KVM_XICS_MASKED) {
+               pr_devel("  masked, saving prio\n");
+               state->guest_priority = MASKED;
+               state->saved_priority = guest_prio;
+       } else {
+               pr_devel("  unmasked, restoring to prio %d\n", guest_prio);
+               xive_finish_unmask(xive, sb, state, guest_prio);
+               state->saved_priority = guest_prio;
+       }
+
+       /* Increment the number of valid sources and mark this one valid */
+       if (!state->valid)
+               xive->src_count++;
+       state->valid = true;
+
+       return 0;
+}
+
+int kvmppc_xive_set_irq(struct kvm *kvm, int irq_source_id, u32 irq, int level,
+                       bool line_status)
+{
+       struct kvmppc_xive *xive = kvm->arch.xive;
+       struct kvmppc_xive_src_block *sb;
+       struct kvmppc_xive_irq_state *state;
+       u16 idx;
+
+       if (!xive)
+               return -ENODEV;
+
+       sb = kvmppc_xive_find_source(xive, irq, &idx);
+       if (!sb)
+               return -EINVAL;
+
+       /* Perform locklessly .... (we need to do some RCUisms here...) */
+       state = &sb->irq_state[idx];
+       if (!state->valid)
+               return -EINVAL;
+
+       /* We don't allow a trigger on a passed-through interrupt */
+       if (state->pt_number)
+               return -EINVAL;
+
+       if ((level == 1 && state->lsi) || level == KVM_INTERRUPT_SET_LEVEL)
+               state->asserted = 1;
+       else if (level == 0 || level == KVM_INTERRUPT_UNSET) {
+               state->asserted = 0;
+               return 0;
+       }
+
+       /* Trigger the IPI */
+       xive_irq_trigger(&state->ipi_data);
+
+       return 0;
+}
+
+static int xive_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
+{
+       struct kvmppc_xive *xive = dev->private;
+
+       /* We honor the existing XICS ioctl */
+       switch (attr->group) {
+       case KVM_DEV_XICS_GRP_SOURCES:
+               return xive_set_source(xive, attr->attr, attr->addr);
+       }
+       return -ENXIO;
+}
+
+static int xive_get_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
+{
+       struct kvmppc_xive *xive = dev->private;
+
+       /* We honor the existing XICS ioctl */
+       switch (attr->group) {
+       case KVM_DEV_XICS_GRP_SOURCES:
+               return xive_get_source(xive, attr->attr, attr->addr);
+       }
+       return -ENXIO;
+}
+
+static int xive_has_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
+{
+       /* We honor the same limits as XICS, at least for now */
+       switch (attr->group) {
+       case KVM_DEV_XICS_GRP_SOURCES:
+               if (attr->attr >= KVMPPC_XICS_FIRST_IRQ &&
+                   attr->attr < KVMPPC_XICS_NR_IRQS)
+                       return 0;
+               break;
+       }
+       return -ENXIO;
+}
+
+static void kvmppc_xive_cleanup_irq(u32 hw_num, struct xive_irq_data *xd)
+{
+       xive_vm_esb_load(xd, XIVE_ESB_SET_PQ_01);
+       xive_native_configure_irq(hw_num, 0, MASKED, 0);
+       xive_cleanup_irq_data(xd);
+}
+
+static void kvmppc_xive_free_sources(struct kvmppc_xive_src_block *sb)
+{
+       int i;
+
+       for (i = 0; i < KVMPPC_XICS_IRQ_PER_ICS; i++) {
+               struct kvmppc_xive_irq_state *state = &sb->irq_state[i];
+
+               if (!state->valid)
+                       continue;
+
+               kvmppc_xive_cleanup_irq(state->ipi_number, &state->ipi_data);
+               xive_native_free_irq(state->ipi_number);
+
+               /* Pass-through, cleanup too */
+               if (state->pt_number)
+                       kvmppc_xive_cleanup_irq(state->pt_number, state->pt_data);
+
+               state->valid = false;
+       }
+}
+
+static void kvmppc_xive_free(struct kvm_device *dev)
+{
+       struct kvmppc_xive *xive = dev->private;
+       struct kvm *kvm = xive->kvm;
+       int i;
+
+       debugfs_remove(xive->dentry);
+
+       if (kvm)
+               kvm->arch.xive = NULL;
+
+       /* Mask and free interrupts */
+       for (i = 0; i <= xive->max_sbid; i++) {
+               if (xive->src_blocks[i])
+                       kvmppc_xive_free_sources(xive->src_blocks[i]);
+               kfree(xive->src_blocks[i]);
+               xive->src_blocks[i] = NULL;
+       }
+
+       if (xive->vp_base != XIVE_INVALID_VP)
+               xive_native_free_vp_block(xive->vp_base);
+
+
+       kfree(xive);
+       kfree(dev);
+}
+
+static int kvmppc_xive_create(struct kvm_device *dev, u32 type)
+{
+       struct kvmppc_xive *xive;
+       struct kvm *kvm = dev->kvm;
+       int ret = 0;
+
+       pr_devel("Creating xive for partition\n");
+
+       xive = kzalloc(sizeof(*xive), GFP_KERNEL);
+       if (!xive)
+               return -ENOMEM;
+
+       dev->private = xive;
+       xive->dev = dev;
+       xive->kvm = kvm;
+
+       /* Already there ? */
+       if (kvm->arch.xive)
+               ret = -EEXIST;
+       else
+               kvm->arch.xive = xive;
+
+       /* We use the default queue size set by the host */
+       xive->q_order = xive_native_default_eq_shift();
+       if (xive->q_order < PAGE_SHIFT)
+               xive->q_page_order = 0;
+       else
+               xive->q_page_order = xive->q_order - PAGE_SHIFT;
+
+       /* Allocate a bunch of VPs */
+       xive->vp_base = xive_native_alloc_vp_block(KVM_MAX_VCPUS);
+       pr_devel("VP_Base=%x\n", xive->vp_base);
+
+       if (xive->vp_base == XIVE_INVALID_VP)
+               ret = -ENOMEM;
+
+       if (ret) {
+               kfree(xive);
+               return ret;
+       }
+
+       return 0;
+}
+
+
+static int xive_debug_show(struct seq_file *m, void *private)
+{
+       struct kvmppc_xive *xive = m->private;
+       struct kvm *kvm = xive->kvm;
+       struct kvm_vcpu *vcpu;
+       u64 t_rm_h_xirr = 0;
+       u64 t_rm_h_ipoll = 0;
+       u64 t_rm_h_cppr = 0;
+       u64 t_rm_h_eoi = 0;
+       u64 t_rm_h_ipi = 0;
+       u64 t_vm_h_xirr = 0;
+       u64 t_vm_h_ipoll = 0;
+       u64 t_vm_h_cppr = 0;
+       u64 t_vm_h_eoi = 0;
+       u64 t_vm_h_ipi = 0;
+       unsigned int i;
+
+       if (!kvm)
+               return 0;
+
+       seq_printf(m, "=========\nVCPU state\n=========\n");
+
+       kvm_for_each_vcpu(i, vcpu, kvm) {
+               struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
+
+               if (!xc)
+                       continue;
+
+               seq_printf(m, "cpu server %#x CPPR:%#x HWCPPR:%#x"
+                          " MFRR:%#x PEND:%#x h_xirr: R=%lld V=%lld\n",
+                          xc->server_num, xc->cppr, xc->hw_cppr,
+                          xc->mfrr, xc->pending,
+                          xc->stat_rm_h_xirr, xc->stat_vm_h_xirr);
+
+               t_rm_h_xirr += xc->stat_rm_h_xirr;
+               t_rm_h_ipoll += xc->stat_rm_h_ipoll;
+               t_rm_h_cppr += xc->stat_rm_h_cppr;
+               t_rm_h_eoi += xc->stat_rm_h_eoi;
+               t_rm_h_ipi += xc->stat_rm_h_ipi;
+               t_vm_h_xirr += xc->stat_vm_h_xirr;
+               t_vm_h_ipoll += xc->stat_vm_h_ipoll;
+               t_vm_h_cppr += xc->stat_vm_h_cppr;
+               t_vm_h_eoi += xc->stat_vm_h_eoi;
+               t_vm_h_ipi += xc->stat_vm_h_ipi;
+       }
+
+       seq_printf(m, "Hcalls totals\n");
+       seq_printf(m, " H_XIRR  R=%10lld V=%10lld\n", t_rm_h_xirr, t_vm_h_xirr);
+       seq_printf(m, " H_IPOLL R=%10lld V=%10lld\n", t_rm_h_ipoll, t_vm_h_ipoll);
+       seq_printf(m, " H_CPPR  R=%10lld V=%10lld\n", t_rm_h_cppr, t_vm_h_cppr);
+       seq_printf(m, " H_EOI   R=%10lld V=%10lld\n", t_rm_h_eoi, t_vm_h_eoi);
+       seq_printf(m, " H_IPI   R=%10lld V=%10lld\n", t_rm_h_ipi, t_vm_h_ipi);
+
+       return 0;
+}
+
+static int xive_debug_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, xive_debug_show, inode->i_private);
+}
+
+static const struct file_operations xive_debug_fops = {
+       .open = xive_debug_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = single_release,
+};
+
+static void xive_debugfs_init(struct kvmppc_xive *xive)
+{
+       char *name;
+
+       name = kasprintf(GFP_KERNEL, "kvm-xive-%p", xive);
+       if (!name) {
+               pr_err("%s: no memory for name\n", __func__);
+               return;
+       }
+
+       xive->dentry = debugfs_create_file(name, S_IRUGO, powerpc_debugfs_root,
+                                          xive, &xive_debug_fops);
+
+       pr_debug("%s: created %s\n", __func__, name);
+       kfree(name);
+}
+
+static void kvmppc_xive_init(struct kvm_device *dev)
+{
+       struct kvmppc_xive *xive = (struct kvmppc_xive *)dev->private;
+
+       /* Register some debug interfaces */
+       xive_debugfs_init(xive);
+}
+
+struct kvm_device_ops kvm_xive_ops = {
+       .name = "kvm-xive",
+       .create = kvmppc_xive_create,
+       .init = kvmppc_xive_init,
+       .destroy = kvmppc_xive_free,
+       .set_attr = xive_set_attr,
+       .get_attr = xive_get_attr,
+       .has_attr = xive_has_attr,
+};
+
+void kvmppc_xive_init_module(void)
+{
+       __xive_vm_h_xirr = xive_vm_h_xirr;
+       __xive_vm_h_ipoll = xive_vm_h_ipoll;
+       __xive_vm_h_ipi = xive_vm_h_ipi;
+       __xive_vm_h_cppr = xive_vm_h_cppr;
+       __xive_vm_h_eoi = xive_vm_h_eoi;
+}
+
+void kvmppc_xive_exit_module(void)
+{
+       __xive_vm_h_xirr = NULL;
+       __xive_vm_h_ipoll = NULL;
+       __xive_vm_h_ipi = NULL;
+       __xive_vm_h_cppr = NULL;
+       __xive_vm_h_eoi = NULL;
+}
diff --git a/arch/powerpc/kvm/book3s_xive.h b/arch/powerpc/kvm/book3s_xive.h
new file mode 100644 (file)
index 0000000..5938f76
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ * Copyright 2017 Benjamin Herrenschmidt, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _KVM_PPC_BOOK3S_XIVE_H
+#define _KVM_PPC_BOOK3S_XIVE_H
+
+#ifdef CONFIG_KVM_XICS
+#include "book3s_xics.h"
+
+/*
+ * State for one guest irq source.
+ *
+ * For each guest source we allocate a HW interrupt in the XIVE
+ * which we use for all SW triggers. It will be unused for
+ * pass-through but it's easier to keep around as the same
+ * guest interrupt can alternatively be emulated or pass-through
+ * if a physical device is hot unplugged and replaced with an
+ * emulated one.
+ *
+ * This state structure is very similar to the XICS one with
+ * additional XIVE specific tracking.
+ */
+struct kvmppc_xive_irq_state {
+       bool valid;                     /* Interrupt entry is valid */
+
+       u32 number;                     /* Guest IRQ number */
+       u32 ipi_number;                 /* XIVE IPI HW number */
+       struct xive_irq_data ipi_data;  /* XIVE IPI associated data */
+       u32 pt_number;                  /* XIVE Pass-through number if any */
+       struct xive_irq_data *pt_data;  /* XIVE Pass-through associated data */
+
+       /* Targetting as set by guest */
+       u32 guest_server;               /* Current guest selected target */
+       u8 guest_priority;              /* Guest set priority */
+       u8 saved_priority;              /* Saved priority when masking */
+
+       /* Actual targetting */
+       u32 act_server;                 /* Actual server */
+       u8 act_priority;                /* Actual priority */
+
+       /* Various state bits */
+       bool in_eoi;                    /* Synchronize with H_EOI */
+       bool old_p;                     /* P bit state when masking */
+       bool old_q;                     /* Q bit state when masking */
+       bool lsi;                       /* level-sensitive interrupt */
+       bool asserted;                  /* Only for emulated LSI: current state */
+
+       /* Saved for migration state */
+       bool in_queue;
+       bool saved_p;
+       bool saved_q;
+       u8 saved_scan_prio;
+};
+
+/* Select the "right" interrupt (IPI vs. passthrough) */
+static inline void kvmppc_xive_select_irq(struct kvmppc_xive_irq_state *state,
+                                         u32 *out_hw_irq,
+                                         struct xive_irq_data **out_xd)
+{
+       if (state->pt_number) {
+               if (out_hw_irq)
+                       *out_hw_irq = state->pt_number;
+               if (out_xd)
+                       *out_xd = state->pt_data;
+       } else {
+               if (out_hw_irq)
+                       *out_hw_irq = state->ipi_number;
+               if (out_xd)
+                       *out_xd = &state->ipi_data;
+       }
+}
+
+/*
+ * This corresponds to an "ICS" in XICS terminology, we use it
+ * as a mean to break up source information into multiple structures.
+ */
+struct kvmppc_xive_src_block {
+       arch_spinlock_t lock;
+       u16 id;
+       struct kvmppc_xive_irq_state irq_state[KVMPPC_XICS_IRQ_PER_ICS];
+};
+
+
+struct kvmppc_xive {
+       struct kvm *kvm;
+       struct kvm_device *dev;
+       struct dentry *dentry;
+
+       /* VP block associated with the VM */
+       u32     vp_base;
+
+       /* Blocks of sources */
+       struct kvmppc_xive_src_block *src_blocks[KVMPPC_XICS_MAX_ICS_ID + 1];
+       u32     max_sbid;
+
+       /*
+        * For state save, we lazily scan the queues on the first interrupt
+        * being migrated. We don't have a clean way to reset that flags
+        * so we keep track of the number of valid sources and how many of
+        * them were migrated so we can reset when all of them have been
+        * processed.
+        */
+       u32     src_count;
+       u32     saved_src_count;
+
+       /*
+        * Some irqs are delayed on restore until the source is created,
+        * keep track here of how many of them
+        */
+       u32     delayed_irqs;
+
+       /* Which queues (priorities) are in use by the guest */
+       u8      qmap;
+
+       /* Queue orders */
+       u32     q_order;
+       u32     q_page_order;
+
+};
+
+#define KVMPPC_XIVE_Q_COUNT    8
+
+struct kvmppc_xive_vcpu {
+       struct kvmppc_xive      *xive;
+       struct kvm_vcpu         *vcpu;
+       bool                    valid;
+
+       /* Server number. This is the HW CPU ID from a guest perspective */
+       u32                     server_num;
+
+       /*
+        * HW VP corresponding to this VCPU. This is the base of the VP
+        * block plus the server number.
+        */
+       u32                     vp_id;
+       u32                     vp_chip_id;
+       u32                     vp_cam;
+
+       /* IPI used for sending ... IPIs */
+       u32                     vp_ipi;
+       struct xive_irq_data    vp_ipi_data;
+
+       /* Local emulation state */
+       uint8_t                 cppr;   /* guest CPPR */
+       uint8_t                 hw_cppr;/* Hardware CPPR */
+       uint8_t                 mfrr;
+       uint8_t                 pending;
+
+       /* Each VP has 8 queues though we only provision some */
+       struct xive_q           queues[KVMPPC_XIVE_Q_COUNT];
+       u32                     esc_virq[KVMPPC_XIVE_Q_COUNT];
+       char                    *esc_virq_names[KVMPPC_XIVE_Q_COUNT];
+
+       /* Stash a delayed irq on restore from migration (see set_icp) */
+       u32                     delayed_irq;
+
+       /* Stats */
+       u64                     stat_rm_h_xirr;
+       u64                     stat_rm_h_ipoll;
+       u64                     stat_rm_h_cppr;
+       u64                     stat_rm_h_eoi;
+       u64                     stat_rm_h_ipi;
+       u64                     stat_vm_h_xirr;
+       u64                     stat_vm_h_ipoll;
+       u64                     stat_vm_h_cppr;
+       u64                     stat_vm_h_eoi;
+       u64                     stat_vm_h_ipi;
+};
+
+static inline struct kvm_vcpu *kvmppc_xive_find_server(struct kvm *kvm, u32 nr)
+{
+       struct kvm_vcpu *vcpu = NULL;
+       int i;
+
+       kvm_for_each_vcpu(i, vcpu, kvm) {
+               if (vcpu->arch.xive_vcpu && nr == vcpu->arch.xive_vcpu->server_num)
+                       return vcpu;
+       }
+       return NULL;
+}
+
+static inline struct kvmppc_xive_src_block *kvmppc_xive_find_source(struct kvmppc_xive *xive,
+               u32 irq, u16 *source)
+{
+       u32 bid = irq >> KVMPPC_XICS_ICS_SHIFT;
+       u16 src = irq & KVMPPC_XICS_SRC_MASK;
+
+       if (source)
+               *source = src;
+       if (bid > KVMPPC_XICS_MAX_ICS_ID)
+               return NULL;
+       return xive->src_blocks[bid];
+}
+
+/*
+ * Mapping between guest priorities and host priorities
+ * is as follow.
+ *
+ * Guest request for 0...6 are honored. Guest request for anything
+ * higher results in a priority of 7 being applied.
+ *
+ * However, when XIRR is returned via H_XIRR, 7 is translated to 0xb
+ * in order to match AIX expectations
+ *
+ * Similar mapping is done for CPPR values
+ */
+static inline u8 xive_prio_from_guest(u8 prio)
+{
+       if (prio == 0xff || prio < 8)
+               return prio;
+       return 7;
+}
+
+static inline u8 xive_prio_to_guest(u8 prio)
+{
+       if (prio == 0xff || prio < 7)
+               return prio;
+       return 0xb;
+}
+
+static inline u32 __xive_read_eq(__be32 *qpage, u32 msk, u32 *idx, u32 *toggle)
+{
+       u32 cur;
+
+       if (!qpage)
+               return 0;
+       cur = be32_to_cpup(qpage + *idx);
+       if ((cur >> 31) == *toggle)
+               return 0;
+       *idx = (*idx + 1) & msk;
+       if (*idx == 0)
+               (*toggle) ^= 1;
+       return cur & 0x7fffffff;
+}
+
+extern unsigned long xive_rm_h_xirr(struct kvm_vcpu *vcpu);
+extern unsigned long xive_rm_h_ipoll(struct kvm_vcpu *vcpu, unsigned long server);
+extern int xive_rm_h_ipi(struct kvm_vcpu *vcpu, unsigned long server,
+                        unsigned long mfrr);
+extern int xive_rm_h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr);
+extern int xive_rm_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr);
+
+extern unsigned long (*__xive_vm_h_xirr)(struct kvm_vcpu *vcpu);
+extern unsigned long (*__xive_vm_h_ipoll)(struct kvm_vcpu *vcpu, unsigned long server);
+extern int (*__xive_vm_h_ipi)(struct kvm_vcpu *vcpu, unsigned long server,
+                             unsigned long mfrr);
+extern int (*__xive_vm_h_cppr)(struct kvm_vcpu *vcpu, unsigned long cppr);
+extern int (*__xive_vm_h_eoi)(struct kvm_vcpu *vcpu, unsigned long xirr);
+
+#endif /* CONFIG_KVM_XICS */
+#endif /* _KVM_PPC_BOOK3S_XICS_H */
diff --git a/arch/powerpc/kvm/book3s_xive_template.c b/arch/powerpc/kvm/book3s_xive_template.c
new file mode 100644 (file)
index 0000000..023a311
--- /dev/null
@@ -0,0 +1,503 @@
+/*
+ * Copyright 2017 Benjamin Herrenschmidt, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ */
+
+/* File to be included by other .c files */
+
+#define XGLUE(a,b) a##b
+#define GLUE(a,b) XGLUE(a,b)
+
+static void GLUE(X_PFX,ack_pending)(struct kvmppc_xive_vcpu *xc)
+{
+       u8 cppr;
+       u16 ack;
+
+       /* XXX DD1 bug workaround: Check PIPR vs. CPPR first ! */
+
+       /* Perform the acknowledge OS to register cycle. */
+       ack = be16_to_cpu(__x_readw(__x_tima + TM_SPC_ACK_OS_REG));
+
+       /* Synchronize subsequent queue accesses */
+       mb();
+
+       /* XXX Check grouping level */
+
+       /* Anything ? */
+       if (!((ack >> 8) & TM_QW1_NSR_EO))
+               return;
+
+       /* Grab CPPR of the most favored pending interrupt */
+       cppr = ack & 0xff;
+       if (cppr < 8)
+               xc->pending |= 1 << cppr;
+
+#ifdef XIVE_RUNTIME_CHECKS
+       /* Check consistency */
+       if (cppr >= xc->hw_cppr)
+               pr_warn("KVM-XIVE: CPU %d odd ack CPPR, got %d at %d\n",
+                       smp_processor_id(), cppr, xc->hw_cppr);
+#endif
+
+       /*
+        * Update our image of the HW CPPR. We don't yet modify
+        * xc->cppr, this will be done as we scan for interrupts
+        * in the queues.
+        */
+       xc->hw_cppr = cppr;
+}
+
+static u8 GLUE(X_PFX,esb_load)(struct xive_irq_data *xd, u32 offset)
+{
+       u64 val;
+
+       if (xd->flags & XIVE_IRQ_FLAG_SHIFT_BUG)
+               offset |= offset << 4;
+
+       val =__x_readq(__x_eoi_page(xd) + offset);
+#ifdef __LITTLE_ENDIAN__
+       val >>= 64-8;
+#endif
+       return (u8)val;
+}
+
+
+static void GLUE(X_PFX,source_eoi)(u32 hw_irq, struct xive_irq_data *xd)
+{
+       /* If the XIVE supports the new "store EOI facility, use it */
+       if (xd->flags & XIVE_IRQ_FLAG_STORE_EOI)
+               __x_writeq(0, __x_eoi_page(xd));
+       else if (hw_irq && xd->flags & XIVE_IRQ_FLAG_EOI_FW) {
+               opal_int_eoi(hw_irq);
+       } else {
+               uint64_t eoi_val;
+
+               /*
+                * Otherwise for EOI, we use the special MMIO that does
+                * a clear of both P and Q and returns the old Q,
+                * except for LSIs where we use the "EOI cycle" special
+                * load.
+                *
+                * This allows us to then do a re-trigger if Q was set
+                * rather than synthetizing an interrupt in software
+                *
+                * For LSIs, using the HW EOI cycle works around a problem
+                * on P9 DD1 PHBs where the other ESB accesses don't work
+                * properly.
+                */
+               if (xd->flags & XIVE_IRQ_FLAG_LSI)
+                       __x_readq(__x_eoi_page(xd));
+               else {
+                       eoi_val = GLUE(X_PFX,esb_load)(xd, XIVE_ESB_SET_PQ_00);
+
+                       /* Re-trigger if needed */
+                       if ((eoi_val & 1) && __x_trig_page(xd))
+                               __x_writeq(0, __x_trig_page(xd));
+               }
+       }
+}
+
+enum {
+       scan_fetch,
+       scan_poll,
+       scan_eoi,
+};
+
+static u32 GLUE(X_PFX,scan_interrupts)(struct kvmppc_xive_vcpu *xc,
+                                      u8 pending, int scan_type)
+{
+       u32 hirq = 0;
+       u8 prio = 0xff;
+
+       /* Find highest pending priority */
+       while ((xc->mfrr != 0xff || pending != 0) && hirq == 0) {
+               struct xive_q *q;
+               u32 idx, toggle;
+               __be32 *qpage;
+
+               /*
+                * If pending is 0 this will return 0xff which is what
+                * we want
+                */
+               prio = ffs(pending) - 1;
+
+               /*
+                * If the most favoured prio we found pending is less
+                * favored (or equal) than a pending IPI, we return
+                * the IPI instead.
+                *
+                * Note: If pending was 0 and mfrr is 0xff, we will
+                * not spurriously take an IPI because mfrr cannot
+                * then be smaller than cppr.
+                */
+               if (prio >= xc->mfrr && xc->mfrr < xc->cppr) {
+                       prio = xc->mfrr;
+                       hirq = XICS_IPI;
+                       break;
+               }
+
+               /* Don't scan past the guest cppr */
+               if (prio >= xc->cppr || prio > 7)
+                       break;
+
+               /* Grab queue and pointers */
+               q = &xc->queues[prio];
+               idx = q->idx;
+               toggle = q->toggle;
+
+               /*
+                * Snapshot the queue page. The test further down for EOI
+                * must use the same "copy" that was used by __xive_read_eq
+                * since qpage can be set concurrently and we don't want
+                * to miss an EOI.
+                */
+               qpage = READ_ONCE(q->qpage);
+
+skip_ipi:
+               /*
+                * Try to fetch from the queue. Will return 0 for a
+                * non-queueing priority (ie, qpage = 0).
+                */
+               hirq = __xive_read_eq(qpage, q->msk, &idx, &toggle);
+
+               /*
+                * If this was a signal for an MFFR change done by
+                * H_IPI we skip it. Additionally, if we were fetching
+                * we EOI it now, thus re-enabling reception of a new
+                * such signal.
+                *
+                * We also need to do that if prio is 0 and we had no
+                * page for the queue. In this case, we have non-queued
+                * IPI that needs to be EOId.
+                *
+                * This is safe because if we have another pending MFRR
+                * change that wasn't observed above, the Q bit will have
+                * been set and another occurrence of the IPI will trigger.
+                */
+               if (hirq == XICS_IPI || (prio == 0 && !qpage)) {
+                       if (scan_type == scan_fetch)
+                               GLUE(X_PFX,source_eoi)(xc->vp_ipi,
+                                                      &xc->vp_ipi_data);
+                       /* Loop back on same queue with updated idx/toggle */
+#ifdef XIVE_RUNTIME_CHECKS
+                       WARN_ON(hirq && hirq != XICS_IPI);
+#endif
+                       if (hirq)
+                               goto skip_ipi;
+               }
+
+               /* If fetching, update queue pointers */
+               if (scan_type == scan_fetch) {
+                       q->idx = idx;
+                       q->toggle = toggle;
+               }
+
+               /* Something found, stop searching */
+               if (hirq)
+                       break;
+
+               /* Clear the pending bit on the now empty queue */
+               pending &= ~(1 << prio);
+
+               /*
+                * Check if the queue count needs adjusting due to
+                * interrupts being moved away.
+                */
+               if (atomic_read(&q->pending_count)) {
+                       int p = atomic_xchg(&q->pending_count, 0);
+                       if (p) {
+#ifdef XIVE_RUNTIME_CHECKS
+                               WARN_ON(p > atomic_read(&q->count));
+#endif
+                               atomic_sub(p, &q->count);
+                       }
+               }
+       }
+
+       /* If we are just taking a "peek", do nothing else */
+       if (scan_type == scan_poll)
+               return hirq;
+
+       /* Update the pending bits */
+       xc->pending = pending;
+
+       /*
+        * If this is an EOI that's it, no CPPR adjustment done here,
+        * all we needed was cleanup the stale pending bits and check
+        * if there's anything left.
+        */
+       if (scan_type == scan_eoi)
+               return hirq;
+
+       /*
+        * If we found an interrupt, adjust what the guest CPPR should
+        * be as if we had just fetched that interrupt from HW.
+        */
+       if (hirq)
+               xc->cppr = prio;
+       /*
+        * If it was an IPI the HW CPPR might have been lowered too much
+        * as the HW interrupt we use for IPIs is routed to priority 0.
+        *
+        * We re-sync it here.
+        */
+       if (xc->cppr != xc->hw_cppr) {
+               xc->hw_cppr = xc->cppr;
+               __x_writeb(xc->cppr, __x_tima + TM_QW1_OS + TM_CPPR);
+       }
+
+       return hirq;
+}
+
+X_STATIC unsigned long GLUE(X_PFX,h_xirr)(struct kvm_vcpu *vcpu)
+{
+       struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
+       u8 old_cppr;
+       u32 hirq;
+
+       pr_devel("H_XIRR\n");
+
+       xc->GLUE(X_STAT_PFX,h_xirr)++;
+
+       /* First collect pending bits from HW */
+       GLUE(X_PFX,ack_pending)(xc);
+
+       /*
+        * Cleanup the old-style bits if needed (they may have been
+        * set by pull or an escalation interrupts).
+        */
+       if (test_bit(BOOK3S_IRQPRIO_EXTERNAL, &vcpu->arch.pending_exceptions))
+               clear_bit(BOOK3S_IRQPRIO_EXTERNAL_LEVEL,
+                         &vcpu->arch.pending_exceptions);
+
+       pr_devel(" new pending=0x%02x hw_cppr=%d cppr=%d\n",
+                xc->pending, xc->hw_cppr, xc->cppr);
+
+       /* Grab previous CPPR and reverse map it */
+       old_cppr = xive_prio_to_guest(xc->cppr);
+
+       /* Scan for actual interrupts */
+       hirq = GLUE(X_PFX,scan_interrupts)(xc, xc->pending, scan_fetch);
+
+       pr_devel(" got hirq=0x%x hw_cppr=%d cppr=%d\n",
+                hirq, xc->hw_cppr, xc->cppr);
+
+#ifdef XIVE_RUNTIME_CHECKS
+       /* That should never hit */
+       if (hirq & 0xff000000)
+               pr_warn("XIVE: Weird guest interrupt number 0x%08x\n", hirq);
+#endif
+
+       /*
+        * XXX We could check if the interrupt is masked here and
+        * filter it. If we chose to do so, we would need to do:
+        *
+        *    if (masked) {
+        *        lock();
+        *        if (masked) {
+        *            old_Q = true;
+        *            hirq = 0;
+        *        }
+        *        unlock();
+        *    }
+        */
+
+       /* Return interrupt and old CPPR in GPR4 */
+       vcpu->arch.gpr[4] = hirq | (old_cppr << 24);
+
+       return H_SUCCESS;
+}
+
+X_STATIC unsigned long GLUE(X_PFX,h_ipoll)(struct kvm_vcpu *vcpu, unsigned long server)
+{
+       struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
+       u8 pending = xc->pending;
+       u32 hirq;
+       u8 pipr;
+
+       pr_devel("H_IPOLL(server=%ld)\n", server);
+
+       xc->GLUE(X_STAT_PFX,h_ipoll)++;
+
+       /* Grab the target VCPU if not the current one */
+       if (xc->server_num != server) {
+               vcpu = kvmppc_xive_find_server(vcpu->kvm, server);
+               if (!vcpu)
+                       return H_PARAMETER;
+               xc = vcpu->arch.xive_vcpu;
+
+               /* Scan all priorities */
+               pending = 0xff;
+       } else {
+               /* Grab pending interrupt if any */
+               pipr = __x_readb(__x_tima + TM_QW1_OS + TM_PIPR);
+               if (pipr < 8)
+                       pending |= 1 << pipr;
+       }
+
+       hirq = GLUE(X_PFX,scan_interrupts)(xc, pending, scan_poll);
+
+       /* Return interrupt and old CPPR in GPR4 */
+       vcpu->arch.gpr[4] = hirq | (xc->cppr << 24);
+
+       return H_SUCCESS;
+}
+
+static void GLUE(X_PFX,push_pending_to_hw)(struct kvmppc_xive_vcpu *xc)
+{
+       u8 pending, prio;
+
+       pending = xc->pending;
+       if (xc->mfrr != 0xff) {
+               if (xc->mfrr < 8)
+                       pending |= 1 << xc->mfrr;
+               else
+                       pending |= 0x80;
+       }
+       if (!pending)
+               return;
+       prio = ffs(pending) - 1;
+
+       __x_writeb(prio, __x_tima + TM_SPC_SET_OS_PENDING);
+}
+
+X_STATIC int GLUE(X_PFX,h_cppr)(struct kvm_vcpu *vcpu, unsigned long cppr)
+{
+       struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
+       u8 old_cppr;
+
+       pr_devel("H_CPPR(cppr=%ld)\n", cppr);
+
+       xc->GLUE(X_STAT_PFX,h_cppr)++;
+
+       /* Map CPPR */
+       cppr = xive_prio_from_guest(cppr);
+
+       /* Remember old and update SW state */
+       old_cppr = xc->cppr;
+       xc->cppr = cppr;
+
+       /*
+        * We are masking less, we need to look for pending things
+        * to deliver and set VP pending bits accordingly to trigger
+        * a new interrupt otherwise we might miss MFRR changes for
+        * which we have optimized out sending an IPI signal.
+        */
+       if (cppr > old_cppr)
+               GLUE(X_PFX,push_pending_to_hw)(xc);
+
+       /* Apply new CPPR */
+       xc->hw_cppr = cppr;
+       __x_writeb(cppr, __x_tima + TM_QW1_OS + TM_CPPR);
+
+       return H_SUCCESS;
+}
+
+X_STATIC int GLUE(X_PFX,h_eoi)(struct kvm_vcpu *vcpu, unsigned long xirr)
+{
+       struct kvmppc_xive *xive = vcpu->kvm->arch.xive;
+       struct kvmppc_xive_src_block *sb;
+       struct kvmppc_xive_irq_state *state;
+       struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
+       struct xive_irq_data *xd;
+       u8 new_cppr = xirr >> 24;
+       u32 irq = xirr & 0x00ffffff, hw_num;
+       u16 src;
+       int rc = 0;
+
+       pr_devel("H_EOI(xirr=%08lx)\n", xirr);
+
+       xc->GLUE(X_STAT_PFX,h_eoi)++;
+
+       xc->cppr = xive_prio_from_guest(new_cppr);
+
+       /*
+        * IPIs are synthetized from MFRR and thus don't need
+        * any special EOI handling. The underlying interrupt
+        * used to signal MFRR changes is EOId when fetched from
+        * the queue.
+        */
+       if (irq == XICS_IPI || irq == 0)
+               goto bail;
+
+       /* Find interrupt source */
+       sb = kvmppc_xive_find_source(xive, irq, &src);
+       if (!sb) {
+               pr_devel(" source not found !\n");
+               rc = H_PARAMETER;
+               goto bail;
+       }
+       state = &sb->irq_state[src];
+       kvmppc_xive_select_irq(state, &hw_num, &xd);
+
+       state->in_eoi = true;
+       mb();
+
+again:
+       if (state->guest_priority == MASKED) {
+               arch_spin_lock(&sb->lock);
+               if (state->guest_priority != MASKED) {
+                       arch_spin_unlock(&sb->lock);
+                       goto again;
+               }
+               pr_devel(" EOI on saved P...\n");
+
+               /* Clear old_p, that will cause unmask to perform an EOI */
+               state->old_p = false;
+
+               arch_spin_unlock(&sb->lock);
+       } else {
+               pr_devel(" EOI on source...\n");
+
+               /* Perform EOI on the source */
+               GLUE(X_PFX,source_eoi)(hw_num, xd);
+
+               /* If it's an emulated LSI, check level and resend */
+               if (state->lsi && state->asserted)
+                       __x_writeq(0, __x_trig_page(xd));
+
+       }
+
+       mb();
+       state->in_eoi = false;
+bail:
+
+       /* Re-evaluate pending IRQs and update HW */
+       GLUE(X_PFX,scan_interrupts)(xc, xc->pending, scan_eoi);
+       GLUE(X_PFX,push_pending_to_hw)(xc);
+       pr_devel(" after scan pending=%02x\n", xc->pending);
+
+       /* Apply new CPPR */
+       xc->hw_cppr = xc->cppr;
+       __x_writeb(xc->cppr, __x_tima + TM_QW1_OS + TM_CPPR);
+
+       return rc;
+}
+
+X_STATIC int GLUE(X_PFX,h_ipi)(struct kvm_vcpu *vcpu, unsigned long server,
+                              unsigned long mfrr)
+{
+       struct kvmppc_xive_vcpu *xc = vcpu->arch.xive_vcpu;
+
+       pr_devel("H_IPI(server=%08lx,mfrr=%ld)\n", server, mfrr);
+
+       xc->GLUE(X_STAT_PFX,h_ipi)++;
+
+       /* Find target */
+       vcpu = kvmppc_xive_find_server(vcpu->kvm, server);
+       if (!vcpu)
+               return H_PARAMETER;
+       xc = vcpu->arch.xive_vcpu;
+
+       /* Locklessly write over MFRR */
+       xc->mfrr = mfrr;
+
+       /* Shoot the IPI if most favored than target cppr */
+       if (mfrr < xc->cppr)
+               __x_writeq(0, __x_trig_page(&xc->vp_ipi_data));
+
+       return H_SUCCESS;
+}
index 5a9a10b90762ad2018155e0eace9e70600b5e0e0..3f1be85a83bcf94424d7957c651f217c4ef47433 100644 (file)
@@ -12,6 +12,7 @@ static inline int irqchip_in_kernel(struct kvm *kvm)
 #endif
 #ifdef CONFIG_KVM_XICS
        ret = ret || (kvm->arch.xics != NULL);
+       ret = ret || (kvm->arch.xive != NULL);
 #endif
        smp_rmb();
        return ret;
index 1ee22a9100748f5cfbc276ea132a46279f8f8799..7f71ab5fcad1bbc20abaa43627c1220c3ff4e17b 100644 (file)
@@ -38,6 +38,8 @@
 #include <asm/irqflags.h>
 #include <asm/iommu.h>
 #include <asm/switch_to.h>
+#include <asm/xive.h>
+
 #include "timing.h"
 #include "irq.h"
 #include "../mm/mmu_decl.h"
@@ -697,7 +699,10 @@ void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
                kvmppc_mpic_disconnect_vcpu(vcpu->arch.mpic, vcpu);
                break;
        case KVMPPC_IRQ_XICS:
-               kvmppc_xics_free_icp(vcpu);
+               if (xive_enabled())
+                       kvmppc_xive_cleanup_vcpu(vcpu);
+               else
+                       kvmppc_xics_free_icp(vcpu);
                break;
        }
 
@@ -1522,8 +1527,12 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
 
                r = -EPERM;
                dev = kvm_device_from_filp(f.file);
-               if (dev)
-                       r = kvmppc_xics_connect_vcpu(dev, vcpu, cap->args[1]);
+               if (dev) {
+                       if (xive_enabled())
+                               r = kvmppc_xive_connect_vcpu(dev, vcpu, cap->args[1]);
+                       else
+                               r = kvmppc_xics_connect_vcpu(dev, vcpu, cap->args[1]);
+               }
 
                fdput(f);
                break;
@@ -1547,7 +1556,7 @@ bool kvm_arch_intc_initialized(struct kvm *kvm)
                return true;
 #endif
 #ifdef CONFIG_KVM_XICS
-       if (kvm->arch.xics)
+       if (kvm->arch.xics || kvm->arch.xive)
                return true;
 #endif
        return false;
@@ -1740,7 +1749,7 @@ long kvm_arch_vm_ioctl(struct file *filp,
                r = kvm_vm_ioctl_enable_cap(kvm, &cap);
                break;
        }
-#ifdef CONFIG_PPC_BOOK3S_64
+#ifdef CONFIG_SPAPR_TCE_IOMMU
        case KVM_CREATE_SPAPR_TCE_64: {
                struct kvm_create_spapr_tce_64 create_tce_64;
 
@@ -1771,6 +1780,8 @@ long kvm_arch_vm_ioctl(struct file *filp,
                r = kvm_vm_ioctl_create_spapr_tce(kvm, &create_tce_64);
                goto out;
        }
+#endif
+#ifdef CONFIG_PPC_BOOK3S_64
        case KVM_PPC_GET_SMMU_INFO: {
                struct kvm_ppc_smmu_info info;
                struct kvm *kvm = filp->private_data;
index d659345a98d66c03a2cab1ceed3526af95551cc6..44fe4833910f64bcd014a2e3843ecd8c3077fc26 100644 (file)
@@ -16,6 +16,7 @@
  */
 #include <linux/debugfs.h>
 #include <linux/fs.h>
+#include <linux/hugetlb.h>
 #include <linux/io.h>
 #include <linux/mm.h>
 #include <linux/sched.h>
@@ -391,7 +392,7 @@ static void walk_pmd(struct pg_state *st, pud_t *pud, unsigned long start)
 
        for (i = 0; i < PTRS_PER_PMD; i++, pmd++) {
                addr = start + i * PMD_SIZE;
-               if (!pmd_none(*pmd))
+               if (!pmd_none(*pmd) && !pmd_huge(*pmd))
                        /* pmd exists */
                        walk_pte(st, pmd, addr);
                else
@@ -407,7 +408,7 @@ static void walk_pud(struct pg_state *st, pgd_t *pgd, unsigned long start)
 
        for (i = 0; i < PTRS_PER_PUD; i++, pud++) {
                addr = start + i * PUD_SIZE;
-               if (!pud_none(*pud))
+               if (!pud_none(*pud) && !pud_huge(*pud))
                        /* pud exists */
                        walk_pmd(st, pud, addr);
                else
@@ -427,7 +428,7 @@ static void walk_pagetables(struct pg_state *st)
         */
        for (i = 0; i < PTRS_PER_PGD; i++, pgd++) {
                addr = KERN_VIRT_START + i * PGDIR_SIZE;
-               if (!pgd_none(*pgd))
+               if (!pgd_none(*pgd) && !pgd_huge(*pgd))
                        /* pgd exists */
                        walk_pud(st, pgd, addr);
                else
index 915412e4d5ba58d3b898afe502d89273b6945aad..1fa794d7d59f2d693fca0732b15b727e831bbcad 100644 (file)
@@ -186,7 +186,7 @@ static u32 acop_get_inst(struct pt_regs *regs)
 }
 
 /**
- * @regs: regsiters at time of interrupt
+ * @regs: registers at time of interrupt
  * @address: storage address
  * @error_code: Fault code, usually the DSISR or ESR depending on
  *             processor type
index d2f19821d71dbae2d749d0baaed56d4d9d570570..d12ea7b9fd47ba20dcc963b33a506ce0cff8a626 100644 (file)
@@ -412,11 +412,14 @@ static void *pnv_eeh_probe(struct pci_dn *pdn, void *data)
         * been set for the PE, we will set EEH_PE_CFG_BLOCKED for
         * that PE to block its config space.
         *
+        * Broadcom BCM5718 2-ports NICs (14e4:1656)
         * Broadcom Austin 4-ports NICs (14e4:1657)
         * Broadcom Shiner 4-ports 1G NICs (14e4:168a)
         * Broadcom Shiner 2-ports 10G NICs (14e4:168e)
         */
        if ((pdn->vendor_id == PCI_VENDOR_ID_BROADCOM &&
+            pdn->device_id == 0x1656) ||
+           (pdn->vendor_id == PCI_VENDOR_ID_BROADCOM &&
             pdn->device_id == 0x1657) ||
            (pdn->vendor_id == PCI_VENDOR_ID_BROADCOM &&
             pdn->device_id == 0x168a) ||
index 7925a9d72ccadec495b765ad08ffdf5d791e0e2b..59684b4af4d1dfba4990ae73f63d03f77fc61f38 100644 (file)
@@ -967,3 +967,4 @@ EXPORT_SYMBOL_GPL(opal_leds_set_ind);
 EXPORT_SYMBOL_GPL(opal_write_oppanel_async);
 /* Export this for KVM */
 EXPORT_SYMBOL_GPL(opal_int_set_mfrr);
+EXPORT_SYMBOL_GPL(opal_int_eoi);
index 6fdbd383f67665b09c79675c95d98682d9340007..283caf1070c95ee7c60d354e18cce8178440bc95 100644 (file)
@@ -3330,6 +3330,11 @@ static void pnv_pci_setup_bridge(struct pci_bus *bus, unsigned long type)
        }
 }
 
+static resource_size_t pnv_pci_default_alignment(void)
+{
+       return PAGE_SIZE;
+}
+
 #ifdef CONFIG_PCI_IOV
 static resource_size_t pnv_pci_iov_resource_alignment(struct pci_dev *pdev,
                                                      int resno)
@@ -3863,6 +3868,8 @@ static void __init pnv_pci_init_ioda_phb(struct device_node *np,
                hose->controller_ops = pnv_pci_ioda_controller_ops;
        }
 
+       ppc_md.pcibios_default_alignment = pnv_pci_default_alignment;
+
 #ifdef CONFIG_PCI_IOV
        ppc_md.pcibios_fixup_sriov = pnv_pci_ioda_fixup_iov_resources;
        ppc_md.pcibios_iov_resource_alignment = pnv_pci_iov_resource_alignment;
index 986cd111d4df1064161238a6b2fabad474fa5260..c651e668996bc4d7c2592f8f9602c81147d1f3b6 100644 (file)
@@ -377,6 +377,10 @@ static void cpm1_set_pin16(int port, int pin, int flags)
                        setbits16(&iop->odr_sor, pin);
                else
                        clrbits16(&iop->odr_sor, pin);
+               if (flags & CPM_PIN_FALLEDGE)
+                       setbits16(&iop->intr, pin);
+               else
+                       clrbits16(&iop->intr, pin);
        }
 }
 
@@ -528,6 +532,9 @@ struct cpm1_gpio16_chip {
 
        /* shadowed data register to clear/set bits safely */
        u16 cpdata;
+
+       /* IRQ associated with Pins when relevant */
+       int irq[16];
 };
 
 static void cpm1_gpio16_save_regs(struct of_mm_gpio_chip *mm_gc)
@@ -578,6 +585,14 @@ static void cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value)
        spin_unlock_irqrestore(&cpm1_gc->lock, flags);
 }
 
+static int cpm1_gpio16_to_irq(struct gpio_chip *gc, unsigned int gpio)
+{
+       struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
+       struct cpm1_gpio16_chip *cpm1_gc = gpiochip_get_data(&mm_gc->gc);
+
+       return cpm1_gc->irq[gpio] ? : -ENXIO;
+}
+
 static int cpm1_gpio16_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
 {
        struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc);
@@ -618,6 +633,7 @@ int cpm1_gpiochip_add16(struct device_node *np)
        struct cpm1_gpio16_chip *cpm1_gc;
        struct of_mm_gpio_chip *mm_gc;
        struct gpio_chip *gc;
+       u16 mask;
 
        cpm1_gc = kzalloc(sizeof(*cpm1_gc), GFP_KERNEL);
        if (!cpm1_gc)
@@ -625,6 +641,14 @@ int cpm1_gpiochip_add16(struct device_node *np)
 
        spin_lock_init(&cpm1_gc->lock);
 
+       if (!of_property_read_u16(np, "fsl,cpm1-gpio-irq-mask", &mask)) {
+               int i, j;
+
+               for (i = 0, j = 0; i < 16; i++)
+                       if (mask & (1 << (15 - i)))
+                               cpm1_gc->irq[i] = irq_of_parse_and_map(np, j++);
+       }
+
        mm_gc = &cpm1_gc->mm_gc;
        gc = &mm_gc->gc;
 
@@ -634,6 +658,7 @@ int cpm1_gpiochip_add16(struct device_node *np)
        gc->direction_output = cpm1_gpio16_dir_out;
        gc->get = cpm1_gpio16_get;
        gc->set = cpm1_gpio16_set;
+       gc->to_irq = cpm1_gpio16_to_irq;
 
        return of_mm_gpiochip_add_data(np, mm_gc, cpm1_gc);
 }
index 6a98efb142649a577bb3b8abc32f5aa68c98bef4..913825086b8df675f68f69a0b993934c3b607104 100644 (file)
 #endif
 
 bool __xive_enabled;
+EXPORT_SYMBOL_GPL(__xive_enabled);
 bool xive_cmdline_disabled;
 
 /* We use only one priority for now */
 static u8 xive_irq_priority;
 
-/* TIMA */
+/* TIMA exported to KVM */
 void __iomem *xive_tima;
+EXPORT_SYMBOL_GPL(xive_tima);
 u32 xive_tima_offset;
 
 /* Backend ops */
@@ -345,8 +347,11 @@ static void xive_irq_eoi(struct irq_data *d)
        DBG_VERBOSE("eoi_irq: irq=%d [0x%lx] pending=%02x\n",
                    d->irq, irqd_to_hwirq(d), xc->pending_prio);
 
-       /* EOI the source if it hasn't been disabled */
-       if (!irqd_irq_disabled(d))
+       /*
+        * EOI the source if it hasn't been disabled and hasn't
+        * been passed-through to a KVM guest
+        */
+       if (!irqd_irq_disabled(d) && !irqd_is_forwarded_to_vcpu(d))
                xive_do_source_eoi(irqd_to_hwirq(d), xd);
 
        /*
@@ -689,9 +694,14 @@ static int xive_irq_set_affinity(struct irq_data *d,
 
        old_target = xd->target;
 
-       rc = xive_ops->configure_irq(hw_irq,
-                                    get_hard_smp_processor_id(target),
-                                    xive_irq_priority, d->irq);
+       /*
+        * Only configure the irq if it's not currently passed-through to
+        * a KVM guest
+        */
+       if (!irqd_is_forwarded_to_vcpu(d))
+               rc = xive_ops->configure_irq(hw_irq,
+                                            get_hard_smp_processor_id(target),
+                                            xive_irq_priority, d->irq);
        if (rc < 0) {
                pr_err("Error %d reconfiguring irq %d\n", rc, d->irq);
                return rc;
@@ -771,6 +781,123 @@ static int xive_irq_retrigger(struct irq_data *d)
        return 1;
 }
 
+static int xive_irq_set_vcpu_affinity(struct irq_data *d, void *state)
+{
+       struct xive_irq_data *xd = irq_data_get_irq_handler_data(d);
+       unsigned int hw_irq = (unsigned int)irqd_to_hwirq(d);
+       int rc;
+       u8 pq;
+
+       /*
+        * We only support this on interrupts that do not require
+        * firmware calls for masking and unmasking
+        */
+       if (xd->flags & XIVE_IRQ_FLAG_MASK_FW)
+               return -EIO;
+
+       /*
+        * This is called by KVM with state non-NULL for enabling
+        * pass-through or NULL for disabling it
+        */
+       if (state) {
+               irqd_set_forwarded_to_vcpu(d);
+
+               /* Set it to PQ=10 state to prevent further sends */
+               pq = xive_poke_esb(xd, XIVE_ESB_SET_PQ_10);
+
+               /* No target ? nothing to do */
+               if (xd->target == XIVE_INVALID_TARGET) {
+                       /*
+                        * An untargetted interrupt should have been
+                        * also masked at the source
+                        */
+                       WARN_ON(pq & 2);
+
+                       return 0;
+               }
+
+               /*
+                * If P was set, adjust state to PQ=11 to indicate
+                * that a resend is needed for the interrupt to reach
+                * the guest. Also remember the value of P.
+                *
+                * This also tells us that it's in flight to a host queue
+                * or has already been fetched but hasn't been EOIed yet
+                * by the host. This it's potentially using up a host
+                * queue slot. This is important to know because as long
+                * as this is the case, we must not hard-unmask it when
+                * "returning" that interrupt to the host.
+                *
+                * This saved_p is cleared by the host EOI, when we know
+                * for sure the queue slot is no longer in use.
+                */
+               if (pq & 2) {
+                       pq = xive_poke_esb(xd, XIVE_ESB_SET_PQ_11);
+                       xd->saved_p = true;
+
+                       /*
+                        * Sync the XIVE source HW to ensure the interrupt
+                        * has gone through the EAS before we change its
+                        * target to the guest. That should guarantee us
+                        * that we *will* eventually get an EOI for it on
+                        * the host. Otherwise there would be a small window
+                        * for P to be seen here but the interrupt going
+                        * to the guest queue.
+                        */
+                       if (xive_ops->sync_source)
+                               xive_ops->sync_source(hw_irq);
+               } else
+                       xd->saved_p = false;
+       } else {
+               irqd_clr_forwarded_to_vcpu(d);
+
+               /* No host target ? hard mask and return */
+               if (xd->target == XIVE_INVALID_TARGET) {
+                       xive_do_source_set_mask(xd, true);
+                       return 0;
+               }
+
+               /*
+                * Sync the XIVE source HW to ensure the interrupt
+                * has gone through the EAS before we change its
+                * target to the host.
+                */
+               if (xive_ops->sync_source)
+                       xive_ops->sync_source(hw_irq);
+
+               /*
+                * By convention we are called with the interrupt in
+                * a PQ=10 or PQ=11 state, ie, it won't fire and will
+                * have latched in Q whether there's a pending HW
+                * interrupt or not.
+                *
+                * First reconfigure the target.
+                */
+               rc = xive_ops->configure_irq(hw_irq,
+                                            get_hard_smp_processor_id(xd->target),
+                                            xive_irq_priority, d->irq);
+               if (rc)
+                       return rc;
+
+               /*
+                * Then if saved_p is not set, effectively re-enable the
+                * interrupt with an EOI. If it is set, we know there is
+                * still a message in a host queue somewhere that will be
+                * EOId eventually.
+                *
+                * Note: We don't check irqd_irq_disabled(). Effectively,
+                * we *will* let the irq get through even if masked if the
+                * HW is still firing it in order to deal with the whole
+                * saved_p business properly. If the interrupt triggers
+                * while masked, the generic code will re-mask it anyway.
+                */
+               if (!xd->saved_p)
+                       xive_do_source_eoi(hw_irq, xd);
+
+       }
+       return 0;
+}
+
 static struct irq_chip xive_irq_chip = {
        .name = "XIVE-IRQ",
        .irq_startup = xive_irq_startup,
@@ -781,12 +908,14 @@ static struct irq_chip xive_irq_chip = {
        .irq_set_affinity = xive_irq_set_affinity,
        .irq_set_type = xive_irq_set_type,
        .irq_retrigger = xive_irq_retrigger,
+       .irq_set_vcpu_affinity = xive_irq_set_vcpu_affinity,
 };
 
 bool is_xive_irq(struct irq_chip *chip)
 {
        return chip == &xive_irq_chip;
 }
+EXPORT_SYMBOL_GPL(is_xive_irq);
 
 void xive_cleanup_irq_data(struct xive_irq_data *xd)
 {
@@ -801,6 +930,7 @@ void xive_cleanup_irq_data(struct xive_irq_data *xd)
                xd->trig_mmio = NULL;
        }
 }
+EXPORT_SYMBOL_GPL(xive_cleanup_irq_data);
 
 static int xive_irq_alloc_data(unsigned int virq, irq_hw_number_t hw)
 {
index 1a726229a4274f3e5be275b96ab48a47c0c31e6f..ab9ecce61ee5c22c70068408cc81097cf634b910 100644 (file)
@@ -31,6 +31,7 @@
 #include <asm/xive.h>
 #include <asm/xive-regs.h>
 #include <asm/opal.h>
+#include <asm/kvm_ppc.h>
 
 #include "xive-internal.h"
 
@@ -95,6 +96,7 @@ int xive_native_populate_irq_data(u32 hw_irq, struct xive_irq_data *data)
        }
        return 0;
 }
+EXPORT_SYMBOL_GPL(xive_native_populate_irq_data);
 
 int xive_native_configure_irq(u32 hw_irq, u32 target, u8 prio, u32 sw_irq)
 {
@@ -108,6 +110,8 @@ int xive_native_configure_irq(u32 hw_irq, u32 target, u8 prio, u32 sw_irq)
        }
        return rc == 0 ? 0 : -ENXIO;
 }
+EXPORT_SYMBOL_GPL(xive_native_configure_irq);
+
 
 /* This can be called multiple time to change a queue configuration */
 int xive_native_configure_queue(u32 vp_id, struct xive_q *q, u8 prio,
@@ -172,6 +176,7 @@ int xive_native_configure_queue(u32 vp_id, struct xive_q *q, u8 prio,
 fail:
        return rc;
 }
+EXPORT_SYMBOL_GPL(xive_native_configure_queue);
 
 static void __xive_native_disable_queue(u32 vp_id, struct xive_q *q, u8 prio)
 {
@@ -192,6 +197,7 @@ void xive_native_disable_queue(u32 vp_id, struct xive_q *q, u8 prio)
 {
        __xive_native_disable_queue(vp_id, q, prio);
 }
+EXPORT_SYMBOL_GPL(xive_native_disable_queue);
 
 static int xive_native_setup_queue(unsigned int cpu, struct xive_cpu *xc, u8 prio)
 {
@@ -262,6 +268,7 @@ static int xive_native_get_ipi(unsigned int cpu, struct xive_cpu *xc)
        }
        return 0;
 }
+#endif /* CONFIG_SMP */
 
 u32 xive_native_alloc_irq(void)
 {
@@ -277,6 +284,7 @@ u32 xive_native_alloc_irq(void)
                return 0;
        return rc;
 }
+EXPORT_SYMBOL_GPL(xive_native_alloc_irq);
 
 void xive_native_free_irq(u32 irq)
 {
@@ -287,7 +295,9 @@ void xive_native_free_irq(u32 irq)
                msleep(1);
        }
 }
+EXPORT_SYMBOL_GPL(xive_native_free_irq);
 
+#ifdef CONFIG_SMP
 static void xive_native_put_ipi(unsigned int cpu, struct xive_cpu *xc)
 {
        s64 rc;
@@ -383,7 +393,7 @@ static void xive_native_setup_cpu(unsigned int cpu, struct xive_cpu *xc)
                return;
 
        /* Enable the pool VP */
-       vp = xive_pool_vps + get_hard_smp_processor_id(cpu);
+       vp = xive_pool_vps + cpu;
        pr_debug("CPU %d setting up pool VP 0x%x\n", cpu, vp);
        for (;;) {
                rc = opal_xive_set_vp_info(vp, OPAL_XIVE_VP_ENABLED, 0);
@@ -428,7 +438,7 @@ static void xive_native_teardown_cpu(unsigned int cpu, struct xive_cpu *xc)
        in_be64(xive_tima + TM_SPC_PULL_POOL_CTX);
 
        /* Disable it */
-       vp = xive_pool_vps + get_hard_smp_processor_id(cpu);
+       vp = xive_pool_vps + cpu;
        for (;;) {
                rc = opal_xive_set_vp_info(vp, 0, 0);
                if (rc != OPAL_BUSY)
@@ -437,10 +447,11 @@ static void xive_native_teardown_cpu(unsigned int cpu, struct xive_cpu *xc)
        }
 }
 
-static void xive_native_sync_source(u32 hw_irq)
+void xive_native_sync_source(u32 hw_irq)
 {
        opal_xive_sync(XIVE_SYNC_EAS, hw_irq);
 }
+EXPORT_SYMBOL_GPL(xive_native_sync_source);
 
 static const struct xive_ops xive_native_ops = {
        .populate_irq_data      = xive_native_populate_irq_data,
@@ -501,10 +512,24 @@ static bool xive_parse_provisioning(struct device_node *np)
        return true;
 }
 
+static void xive_native_setup_pools(void)
+{
+       /* Allocate a pool big enough */
+       pr_debug("XIVE: Allocating VP block for pool size %d\n", nr_cpu_ids);
+
+       xive_pool_vps = xive_native_alloc_vp_block(nr_cpu_ids);
+       if (WARN_ON(xive_pool_vps == XIVE_INVALID_VP))
+               pr_err("XIVE: Failed to allocate pool VP, KVM might not function\n");
+
+       pr_debug("XIVE: Pool VPs allocated at 0x%x for %d max CPUs\n",
+                xive_pool_vps, nr_cpu_ids);
+}
+
 u32 xive_native_default_eq_shift(void)
 {
        return xive_queue_shift;
 }
+EXPORT_SYMBOL_GPL(xive_native_default_eq_shift);
 
 bool xive_native_init(void)
 {
@@ -514,7 +539,7 @@ bool xive_native_init(void)
        struct property *prop;
        u8 max_prio = 7;
        const __be32 *p;
-       u32 val;
+       u32 val, cpu;
        s64 rc;
 
        if (xive_cmdline_disabled)
@@ -550,7 +575,11 @@ bool xive_native_init(void)
                        break;
        }
 
-       /* Grab size of provisioning pages */
+       /* Configure Thread Management areas for KVM */
+       for_each_possible_cpu(cpu)
+               kvmppc_set_xive_tima(cpu, r.start, tima);
+
+       /* Grab size of provisionning pages */
        xive_parse_provisioning(np);
 
        /* Switch the XIVE to exploitation mode */
@@ -560,6 +589,9 @@ bool xive_native_init(void)
                return false;
        }
 
+       /* Setup some dummy HV pool VPs */
+       xive_native_setup_pools();
+
        /* Initialize XIVE core with our backend */
        if (!xive_core_init(&xive_native_ops, tima, TM_QW3_HV_PHYS,
                            max_prio)) {
@@ -638,3 +670,47 @@ void xive_native_free_vp_block(u32 vp_base)
                pr_warn("OPAL error %lld freeing VP block\n", rc);
 }
 EXPORT_SYMBOL_GPL(xive_native_free_vp_block);
+
+int xive_native_enable_vp(u32 vp_id)
+{
+       s64 rc;
+
+       for (;;) {
+               rc = opal_xive_set_vp_info(vp_id, OPAL_XIVE_VP_ENABLED, 0);
+               if (rc != OPAL_BUSY)
+                       break;
+               msleep(1);
+       }
+       return rc ? -EIO : 0;
+}
+EXPORT_SYMBOL_GPL(xive_native_enable_vp);
+
+int xive_native_disable_vp(u32 vp_id)
+{
+       s64 rc;
+
+       for (;;) {
+               rc = opal_xive_set_vp_info(vp_id, 0, 0);
+               if (rc != OPAL_BUSY)
+                       break;
+               msleep(1);
+       }
+       return rc ? -EIO : 0;
+}
+EXPORT_SYMBOL_GPL(xive_native_disable_vp);
+
+int xive_native_get_vp_info(u32 vp_id, u32 *out_cam_id, u32 *out_chip_id)
+{
+       __be64 vp_cam_be;
+       __be32 vp_chip_id_be;
+       s64 rc;
+
+       rc = opal_xive_get_vp_info(vp_id, NULL, &vp_cam_be, NULL, &vp_chip_id_be);
+       if (rc)
+               return -EIO;
+       *out_cam_id = be64_to_cpu(vp_cam_be) & 0xffffffffu;
+       *out_chip_id = be32_to_cpu(vp_chip_id_be);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(xive_native_get_vp_info);
index 7e3481eb2174e8e3fe19eb66c35eab035e4f4a77..45092b12f54f530296f79cfbe4cb4b7c6991d889 100644 (file)
@@ -1,4 +1,5 @@
 generic-y += asm-offsets.h
+generic-y += cacheflush.h
 generic-y += clkdev.h
 generic-y += dma-contiguous.h
 generic-y += div64.h
index 0206c805232878c95a6588dbb9909ecb4268d5d0..df7b54ea956daeb6c9a1091518e73417e688e504 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/spinlock.h>
 #include <linux/kernel.h>
 #include <linux/time.h>
+#include <linux/refcount.h>
 #include <uapi/asm/debug.h>
 
 #define DEBUG_MAX_LEVEL            6  /* debug levels range from 0 to 6 */
@@ -31,7 +32,7 @@ struct debug_view;
 typedef struct debug_info {    
        struct debug_info* next;
        struct debug_info* prev;
-       atomic_t ref_count;
+       refcount_t ref_count;
        spinlock_t lock;                        
        int level;
        int nr_areas;
index 60323c21938bb5d97407e9f0cb35c6fcdd335597..37f617dfbeded0de8edb9f9f4e1a263c46bd0635 100644 (file)
@@ -40,6 +40,8 @@ static inline int insn_length(unsigned char code)
        return ((((int) code + 64) >> 7) + 1) << 1;
 }
 
+struct pt_regs;
+
 void show_code(struct pt_regs *regs);
 void print_fn_code(unsigned char *code, unsigned long len);
 int insn_to_mnemonic(unsigned char *instruction, char *buf, unsigned int len);
index 1293c4066cfc806f96f06bec93743f7d051f2973..28792ef82c837a2f2c11a5765098434018d02598 100644 (file)
  * 2005-Dec    Used as a template for s390 by Mike Grundy
  *             <grundym@us.ibm.com>
  */
+#include <linux/types.h>
 #include <asm-generic/kprobes.h>
 
 #define BREAKPOINT_INSTRUCTION 0x0002
 
+#define FIXUP_PSW_NORMAL       0x08
+#define FIXUP_BRANCH_NOT_TAKEN 0x04
+#define FIXUP_RETURN_REGISTER  0x02
+#define FIXUP_NOT_REQUIRED     0x01
+
+int probe_is_prohibited_opcode(u16 *insn);
+int probe_get_fixup_type(u16 *insn);
+int probe_is_insn_relative_long(u16 *insn);
+
 #ifdef CONFIG_KPROBES
-#include <linux/types.h>
 #include <linux/ptrace.h>
 #include <linux/percpu.h>
 #include <linux/sched/task_stack.h>
@@ -56,11 +65,6 @@ typedef u16 kprobe_opcode_t;
 
 #define KPROBE_SWAP_INST       0x10
 
-#define FIXUP_PSW_NORMAL       0x08
-#define FIXUP_BRANCH_NOT_TAKEN 0x04
-#define FIXUP_RETURN_REGISTER  0x02
-#define FIXUP_NOT_REQUIRED     0x01
-
 /* Architecture specific copy of original instruction */
 struct arch_specific_insn {
        /* copy of original instruction */
@@ -90,10 +94,6 @@ int kprobe_fault_handler(struct pt_regs *regs, int trapnr);
 int kprobe_exceptions_notify(struct notifier_block *self,
        unsigned long val, void *data);
 
-int probe_is_prohibited_opcode(u16 *insn);
-int probe_get_fixup_type(u16 *insn);
-int probe_is_insn_relative_long(u16 *insn);
-
 #define flush_insn_slot(p)     do { } while (0)
 
 #endif /* CONFIG_KPROBES */
similarity index 80%
rename from arch/s390/include/asm/cacheflush.h
rename to arch/s390/include/asm/set_memory.h
index 0499334f9473a94e6a80e9144e9fd2946167f4d7..46a4db44c47a74afac870091407fa09567f6eb04 100644 (file)
@@ -1,8 +1,5 @@
-#ifndef _S390_CACHEFLUSH_H
-#define _S390_CACHEFLUSH_H
-
-/* Caches aren't brain-dead on the s390. */
-#include <asm-generic/cacheflush.h>
+#ifndef _ASMS390_SET_MEMORY_H
+#define _ASMS390_SET_MEMORY_H
 
 #define SET_MEMORY_RO  1UL
 #define SET_MEMORY_RW  2UL
@@ -31,4 +28,4 @@ static inline int set_memory_x(unsigned long addr, int numpages)
        return __set_memory(addr, numpages, SET_MEMORY_X);
 }
 
-#endif /* _S390_CACHEFLUSH_H */
+#endif
index 73bff45ced55268c7f06e52a98be46f7eaa2ea54..e784bed6ed7ffb24cabb02eb92a1d90494e3b7e1 100644 (file)
@@ -146,7 +146,7 @@ extern int topology_max_mnest;
  * Returns the maximum nesting level supported by the cpu topology code.
  * The current maximum level is 4 which is the drawer level.
  */
-static inline int topology_mnest_limit(void)
+static inline unsigned char topology_mnest_limit(void)
 {
        return min(topology_max_mnest, 4);
 }
index addb09cee0f531c79da02c88226e13c6132d6d68..ca62066895e00eeff9e569790e875c02a7e936f1 100644 (file)
@@ -10,49 +10,3 @@ generic-y += poll.h
 generic-y += resource.h
 generic-y += sockios.h
 generic-y += termbits.h
-
-header-y += auxvec.h
-header-y += bitsperlong.h
-header-y += byteorder.h
-header-y += chpid.h
-header-y += chsc.h
-header-y += clp.h
-header-y += cmb.h
-header-y += dasd.h
-header-y += debug.h
-header-y += errno.h
-header-y += guarded_storage.h
-header-y += hypfs.h
-header-y += ioctls.h
-header-y += ipcbuf.h
-header-y += kvm.h
-header-y += kvm_para.h
-header-y += kvm_perf.h
-header-y += kvm_virtio.h
-header-y += monwriter.h
-header-y += msgbuf.h
-header-y += pkey.h
-header-y += posix_types.h
-header-y += ptrace.h
-header-y += qeth.h
-header-y += schid.h
-header-y += sclp_ctl.h
-header-y += sembuf.h
-header-y += setup.h
-header-y += shmbuf.h
-header-y += sie.h
-header-y += sigcontext.h
-header-y += siginfo.h
-header-y += signal.h
-header-y += socket.h
-header-y += stat.h
-header-y += statfs.h
-header-y += swab.h
-header-y += tape390.h
-header-y += termios.h
-header-y += types.h
-header-y += ucontext.h
-header-y += unistd.h
-header-y += virtio-ccw.h
-header-y += vtoc.h
-header-y += zcrypt.h
index 530226b6cb19a2ed5bb011ab61215f69e243d4c5..86b3e74f569eb7823ba6c4b0c4ec7baeb456e2f1 100644 (file)
@@ -277,7 +277,7 @@ debug_info_alloc(const char *name, int pages_per_area, int nr_areas,
        memset(rc->views, 0, DEBUG_MAX_VIEWS * sizeof(struct debug_view *));
        memset(rc->debugfs_entries, 0 ,DEBUG_MAX_VIEWS *
                sizeof(struct dentry*));
-       atomic_set(&(rc->ref_count), 0);
+       refcount_set(&(rc->ref_count), 0);
 
        return rc;
 
@@ -361,7 +361,7 @@ debug_info_create(const char *name, int pages_per_area, int nr_areas,
         debug_area_last = rc;
         rc->next = NULL;
 
-       debug_info_get(rc);
+       refcount_set(&rc->ref_count, 1);
 out:
        return rc;
 }
@@ -416,7 +416,7 @@ static void
 debug_info_get(debug_info_t * db_info)
 {
        if (db_info)
-               atomic_inc(&db_info->ref_count);
+               refcount_inc(&db_info->ref_count);
 }
 
 /*
@@ -431,7 +431,7 @@ debug_info_put(debug_info_t *db_info)
 
        if (!db_info)
                return;
-       if (atomic_dec_and_test(&db_info->ref_count)) {
+       if (refcount_dec_and_test(&db_info->ref_count)) {
                for (i = 0; i < DEBUG_MAX_VIEWS; i++) {
                        if (!db_info->views[i])
                                continue;
index a5f5d3bb3dbc516d23c98082d0f3abe186fc95c1..e408d9cc5b96adf40b873d8aabb3235793cd1b16 100644 (file)
@@ -312,6 +312,7 @@ ENTRY(system_call)
        lg      %r14,__LC_VDSO_PER_CPU
        lmg     %r0,%r10,__PT_R0(%r11)
        mvc     __LC_RETURN_PSW(16),__PT_PSW(%r11)
+.Lsysc_exit_timer:
        stpt    __LC_EXIT_TIMER
        mvc     __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER
        lmg     %r11,%r15,__PT_R11(%r11)
@@ -623,6 +624,7 @@ ENTRY(io_int_handler)
        lg      %r14,__LC_VDSO_PER_CPU
        lmg     %r0,%r10,__PT_R0(%r11)
        mvc     __LC_RETURN_PSW(16),__PT_PSW(%r11)
+.Lio_exit_timer:
        stpt    __LC_EXIT_TIMER
        mvc     __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER
        lmg     %r11,%r15,__PT_R11(%r11)
@@ -1174,15 +1176,23 @@ cleanup_critical:
        br      %r14
 
 .Lcleanup_sysc_restore:
+       # check if stpt has been executed
        clg     %r9,BASED(.Lcleanup_sysc_restore_insn)
+       jh      0f
+       mvc     __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER
+       cghi    %r11,__LC_SAVE_AREA_ASYNC
        je      0f
+       mvc     __LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER
+0:     clg     %r9,BASED(.Lcleanup_sysc_restore_insn+8)
+       je      1f
        lg      %r9,24(%r11)            # get saved pointer to pt_regs
        mvc     __LC_RETURN_PSW(16),__PT_PSW(%r9)
        mvc     0(64,%r11),__PT_R8(%r9)
        lmg     %r0,%r7,__PT_R0(%r9)
-0:     lmg     %r8,%r9,__LC_RETURN_PSW
+1:     lmg     %r8,%r9,__LC_RETURN_PSW
        br      %r14
 .Lcleanup_sysc_restore_insn:
+       .quad   .Lsysc_exit_timer
        .quad   .Lsysc_done - 4
 
 .Lcleanup_io_tif:
@@ -1190,15 +1200,20 @@ cleanup_critical:
        br      %r14
 
 .Lcleanup_io_restore:
+       # check if stpt has been executed
        clg     %r9,BASED(.Lcleanup_io_restore_insn)
-       je      0f
+       jh      0f
+       mvc     __LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER
+0:     clg     %r9,BASED(.Lcleanup_io_restore_insn+8)
+       je      1f
        lg      %r9,24(%r11)            # get saved r11 pointer to pt_regs
        mvc     __LC_RETURN_PSW(16),__PT_PSW(%r9)
        mvc     0(64,%r11),__PT_R8(%r9)
        lmg     %r0,%r7,__PT_R0(%r9)
-0:     lmg     %r8,%r9,__LC_RETURN_PSW
+1:     lmg     %r8,%r9,__LC_RETURN_PSW
        br      %r14
 .Lcleanup_io_restore_insn:
+       .quad   .Lio_exit_timer
        .quad   .Lio_done - 4
 
 .Lcleanup_idle:
index 60a8a4e207edbc080a15b809b3efd97ea245942a..d03a6d12c4bdc4118c3c10e0c80e90822cac6a03 100644 (file)
@@ -17,6 +17,7 @@
 #include <trace/syscall.h>
 #include <asm/asm-offsets.h>
 #include <asm/cacheflush.h>
+#include <asm/set_memory.h>
 #include "entry.h"
 
 /*
@@ -172,6 +173,8 @@ int __init ftrace_dyn_arch_init(void)
        return 0;
 }
 
+#ifdef CONFIG_MODULES
+
 static int __init ftrace_plt_init(void)
 {
        unsigned int *ip;
@@ -190,6 +193,8 @@ static int __init ftrace_plt_init(void)
 }
 device_initcall(ftrace_plt_init);
 
+#endif /* CONFIG_MODULES */
+
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 /*
  * Hook the return address and push it in the stack of return addresses
index 76f9eda1d7c0e8b5f0150a1b2fe0481241b1b0fa..3d6a997464549c651831ead6f7db836ce452b638 100644 (file)
@@ -31,7 +31,7 @@
 #include <linux/slab.h>
 #include <linux/hardirq.h>
 #include <linux/ftrace.h>
-#include <asm/cacheflush.h>
+#include <asm/set_memory.h>
 #include <asm/sections.h>
 #include <linux/uaccess.h>
 #include <asm/dis.h>
index db5658daf9945702f634c714177825acda8fa44a..49a6bd45957b53aaee9a4ad387725c06ca299cac 100644 (file)
@@ -26,6 +26,7 @@
 #include <asm/asm-offsets.h>
 #include <asm/cacheflush.h>
 #include <asm/os_info.h>
+#include <asm/set_memory.h>
 #include <asm/switch_to.h>
 #include <asm/nmi.h>
 
index 9a4f279d25ca9675a711d604f0a9ec7c633cae7b..ca960d0370d56517f7cf10ec86f20c7ea31c3746 100644 (file)
@@ -823,7 +823,7 @@ static int cpumsf_pmu_event_init(struct perf_event *event)
        }
 
        /* Check online status of the CPU to which the event is pinned */
-       if (event->cpu >= nr_cpumask_bits ||
+       if ((unsigned int)event->cpu >= nr_cpumask_bits ||
            (event->cpu >= 0 && !cpu_online(event->cpu)))
                return -ENODEV;
 
index 72307f108c40387fd718e9ca1e07ee5cb6ef9cb8..6e2c42bd1c3badbc4837176aeb1e266d86890bcf 100644 (file)
@@ -31,8 +31,14 @@ SECTIONS
 {
        . = 0x00000000;
        .text : {
-       _text = .;              /* Text and read-only data */
+               /* Text and read-only data */
                HEAD_TEXT
+               /*
+                * E.g. perf doesn't like symbols starting at address zero,
+                * therefore skip the initial PSW and channel program located
+                * at address zero and let _text start at 0x200.
+                */
+       _text = 0x200;
                TEXT_TEXT
                SCHED_TEXT
                CPUIDLE_TEXT
index aeb3feb9de534bd5e9d8fc2da9770a594f6adaa2..689ac48361c697318ba6192962c7790d027a3199 100644 (file)
@@ -1204,10 +1204,7 @@ static long kvm_s390_get_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
        if (args->count < 1 || args->count > KVM_S390_SKEYS_MAX)
                return -EINVAL;
 
-       keys = kmalloc_array(args->count, sizeof(uint8_t),
-                            GFP_KERNEL | __GFP_NOWARN);
-       if (!keys)
-               keys = vmalloc(sizeof(uint8_t) * args->count);
+       keys = kvmalloc_array(args->count, sizeof(uint8_t), GFP_KERNEL);
        if (!keys)
                return -ENOMEM;
 
@@ -1249,10 +1246,7 @@ static long kvm_s390_set_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
        if (args->count < 1 || args->count > KVM_S390_SKEYS_MAX)
                return -EINVAL;
 
-       keys = kmalloc_array(args->count, sizeof(uint8_t),
-                            GFP_KERNEL | __GFP_NOWARN);
-       if (!keys)
-               keys = vmalloc(sizeof(uint8_t) * args->count);
+       keys = kvmalloc_array(args->count, sizeof(uint8_t), GFP_KERNEL);
        if (!keys)
                return -ENOMEM;
 
index ae90e1ae3607052c6ac4403f815d33061fcaf604..1963ddbf4ab385898160ce1d75881201b9c848c8 100644 (file)
@@ -4,6 +4,7 @@
  *    Copyright IBM Corp. 2014
  */
 
+#include <linux/errno.h>
 #include <asm/kprobes.h>
 #include <asm/dis.h>
 
index 1e5bb2b86c423fefee7987ec45483077748e8ca8..b3bd3f23b8e851c7f67e46cb527e20603512e7f5 100644 (file)
@@ -337,8 +337,8 @@ long __strncpy_from_user(char *dst, const char __user *src, long size)
                return 0;
        done = 0;
        do {
-               offset = (size_t)src & ~PAGE_MASK;
-               len = min(size - done, PAGE_SIZE - offset);
+               offset = (size_t)src & (L1_CACHE_BYTES - 1);
+               len = min(size - done, L1_CACHE_BYTES - offset);
                if (copy_from_user(dst, src, len))
                        return -EFAULT;
                len_str = strnlen(dst, len);
index ee5066718b212b1319baf3ec2da51a5f43ae6ebc..ee6a1d3d4983bc3cf65c9de4a901528b2c77e0ee 100644 (file)
@@ -39,6 +39,7 @@
 #include <asm/sections.h>
 #include <asm/ctl_reg.h>
 #include <asm/sclp.h>
+#include <asm/set_memory.h>
 
 pgd_t swapper_pg_dir[PTRS_PER_PGD] __section(.bss..swapper_pg_dir);
 
index fc321c5ec30e0c91bd035e4848db2aef3875a00c..49e721f3645e8ce143856ed82eb046fd34a9f235 100644 (file)
@@ -8,6 +8,7 @@
 #include <asm/facility.h>
 #include <asm/pgtable.h>
 #include <asm/page.h>
+#include <asm/set_memory.h>
 
 static inline unsigned long sske_frame(unsigned long addr, unsigned char skey)
 {
index 60d38993f2323ac3865cd2f2ec44ba8bc8cafd97..c33c94b4be6036e8558e677c78136e3300c48ae3 100644 (file)
@@ -17,6 +17,7 @@
 #include <asm/setup.h>
 #include <asm/tlbflush.h>
 #include <asm/sections.h>
+#include <asm/set_memory.h>
 
 static DEFINE_MUTEX(vmem_mutex);
 
index 4ecf6d68750914e75c5ffab3c0dc2e5d8b9ef2f8..6e97a2e3fd8d1fc5b5a2e89c67b52d1c322b1da3 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/bpf.h>
 #include <asm/cacheflush.h>
 #include <asm/dis.h>
+#include <asm/set_memory.h>
 #include "bpf_jit.h"
 
 int bpf_jit_enable __read_mostly;
index e3a8d0f96652d59944c78def1fac1de8494b4e1f..54b3b2039af1e985960d97a35510a6455eafe573 100644 (file)
@@ -1,6 +1,3 @@
-
-header-y +=
-
 generic-y += barrier.h
 generic-y += clkdev.h
 generic-y += current.h
index 040178cdb3eb9816f3d50769fee272e802becf9b..b15bf6bc0e94f46f035e8781ffa921060341fe91 100644 (file)
@@ -1,34 +1,2 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
-
-header-y += auxvec.h
-header-y += bitsperlong.h
-header-y += byteorder.h
-header-y += errno.h
-header-y += fcntl.h
-header-y += ioctl.h
-header-y += ioctls.h
-header-y += ipcbuf.h
-header-y += kvm_para.h
-header-y += mman.h
-header-y += msgbuf.h
-header-y += param.h
-header-y += poll.h
-header-y += posix_types.h
-header-y += ptrace.h
-header-y += resource.h
-header-y += sembuf.h
-header-y += setup.h
-header-y += shmbuf.h
-header-y += sigcontext.h
-header-y += siginfo.h
-header-y += signal.h
-header-y += socket.h
-header-y += sockios.h
-header-y += stat.h
-header-y += statfs.h
-header-y += swab.h
-header-y += termbits.h
-header-y += termios.h
-header-y += types.h
-header-y += unistd.h
index 336f33a419d99561d57b329a3ee6a513164ca43f..280bbff121020ef49298705a1c86233f1ded1c6f 100644 (file)
@@ -94,7 +94,8 @@ defaultimage-$(CONFIG_SH_7206_SOLUTION_ENGINE)        := vmlinux
 defaultimage-$(CONFIG_SH_7619_SOLUTION_ENGINE) := vmlinux
 
 # Set some sensible Kbuild defaults
-KBUILD_IMAGE           := $(defaultimage-y)
+boot := arch/sh/boot
+KBUILD_IMAGE           := $(boot)/$(defaultimage-y)
 
 #
 # Choosing incompatible machines durings configuration will result in
@@ -186,8 +187,6 @@ cpuincdir-y                 += cpu-common   # Must be last
 drivers-y                      += arch/sh/drivers/
 drivers-$(CONFIG_OPROFILE)     += arch/sh/oprofile/
 
-boot := arch/sh/boot
-
 cflags-y       += $(foreach d, $(cpuincdir-y), -Iarch/sh/include/$(d)) \
                   $(foreach d, $(machdir-y), -Iarch/sh/include/$(d))
 
@@ -211,7 +210,7 @@ BOOT_TARGETS = uImage uImage.bz2 uImage.gz uImage.lzma uImage.xz uImage.lzo \
               romImage
 PHONY += $(BOOT_TARGETS)
 
-all: $(KBUILD_IMAGE)
+all: $(notdir $(KBUILD_IMAGE))
 
 $(BOOT_TARGETS): vmlinux
        $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
index 84563e39a5b821cef555af1185b60b815080a84c..c99ee286b69f126506eebe9814588096cb224a5b 100644 (file)
@@ -269,27 +269,6 @@ void __ref pcibios_report_status(unsigned int status_mask, int warn)
        }
 }
 
-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
-                       enum pci_mmap_state mmap_state, int write_combine)
-{
-       /*
-        * I/O space can be accessed via normal processor loads and stores on
-        * this platform but for now we elect not to do this and portable
-        * drivers should not do this anyway.
-        */
-       if (mmap_state == pci_mmap_io)
-               return -EINVAL;
-
-       /*
-        * Ignore write-combine; for now only return uncached mappings.
-        */
-       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
-       return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
-                              vma->vm_end - vma->vm_start,
-                              vma->vm_page_prot);
-}
-
 #ifndef CONFIG_GENERIC_IOMAP
 
 void __iomem *__pci_ioport_map(struct pci_dev *dev,
index 644314f2b1ef0ba94e22bb1707f68036ac3968cc..17fa69bc814d7967e33ba119202428142ab50343 100644 (file)
@@ -66,8 +66,8 @@ extern unsigned long PCIBIOS_MIN_IO, PCIBIOS_MIN_MEM;
 struct pci_dev;
 
 #define HAVE_PCI_MMAP
-extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
-       enum pci_mmap_state mmap_state, int write_combine);
+#define ARCH_GENERIC_PCI_MMAP_RESOURCE
+
 extern void pcibios_set_master(struct pci_dev *dev);
 
 /* Dynamic DMA mapping stuff.
index 60613ae78513a0c60ed146e9d11a0cf734adc4d0..b15bf6bc0e94f46f035e8781ffa921060341fe91 100644 (file)
@@ -1,25 +1,2 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
-
-header-y += auxvec.h
-header-y += byteorder.h
-header-y += cachectl.h
-header-y += cpu-features.h
-header-y += hw_breakpoint.h
-header-y += ioctls.h
-header-y += posix_types.h
-header-y += posix_types_32.h
-header-y += posix_types_64.h
-header-y += ptrace.h
-header-y += ptrace_32.h
-header-y += ptrace_64.h
-header-y += setup.h
-header-y += sigcontext.h
-header-y += signal.h
-header-y += sockios.h
-header-y += stat.h
-header-y += swab.h
-header-y += types.h
-header-y += unistd.h
-header-y += unistd_32.h
-header-y += unistd_64.h
index dcbf985ab243201250222a824fc1146320522e65..d1f837dc77a4d0c975f94e5bbd315b347001d01a 100644 (file)
@@ -24,9 +24,11 @@ static inline int is_hugepage_only_range(struct mm_struct *mm,
 static inline int prepare_hugepage_range(struct file *file,
                        unsigned long addr, unsigned long len)
 {
-       if (len & ~HPAGE_MASK)
+       struct hstate *h = hstate_file(file);
+
+       if (len & ~huge_page_mask(h))
                return -EINVAL;
-       if (addr & ~HPAGE_MASK)
+       if (addr & ~huge_page_mask(h))
                return -EINVAL;
        return 0;
 }
index 2303635158f56fc9b5653e5a5949642328d9cfe5..b957ca5527a3d23c603a53eab461991536cc66ff 100644 (file)
@@ -42,13 +42,10 @@ static inline int pci_proc_domain(struct pci_bus *bus)
 /* Platform support for /proc/bus/pci/X/Y mmap()s. */
 
 #define HAVE_PCI_MMAP
+#define arch_can_pci_mmap_io() 1
 #define HAVE_ARCH_PCI_GET_UNMAPPED_AREA
 #define get_pci_unmapped_area get_fb_unmapped_area
 
-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
-                       enum pci_mmap_state mmap_state,
-                       int write_combine);
-
 static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
 {
        return PCI_IRQ_NONE;
index ce6f56980aefd2902bfae849eb90a993295976eb..cf190728360bbfb43621d23a7fb3a22c443a7399 100644 (file)
@@ -91,9 +91,9 @@ extern unsigned long pfn_base;
  * ZERO_PAGE is a global shared page that is always zero: used
  * for zero-mapped memory areas etc..
  */
-extern unsigned long empty_zero_page;
+extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
 
-#define ZERO_PAGE(vaddr) (virt_to_page(&empty_zero_page))
+#define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
 
 /*
  * In general all page table modifications should use the V8 atomic
index 478bf6bb4598b345dd7f590beee86f43893e7645..3fae200dd251f094bad756ef145ec39882470d8e 100644 (file)
@@ -16,7 +16,7 @@ extern char reboot_command[];
  */
 extern unsigned char boot_cpu_id;
 
-extern unsigned long empty_zero_page;
+extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
 
 extern int serial_console;
 static inline int con_is_present(void)
index b5843ee09fb53a6e4438b29140adbd34d9c887c1..b15bf6bc0e94f46f035e8781ffa921060341fe91 100644 (file)
@@ -1,50 +1,2 @@
 # UAPI Header export list
-# User exported sparc header files
-
 include include/uapi/asm-generic/Kbuild.asm
-
-header-y += apc.h
-header-y += asi.h
-header-y += auxvec.h
-header-y += bitsperlong.h
-header-y += byteorder.h
-header-y += display7seg.h
-header-y += envctrl.h
-header-y += errno.h
-header-y += fbio.h
-header-y += fcntl.h
-header-y += ioctl.h
-header-y += ioctls.h
-header-y += ipcbuf.h
-header-y += jsflash.h
-header-y += kvm_para.h
-header-y += mman.h
-header-y += msgbuf.h
-header-y += openpromio.h
-header-y += param.h
-header-y += perfctr.h
-header-y += poll.h
-header-y += posix_types.h
-header-y += psr.h
-header-y += psrcompat.h
-header-y += pstate.h
-header-y += ptrace.h
-header-y += resource.h
-header-y += sembuf.h
-header-y += setup.h
-header-y += shmbuf.h
-header-y += sigcontext.h
-header-y += siginfo.h
-header-y += signal.h
-header-y += socket.h
-header-y += sockios.h
-header-y += stat.h
-header-y += statfs.h
-header-y += swab.h
-header-y += termbits.h
-header-y += termios.h
-header-y += traps.h
-header-y += uctx.h
-header-y += unistd.h
-header-y += utrap.h
-header-y += watchdog.h
index 6bcff698069bf1fa57c1d84df180c1cb67f18a65..cec54dc4ab817e7c9c54c2d9b0532f0fd49bc7d8 100644 (file)
@@ -130,17 +130,16 @@ unsigned long prepare_ftrace_return(unsigned long parent,
        if (unlikely(atomic_read(&current->tracing_graph_pause)))
                return parent + 8UL;
 
-       if (ftrace_push_return_trace(parent, self_addr, &trace.depth,
-                                    frame_pointer, NULL) == -EBUSY)
-               return parent + 8UL;
-
        trace.func = self_addr;
+       trace.depth = current->curr_ret_stack + 1;
 
        /* Only trace if the calling function expects to */
-       if (!ftrace_graph_entry(&trace)) {
-               current->curr_ret_stack--;
+       if (!ftrace_graph_entry(&trace))
+               return parent + 8UL;
+
+       if (ftrace_push_return_trace(parent, self_addr, &trace.depth,
+                                    frame_pointer, NULL) == -EBUSY)
                return parent + 8UL;
-       }
 
        return return_hooker;
 }
index 44101196d02b5dacb5e3c67248b3c3de77c4a9b4..41a4073286671eff51f275bfca4ae6d9d01db74d 100644 (file)
@@ -939,3 +939,9 @@ ENTRY(__retl_o1)
        retl
         mov    %o1, %o0
 ENDPROC(__retl_o1)
+
+ENTRY(__retl_o1_asi)
+       wr      %o5, 0x0, %asi
+       retl
+        mov    %o1, %o0
+ENDPROC(__retl_o1_asi)
index 44a3ed93c214c5ad785386c1f7ad604525721025..e278bf52963b58e834ca21015ac59c2a84fe6ec0 100644 (file)
@@ -70,16 +70,9 @@ static ssize_t led_proc_write(struct file *file, const char __user *buffer,
        if (count > LED_MAX_LENGTH)
                count = LED_MAX_LENGTH;
 
-       buf = kmalloc(sizeof(char) * (count + 1), GFP_KERNEL);
-       if (!buf)
-               return -ENOMEM;
-
-       if (copy_from_user(buf, buffer, count)) {
-               kfree(buf);
-               return -EFAULT;
-       }
-
-       buf[count] = '\0';
+       buf = memdup_user_nul(buffer, count);
+       if (IS_ERR(buf))
+               return PTR_ERR(buf);
 
        /* work around \n when echo'ing into proc */
        if (buf[count - 1] == '\n')
index 015e55a7495d40cc3fd93c535b0723cd6ce147b4..7eceaa10836f0141472a7b71c445b4a65140a3e6 100644 (file)
@@ -862,9 +862,9 @@ static void __pci_mmap_set_pgprot(struct pci_dev *dev, struct vm_area_struct *vm
  *
  * Returns a negative error code on failure, zero on success.
  */
-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
-                       enum pci_mmap_state mmap_state,
-                       int write_combine)
+int pci_mmap_page_range(struct pci_dev *dev, int bar,
+                       struct vm_area_struct *vma,
+                       enum pci_mmap_state mmap_state, int write_combine)
 {
        int ret;
 
index 6f06058c5ae72a80c71de217c3c105cfe7a08b18..6722308d1a98ac0d1005f0fa4abc5287f4f3caf4 100644 (file)
@@ -148,7 +148,7 @@ static void __init boot_flags_init(char *commands)
 {
        while (*commands) {
                /* Move to the start of the next "argument". */
-               while (*commands && *commands == ' ')
+               while (*commands == ' ')
                        commands++;
 
                /* Process any command switches, otherwise skip it. */
index 6b7331d198e9d8b9b0596acbfdab443d227682a3..422b178809557c13345c312db96ec1cb893e50e6 100644 (file)
@@ -133,7 +133,7 @@ static void __init boot_flags_init(char *commands)
 {
        while (*commands) {
                /* Move to the start of the next "argument". */
-               while (*commands && *commands == ' ')
+               while (*commands == ' ')
                        commands++;
 
                /* Process any command switches, otherwise skip it. */
index 8e7a843ddd88366411de59480377798033d4c0a9..2fbf6297d57cfca68cebbf3da2ac9c62eba837b0 100644 (file)
@@ -8,7 +8,7 @@
 98:    x,y;                    \
        .section __ex_table,"a";\
        .align 4;               \
-       .word 98b, __retl_o1;   \
+       .word 98b, __retl_o1_asi;\
        .text;                  \
        .align 4;
 
index beab29bf419b606ae23a7c1e8151e2527bc0943c..33053bdf3766b35ee4396c04403931f37965c5d8 100644 (file)
@@ -8,7 +8,7 @@
 98:    x,y;                    \
        .section __ex_table,"a";\
        .align 4;               \
-       .word 98b, __retl_o1;   \
+       .word 98b, __retl_o1_asi;\
        .text;                  \
        .align 4;
 
index c6afe98de4d9aba5ebad292031735988afd8180d..3bd0d513bddbde7f95275be6e3ae94bd26729c6f 100644 (file)
@@ -290,7 +290,7 @@ void __init mem_init(void)
 
 
        /* Saves us work later. */
-       memset((void *)&empty_zero_page, 0, PAGE_SIZE);
+       memset((void *)empty_zero_page, 0, PAGE_SIZE);
 
        i = last_valid_pfn >> ((20 - PAGE_SHIFT) + 5);
        i += 1;
diff --git a/arch/tile/include/arch/Kbuild b/arch/tile/include/arch/Kbuild
deleted file mode 100644 (file)
index 3751c9f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-# Tile arch headers
index 24c44e93804defa17c073841c4a649485d41a8f7..16f0b08c8ce9aae410245e6d9cbac73391a44998 100644 (file)
@@ -1,6 +1,3 @@
-
-header-y += ../arch/
-
 generic-y += bug.h
 generic-y += bugs.h
 generic-y += clkdev.h
diff --git a/arch/tile/include/uapi/arch/Kbuild b/arch/tile/include/uapi/arch/Kbuild
deleted file mode 100644 (file)
index 97dfbec..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-# UAPI Header export list
-header-y += abi.h
-header-y += chip.h
-header-y += chip_tilegx.h
-header-y += chip_tilepro.h
-header-y += icache.h
-header-y += interrupts.h
-header-y += interrupts_32.h
-header-y += interrupts_64.h
-header-y += opcode.h
-header-y += opcode_tilegx.h
-header-y += opcode_tilepro.h
-header-y += sim.h
-header-y += sim_def.h
-header-y += spr_def.h
-header-y += spr_def_32.h
-header-y += spr_def_64.h
index c20db8e428bf698cca387f3c71a29e44f1df48ce..0c74c3c5ebfa4f6a1c47a9ea4c5ce784bc6188ca 100644 (file)
@@ -1,21 +1,4 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
-header-y += auxvec.h
-header-y += bitsperlong.h
-header-y += byteorder.h
-header-y += cachectl.h
-header-y += hardwall.h
-header-y += kvm_para.h
-header-y += mman.h
-header-y += ptrace.h
-header-y += setup.h
-header-y += sigcontext.h
-header-y += siginfo.h
-header-y += signal.h
-header-y += stat.h
-header-y += swab.h
-header-y += ucontext.h
-header-y += unistd.h
-
 generic-y += ucontext.h
index ed9c5b5ff028947061bd8a86949c58e9456e98a3..85f6dd204ab616a7fdd6bc080310bfc4967c1ef5 100644 (file)
@@ -57,3 +57,8 @@ config HZ
 config SUBARCH
        string
        option env="SUBARCH"
+
+config NR_CPUS
+       int
+       range 1 1
+       default 1
index 48bae81f8dcab2febedc7238f190b985e5da4a13..6f6e7896e53f4ea1f7141b1cbbec9de266108498 100644 (file)
@@ -14,7 +14,7 @@
 static char *initrd __initdata = NULL;
 static int load_initrd(char *filename, void *buf, int size);
 
-static int __init read_initrd(void)
+int __init read_initrd(void)
 {
        void *area;
        long long size;
@@ -46,8 +46,6 @@ static int __init read_initrd(void)
        return 0;
 }
 
-__uml_postsetup(read_initrd);
-
 static int __init uml_initrd_setup(char *line, int *add)
 {
        initrd = line;
index a76295f7ede9cd58beba128a21b05e685a3b0c02..6b995e870d555b12f92ab8fadb71d283fc236a76 100644 (file)
 
 static void _print_addr(void *data, unsigned long address, int reliable)
 {
-       pr_info(" [<%08lx>]", address);
-       pr_cont(" %s", reliable ? "" : "? ");
-       print_symbol("%s", address);
-       pr_cont("\n");
+       pr_info(" [<%08lx>] %s%pF\n", address, reliable ? "" : "? ",
+               (void *)address);
 }
 
 static const struct stacktrace_ops stackops = {
index 4b85acd4020c408fdf15d01408c9cc4d2bab8b40..64a1fd06f3fde02d964c4fedcb9e73328085c94d 100644 (file)
@@ -338,11 +338,17 @@ int __init linux_main(int argc, char **argv)
        return start_uml();
 }
 
+int __init __weak read_initrd(void)
+{
+       return 0;
+}
+
 void __init setup_arch(char **cmdline_p)
 {
        stack_protections((unsigned long) &init_thread_info);
        setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem);
        mem_total_pages(physmem_size, iomem_size, highmem);
+       read_initrd();
 
        paging_init();
        strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
index 23025d64516019e0d1451298570b5dc845b2bc62..03b3c4cc7735ac49f30e4b867dbd06944ec6456d 100644 (file)
@@ -21,6 +21,7 @@
 #include <registers.h>
 #include <skas.h>
 #include <sysdep/stub.h>
+#include <linux/threads.h>
 
 int is_skas_winch(int pid, int fd, void *data)
 {
@@ -233,9 +234,6 @@ static int userspace_tramp(void *stack)
        return 0;
 }
 
-/* Each element set once, and only accessed by a single processor anyway */
-#undef NR_CPUS
-#define NR_CPUS 1
 int userspace_pid[NR_CPUS];
 
 int start_userspace(unsigned long stub_stack)
index b6f5c4c1eaf95d1fe79f14771e81a674dc49a45d..98a5ca43ae87001c67b2b3e38304afb371831f2f 100644 (file)
@@ -43,9 +43,9 @@ boot                  := arch/unicore32/boot
 
 # Default defconfig and target when executing plain make
 KBUILD_DEFCONFIG       := $(ARCH)_defconfig
-KBUILD_IMAGE           := zImage
+KBUILD_IMAGE           := $(boot)/zImage
 
-all:   $(KBUILD_IMAGE)
+all:   zImage
 
 zImage Image uImage: vmlinux
        $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
index 37e55d018de5f979051ec6526f32f5722af87bb5..ac5acdf4c4d01d35c49adcdd3142df513feaf48f 100644 (file)
@@ -17,8 +17,7 @@
 #include <mach/hardware.h> /* for PCIBIOS_MIN_* */
 
 #define HAVE_PCI_MMAP
-extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
-       enum pci_mmap_state mmap_state, int write_combine);
+#define ARCH_GENERIC_PCI_MMAP_RESOURCE
 
 #endif /* __KERNEL__ */
 #endif
index 0514d7ad68551de6b0e7a7946263bfc6c6249ab0..13a97aa2285f7418d18f1396f03bf6281b580a0f 100644 (file)
@@ -1,10 +1,4 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
 
-header-y += byteorder.h
-header-y += kvm_para.h
-header-y += ptrace.h
-header-y += sigcontext.h
-header-y += unistd.h
-
 generic-y += kvm_para.h
index 62137d13c6f9d2d75783dca25139217f23b09d54..1053bca1f8aa1592f03c8bff0759d8673b3f3217 100644 (file)
@@ -356,26 +356,3 @@ int pcibios_enable_device(struct pci_dev *dev, int mask)
        }
        return 0;
 }
-
-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
-                       enum pci_mmap_state mmap_state, int write_combine)
-{
-       unsigned long phys;
-
-       if (mmap_state == pci_mmap_io)
-               return -EINVAL;
-
-       phys = vma->vm_pgoff;
-
-       /*
-        * Mark this as IO
-        */
-       vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
-
-       if (remap_pfn_range(vma, vma->vm_start, phys,
-                            vma->vm_end - vma->vm_start,
-                            vma->vm_page_prot))
-               return -EAGAIN;
-
-       return 0;
-}
index 4430dd489620f0ed1f7e35af5ddde0b02356110d..5851411e60fb9fd008f0035ac92932bd03eb519b 100644 (file)
@@ -179,7 +179,8 @@ ifdef CONFIG_JUMP_LABEL
 endif
 
 ifeq ($(ACCUMULATE_OUTGOING_ARGS), 1)
-       KBUILD_CFLAGS += -maccumulate-outgoing-args
+       # This compiler flag is not supported by Clang:
+       KBUILD_CFLAGS += $(call cc-option,-maccumulate-outgoing-args,)
 endif
 
 # Stackpointer is addressed different for 32 bit and 64 bit x86
index 2e59dac07f9e051ad34e1061c3ae7b9a8e111480..d732e608e3af63e8f9f73210377509c24a56b38b 100644 (file)
@@ -1,7 +1,9 @@
 #ifndef BOOT_COMPRESSED_ERROR_H
 #define BOOT_COMPRESSED_ERROR_H
 
+#include <linux/compiler.h>
+
 void warn(char *m);
-void error(char *m);
+void error(char *m) __noreturn;
 
 #endif /* BOOT_COMPRESSED_ERROR_H */
index 56589d0a804b1239c7e8f5dce5ea1fd237a8ae8a..1d78f17390876233937a4514affb99d0facdd986 100644 (file)
@@ -70,7 +70,7 @@ static unsigned long level4p;
  * Due to relocation, pointers must be assigned at run time not build time.
  */
 static struct x86_mapping_info mapping_info = {
-       .pmd_flag       = __PAGE_KERNEL_LARGE_EXEC,
+       .page_flag       = __PAGE_KERNEL_LARGE_EXEC,
 };
 
 /* Locates and clears a region for a new top level page table. */
index 9d05c7e67f6073e3441c164d1bdc6db390507ef0..a45e2114a8460925b44bd6e0983f3ee37e83d861 100644 (file)
@@ -761,7 +761,7 @@ static const struct x86_cpu_id rapl_cpu_match[] __initconst = {
 
        X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_CORE,   hsw_rapl_init),
        X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_GT3E,   hsw_rapl_init),
-       X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_X,      hsw_rapl_init),
+       X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_X,      hsx_rapl_init),
        X86_RAPL_MODEL_MATCH(INTEL_FAM6_BROADWELL_XEON_D, hsw_rapl_init),
 
        X86_RAPL_MODEL_MATCH(INTEL_FAM6_XEON_PHI_KNL, knl_rapl_init),
index 7acb51c49fec46220052c94c5f6a4a308f4a1fc9..7a9df3beb89b1c6ba39365eb5059d39373bb6070 100644 (file)
@@ -32,6 +32,7 @@
 #define _ASM_ADD       __ASM_SIZE(add)
 #define _ASM_SUB       __ASM_SIZE(sub)
 #define _ASM_XADD      __ASM_SIZE(xadd)
+#define _ASM_MUL       __ASM_SIZE(mul)
 
 #define _ASM_AX                __ASM_REG(ax)
 #define _ASM_BX                __ASM_REG(bx)
index e7e1942edff7360bb36be03bd0f097c2f04e34e7..8b4140f6724f4cfe4cf89135b9e0547baa527d94 100644 (file)
@@ -5,93 +5,8 @@
 #include <asm-generic/cacheflush.h>
 #include <asm/special_insns.h>
 
-/*
- * The set_memory_* API can be used to change various attributes of a virtual
- * address range. The attributes include:
- * Cachability   : UnCached, WriteCombining, WriteThrough, WriteBack
- * Executability : eXeutable, NoteXecutable
- * Read/Write    : ReadOnly, ReadWrite
- * Presence      : NotPresent
- *
- * Within a category, the attributes are mutually exclusive.
- *
- * The implementation of this API will take care of various aspects that
- * are associated with changing such attributes, such as:
- * - Flushing TLBs
- * - Flushing CPU caches
- * - Making sure aliases of the memory behind the mapping don't violate
- *   coherency rules as defined by the CPU in the system.
- *
- * What this API does not do:
- * - Provide exclusion between various callers - including callers that
- *   operation on other mappings of the same physical page
- * - Restore default attributes when a page is freed
- * - Guarantee that mappings other than the requested one are
- *   in any state, other than that these do not violate rules for
- *   the CPU you have. Do not depend on any effects on other mappings,
- *   CPUs other than the one you have may have more relaxed rules.
- * The caller is required to take care of these.
- */
-
-int _set_memory_uc(unsigned long addr, int numpages);
-int _set_memory_wc(unsigned long addr, int numpages);
-int _set_memory_wt(unsigned long addr, int numpages);
-int _set_memory_wb(unsigned long addr, int numpages);
-int set_memory_uc(unsigned long addr, int numpages);
-int set_memory_wc(unsigned long addr, int numpages);
-int set_memory_wt(unsigned long addr, int numpages);
-int set_memory_wb(unsigned long addr, int numpages);
-int set_memory_x(unsigned long addr, int numpages);
-int set_memory_nx(unsigned long addr, int numpages);
-int set_memory_ro(unsigned long addr, int numpages);
-int set_memory_rw(unsigned long addr, int numpages);
-int set_memory_np(unsigned long addr, int numpages);
-int set_memory_4k(unsigned long addr, int numpages);
-
-int set_memory_array_uc(unsigned long *addr, int addrinarray);
-int set_memory_array_wc(unsigned long *addr, int addrinarray);
-int set_memory_array_wt(unsigned long *addr, int addrinarray);
-int set_memory_array_wb(unsigned long *addr, int addrinarray);
-
-int set_pages_array_uc(struct page **pages, int addrinarray);
-int set_pages_array_wc(struct page **pages, int addrinarray);
-int set_pages_array_wt(struct page **pages, int addrinarray);
-int set_pages_array_wb(struct page **pages, int addrinarray);
-
-/*
- * For legacy compatibility with the old APIs, a few functions
- * are provided that work on a "struct page".
- * These functions operate ONLY on the 1:1 kernel mapping of the
- * memory that the struct page represents, and internally just
- * call the set_memory_* function. See the description of the
- * set_memory_* function for more details on conventions.
- *
- * These APIs should be considered *deprecated* and are likely going to
- * be removed in the future.
- * The reason for this is the implicit operation on the 1:1 mapping only,
- * making this not a generally useful API.
- *
- * Specifically, many users of the old APIs had a virtual address,
- * called virt_to_page() or vmalloc_to_page() on that address to
- * get a struct page* that the old API required.
- * To convert these cases, use set_memory_*() on the original
- * virtual address, do not use these functions.
- */
-
-int set_pages_uc(struct page *page, int numpages);
-int set_pages_wb(struct page *page, int numpages);
-int set_pages_x(struct page *page, int numpages);
-int set_pages_nx(struct page *page, int numpages);
-int set_pages_ro(struct page *page, int numpages);
-int set_pages_rw(struct page *page, int numpages);
-
-
 void clflush_cache_range(void *addr, unsigned int size);
 
 #define mmio_flush_range(addr, size) clflush_cache_range(addr, size)
 
-extern int kernel_set_to_readonly;
-void set_kernel_text_rw(void);
-void set_kernel_text_ro(void);
-
 #endif /* _ASM_X86_CACHEFLUSH_H */
index 737da62bfeb095e875912b18e5732b7ce04cb18e..474eb8c66feeb2c98de2f5d6fe1db84de752c806 100644 (file)
@@ -4,8 +4,9 @@
 struct x86_mapping_info {
        void *(*alloc_pgt_page)(void *); /* allocate buf for page table */
        void *context;                   /* context for alloc_pgt_page */
-       unsigned long pmd_flag;          /* page flag for PMD entry */
+       unsigned long page_flag;         /* page flag for PMD or PUD entry */
        unsigned long offset;            /* ident mapping offset */
+       bool direct_gbpages;             /* PUD level 1GB page support */
 };
 
 int kernel_ident_mapping_init(struct x86_mapping_info *info, pgd_t *pgd_page,
index f5bddf92faba81675594db3c6ead4d1baf94f68f..695605eb1dfbd941b591564fef723bd030c3316f 100644 (file)
@@ -43,7 +43,7 @@
 #define KVM_PRIVATE_MEM_SLOTS 3
 #define KVM_MEM_SLOTS_NUM (KVM_USER_MEM_SLOTS + KVM_PRIVATE_MEM_SLOTS)
 
-#define KVM_HALT_POLL_NS_DEFAULT 400000
+#define KVM_HALT_POLL_NS_DEFAULT 200000
 
 #define KVM_IRQCHIP_NUM_PINS  KVM_IOAPIC_NUM_PINS
 
@@ -1020,6 +1020,8 @@ struct kvm_x86_ops {
        void (*enable_log_dirty_pt_masked)(struct kvm *kvm,
                                           struct kvm_memory_slot *slot,
                                           gfn_t offset, unsigned long mask);
+       int (*write_log_dirty)(struct kvm_vcpu *vcpu);
+
        /* pmu operations of sub-arch */
        const struct kvm_pmu_ops *pmu_ops;
 
index 1411dbed5e5e71ef62171f18ea4bb027d20eba71..f513cc231151c760a2aff203b32a72f1fc1a15e1 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/string.h>
 #include <linux/scatterlist.h>
 #include <asm/io.h>
+#include <asm/pat.h>
 #include <asm/x86_init.h>
 
 #ifdef __KERNEL__
@@ -102,10 +103,8 @@ int pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq);
 
 
 #define HAVE_PCI_MMAP
-extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
-                              enum pci_mmap_state mmap_state,
-                              int write_combine);
-
+#define arch_can_pci_mmap_wc() pat_enabled()
+#define ARCH_GENERIC_PCI_MMAP_RESOURCE
 
 #ifdef CONFIG_PCI
 extern void early_quirks(void);
index d5a22bac99880212c8ea4a799cc15898a6265819..0ff8fe71b25543b3d9f65d7f81a4c9db29e3bd6f 100644 (file)
@@ -98,7 +98,7 @@ static inline size_t arch_copy_from_iter_pmem(void *addr, size_t bytes,
 
                if (bytes < 8) {
                        if (!IS_ALIGNED(dest, 4) || (bytes != 4))
-                               arch_wb_cache_pmem(addr, 1);
+                               arch_wb_cache_pmem(addr, bytes);
                } else {
                        if (!IS_ALIGNED(dest, 8)) {
                                dest = ALIGN(dest, boot_cpu_data.x86_clflush_size);
diff --git a/arch/x86/include/asm/set_memory.h b/arch/x86/include/asm/set_memory.h
new file mode 100644 (file)
index 0000000..eaec6c3
--- /dev/null
@@ -0,0 +1,87 @@
+#ifndef _ASM_X86_SET_MEMORY_H
+#define _ASM_X86_SET_MEMORY_H
+
+#include <asm/page.h>
+#include <asm-generic/set_memory.h>
+
+/*
+ * The set_memory_* API can be used to change various attributes of a virtual
+ * address range. The attributes include:
+ * Cachability   : UnCached, WriteCombining, WriteThrough, WriteBack
+ * Executability : eXeutable, NoteXecutable
+ * Read/Write    : ReadOnly, ReadWrite
+ * Presence      : NotPresent
+ *
+ * Within a category, the attributes are mutually exclusive.
+ *
+ * The implementation of this API will take care of various aspects that
+ * are associated with changing such attributes, such as:
+ * - Flushing TLBs
+ * - Flushing CPU caches
+ * - Making sure aliases of the memory behind the mapping don't violate
+ *   coherency rules as defined by the CPU in the system.
+ *
+ * What this API does not do:
+ * - Provide exclusion between various callers - including callers that
+ *   operation on other mappings of the same physical page
+ * - Restore default attributes when a page is freed
+ * - Guarantee that mappings other than the requested one are
+ *   in any state, other than that these do not violate rules for
+ *   the CPU you have. Do not depend on any effects on other mappings,
+ *   CPUs other than the one you have may have more relaxed rules.
+ * The caller is required to take care of these.
+ */
+
+int _set_memory_uc(unsigned long addr, int numpages);
+int _set_memory_wc(unsigned long addr, int numpages);
+int _set_memory_wt(unsigned long addr, int numpages);
+int _set_memory_wb(unsigned long addr, int numpages);
+int set_memory_uc(unsigned long addr, int numpages);
+int set_memory_wc(unsigned long addr, int numpages);
+int set_memory_wt(unsigned long addr, int numpages);
+int set_memory_wb(unsigned long addr, int numpages);
+int set_memory_np(unsigned long addr, int numpages);
+int set_memory_4k(unsigned long addr, int numpages);
+
+int set_memory_array_uc(unsigned long *addr, int addrinarray);
+int set_memory_array_wc(unsigned long *addr, int addrinarray);
+int set_memory_array_wt(unsigned long *addr, int addrinarray);
+int set_memory_array_wb(unsigned long *addr, int addrinarray);
+
+int set_pages_array_uc(struct page **pages, int addrinarray);
+int set_pages_array_wc(struct page **pages, int addrinarray);
+int set_pages_array_wt(struct page **pages, int addrinarray);
+int set_pages_array_wb(struct page **pages, int addrinarray);
+
+/*
+ * For legacy compatibility with the old APIs, a few functions
+ * are provided that work on a "struct page".
+ * These functions operate ONLY on the 1:1 kernel mapping of the
+ * memory that the struct page represents, and internally just
+ * call the set_memory_* function. See the description of the
+ * set_memory_* function for more details on conventions.
+ *
+ * These APIs should be considered *deprecated* and are likely going to
+ * be removed in the future.
+ * The reason for this is the implicit operation on the 1:1 mapping only,
+ * making this not a generally useful API.
+ *
+ * Specifically, many users of the old APIs had a virtual address,
+ * called virt_to_page() or vmalloc_to_page() on that address to
+ * get a struct page* that the old API required.
+ * To convert these cases, use set_memory_*() on the original
+ * virtual address, do not use these functions.
+ */
+
+int set_pages_uc(struct page *page, int numpages);
+int set_pages_wb(struct page *page, int numpages);
+int set_pages_x(struct page *page, int numpages);
+int set_pages_nx(struct page *page, int numpages);
+int set_pages_ro(struct page *page, int numpages);
+int set_pages_rw(struct page *page, int numpages);
+
+extern int kernel_set_to_readonly;
+void set_kernel_text_rw(void);
+void set_kernel_text_ro(void);
+
+#endif /* _ASM_X86_SET_MEMORY_H */
index 3dec769cadf756a48a2f703a75298fb8f5a2cd05..83b6e9a0dce476c4840b02544b76ef049d92f166 100644 (file)
@@ -4,62 +4,3 @@ include include/uapi/asm-generic/Kbuild.asm
 genhdr-y += unistd_32.h
 genhdr-y += unistd_64.h
 genhdr-y += unistd_x32.h
-header-y += a.out.h
-header-y += auxvec.h
-header-y += bitsperlong.h
-header-y += boot.h
-header-y += bootparam.h
-header-y += byteorder.h
-header-y += debugreg.h
-header-y += e820.h
-header-y += errno.h
-header-y += fcntl.h
-header-y += hw_breakpoint.h
-header-y += hyperv.h
-header-y += ioctl.h
-header-y += ioctls.h
-header-y += ipcbuf.h
-header-y += ist.h
-header-y += kvm.h
-header-y += kvm_para.h
-header-y += kvm_perf.h
-header-y += ldt.h
-header-y += mce.h
-header-y += mman.h
-header-y += msgbuf.h
-header-y += msr-index.h
-header-y += msr.h
-header-y += mtrr.h
-header-y += param.h
-header-y += perf_regs.h
-header-y += poll.h
-header-y += posix_types.h
-header-y += posix_types_32.h
-header-y += posix_types_64.h
-header-y += posix_types_x32.h
-header-y += prctl.h
-header-y += processor-flags.h
-header-y += ptrace-abi.h
-header-y += ptrace.h
-header-y += resource.h
-header-y += sembuf.h
-header-y += setup.h
-header-y += shmbuf.h
-header-y += sigcontext.h
-header-y += sigcontext32.h
-header-y += siginfo.h
-header-y += signal.h
-header-y += socket.h
-header-y += sockios.h
-header-y += stat.h
-header-y += statfs.h
-header-y += svm.h
-header-y += swab.h
-header-y += termbits.h
-header-y += termios.h
-header-y += types.h
-header-y += ucontext.h
-header-y += unistd.h
-header-y += vm86.h
-header-y += vmx.h
-header-y += vsyscall.h
index df083efe6ee0075ad78391bbfdec3395bae5c022..815dd63f49d0311225775e377977891b9d6c7493 100644 (file)
@@ -36,7 +36,7 @@
 #include <asm/proto.h>
 #include <asm/iommu.h>
 #include <asm/gart.h>
-#include <asm/cacheflush.h>
+#include <asm/set_memory.h>
 #include <asm/swiotlb.h>
 #include <asm/dma.h>
 #include <asm/amd_nb.h>
index c36140d788fe215aadb3a8f27a8de040f2c44c06..bb5abe8f5fd46c17ca7c27361cbdb99e00db645f 100644 (file)
@@ -16,7 +16,7 @@
 
 #ifdef CONFIG_X86_64
 # include <asm/mmconfig.h>
-# include <asm/cacheflush.h>
+# include <asm/set_memory.h>
 #endif
 
 #include "cpu.h"
@@ -799,8 +799,9 @@ static void init_amd(struct cpuinfo_x86 *c)
                if (cpu_has(c, X86_FEATURE_3DNOW) || cpu_has(c, X86_FEATURE_LM))
                        set_cpu_cap(c, X86_FEATURE_3DNOWPREFETCH);
 
-       /* AMD CPUs don't reset SS attributes on SYSRET */
-       set_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS);
+       /* AMD CPUs don't reset SS attributes on SYSRET, Xen does. */
+       if (!cpu_has(c, X86_FEATURE_XENPV))
+               set_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS);
 }
 
 #ifdef CONFIG_X86_32
index a44ef52184df0c6d2fae5eba3ecbf21f9098e067..0af86d9242da0f6882f1f5252dfa659038c627ac 100644 (file)
@@ -17,7 +17,7 @@
 #include <asm/paravirt.h>
 #include <asm/alternative.h>
 #include <asm/pgtable.h>
-#include <asm/cacheflush.h>
+#include <asm/set_memory.h>
 
 void __init check_bugs(void)
 {
index 7889ae492af020ee2ab546f19b9fe4b509b09d3a..45db4d2ebd0118e666c205185b9162d13e33316e 100644 (file)
@@ -10,7 +10,7 @@
  *  Author: Peter Oruba <peter.oruba@amd.com>
  *
  *  Based on work by:
- *  Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
+ *  Tigran Aivazian <aivazian.tigran@gmail.com>
  *
  *  early loader:
  *  Copyright (C) 2013 Advanced Micro Devices, Inc.
@@ -352,8 +352,6 @@ void reload_ucode_amd(void)
        u32 rev, dummy;
 
        mc = (struct microcode_amd *)amd_ucode_patch;
-       if (!mc)
-               return;
 
        rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
 
index b4a4cd39b35829c73c20be28cda3bb58201d0f55..e53d3c909840b42669d4b9705cc2cf1afcdc9b3d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * CPU Microcode Update Driver for Linux
  *
- * Copyright (C) 2000-2006 Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
+ * Copyright (C) 2000-2006 Tigran Aivazian <aivazian.tigran@gmail.com>
  *           2006      Shaohua Li <shaohua.li@intel.com>
  *           2013-2016 Borislav Petkov <bp@alien8.de>
  *
index 8325d8a09ab0768dd08156b8e4c5b755b78c10f9..afdfd237b59fd7722f4b595dbde17a940096ca81 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Intel CPU Microcode Update Driver for Linux
  *
- * Copyright (C) 2000-2006 Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
+ * Copyright (C) 2000-2006 Tigran Aivazian <aivazian.tigran@gmail.com>
  *              2006 Shaohua Li <shaohua.li@intel.com>
  *
  * Intel CPU microcode early update for Linux
index c2f8dde3255ca706f613ff662d313ef1f06aa97d..d5d44c452624c88e3abb5c75e68d00b55fee6019 100644 (file)
@@ -90,6 +90,7 @@ static void fpu__init_system_early_generic(struct cpuinfo_x86 *c)
  * Boot time FPU feature detection code:
  */
 unsigned int mxcsr_feature_mask __read_mostly = 0xffffffffu;
+EXPORT_SYMBOL_GPL(mxcsr_feature_mask);
 
 static void __init fpu__init_system_mxcsr(void)
 {
index 8ee76dce9140323d8376974b6b1c492f11117691..0651e974dcb3a88211db1711a5969434d3163e5a 100644 (file)
@@ -24,7 +24,7 @@
 
 #include <trace/syscall.h>
 
-#include <asm/cacheflush.h>
+#include <asm/set_memory.h>
 #include <asm/kprobes.h>
 #include <asm/ftrace.h>
 #include <asm/nops.h>
index be22f5a2192e358153610ebdf95a823da1ea8e5f..4e3b8a587c882ee8a0e2c39678fde12738c7752c 100644 (file)
@@ -418,6 +418,7 @@ struct legacy_pic default_legacy_pic = {
 };
 
 struct legacy_pic *legacy_pic = &default_legacy_pic;
+EXPORT_SYMBOL(legacy_pic);
 
 static int __init i8259A_init_ops(void)
 {
index 19e1f2a6d7b0a74cbae05aaca928d6194d7e0f10..5b2bbfbb371284942b2ce95a3b2495eb9ecc8981 100644 (file)
@@ -61,6 +61,7 @@
 #include <asm/alternative.h>
 #include <asm/insn.h>
 #include <asm/debugreg.h>
+#include <asm/set_memory.h>
 
 #include "common.h"
 
index 9aadff3d0902a910afeb2ea8a82e4bef53e3a299..901c640d152f7cb76529c38e5ab5576ca2d07c9f 100644 (file)
@@ -37,6 +37,7 @@
 #include <asm/alternative.h>
 #include <asm/insn.h>
 #include <asm/debugreg.h>
+#include <asm/set_memory.h>
 
 #include "common.h"
 
index 5f43cec296c5c38dc28a2a0c0e43aee91ee89934..8c53c5d7a1bc5e9733e4b4da8ed1a760ab138dbe 100644 (file)
@@ -23,7 +23,7 @@
 #include <asm/io_apic.h>
 #include <asm/cpufeature.h>
 #include <asm/desc.h>
-#include <asm/cacheflush.h>
+#include <asm/set_memory.h>
 #include <asm/debugreg.h>
 
 static void set_idt(void *newidt, __u16 limit)
index 085c3b300d32e15faeb297028ad45ddb14513dd3..6f5ca4ebe6e5dd834781c678ffd39e4afd688395 100644 (file)
@@ -27,6 +27,7 @@
 #include <asm/debugreg.h>
 #include <asm/kexec-bzimage64.h>
 #include <asm/setup.h>
+#include <asm/set_memory.h>
 
 #ifdef CONFIG_KEXEC_FILE
 static struct kexec_file_ops *kexec_file_loaders[] = {
@@ -113,7 +114,7 @@ static int init_pgtable(struct kimage *image, unsigned long start_pgtable)
        struct x86_mapping_info info = {
                .alloc_pgt_page = alloc_pgt_page,
                .context        = image,
-               .pmd_flag       = __PAGE_KERNEL_LARGE_EXEC,
+               .page_flag      = __PAGE_KERNEL_LARGE_EXEC,
        };
        unsigned long mstart, mend;
        pgd_t *level4p;
@@ -122,6 +123,10 @@ static int init_pgtable(struct kimage *image, unsigned long start_pgtable)
 
        level4p = (pgd_t *)__va(start_pgtable);
        clear_page(level4p);
+
+       if (direct_gbpages)
+               info.direct_gbpages = true;
+
        for (i = 0; i < nr_pfn_mapped; i++) {
                mstart = pfn_mapped[i].start << PAGE_SHIFT;
                mend   = pfn_mapped[i].end << PAGE_SHIFT;
index 477ae806c2fa71f425ff56a8b75b1306dfcf7535..f67bd3205df7aafd61d22d55b0a4f4573bf90b9e 100644 (file)
@@ -85,7 +85,7 @@ void *module_alloc(unsigned long size)
 
        p = __vmalloc_node_range(size, MODULE_ALIGN,
                                    MODULES_VADDR + get_module_load_offset(),
-                                   MODULES_END, GFP_KERNEL | __GFP_HIGHMEM,
+                                   MODULES_END, GFP_KERNEL,
                                    PAGE_KERNEL_EXEC, 0, NUMA_NO_NODE,
                                    __builtin_return_address(0));
        if (p && (kasan_module_alloc(p, size) < 0)) {
index 603a1669a2ecf2ba62f0b24bee93955296a9f97c..0b4d3c686b1ef94463c8caabce01e38404d1b8c1 100644 (file)
@@ -1225,6 +1225,21 @@ void __init setup_arch(char **cmdline_p)
 
        kasan_init();
 
+#ifdef CONFIG_X86_32
+       /* sync back kernel address range */
+       clone_pgd_range(initial_page_table + KERNEL_PGD_BOUNDARY,
+                       swapper_pg_dir     + KERNEL_PGD_BOUNDARY,
+                       KERNEL_PGD_PTRS);
+
+       /*
+        * sync back low identity map too.  It is used for example
+        * in the 32-bit EFI stub.
+        */
+       clone_pgd_range(initial_page_table,
+                       swapper_pg_dir     + KERNEL_PGD_BOUNDARY,
+                       min(KERNEL_PGD_PTRS, KERNEL_PGD_BOUNDARY));
+#endif
+
        tboot_probe();
 
        map_vsyscall();
index bb1e8cc0bc84816b8976dec088d3c18b038f8c01..10edd1e69a68bffcc7ee22ef220b25c24cadfc62 100644 (file)
@@ -291,11 +291,11 @@ void __init setup_per_cpu_areas(void)
 
 #ifdef CONFIG_X86_32
        /*
-        * Sync back kernel address range.  We want to make sure that
-        * all kernel mappings, including percpu mappings, are available
-        * in the smpboot asm.  We can't reliably pick up percpu
-        * mappings using vmalloc_fault(), because exception dispatch
-        * needs percpu data.
+        * Sync back kernel address range again.  We already did this in
+        * setup_arch(), but percpu data also needs to be available in
+        * the smpboot asm.  We can't reliably pick up percpu mappings
+        * using vmalloc_fault(), because exception dispatch needs
+        * percpu data.
         */
        clone_pgd_range(initial_page_table + KERNEL_PGD_BOUNDARY,
                        swapper_pg_dir     + KERNEL_PGD_BOUNDARY,
index d4c8011a22937ffe9230cbef97ae8bc70f0f4c82..4b17240599093a6ec34c45e053ae665050d18e14 100644 (file)
@@ -514,6 +514,9 @@ int tboot_force_iommu(void)
        if (!tboot_enabled())
                return 0;
 
+       if (!intel_iommu_tboot_noforce)
+               return 1;
+
        if (no_iommu || swiotlb || dmar_disabled)
                pr_warning("Forcing Intel-IOMMU to enabled\n");
 
index c25cfaf584e7285c10d23ee8d9240f22b7c94628..0816ab2e8adcae2b45f83c95c51e8b95a245b07e 100644 (file)
@@ -4173,7 +4173,7 @@ static int check_dr_write(struct x86_emulate_ctxt *ctxt)
 
 static int check_svme(struct x86_emulate_ctxt *ctxt)
 {
-       u64 efer;
+       u64 efer = 0;
 
        ctxt->ops->get_msr(ctxt, MSR_EFER, &efer);
 
index 9fa5b816496199d00c437707a45074f14a859150..c329d28949056e2d6ad4688e411c5644b81e4d68 100644 (file)
@@ -177,8 +177,8 @@ static void recalculate_apic_map(struct kvm *kvm)
                if (kvm_apic_present(vcpu))
                        max_id = max(max_id, kvm_x2apic_id(vcpu->arch.apic));
 
-       new = kvm_kvzalloc(sizeof(struct kvm_apic_map) +
-                          sizeof(struct kvm_lapic *) * ((u64)max_id + 1));
+       new = kvzalloc(sizeof(struct kvm_apic_map) +
+                          sizeof(struct kvm_lapic *) * ((u64)max_id + 1), GFP_KERNEL);
 
        if (!new)
                goto out;
index 558676538fca3c213d9e360f39e03ef15e2b1d47..5d3376f677949067f39c5e29fca2f3aceb7880bc 100644 (file)
@@ -1498,6 +1498,21 @@ void kvm_arch_mmu_enable_log_dirty_pt_masked(struct kvm *kvm,
                kvm_mmu_write_protect_pt_masked(kvm, slot, gfn_offset, mask);
 }
 
+/**
+ * kvm_arch_write_log_dirty - emulate dirty page logging
+ * @vcpu: Guest mode vcpu
+ *
+ * Emulate arch specific page modification logging for the
+ * nested hypervisor
+ */
+int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu)
+{
+       if (kvm_x86_ops->write_log_dirty)
+               return kvm_x86_ops->write_log_dirty(vcpu);
+
+       return 0;
+}
+
 bool kvm_mmu_slot_gfn_write_protect(struct kvm *kvm,
                                    struct kvm_memory_slot *slot, u64 gfn)
 {
index d8ccb32f7308ab3e2d1955b6dbd11203716f03a2..27975807cc64fcae7bccbb53eecab35c3f0c64e2 100644 (file)
@@ -202,4 +202,5 @@ void kvm_mmu_gfn_disallow_lpage(struct kvm_memory_slot *slot, gfn_t gfn);
 void kvm_mmu_gfn_allow_lpage(struct kvm_memory_slot *slot, gfn_t gfn);
 bool kvm_mmu_slot_gfn_write_protect(struct kvm *kvm,
                                    struct kvm_memory_slot *slot, u64 gfn);
+int kvm_arch_write_log_dirty(struct kvm_vcpu *vcpu);
 #endif
index 60168cdd05463e2e18c993e20dfdeed7986808ce..ea67dc876316487f4fff2bf2e6a5193510086aee 100644 (file)
@@ -40,8 +40,8 @@ int kvm_page_track_create_memslot(struct kvm_memory_slot *slot,
        int  i;
 
        for (i = 0; i < KVM_PAGE_TRACK_MAX; i++) {
-               slot->arch.gfn_track[i] = kvm_kvzalloc(npages *
-                                           sizeof(*slot->arch.gfn_track[i]));
+               slot->arch.gfn_track[i] = kvzalloc(npages *
+                                           sizeof(*slot->arch.gfn_track[i]), GFP_KERNEL);
                if (!slot->arch.gfn_track[i])
                        goto track_free;
        }
index 314d2071b3376e697163dc5a20ce2bbb11953ed0..b0454c7e4cffe6c99e9619892a82afcd5d7ab70e 100644 (file)
@@ -226,6 +226,10 @@ static int FNAME(update_accessed_dirty_bits)(struct kvm_vcpu *vcpu,
                if (level == walker->level && write_fault &&
                                !(pte & PT_GUEST_DIRTY_MASK)) {
                        trace_kvm_mmu_set_dirty_bit(table_gfn, index, sizeof(pte));
+#if PTTYPE == PTTYPE_EPT
+                       if (kvm_arch_write_log_dirty(vcpu))
+                               return -EINVAL;
+#endif
                        pte |= PT_GUEST_DIRTY_MASK;
                }
                if (pte == orig_pte)
@@ -279,11 +283,13 @@ static int FNAME(walk_addr_generic)(struct guest_walker *walker,
        pt_element_t pte;
        pt_element_t __user *uninitialized_var(ptep_user);
        gfn_t table_gfn;
-       unsigned index, pt_access, pte_access, accessed_dirty, pte_pkey;
+       u64 pt_access, pte_access;
+       unsigned index, accessed_dirty, pte_pkey;
        unsigned nested_access;
        gpa_t pte_gpa;
        bool have_ad;
        int offset;
+       u64 walk_nx_mask = 0;
        const int write_fault = access & PFERR_WRITE_MASK;
        const int user_fault  = access & PFERR_USER_MASK;
        const int fetch_fault = access & PFERR_FETCH_MASK;
@@ -298,6 +304,7 @@ retry_walk:
        have_ad       = PT_HAVE_ACCESSED_DIRTY(mmu);
 
 #if PTTYPE == 64
+       walk_nx_mask = 1ULL << PT64_NX_SHIFT;
        if (walker->level == PT32E_ROOT_LEVEL) {
                pte = mmu->get_pdptr(vcpu, (addr >> 30) & 3);
                trace_kvm_mmu_paging_element(pte, walker->level);
@@ -309,8 +316,6 @@ retry_walk:
        walker->max_level = walker->level;
        ASSERT(!(is_long_mode(vcpu) && !is_pae(vcpu)));
 
-       accessed_dirty = have_ad ? PT_GUEST_ACCESSED_MASK : 0;
-
        /*
         * FIXME: on Intel processors, loads of the PDPTE registers for PAE paging
         * by the MOV to CR instruction are treated as reads and do not cause the
@@ -318,14 +323,14 @@ retry_walk:
         */
        nested_access = (have_ad ? PFERR_WRITE_MASK : 0) | PFERR_USER_MASK;
 
-       pt_access = pte_access = ACC_ALL;
+       pte_access = ~0;
        ++walker->level;
 
        do {
                gfn_t real_gfn;
                unsigned long host_addr;
 
-               pt_access &= pte_access;
+               pt_access = pte_access;
                --walker->level;
 
                index = PT_INDEX(addr, walker->level);
@@ -367,6 +372,12 @@ retry_walk:
 
                trace_kvm_mmu_paging_element(pte, walker->level);
 
+               /*
+                * Inverting the NX it lets us AND it like other
+                * permission bits.
+                */
+               pte_access = pt_access & (pte ^ walk_nx_mask);
+
                if (unlikely(!FNAME(is_present_gpte)(pte)))
                        goto error;
 
@@ -375,14 +386,16 @@ retry_walk:
                        goto error;
                }
 
-               accessed_dirty &= pte;
-               pte_access = pt_access & FNAME(gpte_access)(vcpu, pte);
-
                walker->ptes[walker->level - 1] = pte;
        } while (!is_last_gpte(mmu, walker->level, pte));
 
        pte_pkey = FNAME(gpte_pkeys)(vcpu, pte);
-       errcode = permission_fault(vcpu, mmu, pte_access, pte_pkey, access);
+       accessed_dirty = have_ad ? pte_access & PT_GUEST_ACCESSED_MASK : 0;
+
+       /* Convert to ACC_*_MASK flags for struct guest_walker.  */
+       walker->pt_access = FNAME(gpte_access)(vcpu, pt_access ^ walk_nx_mask);
+       walker->pte_access = FNAME(gpte_access)(vcpu, pte_access ^ walk_nx_mask);
+       errcode = permission_fault(vcpu, mmu, walker->pte_access, pte_pkey, access);
        if (unlikely(errcode))
                goto error;
 
@@ -399,7 +412,7 @@ retry_walk:
        walker->gfn = real_gpa >> PAGE_SHIFT;
 
        if (!write_fault)
-               FNAME(protect_clean_gpte)(mmu, &pte_access, pte);
+               FNAME(protect_clean_gpte)(mmu, &walker->pte_access, pte);
        else
                /*
                 * On a write fault, fold the dirty bit into accessed_dirty.
@@ -417,10 +430,8 @@ retry_walk:
                        goto retry_walk;
        }
 
-       walker->pt_access = pt_access;
-       walker->pte_access = pte_access;
        pgprintk("%s: pte %llx pte_access %x pt_access %x\n",
-                __func__, (u64)pte, pte_access, pt_access);
+                __func__, (u64)pte, walker->pte_access, walker->pt_access);
        return 1;
 
 error:
@@ -448,7 +459,7 @@ error:
         */
        if (!(errcode & PFERR_RSVD_MASK)) {
                vcpu->arch.exit_qualification &= 0x187;
-               vcpu->arch.exit_qualification |= ((pt_access & pte) & 0x7) << 3;
+               vcpu->arch.exit_qualification |= (pte_access & 0x7) << 3;
        }
 #endif
        walker->fault.address = addr;
index 9d4a8504a95a3ba687a5bd34b8ef3c58d4a5f2db..5ab4a364348e3c10987c33203be4ff6fa97e1e73 100644 (file)
@@ -294,7 +294,7 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
                        ((u64)1 << edx.split.bit_width_fixed) - 1;
        }
 
-       pmu->global_ctrl = ((1 << pmu->nr_arch_gp_counters) - 1) |
+       pmu->global_ctrl = ((1ull << pmu->nr_arch_gp_counters) - 1) |
                (((1ull << pmu->nr_arch_fixed_counters) - 1) << INTEL_PMC_IDX_FIXED);
        pmu->global_ctrl_mask = ~pmu->global_ctrl;
 
index c27ac6923a18463751d153626f54413f9615201e..183ddb235fb48658028433d451db75d554152c54 100644 (file)
@@ -1272,7 +1272,8 @@ static void init_vmcb(struct vcpu_svm *svm)
 
 }
 
-static u64 *avic_get_physical_id_entry(struct kvm_vcpu *vcpu, int index)
+static u64 *avic_get_physical_id_entry(struct kvm_vcpu *vcpu,
+                                      unsigned int index)
 {
        u64 *avic_physical_id_table;
        struct kvm_arch *vm_data = &vcpu->kvm->arch;
index c5fd459c404367405f36d728951982322bc5ada6..72f78396bc0960968161b66ccee00c42fa203fb7 100644 (file)
@@ -248,6 +248,7 @@ struct __packed vmcs12 {
        u64 xss_exit_bitmap;
        u64 guest_physical_address;
        u64 vmcs_link_pointer;
+       u64 pml_address;
        u64 guest_ia32_debugctl;
        u64 guest_ia32_pat;
        u64 guest_ia32_efer;
@@ -369,6 +370,7 @@ struct __packed vmcs12 {
        u16 guest_ldtr_selector;
        u16 guest_tr_selector;
        u16 guest_intr_status;
+       u16 guest_pml_index;
        u16 host_es_selector;
        u16 host_cs_selector;
        u16 host_ss_selector;
@@ -407,6 +409,7 @@ struct nested_vmx {
        /* Has the level1 guest done vmxon? */
        bool vmxon;
        gpa_t vmxon_ptr;
+       bool pml_full;
 
        /* The guest-physical address of the current VMCS L1 keeps for L2 */
        gpa_t current_vmptr;
@@ -742,6 +745,7 @@ static const unsigned short vmcs_field_to_offset_table[] = {
        FIELD(GUEST_LDTR_SELECTOR, guest_ldtr_selector),
        FIELD(GUEST_TR_SELECTOR, guest_tr_selector),
        FIELD(GUEST_INTR_STATUS, guest_intr_status),
+       FIELD(GUEST_PML_INDEX, guest_pml_index),
        FIELD(HOST_ES_SELECTOR, host_es_selector),
        FIELD(HOST_CS_SELECTOR, host_cs_selector),
        FIELD(HOST_SS_SELECTOR, host_ss_selector),
@@ -767,6 +771,7 @@ static const unsigned short vmcs_field_to_offset_table[] = {
        FIELD64(XSS_EXIT_BITMAP, xss_exit_bitmap),
        FIELD64(GUEST_PHYSICAL_ADDRESS, guest_physical_address),
        FIELD64(VMCS_LINK_POINTER, vmcs_link_pointer),
+       FIELD64(PML_ADDRESS, pml_address),
        FIELD64(GUEST_IA32_DEBUGCTL, guest_ia32_debugctl),
        FIELD64(GUEST_IA32_PAT, guest_ia32_pat),
        FIELD64(GUEST_IA32_EFER, guest_ia32_efer),
@@ -1314,6 +1319,11 @@ static inline bool report_flexpriority(void)
        return flexpriority_enabled;
 }
 
+static inline unsigned nested_cpu_vmx_misc_cr3_count(struct kvm_vcpu *vcpu)
+{
+       return vmx_misc_cr3_count(to_vmx(vcpu)->nested.nested_vmx_misc_low);
+}
+
 static inline bool nested_cpu_has(struct vmcs12 *vmcs12, u32 bit)
 {
        return vmcs12->cpu_based_vm_exec_control & bit;
@@ -1348,6 +1358,11 @@ static inline bool nested_cpu_has_xsaves(struct vmcs12 *vmcs12)
                vmx_xsaves_supported();
 }
 
+static inline bool nested_cpu_has_pml(struct vmcs12 *vmcs12)
+{
+       return nested_cpu_has2(vmcs12, SECONDARY_EXEC_ENABLE_PML);
+}
+
 static inline bool nested_cpu_has_virt_x2apic_mode(struct vmcs12 *vmcs12)
 {
        return nested_cpu_has2(vmcs12, SECONDARY_EXEC_VIRTUALIZE_X2APIC_MODE);
@@ -2751,8 +2766,11 @@ static void nested_vmx_setup_ctls_msrs(struct vcpu_vmx *vmx)
                vmx->nested.nested_vmx_ept_caps |= VMX_EPT_EXTENT_GLOBAL_BIT |
                        VMX_EPT_EXTENT_CONTEXT_BIT | VMX_EPT_2MB_PAGE_BIT |
                        VMX_EPT_1GB_PAGE_BIT;
-              if (enable_ept_ad_bits)
+               if (enable_ept_ad_bits) {
+                       vmx->nested.nested_vmx_secondary_ctls_high |=
+                               SECONDARY_EXEC_ENABLE_PML;
                       vmx->nested.nested_vmx_ept_caps |= VMX_EPT_AD_BIT;
+               }
        } else
                vmx->nested.nested_vmx_ept_caps = 0;
 
@@ -6486,7 +6504,7 @@ static __init int hardware_setup(void)
                enable_ept_ad_bits = 0;
        }
 
-       if (!cpu_has_vmx_ept_ad_bits())
+       if (!cpu_has_vmx_ept_ad_bits() || !enable_ept)
                enable_ept_ad_bits = 0;
 
        if (!cpu_has_vmx_unrestricted_guest())
@@ -8114,7 +8132,7 @@ static bool nested_vmx_exit_handled(struct kvm_vcpu *vcpu)
        case EXIT_REASON_PREEMPTION_TIMER:
                return false;
        case EXIT_REASON_PML_FULL:
-               /* We don't expose PML support to L1. */
+               /* We emulate PML support to L1. */
                return false;
        default:
                return true;
@@ -9364,13 +9382,20 @@ static void nested_ept_inject_page_fault(struct kvm_vcpu *vcpu,
                struct x86_exception *fault)
 {
        struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
+       struct vcpu_vmx *vmx = to_vmx(vcpu);
        u32 exit_reason;
+       unsigned long exit_qualification = vcpu->arch.exit_qualification;
 
-       if (fault->error_code & PFERR_RSVD_MASK)
+       if (vmx->nested.pml_full) {
+               exit_reason = EXIT_REASON_PML_FULL;
+               vmx->nested.pml_full = false;
+               exit_qualification &= INTR_INFO_UNBLOCK_NMI;
+       } else if (fault->error_code & PFERR_RSVD_MASK)
                exit_reason = EXIT_REASON_EPT_MISCONFIG;
        else
                exit_reason = EXIT_REASON_EPT_VIOLATION;
-       nested_vmx_vmexit(vcpu, exit_reason, 0, vcpu->arch.exit_qualification);
+
+       nested_vmx_vmexit(vcpu, exit_reason, 0, exit_qualification);
        vmcs12->guest_physical_address = fault->address;
 }
 
@@ -9713,6 +9738,22 @@ static int nested_vmx_check_msr_switch_controls(struct kvm_vcpu *vcpu,
        return 0;
 }
 
+static int nested_vmx_check_pml_controls(struct kvm_vcpu *vcpu,
+                                        struct vmcs12 *vmcs12)
+{
+       u64 address = vmcs12->pml_address;
+       int maxphyaddr = cpuid_maxphyaddr(vcpu);
+
+       if (nested_cpu_has2(vmcs12, SECONDARY_EXEC_ENABLE_PML)) {
+               if (!nested_cpu_has_ept(vmcs12) ||
+                   !IS_ALIGNED(address, 4096)  ||
+                   address >> maxphyaddr)
+                       return -EINVAL;
+       }
+
+       return 0;
+}
+
 static int nested_vmx_msr_check_common(struct kvm_vcpu *vcpu,
                                       struct vmx_msr_entry *e)
 {
@@ -9886,7 +9927,7 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
                          bool from_vmentry, u32 *entry_failure_code)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
-       u32 exec_control;
+       u32 exec_control, vmcs12_exec_ctrl;
 
        vmcs_write16(GUEST_ES_SELECTOR, vmcs12->guest_es_selector);
        vmcs_write16(GUEST_CS_SELECTOR, vmcs12->guest_cs_selector);
@@ -10017,8 +10058,11 @@ static int prepare_vmcs02(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
                                  SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY |
                                  SECONDARY_EXEC_APIC_REGISTER_VIRT);
                if (nested_cpu_has(vmcs12,
-                               CPU_BASED_ACTIVATE_SECONDARY_CONTROLS))
-                       exec_control |= vmcs12->secondary_vm_exec_control;
+                                  CPU_BASED_ACTIVATE_SECONDARY_CONTROLS)) {
+                       vmcs12_exec_ctrl = vmcs12->secondary_vm_exec_control &
+                               ~SECONDARY_EXEC_ENABLE_PML;
+                       exec_control |= vmcs12_exec_ctrl;
+               }
 
                if (exec_control & SECONDARY_EXEC_VIRTUAL_INTR_DELIVERY) {
                        vmcs_write64(EOI_EXIT_BITMAP0,
@@ -10248,6 +10292,9 @@ static int check_vmentry_prereqs(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
        if (nested_vmx_check_msr_switch_controls(vcpu, vmcs12))
                return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
 
+       if (nested_vmx_check_pml_controls(vcpu, vmcs12))
+               return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
+
        if (!vmx_control_verify(vmcs12->cpu_based_vm_exec_control,
                                vmx->nested.nested_vmx_procbased_ctls_low,
                                vmx->nested.nested_vmx_procbased_ctls_high) ||
@@ -10266,6 +10313,9 @@ static int check_vmentry_prereqs(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
                                vmx->nested.nested_vmx_entry_ctls_high))
                return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
 
+       if (vmcs12->cr3_target_count > nested_cpu_vmx_misc_cr3_count(vcpu))
+               return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
+
        if (!nested_host_cr0_valid(vcpu, vmcs12->host_cr0) ||
            !nested_host_cr4_valid(vcpu, vmcs12->host_cr4) ||
            !nested_cr3_valid(vcpu, vmcs12->host_cr3))
@@ -11143,6 +11193,46 @@ static void vmx_flush_log_dirty(struct kvm *kvm)
        kvm_flush_pml_buffers(kvm);
 }
 
+static int vmx_write_pml_buffer(struct kvm_vcpu *vcpu)
+{
+       struct vmcs12 *vmcs12;
+       struct vcpu_vmx *vmx = to_vmx(vcpu);
+       gpa_t gpa;
+       struct page *page = NULL;
+       u64 *pml_address;
+
+       if (is_guest_mode(vcpu)) {
+               WARN_ON_ONCE(vmx->nested.pml_full);
+
+               /*
+                * Check if PML is enabled for the nested guest.
+                * Whether eptp bit 6 is set is already checked
+                * as part of A/D emulation.
+                */
+               vmcs12 = get_vmcs12(vcpu);
+               if (!nested_cpu_has_pml(vmcs12))
+                       return 0;
+
+               if (vmcs12->guest_pml_index >= PML_ENTITY_NUM) {
+                       vmx->nested.pml_full = true;
+                       return 1;
+               }
+
+               gpa = vmcs_read64(GUEST_PHYSICAL_ADDRESS) & ~0xFFFull;
+
+               page = nested_get_page(vcpu, vmcs12->pml_address);
+               if (!page)
+                       return 0;
+
+               pml_address = kmap(page);
+               pml_address[vmcs12->guest_pml_index--] = gpa;
+               kunmap(page);
+               nested_release_page_clean(page);
+       }
+
+       return 0;
+}
+
 static void vmx_enable_log_dirty_pt_masked(struct kvm *kvm,
                                           struct kvm_memory_slot *memslot,
                                           gfn_t offset, unsigned long mask)
@@ -11502,6 +11592,7 @@ static struct kvm_x86_ops vmx_x86_ops __ro_after_init = {
        .slot_disable_log_dirty = vmx_slot_disable_log_dirty,
        .flush_log_dirty = vmx_flush_log_dirty,
        .enable_log_dirty_pt_masked = vmx_enable_log_dirty_pt_masked,
+       .write_log_dirty = vmx_write_pml_buffer,
 
        .pre_block = vmx_pre_block,
        .post_block = vmx_post_block,
index b38a302858a063d873395b8f14743c3e9bb0e588..02363e37d4a61e8271d7fed0a8c534e9dd90f264 100644 (file)
@@ -1763,6 +1763,7 @@ u64 get_kvmclock_ns(struct kvm *kvm)
 {
        struct kvm_arch *ka = &kvm->arch;
        struct pvclock_vcpu_time_info hv_clock;
+       u64 ret;
 
        spin_lock(&ka->pvclock_gtod_sync_lock);
        if (!ka->use_master_clock) {
@@ -1774,10 +1775,17 @@ u64 get_kvmclock_ns(struct kvm *kvm)
        hv_clock.system_time = ka->master_kernel_ns + ka->kvmclock_offset;
        spin_unlock(&ka->pvclock_gtod_sync_lock);
 
+       /* both __this_cpu_read() and rdtsc() should be on the same cpu */
+       get_cpu();
+
        kvm_get_time_scale(NSEC_PER_SEC, __this_cpu_read(cpu_tsc_khz) * 1000LL,
                           &hv_clock.tsc_shift,
                           &hv_clock.tsc_to_system_mul);
-       return __pvclock_read_cycles(&hv_clock, rdtsc());
+       ret = __pvclock_read_cycles(&hv_clock, rdtsc());
+
+       put_cpu();
+
+       return ret;
 }
 
 static void kvm_setup_pvclock_page(struct kvm_vcpu *v)
@@ -3288,11 +3296,14 @@ static void kvm_vcpu_ioctl_x86_get_xsave(struct kvm_vcpu *vcpu,
        }
 }
 
+#define XSAVE_MXCSR_OFFSET 24
+
 static int kvm_vcpu_ioctl_x86_set_xsave(struct kvm_vcpu *vcpu,
                                        struct kvm_xsave *guest_xsave)
 {
        u64 xstate_bv =
                *(u64 *)&guest_xsave->region[XSAVE_HDR_OFFSET / sizeof(u32)];
+       u32 mxcsr = *(u32 *)&guest_xsave->region[XSAVE_MXCSR_OFFSET / sizeof(u32)];
 
        if (boot_cpu_has(X86_FEATURE_XSAVE)) {
                /*
@@ -3300,11 +3311,13 @@ static int kvm_vcpu_ioctl_x86_set_xsave(struct kvm_vcpu *vcpu,
                 * CPUID leaf 0xD, index 0, EDX:EAX.  This is for compatibility
                 * with old userspace.
                 */
-               if (xstate_bv & ~kvm_supported_xcr0())
+               if (xstate_bv & ~kvm_supported_xcr0() ||
+                       mxcsr & ~mxcsr_feature_mask)
                        return -EINVAL;
                load_xsave(vcpu, (u8 *)guest_xsave->region);
        } else {
-               if (xstate_bv & ~XFEATURE_MASK_FPSSE)
+               if (xstate_bv & ~XFEATURE_MASK_FPSSE ||
+                       mxcsr & ~mxcsr_feature_mask)
                        return -EINVAL;
                memcpy(&vcpu->arch.guest_fpu.state.fxsave,
                        guest_xsave->region, sizeof(struct fxregs_state));
@@ -4818,16 +4831,20 @@ emul_write:
 
 static int kernel_pio(struct kvm_vcpu *vcpu, void *pd)
 {
-       /* TODO: String I/O for in kernel device */
-       int r;
+       int r = 0, i;
 
-       if (vcpu->arch.pio.in)
-               r = kvm_io_bus_read(vcpu, KVM_PIO_BUS, vcpu->arch.pio.port,
-                                   vcpu->arch.pio.size, pd);
-       else
-               r = kvm_io_bus_write(vcpu, KVM_PIO_BUS,
-                                    vcpu->arch.pio.port, vcpu->arch.pio.size,
-                                    pd);
+       for (i = 0; i < vcpu->arch.pio.count; i++) {
+               if (vcpu->arch.pio.in)
+                       r = kvm_io_bus_read(vcpu, KVM_PIO_BUS, vcpu->arch.pio.port,
+                                           vcpu->arch.pio.size, pd);
+               else
+                       r = kvm_io_bus_write(vcpu, KVM_PIO_BUS,
+                                            vcpu->arch.pio.port, vcpu->arch.pio.size,
+                                            pd);
+               if (r)
+                       break;
+               pd += vcpu->arch.pio.size;
+       }
        return r;
 }
 
@@ -4865,6 +4882,8 @@ static int emulator_pio_in_emulated(struct x86_emulate_ctxt *ctxt,
        if (vcpu->arch.pio.count)
                goto data_avail;
 
+       memset(vcpu->arch.pio_data, 0, size * count);
+
        ret = emulator_pio_in_out(vcpu, size, port, val, count, true);
        if (ret) {
 data_avail:
@@ -5048,6 +5067,8 @@ static bool emulator_get_segment(struct x86_emulate_ctxt *ctxt, u16 *selector,
 
        if (var.unusable) {
                memset(desc, 0, sizeof(*desc));
+               if (base3)
+                       *base3 = 0;
                return false;
        }
 
@@ -8190,13 +8211,13 @@ int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot,
                                      slot->base_gfn, level) + 1;
 
                slot->arch.rmap[i] =
-                       kvm_kvzalloc(lpages * sizeof(*slot->arch.rmap[i]));
+                       kvzalloc(lpages * sizeof(*slot->arch.rmap[i]), GFP_KERNEL);
                if (!slot->arch.rmap[i])
                        goto out_free;
                if (i == 0)
                        continue;
 
-               linfo = kvm_kvzalloc(lpages * sizeof(*linfo));
+               linfo = kvzalloc(lpages * sizeof(*linfo), GFP_KERNEL);
                if (!linfo)
                        goto out_free;
 
index 7e48807b2fa198c4e2b8e7022df2218308a41b7c..45a53dfe1859b1955fa91bad9bf1543903f1c1a8 100644 (file)
@@ -55,7 +55,7 @@ ENTRY(csum_partial_copy_generic)
        movq  %r12, 3*8(%rsp)
        movq  %r14, 4*8(%rsp)
        movq  %r13, 5*8(%rsp)
-       movq  %rbp, 6*8(%rsp)
+       movq  %r15, 6*8(%rsp)
 
        movq  %r8, (%rsp)
        movq  %r9, 1*8(%rsp)
@@ -74,7 +74,7 @@ ENTRY(csum_partial_copy_generic)
        /* main loop. clear in 64 byte blocks */
        /* r9: zero, r8: temp2, rbx: temp1, rax: sum, rcx: saved length */
        /* r11: temp3, rdx: temp4, r12 loopcnt */
-       /* r10: temp5, rbp: temp6, r14 temp7, r13 temp8 */
+       /* r10: temp5, r15: temp6, r14 temp7, r13 temp8 */
        .p2align 4
 .Lloop:
        source
@@ -89,7 +89,7 @@ ENTRY(csum_partial_copy_generic)
        source
        movq  32(%rdi), %r10
        source
-       movq  40(%rdi), %rbp
+       movq  40(%rdi), %r15
        source
        movq  48(%rdi), %r14
        source
@@ -103,7 +103,7 @@ ENTRY(csum_partial_copy_generic)
        adcq  %r11, %rax
        adcq  %rdx, %rax
        adcq  %r10, %rax
-       adcq  %rbp, %rax
+       adcq  %r15, %rax
        adcq  %r14, %rax
        adcq  %r13, %rax
 
@@ -121,7 +121,7 @@ ENTRY(csum_partial_copy_generic)
        dest
        movq %r10, 32(%rsi)
        dest
-       movq %rbp, 40(%rsi)
+       movq %r15, 40(%rsi)
        dest
        movq %r14, 48(%rsi)
        dest
@@ -203,7 +203,7 @@ ENTRY(csum_partial_copy_generic)
        movq 3*8(%rsp), %r12
        movq 4*8(%rsp), %r14
        movq 5*8(%rsp), %r13
-       movq 6*8(%rsp), %rbp
+       movq 6*8(%rsp), %r15
        addq $7*8, %rsp
        ret
 
index 5761a4f19455cd1a7a3d6678857c8aef2277a353..ab2d1d73e9e7c0deaf06f040d178baee04a2b514 100644 (file)
@@ -5,6 +5,7 @@
  * kernel starts. This file is included in the compressed kernel and
  * normally linked in the regular.
  */
+#include <asm/asm.h>
 #include <asm/kaslr.h>
 #include <asm/msr.h>
 #include <asm/archrandom.h>
@@ -79,7 +80,7 @@ unsigned long kaslr_get_random_long(const char *purpose)
        }
 
        /* Circular multiply for better bit diffusion */
-       asm("mul %3"
+       asm(_ASM_MUL "%3"
            : "=a" (random), "=d" (raw)
            : "a" (random), "rm" (mix_const));
        random += raw;
index 04210a29dd6060959745c4d974c4c99e6292786d..adab1595f4bd89ba0729db70dd21d619d93e829d 100644 (file)
@@ -13,7 +13,7 @@ static void ident_pmd_init(struct x86_mapping_info *info, pmd_t *pmd_page,
                if (pmd_present(*pmd))
                        continue;
 
-               set_pmd(pmd, __pmd((addr - info->offset) | info->pmd_flag));
+               set_pmd(pmd, __pmd((addr - info->offset) | info->page_flag));
        }
 }
 
@@ -30,6 +30,18 @@ static int ident_pud_init(struct x86_mapping_info *info, pud_t *pud_page,
                if (next > end)
                        next = end;
 
+               if (info->direct_gbpages) {
+                       pud_t pudval;
+
+                       if (pud_present(*pud))
+                               continue;
+
+                       addr &= PUD_MASK;
+                       pudval = __pud((addr - info->offset) | info->page_flag);
+                       set_pud(pud, pudval);
+                       continue;
+               }
+
                if (pud_present(*pud)) {
                        pmd = pmd_offset(pud, 0);
                        ident_pmd_init(info, pmd, addr, next);
index 138bad2fb6bcd364826f75fa2be42e09904718a6..cbc87ea9875109b79b70a17ea6c130d8803ff207 100644 (file)
@@ -5,7 +5,7 @@
 #include <linux/memblock.h>
 #include <linux/bootmem.h>     /* for max_low_pfn */
 
-#include <asm/cacheflush.h>
+#include <asm/set_memory.h>
 #include <asm/e820/api.h>
 #include <asm/init.h>
 #include <asm/page.h>
index f34d275ee2015f8d8ce43fe0b93e9cc0523e7c60..99fb83819a5ff053d17cd1fd99ccb2f153c85a4d 100644 (file)
@@ -48,7 +48,7 @@
 #include <asm/sections.h>
 #include <asm/paravirt.h>
 #include <asm/setup.h>
-#include <asm/cacheflush.h>
+#include <asm/set_memory.h>
 #include <asm/page_types.h>
 #include <asm/init.h>
 
index 745e5e183169439463984c6c9e09085bc6b41b0f..95651dc58e0900d3717a462d4cfe05efffc9374e 100644 (file)
@@ -50,7 +50,7 @@
 #include <asm/sections.h>
 #include <asm/kdebug.h>
 #include <asm/numa.h>
-#include <asm/cacheflush.h>
+#include <asm/set_memory.h>
 #include <asm/init.h>
 #include <asm/uv/uv.h>
 #include <asm/setup.h>
@@ -94,10 +94,10 @@ __setup("noexec32=", nonx32_setup);
  */
 void sync_global_pgds(unsigned long start, unsigned long end)
 {
-       unsigned long address;
+       unsigned long addr;
 
-       for (address = start; address <= end; address += PGDIR_SIZE) {
-               pgd_t *pgd_ref = pgd_offset_k(address);
+       for (addr = start; addr <= end; addr = ALIGN(addr + 1, PGDIR_SIZE)) {
+               pgd_t *pgd_ref = pgd_offset_k(addr);
                const p4d_t *p4d_ref;
                struct page *page;
 
@@ -106,7 +106,7 @@ void sync_global_pgds(unsigned long start, unsigned long end)
                 * handle synchonization on p4d level.
                 */
                BUILD_BUG_ON(pgd_none(*pgd_ref));
-               p4d_ref = p4d_offset(pgd_ref, address);
+               p4d_ref = p4d_offset(pgd_ref, addr);
 
                if (p4d_none(*p4d_ref))
                        continue;
@@ -117,8 +117,8 @@ void sync_global_pgds(unsigned long start, unsigned long end)
                        p4d_t *p4d;
                        spinlock_t *pgt_lock;
 
-                       pgd = (pgd_t *)page_address(page) + pgd_index(address);
-                       p4d = p4d_offset(pgd, address);
+                       pgd = (pgd_t *)page_address(page) + pgd_index(addr);
+                       p4d = p4d_offset(pgd, addr);
                        /* the pgt_lock only for Xen */
                        pgt_lock = &pgd_page_get_mm(page)->page_table_lock;
                        spin_lock(pgt_lock);
index e4f7b25df18ea310d689923bef6f653aca53fe5e..bbc558b88a8842aaa0620021c0552faaf4b56ada 100644 (file)
@@ -14,7 +14,7 @@
 #include <linux/vmalloc.h>
 #include <linux/mmiotrace.h>
 
-#include <asm/cacheflush.h>
+#include <asm/set_memory.h>
 #include <asm/e820/api.h>
 #include <asm/fixmap.h>
 #include <asm/pgtable.h>
index 6b7ce6279133edc52912c7032d521c79aac6ae34..aca6295350f30df220c63a282cede3ccd660096d 100644 (file)
@@ -100,5 +100,6 @@ void __init initmem_init(void)
        printk(KERN_DEBUG "High memory starts at vaddr %08lx\n",
                        (ulong) pfn_to_kaddr(highstart_pfn));
 
+       __vmalloc_start_set = true;
        setup_bootmem_allocator();
 }
index 56b22fa504dfa8818ab6f301a90f712e1cf06bb9..1dcd2be4cce44aabd5659b531962f918da1b8dd3 100644 (file)
@@ -24,6 +24,7 @@
 #include <asm/pgalloc.h>
 #include <asm/proto.h>
 #include <asm/pat.h>
+#include <asm/set_memory.h>
 
 /*
  * The current flushing context - we pass it instead of 5 arguments:
index 38868adf07ea9d68e4f23b486f636575d728687c..f6ae6830b341ba4fb98f8efdb81bc03c11408773 100644 (file)
@@ -9,7 +9,7 @@
 #include <linux/mmiotrace.h>
 
 static unsigned long mmio_address;
-module_param(mmio_address, ulong, 0);
+module_param_hw(mmio_address, ulong, iomem, 0);
 MODULE_PARM_DESC(mmio_address, " Start address of the mapping of 16 kB "
                                "(or 8 MB if read_far is non-zero).");
 
index 14f840df1d9505bd43859537b0d88d66206a1608..f58939393eefe2b07cf12179f7f8ccbab33b54fc 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/filter.h>
 #include <linux/if_vlan.h>
 #include <asm/cacheflush.h>
+#include <asm/set_memory.h>
 #include <linux/bpf.h>
 
 int bpf_jit_enable __read_mostly;
index 6fa84d531f4feabb5d695dae191b61d1f79cd6b3..7b4307163eacc8f120983948c634d83c90155328 100644 (file)
@@ -406,50 +406,3 @@ void __init pcibios_resource_survey(void)
         */
        ioapic_insert_resources();
 }
-
-static const struct vm_operations_struct pci_mmap_ops = {
-       .access = generic_access_phys,
-};
-
-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
-                       enum pci_mmap_state mmap_state, int write_combine)
-{
-       unsigned long prot;
-
-       /* I/O space cannot be accessed via normal processor loads and
-        * stores on this platform.
-        */
-       if (mmap_state == pci_mmap_io)
-               return -EINVAL;
-
-       prot = pgprot_val(vma->vm_page_prot);
-
-       /*
-        * Return error if pat is not enabled and write_combine is requested.
-        * Caller can followup with UC MINUS request and add a WC mtrr if there
-        * is a free mtrr slot.
-        */
-       if (!pat_enabled() && write_combine)
-               return -EINVAL;
-
-       if (pat_enabled() && write_combine)
-               prot |= cachemode2protval(_PAGE_CACHE_MODE_WC);
-       else if (pat_enabled() || boot_cpu_data.x86 > 3)
-               /*
-                * ioremap() and ioremap_nocache() defaults to UC MINUS for now.
-                * To avoid attribute conflicts, request UC MINUS here
-                * as well.
-                */
-               prot |= cachemode2protval(_PAGE_CACHE_MODE_UC_MINUS);
-
-       vma->vm_page_prot = __pgprot(prot);
-
-       if (io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
-                              vma->vm_end - vma->vm_start,
-                              vma->vm_page_prot))
-               return -EAGAIN;
-
-       vma->vm_ops = &pci_mmap_ops;
-
-       return 0;
-}
index 29e9ba6ace9d71a000fc46133863caec101d8bff..c1bdb9edcae7cb833d4a1de58fb8b1d68046133f 100644 (file)
@@ -11,7 +11,7 @@
 #include <asm/pci_x86.h>
 #include <asm/e820/types.h>
 #include <asm/pci-functions.h>
-#include <asm/cacheflush.h>
+#include <asm/set_memory.h>
 
 /* BIOS32 signature: "_32_" */
 #define BIOS32_SIGNATURE       (('_' << 0) + ('3' << 8) + ('2' << 16) + ('_' << 24))
index a15cf815ac4ead121415f6565f522d5578df1325..7e76a4d8304bc5add30e5f86d16e4f5b423a24f6 100644 (file)
@@ -49,7 +49,7 @@
 #include <asm/efi.h>
 #include <asm/e820/api.h>
 #include <asm/time.h>
-#include <asm/cacheflush.h>
+#include <asm/set_memory.h>
 #include <asm/tlbflush.h>
 #include <asm/x86_init.h>
 #include <asm/uv/uv.h>
index 6a61194ffd5868c883efa55bb22a4d6334450913..a6e21fee22ea2e5fb5ba6e46b09637ec88ec26f6 100644 (file)
@@ -104,7 +104,7 @@ static int set_up_temporary_mappings(void)
 {
        struct x86_mapping_info info = {
                .alloc_pgt_page = alloc_pgt_page,
-               .pmd_flag       = __PAGE_KERNEL_LARGE_EXEC,
+               .page_flag      = __PAGE_KERNEL_LARGE_EXEC,
                .offset         = __PAGE_OFFSET,
        };
        unsigned long mstart, mend;
index 5db706f14111c7c12a55fc0731a86641fe2c4741..a163a90af4aa8f81db742cba00a833d5f9011857 100644 (file)
@@ -2,7 +2,7 @@
 #include <linux/slab.h>
 #include <linux/memblock.h>
 
-#include <asm/cacheflush.h>
+#include <asm/set_memory.h>
 #include <asm/pgtable.h>
 #include <asm/realmode.h>
 #include <asm/tlbflush.h>
index a5c9910d234f2f235500ecf8a2fa587eaec56f88..09a085bde0d43250f7a1f864ed49f565c71383a6 100644 (file)
@@ -125,7 +125,7 @@ int poke_user(struct task_struct *child, long addr, long data)
        else if ((addr >= offsetof(struct user, u_debugreg[0])) &&
                (addr <= offsetof(struct user, u_debugreg[7]))) {
                addr -= offsetof(struct user, u_debugreg[0]);
-               addr = addr >> 2;
+               addr = addr >> 3;
                if ((addr == 4) || (addr == 5))
                        return -EIO;
                child->thread.arch.debugregs[addr] = data;
index 46a9df99f3c5c952601d7f153adf6bf8c1e3e937..7e1d35b6ad5c0990c4fb33984ecd833767cdbeb9 100644 (file)
@@ -2,16 +2,9 @@
 #include <linux/sched.h>
 #include <linux/elf.h>
 #include <linux/crypto.h>
+#include <linux/kbuild.h>
 #include <asm/mman.h>
 
-#define DEFINE(sym, val) \
-       asm volatile("\n->" #sym " %0 " #val : : "i" (val))
-
-#define BLANK() asm volatile("\n->" : : )
-
-#define OFFSET(sym, str, mem) \
-       DEFINE(sym, offsetof(struct str, mem));
-
 void foo(void)
 {
 #include <common-offsets.h>
index a732bc2b9dfcd860f832e64c344d60fef59ea4c9..f33eef4ebd12b55645365732135638855ef313cd 100644 (file)
@@ -142,9 +142,7 @@ static void __init xen_banner(void)
        struct xen_extraversion extra;
        HYPERVISOR_xen_version(XENVER_extraversion, &extra);
 
-       pr_info("Booting paravirtualized kernel %son %s\n",
-               xen_feature(XENFEAT_auto_translated_physmap) ?
-                       "with PVH extensions " : "", pv_info.name);
+       pr_info("Booting paravirtualized kernel on %s\n", pv_info.name);
        printk(KERN_INFO "Xen version: %d.%d%s%s\n",
               version >> 16, version & 0xffff, extra.extraversion,
               xen_feature(XENFEAT_mmu_pt_update_preserve_ad) ? " (preserve-AD)" : "");
@@ -277,31 +275,19 @@ static bool __init xen_check_mwait(void)
 
 static bool __init xen_check_xsave(void)
 {
-       unsigned int err, eax, edx;
+       unsigned int cx, xsave_mask;
 
-       /*
-        * Xen 4.0 and older accidentally leaked the host XSAVE flag into guest
-        * view, despite not being able to support guests using the
-        * functionality. Probe for the actual availability of XSAVE by seeing
-        * whether xgetbv executes successfully or raises #UD.
-        */
-       asm volatile("1: .byte 0x0f,0x01,0xd0\n\t" /* xgetbv */
-                    "xor %[err], %[err]\n"
-                    "2:\n\t"
-                    ".pushsection .fixup,\"ax\"\n\t"
-                    "3: movl $1,%[err]\n\t"
-                    "jmp 2b\n\t"
-                    ".popsection\n\t"
-                    _ASM_EXTABLE(1b, 3b)
-                    : [err] "=r" (err), "=a" (eax), "=d" (edx)
-                    : "c" (0));
-
-       return err == 0;
+       cx = cpuid_ecx(1);
+
+       xsave_mask = (1 << (X86_FEATURE_XSAVE % 32)) |
+                    (1 << (X86_FEATURE_OSXSAVE % 32));
+
+       /* Xen will set CR4.OSXSAVE if supported and not disabled by force */
+       return (cx & xsave_mask) == xsave_mask;
 }
 
 static void __init xen_init_capabilities(void)
 {
-       setup_clear_cpu_cap(X86_BUG_SYSRET_SS_ATTRS);
        setup_force_cpu_cap(X86_FEATURE_XENPV);
        setup_clear_cpu_cap(X86_FEATURE_DCA);
        setup_clear_cpu_cap(X86_FEATURE_APERFMPERF);
@@ -317,10 +303,7 @@ static void __init xen_init_capabilities(void)
        else
                setup_clear_cpu_cap(X86_FEATURE_MWAIT);
 
-       if (xen_check_xsave()) {
-               setup_force_cpu_cap(X86_FEATURE_XSAVE);
-               setup_force_cpu_cap(X86_FEATURE_OSXSAVE);
-       } else {
+       if (!xen_check_xsave()) {
                setup_clear_cpu_cap(X86_FEATURE_XSAVE);
                setup_clear_cpu_cap(X86_FEATURE_OSXSAVE);
        }
@@ -972,15 +955,10 @@ static void xen_write_msr(unsigned int msr, unsigned low, unsigned high)
 
 void xen_setup_shared_info(void)
 {
-       if (!xen_feature(XENFEAT_auto_translated_physmap)) {
-               set_fixmap(FIX_PARAVIRT_BOOTMAP,
-                          xen_start_info->shared_info);
+       set_fixmap(FIX_PARAVIRT_BOOTMAP, xen_start_info->shared_info);
 
-               HYPERVISOR_shared_info =
-                       (struct shared_info *)fix_to_virt(FIX_PARAVIRT_BOOTMAP);
-       } else
-               HYPERVISOR_shared_info =
-                       (struct shared_info *)__va(xen_start_info->shared_info);
+       HYPERVISOR_shared_info =
+               (struct shared_info *)fix_to_virt(FIX_PARAVIRT_BOOTMAP);
 
 #ifndef CONFIG_SMP
        /* In UP this is as good a place as any to set up shared info */
@@ -988,6 +966,13 @@ void xen_setup_shared_info(void)
 #endif
 
        xen_setup_mfn_list_list();
+
+       /*
+        * Now that shared info is set up we can start using routines that
+        * point to pvclock area.
+        */
+       if (system_state == SYSTEM_BOOTING)
+               xen_init_time_ops();
 }
 
 /* This is called once we have the cpu_possible_mask */
@@ -1286,8 +1271,6 @@ asmlinkage __visible void __init xen_start_kernel(void)
        x86_init.oem.arch_setup = xen_arch_setup;
        x86_init.oem.banner = xen_banner;
 
-       xen_init_time_ops();
-
        /*
         * Set up some pagetable state before starting to set any ptes.
         */
index 5e375a5e815fb2b90535429373c129c6aaa8862b..3be06f3caf3c1e25aa318fb2fd0ae8706cc0a717 100644 (file)
@@ -42,7 +42,7 @@ xmaddr_t arbitrary_virt_to_machine(void *vaddr)
 }
 EXPORT_SYMBOL_GPL(arbitrary_virt_to_machine);
 
-void xen_flush_tlb_all(void)
+static void xen_flush_tlb_all(void)
 {
        struct mmuext_op *op;
        struct multicall_space mcs;
index 9d9ae6650aa1d3d9e84a9929a7e5937ec89b6135..1f386d7fdf708489bf09b40c04ed338281c3e3c2 100644 (file)
@@ -355,10 +355,8 @@ static pteval_t pte_pfn_to_mfn(pteval_t val)
                pteval_t flags = val & PTE_FLAGS_MASK;
                unsigned long mfn;
 
-               if (!xen_feature(XENFEAT_auto_translated_physmap))
-                       mfn = __pfn_to_mfn(pfn);
-               else
-                       mfn = pfn;
+               mfn = __pfn_to_mfn(pfn);
+
                /*
                 * If there's no mfn for the pfn, then just create an
                 * empty non-present pte.  Unfortunately this loses
@@ -647,9 +645,6 @@ static int __xen_pgd_walk(struct mm_struct *mm, pgd_t *pgd,
        limit--;
        BUG_ON(limit >= FIXADDR_TOP);
 
-       if (xen_feature(XENFEAT_auto_translated_physmap))
-               return 0;
-
        /*
         * 64-bit has a great big hole in the middle of the address
         * space, which contains the Xen mappings.  On 32-bit these
@@ -1289,9 +1284,6 @@ static void __init xen_pagetable_cleanhighmap(void)
 
 static void __init xen_pagetable_p2m_setup(void)
 {
-       if (xen_feature(XENFEAT_auto_translated_physmap))
-               return;
-
        xen_vmalloc_p2m_tree();
 
 #ifdef CONFIG_X86_64
@@ -1314,8 +1306,7 @@ static void __init xen_pagetable_init(void)
        xen_build_mfn_list_list();
 
        /* Remap memory freed due to conflicts with E820 map */
-       if (!xen_feature(XENFEAT_auto_translated_physmap))
-               xen_remap_memory();
+       xen_remap_memory();
 
        xen_setup_shared_info();
 }
@@ -1925,21 +1916,20 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
        /* Zap identity mapping */
        init_level4_pgt[0] = __pgd(0);
 
-       if (!xen_feature(XENFEAT_auto_translated_physmap)) {
-               /* Pre-constructed entries are in pfn, so convert to mfn */
-               /* L4[272] -> level3_ident_pgt
-                * L4[511] -> level3_kernel_pgt */
-               convert_pfn_mfn(init_level4_pgt);
+       /* Pre-constructed entries are in pfn, so convert to mfn */
+       /* L4[272] -> level3_ident_pgt  */
+       /* L4[511] -> level3_kernel_pgt */
+       convert_pfn_mfn(init_level4_pgt);
 
-               /* L3_i[0] -> level2_ident_pgt */
-               convert_pfn_mfn(level3_ident_pgt);
-               /* L3_k[510] -> level2_kernel_pgt
-                * L3_k[511] -> level2_fixmap_pgt */
-               convert_pfn_mfn(level3_kernel_pgt);
+       /* L3_i[0] -> level2_ident_pgt */
+       convert_pfn_mfn(level3_ident_pgt);
+       /* L3_k[510] -> level2_kernel_pgt */
+       /* L3_k[511] -> level2_fixmap_pgt */
+       convert_pfn_mfn(level3_kernel_pgt);
+
+       /* L3_k[511][506] -> level1_fixmap_pgt */
+       convert_pfn_mfn(level2_fixmap_pgt);
 
-               /* L3_k[511][506] -> level1_fixmap_pgt */
-               convert_pfn_mfn(level2_fixmap_pgt);
-       }
        /* We get [511][511] and have Xen's version of level2_kernel_pgt */
        l3 = m2v(pgd[pgd_index(__START_KERNEL_map)].pgd);
        l2 = m2v(l3[pud_index(__START_KERNEL_map)].pud);
@@ -1962,34 +1952,30 @@ void __init xen_setup_kernel_pagetable(pgd_t *pgd, unsigned long max_pfn)
        if (i && i < pgd_index(__START_KERNEL_map))
                init_level4_pgt[i] = ((pgd_t *)xen_start_info->pt_base)[i];
 
-       if (!xen_feature(XENFEAT_auto_translated_physmap)) {
-               /* Make pagetable pieces RO */
-               set_page_prot(init_level4_pgt, PAGE_KERNEL_RO);
-               set_page_prot(level3_ident_pgt, PAGE_KERNEL_RO);
-               set_page_prot(level3_kernel_pgt, PAGE_KERNEL_RO);
-               set_page_prot(level3_user_vsyscall, PAGE_KERNEL_RO);
-               set_page_prot(level2_ident_pgt, PAGE_KERNEL_RO);
-               set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO);
-               set_page_prot(level2_fixmap_pgt, PAGE_KERNEL_RO);
-               set_page_prot(level1_fixmap_pgt, PAGE_KERNEL_RO);
-
-               /* Pin down new L4 */
-               pin_pagetable_pfn(MMUEXT_PIN_L4_TABLE,
-                                 PFN_DOWN(__pa_symbol(init_level4_pgt)));
-
-               /* Unpin Xen-provided one */
-               pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd)));
+       /* Make pagetable pieces RO */
+       set_page_prot(init_level4_pgt, PAGE_KERNEL_RO);
+       set_page_prot(level3_ident_pgt, PAGE_KERNEL_RO);
+       set_page_prot(level3_kernel_pgt, PAGE_KERNEL_RO);
+       set_page_prot(level3_user_vsyscall, PAGE_KERNEL_RO);
+       set_page_prot(level2_ident_pgt, PAGE_KERNEL_RO);
+       set_page_prot(level2_kernel_pgt, PAGE_KERNEL_RO);
+       set_page_prot(level2_fixmap_pgt, PAGE_KERNEL_RO);
+       set_page_prot(level1_fixmap_pgt, PAGE_KERNEL_RO);
+
+       /* Pin down new L4 */
+       pin_pagetable_pfn(MMUEXT_PIN_L4_TABLE,
+                         PFN_DOWN(__pa_symbol(init_level4_pgt)));
+
+       /* Unpin Xen-provided one */
+       pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, PFN_DOWN(__pa(pgd)));
 
-               /*
-                * At this stage there can be no user pgd, and no page
-                * structure to attach it to, so make sure we just set kernel
-                * pgd.
-                */
-               xen_mc_batch();
-               __xen_write_cr3(true, __pa(init_level4_pgt));
-               xen_mc_issue(PARAVIRT_LAZY_CPU);
-       } else
-               native_write_cr3(__pa(init_level4_pgt));
+       /*
+        * At this stage there can be no user pgd, and no page structure to
+        * attach it to, so make sure we just set kernel pgd.
+        */
+       xen_mc_batch();
+       __xen_write_cr3(true, __pa(init_level4_pgt));
+       xen_mc_issue(PARAVIRT_LAZY_CPU);
 
        /* We can't that easily rip out L3 and L2, as the Xen pagetables are
         * set out this way: [L4], [L1], [L2], [L3], [L1], [L1] ...  for
@@ -2025,7 +2011,8 @@ static unsigned long __init xen_read_phys_ulong(phys_addr_t addr)
 
 /*
  * Translate a virtual address to a physical one without relying on mapped
- * page tables.
+ * page tables. Don't rely on big pages being aligned in (guest) physical
+ * space!
  */
 static phys_addr_t __init xen_early_virt_to_phys(unsigned long vaddr)
 {
@@ -2046,7 +2033,7 @@ static phys_addr_t __init xen_early_virt_to_phys(unsigned long vaddr)
                                                       sizeof(pud)));
        if (!pud_present(pud))
                return 0;
-       pa = pud_pfn(pud) << PAGE_SHIFT;
+       pa = pud_val(pud) & PTE_PFN_MASK;
        if (pud_large(pud))
                return pa + (vaddr & ~PUD_MASK);
 
@@ -2054,7 +2041,7 @@ static phys_addr_t __init xen_early_virt_to_phys(unsigned long vaddr)
                                                       sizeof(pmd)));
        if (!pmd_present(pmd))
                return 0;
-       pa = pmd_pfn(pmd) << PAGE_SHIFT;
+       pa = pmd_val(pmd) & PTE_PFN_MASK;
        if (pmd_large(pmd))
                return pa + (vaddr & ~PMD_MASK);
 
@@ -2402,9 +2389,6 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)
 
 static void __init xen_post_allocator_init(void)
 {
-       if (xen_feature(XENFEAT_auto_translated_physmap))
-               return;
-
        pv_mmu_ops.set_pte = xen_set_pte;
        pv_mmu_ops.set_pmd = xen_set_pmd;
        pv_mmu_ops.set_pud = xen_set_pud;
@@ -2510,9 +2494,6 @@ void __init xen_init_mmu_ops(void)
 {
        x86_init.paging.pagetable_init = xen_pagetable_init;
 
-       if (xen_feature(XENFEAT_auto_translated_physmap))
-               return;
-
        pv_mmu_ops = xen_mmu_ops;
 
        memset(dummy_mapping, 0xff, PAGE_SIZE);
@@ -2649,9 +2630,6 @@ int xen_create_contiguous_region(phys_addr_t pstart, unsigned int order,
         * this function are redundant and can be ignored.
         */
 
-       if (xen_feature(XENFEAT_auto_translated_physmap))
-               return 0;
-
        if (unlikely(order > MAX_CONTIG_ORDER))
                return -ENOMEM;
 
@@ -2688,9 +2666,6 @@ void xen_destroy_contiguous_region(phys_addr_t pstart, unsigned int order)
        int success;
        unsigned long vstart;
 
-       if (xen_feature(XENFEAT_auto_translated_physmap))
-               return;
-
        if (unlikely(order > MAX_CONTIG_ORDER))
                return;
 
index 090c7eb4dca9c43d5a52ff14e426a192349f7088..a1895a8e85c15753d4781c3ac72185b4c96a7d9d 100644 (file)
@@ -406,7 +406,7 @@ static void __init xen_time_init(void)
                pvclock_gtod_register_notifier(&xen_pvclock_gtod_notifier);
 }
 
-void __init xen_init_time_ops(void)
+void __ref xen_init_time_ops(void)
 {
        pv_time_ops = xen_time_ops;
 
index 5d6bd932ba4e37eaf1ea19581b3e3a6320ee1099..e4f366a488d3dc2fd7ba292d7ae4e2ccbe1fcae3 100644 (file)
@@ -46,12 +46,9 @@ struct pci_dev;
 
 #define PCI_DMA_BUS_IS_PHYS    (1)
 
-/* Map a range of PCI memory or I/O space for a device into user space */
-int pci_mmap_page_range(struct pci_dev *pdev, struct vm_area_struct *vma,
-                       enum pci_mmap_state mmap_state, int write_combine);
-
 /* Tell drivers/pci/proc.c that we have pci_mmap_page_range() */
-#define HAVE_PCI_MMAP  1
+#define HAVE_PCI_MMAP          1
+#define arch_can_pci_mmap_io() 1
 
 #endif /* __KERNEL__ */
 
index 56aad54e7fb7b7fd62c5a55e13589705d194ebb7..b15bf6bc0e94f46f035e8781ffa921060341fe91 100644 (file)
@@ -1,25 +1,2 @@
 # UAPI Header export list
 include include/uapi/asm-generic/Kbuild.asm
-
-header-y += auxvec.h
-header-y += byteorder.h
-header-y += ioctls.h
-header-y += ipcbuf.h
-header-y += mman.h
-header-y += msgbuf.h
-header-y += param.h
-header-y += poll.h
-header-y += posix_types.h
-header-y += ptrace.h
-header-y += sembuf.h
-header-y += setup.h
-header-y += shmbuf.h
-header-y += sigcontext.h
-header-y += signal.h
-header-y += socket.h
-header-y += sockios.h
-header-y += stat.h
-header-y += swab.h
-header-y += termbits.h
-header-y += types.h
-header-y += unistd.h
index b848cc3dc913d8de7dc5181fc140a9f83215e6cf..903963ee495d50807d2e0e039a1b1ee044caf245 100644 (file)
@@ -333,25 +333,6 @@ __pci_mmap_make_offset(struct pci_dev *dev, struct vm_area_struct *vma,
        return -EINVAL;
 }
 
-/*
- * Set vm_page_prot of VMA, as appropriate for this architecture, for a pci
- * device mapping.
- */
-static __inline__ void
-__pci_mmap_set_pgprot(struct pci_dev *dev, struct vm_area_struct *vma,
-                     enum pci_mmap_state mmap_state, int write_combine)
-{
-       int prot = pgprot_val(vma->vm_page_prot);
-
-       /* Set to write-through */
-       prot = (prot & _PAGE_CA_MASK) | _PAGE_CA_WT;
-#if 0
-       if (!write_combine)
-               prot |= _PAGE_WRITETHRU;
-#endif
-       vma->vm_page_prot = __pgprot(prot);
-}
-
 /*
  * Perform the actual remap of the pages for a PCI device mapping, as
  * appropriate for this architecture.  The region in the process to map
@@ -362,7 +343,8 @@ __pci_mmap_set_pgprot(struct pci_dev *dev, struct vm_area_struct *vma,
  *
  * Returns a negative error code on failure, zero on success.
  */
-int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+int pci_mmap_page_range(struct pci_dev *dev, int bar,
+                       struct vm_area_struct *vma,
                        enum pci_mmap_state mmap_state,
                        int write_combine)
 {
@@ -372,7 +354,7 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
        if (ret < 0)
                return ret;
 
-       __pci_mmap_set_pgprot(dev, vma, mmap_state, write_combine);
+       vma->vm_page_prot = pgprot_device(vma->vm_page_prot);
 
        ret = io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
                                 vma->vm_end - vma->vm_start,vma->vm_page_prot);
index a8ad7e77db28c86cf1cb825fed27c22493f4793e..89cd28f8d05129680aa531dd462fc013966c9654 100644 (file)
@@ -6,7 +6,6 @@ menuconfig BLOCK
        default y
        select SBITMAP
        select SRCU
-       select DAX
        help
         Provide block layer support for the kernel.
 
index bd8499ef157ce8786c6eaa164448eb0bf9e84c6c..08ce45096350561896fb6c8959c5c04603e98555 100644 (file)
  * rotational or flash-based devices, and to get the job done quickly
  * for applications consisting in many I/O-bound processes.
  *
+ * NOTE: if the main or only goal, with a given device, is to achieve
+ * the maximum-possible throughput at all times, then do switch off
+ * all low-latency heuristics for that device, by setting low_latency
+ * to 0.
+ *
  * BFQ is described in [1], where also a reference to the initial, more
  * theoretical paper on BFQ can be found. The interested reader can find
  * in the latter paper full details on the main algorithm, as well as
index b4fc3e4260b71f91ee8e989ddf9b09b0d7986a13..8726ede19eef2c632a8e53d2bc340a7cae832e6e 100644 (file)
@@ -1114,12 +1114,21 @@ static void bfq_activate_requeue_entity(struct bfq_entity *entity,
 bool __bfq_deactivate_entity(struct bfq_entity *entity, bool ins_into_idle_tree)
 {
        struct bfq_sched_data *sd = entity->sched_data;
-       struct bfq_service_tree *st = bfq_entity_service_tree(entity);
-       int is_in_service = entity == sd->in_service_entity;
+       struct bfq_service_tree *st;
+       bool is_in_service;
 
        if (!entity->on_st) /* entity never activated, or already inactive */
                return false;
 
+       /*
+        * If we get here, then entity is active, which implies that
+        * bfq_group_set_parent has already been invoked for the group
+        * represented by entity. Therefore, the field
+        * entity->sched_data has been set, and we can safely use it.
+        */
+       st = bfq_entity_service_tree(entity);
+       is_in_service = entity == sd->in_service_entity;
+
        if (is_in_service)
                bfq_calc_finish(entity, entity->service);
 
index c580b0138a7f3713486dc1005d47a75a357a24d2..c7068520794bd0ba060b905f850efaae6a8cbd36 100644 (file)
@@ -2644,8 +2644,6 @@ bool blk_update_request(struct request *req, int error, unsigned int nr_bytes)
                return false;
        }
 
-       WARN_ON_ONCE(req->rq_flags & RQF_SPECIAL_PAYLOAD);
-
        req->__data_len -= total_bytes;
 
        /* update sector only for requests with clear definition of sector */
@@ -2658,17 +2656,19 @@ bool blk_update_request(struct request *req, int error, unsigned int nr_bytes)
                req->cmd_flags |= req->bio->bi_opf & REQ_FAILFAST_MASK;
        }
 
-       /*
-        * If total number of sectors is less than the first segment
-        * size, something has gone terribly wrong.
-        */
-       if (blk_rq_bytes(req) < blk_rq_cur_bytes(req)) {
-               blk_dump_rq_flags(req, "request botched");
-               req->__data_len = blk_rq_cur_bytes(req);
-       }
+       if (!(req->rq_flags & RQF_SPECIAL_PAYLOAD)) {
+               /*
+                * If total number of sectors is less than the first segment
+                * size, something has gone terribly wrong.
+                */
+               if (blk_rq_bytes(req) < blk_rq_cur_bytes(req)) {
+                       blk_dump_rq_flags(req, "request botched");
+                       req->__data_len = blk_rq_cur_bytes(req);
+               }
 
-       /* recalculate the number of segments */
-       blk_recalc_rq_segments(req);
+               /* recalculate the number of segments */
+               blk_recalc_rq_segments(req);
+       }
 
        return true;
 }
index 5d4ce7eb8dbfb9100b7cfc7b673a64a1ab4822ad..a69ad122ed66c6b93385f1b3959a893b407b9d05 100644 (file)
@@ -1236,7 +1236,7 @@ void blk_mq_stop_hw_queue(struct blk_mq_hw_ctx *hctx)
 }
 EXPORT_SYMBOL(blk_mq_stop_hw_queue);
 
-void __blk_mq_stop_hw_queues(struct request_queue *q, bool sync)
+static void __blk_mq_stop_hw_queues(struct request_queue *q, bool sync)
 {
        struct blk_mq_hw_ctx *hctx;
        int i;
@@ -1554,13 +1554,13 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio)
 
        blk_queue_bounce(q, &bio);
 
+       blk_queue_split(q, &bio, q->bio_split);
+
        if (bio_integrity_enabled(bio) && bio_integrity_prep(bio)) {
                bio_io_error(bio);
                return BLK_QC_T_NONE;
        }
 
-       blk_queue_split(q, &bio, q->bio_split);
-
        if (!is_flush_fua && !blk_queue_nomerges(q) &&
            blk_attempt_plug_merge(q, bio, &request_count, &same_queue_rq))
                return BLK_QC_T_NONE;
@@ -2341,15 +2341,15 @@ struct request_queue *blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
 
        blk_mq_init_cpu_queues(q, set->nr_hw_queues);
 
-       mutex_lock(&all_q_mutex);
        get_online_cpus();
+       mutex_lock(&all_q_mutex);
 
        list_add_tail(&q->all_q_node, &all_q_list);
        blk_mq_add_queue_tag_set(set, q);
        blk_mq_map_swqueue(q, cpu_online_mask);
 
-       put_online_cpus();
        mutex_unlock(&all_q_mutex);
+       put_online_cpus();
 
        if (!(set->flags & BLK_MQ_F_NO_SCHED)) {
                int ret;
index 6c2f40940439c5b50a6aad0c0a560e8a2b2bf08b..c52356d90fe3854f05faebda241707a1b112a543 100644 (file)
@@ -96,13 +96,16 @@ void blk_stat_add(struct request *rq)
 
        rcu_read_lock();
        list_for_each_entry_rcu(cb, &q->stats->callbacks, list) {
-               if (blk_stat_is_active(cb)) {
-                       bucket = cb->bucket_fn(rq);
-                       if (bucket < 0)
-                               continue;
-                       stat = &this_cpu_ptr(cb->cpu_stat)[bucket];
-                       __blk_stat_add(stat, value);
-               }
+               if (!blk_stat_is_active(cb))
+                       continue;
+
+               bucket = cb->bucket_fn(rq);
+               if (bucket < 0)
+                       continue;
+
+               stat = &get_cpu_ptr(cb->cpu_stat)[bucket];
+               __blk_stat_add(stat, value);
+               put_cpu_ptr(cb->cpu_stat);
        }
        rcu_read_unlock();
 }
index ab726a5c0bf6eaa3039a472a65dd8fb3435f606b..dac99fbfc273f36234b95f80feb711173fdf41e7 100644 (file)
@@ -1062,10 +1062,8 @@ static int __elevator_change(struct request_queue *q, const char *name)
 
        strlcpy(elevator_name, name, sizeof(elevator_name));
        e = elevator_get(strstrip(elevator_name), true);
-       if (!e) {
-               printk(KERN_ERR "elevator: type %s not found\n", elevator_name);
+       if (!e)
                return -EINVAL;
-       }
 
        if (q->elevator &&
            !strcmp(elevator_name, q->elevator->type->elevator_name)) {
@@ -1105,7 +1103,6 @@ ssize_t elv_iosched_store(struct request_queue *q, const char *name,
        if (!ret)
                return count;
 
-       printk(KERN_ERR "elevator: switch to %s failed\n", name);
        return ret;
 }
 
index 3eddce0e307a16905fee0fcdc2be324fb20e9e72..3a507b9e2568a27e9d2e4359fc4fbdc3218dda4b 100644 (file)
@@ -140,7 +140,7 @@ int is_hash_blacklisted(const u8 *hash, size_t hash_len, const char *type)
 EXPORT_SYMBOL_GPL(is_hash_blacklisted);
 
 /*
- * Intialise the blacklist
+ * Initialise the blacklist
  */
 static int __init blacklist_init(void)
 {
index 168df784da8491e2daccf5b79316fb2191b46e6d..218567d717d6831bff36743e5977ee73236cf0ce 100644 (file)
@@ -32,9 +32,7 @@ static void *lzo_alloc_ctx(struct crypto_scomp *tfm)
 {
        void *ctx;
 
-       ctx = kmalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL | __GFP_NOWARN);
-       if (!ctx)
-               ctx = vmalloc(LZO1X_MEM_COMPRESS);
+       ctx = kvmalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
        if (!ctx)
                return ERR_PTR(-ENOMEM);
 
index 117ca14ccf8595813841585719790c7ac89d7e84..ba2901e76769091cf9ebb0d9a6287be2e24f0d71 100644 (file)
@@ -204,4 +204,6 @@ source "drivers/fpga/Kconfig"
 
 source "drivers/fsi/Kconfig"
 
+source "drivers/tee/Kconfig"
+
 endmenu
index 903b19199b695410d7dff701a97c56d056bc839a..cfabd141dba2ad3a6208f3c880f5cc7a14eecc3e 100644 (file)
@@ -14,7 +14,9 @@ obj-$(CONFIG_GENERIC_PHY)     += phy/
 obj-$(CONFIG_PINCTRL)          += pinctrl/
 obj-$(CONFIG_GPIOLIB)          += gpio/
 obj-y                          += pwm/
+
 obj-$(CONFIG_PCI)              += pci/
+obj-$(CONFIG_PCI_ENDPOINT)     += pci/endpoint/
 # PCI dwc controller drivers
 obj-y                          += pci/dwc/
 
@@ -178,3 +180,4 @@ obj-$(CONFIG_ANDROID)               += android/
 obj-$(CONFIG_NVMEM)            += nvmem/
 obj-$(CONFIG_FPGA)             += fpga/
 obj-$(CONFIG_FSI)              += fsi/
+obj-$(CONFIG_TEE)              += tee/
index d78065cc932473071450697938bf9221ca67a67f..b1aacfc62b1f7107590c2907b02e3d678d0a1c2b 100644 (file)
@@ -50,6 +50,7 @@ acpi-$(CONFIG_ACPI_REDUCED_HARDWARE_ONLY) += evged.o
 acpi-y                         += sysfs.o
 acpi-y                         += property.o
 acpi-$(CONFIG_X86)             += acpi_cmos_rtc.o
+acpi-$(CONFIG_X86)             += x86/utils.o
 acpi-$(CONFIG_DEBUG_FS)                += debugfs.o
 acpi-$(CONFIG_ACPI_NUMA)       += numa.o
 acpi-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o
index 17a1eb14847ad6540dab29708aaaa528395c2eb1..fc6c416f8724670aef2f29d4d81d373ed400dcd5 100644 (file)
@@ -106,6 +106,16 @@ static const struct apd_device_desc vulcan_spi_desc = {
        .setup = acpi_apd_setup,
        .fixed_clk_rate = 133000000,
 };
+
+static const struct apd_device_desc hip07_i2c_desc = {
+       .setup = acpi_apd_setup,
+       .fixed_clk_rate = 200000000,
+};
+
+static const struct apd_device_desc hip08_i2c_desc = {
+       .setup = acpi_apd_setup,
+       .fixed_clk_rate = 250000000,
+};
 #endif
 
 #else
@@ -170,6 +180,8 @@ static const struct acpi_device_id acpi_apd_device_ids[] = {
        { "APMC0D0F", APD_ADDR(xgene_i2c_desc) },
        { "BRCM900D", APD_ADDR(vulcan_spi_desc) },
        { "CAV900D",  APD_ADDR(vulcan_spi_desc) },
+       { "HISI0A21", APD_ADDR(hip07_i2c_desc) },
+       { "HISI0A22", APD_ADDR(hip08_i2c_desc) },
 #endif
        { }
 };
index 5edfd9c4904458ae6b30eb844be451aa81f38bca..10347e3d73ad00d1cdf25ba462c1659f9638840e 100644 (file)
@@ -143,6 +143,22 @@ static void lpss_deassert_reset(struct lpss_private_data *pdata)
        writel(val, pdata->mmio_base + offset);
 }
 
+/*
+ * BYT PWM used for backlight control by the i915 driver on systems without
+ * the Crystal Cove PMIC.
+ */
+static struct pwm_lookup byt_pwm_lookup[] = {
+       PWM_LOOKUP_WITH_MODULE("80860F09:00", 0, "0000:00:02.0",
+                              "pwm_backlight", 0, PWM_POLARITY_NORMAL,
+                              "pwm-lpss-platform"),
+};
+
+static void byt_pwm_setup(struct lpss_private_data *pdata)
+{
+       if (!acpi_dev_present("INT33FD", NULL, -1))
+               pwm_add_table(byt_pwm_lookup, ARRAY_SIZE(byt_pwm_lookup));
+}
+
 #define LPSS_I2C_ENABLE                        0x6c
 
 static void byt_i2c_setup(struct lpss_private_data *pdata)
@@ -200,6 +216,7 @@ static const struct lpss_device_desc lpt_sdio_dev_desc = {
 
 static const struct lpss_device_desc byt_pwm_dev_desc = {
        .flags = LPSS_SAVE_CTX,
+       .setup = byt_pwm_setup,
 };
 
 static const struct lpss_device_desc bsw_pwm_dev_desc = {
index 32d93edbc47914d56a0609c6dbf05f4f87337964..dea65306b68719a1c4e5fd737835ef1819b90107 100644 (file)
@@ -2,7 +2,7 @@
 # Makefile for ACPICA Core interpreter
 #
 
-ccflags-y                      := -Os -DBUILDING_ACPICA
+ccflags-y                      := -Os -D_LINUX -DBUILDING_ACPICA
 ccflags-$(CONFIG_ACPI_DEBUG)   += -DACPI_DEBUG_OUTPUT
 
 # use acpi.o to put all files here into acpi.o modparam namespace
diff --git a/drivers/acpi/acpica/acconvert.h b/drivers/acpi/acpica/acconvert.h
new file mode 100644 (file)
index 0000000..c84223b
--- /dev/null
@@ -0,0 +1,144 @@
+/******************************************************************************
+ *
+ * Module Name: acapps - common include for ACPI applications/tools
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2017, Intel Corp.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ *    substantially similar to the "NO WARRANTY" disclaimer below
+ *    ("Disclaimer") and any redistribution must be conditioned upon
+ *    including a substantially similar Disclaimer requirement for further
+ *    binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ *    of any contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#ifndef _ACCONVERT
+#define _ACCONVERT
+
+/* Definitions for comment state */
+
+#define ASL_COMMENT_STANDARD    1
+#define ASLCOMMENT_INLINE       2
+#define ASL_COMMENT_OPEN_PAREN  3
+#define ASL_COMMENT_CLOSE_PAREN 4
+#define ASL_COMMENT_CLOSE_BRACE 5
+
+/* Definitions for comment print function*/
+
+#define AML_COMMENT_STANDARD    1
+#define AMLCOMMENT_INLINE       2
+#define AML_COMMENT_END_NODE    3
+#define AML_NAMECOMMENT         4
+#define AML_COMMENT_CLOSE_BRACE 5
+#define AML_COMMENT_ENDBLK      6
+#define AML_COMMENT_INCLUDE     7
+
+#ifdef ACPI_ASL_COMPILER
+/*
+ * cvcompiler
+ */
+void
+cv_process_comment(struct asl_comment_state current_state,
+                  char *string_buffer, int c1);
+
+void
+cv_process_comment_type2(struct asl_comment_state current_state,
+                        char *string_buffer);
+
+u32 cv_calculate_comment_lengths(union acpi_parse_object *op);
+
+void cv_process_comment_state(char input);
+
+char *cv_append_inline_comment(char *inline_comment, char *to_add);
+
+void cv_add_to_comment_list(char *to_add);
+
+void cv_place_comment(u8 type, char *comment_string);
+
+u32 cv_parse_op_block_type(union acpi_parse_object *op);
+
+struct acpi_comment_node *cv_comment_node_calloc(void);
+
+void cg_write_aml_def_block_comment(union acpi_parse_object *op);
+
+void
+cg_write_one_aml_comment(union acpi_parse_object *op,
+                        char *comment_to_print, u8 input_option);
+
+void cg_write_aml_comment(union acpi_parse_object *op);
+
+/*
+ * cvparser
+ */
+void
+cv_init_file_tree(struct acpi_table_header *table,
+                 u8 *aml_start, u32 aml_length);
+
+void cv_clear_op_comments(union acpi_parse_object *op);
+
+struct acpi_file_node *cv_filename_exists(char *filename,
+                                         struct acpi_file_node *head);
+
+void cv_label_file_node(union acpi_parse_object *op);
+
+void
+cv_capture_list_comments(struct acpi_parse_state *parser_state,
+                        struct acpi_comment_node *list_head,
+                        struct acpi_comment_node *list_tail);
+
+void cv_capture_comments_only(struct acpi_parse_state *parser_state);
+
+void cv_capture_comments(struct acpi_walk_state *walk_state);
+
+void cv_transfer_comments(union acpi_parse_object *op);
+
+/*
+ * cvdisasm
+ */
+void cv_switch_files(u32 level, union acpi_parse_object *op);
+
+u8 cv_file_has_switched(union acpi_parse_object *op);
+
+void cv_close_paren_write_comment(union acpi_parse_object *op, u32 level);
+
+void cv_close_brace_write_comment(union acpi_parse_object *op, u32 level);
+
+void
+cv_print_one_comment_list(struct acpi_comment_node *comment_list, u32 level);
+
+void
+cv_print_one_comment_type(union acpi_parse_object *op,
+                         u8 comment_type, char *end_str, u32 level);
+
+#endif
+
+#endif                         /* _ACCONVERT */
index 1d955fe216c4b68c6b1391577d249fbf70fb95d0..abe8c316908ccd4f0737cad58273c3f4ce3e4982 100644 (file)
@@ -370,6 +370,59 @@ ACPI_GLOBAL(const char, *acpi_gbl_pld_shape_list[]);
 
 #endif
 
+/*
+ * Meant for the -ca option.
+ */
+ACPI_INIT_GLOBAL(char *, acpi_gbl_current_inline_comment, NULL);
+ACPI_INIT_GLOBAL(char *, acpi_gbl_current_end_node_comment, NULL);
+ACPI_INIT_GLOBAL(char *, acpi_gbl_current_open_brace_comment, NULL);
+ACPI_INIT_GLOBAL(char *, acpi_gbl_current_close_brace_comment, NULL);
+
+ACPI_INIT_GLOBAL(char *, acpi_gbl_root_filename, NULL);
+ACPI_INIT_GLOBAL(char *, acpi_gbl_current_filename, NULL);
+ACPI_INIT_GLOBAL(char *, acpi_gbl_current_parent_filename, NULL);
+ACPI_INIT_GLOBAL(char *, acpi_gbl_current_include_filename, NULL);
+
+ACPI_INIT_GLOBAL(struct acpi_comment_node, *acpi_gbl_last_list_head, NULL);
+
+ACPI_INIT_GLOBAL(struct acpi_comment_node, *acpi_gbl_def_blk_comment_list_head,
+                NULL);
+ACPI_INIT_GLOBAL(struct acpi_comment_node, *acpi_gbl_def_blk_comment_list_tail,
+                NULL);
+
+ACPI_INIT_GLOBAL(struct acpi_comment_node, *acpi_gbl_reg_comment_list_head,
+                NULL);
+ACPI_INIT_GLOBAL(struct acpi_comment_node, *acpi_gbl_reg_comment_list_tail,
+                NULL);
+
+ACPI_INIT_GLOBAL(struct acpi_comment_node, *acpi_gbl_inc_comment_list_head,
+                NULL);
+ACPI_INIT_GLOBAL(struct acpi_comment_node, *acpi_gbl_inc_comment_list_tail,
+                NULL);
+
+ACPI_INIT_GLOBAL(struct acpi_comment_node, *acpi_gbl_end_blk_comment_list_head,
+                NULL);
+ACPI_INIT_GLOBAL(struct acpi_comment_node, *acpi_gbl_end_blk_comment_list_tail,
+                NULL);
+
+ACPI_INIT_GLOBAL(struct acpi_comment_addr_node,
+                *acpi_gbl_comment_addr_list_head, NULL);
+
+ACPI_INIT_GLOBAL(union acpi_parse_object, *acpi_gbl_current_scope, NULL);
+
+ACPI_INIT_GLOBAL(struct acpi_file_node, *acpi_gbl_file_tree_root, NULL);
+
+ACPI_GLOBAL(acpi_cache_t *, acpi_gbl_reg_comment_cache);
+ACPI_GLOBAL(acpi_cache_t *, acpi_gbl_comment_addr_cache);
+ACPI_GLOBAL(acpi_cache_t *, acpi_gbl_file_cache);
+
+ACPI_INIT_GLOBAL(u8, gbl_capture_comments, FALSE);
+
+ACPI_INIT_GLOBAL(u8, acpi_gbl_debug_asl_conversion, FALSE);
+ACPI_INIT_GLOBAL(ACPI_FILE, acpi_gbl_conv_debug_file, NULL);
+
+ACPI_GLOBAL(char, acpi_gbl_table_sig[4]);
+
 /*****************************************************************************
  *
  * Application globals
index 8fd495e8fdcef2dcc68c0e3ce09e9755ff1eb861..f9b3f7fef4621891def4b571512521f1f667d4b2 100644 (file)
@@ -53,7 +53,7 @@ typedef u32 acpi_mutex_handle;
 
 /* Total number of aml opcodes defined */
 
-#define AML_NUM_OPCODES                 0x82
+#define AML_NUM_OPCODES                 0x83
 
 /* Forward declarations */
 
@@ -754,21 +754,52 @@ union acpi_parse_value {
 #define ACPI_DISASM_ONLY_MEMBERS(a)
 #endif
 
+#if defined(ACPI_ASL_COMPILER)
+#define ACPI_CONVERTER_ONLY_MEMBERS(a)  a;
+#else
+#define ACPI_CONVERTER_ONLY_MEMBERS(a)
+#endif
+
 #define ACPI_PARSE_COMMON \
-       union acpi_parse_object         *parent;        /* Parent op */\
-       u8                              descriptor_type; /* To differentiate various internal objs */\
-       u8                              flags;          /* Type of Op */\
-       u16                             aml_opcode;     /* AML opcode */\
-       u8                              *aml;           /* Address of declaration in AML */\
-       union acpi_parse_object         *next;          /* Next op */\
-       struct acpi_namespace_node      *node;          /* For use by interpreter */\
-       union acpi_parse_value          value;          /* Value or args associated with the opcode */\
-       u8                              arg_list_length; /* Number of elements in the arg list */\
-       ACPI_DISASM_ONLY_MEMBERS (\
-       u16                             disasm_flags;   /* Used during AML disassembly */\
-       u8                              disasm_opcode;  /* Subtype used for disassembly */\
-       char                            *operator_symbol;/* Used for C-style operator name strings */\
-       char                            aml_op_name[16])        /* Op name (debug only) */
+       union acpi_parse_object         *parent;            /* Parent op */\
+       u8                              descriptor_type;    /* To differentiate various internal objs */\
+       u8                              flags;              /* Type of Op */\
+       u16                             aml_opcode;         /* AML opcode */\
+       u8                              *aml;               /* Address of declaration in AML */\
+       union acpi_parse_object         *next;              /* Next op */\
+       struct acpi_namespace_node      *node;              /* For use by interpreter */\
+       union acpi_parse_value          value;              /* Value or args associated with the opcode */\
+       u8                              arg_list_length;    /* Number of elements in the arg list */\
+        ACPI_DISASM_ONLY_MEMBERS (\
+       u16                             disasm_flags;       /* Used during AML disassembly */\
+       u8                              disasm_opcode;      /* Subtype used for disassembly */\
+       char                            *operator_symbol;   /* Used for C-style operator name strings */\
+       char                            aml_op_name[16])    /* Op name (debug only) */\
+        ACPI_CONVERTER_ONLY_MEMBERS (\
+       char                            *inline_comment;    /* Inline comment */\
+       char                            *end_node_comment;  /* End of node comment */\
+       char                            *name_comment;      /* Comment associated with the first parameter of the name node */\
+       char                            *close_brace_comment; /* Comments that come after } on the same as } */\
+       struct acpi_comment_node        *comment_list;      /* comments that appears before this node */\
+       struct acpi_comment_node        *end_blk_comment;   /* comments that at the end of a block but before ) or } */\
+       char                            *cv_filename;       /* Filename associated with this node. Used for ASL/ASL+ converter */\
+       char                            *cv_parent_filename)    /* Parent filename associated with this node. Used for ASL/ASL+ converter */
+
+/* categories of comments */
+
+typedef enum {
+       STANDARD_COMMENT = 1,
+       INLINE_COMMENT,
+       ENDNODE_COMMENT,
+       OPENBRACE_COMMENT,
+       CLOSE_BRACE_COMMENT,
+       STD_DEFBLK_COMMENT,
+       END_DEFBLK_COMMENT,
+       FILENAME_COMMENT,
+       PARENTFILENAME_COMMENT,
+       ENDBLK_COMMENT,
+       INCLUDE_COMMENT
+} asl_comment_types;
 
 /* Internal opcodes for disasm_opcode field above */
 
@@ -784,9 +815,38 @@ union acpi_parse_value {
 #define ACPI_DASM_LNOT_SUFFIX           0x09   /* End  of a Lnot_equal (etc.) pair of opcodes */
 #define ACPI_DASM_HID_STRING            0x0A   /* String is a _HID or _CID */
 #define ACPI_DASM_IGNORE_SINGLE         0x0B   /* Ignore the opcode but not it's children */
-#define ACPI_DASM_SWITCH_PREDICATE      0x0C   /* Object is a predicate for a Switch or Case block */
-#define ACPI_DASM_CASE                  0x0D   /* If/Else is a Case in a Switch/Case block */
-#define ACPI_DASM_DEFAULT               0x0E   /* Else is a Default in a Switch/Case block */
+#define ACPI_DASM_SWITCH                0x0C   /* While is a Switch */
+#define ACPI_DASM_SWITCH_PREDICATE      0x0D   /* Object is a predicate for a Switch or Case block */
+#define ACPI_DASM_CASE                  0x0E   /* If/Else is a Case in a Switch/Case block */
+#define ACPI_DASM_DEFAULT               0x0F   /* Else is a Default in a Switch/Case block */
+
+/*
+ * List struct used in the -ca option
+ */
+struct acpi_comment_node {
+       char *comment;
+       struct acpi_comment_node *next;
+};
+
+struct acpi_comment_addr_node {
+       u8 *addr;
+       struct acpi_comment_addr_node *next;
+};
+
+/*
+ * File node - used for "Include" operator file stack and
+ * depdendency tree for the -ca option
+ */
+struct acpi_file_node {
+       void *file;
+       char *filename;
+       char *file_start;       /* Points to AML and indicates when the AML for this particular file starts. */
+       char *file_end;         /* Points to AML and indicates when the AML for this particular file ends. */
+       struct acpi_file_node *next;
+       struct acpi_file_node *parent;
+       u8 include_written;
+       struct acpi_comment_node *include_comment;
+};
 
 /*
  * Generic operation (for example:  If, While, Store)
@@ -813,6 +873,8 @@ struct acpi_parse_obj_asl {
        ACPI_PARSE_COMMON union acpi_parse_object *child;
        union acpi_parse_object *parent_method;
        char *filename;
+       u8 file_changed;
+       char *parent_filename;
        char *external_name;
        char *namepath;
        char name_seg[4];
@@ -842,6 +904,14 @@ union acpi_parse_object {
        struct acpi_parse_obj_asl asl;
 };
 
+struct asl_comment_state {
+       u8 comment_type;
+       u32 spaces_before;
+       union acpi_parse_object *latest_parse_node;
+       union acpi_parse_object *parsing_paren_brace_node;
+       u8 capture_comments;
+};
+
 /*
  * Parse state - one state per parser invocation and each control
  * method.
index c3337514e0ed3e5152eb3a194e45e8930b756e85..c7f0c96cc00fcb113fa02f482762ad9dc49fcfd3 100644 (file)
 
 #define ACPI_IS_OCTAL_DIGIT(d)              (((char)(d) >= '0') && ((char)(d) <= '7'))
 
+/*
+ * Macors used for the ASL-/ASL+ converter utility
+ */
+#ifdef ACPI_ASL_COMPILER
+
+#define ASL_CV_LABEL_FILENODE(a)         cv_label_file_node(a);
+#define ASL_CV_CAPTURE_COMMENTS_ONLY(a)   cv_capture_comments_only (a);
+#define ASL_CV_CAPTURE_COMMENTS(a)       cv_capture_comments (a);
+#define ASL_CV_TRANSFER_COMMENTS(a)      cv_transfer_comments (a);
+#define ASL_CV_CLOSE_PAREN(a,b)          cv_close_paren_write_comment(a,b);
+#define ASL_CV_CLOSE_BRACE(a,b)          cv_close_brace_write_comment(a,b);
+#define ASL_CV_SWITCH_FILES(a,b)         cv_switch_files(a,b);
+#define ASL_CV_CLEAR_OP_COMMENTS(a)       cv_clear_op_comments(a);
+#define ASL_CV_PRINT_ONE_COMMENT(a,b,c,d) cv_print_one_comment_type (a,b,c,d);
+#define ASL_CV_PRINT_ONE_COMMENT_LIST(a,b) cv_print_one_comment_list (a,b);
+#define ASL_CV_FILE_HAS_SWITCHED(a)       cv_file_has_switched(a)
+#define ASL_CV_INIT_FILETREE(a,b,c)      cv_init_file_tree(a,b,c);
+
+#else
+
+#define ASL_CV_LABEL_FILENODE(a)
+#define ASL_CV_CAPTURE_COMMENTS_ONLY(a)
+#define ASL_CV_CAPTURE_COMMENTS(a)
+#define ASL_CV_TRANSFER_COMMENTS(a)
+#define ASL_CV_CLOSE_PAREN(a,b)          acpi_os_printf (")");
+#define ASL_CV_CLOSE_BRACE(a,b)          acpi_os_printf ("}");
+#define ASL_CV_SWITCH_FILES(a,b)
+#define ASL_CV_CLEAR_OP_COMMENTS(a)
+#define ASL_CV_PRINT_ONE_COMMENT(a,b,c,d)
+#define ASL_CV_PRINT_ONE_COMMENT_LIST(a,b)
+#define ASL_CV_FILE_HAS_SWITCHED(a)       0
+#define ASL_CV_INIT_FILETREE(a,b,c)
+
+#endif
+
 #endif                         /* ACMACROS_H */
index e758f098ff4b14a7d075fa8a66d1074cbc6a95ff..a5d9af758c5242d92a4313d05e6f7f18f6a2d59d 100644 (file)
@@ -90,6 +90,7 @@
 #define ARGP_BUFFER_OP                  ARGP_LIST3 (ARGP_PKGLENGTH,  ARGP_TERMARG,       ARGP_BYTELIST)
 #define ARGP_BYTE_OP                    ARGP_LIST1 (ARGP_BYTEDATA)
 #define ARGP_BYTELIST_OP                ARGP_LIST1 (ARGP_NAMESTRING)
+#define ARGP_COMMENT_OP                 ARGP_LIST2 (ARGP_BYTEDATA,   ARGP_COMMENT)
 #define ARGP_CONCAT_OP                  ARGP_LIST3 (ARGP_TERMARG,    ARGP_TERMARG,       ARGP_TARGET)
 #define ARGP_CONCAT_RES_OP              ARGP_LIST3 (ARGP_TERMARG,    ARGP_TERMARG,       ARGP_TARGET)
 #define ARGP_COND_REF_OF_OP             ARGP_LIST2 (ARGP_SIMPLENAME, ARGP_TARGET)
 #define ARGI_BUFFER_OP                  ARGI_LIST1 (ARGI_INTEGER)
 #define ARGI_BYTE_OP                    ARGI_INVALID_OPCODE
 #define ARGI_BYTELIST_OP                ARGI_INVALID_OPCODE
+#define ARGI_COMMENT_OP                 ARGI_INVALID_OPCODE
 #define ARGI_CONCAT_OP                  ARGI_LIST3 (ARGI_ANYTYPE,    ARGI_ANYTYPE,       ARGI_TARGETREF)
 #define ARGI_CONCAT_RES_OP              ARGI_LIST3 (ARGI_BUFFER,     ARGI_BUFFER,        ARGI_TARGETREF)
 #define ARGI_COND_REF_OF_OP             ARGI_LIST2 (ARGI_OBJECT_REF, ARGI_TARGETREF)
index b536fd4712925184650fc411193d987fb84cdeb8..176f7e9b4d0e0190ed95404f090457c8aaf877f1 100644 (file)
 
 /* primary opcodes */
 
-#define AML_NULL_CHAR               (u16) 0x00
-
 #define AML_ZERO_OP                 (u16) 0x00
 #define AML_ONE_OP                  (u16) 0x01
-#define AML_UNASSIGNED              (u16) 0x02
 #define AML_ALIAS_OP                (u16) 0x06
 #define AML_NAME_OP                 (u16) 0x08
 #define AML_BYTE_OP                 (u16) 0x0a
 #define AML_SCOPE_OP                (u16) 0x10
 #define AML_BUFFER_OP               (u16) 0x11
 #define AML_PACKAGE_OP              (u16) 0x12
-#define AML_VAR_PACKAGE_OP          (u16) 0x13 /* ACPI 2.0 */
+#define AML_VARIABLE_PACKAGE_OP     (u16) 0x13 /* ACPI 2.0 */
 #define AML_METHOD_OP               (u16) 0x14
 #define AML_EXTERNAL_OP             (u16) 0x15 /* ACPI 6.0 */
 #define AML_DUAL_NAME_PREFIX        (u16) 0x2e
-#define AML_MULTI_NAME_PREFIX_OP    (u16) 0x2f
-#define AML_NAME_CHAR_SUBSEQ        (u16) 0x30
-#define AML_NAME_CHAR_FIRST         (u16) 0x41
-#define AML_EXTENDED_OP_PREFIX      (u16) 0x5b
+#define AML_MULTI_NAME_PREFIX       (u16) 0x2f
+#define AML_EXTENDED_PREFIX         (u16) 0x5b
 #define AML_ROOT_PREFIX             (u16) 0x5c
 #define AML_PARENT_PREFIX           (u16) 0x5e
-#define AML_LOCAL_OP                (u16) 0x60
+#define AML_FIRST_LOCAL_OP          (u16) 0x60 /* Used for Local op # calculations */
 #define AML_LOCAL0                  (u16) 0x60
 #define AML_LOCAL1                  (u16) 0x61
 #define AML_LOCAL2                  (u16) 0x62
@@ -82,7 +77,7 @@
 #define AML_LOCAL5                  (u16) 0x65
 #define AML_LOCAL6                  (u16) 0x66
 #define AML_LOCAL7                  (u16) 0x67
-#define AML_ARG_OP                  (u16) 0x68
+#define AML_FIRST_ARG_OP            (u16) 0x68 /* Used for Arg op # calculations */
 #define AML_ARG0                    (u16) 0x68
 #define AML_ARG1                    (u16) 0x69
 #define AML_ARG2                    (u16) 0x6a
@@ -93,7 +88,7 @@
 #define AML_STORE_OP                (u16) 0x70
 #define AML_REF_OF_OP               (u16) 0x71
 #define AML_ADD_OP                  (u16) 0x72
-#define AML_CONCAT_OP               (u16) 0x73
+#define AML_CONCATENATE_OP          (u16) 0x73
 #define AML_SUBTRACT_OP             (u16) 0x74
 #define AML_INCREMENT_OP            (u16) 0x75
 #define AML_DECREMENT_OP            (u16) 0x76
 #define AML_FIND_SET_LEFT_BIT_OP    (u16) 0x81
 #define AML_FIND_SET_RIGHT_BIT_OP   (u16) 0x82
 #define AML_DEREF_OF_OP             (u16) 0x83
-#define AML_CONCAT_RES_OP           (u16) 0x84 /* ACPI 2.0 */
+#define AML_CONCATENATE_TEMPLATE_OP (u16) 0x84 /* ACPI 2.0 */
 #define AML_MOD_OP                  (u16) 0x85 /* ACPI 2.0 */
 #define AML_NOTIFY_OP               (u16) 0x86
 #define AML_SIZE_OF_OP              (u16) 0x87
 #define AML_CREATE_BIT_FIELD_OP     (u16) 0x8d
 #define AML_OBJECT_TYPE_OP          (u16) 0x8e
 #define AML_CREATE_QWORD_FIELD_OP   (u16) 0x8f /* ACPI 2.0 */
-#define AML_LAND_OP                 (u16) 0x90
-#define AML_LOR_OP                  (u16) 0x91
-#define AML_LNOT_OP                 (u16) 0x92
-#define AML_LEQUAL_OP               (u16) 0x93
-#define AML_LGREATER_OP             (u16) 0x94
-#define AML_LLESS_OP                (u16) 0x95
+#define AML_LOGICAL_AND_OP          (u16) 0x90
+#define AML_LOGICAL_OR_OP           (u16) 0x91
+#define AML_LOGICAL_NOT_OP          (u16) 0x92
+#define AML_LOGICAL_EQUAL_OP        (u16) 0x93
+#define AML_LOGICAL_GREATER_OP      (u16) 0x94
+#define AML_LOGICAL_LESS_OP         (u16) 0x95
 #define AML_TO_BUFFER_OP            (u16) 0x96 /* ACPI 2.0 */
-#define AML_TO_DECSTRING_OP         (u16) 0x97 /* ACPI 2.0 */
-#define AML_TO_HEXSTRING_OP         (u16) 0x98 /* ACPI 2.0 */
+#define AML_TO_DECIMAL_STRING_OP    (u16) 0x97 /* ACPI 2.0 */
+#define AML_TO_HEX_STRING_OP        (u16) 0x98 /* ACPI 2.0 */
 #define AML_TO_INTEGER_OP           (u16) 0x99 /* ACPI 2.0 */
 #define AML_TO_STRING_OP            (u16) 0x9c /* ACPI 2.0 */
-#define AML_COPY_OP                 (u16) 0x9d /* ACPI 2.0 */
+#define AML_COPY_OBJECT_OP          (u16) 0x9d /* ACPI 2.0 */
 #define AML_MID_OP                  (u16) 0x9e /* ACPI 2.0 */
 #define AML_CONTINUE_OP             (u16) 0x9f /* ACPI 2.0 */
 #define AML_IF_OP                   (u16) 0xa0
 #define AML_NOOP_OP                 (u16) 0xa3
 #define AML_RETURN_OP               (u16) 0xa4
 #define AML_BREAK_OP                (u16) 0xa5
-#define AML_BREAK_POINT_OP          (u16) 0xcc
+#define AML_COMMENT_OP              (u16) 0xa9
+#define AML_BREAKPOINT_OP          (u16) 0xcc
 #define AML_ONES_OP                 (u16) 0xff
 
-/* prefixed opcodes */
+/*
+ * Combination opcodes (actually two one-byte opcodes)
+ * Used by the disassembler and iASL compiler
+ */
+#define AML_LOGICAL_GREATER_EQUAL_OP (u16) 0x9295      /* LNot (LLess) */
+#define AML_LOGICAL_LESS_EQUAL_OP    (u16) 0x9294      /* LNot (LGreater) */
+#define AML_LOGICAL_NOT_EQUAL_OP     (u16) 0x9293      /* LNot (LEqual) */
+
+/* Prefixed (2-byte) opcodes (with AML_EXTENDED_PREFIX) */
 
-#define AML_EXTENDED_OPCODE         (u16) 0x5b00       /* prefix for 2-byte opcodes */
+#define AML_EXTENDED_OPCODE         (u16) 0x5b00       /* Prefix for 2-byte opcodes */
 
 #define AML_MUTEX_OP                (u16) 0x5b01
 #define AML_EVENT_OP                (u16) 0x5b02
-#define AML_SHIFT_RIGHT_BIT_OP      (u16) 0x5b10
-#define AML_SHIFT_LEFT_BIT_OP       (u16) 0x5b11
-#define AML_COND_REF_OF_OP          (u16) 0x5b12
+#define AML_SHIFT_RIGHT_BIT_OP      (u16) 0x5b10       /* Obsolete, not in ACPI spec */
+#define AML_SHIFT_LEFT_BIT_OP       (u16) 0x5b11       /* Obsolete, not in ACPI spec */
+#define AML_CONDITIONAL_REF_OF_OP   (u16) 0x5b12
 #define AML_CREATE_FIELD_OP         (u16) 0x5b13
 #define AML_LOAD_TABLE_OP           (u16) 0x5b1f       /* ACPI 2.0 */
 #define AML_LOAD_OP                 (u16) 0x5b20
 #define AML_FIELD_OP                (u16) 0x5b81
 #define AML_DEVICE_OP               (u16) 0x5b82
 #define AML_PROCESSOR_OP            (u16) 0x5b83
-#define AML_POWER_RES_OP            (u16) 0x5b84
+#define AML_POWER_RESOURCE_OP       (u16) 0x5b84
 #define AML_THERMAL_ZONE_OP         (u16) 0x5b85
 #define AML_INDEX_FIELD_OP          (u16) 0x5b86
 #define AML_BANK_FIELD_OP           (u16) 0x5b87
 #define AML_DATA_REGION_OP          (u16) 0x5b88       /* ACPI 2.0 */
 
-/*
- * Combination opcodes (actually two one-byte opcodes)
- * Used by the disassembler and iASL compiler
- */
-#define AML_LGREATEREQUAL_OP        (u16) 0x9295
-#define AML_LLESSEQUAL_OP           (u16) 0x9294
-#define AML_LNOTEQUAL_OP            (u16) 0x9293
-
 /*
  * Opcodes for "Field" operators
  */
 #define ARGP_SIMPLENAME             0x12       /* name_string | local_term | arg_term */
 #define ARGP_NAME_OR_REF            0x13       /* For object_type only */
 #define ARGP_MAX                    0x13
+#define ARGP_COMMENT                0x14
 
 /*
  * Resolved argument types for the AML Interpreter
 #define ARGI_INVALID_OPCODE         0xFFFFFFFF
 
 /*
- * hash offsets
- */
-#define AML_EXTOP_HASH_OFFSET       22
-#define AML_LNOT_HASH_OFFSET        19
-
-/*
- * opcode groups and types
+ * Some of the flags and types below are of the form:
+ *
+ * AML_FLAGS_EXEC_#A_#T,#R, or
+ * AML_TYPE_EXEC_#A_#T,#R where:
+ *
+ *      #A is the number of required arguments
+ *      #T is the number of target operands
+ *      #R indicates whether there is a return value
  */
-#define OPGRP_NAMED                 0x01
-#define OPGRP_FIELD                 0x02
-#define OPGRP_BYTELIST              0x04
 
 /*
- * Opcode information
+ * Opcode information flags
  */
-
-/* Opcode flags */
-
 #define AML_LOGICAL                 0x0001
 #define AML_LOGICAL_NUMERIC         0x0002
 #define AML_MATH                    0x0004
 #define AML_CONSTANT                0x2000
 #define AML_NO_OPERAND_RESOLVE      0x4000
 
-/* Convenient flag groupings */
+/* Convenient flag groupings of the flags above */
 
 #define AML_FLAGS_EXEC_0A_0T_1R                                     AML_HAS_RETVAL
 #define AML_FLAGS_EXEC_1A_0T_0R     AML_HAS_ARGS       /* Monadic1  */
 
 /*
  * The opcode Type is used in a dispatch table, do not change
- * without updating the table.
+ * or add anything new without updating the table.
  */
 #define AML_TYPE_EXEC_0A_0T_1R      0x00
 #define AML_TYPE_EXEC_1A_0T_0R      0x01       /* Monadic1  */
 
 #define AML_TYPE_METHOD_CALL        0x10
 
-/* Misc */
+/* Miscellaneous types */
 
 #define AML_TYPE_CREATE_FIELD       0x11
 #define AML_TYPE_CREATE_OBJECT      0x12
 #define AML_TYPE_NAMED_SIMPLE       0x16
 #define AML_TYPE_NAMED_COMPLEX      0x17
 #define AML_TYPE_RETURN             0x18
-
 #define AML_TYPE_UNDEFINED          0x19
 #define AML_TYPE_BOGUS              0x1A
 
index 15c8237b8a80a711573300cf504720bd3e6c578d..df62c9245efc2404d30f0af8465c75a59d4cc7a5 100644 (file)
@@ -422,6 +422,7 @@ acpi_db_walk_for_execute(acpi_handle obj_handle,
 
        status = acpi_get_object_info(obj_handle, &obj_info);
        if (ACPI_FAILURE(status)) {
+               ACPI_FREE(pathname);
                return (status);
        }
 
index 205b8e0eded581151f2729ee950325f9d5e53897..8f665d94b8b5cd122019cff8437dfe5bd405113f 100644 (file)
@@ -45,6 +45,7 @@
 #include "accommon.h"
 #include "amlcode.h"
 #include "acdebug.h"
+#include "acinterp.h"
 
 #define _COMPONENT          ACPI_CA_DEBUGGER
 ACPI_MODULE_NAME("dbxface")
@@ -125,7 +126,7 @@ error_exit:
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Called for AML_BREAK_POINT_OP
+ * DESCRIPTION: Called for AML_BREAKPOINT_OP
  *
  ******************************************************************************/
 
@@ -368,7 +369,9 @@ acpi_db_single_step(struct acpi_walk_state *walk_state,
                walk_state->method_breakpoint = 1;      /* Must be non-zero! */
        }
 
+       acpi_ex_exit_interpreter();
        status = acpi_db_start_command(walk_state, op);
+       acpi_ex_enter_interpreter();
 
        /* User commands complete, continue execution of the interrupted method */
 
index d31b49feaa79c308f6878feece2e2ad467963771..f470e81b0499789f63bba32b7e2ae617a169f646 100644 (file)
@@ -347,7 +347,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state *walk_state,
 
                break;
 
-       case AML_BREAK_POINT_OP:
+       case AML_BREAKPOINT_OP:
 
                acpi_db_signal_break_point(walk_state);
 
index adcc72cd53a7a375c30eb61daa70e51b4d102042..27a7de95f7b0acfc5da6c8a37594e5403dcbe615 100644 (file)
@@ -672,7 +672,8 @@ acpi_ds_store_object_to_local(u8 type,
  *
  * FUNCTION:    acpi_ds_method_data_get_type
  *
- * PARAMETERS:  opcode              - Either AML_LOCAL_OP or AML_ARG_OP
+ * PARAMETERS:  opcode              - Either AML_FIRST LOCAL_OP or
+ *                                    AML_FIRST_ARG_OP
  *              index               - Which Local or Arg whose type to get
  *              walk_state          - Current walk state object
  *
index 8deaa16493a07f9382dd335f909b43a90e0c7bb3..7df3152ed8569dd1a60bb96dd0f36d23f812c10e 100644 (file)
@@ -114,7 +114,7 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
                                    ((op->common.parent->common.aml_opcode ==
                                      AML_PACKAGE_OP)
                                     || (op->common.parent->common.aml_opcode ==
-                                        AML_VAR_PACKAGE_OP))) {
+                                        AML_VARIABLE_PACKAGE_OP))) {
                                        /*
                                         * We didn't find the target and we are populating elements
                                         * of a package - ignore if slack enabled. Some ASL code
@@ -144,7 +144,7 @@ acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
 
                if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) ||
                    (op->common.parent->common.aml_opcode ==
-                    AML_VAR_PACKAGE_OP)) {
+                    AML_VARIABLE_PACKAGE_OP)) {
                        /*
                         * Attempt to resolve the node to a value before we insert it into
                         * the package. If this is a reference to a common data type,
@@ -398,7 +398,7 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
 
        parent = op->common.parent;
        while ((parent->common.aml_opcode == AML_PACKAGE_OP) ||
-              (parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) {
+              (parent->common.aml_opcode == AML_VARIABLE_PACKAGE_OP)) {
                parent = parent->common.parent;
        }
 
@@ -769,10 +769,10 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state,
                switch (op_info->type) {
                case AML_TYPE_LOCAL_VARIABLE:
 
-                       /* Local ID (0-7) is (AML opcode - base AML_LOCAL_OP) */
+                       /* Local ID (0-7) is (AML opcode - base AML_FIRST_LOCAL_OP) */
 
                        obj_desc->reference.value =
-                           ((u32)opcode) - AML_LOCAL_OP;
+                           ((u32)opcode) - AML_FIRST_LOCAL_OP;
                        obj_desc->reference.class = ACPI_REFCLASS_LOCAL;
 
 #ifndef ACPI_NO_METHOD_EXECUTION
@@ -790,9 +790,10 @@ acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state,
 
                case AML_TYPE_METHOD_ARGUMENT:
 
-                       /* Arg ID (0-6) is (AML opcode - base AML_ARG_OP) */
+                       /* Arg ID (0-6) is (AML opcode - base AML_FIRST_ARG_OP) */
 
-                       obj_desc->reference.value = ((u32)opcode) - AML_ARG_OP;
+                       obj_desc->reference.value =
+                           ((u32)opcode) - AML_FIRST_ARG_OP;
                        obj_desc->reference.class = ACPI_REFCLASS_ARG;
 
 #ifndef ACPI_NO_METHOD_EXECUTION
index 148523205d4151276e32a07d15fcf46709622c9a..9a8f8a992b3e3f9409a1f35d68b4a1f907ac313c 100644 (file)
@@ -639,7 +639,7 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state,
                break;
 
        case AML_PACKAGE_OP:
-       case AML_VAR_PACKAGE_OP:
+       case AML_VARIABLE_PACKAGE_OP:
 
                status =
                    acpi_ds_build_internal_package_obj(walk_state, op, length,
@@ -660,7 +660,7 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state,
                if ((!op->common.parent) ||
                    ((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) &&
                     (op->common.parent->common.aml_opcode !=
-                     AML_VAR_PACKAGE_OP)
+                     AML_VARIABLE_PACKAGE_OP)
                     && (op->common.parent->common.aml_opcode !=
                         AML_NAME_OP))) {
                        walk_state->result_obj = obj_desc;
index 049fbab4e5a6183c4d1225a143ecdb5946b35eb8..406edec20de7222a6dcd9f671db58df48f6c7579 100644 (file)
@@ -275,9 +275,9 @@ acpi_ds_is_result_used(union acpi_parse_object * op,
                if ((op->common.parent->common.aml_opcode == AML_REGION_OP) ||
                    (op->common.parent->common.aml_opcode == AML_DATA_REGION_OP)
                    || (op->common.parent->common.aml_opcode == AML_PACKAGE_OP)
-                   || (op->common.parent->common.aml_opcode ==
-                       AML_VAR_PACKAGE_OP)
                    || (op->common.parent->common.aml_opcode == AML_BUFFER_OP)
+                   || (op->common.parent->common.aml_opcode ==
+                       AML_VARIABLE_PACKAGE_OP)
                    || (op->common.parent->common.aml_opcode ==
                        AML_INT_EVAL_SUBTREE_OP)
                    || (op->common.parent->common.aml_opcode ==
@@ -551,7 +551,7 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
                         */
                        if (status == AE_NOT_FOUND) {
                                if (parent_op->common.aml_opcode ==
-                                   AML_COND_REF_OF_OP) {
+                                   AML_CONDITIONAL_REF_OF_OP) {
                                        /*
                                         * For the Conditional Reference op, it's OK if
                                         * the name is not found;  We just need a way to
@@ -806,7 +806,7 @@ acpi_status acpi_ds_evaluate_name_path(struct acpi_walk_state *walk_state)
        }
 
        if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) ||
-           (op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP) ||
+           (op->common.parent->common.aml_opcode == AML_VARIABLE_PACKAGE_OP) ||
            (op->common.parent->common.aml_opcode == AML_REF_OF_OP)) {
 
                /* TBD: Should we specify this feature as a bit of op_info->Flags of these opcodes? */
index 78f8e6a4f72f241abb79239abd56aae88bef87b0..a2ff8ad70d581fe267075a3e33bd55cefe18e477 100644 (file)
@@ -497,7 +497,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
                        if ((op->asl.parent) &&
                            ((op->asl.parent->asl.aml_opcode == AML_PACKAGE_OP)
                             || (op->asl.parent->asl.aml_opcode ==
-                                AML_VAR_PACKAGE_OP))) {
+                                AML_VARIABLE_PACKAGE_OP))) {
                                ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
                                                  "Method Reference in a Package, Op=%p\n",
                                                  op));
index 44d4553dfbdd24d80379b23c2689942423f9afdd..8d510c7e20c89f43908586eecb3f998f6e435a5e 100644 (file)
@@ -528,7 +528,7 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
                        status = acpi_ex_create_processor(walk_state);
                        break;
 
-               case AML_POWER_RES_OP:
+               case AML_POWER_RESOURCE_OP:
 
                        status = acpi_ex_create_power_resource(walk_state);
                        break;
index 1a6f59079ea54449e1d917be49b895e5b153aab0..f222a80ca38ef75ec8827fba5dd2dcfd6d2dc180 100644 (file)
@@ -249,14 +249,14 @@ acpi_ex_do_logical_numeric_op(u16 opcode,
        ACPI_FUNCTION_TRACE(ex_do_logical_numeric_op);
 
        switch (opcode) {
-       case AML_LAND_OP:       /* LAnd (Integer0, Integer1) */
+       case AML_LOGICAL_AND_OP:        /* LAnd (Integer0, Integer1) */
 
                if (integer0 && integer1) {
                        local_result = TRUE;
                }
                break;
 
-       case AML_LOR_OP:        /* LOr (Integer0, Integer1) */
+       case AML_LOGICAL_OR_OP: /* LOr (Integer0, Integer1) */
 
                if (integer0 || integer1) {
                        local_result = TRUE;
@@ -365,21 +365,21 @@ acpi_ex_do_logical_op(u16 opcode,
                integer1 = local_operand1->integer.value;
 
                switch (opcode) {
-               case AML_LEQUAL_OP:     /* LEqual (Operand0, Operand1) */
+               case AML_LOGICAL_EQUAL_OP:      /* LEqual (Operand0, Operand1) */
 
                        if (integer0 == integer1) {
                                local_result = TRUE;
                        }
                        break;
 
-               case AML_LGREATER_OP:   /* LGreater (Operand0, Operand1) */
+               case AML_LOGICAL_GREATER_OP:    /* LGreater (Operand0, Operand1) */
 
                        if (integer0 > integer1) {
                                local_result = TRUE;
                        }
                        break;
 
-               case AML_LLESS_OP:      /* LLess (Operand0, Operand1) */
+               case AML_LOGICAL_LESS_OP:       /* LLess (Operand0, Operand1) */
 
                        if (integer0 < integer1) {
                                local_result = TRUE;
@@ -408,7 +408,7 @@ acpi_ex_do_logical_op(u16 opcode,
                                 (length0 > length1) ? length1 : length0);
 
                switch (opcode) {
-               case AML_LEQUAL_OP:     /* LEqual (Operand0, Operand1) */
+               case AML_LOGICAL_EQUAL_OP:      /* LEqual (Operand0, Operand1) */
 
                        /* Length and all bytes must be equal */
 
@@ -420,7 +420,7 @@ acpi_ex_do_logical_op(u16 opcode,
                        }
                        break;
 
-               case AML_LGREATER_OP:   /* LGreater (Operand0, Operand1) */
+               case AML_LOGICAL_GREATER_OP:    /* LGreater (Operand0, Operand1) */
 
                        if (compare > 0) {
                                local_result = TRUE;
@@ -437,7 +437,7 @@ acpi_ex_do_logical_op(u16 opcode,
                        }
                        break;
 
-               case AML_LLESS_OP:      /* LLess (Operand0, Operand1) */
+               case AML_LOGICAL_LESS_OP:       /* LLess (Operand0, Operand1) */
 
                        if (compare > 0) {
                                goto cleanup;   /* FALSE */
index ee7b62a86661644b64b31a830170a0ddcc36b2a7..caa5ed1f65eca274f08ecf0ad6eaad6acea5dca0 100644 (file)
@@ -122,7 +122,7 @@ static char *acpi_ex_allocate_name_string(u32 prefix_count, u32 num_name_segs)
 
                /* Set up multi prefixes   */
 
-               *temp_ptr++ = AML_MULTI_NAME_PREFIX_OP;
+               *temp_ptr++ = AML_MULTI_NAME_PREFIX;
                *temp_ptr++ = (char)num_name_segs;
        } else if (2 == num_name_segs) {
 
@@ -342,7 +342,7 @@ acpi_ex_get_name_string(acpi_object_type data_type,
                        }
                        break;
 
-               case AML_MULTI_NAME_PREFIX_OP:
+               case AML_MULTI_NAME_PREFIX:
 
                        ACPI_DEBUG_PRINT((ACPI_DB_LOAD,
                                          "MultiNamePrefix at %p\n",
index af73fcde7e5c2e1e73e8e6cd298be8bd5216c6b8..e327349675cdb5451334a611e9ebf6bf7c105b6f 100644 (file)
@@ -274,7 +274,7 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state)
        case AML_FIND_SET_RIGHT_BIT_OP:
        case AML_FROM_BCD_OP:
        case AML_TO_BCD_OP:
-       case AML_COND_REF_OF_OP:
+       case AML_CONDITIONAL_REF_OF_OP:
 
                /* Create a return object of type Integer for these opcodes */
 
@@ -405,7 +405,7 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state)
                        }
                        break;
 
-               case AML_COND_REF_OF_OP:        /* cond_ref_of (source_object, Result) */
+               case AML_CONDITIONAL_REF_OF_OP: /* cond_ref_of (source_object, Result) */
                        /*
                         * This op is a little strange because the internal return value is
                         * different than the return value stored in the result descriptor
@@ -475,14 +475,14 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state)
                /*
                 * ACPI 2.0 Opcodes
                 */
-       case AML_COPY_OP:       /* Copy (Source, Target) */
+       case AML_COPY_OBJECT_OP:        /* copy_object (Source, Target) */
 
                status =
                    acpi_ut_copy_iobject_to_iobject(operand[0], &return_desc,
                                                    walk_state);
                break;
 
-       case AML_TO_DECSTRING_OP:       /* to_decimal_string (Data, Result) */
+       case AML_TO_DECIMAL_STRING_OP:  /* to_decimal_string (Data, Result) */
 
                status =
                    acpi_ex_convert_to_string(operand[0], &return_desc,
@@ -495,7 +495,7 @@ acpi_status acpi_ex_opcode_1A_1T_1R(struct acpi_walk_state *walk_state)
                }
                break;
 
-       case AML_TO_HEXSTRING_OP:       /* to_hex_string (Data, Result) */
+       case AML_TO_HEX_STRING_OP:      /* to_hex_string (Data, Result) */
 
                status =
                    acpi_ex_convert_to_string(operand[0], &return_desc,
@@ -603,7 +603,7 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
        /* Examine the AML opcode */
 
        switch (walk_state->opcode) {
-       case AML_LNOT_OP:       /* LNot (Operand) */
+       case AML_LOGICAL_NOT_OP:        /* LNot (Operand) */
 
                return_desc = acpi_ut_create_integer_object((u64) 0);
                if (!return_desc) {
@@ -652,9 +652,8 @@ acpi_status acpi_ex_opcode_1A_0T_1R(struct acpi_walk_state *walk_state)
                 * NOTE:  We use LNOT_OP here in order to force resolution of the
                 * reference operand to an actual integer.
                 */
-               status =
-                   acpi_ex_resolve_operands(AML_LNOT_OP, &temp_desc,
-                                            walk_state);
+               status = acpi_ex_resolve_operands(AML_LOGICAL_NOT_OP,
+                                                 &temp_desc, walk_state);
                if (ACPI_FAILURE(status)) {
                        ACPI_EXCEPTION((AE_INFO, status,
                                        "While resolving operands for [%s]",
index 44ecba50c0da258b1bf10c52263b29a27dc7239e..eecb3bff7fd749b6e6d8f9f9ea151728d2b2a638 100644 (file)
@@ -298,7 +298,7 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
                                        NULL, &return_desc->integer.value);
                break;
 
-       case AML_CONCAT_OP:     /* Concatenate (Data1, Data2, Result) */
+       case AML_CONCATENATE_OP:        /* Concatenate (Data1, Data2, Result) */
 
                status =
                    acpi_ex_do_concatenate(operand[0], operand[1], &return_desc,
@@ -343,7 +343,7 @@ acpi_status acpi_ex_opcode_2A_1T_1R(struct acpi_walk_state *walk_state)
                       operand[0]->buffer.pointer, length);
                break;
 
-       case AML_CONCAT_RES_OP:
+       case AML_CONCATENATE_TEMPLATE_OP:
 
                /* concatenate_res_template (Buffer, Buffer, Result) (ACPI 2.0) */
 
index 31e4df97cbe1852728b43785d37159417cd784b4..688032b58a213be43686c222843cd656ea7f87a4 100644 (file)
@@ -124,8 +124,8 @@ acpi_ex_do_match(u32 match_op,
                 * Change to:     (M == P[i])
                 */
                status =
-                   acpi_ex_do_logical_op(AML_LEQUAL_OP, match_obj, package_obj,
-                                         &logical_result);
+                   acpi_ex_do_logical_op(AML_LOGICAL_EQUAL_OP, match_obj,
+                                         package_obj, &logical_result);
                if (ACPI_FAILURE(status)) {
                        return (FALSE);
                }
@@ -137,8 +137,8 @@ acpi_ex_do_match(u32 match_op,
                 * Change to:                  (M >= P[i]) (M not_less than P[i])
                 */
                status =
-                   acpi_ex_do_logical_op(AML_LLESS_OP, match_obj, package_obj,
-                                         &logical_result);
+                   acpi_ex_do_logical_op(AML_LOGICAL_LESS_OP, match_obj,
+                                         package_obj, &logical_result);
                if (ACPI_FAILURE(status)) {
                        return (FALSE);
                }
@@ -151,7 +151,7 @@ acpi_ex_do_match(u32 match_op,
                 * Change to:         (M > P[i])
                 */
                status =
-                   acpi_ex_do_logical_op(AML_LGREATER_OP, match_obj,
+                   acpi_ex_do_logical_op(AML_LOGICAL_GREATER_OP, match_obj,
                                          package_obj, &logical_result);
                if (ACPI_FAILURE(status)) {
                        return (FALSE);
@@ -164,7 +164,7 @@ acpi_ex_do_match(u32 match_op,
                 * Change to:                     (M <= P[i]) (M not_greater than P[i])
                 */
                status =
-                   acpi_ex_do_logical_op(AML_LGREATER_OP, match_obj,
+                   acpi_ex_do_logical_op(AML_LOGICAL_GREATER_OP, match_obj,
                                          package_obj, &logical_result);
                if (ACPI_FAILURE(status)) {
                        return (FALSE);
@@ -178,8 +178,8 @@ acpi_ex_do_match(u32 match_op,
                 * Change to:            (M < P[i])
                 */
                status =
-                   acpi_ex_do_logical_op(AML_LLESS_OP, match_obj, package_obj,
-                                         &logical_result);
+                   acpi_ex_do_logical_op(AML_LOGICAL_LESS_OP, match_obj,
+                                         package_obj, &logical_result);
                if (ACPI_FAILURE(status)) {
                        return (FALSE);
                }
index 7fecefc2e1b4665f73c9797f698f0fb743128010..aa8c6fd74cc393413c96f3e88b8e4cabf9f39618 100644 (file)
@@ -196,7 +196,8 @@ acpi_ex_resolve_object_to_value(union acpi_operand_object **stack_ptr,
 
                                if ((walk_state->opcode ==
                                     AML_INT_METHODCALL_OP)
-                                   || (walk_state->opcode == AML_COPY_OP)) {
+                                   || (walk_state->opcode ==
+                                       AML_COPY_OBJECT_OP)) {
                                        break;
                                }
 
index a2f8001aeb862edf54059f2c698d5d0d021d8f11..bdd43cde8f3641313d9341f036109c57b3c1586d 100644 (file)
@@ -416,7 +416,7 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc,
 
        /* Only limited target types possible for everything except copy_object */
 
-       if (walk_state->opcode != AML_COPY_OP) {
+       if (walk_state->opcode != AML_COPY_OBJECT_OP) {
                /*
                 * Only copy_object allows all object types to be overwritten. For
                 * target_ref(s), there are restrictions on the object types that
@@ -499,7 +499,8 @@ acpi_ex_store_object_to_node(union acpi_operand_object *source_desc,
        case ACPI_TYPE_STRING:
        case ACPI_TYPE_BUFFER:
 
-               if ((walk_state->opcode == AML_COPY_OP) || !implicit_conversion) {
+               if ((walk_state->opcode == AML_COPY_OBJECT_OP) ||
+                   !implicit_conversion) {
                        /*
                         * However, copy_object and Stores to arg_x do not perform
                         * an implicit conversion, as per the ACPI specification.
index 85db4716a043dbaabe9f4b64ae47f5624e65006e..56f59cf5da2934391c7763c2fd285aea8fcb96c5 100644 (file)
@@ -107,7 +107,7 @@ acpi_ex_resolve_object(union acpi_operand_object **source_desc_ptr,
 
                /* For copy_object, no further validation necessary */
 
-               if (walk_state->opcode == AML_COPY_OP) {
+               if (walk_state->opcode == AML_COPY_OBJECT_OP) {
                        break;
                }
 
index 531620abed803c7ffac13ba6425e9be0486684d3..3094cec4eab47aea503dfbadd55a019cc971ecce 100644 (file)
@@ -102,7 +102,7 @@ static const struct acpi_port_info acpi_protected_ports[] = {
        {"PCI", 0x0CF8, 0x0CFF, ACPI_OSI_WIN_XP}
 };
 
-#define ACPI_PORT_INFO_ENTRIES  ACPI_ARRAY_LENGTH (acpi_protected_ports)
+#define ACPI_PORT_INFO_ENTRIES      ACPI_ARRAY_LENGTH (acpi_protected_ports)
 
 /******************************************************************************
  *
@@ -128,7 +128,7 @@ acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width)
        acpi_io_address last_address;
        const struct acpi_port_info *port_info;
 
-       ACPI_FUNCTION_TRACE(hw_validate_io_request);
+       ACPI_FUNCTION_NAME(hw_validate_io_request);
 
        /* Supported widths are 8/16/32 */
 
@@ -153,13 +153,13 @@ acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width)
                ACPI_ERROR((AE_INFO,
                            "Illegal I/O port address/length above 64K: %8.8X%8.8X/0x%X",
                            ACPI_FORMAT_UINT64(address), byte_width));
-               return_ACPI_STATUS(AE_LIMIT);
+               return (AE_LIMIT);
        }
 
        /* Exit if requested address is not within the protected port table */
 
        if (address > acpi_protected_ports[ACPI_PORT_INFO_ENTRIES - 1].end) {
-               return_ACPI_STATUS(AE_OK);
+               return (AE_OK);
        }
 
        /* Check request against the list of protected I/O ports */
@@ -167,7 +167,7 @@ acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width)
        for (i = 0; i < ACPI_PORT_INFO_ENTRIES; i++, port_info++) {
                /*
                 * Check if the requested address range will write to a reserved
-                * port. Four cases to consider:
+                * port. There are four cases to consider:
                 *
                 * 1) Address range is contained completely in the port address range
                 * 2) Address range overlaps port range at the port range start
@@ -198,7 +198,7 @@ acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width)
                }
        }
 
-       return_ACPI_STATUS(AE_OK);
+       return (AE_OK);
 }
 
 /******************************************************************************
@@ -206,7 +206,7 @@ acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width)
  * FUNCTION:    acpi_hw_read_port
  *
  * PARAMETERS:  Address             Address of I/O port/register to read
- *              Value               Where value is placed
+ *              Value               Where value (data) is returned
  *              Width               Number of bits
  *
  * RETURN:      Status and value read from port
@@ -244,7 +244,7 @@ acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width)
        /*
         * There has been a protection violation within the request. Fall
         * back to byte granularity port I/O and ignore the failing bytes.
-        * This provides Windows compatibility.
+        * This provides compatibility with other ACPI implementations.
         */
        for (i = 0, *value = 0; i < width; i += 8) {
 
@@ -307,7 +307,7 @@ acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width)
        /*
         * There has been a protection violation within the request. Fall
         * back to byte granularity port I/O and ignore the failing bytes.
-        * This provides Windows compatibility.
+        * This provides compatibility with other ACPI implementations.
         */
        for (i = 0; i < width; i += 8) {
 
index 498bb8f70e6beba2506c822fed98b97f6f8d30e7..fb265b5737de7b70409261139f50ec454cba6e15 100644 (file)
@@ -485,7 +485,7 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
                                          flags));
                        break;
 
-               case AML_MULTI_NAME_PREFIX_OP:
+               case AML_MULTI_NAME_PREFIX:
 
                        /* More than one name_seg, search rules do not apply */
 
index 38316266521ea3f67367c1b4549a5166ec4cd750..418ef2ac82abed3bf64f1d8442fdeabb82bd3d9a 100644 (file)
@@ -290,22 +290,12 @@ object_repaired:
        /* Object was successfully repaired */
 
        if (package_index != ACPI_NOT_PACKAGE_ELEMENT) {
-               /*
-                * The original object is a package element. We need to
-                * decrement the reference count of the original object,
-                * for removing it from the package.
-                *
-                * However, if the original object was just wrapped with a
-                * package object as part of the repair, we don't need to
-                * change the reference count.
-                */
+
+               /* Update reference count of new object */
+
                if (!(info->return_flags & ACPI_OBJECT_WRAPPED)) {
                        new_object->common.reference_count =
                            return_object->common.reference_count;
-
-                       if (return_object->common.reference_count > 1) {
-                               return_object->common.reference_count--;
-                       }
                }
 
                ACPI_DEBUG_PRINT((ACPI_DB_REPAIR,
index 352265498e90e9298ab7cf4fe0c6a715de478d0c..06037e0446941368c6702411e8054ae5a7644e6a 100644 (file)
@@ -403,16 +403,12 @@ acpi_ns_repair_CID(struct acpi_evaluate_info *info,
                        return (status);
                }
 
-               /* Take care with reference counts */
-
                if (original_element != *element_ptr) {
 
-                       /* Element was replaced */
+                       /* Update reference count of new object */
 
                        (*element_ptr)->common.reference_count =
                            original_ref_count;
-
-                       acpi_ut_remove_reference(original_element);
                }
 
                element_ptr++;
index 661676714f7b8227e58e2f6343946ad4c1685eab..2fe87d0dd9d5039e78d9c0e862830480b7620d7d 100644 (file)
@@ -252,7 +252,7 @@ acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info)
                        internal_name[1] = AML_DUAL_NAME_PREFIX;
                        result = &internal_name[2];
                } else {
-                       internal_name[1] = AML_MULTI_NAME_PREFIX_OP;
+                       internal_name[1] = AML_MULTI_NAME_PREFIX;
                        internal_name[2] = (char)num_segments;
                        result = &internal_name[3];
                }
@@ -274,7 +274,7 @@ acpi_status acpi_ns_build_internal_name(struct acpi_namestring_info *info)
                        internal_name[i] = AML_DUAL_NAME_PREFIX;
                        result = &internal_name[(acpi_size)i + 1];
                } else {
-                       internal_name[i] = AML_MULTI_NAME_PREFIX_OP;
+                       internal_name[i] = AML_MULTI_NAME_PREFIX;
                        internal_name[(acpi_size)i + 1] = (char)num_segments;
                        result = &internal_name[(acpi_size)i + 2];
                }
@@ -450,7 +450,7 @@ acpi_ns_externalize_name(u32 internal_name_length,
         */
        if (prefix_length < internal_name_length) {
                switch (internal_name[prefix_length]) {
-               case AML_MULTI_NAME_PREFIX_OP:
+               case AML_MULTI_NAME_PREFIX:
 
                        /* <count> 4-byte names */
 
@@ -594,25 +594,20 @@ struct acpi_namespace_node *acpi_ns_validate_handle(acpi_handle handle)
 void acpi_ns_terminate(void)
 {
        acpi_status status;
+       union acpi_operand_object *prev;
+       union acpi_operand_object *next;
 
        ACPI_FUNCTION_TRACE(ns_terminate);
 
-#ifdef ACPI_EXEC_APP
-       {
-               union acpi_operand_object *prev;
-               union acpi_operand_object *next;
+       /* Delete any module-level code blocks */
 
-               /* Delete any module-level code blocks */
-
-               next = acpi_gbl_module_code_list;
-               while (next) {
-                       prev = next;
-                       next = next->method.mutex;
-                       prev->method.mutex = NULL;      /* Clear the Mutex (cheated) field */
-                       acpi_ut_remove_reference(prev);
-               }
+       next = acpi_gbl_module_code_list;
+       while (next) {
+               prev = next;
+               next = next->method.mutex;
+               prev->method.mutex = NULL;      /* Clear the Mutex (cheated) field */
+               acpi_ut_remove_reference(prev);
        }
-#endif
 
        /*
         * Free the entire namespace -- all nodes and all objects
index 05b62ad44c3ecb4f3d4943695113a36026d0d5a7..eb9dfaca555fe31d0a0c318c682268fa3ffece11 100644 (file)
@@ -47,6 +47,7 @@
 #include "amlcode.h"
 #include "acnamesp.h"
 #include "acdispat.h"
+#include "acconvert.h"
 
 #define _COMPONENT          ACPI_PARSER
 ACPI_MODULE_NAME("psargs")
@@ -186,7 +187,7 @@ char *acpi_ps_get_next_namestring(struct acpi_parse_state *parser_state)
                end += 1 + (2 * ACPI_NAME_SIZE);
                break;
 
-       case AML_MULTI_NAME_PREFIX_OP:
+       case AML_MULTI_NAME_PREFIX:
 
                /* Multiple name segments, 4 chars each, count in next byte */
 
@@ -339,7 +340,7 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state,
                /* 2) not_found during a cond_ref_of(x) is ok by definition */
 
                else if (walk_state->op->common.aml_opcode ==
-                        AML_COND_REF_OF_OP) {
+                        AML_CONDITIONAL_REF_OF_OP) {
                        status = AE_OK;
                }
 
@@ -352,7 +353,7 @@ acpi_ps_get_next_namepath(struct acpi_walk_state *walk_state,
                         ((arg->common.parent->common.aml_opcode ==
                           AML_PACKAGE_OP)
                          || (arg->common.parent->common.aml_opcode ==
-                             AML_VAR_PACKAGE_OP))) {
+                             AML_VARIABLE_PACKAGE_OP))) {
                        status = AE_OK;
                }
        }
@@ -502,6 +503,7 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
 
        ACPI_FUNCTION_TRACE(ps_get_next_field);
 
+       ASL_CV_CAPTURE_COMMENTS_ONLY(parser_state);
        aml = parser_state->aml;
 
        /* Determine field type */
@@ -546,6 +548,7 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
 
        /* Decode the field type */
 
+       ASL_CV_CAPTURE_COMMENTS_ONLY(parser_state);
        switch (opcode) {
        case AML_INT_NAMEDFIELD_OP:
 
@@ -555,6 +558,22 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
                acpi_ps_set_name(field, name);
                parser_state->aml += ACPI_NAME_SIZE;
 
+               ASL_CV_CAPTURE_COMMENTS_ONLY(parser_state);
+
+#ifdef ACPI_ASL_COMPILER
+               /*
+                * Because the package length isn't represented as a parse tree object,
+                * take comments surrounding this and add to the previously created
+                * parse node.
+                */
+               if (field->common.inline_comment) {
+                       field->common.name_comment =
+                           field->common.inline_comment;
+               }
+               field->common.inline_comment = acpi_gbl_current_inline_comment;
+               acpi_gbl_current_inline_comment = NULL;
+#endif
+
                /* Get the length which is encoded as a package length */
 
                field->common.value.size =
@@ -609,11 +628,13 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
                if (ACPI_GET8(parser_state->aml) == AML_BUFFER_OP) {
                        parser_state->aml++;
 
+                       ASL_CV_CAPTURE_COMMENTS_ONLY(parser_state);
                        pkg_end = parser_state->aml;
                        pkg_length =
                            acpi_ps_get_next_package_length(parser_state);
                        pkg_end += pkg_length;
 
+                       ASL_CV_CAPTURE_COMMENTS_ONLY(parser_state);
                        if (parser_state->aml < pkg_end) {
 
                                /* Non-empty list */
@@ -630,6 +651,7 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
                                opcode = ACPI_GET8(parser_state->aml);
                                parser_state->aml++;
 
+                               ASL_CV_CAPTURE_COMMENTS_ONLY(parser_state);
                                switch (opcode) {
                                case AML_BYTE_OP:       /* AML_BYTEDATA_ARG */
 
@@ -660,6 +682,7 @@ static union acpi_parse_object *acpi_ps_get_next_field(struct acpi_parse_state
 
                                /* Fill in bytelist data */
 
+                               ASL_CV_CAPTURE_COMMENTS_ONLY(parser_state);
                                arg->named.value.size = buffer_length;
                                arg->named.data = parser_state->aml;
                        }
index 14d689606d2f5695c7a9c956bd62a3e2795a195a..b4224005783c6d1c2fbf6f8bb970e6216ddd788a 100644 (file)
@@ -55,6 +55,7 @@
 #include "acparser.h"
 #include "acdispat.h"
 #include "amlcode.h"
+#include "acconvert.h"
 
 #define _COMPONENT          ACPI_PARSER
 ACPI_MODULE_NAME("psloop")
@@ -132,6 +133,21 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
                       !walk_state->arg_count) {
                        walk_state->aml = walk_state->parser_state.aml;
 
+                       switch (op->common.aml_opcode) {
+                       case AML_METHOD_OP:
+                       case AML_BUFFER_OP:
+                       case AML_PACKAGE_OP:
+                       case AML_VARIABLE_PACKAGE_OP:
+                       case AML_WHILE_OP:
+
+                               break;
+
+                       default:
+
+                               ASL_CV_CAPTURE_COMMENTS(walk_state);
+                               break;
+                       }
+
                        status =
                            acpi_ps_get_next_arg(walk_state,
                                                 &(walk_state->parser_state),
@@ -254,7 +270,7 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
 
                case AML_BUFFER_OP:
                case AML_PACKAGE_OP:
-               case AML_VAR_PACKAGE_OP:
+               case AML_VARIABLE_PACKAGE_OP:
 
                        if ((op->common.parent) &&
                            (op->common.parent->common.aml_opcode ==
@@ -480,6 +496,8 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
        /* Iterative parsing loop, while there is more AML to process: */
 
        while ((parser_state->aml < parser_state->aml_end) || (op)) {
+               ASL_CV_CAPTURE_COMMENTS(walk_state);
+
                aml_op_start = parser_state->aml;
                if (!op) {
                        status =
@@ -516,6 +534,20 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
                 */
                walk_state->arg_count = 0;
 
+               switch (op->common.aml_opcode) {
+               case AML_BYTE_OP:
+               case AML_WORD_OP:
+               case AML_DWORD_OP:
+               case AML_QWORD_OP:
+
+                       break;
+
+               default:
+
+                       ASL_CV_CAPTURE_COMMENTS(walk_state);
+                       break;
+               }
+
                /* Are there any arguments that must be processed? */
 
                if (walk_state->arg_types) {
index 5c4aff0f4f26e116a0c4e125883fb1eda97c072c..5bcb61831706a3902f5baac24cf366ccf4608df7 100644 (file)
@@ -45,6 +45,7 @@
 #include "accommon.h"
 #include "acparser.h"
 #include "amlcode.h"
+#include "acconvert.h"
 
 #define _COMPONENT          ACPI_PARSER
 ACPI_MODULE_NAME("psobject")
@@ -190,6 +191,7 @@ acpi_ps_build_named_op(struct acpi_walk_state *walk_state,
         */
        while (GET_CURRENT_ARG_TYPE(walk_state->arg_types) &&
               (GET_CURRENT_ARG_TYPE(walk_state->arg_types) != ARGP_NAME)) {
+               ASL_CV_CAPTURE_COMMENTS(walk_state);
                status =
                    acpi_ps_get_next_arg(walk_state,
                                         &(walk_state->parser_state),
@@ -203,6 +205,18 @@ acpi_ps_build_named_op(struct acpi_walk_state *walk_state,
                INCREMENT_ARG_LIST(walk_state->arg_types);
        }
 
+       /* are there any inline comments associated with the name_seg?? If so, save this. */
+
+       ASL_CV_CAPTURE_COMMENTS(walk_state);
+
+#ifdef ACPI_ASL_COMPILER
+       if (acpi_gbl_current_inline_comment != NULL) {
+               unnamed_op->common.name_comment =
+                   acpi_gbl_current_inline_comment;
+               acpi_gbl_current_inline_comment = NULL;
+       }
+#endif
+
        /*
         * Make sure that we found a NAME and didn't run out of arguments
         */
@@ -243,6 +257,30 @@ acpi_ps_build_named_op(struct acpi_walk_state *walk_state,
 
        acpi_ps_append_arg(*op, unnamed_op->common.value.arg);
 
+#ifdef ACPI_ASL_COMPILER
+
+       /* save any comments that might be associated with unnamed_op. */
+
+       (*op)->common.inline_comment = unnamed_op->common.inline_comment;
+       (*op)->common.end_node_comment = unnamed_op->common.end_node_comment;
+       (*op)->common.close_brace_comment =
+           unnamed_op->common.close_brace_comment;
+       (*op)->common.name_comment = unnamed_op->common.name_comment;
+       (*op)->common.comment_list = unnamed_op->common.comment_list;
+       (*op)->common.end_blk_comment = unnamed_op->common.end_blk_comment;
+       (*op)->common.cv_filename = unnamed_op->common.cv_filename;
+       (*op)->common.cv_parent_filename =
+           unnamed_op->common.cv_parent_filename;
+       (*op)->named.aml = unnamed_op->common.aml;
+
+       unnamed_op->common.inline_comment = NULL;
+       unnamed_op->common.end_node_comment = NULL;
+       unnamed_op->common.close_brace_comment = NULL;
+       unnamed_op->common.name_comment = NULL;
+       unnamed_op->common.comment_list = NULL;
+       unnamed_op->common.end_blk_comment = NULL;
+#endif
+
        if ((*op)->common.aml_opcode == AML_REGION_OP ||
            (*op)->common.aml_opcode == AML_DATA_REGION_OP) {
                /*
index 451b672915f11f7eacc7c3b6f81148e3c1dd09d2..c343a0d5a3d283ff7fc870038c4dd09b1e87f84e 100644 (file)
@@ -69,7 +69,7 @@ ACPI_MODULE_NAME("psopcode")
        AML_DEVICE_OP
        AML_THERMAL_ZONE_OP
        AML_METHOD_OP
-       AML_POWER_RES_OP
+       AML_POWER_RESOURCE_OP
        AML_PROCESSOR_OP
        AML_FIELD_OP
        AML_INDEX_FIELD_OP
@@ -95,7 +95,7 @@ ACPI_MODULE_NAME("psopcode")
        AML_DEVICE_OP
        AML_THERMAL_ZONE_OP
        AML_METHOD_OP
-       AML_POWER_RES_OP
+       AML_POWER_RESOURCE_OP
        AML_PROCESSOR_OP
        AML_FIELD_OP
        AML_INDEX_FIELD_OP
@@ -113,7 +113,7 @@ ACPI_MODULE_NAME("psopcode")
        AML_DEVICE_OP
        AML_THERMAL_ZONE_OP
        AML_METHOD_OP
-       AML_POWER_RES_OP
+       AML_POWER_RESOURCE_OP
        AML_PROCESSOR_OP
        AML_NAME_OP
        AML_ALIAS_OP
@@ -136,7 +136,7 @@ ACPI_MODULE_NAME("psopcode")
        AML_DEVICE_OP
        AML_THERMAL_ZONE_OP
        AML_METHOD_OP
-       AML_POWER_RES_OP
+       AML_POWER_RESOURCE_OP
        AML_PROCESSOR_OP
        AML_NAME_OP
        AML_ALIAS_OP
@@ -149,7 +149,7 @@ ACPI_MODULE_NAME("psopcode")
   must be deferred until needed
 
        AML_METHOD_OP
-       AML_VAR_PACKAGE_OP
+       AML_VARIABLE_PACKAGE_OP
        AML_CREATE_FIELD_OP
        AML_CREATE_BIT_FIELD_OP
        AML_CREATE_BYTE_FIELD_OP
@@ -652,7 +652,10 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] = {
 
        /* 81 */ ACPI_OP("External", ARGP_EXTERNAL_OP, ARGI_EXTERNAL_OP,
                         ACPI_TYPE_ANY, AML_CLASS_EXECUTE, /* ? */
-                        AML_TYPE_EXEC_3A_0T_0R, AML_FLAGS_EXEC_3A_0T_0R)
+                        AML_TYPE_EXEC_3A_0T_0R, AML_FLAGS_EXEC_3A_0T_0R),
+/* 82 */ ACPI_OP("Comment", ARGP_COMMENT_OP, ARGI_COMMENT_OP,
+                        ACPI_TYPE_STRING, AML_CLASS_ARGUMENT,
+                        AML_TYPE_LITERAL, AML_CONSTANT)
 
 /*! [End] no source code translation !*/
 };
index 89f95b7f26e9ec3f68060a9384b4c25164843507..eff22950232b64a2232cd590598f9005a7c4ab37 100644 (file)
@@ -226,7 +226,7 @@ const u8 acpi_gbl_short_op_index[256] = {
 /* 0x90 */ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x73, 0x74,
 /* 0x98 */ 0x75, 0x76, _UNK, _UNK, 0x77, 0x78, 0x79, 0x7A,
 /* 0xA0 */ 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x60, 0x61,
-/* 0xA8 */ 0x62, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
+/* 0xA8 */ 0x62, 0x82, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
 /* 0xB0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
 /* 0xB8 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
 /* 0xC0 */ _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK, _UNK,
index a813bbbd5a8bc0bf6454e5de8c4c7e3e66b250ae..8116a670de393a6f03a57d1819392e071b1ad918 100644 (file)
@@ -105,7 +105,7 @@ u16 acpi_ps_peek_opcode(struct acpi_parse_state * parser_state)
        aml = parser_state->aml;
        opcode = (u16) ACPI_GET8(aml);
 
-       if (opcode == AML_EXTENDED_OP_PREFIX) {
+       if (opcode == AML_EXTENDED_PREFIX) {
 
                /* Extended opcode, get the second opcode byte */
 
@@ -210,7 +210,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state *walk_state,
                            || (op->common.parent->common.aml_opcode ==
                                AML_BANK_FIELD_OP)
                            || (op->common.parent->common.aml_opcode ==
-                               AML_VAR_PACKAGE_OP)) {
+                               AML_VARIABLE_PACKAGE_OP)) {
                                replacement_op =
                                    acpi_ps_alloc_op(AML_INT_RETURN_VALUE_OP,
                                                     op->common.aml);
@@ -225,7 +225,7 @@ acpi_ps_complete_this_op(struct acpi_walk_state *walk_state,
                                if ((op->common.aml_opcode == AML_BUFFER_OP)
                                    || (op->common.aml_opcode == AML_PACKAGE_OP)
                                    || (op->common.aml_opcode ==
-                                       AML_VAR_PACKAGE_OP)) {
+                                       AML_VARIABLE_PACKAGE_OP)) {
                                        replacement_op =
                                            acpi_ps_alloc_op(op->common.
                                                             aml_opcode,
index 9677fff8fd4723a925ebb3a37fd3e827361b5a28..c06d6e2fc7a5d06394b7893d0de226ad8a449129 100644 (file)
@@ -45,6 +45,7 @@
 #include "accommon.h"
 #include "acparser.h"
 #include "amlcode.h"
+#include "acconvert.h"
 
 #define _COMPONENT          ACPI_PARSER
 ACPI_MODULE_NAME("pstree")
@@ -216,6 +217,7 @@ union acpi_parse_object *acpi_ps_get_depth_next(union acpi_parse_object *origin,
 
        next = acpi_ps_get_arg(op, 0);
        if (next) {
+               ASL_CV_LABEL_FILENODE(next);
                return (next);
        }
 
@@ -223,6 +225,7 @@ union acpi_parse_object *acpi_ps_get_depth_next(union acpi_parse_object *origin,
 
        next = op->common.next;
        if (next) {
+               ASL_CV_LABEL_FILENODE(next);
                return (next);
        }
 
@@ -233,6 +236,8 @@ union acpi_parse_object *acpi_ps_get_depth_next(union acpi_parse_object *origin,
        while (parent) {
                arg = acpi_ps_get_arg(parent, 0);
                while (arg && (arg != origin) && (arg != op)) {
+
+                       ASL_CV_LABEL_FILENODE(arg);
                        arg = arg->common.next;
                }
 
@@ -247,6 +252,7 @@ union acpi_parse_object *acpi_ps_get_depth_next(union acpi_parse_object *origin,
 
                        /* Found sibling of parent */
 
+                       ASL_CV_LABEL_FILENODE(parent->common.next);
                        return (parent->common.next);
                }
 
@@ -254,6 +260,7 @@ union acpi_parse_object *acpi_ps_get_depth_next(union acpi_parse_object *origin,
                parent = parent->common.parent;
        }
 
+       ASL_CV_LABEL_FILENODE(next);
        return (next);
 }
 
@@ -296,7 +303,7 @@ union acpi_parse_object *acpi_ps_get_child(union acpi_parse_object *op)
                child = acpi_ps_get_arg(op, 1);
                break;
 
-       case AML_POWER_RES_OP:
+       case AML_POWER_RESOURCE_OP:
        case AML_INDEX_FIELD_OP:
 
                child = acpi_ps_get_arg(op, 2);
index 2fa38bb76a55d708a3036be3a4a57b30b03cb720..02642760cb93128f77af1e05cc2db489fe0101bd 100644 (file)
@@ -45,6 +45,7 @@
 #include "accommon.h"
 #include "acparser.h"
 #include "amlcode.h"
+#include "acconvert.h"
 
 #define _COMPONENT          ACPI_PARSER
 ACPI_MODULE_NAME("psutils")
@@ -152,6 +153,15 @@ union acpi_parse_object *acpi_ps_alloc_op(u16 opcode, u8 *aml)
                acpi_ps_init_op(op, opcode);
                op->common.aml = aml;
                op->common.flags = flags;
+               ASL_CV_CLEAR_OP_COMMENTS(op);
+
+               if (opcode == AML_SCOPE_OP) {
+                       acpi_gbl_current_scope = op;
+               }
+       }
+
+       if (gbl_capture_comments) {
+               ASL_CV_TRANSFER_COMMENTS(op);
        }
 
        return (op);
@@ -174,6 +184,7 @@ void acpi_ps_free_op(union acpi_parse_object *op)
 {
        ACPI_FUNCTION_NAME(ps_free_op);
 
+       ASL_CV_CLEAR_OP_COMMENTS(op);
        if (op->common.aml_opcode == AML_INT_RETURN_VALUE_OP) {
                ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
                                  "Free retval op: %p\n", op));
index a3401bd29413a17b7a2decec19c406cbc05ab3f2..5594a359dbf178d86a166f1d7ef3d4eb10442858 100644 (file)
@@ -142,6 +142,45 @@ acpi_status acpi_ut_create_caches(void)
        if (ACPI_FAILURE(status)) {
                return (status);
        }
+#ifdef ACPI_ASL_COMPILER
+       /*
+        * For use with the ASL-/ASL+ option. This cache keeps track of regular
+        * 0xA9 0x01 comments.
+        */
+       status =
+           acpi_os_create_cache("Acpi-Comment",
+                                sizeof(struct acpi_comment_node),
+                                ACPI_MAX_COMMENT_CACHE_DEPTH,
+                                &acpi_gbl_reg_comment_cache);
+       if (ACPI_FAILURE(status)) {
+               return (status);
+       }
+
+       /*
+        * This cache keeps track of the starting addresses of where the comments
+        * lie. This helps prevent duplication of comments.
+        */
+       status =
+           acpi_os_create_cache("Acpi-Comment-Addr",
+                                sizeof(struct acpi_comment_addr_node),
+                                ACPI_MAX_COMMENT_CACHE_DEPTH,
+                                &acpi_gbl_comment_addr_cache);
+       if (ACPI_FAILURE(status)) {
+               return (status);
+       }
+
+       /*
+        * This cache will be used for nodes that represent files.
+        */
+       status =
+           acpi_os_create_cache("Acpi-File", sizeof(struct acpi_file_node),
+                                ACPI_MAX_COMMENT_CACHE_DEPTH,
+                                &acpi_gbl_file_cache);
+       if (ACPI_FAILURE(status)) {
+               return (status);
+       }
+#endif
+
 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
 
        /* Memory allocation lists */
@@ -201,6 +240,17 @@ acpi_status acpi_ut_delete_caches(void)
        (void)acpi_os_delete_cache(acpi_gbl_ps_node_ext_cache);
        acpi_gbl_ps_node_ext_cache = NULL;
 
+#ifdef ACPI_ASL_COMPILER
+       (void)acpi_os_delete_cache(acpi_gbl_reg_comment_cache);
+       acpi_gbl_reg_comment_cache = NULL;
+
+       (void)acpi_os_delete_cache(acpi_gbl_comment_addr_cache);
+       acpi_gbl_comment_addr_cache = NULL;
+
+       (void)acpi_os_delete_cache(acpi_gbl_file_cache);
+       acpi_gbl_file_cache = NULL;
+#endif
+
 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
 
        /* Debug only - display leftover memory allocation, if any */
index 11c7f72f2d5608d4baa2e441275e7ad39e7aa707..531493306dee9237bfdbcce4e933be03957b4822 100644 (file)
@@ -71,7 +71,7 @@ acpi_os_create_cache(char *cache_name,
 
        ACPI_FUNCTION_ENTRY();
 
-       if (!cache_name || !return_cache || (object_size < 16)) {
+       if (!cache_name || !return_cache || !object_size) {
                return (AE_BAD_PARAMETER);
        }
 
index bd5ea3101eb77a07082f65089caa14855233f86f..615a885e2ca3c6fc276d5eae53793242adbf56b8 100644 (file)
@@ -627,4 +627,5 @@ acpi_trace_point(acpi_trace_event_type type, u8 begin, u8 *aml, char *pathname)
 }
 
 ACPI_EXPORT_SYMBOL(acpi_trace_point)
+
 #endif
index ff096d9755b925d9f72105f42993ebcc7c0522e1..e0587c85bafdf73a299c40d531eefa27deab4761 100644 (file)
@@ -474,6 +474,15 @@ acpi_ut_walk_aml_resources(struct acpi_walk_state *walk_state,
                                return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
                        }
 
+                       /*
+                        * The end_tag opcode must be followed by a zero byte.
+                        * Although this byte is technically defined to be a checksum,
+                        * in practice, all ASL compilers set this byte to zero.
+                        */
+                       if (*(aml + 1) != 0) {
+                               return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
+                       }
+
                        /* Return the pointer to the end_tag if requested */
 
                        if (!user_function) {
index a16bd9eac6537b4660539d9669156cce2eb924a2..950a1e500bfa2f09e0c72e69e9a73bef65f1f1d8 100644 (file)
@@ -91,7 +91,7 @@ ACPI_EXPORT_SYMBOL(acpi_error)
  *
  * PARAMETERS:  module_name         - Caller's module name (for error output)
  *              line_number         - Caller's line number (for error output)
- *              status              - Status to be formatted
+ *              status              - Status value to be decoded/formatted
  *              format              - Printf format string + additional args
  *
  * RETURN:      None
@@ -132,8 +132,8 @@ ACPI_EXPORT_SYMBOL(acpi_exception)
  *
  * FUNCTION:    acpi_warning
  *
- * PARAMETERS:  module_name         - Caller's module name (for error output)
- *              line_number         - Caller's line number (for error output)
+ * PARAMETERS:  module_name         - Caller's module name (for warning output)
+ *              line_number         - Caller's line number (for warning output)
  *              format              - Printf format string + additional args
  *
  * RETURN:      None
@@ -163,17 +163,13 @@ ACPI_EXPORT_SYMBOL(acpi_warning)
  *
  * FUNCTION:    acpi_info
  *
- * PARAMETERS:  module_name         - Caller's module name (for error output)
- *              line_number         - Caller's line number (for error output)
- *              format              - Printf format string + additional args
+ * PARAMETERS:  format              - Printf format string + additional args
  *
  * RETURN:      None
  *
  * DESCRIPTION: Print generic "ACPI:" information message. There is no
  *              module/line/version info in order to keep the message simple.
  *
- * TBD: module_name and line_number args are not needed, should be removed.
- *
  ******************************************************************************/
 void ACPI_INTERNAL_VAR_XFACE acpi_info(const char *format, ...)
 {
@@ -229,8 +225,8 @@ ACPI_EXPORT_SYMBOL(acpi_bios_error)
  *
  * FUNCTION:    acpi_bios_warning
  *
- * PARAMETERS:  module_name         - Caller's module name (for error output)
- *              line_number         - Caller's line number (for error output)
+ * PARAMETERS:  module_name         - Caller's module name (for warning output)
+ *              line_number         - Caller's line number (for warning output)
  *              format              - Printf format string + additional args
  *
  * RETURN:      None
index 7207e5fc9d3d3e7aa7db77838585440686ad4c62..2c462beee5513ec40448f6faf0179e621644558f 100644 (file)
@@ -513,7 +513,7 @@ retry:
        if (i < erst_record_id_cache.len)
                goto retry;
        if (erst_record_id_cache.len >= erst_record_id_cache.size) {
-               int new_size, alloc_size;
+               int new_size;
                u64 *new_entries;
 
                new_size = erst_record_id_cache.size * 2;
@@ -524,11 +524,7 @@ retry:
                                pr_warn(FW_WARN "too many record IDs!\n");
                        return 0;
                }
-               alloc_size = new_size * sizeof(entries[0]);
-               if (alloc_size < PAGE_SIZE)
-                       new_entries = kmalloc(alloc_size, GFP_KERNEL);
-               else
-                       new_entries = vmalloc(alloc_size);
+               new_entries = kvmalloc(new_size * sizeof(entries[0]), GFP_KERNEL);
                if (!new_entries)
                        return -ENOMEM;
                memcpy(new_entries, entries,
index 22e08d272db7f66969d37744bcc56cb70b10f4f2..c5fecf97ee2f52bd11188a0cd2295bd82d5d02db 100644 (file)
@@ -618,6 +618,46 @@ static int arm_smmu_iort_xlate(struct device *dev, u32 streamid,
        return ret;
 }
 
+static inline bool iort_iommu_driver_enabled(u8 type)
+{
+       switch (type) {
+       case ACPI_IORT_NODE_SMMU_V3:
+               return IS_BUILTIN(CONFIG_ARM_SMMU_V3);
+       case ACPI_IORT_NODE_SMMU:
+               return IS_BUILTIN(CONFIG_ARM_SMMU);
+       default:
+               pr_warn("IORT node type %u does not describe an SMMU\n", type);
+               return false;
+       }
+}
+
+#ifdef CONFIG_IOMMU_API
+static inline
+const struct iommu_ops *iort_fwspec_iommu_ops(struct iommu_fwspec *fwspec)
+{
+       return (fwspec && fwspec->ops) ? fwspec->ops : NULL;
+}
+
+static inline
+int iort_add_device_replay(const struct iommu_ops *ops, struct device *dev)
+{
+       int err = 0;
+
+       if (!IS_ERR_OR_NULL(ops) && ops->add_device && dev->bus &&
+           !dev->iommu_group)
+               err = ops->add_device(dev);
+
+       return err;
+}
+#else
+static inline
+const struct iommu_ops *iort_fwspec_iommu_ops(struct iommu_fwspec *fwspec)
+{ return NULL; }
+static inline
+int iort_add_device_replay(const struct iommu_ops *ops, struct device *dev)
+{ return 0; }
+#endif
+
 static const struct iommu_ops *iort_iommu_xlate(struct device *dev,
                                        struct acpi_iort_node *node,
                                        u32 streamid)
@@ -626,14 +666,31 @@ static const struct iommu_ops *iort_iommu_xlate(struct device *dev,
        int ret = -ENODEV;
        struct fwnode_handle *iort_fwnode;
 
+       /*
+        * If we already translated the fwspec there
+        * is nothing left to do, return the iommu_ops.
+        */
+       ops = iort_fwspec_iommu_ops(dev->iommu_fwspec);
+       if (ops)
+               return ops;
+
        if (node) {
                iort_fwnode = iort_get_fwnode(node);
                if (!iort_fwnode)
                        return NULL;
 
                ops = iommu_ops_from_fwnode(iort_fwnode);
+               /*
+                * If the ops look-up fails, this means that either
+                * the SMMU drivers have not been probed yet or that
+                * the SMMU drivers are not built in the kernel;
+                * Depending on whether the SMMU drivers are built-in
+                * in the kernel or not, defer the IOMMU configuration
+                * or just abort it.
+                */
                if (!ops)
-                       return NULL;
+                       return iort_iommu_driver_enabled(node->type) ?
+                              ERR_PTR(-EPROBE_DEFER) : NULL;
 
                ret = arm_smmu_iort_xlate(dev, streamid, iort_fwnode, ops);
        }
@@ -676,6 +733,7 @@ const struct iommu_ops *iort_iommu_configure(struct device *dev)
        struct acpi_iort_node *node, *parent;
        const struct iommu_ops *ops = NULL;
        u32 streamid = 0;
+       int err;
 
        if (dev_is_pci(dev)) {
                struct pci_bus *bus = to_pci_dev(dev)->bus;
@@ -707,6 +765,8 @@ const struct iommu_ops *iort_iommu_configure(struct device *dev)
 
                while (parent) {
                        ops = iort_iommu_xlate(dev, parent, streamid);
+                       if (IS_ERR_OR_NULL(ops))
+                               return ops;
 
                        parent = iort_node_map_platform_id(node, &streamid,
                                                           IORT_IOMMU_TYPE,
@@ -714,6 +774,14 @@ const struct iommu_ops *iort_iommu_configure(struct device *dev)
                }
        }
 
+       /*
+        * If we have reason to believe the IOMMU driver missed the initial
+        * add_device callback for dev, replay it to get things in order.
+        */
+       err = iort_add_device_replay(ops, dev);
+       if (err)
+               ops = ERR_PTR(err);
+
        return ops;
 }
 
@@ -1052,6 +1120,4 @@ void __init acpi_iort_init(void)
        }
 
        iort_init_platform_devices();
-
-       acpi_probe_device_table(iort);
 }
index d42eeef9d9287815ce5f4c82d8d915ae5deabe51..a9a9ab3399d47ff8087e62d495f1d2ba930fc1d3 100644 (file)
@@ -782,7 +782,7 @@ static int acpi_battery_update(struct acpi_battery *battery, bool resume)
        if ((battery->state & ACPI_BATTERY_STATE_CRITICAL) ||
            (test_bit(ACPI_BATTERY_ALARM_PRESENT, &battery->flags) &&
             (battery->capacity_now <= battery->alarm)))
-               pm_wakeup_event(&battery->device->dev, 0);
+               pm_wakeup_hard_event(&battery->device->dev);
 
        return result;
 }
index 34fbe027e73a26f195f981d2fbd373608f724415..784bda663d162d36d1e4bdc47ce8a6b5b595be8a 100644 (file)
@@ -114,6 +114,11 @@ int acpi_bus_get_status(struct acpi_device *device)
        acpi_status status;
        unsigned long long sta;
 
+       if (acpi_device_always_present(device)) {
+               acpi_set_device_status(device, ACPI_STA_DEFAULT);
+               return 0;
+       }
+
        status = acpi_bus_get_status_handle(device->handle, &sta);
        if (ACPI_FAILURE(status))
                return -ENODEV;
index 668137e4a0697cf230b074e13cbb6dd255c7bf59..b7c2a06963d6fb79cb5f5aaa2576936d17d5088f 100644 (file)
@@ -216,7 +216,7 @@ static int acpi_lid_notify_state(struct acpi_device *device, int state)
        }
 
        if (state)
-               pm_wakeup_event(&device->dev, 0);
+               pm_wakeup_hard_event(&device->dev);
 
        ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device);
        if (ret == NOTIFY_DONE)
@@ -398,7 +398,7 @@ static void acpi_button_notify(struct acpi_device *device, u32 event)
                } else {
                        int keycode;
 
-                       pm_wakeup_event(&device->dev, 0);
+                       pm_wakeup_hard_event(&device->dev);
                        if (button->suspended)
                                break;
 
@@ -530,6 +530,7 @@ static int acpi_button_add(struct acpi_device *device)
                lid_device = device;
        }
 
+       device_init_wakeup(&device->dev, true);
        printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device));
        return 0;
 
index 6cbe6036da998faabfd9977ccc5af1594d7af7d0..e5b47f032d9af552a04dc9aee301a8160f942997 100644 (file)
@@ -95,7 +95,7 @@ static DEFINE_PER_CPU(struct cpc_desc *, cpc_desc_ptr);
 /* pcc mapped address + header size + offset within PCC subspace */
 #define GET_PCC_VADDR(offs) (pcc_data.pcc_comm_addr + 0x8 + (offs))
 
-/* Check if a CPC regsiter is in PCC */
+/* Check if a CPC register is in PCC */
 #define CPC_IN_PCC(cpc) ((cpc)->type == ACPI_TYPE_BUFFER &&            \
                                (cpc)->cpc_entry.reg.space_id ==        \
                                ACPI_ADR_SPACE_PLATFORM_COMM)
index 993fd31394c854c99e5ce0c2af824f36c50b7a22..798d5003a039d876f275fc2d933be71cb7ebfbed 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/pm_qos.h>
 #include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
+#include <linux/suspend.h>
 
 #include "internal.h"
 
@@ -399,7 +400,7 @@ static void acpi_pm_notify_handler(acpi_handle handle, u32 val, void *not_used)
        mutex_lock(&acpi_pm_notifier_lock);
 
        if (adev->wakeup.flags.notifier_present) {
-               __pm_wakeup_event(adev->wakeup.ws, 0);
+               pm_wakeup_ws_event(adev->wakeup.ws, 0, true);
                if (adev->wakeup.context.work.func)
                        queue_pm_work(&adev->wakeup.context.work);
        }
index 3e7020751d34de65bdff3d5c04e840b5f4ca83fb..3be1433853bfb9920a96f1cd212f052922f253a3 100644 (file)
@@ -179,7 +179,6 @@ int acpi_bind_one(struct device *dev, struct acpi_device *acpi_dev)
        struct list_head *physnode_list;
        unsigned int node_id;
        int retval = -EINVAL;
-       enum dev_dma_attr attr;
 
        if (has_acpi_companion(dev)) {
                if (acpi_dev) {
@@ -236,10 +235,6 @@ int acpi_bind_one(struct device *dev, struct acpi_device *acpi_dev)
        if (!has_acpi_companion(dev))
                ACPI_COMPANION_SET(dev, acpi_dev);
 
-       attr = acpi_get_dma_attr(acpi_dev);
-       if (attr != DEV_DMA_NOT_SUPPORTED)
-               acpi_dma_configure(dev, attr);
-
        acpi_physnode_link_name(physical_node_name, node_id);
        retval = sysfs_create_link(&acpi_dev->dev.kobj, &dev->kobj,
                                   physical_node_name);
index 2944353253ed47f80a1ef936f498e61088e6ff84..a4e8432fc2fba456f9ca489bb2614df01537f72c 100644 (file)
@@ -54,6 +54,7 @@ static struct mcfg_fixup mcfg_quirks[] = {
 
 #define QCOM_ECAM32(seg) \
        { "QCOM  ", "QDF2432 ", 1, seg, MCFG_BUS_ANY, &pci_32b_ops }
+
        QCOM_ECAM32(0),
        QCOM_ECAM32(1),
        QCOM_ECAM32(2),
@@ -68,6 +69,7 @@ static struct mcfg_fixup mcfg_quirks[] = {
        { "HISI  ", table_id, 0, (seg) + 1, MCFG_BUS_ANY, ops }, \
        { "HISI  ", table_id, 0, (seg) + 2, MCFG_BUS_ANY, ops }, \
        { "HISI  ", table_id, 0, (seg) + 3, MCFG_BUS_ANY, ops }
+
        HISI_QUAD_DOM("HIP05   ",  0, &hisi_pcie_ops),
        HISI_QUAD_DOM("HIP06   ",  0, &hisi_pcie_ops),
        HISI_QUAD_DOM("HIP07   ",  0, &hisi_pcie_ops),
@@ -77,6 +79,7 @@ static struct mcfg_fixup mcfg_quirks[] = {
 
 #define THUNDER_PEM_RES(addr, node) \
        DEFINE_RES_MEM((addr) + ((u64) (node) << 44), 0x39 * SZ_16M)
+
 #define THUNDER_PEM_QUIRK(rev, node) \
        { "CAVIUM", "THUNDERX", rev, 4 + (10 * (node)), MCFG_BUS_ANY,       \
          &thunder_pem_ecam_ops, THUNDER_PEM_RES(0x88001f000000UL, node) },  \
@@ -90,13 +93,16 @@ static struct mcfg_fixup mcfg_quirks[] = {
          &thunder_pem_ecam_ops, THUNDER_PEM_RES(0x894057000000UL, node) },  \
        { "CAVIUM", "THUNDERX", rev, 9 + (10 * (node)), MCFG_BUS_ANY,       \
          &thunder_pem_ecam_ops, THUNDER_PEM_RES(0x89808f000000UL, node) }
-       /* SoC pass2.x */
-       THUNDER_PEM_QUIRK(1, 0),
-       THUNDER_PEM_QUIRK(1, 1),
 
 #define THUNDER_ECAM_QUIRK(rev, seg)                                   \
        { "CAVIUM", "THUNDERX", rev, seg, MCFG_BUS_ANY,                 \
        &pci_thunder_ecam_ops }
+
+       /* SoC pass2.x */
+       THUNDER_PEM_QUIRK(1, 0),
+       THUNDER_PEM_QUIRK(1, 1),
+       THUNDER_ECAM_QUIRK(1, 10),
+
        /* SoC pass1.x */
        THUNDER_PEM_QUIRK(2, 0),        /* off-chip devices */
        THUNDER_PEM_QUIRK(2, 1),        /* off-chip devices */
@@ -112,9 +118,11 @@ static struct mcfg_fixup mcfg_quirks[] = {
 #define XGENE_V1_ECAM_MCFG(rev, seg) \
        {"APM   ", "XGENE   ", rev, seg, MCFG_BUS_ANY, \
                &xgene_v1_pcie_ecam_ops }
+
 #define XGENE_V2_ECAM_MCFG(rev, seg) \
        {"APM   ", "XGENE   ", rev, seg, MCFG_BUS_ANY, \
                &xgene_v2_pcie_ecam_ops }
+
        /* X-Gene SoC with v1 PCIe controller */
        XGENE_V1_ECAM_MCFG(1, 0),
        XGENE_V1_ECAM_MCFG(1, 1),
index 55f51115f0166d8eb3415134f9bbf6ef3b1cf173..1a76c784cd4cbfb7a3ec9ff7b7120d2e8a9f01cb 100644 (file)
@@ -27,97 +27,97 @@ static struct pmic_table power_table[] = {
                .address = 0x00,
                .reg = 0x13,
                .bit = 0x05,
-       },
+       }, /* ALD1 */
        {
                .address = 0x04,
                .reg = 0x13,
                .bit = 0x06,
-       },
+       }, /* ALD2 */
        {
                .address = 0x08,
                .reg = 0x13,
                .bit = 0x07,
-       },
+       }, /* ALD3 */
        {
                .address = 0x0c,
                .reg = 0x12,
                .bit = 0x03,
-       },
+       }, /* DLD1 */
        {
                .address = 0x10,
                .reg = 0x12,
                .bit = 0x04,
-       },
+       }, /* DLD2 */
        {
                .address = 0x14,
                .reg = 0x12,
                .bit = 0x05,
-       },
+       }, /* DLD3 */
        {
                .address = 0x18,
                .reg = 0x12,
                .bit = 0x06,
-       },
+       }, /* DLD4 */
        {
                .address = 0x1c,
                .reg = 0x12,
                .bit = 0x00,
-       },
+       }, /* ELD1 */
        {
                .address = 0x20,
                .reg = 0x12,
                .bit = 0x01,
-       },
+       }, /* ELD2 */
        {
                .address = 0x24,
                .reg = 0x12,
                .bit = 0x02,
-       },
+       }, /* ELD3 */
        {
                .address = 0x28,
                .reg = 0x13,
                .bit = 0x02,
-       },
+       }, /* FLD1 */
        {
                .address = 0x2c,
                .reg = 0x13,
                .bit = 0x03,
-       },
+       }, /* FLD2 */
        {
                .address = 0x30,
                .reg = 0x13,
                .bit = 0x04,
-       },
+       }, /* FLD3 */
        {
-               .address = 0x38,
+               .address = 0x34,
                .reg = 0x10,
                .bit = 0x03,
-       },
+       }, /* BUC1 */
        {
-               .address = 0x3c,
+               .address = 0x38,
                .reg = 0x10,
                .bit = 0x06,
-       },
+       }, /* BUC2 */
        {
-               .address = 0x40,
+               .address = 0x3c,
                .reg = 0x10,
                .bit = 0x05,
-       },
+       }, /* BUC3 */
        {
-               .address = 0x44,
+               .address = 0x40,
                .reg = 0x10,
                .bit = 0x04,
-       },
+       }, /* BUC4 */
        {
-               .address = 0x48,
+               .address = 0x44,
                .reg = 0x10,
                .bit = 0x01,
-       },
+       }, /* BUC5 */
        {
-               .address = 0x4c,
+               .address = 0x48,
                .reg = 0x10,
                .bit = 0x00
-       },
+       }, /* BUC6 */
 };
 
 /* TMP0 - TMP5 are the same, all from GPADC */
index 1c2b846c577604d0b471e87d19cecea6caa286f9..3a6c9b741b233cd81304961e43482d003347397d 100644 (file)
@@ -864,6 +864,16 @@ void acpi_resume_power_resources(void)
 
                mutex_unlock(&resource->resource_lock);
        }
+
+       mutex_unlock(&power_resource_list_lock);
+}
+
+void acpi_turn_off_unused_power_resources(void)
+{
+       struct acpi_power_resource *resource;
+
+       mutex_lock(&power_resource_list_lock);
+
        list_for_each_entry_reverse(resource, &acpi_power_resource_list, list_node) {
                int result, state;
 
index c269310674158fa56104bdf4d7b4a04dcfda6221..e39ec7b7cb674fbad3cab60f4e5139d7e06a1f09 100644 (file)
@@ -1363,20 +1363,25 @@ enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev)
  * @dev: The pointer to the device
  * @attr: device dma attributes
  */
-void acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
+int acpi_dma_configure(struct device *dev, enum dev_dma_attr attr)
 {
        const struct iommu_ops *iommu;
+       u64 size;
 
        iort_set_dma_mask(dev);
 
        iommu = iort_iommu_configure(dev);
+       if (IS_ERR(iommu))
+               return PTR_ERR(iommu);
 
+       size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1);
        /*
         * Assume dma valid range starts at 0 and covers the whole
         * coherent_dma_mask.
         */
-       arch_setup_dma_ops(dev, 0, dev->coherent_dma_mask + 1, iommu,
-                          attr == DEV_DMA_COHERENT);
+       arch_setup_dma_ops(dev, 0, size, iommu, attr == DEV_DMA_COHERENT);
+
+       return 0;
 }
 EXPORT_SYMBOL_GPL(acpi_dma_configure);
 
index a4327af676fe81948cdb76c3b15786256929ffa8..a6574d62634031ac6e351418b935a333b556b665 100644 (file)
@@ -474,6 +474,7 @@ static void acpi_pm_start(u32 acpi_state)
  */
 static void acpi_pm_end(void)
 {
+       acpi_turn_off_unused_power_resources();
        acpi_scan_lock_release();
        /*
         * This is necessary in case acpi_pm_finish() is not called during a
@@ -662,14 +663,40 @@ static int acpi_freeze_prepare(void)
        acpi_os_wait_events_complete();
        if (acpi_sci_irq_valid())
                enable_irq_wake(acpi_sci_irq);
+
        return 0;
 }
 
+static void acpi_freeze_wake(void)
+{
+       /*
+        * If IRQD_WAKEUP_ARMED is not set for the SCI at this point, it means
+        * that the SCI has triggered while suspended, so cancel the wakeup in
+        * case it has not been a wakeup event (the GPEs will be checked later).
+        */
+       if (acpi_sci_irq_valid() &&
+           !irqd_is_wakeup_armed(irq_get_irq_data(acpi_sci_irq)))
+               pm_system_cancel_wakeup();
+}
+
+static void acpi_freeze_sync(void)
+{
+       /*
+        * Process all pending events in case there are any wakeup ones.
+        *
+        * The EC driver uses the system workqueue, so that one needs to be
+        * flushed too.
+        */
+       acpi_os_wait_events_complete();
+       flush_scheduled_work();
+}
+
 static void acpi_freeze_restore(void)
 {
        acpi_disable_wakeup_devices(ACPI_STATE_S0);
        if (acpi_sci_irq_valid())
                disable_irq_wake(acpi_sci_irq);
+
        acpi_enable_all_runtime_gpes();
 }
 
@@ -681,6 +708,8 @@ static void acpi_freeze_end(void)
 static const struct platform_freeze_ops acpi_freeze_ops = {
        .begin = acpi_freeze_begin,
        .prepare = acpi_freeze_prepare,
+       .wake = acpi_freeze_wake,
+       .sync = acpi_freeze_sync,
        .restore = acpi_freeze_restore,
        .end = acpi_freeze_end,
 };
index a9cc34e663f9cf15d356c90d6f36f1d3a78435ed..a82ff74faf7a2ae94c8b16ce7a60cdc4c78f70fc 100644 (file)
@@ -6,6 +6,7 @@ extern struct list_head acpi_wakeup_device_list;
 extern struct mutex acpi_device_lock;
 
 extern void acpi_resume_power_resources(void);
+extern void acpi_turn_off_unused_power_resources(void);
 
 static inline acpi_status acpi_set_waking_vector(u32 wakeup_address)
 {
diff --git a/drivers/acpi/x86/utils.c b/drivers/acpi/x86/utils.c
new file mode 100644 (file)
index 0000000..bd86b80
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * X86 ACPI Utility Functions
+ *
+ * Copyright (C) 2017 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Based on various non upstream patches to support the CHT Whiskey Cove PMIC:
+ * Copyright (C) 2013-2015 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/acpi.h>
+#include <asm/cpu_device_id.h>
+#include <asm/intel-family.h>
+#include "../internal.h"
+
+/*
+ * Some ACPI devices are hidden (status == 0x0) in recent BIOS-es because
+ * some recent Windows drivers bind to one device but poke at multiple
+ * devices at the same time, so the others get hidden.
+ * We work around this by always reporting ACPI_STA_DEFAULT for these
+ * devices. Note this MUST only be done for devices where this is safe.
+ *
+ * This forcing of devices to be present is limited to specific CPU (SoC)
+ * models both to avoid potentially causing trouble on other models and
+ * because some HIDs are re-used on different SoCs for completely
+ * different devices.
+ */
+struct always_present_id {
+       struct acpi_device_id hid[2];
+       struct x86_cpu_id cpu_ids[2];
+       const char *uid;
+};
+
+#define ICPU(model)    { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, }
+
+#define ENTRY(hid, uid, cpu_models) {                                  \
+       { { hid, }, {} },                                               \
+       { cpu_models, {} },                                             \
+       uid,                                                            \
+}
+
+static const struct always_present_id always_present_ids[] = {
+       /*
+        * Bay / Cherry Trail PWM directly poked by GPU driver in win10,
+        * but Linux uses a separate PWM driver, harmless if not used.
+        */
+       ENTRY("80860F09", "1", ICPU(INTEL_FAM6_ATOM_SILVERMONT1)),
+       ENTRY("80862288", "1", ICPU(INTEL_FAM6_ATOM_AIRMONT)),
+       /*
+        * The INT0002 device is necessary to clear wakeup interrupt sources
+        * on Cherry Trail devices, without it we get nobody cared IRQ msgs.
+        */
+       ENTRY("INT0002", "1", ICPU(INTEL_FAM6_ATOM_AIRMONT)),
+};
+
+bool acpi_device_always_present(struct acpi_device *adev)
+{
+       u32 *status = (u32 *)&adev->status;
+       u32 old_status = *status;
+       bool ret = false;
+       unsigned int i;
+
+       /* acpi_match_device_ids checks status, so set it to default */
+       *status = ACPI_STA_DEFAULT;
+       for (i = 0; i < ARRAY_SIZE(always_present_ids); i++) {
+               if (acpi_match_device_ids(adev, always_present_ids[i].hid))
+                       continue;
+
+               if (!adev->pnp.unique_id ||
+                   strcmp(adev->pnp.unique_id, always_present_ids[i].uid))
+                       continue;
+
+               if (!x86_match_cpu(always_present_ids[i].cpu_ids))
+                       continue;
+
+               if (old_status != ACPI_STA_DEFAULT) /* Log only once */
+                       dev_info(&adev->dev,
+                                "Device [%s] is in always present list\n",
+                                adev->pnp.bus_id);
+
+               ret = true;
+               break;
+       }
+       *status = old_status;
+
+       return ret;
+}
index ff6cb9e4c3811c9a34bcf14beb395faacc552a15..de3eaf051697601a641440d12687e88258ebc394 100644 (file)
@@ -518,6 +518,15 @@ config PATA_BF54X
 
          If unsure, say N.
 
+config PATA_BK3710
+       tristate "Palmchip BK3710 PATA support"
+       depends on ARCH_DAVINCI
+       help
+         This option enables support for the integrated IDE controller on
+         the TI DaVinci SoC.
+
+         If unsure, say N.
+
 config PATA_CMD64X
        tristate "CMD64x PATA support"
        depends on PCI
index 3048cc100a46691c3c3d581213fdc1073d499e65..cd931a5eba922267e0307a833f0b4e1f9f8cec17 100644 (file)
@@ -51,6 +51,7 @@ obj-$(CONFIG_PATA_ARTOP)      += pata_artop.o
 obj-$(CONFIG_PATA_ATIIXP)      += pata_atiixp.o
 obj-$(CONFIG_PATA_ATP867X)     += pata_atp867x.o
 obj-$(CONFIG_PATA_BF54X)       += pata_bf54x.o
+obj-$(CONFIG_PATA_BK3710)      += pata_bk3710.o
 obj-$(CONFIG_PATA_CMD64X)      += pata_cmd64x.o
 obj-$(CONFIG_PATA_CS5520)      += pata_cs5520.o
 obj-$(CONFIG_PATA_CS5530)      += pata_cs5530.o
diff --git a/drivers/ata/pata_bk3710.c b/drivers/ata/pata_bk3710.c
new file mode 100644 (file)
index 0000000..6c3bd5f
--- /dev/null
@@ -0,0 +1,382 @@
+/*
+ * Palmchip BK3710 PATA controller driver
+ *
+ * Copyright (c) 2017 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Based on palm_bk3710.c:
+ *
+ * Copyright (C) 2006 Texas Instruments.
+ * Copyright (C) 2007 MontaVista Software, Inc., <source@mvista.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/ata.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/libata.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+
+#define DRV_NAME "pata_bk3710"
+
+#define BK3710_TF_OFFSET       0x1F0
+#define BK3710_CTL_OFFSET      0x3F6
+
+#define BK3710_BMISP           0x02
+#define BK3710_IDETIMP         0x40
+#define BK3710_UDMACTL         0x48
+#define BK3710_MISCCTL         0x50
+#define BK3710_REGSTB          0x54
+#define BK3710_REGRCVR         0x58
+#define BK3710_DATSTB          0x5C
+#define BK3710_DATRCVR         0x60
+#define BK3710_DMASTB          0x64
+#define BK3710_DMARCVR         0x68
+#define BK3710_UDMASTB         0x6C
+#define BK3710_UDMATRP         0x70
+#define BK3710_UDMAENV         0x74
+#define BK3710_IORDYTMP                0x78
+
+static struct scsi_host_template pata_bk3710_sht = {
+       ATA_BMDMA_SHT(DRV_NAME),
+};
+
+static unsigned int ideclk_period; /* in nanoseconds */
+
+struct pata_bk3710_udmatiming {
+       unsigned int rptime;    /* tRP -- Ready to pause time (nsec) */
+       unsigned int cycletime; /* tCYCTYP2/2 -- avg Cycle Time (nsec) */
+                               /* tENV is always a minimum of 20 nsec */
+};
+
+static const struct pata_bk3710_udmatiming pata_bk3710_udmatimings[6] = {
+       { 160, 240 / 2 },       /* UDMA Mode 0 */
+       { 125, 160 / 2 },       /* UDMA Mode 1 */
+       { 100, 120 / 2 },       /* UDMA Mode 2 */
+       { 100,  90 / 2 },       /* UDMA Mode 3 */
+       { 100,  60 / 2 },       /* UDMA Mode 4 */
+       {  85,  40 / 2 },       /* UDMA Mode 5 */
+};
+
+static void pata_bk3710_setudmamode(void __iomem *base, unsigned int dev,
+                                   unsigned int mode)
+{
+       u32 val32;
+       u16 val16;
+       u8 tenv, trp, t0;
+
+       /* DMA Data Setup */
+       t0 = DIV_ROUND_UP(pata_bk3710_udmatimings[mode].cycletime,
+                         ideclk_period) - 1;
+       tenv = DIV_ROUND_UP(20, ideclk_period) - 1;
+       trp = DIV_ROUND_UP(pata_bk3710_udmatimings[mode].rptime,
+                          ideclk_period) - 1;
+
+       /* udmastb Ultra DMA Access Strobe Width */
+       val32 = ioread32(base + BK3710_UDMASTB) & (0xFF << (dev ? 0 : 8));
+       val32 |= t0 << (dev ? 8 : 0);
+       iowrite32(val32, base + BK3710_UDMASTB);
+
+       /* udmatrp Ultra DMA Ready to Pause Time */
+       val32 = ioread32(base + BK3710_UDMATRP) & (0xFF << (dev ? 0 : 8));
+       val32 |= trp << (dev ? 8 : 0);
+       iowrite32(val32, base + BK3710_UDMATRP);
+
+       /* udmaenv Ultra DMA envelop Time */
+       val32 = ioread32(base + BK3710_UDMAENV) & (0xFF << (dev ? 0 : 8));
+       val32 |= tenv << (dev ? 8 : 0);
+       iowrite32(val32, base + BK3710_UDMAENV);
+
+       /* Enable UDMA for Device */
+       val16 = ioread16(base + BK3710_UDMACTL) | (1 << dev);
+       iowrite16(val16, base + BK3710_UDMACTL);
+}
+
+static void pata_bk3710_setmwdmamode(void __iomem *base, unsigned int dev,
+                                    unsigned short min_cycle,
+                                    unsigned int mode)
+{
+       const struct ata_timing *t;
+       int cycletime;
+       u32 val32;
+       u16 val16;
+       u8 td, tkw, t0;
+
+       t = ata_timing_find_mode(mode);
+       cycletime = max_t(int, t->cycle, min_cycle);
+
+       /* DMA Data Setup */
+       t0 = DIV_ROUND_UP(cycletime, ideclk_period);
+       td = DIV_ROUND_UP(t->active, ideclk_period);
+       tkw = t0 - td - 1;
+       td--;
+
+       val32 = ioread32(base + BK3710_DMASTB) & (0xFF << (dev ? 0 : 8));
+       val32 |= td << (dev ? 8 : 0);
+       iowrite32(val32, base + BK3710_DMASTB);
+
+       val32 = ioread32(base + BK3710_DMARCVR) & (0xFF << (dev ? 0 : 8));
+       val32 |= tkw << (dev ? 8 : 0);
+       iowrite32(val32, base + BK3710_DMARCVR);
+
+       /* Disable UDMA for Device */
+       val16 = ioread16(base + BK3710_UDMACTL) & ~(1 << dev);
+       iowrite16(val16, base + BK3710_UDMACTL);
+}
+
+static void pata_bk3710_set_dmamode(struct ata_port *ap,
+                                   struct ata_device *adev)
+{
+       void __iomem *base = (void __iomem *)ap->ioaddr.bmdma_addr;
+       int is_slave = adev->devno;
+       const u8 xferspeed = adev->dma_mode;
+
+       if (xferspeed >= XFER_UDMA_0)
+               pata_bk3710_setudmamode(base, is_slave,
+                                       xferspeed - XFER_UDMA_0);
+       else
+               pata_bk3710_setmwdmamode(base, is_slave,
+                                        adev->id[ATA_ID_EIDE_DMA_MIN],
+                                        xferspeed);
+}
+
+static void pata_bk3710_setpiomode(void __iomem *base, struct ata_device *pair,
+                                  unsigned int dev, unsigned int cycletime,
+                                  unsigned int mode)
+{
+       const struct ata_timing *t;
+       u32 val32;
+       u8 t2, t2i, t0;
+
+       t = ata_timing_find_mode(XFER_PIO_0 + mode);
+
+       /* PIO Data Setup */
+       t0 = DIV_ROUND_UP(cycletime, ideclk_period);
+       t2 = DIV_ROUND_UP(t->active, ideclk_period);
+
+       t2i = t0 - t2 - 1;
+       t2--;
+
+       val32 = ioread32(base + BK3710_DATSTB) & (0xFF << (dev ? 0 : 8));
+       val32 |= t2 << (dev ? 8 : 0);
+       iowrite32(val32, base + BK3710_DATSTB);
+
+       val32 = ioread32(base + BK3710_DATRCVR) & (0xFF << (dev ? 0 : 8));
+       val32 |= t2i << (dev ? 8 : 0);
+       iowrite32(val32, base + BK3710_DATRCVR);
+
+       /* FIXME: this is broken also in the old driver */
+       if (pair) {
+               u8 mode2 = pair->pio_mode - XFER_PIO_0;
+
+               if (mode2 < mode)
+                       mode = mode2;
+       }
+
+       /* TASKFILE Setup */
+       t0 = DIV_ROUND_UP(t->cyc8b, ideclk_period);
+       t2 = DIV_ROUND_UP(t->act8b, ideclk_period);
+
+       t2i = t0 - t2 - 1;
+       t2--;
+
+       val32 = ioread32(base + BK3710_REGSTB) & (0xFF << (dev ? 0 : 8));
+       val32 |= t2 << (dev ? 8 : 0);
+       iowrite32(val32, base + BK3710_REGSTB);
+
+       val32 = ioread32(base + BK3710_REGRCVR) & (0xFF << (dev ? 0 : 8));
+       val32 |= t2i << (dev ? 8 : 0);
+       iowrite32(val32, base + BK3710_REGRCVR);
+}
+
+static void pata_bk3710_set_piomode(struct ata_port *ap,
+                                   struct ata_device *adev)
+{
+       void __iomem *base = (void __iomem *)ap->ioaddr.bmdma_addr;
+       struct ata_device *pair = ata_dev_pair(adev);
+       const struct ata_timing *t = ata_timing_find_mode(adev->pio_mode);
+       const u16 *id = adev->id;
+       unsigned int cycle_time = 0;
+       int is_slave = adev->devno;
+       const u8 pio = adev->pio_mode - XFER_PIO_0;
+
+       if (id[ATA_ID_FIELD_VALID] & 2) {
+               if (ata_id_has_iordy(id))
+                       cycle_time = id[ATA_ID_EIDE_PIO_IORDY];
+               else
+                       cycle_time = id[ATA_ID_EIDE_PIO];
+
+               /* conservative "downgrade" for all pre-ATA2 drives */
+               if (pio < 3 && cycle_time < t->cycle)
+                       cycle_time = 0; /* use standard timing */
+       }
+
+       if (!cycle_time)
+               cycle_time = t->cycle;
+
+       pata_bk3710_setpiomode(base, pair, is_slave, cycle_time, pio);
+}
+
+static void pata_bk3710_chipinit(void __iomem *base)
+{
+       /*
+        * REVISIT:  the ATA reset signal needs to be managed through a
+        * GPIO, which means it should come from platform_data.  Until
+        * we get and use such information, we have to trust that things
+        * have been reset before we get here.
+        */
+
+       /*
+        * Program the IDETIMP Register Value based on the following assumptions
+        *
+        * (ATA_IDETIMP_IDEEN           , ENABLE ) |
+        * (ATA_IDETIMP_PREPOST1        , DISABLE) |
+        * (ATA_IDETIMP_PREPOST0        , DISABLE) |
+        *
+        * DM6446 silicon rev 2.1 and earlier have no observed net benefit
+        * from enabling prefetch/postwrite.
+        */
+       iowrite16(BIT(15), base + BK3710_IDETIMP);
+
+       /*
+        * UDMACTL Ultra-ATA DMA Control
+        * (ATA_UDMACTL_UDMAP1  , 0 ) |
+        * (ATA_UDMACTL_UDMAP0  , 0 )
+        *
+        */
+       iowrite16(0, base + BK3710_UDMACTL);
+
+       /*
+        * MISCCTL Miscellaneous Conrol Register
+        * (ATA_MISCCTL_HWNHLD1P        , 1 cycle)
+        * (ATA_MISCCTL_HWNHLD0P        , 1 cycle)
+        * (ATA_MISCCTL_TIMORIDE        , 1)
+        */
+       iowrite32(0x001, base + BK3710_MISCCTL);
+
+       /*
+        * IORDYTMP IORDY Timer for Primary Register
+        * (ATA_IORDYTMP_IORDYTMP       , DISABLE)
+        */
+       iowrite32(0, base + BK3710_IORDYTMP);
+
+       /*
+        * Configure BMISP Register
+        * (ATA_BMISP_DMAEN1    , DISABLE )     |
+        * (ATA_BMISP_DMAEN0    , DISABLE )     |
+        * (ATA_BMISP_IORDYINT  , CLEAR)        |
+        * (ATA_BMISP_INTRSTAT  , CLEAR)        |
+        * (ATA_BMISP_DMAERROR  , CLEAR)
+        */
+       iowrite16(0xE, base + BK3710_BMISP);
+
+       pata_bk3710_setpiomode(base, NULL, 0, 600, 0);
+       pata_bk3710_setpiomode(base, NULL, 1, 600, 0);
+}
+
+static struct ata_port_operations pata_bk3710_ports_ops = {
+       .inherits               = &ata_bmdma_port_ops,
+       .cable_detect           = ata_cable_80wire,
+
+       .set_piomode            = pata_bk3710_set_piomode,
+       .set_dmamode            = pata_bk3710_set_dmamode,
+};
+
+static int __init pata_bk3710_probe(struct platform_device *pdev)
+{
+       struct clk *clk;
+       struct resource *mem;
+       struct ata_host *host;
+       struct ata_port *ap;
+       void __iomem *base;
+       unsigned long rate;
+       int irq;
+
+       clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(clk))
+               return -ENODEV;
+
+       clk_enable(clk);
+       rate = clk_get_rate(clk);
+       if (!rate)
+               return -EINVAL;
+
+       /* NOTE:  round *down* to meet minimum timings; we count in clocks */
+       ideclk_period = 1000000000UL / rate;
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               pr_err(DRV_NAME ": failed to get IRQ resource\n");
+               return irq;
+       }
+
+       base = devm_ioremap_resource(&pdev->dev, mem);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       /* configure the Palmchip controller */
+       pata_bk3710_chipinit(base);
+
+       /* allocate host */
+       host = ata_host_alloc(&pdev->dev, 1);
+       if (!host)
+               return -ENOMEM;
+       ap = host->ports[0];
+
+       ap->ops = &pata_bk3710_ports_ops;
+       ap->pio_mask = ATA_PIO4;
+       ap->mwdma_mask = ATA_MWDMA2;
+       ap->udma_mask = rate < 100000000 ? ATA_UDMA4 : ATA_UDMA5;
+       ap->flags |= ATA_FLAG_SLAVE_POSS;
+
+       ap->ioaddr.data_addr            = base + BK3710_TF_OFFSET;
+       ap->ioaddr.error_addr           = base + BK3710_TF_OFFSET + 1;
+       ap->ioaddr.feature_addr         = base + BK3710_TF_OFFSET + 1;
+       ap->ioaddr.nsect_addr           = base + BK3710_TF_OFFSET + 2;
+       ap->ioaddr.lbal_addr            = base + BK3710_TF_OFFSET + 3;
+       ap->ioaddr.lbam_addr            = base + BK3710_TF_OFFSET + 4;
+       ap->ioaddr.lbah_addr            = base + BK3710_TF_OFFSET + 5;
+       ap->ioaddr.device_addr          = base + BK3710_TF_OFFSET + 6;
+       ap->ioaddr.status_addr          = base + BK3710_TF_OFFSET + 7;
+       ap->ioaddr.command_addr         = base + BK3710_TF_OFFSET + 7;
+
+       ap->ioaddr.altstatus_addr       = base + BK3710_CTL_OFFSET;
+       ap->ioaddr.ctl_addr             = base + BK3710_CTL_OFFSET;
+
+       ap->ioaddr.bmdma_addr           = base;
+
+       ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx",
+                     (unsigned long)base + BK3710_TF_OFFSET,
+                     (unsigned long)base + BK3710_CTL_OFFSET);
+
+       /* activate */
+       return ata_host_activate(host, irq, ata_sff_interrupt, 0,
+                                &pata_bk3710_sht);
+}
+
+/* work with hotplug and coldplug */
+MODULE_ALIAS("platform:palm_bk3710");
+
+static struct platform_driver pata_bk3710_driver = {
+       .driver = {
+               .name = "palm_bk3710",
+       },
+};
+
+static int __init pata_bk3710_init(void)
+{
+       return platform_driver_probe(&pata_bk3710_driver, pata_bk3710_probe);
+}
+
+module_init(pata_bk3710_init);
+MODULE_LICENSE("GPL");
index a1fbf55c4d3abbea786ef5585b96d769ca3a144a..4882f06d12dfe3b6e8ab7393a5e95c0ab7892d20 100644 (file)
@@ -19,6 +19,7 @@
 
 #include <linux/device.h>
 #include <linux/delay.h>
+#include <linux/dma-mapping.h>
 #include <linux/module.h>
 #include <linux/kthread.h>
 #include <linux/wait.h>
@@ -356,6 +357,10 @@ re_probe:
        if (ret)
                goto pinctrl_bind_failed;
 
+       ret = dma_configure(dev);
+       if (ret)
+               goto dma_failed;
+
        if (driver_sysfs_add(dev)) {
                printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n",
                        __func__, dev_name(dev));
@@ -417,6 +422,8 @@ re_probe:
        goto done;
 
 probe_failed:
+       dma_deconfigure(dev);
+dma_failed:
        if (dev->bus)
                blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
                                             BUS_NOTIFY_DRIVER_NOT_BOUND, dev);
@@ -826,6 +833,8 @@ static void __device_release_driver(struct device *dev, struct device *parent)
                        drv->remove(dev);
 
                device_links_driver_cleanup(dev);
+               dma_deconfigure(dev);
+
                devres_release_all(dev);
                dev->driver = NULL;
                dev_set_drvdata(dev, NULL);
index 51b7061ff7c04920146f3998ccfeeb62e540260e..f3deb6af42ad1473364ace69908cbd0908e9c6d5 100644 (file)
@@ -7,9 +7,11 @@
  * This file is released under the GPLv2.
  */
 
+#include <linux/acpi.h>
 #include <linux/dma-mapping.h>
 #include <linux/export.h>
 #include <linux/gfp.h>
+#include <linux/of_device.h>
 #include <linux/slab.h>
 #include <linux/vmalloc.h>
 
@@ -340,3 +342,42 @@ void dma_common_free_remap(void *cpu_addr, size_t size, unsigned long vm_flags)
        vunmap(cpu_addr);
 }
 #endif
+
+/*
+ * Common configuration to enable DMA API use for a device
+ */
+#include <linux/pci.h>
+
+int dma_configure(struct device *dev)
+{
+       struct device *bridge = NULL, *dma_dev = dev;
+       enum dev_dma_attr attr;
+       int ret = 0;
+
+       if (dev_is_pci(dev)) {
+               bridge = pci_get_host_bridge_device(to_pci_dev(dev));
+               dma_dev = bridge;
+               if (IS_ENABLED(CONFIG_OF) && dma_dev->parent &&
+                   dma_dev->parent->of_node)
+                       dma_dev = dma_dev->parent;
+       }
+
+       if (dma_dev->of_node) {
+               ret = of_dma_configure(dev, dma_dev->of_node);
+       } else if (has_acpi_companion(dma_dev)) {
+               attr = acpi_get_dma_attr(to_acpi_device_node(dma_dev->fwnode));
+               if (attr != DEV_DMA_NOT_SUPPORTED)
+                       ret = acpi_dma_configure(dev, attr);
+       }
+
+       if (bridge)
+               pci_put_host_bridge_device(bridge);
+
+       return ret;
+}
+
+void dma_deconfigure(struct device *dev)
+{
+       of_dma_deconfigure(dev);
+       acpi_dma_deconfigure(dev);
+}
index ad196427b4f2a1c07f80e3a457d72b746c873eed..da49a8383dc30b074d28463e3b2771cd2ebd8adb 100644 (file)
@@ -1636,8 +1636,6 @@ static struct generic_pm_domain *genpd_xlate_simple(
                                        struct of_phandle_args *genpdspec,
                                        void *data)
 {
-       if (genpdspec->args_count != 0)
-               return ERR_PTR(-EINVAL);
        return data;
 }
 
index 9faee1c893e53c8dea6e14d472a73a8b7131bf96..e987a6f55d36747f79b470b0372a1abcff6390d7 100644 (file)
@@ -1091,11 +1091,6 @@ static int __device_suspend_noirq(struct device *dev, pm_message_t state, bool a
        if (async_error)
                goto Complete;
 
-       if (pm_wakeup_pending()) {
-               async_error = -EBUSY;
-               goto Complete;
-       }
-
        if (dev->power.syscore || dev->power.direct_complete)
                goto Complete;
 
index 1368549704893c0c93e50ccf2ccaaecda51c2b1e..f62082fdd6703e11c7576dc5db673dbc7dbba056 100644 (file)
@@ -28,8 +28,8 @@ bool events_check_enabled __read_mostly;
 /* First wakeup IRQ seen by the kernel in the last cycle. */
 unsigned int pm_wakeup_irq __read_mostly;
 
-/* If set and the system is suspending, terminate the suspend. */
-static bool pm_abort_suspend __read_mostly;
+/* If greater than 0 and the system is suspending, terminate the suspend. */
+static atomic_t pm_abort_suspend __read_mostly;
 
 /*
  * Combined counters of registered wakeup events and wakeup events in progress.
@@ -512,12 +512,13 @@ static bool wakeup_source_not_registered(struct wakeup_source *ws)
 /**
  * wakup_source_activate - Mark given wakeup source as active.
  * @ws: Wakeup source to handle.
+ * @hard: If set, abort suspends in progress and wake up from suspend-to-idle.
  *
  * Update the @ws' statistics and, if @ws has just been activated, notify the PM
  * core of the event by incrementing the counter of of wakeup events being
  * processed.
  */
-static void wakeup_source_activate(struct wakeup_source *ws)
+static void wakeup_source_activate(struct wakeup_source *ws, bool hard)
 {
        unsigned int cec;
 
@@ -525,11 +526,8 @@ static void wakeup_source_activate(struct wakeup_source *ws)
                        "unregistered wakeup source\n"))
                return;
 
-       /*
-        * active wakeup source should bring the system
-        * out of PM_SUSPEND_FREEZE state
-        */
-       freeze_wake();
+       if (hard)
+               pm_system_wakeup();
 
        ws->active = true;
        ws->active_count++;
@@ -546,8 +544,9 @@ static void wakeup_source_activate(struct wakeup_source *ws)
 /**
  * wakeup_source_report_event - Report wakeup event using the given source.
  * @ws: Wakeup source to report the event for.
+ * @hard: If set, abort suspends in progress and wake up from suspend-to-idle.
  */
-static void wakeup_source_report_event(struct wakeup_source *ws)
+static void wakeup_source_report_event(struct wakeup_source *ws, bool hard)
 {
        ws->event_count++;
        /* This is racy, but the counter is approximate anyway. */
@@ -555,7 +554,7 @@ static void wakeup_source_report_event(struct wakeup_source *ws)
                ws->wakeup_count++;
 
        if (!ws->active)
-               wakeup_source_activate(ws);
+               wakeup_source_activate(ws, hard);
 }
 
 /**
@@ -573,7 +572,7 @@ void __pm_stay_awake(struct wakeup_source *ws)
 
        spin_lock_irqsave(&ws->lock, flags);
 
-       wakeup_source_report_event(ws);
+       wakeup_source_report_event(ws, false);
        del_timer(&ws->timer);
        ws->timer_expires = 0;
 
@@ -739,9 +738,10 @@ static void pm_wakeup_timer_fn(unsigned long data)
 }
 
 /**
- * __pm_wakeup_event - Notify the PM core of a wakeup event.
+ * pm_wakeup_ws_event - Notify the PM core of a wakeup event.
  * @ws: Wakeup source object associated with the event source.
  * @msec: Anticipated event processing time (in milliseconds).
+ * @hard: If set, abort suspends in progress and wake up from suspend-to-idle.
  *
  * Notify the PM core of a wakeup event whose source is @ws that will take
  * approximately @msec milliseconds to be processed by the kernel.  If @ws is
@@ -750,7 +750,7 @@ static void pm_wakeup_timer_fn(unsigned long data)
  *
  * It is safe to call this function from interrupt context.
  */
-void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec)
+void pm_wakeup_ws_event(struct wakeup_source *ws, unsigned int msec, bool hard)
 {
        unsigned long flags;
        unsigned long expires;
@@ -760,7 +760,7 @@ void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec)
 
        spin_lock_irqsave(&ws->lock, flags);
 
-       wakeup_source_report_event(ws);
+       wakeup_source_report_event(ws, hard);
 
        if (!msec) {
                wakeup_source_deactivate(ws);
@@ -779,17 +779,17 @@ void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec)
  unlock:
        spin_unlock_irqrestore(&ws->lock, flags);
 }
-EXPORT_SYMBOL_GPL(__pm_wakeup_event);
-
+EXPORT_SYMBOL_GPL(pm_wakeup_ws_event);
 
 /**
  * pm_wakeup_event - Notify the PM core of a wakeup event.
  * @dev: Device the wakeup event is related to.
  * @msec: Anticipated event processing time (in milliseconds).
+ * @hard: If set, abort suspends in progress and wake up from suspend-to-idle.
  *
- * Call __pm_wakeup_event() for the @dev's wakeup source object.
+ * Call pm_wakeup_ws_event() for the @dev's wakeup source object.
  */
-void pm_wakeup_event(struct device *dev, unsigned int msec)
+void pm_wakeup_dev_event(struct device *dev, unsigned int msec, bool hard)
 {
        unsigned long flags;
 
@@ -797,10 +797,10 @@ void pm_wakeup_event(struct device *dev, unsigned int msec)
                return;
 
        spin_lock_irqsave(&dev->power.lock, flags);
-       __pm_wakeup_event(dev->power.wakeup, msec);
+       pm_wakeup_ws_event(dev->power.wakeup, msec, hard);
        spin_unlock_irqrestore(&dev->power.lock, flags);
 }
-EXPORT_SYMBOL_GPL(pm_wakeup_event);
+EXPORT_SYMBOL_GPL(pm_wakeup_dev_event);
 
 void pm_print_active_wakeup_sources(void)
 {
@@ -856,20 +856,26 @@ bool pm_wakeup_pending(void)
                pm_print_active_wakeup_sources();
        }
 
-       return ret || pm_abort_suspend;
+       return ret || atomic_read(&pm_abort_suspend) > 0;
 }
 
 void pm_system_wakeup(void)
 {
-       pm_abort_suspend = true;
+       atomic_inc(&pm_abort_suspend);
        freeze_wake();
 }
 EXPORT_SYMBOL_GPL(pm_system_wakeup);
 
-void pm_wakeup_clear(void)
+void pm_system_cancel_wakeup(void)
+{
+       atomic_dec(&pm_abort_suspend);
+}
+
+void pm_wakeup_clear(bool reset)
 {
-       pm_abort_suspend = false;
        pm_wakeup_irq = 0;
+       if (reset)
+               atomic_set(&pm_abort_suspend, 0);
 }
 
 void pm_system_irq_wakeup(unsigned int irq_number)
index dc26e5949a3202233ddbeecd6921cd3f1488120b..909dedae4c4e1d4802542e5f33e464da4be0e21d 100644 (file)
@@ -109,15 +109,18 @@ static void soc_release(struct device *dev)
        kfree(soc_dev);
 }
 
+static struct soc_device_attribute *early_soc_dev_attr;
+
 struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr)
 {
        struct soc_device *soc_dev;
        int ret;
 
        if (!soc_bus_type.p) {
-               ret = bus_register(&soc_bus_type);
-               if (ret)
-                       goto out1;
+               if (early_soc_dev_attr)
+                       return ERR_PTR(-EBUSY);
+               early_soc_dev_attr = soc_dev_attr;
+               return NULL;
        }
 
        soc_dev = kzalloc(sizeof(*soc_dev), GFP_KERNEL);
@@ -159,45 +162,53 @@ void soc_device_unregister(struct soc_device *soc_dev)
        ida_simple_remove(&soc_ida, soc_dev->soc_dev_num);
 
        device_unregister(&soc_dev->dev);
+       early_soc_dev_attr = NULL;
 }
 
 static int __init soc_bus_register(void)
 {
-       if (soc_bus_type.p)
-               return 0;
+       int ret;
 
-       return bus_register(&soc_bus_type);
+       ret = bus_register(&soc_bus_type);
+       if (ret)
+               return ret;
+
+       if (early_soc_dev_attr)
+               return PTR_ERR(soc_device_register(early_soc_dev_attr));
+
+       return 0;
 }
 core_initcall(soc_bus_register);
 
-static int soc_device_match_one(struct device *dev, void *arg)
+static int soc_device_match_attr(const struct soc_device_attribute *attr,
+                                const struct soc_device_attribute *match)
 {
-       struct soc_device *soc_dev = container_of(dev, struct soc_device, dev);
-       const struct soc_device_attribute *match = arg;
-
        if (match->machine &&
-           (!soc_dev->attr->machine ||
-            !glob_match(match->machine, soc_dev->attr->machine)))
+           (!attr->machine || !glob_match(match->machine, attr->machine)))
                return 0;
 
        if (match->family &&
-           (!soc_dev->attr->family ||
-            !glob_match(match->family, soc_dev->attr->family)))
+           (!attr->family || !glob_match(match->family, attr->family)))
                return 0;
 
        if (match->revision &&
-           (!soc_dev->attr->revision ||
-            !glob_match(match->revision, soc_dev->attr->revision)))
+           (!attr->revision || !glob_match(match->revision, attr->revision)))
                return 0;
 
        if (match->soc_id &&
-           (!soc_dev->attr->soc_id ||
-            !glob_match(match->soc_id, soc_dev->attr->soc_id)))
+           (!attr->soc_id || !glob_match(match->soc_id, attr->soc_id)))
                return 0;
 
        return 1;
 }
 
+static int soc_device_match_one(struct device *dev, void *arg)
+{
+       struct soc_device *soc_dev = container_of(dev, struct soc_device, dev);
+
+       return soc_device_match_attr(soc_dev->attr, arg);
+}
+
 /*
  * soc_device_match - identify the SoC in the machine
  * @matches: zero-terminated array of possible matches
@@ -230,6 +241,11 @@ const struct soc_device_attribute *soc_device_match(
                        break;
                ret = bus_for_each_dev(&soc_bus_type, NULL, (void *)matches,
                                       soc_device_match_one);
+               if (ret < 0 && early_soc_dev_attr)
+                       ret = soc_device_match_attr(early_soc_dev_attr,
+                                                   matches);
+               if (ret < 0)
+                       return NULL;
                if (!ret)
                        matches++;
                else
index dece26f119d4a637f742dca833b7ec9eecd25ebe..a804a4107fbc132795ae67a000f2b517b1047d32 100644 (file)
@@ -409,7 +409,7 @@ static struct page **bm_realloc_pages(struct drbd_bitmap *b, unsigned long want)
        new_pages = kzalloc(bytes, GFP_NOIO | __GFP_NOWARN);
        if (!new_pages) {
                new_pages = __vmalloc(bytes,
-                               GFP_NOIO | __GFP_HIGHMEM | __GFP_ZERO,
+                               GFP_NOIO | __GFP_ZERO,
                                PAGE_KERNEL);
                if (!new_pages)
                        return NULL;
index e9e2a9e95a66479ae780a785b3410469ed41451e..9a7bb2c2944772cad8124a965bacc17d0aa8f935 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/sched.h>
+#include <linux/sched/mm.h>
 #include <linux/fs.h>
 #include <linux/bio.h>
 #include <linux/stat.h>
@@ -347,7 +348,7 @@ static int sock_xmit(struct nbd_device *nbd, int index, int send,
        struct socket *sock = config->socks[index]->sock;
        int result;
        struct msghdr msg;
-       unsigned long pflags = current->flags;
+       unsigned int noreclaim_flag;
 
        if (unlikely(!sock)) {
                dev_err_ratelimited(disk_to_dev(nbd->disk),
@@ -358,7 +359,7 @@ static int sock_xmit(struct nbd_device *nbd, int index, int send,
 
        msg.msg_iter = *iter;
 
-       current->flags |= PF_MEMALLOC;
+       noreclaim_flag = memalloc_noreclaim_save();
        do {
                sock->sk->sk_allocation = GFP_NOIO | __GFP_MEMALLOC;
                msg.msg_name = NULL;
@@ -381,7 +382,7 @@ static int sock_xmit(struct nbd_device *nbd, int index, int send,
                        *sent += result;
        } while (msg_data_left(&msg));
 
-       current_restore_flags(pflags, PF_MEMALLOC);
+       memalloc_noreclaim_restore(noreclaim_flag);
 
        return result;
 }
index 3670e8dd03fe383dc6570fef16bbffa2784d61e8..454bf9c34882f33d673ccbaf0c8afa4f3ee18ad4 100644 (file)
@@ -387,6 +387,7 @@ struct rbd_device {
 
        struct rw_semaphore     lock_rwsem;
        enum rbd_lock_state     lock_state;
+       char                    lock_cookie[32];
        struct rbd_client_id    owner_cid;
        struct work_struct      acquired_lock_work;
        struct work_struct      released_lock_work;
@@ -477,13 +478,6 @@ static int minor_to_rbd_dev_id(int minor)
        return minor >> RBD_SINGLE_MAJOR_PART_SHIFT;
 }
 
-static bool rbd_is_lock_supported(struct rbd_device *rbd_dev)
-{
-       return (rbd_dev->header.features & RBD_FEATURE_EXCLUSIVE_LOCK) &&
-              rbd_dev->spec->snap_id == CEPH_NOSNAP &&
-              !rbd_dev->mapping.read_only;
-}
-
 static bool __rbd_is_lock_owner(struct rbd_device *rbd_dev)
 {
        return rbd_dev->lock_state == RBD_LOCK_STATE_LOCKED ||
@@ -731,7 +725,7 @@ static struct rbd_client *rbd_client_create(struct ceph_options *ceph_opts)
        kref_init(&rbdc->kref);
        INIT_LIST_HEAD(&rbdc->node);
 
-       rbdc->client = ceph_create_client(ceph_opts, rbdc, 0, 0);
+       rbdc->client = ceph_create_client(ceph_opts, rbdc);
        if (IS_ERR(rbdc->client))
                goto out_rbdc;
        ceph_opts = NULL; /* Now rbdc->client is responsible for ceph_opts */
@@ -804,6 +798,7 @@ enum {
        Opt_read_only,
        Opt_read_write,
        Opt_lock_on_read,
+       Opt_exclusive,
        Opt_err
 };
 
@@ -816,6 +811,7 @@ static match_table_t rbd_opts_tokens = {
        {Opt_read_write, "read_write"},
        {Opt_read_write, "rw"},         /* Alternate spelling */
        {Opt_lock_on_read, "lock_on_read"},
+       {Opt_exclusive, "exclusive"},
        {Opt_err, NULL}
 };
 
@@ -823,11 +819,13 @@ struct rbd_options {
        int     queue_depth;
        bool    read_only;
        bool    lock_on_read;
+       bool    exclusive;
 };
 
 #define RBD_QUEUE_DEPTH_DEFAULT        BLKDEV_MAX_RQ
 #define RBD_READ_ONLY_DEFAULT  false
 #define RBD_LOCK_ON_READ_DEFAULT false
+#define RBD_EXCLUSIVE_DEFAULT  false
 
 static int parse_rbd_opts_token(char *c, void *private)
 {
@@ -866,6 +864,9 @@ static int parse_rbd_opts_token(char *c, void *private)
        case Opt_lock_on_read:
                rbd_opts->lock_on_read = true;
                break;
+       case Opt_exclusive:
+               rbd_opts->exclusive = true;
+               break;
        default:
                /* libceph prints "bad option" msg */
                return -EINVAL;
@@ -1922,7 +1923,7 @@ static void rbd_osd_req_format_write(struct rbd_obj_request *obj_request)
 {
        struct ceph_osd_request *osd_req = obj_request->osd_req;
 
-       osd_req->r_mtime = CURRENT_TIME;
+       ktime_get_real_ts(&osd_req->r_mtime);
        osd_req->r_data_offset = obj_request->offset;
 }
 
@@ -3079,7 +3080,8 @@ static int rbd_lock(struct rbd_device *rbd_dev)
        char cookie[32];
        int ret;
 
-       WARN_ON(__rbd_is_lock_owner(rbd_dev));
+       WARN_ON(__rbd_is_lock_owner(rbd_dev) ||
+               rbd_dev->lock_cookie[0] != '\0');
 
        format_lock_cookie(rbd_dev, cookie);
        ret = ceph_cls_lock(osdc, &rbd_dev->header_oid, &rbd_dev->header_oloc,
@@ -3089,6 +3091,7 @@ static int rbd_lock(struct rbd_device *rbd_dev)
                return ret;
 
        rbd_dev->lock_state = RBD_LOCK_STATE_LOCKED;
+       strcpy(rbd_dev->lock_cookie, cookie);
        rbd_set_owner_cid(rbd_dev, &cid);
        queue_work(rbd_dev->task_wq, &rbd_dev->acquired_lock_work);
        return 0;
@@ -3097,27 +3100,24 @@ static int rbd_lock(struct rbd_device *rbd_dev)
 /*
  * lock_rwsem must be held for write
  */
-static int rbd_unlock(struct rbd_device *rbd_dev)
+static void rbd_unlock(struct rbd_device *rbd_dev)
 {
        struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc;
-       char cookie[32];
        int ret;
 
-       WARN_ON(!__rbd_is_lock_owner(rbd_dev));
-
-       rbd_dev->lock_state = RBD_LOCK_STATE_UNLOCKED;
+       WARN_ON(!__rbd_is_lock_owner(rbd_dev) ||
+               rbd_dev->lock_cookie[0] == '\0');
 
-       format_lock_cookie(rbd_dev, cookie);
        ret = ceph_cls_unlock(osdc, &rbd_dev->header_oid, &rbd_dev->header_oloc,
-                             RBD_LOCK_NAME, cookie);
-       if (ret && ret != -ENOENT) {
-               rbd_warn(rbd_dev, "cls_unlock failed: %d", ret);
-               return ret;
-       }
+                             RBD_LOCK_NAME, rbd_dev->lock_cookie);
+       if (ret && ret != -ENOENT)
+               rbd_warn(rbd_dev, "failed to unlock: %d", ret);
 
+       /* treat errors as the image is unlocked */
+       rbd_dev->lock_state = RBD_LOCK_STATE_UNLOCKED;
+       rbd_dev->lock_cookie[0] = '\0';
        rbd_set_owner_cid(rbd_dev, &rbd_empty_cid);
        queue_work(rbd_dev->task_wq, &rbd_dev->released_lock_work);
-       return 0;
 }
 
 static int __rbd_notify_op_lock(struct rbd_device *rbd_dev,
@@ -3447,6 +3447,18 @@ again:
        ret = rbd_request_lock(rbd_dev);
        if (ret == -ETIMEDOUT) {
                goto again; /* treat this as a dead client */
+       } else if (ret == -EROFS) {
+               rbd_warn(rbd_dev, "peer will not release lock");
+               /*
+                * If this is rbd_add_acquire_lock(), we want to fail
+                * immediately -- reuse BLACKLISTED flag.  Otherwise we
+                * want to block.
+                */
+               if (!(rbd_dev->disk->flags & GENHD_FL_UP)) {
+                       set_bit(RBD_DEV_FLAG_BLACKLISTED, &rbd_dev->flags);
+                       /* wake "rbd map --exclusive" process */
+                       wake_requests(rbd_dev, false);
+               }
        } else if (ret < 0) {
                rbd_warn(rbd_dev, "error requesting lock: %d", ret);
                mod_delayed_work(rbd_dev->task_wq, &rbd_dev->lock_dwork,
@@ -3490,16 +3502,15 @@ static bool rbd_release_lock(struct rbd_device *rbd_dev)
        if (rbd_dev->lock_state != RBD_LOCK_STATE_RELEASING)
                return false;
 
-       if (!rbd_unlock(rbd_dev))
-               /*
-                * Give others a chance to grab the lock - we would re-acquire
-                * almost immediately if we got new IO during ceph_osdc_sync()
-                * otherwise.  We need to ack our own notifications, so this
-                * lock_dwork will be requeued from rbd_wait_state_locked()
-                * after wake_requests() in rbd_handle_released_lock().
-                */
-               cancel_delayed_work(&rbd_dev->lock_dwork);
-
+       rbd_unlock(rbd_dev);
+       /*
+        * Give others a chance to grab the lock - we would re-acquire
+        * almost immediately if we got new IO during ceph_osdc_sync()
+        * otherwise.  We need to ack our own notifications, so this
+        * lock_dwork will be requeued from rbd_wait_state_locked()
+        * after wake_requests() in rbd_handle_released_lock().
+        */
+       cancel_delayed_work(&rbd_dev->lock_dwork);
        return true;
 }
 
@@ -3580,12 +3591,16 @@ static void rbd_handle_released_lock(struct rbd_device *rbd_dev, u8 struct_v,
        up_read(&rbd_dev->lock_rwsem);
 }
 
-static bool rbd_handle_request_lock(struct rbd_device *rbd_dev, u8 struct_v,
-                                   void **p)
+/*
+ * Returns result for ResponseMessage to be encoded (<= 0), or 1 if no
+ * ResponseMessage is needed.
+ */
+static int rbd_handle_request_lock(struct rbd_device *rbd_dev, u8 struct_v,
+                                  void **p)
 {
        struct rbd_client_id my_cid = rbd_get_cid(rbd_dev);
        struct rbd_client_id cid = { 0 };
-       bool need_to_send;
+       int result = 1;
 
        if (struct_v >= 2) {
                cid.gid = ceph_decode_64(p);
@@ -3595,19 +3610,36 @@ static bool rbd_handle_request_lock(struct rbd_device *rbd_dev, u8 struct_v,
        dout("%s rbd_dev %p cid %llu-%llu\n", __func__, rbd_dev, cid.gid,
             cid.handle);
        if (rbd_cid_equal(&cid, &my_cid))
-               return false;
+               return result;
 
        down_read(&rbd_dev->lock_rwsem);
-       need_to_send = __rbd_is_lock_owner(rbd_dev);
-       if (rbd_dev->lock_state == RBD_LOCK_STATE_LOCKED) {
-               if (!rbd_cid_equal(&rbd_dev->owner_cid, &rbd_empty_cid)) {
-                       dout("%s rbd_dev %p queueing unlock_work\n", __func__,
-                            rbd_dev);
-                       queue_work(rbd_dev->task_wq, &rbd_dev->unlock_work);
+       if (__rbd_is_lock_owner(rbd_dev)) {
+               if (rbd_dev->lock_state == RBD_LOCK_STATE_LOCKED &&
+                   rbd_cid_equal(&rbd_dev->owner_cid, &rbd_empty_cid))
+                       goto out_unlock;
+
+               /*
+                * encode ResponseMessage(0) so the peer can detect
+                * a missing owner
+                */
+               result = 0;
+
+               if (rbd_dev->lock_state == RBD_LOCK_STATE_LOCKED) {
+                       if (!rbd_dev->opts->exclusive) {
+                               dout("%s rbd_dev %p queueing unlock_work\n",
+                                    __func__, rbd_dev);
+                               queue_work(rbd_dev->task_wq,
+                                          &rbd_dev->unlock_work);
+                       } else {
+                               /* refuse to release the lock */
+                               result = -EROFS;
+                       }
                }
        }
+
+out_unlock:
        up_read(&rbd_dev->lock_rwsem);
-       return need_to_send;
+       return result;
 }
 
 static void __rbd_acknowledge_notify(struct rbd_device *rbd_dev,
@@ -3690,13 +3722,10 @@ static void rbd_watch_cb(void *arg, u64 notify_id, u64 cookie,
                rbd_acknowledge_notify(rbd_dev, notify_id, cookie);
                break;
        case RBD_NOTIFY_OP_REQUEST_LOCK:
-               if (rbd_handle_request_lock(rbd_dev, struct_v, &p))
-                       /*
-                        * send ResponseMessage(0) back so the client
-                        * can detect a missing owner
-                        */
+               ret = rbd_handle_request_lock(rbd_dev, struct_v, &p);
+               if (ret <= 0)
                        rbd_acknowledge_notify_result(rbd_dev, notify_id,
-                                                     cookie, 0);
+                                                     cookie, ret);
                else
                        rbd_acknowledge_notify(rbd_dev, notify_id, cookie);
                break;
@@ -3821,24 +3850,51 @@ static void rbd_unregister_watch(struct rbd_device *rbd_dev)
        ceph_osdc_flush_notifies(&rbd_dev->rbd_client->client->osdc);
 }
 
+/*
+ * lock_rwsem must be held for write
+ */
+static void rbd_reacquire_lock(struct rbd_device *rbd_dev)
+{
+       struct ceph_osd_client *osdc = &rbd_dev->rbd_client->client->osdc;
+       char cookie[32];
+       int ret;
+
+       WARN_ON(rbd_dev->lock_state != RBD_LOCK_STATE_LOCKED);
+
+       format_lock_cookie(rbd_dev, cookie);
+       ret = ceph_cls_set_cookie(osdc, &rbd_dev->header_oid,
+                                 &rbd_dev->header_oloc, RBD_LOCK_NAME,
+                                 CEPH_CLS_LOCK_EXCLUSIVE, rbd_dev->lock_cookie,
+                                 RBD_LOCK_TAG, cookie);
+       if (ret) {
+               if (ret != -EOPNOTSUPP)
+                       rbd_warn(rbd_dev, "failed to update lock cookie: %d",
+                                ret);
+
+               /*
+                * Lock cookie cannot be updated on older OSDs, so do
+                * a manual release and queue an acquire.
+                */
+               if (rbd_release_lock(rbd_dev))
+                       queue_delayed_work(rbd_dev->task_wq,
+                                          &rbd_dev->lock_dwork, 0);
+       } else {
+               strcpy(rbd_dev->lock_cookie, cookie);
+       }
+}
+
 static void rbd_reregister_watch(struct work_struct *work)
 {
        struct rbd_device *rbd_dev = container_of(to_delayed_work(work),
                                            struct rbd_device, watch_dwork);
-       bool was_lock_owner = false;
-       bool need_to_wake = false;
        int ret;
 
        dout("%s rbd_dev %p\n", __func__, rbd_dev);
 
-       down_write(&rbd_dev->lock_rwsem);
-       if (rbd_dev->lock_state == RBD_LOCK_STATE_LOCKED)
-               was_lock_owner = rbd_release_lock(rbd_dev);
-
        mutex_lock(&rbd_dev->watch_mutex);
        if (rbd_dev->watch_state != RBD_WATCH_STATE_ERROR) {
                mutex_unlock(&rbd_dev->watch_mutex);
-               goto out;
+               return;
        }
 
        ret = __rbd_register_watch(rbd_dev);
@@ -3846,36 +3902,28 @@ static void rbd_reregister_watch(struct work_struct *work)
                rbd_warn(rbd_dev, "failed to reregister watch: %d", ret);
                if (ret == -EBLACKLISTED || ret == -ENOENT) {
                        set_bit(RBD_DEV_FLAG_BLACKLISTED, &rbd_dev->flags);
-                       need_to_wake = true;
+                       wake_requests(rbd_dev, true);
                } else {
                        queue_delayed_work(rbd_dev->task_wq,
                                           &rbd_dev->watch_dwork,
                                           RBD_RETRY_DELAY);
                }
                mutex_unlock(&rbd_dev->watch_mutex);
-               goto out;
+               return;
        }
 
-       need_to_wake = true;
        rbd_dev->watch_state = RBD_WATCH_STATE_REGISTERED;
        rbd_dev->watch_cookie = rbd_dev->watch_handle->linger_id;
        mutex_unlock(&rbd_dev->watch_mutex);
 
+       down_write(&rbd_dev->lock_rwsem);
+       if (rbd_dev->lock_state == RBD_LOCK_STATE_LOCKED)
+               rbd_reacquire_lock(rbd_dev);
+       up_write(&rbd_dev->lock_rwsem);
+
        ret = rbd_dev_refresh(rbd_dev);
        if (ret)
                rbd_warn(rbd_dev, "reregisteration refresh failed: %d", ret);
-
-       if (was_lock_owner) {
-               ret = rbd_try_lock(rbd_dev);
-               if (ret)
-                       rbd_warn(rbd_dev, "reregisteration lock failed: %d",
-                                ret);
-       }
-
-out:
-       up_write(&rbd_dev->lock_rwsem);
-       if (need_to_wake)
-               wake_requests(rbd_dev, true);
 }
 
 /*
@@ -4034,10 +4082,6 @@ static void rbd_queue_workfn(struct work_struct *work)
        if (op_type != OBJ_OP_READ) {
                snapc = rbd_dev->header.snapc;
                ceph_get_snap_context(snapc);
-               must_be_locked = rbd_is_lock_supported(rbd_dev);
-       } else {
-               must_be_locked = rbd_dev->opts->lock_on_read &&
-                                       rbd_is_lock_supported(rbd_dev);
        }
        up_read(&rbd_dev->header_rwsem);
 
@@ -4048,14 +4092,20 @@ static void rbd_queue_workfn(struct work_struct *work)
                goto err_rq;
        }
 
+       must_be_locked =
+           (rbd_dev->header.features & RBD_FEATURE_EXCLUSIVE_LOCK) &&
+           (op_type != OBJ_OP_READ || rbd_dev->opts->lock_on_read);
        if (must_be_locked) {
                down_read(&rbd_dev->lock_rwsem);
                if (rbd_dev->lock_state != RBD_LOCK_STATE_LOCKED &&
-                   !test_bit(RBD_DEV_FLAG_BLACKLISTED, &rbd_dev->flags))
+                   !test_bit(RBD_DEV_FLAG_BLACKLISTED, &rbd_dev->flags)) {
+                       if (rbd_dev->opts->exclusive) {
+                               rbd_warn(rbd_dev, "exclusive lock required");
+                               result = -EROFS;
+                               goto err_unlock;
+                       }
                        rbd_wait_state_locked(rbd_dev);
-
-               WARN_ON((rbd_dev->lock_state == RBD_LOCK_STATE_LOCKED) ^
-                       !test_bit(RBD_DEV_FLAG_BLACKLISTED, &rbd_dev->flags));
+               }
                if (test_bit(RBD_DEV_FLAG_BLACKLISTED, &rbd_dev->flags)) {
                        result = -EBLACKLISTED;
                        goto err_unlock;
@@ -4114,19 +4164,10 @@ static int rbd_queue_rq(struct blk_mq_hw_ctx *hctx,
 
 static void rbd_free_disk(struct rbd_device *rbd_dev)
 {
-       struct gendisk *disk = rbd_dev->disk;
-
-       if (!disk)
-               return;
-
+       blk_cleanup_queue(rbd_dev->disk->queue);
+       blk_mq_free_tag_set(&rbd_dev->tag_set);
+       put_disk(rbd_dev->disk);
        rbd_dev->disk = NULL;
-       if (disk->flags & GENHD_FL_UP) {
-               del_gendisk(disk);
-               if (disk->queue)
-                       blk_cleanup_queue(disk->queue);
-               blk_mq_free_tag_set(&rbd_dev->tag_set);
-       }
-       put_disk(disk);
 }
 
 static int rbd_obj_read_sync(struct rbd_device *rbd_dev,
@@ -4383,8 +4424,12 @@ static int rbd_init_disk(struct rbd_device *rbd_dev)
        if (!ceph_test_opt(rbd_dev->rbd_client->client, NOCRC))
                q->backing_dev_info->capabilities |= BDI_CAP_STABLE_WRITES;
 
+       /*
+        * disk_release() expects a queue ref from add_disk() and will
+        * put it.  Hold an extra ref until add_disk() is called.
+        */
+       WARN_ON(!blk_get_queue(q));
        disk->queue = q;
-
        q->queuedata = rbd_dev;
 
        rbd_dev->disk = disk;
@@ -5624,6 +5669,7 @@ static int rbd_add_parse_args(const char *buf,
        rbd_opts->read_only = RBD_READ_ONLY_DEFAULT;
        rbd_opts->queue_depth = RBD_QUEUE_DEPTH_DEFAULT;
        rbd_opts->lock_on_read = RBD_LOCK_ON_READ_DEFAULT;
+       rbd_opts->exclusive = RBD_EXCLUSIVE_DEFAULT;
 
        copts = ceph_parse_options(options, mon_addrs,
                                        mon_addrs + mon_addrs_size - 1,
@@ -5682,6 +5728,33 @@ again:
        return ret;
 }
 
+static void rbd_dev_image_unlock(struct rbd_device *rbd_dev)
+{
+       down_write(&rbd_dev->lock_rwsem);
+       if (__rbd_is_lock_owner(rbd_dev))
+               rbd_unlock(rbd_dev);
+       up_write(&rbd_dev->lock_rwsem);
+}
+
+static int rbd_add_acquire_lock(struct rbd_device *rbd_dev)
+{
+       if (!(rbd_dev->header.features & RBD_FEATURE_EXCLUSIVE_LOCK)) {
+               rbd_warn(rbd_dev, "exclusive-lock feature is not enabled");
+               return -EINVAL;
+       }
+
+       /* FIXME: "rbd map --exclusive" should be in interruptible */
+       down_read(&rbd_dev->lock_rwsem);
+       rbd_wait_state_locked(rbd_dev);
+       up_read(&rbd_dev->lock_rwsem);
+       if (test_bit(RBD_DEV_FLAG_BLACKLISTED, &rbd_dev->flags)) {
+               rbd_warn(rbd_dev, "failed to acquire exclusive lock");
+               return -EROFS;
+       }
+
+       return 0;
+}
+
 /*
  * An rbd format 2 image has a unique identifier, distinct from the
  * name given to it by the user.  Internally, that identifier is
@@ -5873,6 +5946,15 @@ out_err:
        return ret;
 }
 
+static void rbd_dev_device_release(struct rbd_device *rbd_dev)
+{
+       clear_bit(RBD_DEV_FLAG_EXISTS, &rbd_dev->flags);
+       rbd_dev_mapping_clear(rbd_dev);
+       rbd_free_disk(rbd_dev);
+       if (!single_major)
+               unregister_blkdev(rbd_dev->major, rbd_dev->name);
+}
+
 /*
  * rbd_dev->header_rwsem must be locked for write and will be unlocked
  * upon return.
@@ -5908,26 +5990,13 @@ static int rbd_dev_device_setup(struct rbd_device *rbd_dev)
        set_capacity(rbd_dev->disk, rbd_dev->mapping.size / SECTOR_SIZE);
        set_disk_ro(rbd_dev->disk, rbd_dev->mapping.read_only);
 
-       dev_set_name(&rbd_dev->dev, "%d", rbd_dev->dev_id);
-       ret = device_add(&rbd_dev->dev);
+       ret = dev_set_name(&rbd_dev->dev, "%d", rbd_dev->dev_id);
        if (ret)
                goto err_out_mapping;
 
-       /* Everything's ready.  Announce the disk to the world. */
-
        set_bit(RBD_DEV_FLAG_EXISTS, &rbd_dev->flags);
        up_write(&rbd_dev->header_rwsem);
-
-       spin_lock(&rbd_dev_list_lock);
-       list_add_tail(&rbd_dev->node, &rbd_dev_list);
-       spin_unlock(&rbd_dev_list_lock);
-
-       add_disk(rbd_dev->disk);
-       pr_info("%s: capacity %llu features 0x%llx\n", rbd_dev->disk->disk_name,
-               (unsigned long long)get_capacity(rbd_dev->disk) << SECTOR_SHIFT,
-               rbd_dev->header.features);
-
-       return ret;
+       return 0;
 
 err_out_mapping:
        rbd_dev_mapping_clear(rbd_dev);
@@ -5962,11 +6031,11 @@ static int rbd_dev_header_name(struct rbd_device *rbd_dev)
 static void rbd_dev_image_release(struct rbd_device *rbd_dev)
 {
        rbd_dev_unprobe(rbd_dev);
+       if (rbd_dev->opts)
+               rbd_unregister_watch(rbd_dev);
        rbd_dev->image_format = 0;
        kfree(rbd_dev->spec->image_id);
        rbd_dev->spec->image_id = NULL;
-
-       rbd_dev_destroy(rbd_dev);
 }
 
 /*
@@ -6126,22 +6195,43 @@ static ssize_t do_rbd_add(struct bus_type *bus,
        rbd_dev->mapping.read_only = read_only;
 
        rc = rbd_dev_device_setup(rbd_dev);
-       if (rc) {
-               /*
-                * rbd_unregister_watch() can't be moved into
-                * rbd_dev_image_release() without refactoring, see
-                * commit 1f3ef78861ac.
-                */
-               rbd_unregister_watch(rbd_dev);
-               rbd_dev_image_release(rbd_dev);
-               goto out;
+       if (rc)
+               goto err_out_image_probe;
+
+       if (rbd_dev->opts->exclusive) {
+               rc = rbd_add_acquire_lock(rbd_dev);
+               if (rc)
+                       goto err_out_device_setup;
        }
 
+       /* Everything's ready.  Announce the disk to the world. */
+
+       rc = device_add(&rbd_dev->dev);
+       if (rc)
+               goto err_out_image_lock;
+
+       add_disk(rbd_dev->disk);
+       /* see rbd_init_disk() */
+       blk_put_queue(rbd_dev->disk->queue);
+
+       spin_lock(&rbd_dev_list_lock);
+       list_add_tail(&rbd_dev->node, &rbd_dev_list);
+       spin_unlock(&rbd_dev_list_lock);
+
+       pr_info("%s: capacity %llu features 0x%llx\n", rbd_dev->disk->disk_name,
+               (unsigned long long)get_capacity(rbd_dev->disk) << SECTOR_SHIFT,
+               rbd_dev->header.features);
        rc = count;
 out:
        module_put(THIS_MODULE);
        return rc;
 
+err_out_image_lock:
+       rbd_dev_image_unlock(rbd_dev);
+err_out_device_setup:
+       rbd_dev_device_release(rbd_dev);
+err_out_image_probe:
+       rbd_dev_image_release(rbd_dev);
 err_out_rbd_dev:
        rbd_dev_destroy(rbd_dev);
 err_out_client:
@@ -6169,21 +6259,6 @@ static ssize_t rbd_add_single_major(struct bus_type *bus,
        return do_rbd_add(bus, buf, count);
 }
 
-static void rbd_dev_device_release(struct rbd_device *rbd_dev)
-{
-       rbd_free_disk(rbd_dev);
-
-       spin_lock(&rbd_dev_list_lock);
-       list_del_init(&rbd_dev->node);
-       spin_unlock(&rbd_dev_list_lock);
-
-       clear_bit(RBD_DEV_FLAG_EXISTS, &rbd_dev->flags);
-       device_del(&rbd_dev->dev);
-       rbd_dev_mapping_clear(rbd_dev);
-       if (!single_major)
-               unregister_blkdev(rbd_dev->major, rbd_dev->name);
-}
-
 static void rbd_dev_remove_parent(struct rbd_device *rbd_dev)
 {
        while (rbd_dev->parent) {
@@ -6201,6 +6276,7 @@ static void rbd_dev_remove_parent(struct rbd_device *rbd_dev)
                }
                rbd_assert(second);
                rbd_dev_image_release(second);
+               rbd_dev_destroy(second);
                first->parent = NULL;
                first->parent_overlap = 0;
 
@@ -6269,21 +6345,16 @@ static ssize_t do_rbd_remove(struct bus_type *bus,
                blk_set_queue_dying(rbd_dev->disk->queue);
        }
 
-       down_write(&rbd_dev->lock_rwsem);
-       if (__rbd_is_lock_owner(rbd_dev))
-               rbd_unlock(rbd_dev);
-       up_write(&rbd_dev->lock_rwsem);
-       rbd_unregister_watch(rbd_dev);
+       del_gendisk(rbd_dev->disk);
+       spin_lock(&rbd_dev_list_lock);
+       list_del_init(&rbd_dev->node);
+       spin_unlock(&rbd_dev_list_lock);
+       device_del(&rbd_dev->dev);
 
-       /*
-        * Don't free anything from rbd_dev->disk until after all
-        * notifies are completely processed. Otherwise
-        * rbd_bus_del_dev() will race with rbd_watch_cb(), resulting
-        * in a potential use after free of rbd_dev->disk or rbd_dev.
-        */
+       rbd_dev_image_unlock(rbd_dev);
        rbd_dev_device_release(rbd_dev);
        rbd_dev_image_release(rbd_dev);
-
+       rbd_dev_destroy(rbd_dev);
        return count;
 }
 
index 94173de1efaab18b07924ed0c8431dbb6ba5ca34..553cc4c542b4f13a5a04d4ca48af24198401c9f8 100644 (file)
@@ -452,8 +452,7 @@ static int init_vq(struct virtio_blk *vblk)
        }
 
        /* Discover virtqueues and write information to configuration.  */
-       err = vdev->config->find_vqs(vdev, num_vqs, vqs, callbacks, names,
-                       &desc);
+       err = virtio_find_vqs(vdev, num_vqs, vqs, callbacks, names, &desc);
        if (err)
                goto out;
 
index 3661a51e93e2d37db31d1aa4997b0bdfeb149a05..5fbd333e4c6d74bbd2e34f25ac74648f9b13a62d 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/page-flags.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
+#include <asm/set_memory.h>
 #include "agp.h"
 
 #define AMD_MMBASE_BAR 1
index 75a9786a77e6307711a74bcde8f4dd7fee8fcae0..0b5ec7af2414bb924fa1a927aafe0d4115492281 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/slab.h>
 #include <linux/agp_backend.h>
 #include <asm/agp.h>
+#include <asm/set_memory.h>
 #include "agp.h"
 
 #define ATI_GART_MMBASE_BAR    1
index f002fa5d1887a0b183b2532891fd853c2587f239..658664a5a5aa4f31404584bd283b1d6530e882ba 100644 (file)
@@ -39,7 +39,9 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <asm/io.h>
-#include <asm/cacheflush.h>
+#ifdef CONFIG_X86
+#include <asm/set_memory.h>
+#endif
 #include <asm/pgtable.h>
 #include "agp.h"
 
@@ -88,13 +90,7 @@ static int agp_get_key(void)
 
 void agp_alloc_page_array(size_t size, struct agp_memory *mem)
 {
-       mem->pages = NULL;
-
-       if (size <= 2*PAGE_SIZE)
-               mem->pages = kmalloc(size, GFP_KERNEL | __GFP_NOWARN);
-       if (mem->pages == NULL) {
-               mem->pages = vmalloc(size);
-       }
+       mem->pages = kvmalloc(size, GFP_KERNEL);
 }
 EXPORT_SYMBOL(agp_alloc_page_array);
 
index 7fcc2a9d1d5afc17aa47f65f15025615d1fe163e..9b6b6023193bcb29ea7390d83b8eab91cae8412b 100644 (file)
@@ -25,6 +25,7 @@
 #include "agp.h"
 #include "intel-agp.h"
 #include <drm/intel-gtt.h>
+#include <asm/set_memory.h>
 
 /*
  * If we have Intel graphics, we're not going to have anything other than
index 9b163b49d976323fae9828f963f5e593031ffb68..03be4ac79b0dfb7d8281bddc0b382e848a3c24f4 100644 (file)
@@ -9,6 +9,7 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/agp_backend.h>
+#include <asm/set_memory.h>
 #include "agp.h"
 
 #define SVWRKS_COMMAND         0x04
index e770ad97747235f0f67d635a8a578bfc76826bfc..b67263d6e34b172a87381a4cfe21fed42bf0799c 100644 (file)
@@ -94,9 +94,9 @@ static struct applicom_board {
 static unsigned int irq = 0;   /* interrupt number IRQ       */
 static unsigned long mem = 0;  /* physical segment of board  */
 
-module_param(irq, uint, 0);
+module_param_hw(irq, uint, irq, 0);
 MODULE_PARM_DESC(irq, "IRQ of the Applicom board");
-module_param(mem, ulong, 0);
+module_param_hw(mem, ulong, iomem, 0);
 MODULE_PARM_DESC(mem, "Shared Memory Address of Applicom board");
 
 static unsigned int numboards; /* number of installed boards */
index 50aa9ba91f255c6a99f1b385ecd065cbc5541d24..0d7b577e0ff0ee5d654b22e3d3bd78644395301b 100644 (file)
@@ -489,7 +489,7 @@ static const struct file_operations dsp56k_fops = {
 
 /****** Init and module functions ******/
 
-static char banner[] __initdata = KERN_INFO "DSP56k driver installed\n";
+static const char banner[] __initconst = KERN_INFO "DSP56k driver installed\n";
 
 static int __init dsp56k_init_driver(void)
 {
index b2b618f066e02b85c185ba3a17cd1a4ca9e8eaf8..59ee93ea84ebe8807ee3bcf1084f95cd53d5e4f8 100644 (file)
@@ -1375,39 +1375,39 @@ MODULE_PARM_DESC(type, "Defines the type of each interface, each"
                 " interface separated by commas.  The types are 'kcs',"
                 " 'smic', and 'bt'.  For example si_type=kcs,bt will set"
                 " the first interface to kcs and the second to bt");
-module_param_array(addrs, ulong, &num_addrs, 0);
+module_param_hw_array(addrs, ulong, iomem, &num_addrs, 0);
 MODULE_PARM_DESC(addrs, "Sets the memory address of each interface, the"
                 " addresses separated by commas.  Only use if an interface"
                 " is in memory.  Otherwise, set it to zero or leave"
                 " it blank.");
-module_param_array(ports, uint, &num_ports, 0);
+module_param_hw_array(ports, uint, ioport, &num_ports, 0);
 MODULE_PARM_DESC(ports, "Sets the port address of each interface, the"
                 " addresses separated by commas.  Only use if an interface"
                 " is a port.  Otherwise, set it to zero or leave"
                 " it blank.");
-module_param_array(irqs, int, &num_irqs, 0);
+module_param_hw_array(irqs, int, irq, &num_irqs, 0);
 MODULE_PARM_DESC(irqs, "Sets the interrupt of each interface, the"
                 " addresses separated by commas.  Only use if an interface"
                 " has an interrupt.  Otherwise, set it to zero or leave"
                 " it blank.");
-module_param_array(regspacings, int, &num_regspacings, 0);
+module_param_hw_array(regspacings, int, other, &num_regspacings, 0);
 MODULE_PARM_DESC(regspacings, "The number of bytes between the start address"
                 " and each successive register used by the interface.  For"
                 " instance, if the start address is 0xca2 and the spacing"
                 " is 2, then the second address is at 0xca4.  Defaults"
                 " to 1.");
-module_param_array(regsizes, int, &num_regsizes, 0);
+module_param_hw_array(regsizes, int, other, &num_regsizes, 0);
 MODULE_PARM_DESC(regsizes, "The size of the specific IPMI register in bytes."
                 " This should generally be 1, 2, 4, or 8 for an 8-bit,"
                 " 16-bit, 32-bit, or 64-bit register.  Use this if you"
                 " the 8-bit IPMI register has to be read from a larger"
                 " register.");
-module_param_array(regshifts, int, &num_regshifts, 0);
+module_param_hw_array(regshifts, int, other, &num_regshifts, 0);
 MODULE_PARM_DESC(regshifts, "The amount to shift the data read from the."
                 " IPMI register, in bits.  For instance, if the data"
                 " is read from a 32-bit word and the IPMI data is in"
                 " bit 8-15, then the shift would be 8");
-module_param_array(slave_addrs, int, &num_slave_addrs, 0);
+module_param_hw_array(slave_addrs, int, other, &num_slave_addrs, 0);
 MODULE_PARM_DESC(slave_addrs, "Set the default IPMB slave address for"
                 " the controller.  Normally this is 0x20, but can be"
                 " overridden by this parm.  This is an array indexed"
index 3a3ff2eb6cba3f2e530e11700cfb133451badb70..b5e3103c1175575a0e16d3f4168b4d343aca7b6f 100644 (file)
@@ -80,10 +80,10 @@ int mwave_3780i_io = 0;
 int mwave_uart_irq = 0;
 int mwave_uart_io = 0;
 module_param(mwave_debug, int, 0);
-module_param(mwave_3780i_irq, int, 0);
-module_param(mwave_3780i_io, int, 0);
-module_param(mwave_uart_irq, int, 0);
-module_param(mwave_uart_io, int, 0);
+module_param_hw(mwave_3780i_irq, int, irq, 0);
+module_param_hw(mwave_3780i_io, int, ioport, 0);
+module_param_hw(mwave_uart_irq, int, irq, 0);
+module_param_hw(mwave_uart_io, int, ioport, 0);
 
 static int mwave_open(struct inode *inode, struct file *file);
 static int mwave_close(struct inode *inode, struct file *file);
index 7d041d026680d337a06fcb4fabf0f4ff955612c6..ad843eb02ae7be21ae7470c6cc840a30a3f6e272 100644 (file)
@@ -1945,9 +1945,9 @@ static int init_vqs(struct ports_device *portdev)
                }
        }
        /* Find the queues. */
-       err = portdev->vdev->config->find_vqs(portdev->vdev, nr_queues, vqs,
-                                             io_callbacks,
-                                             (const char **)io_names, NULL);
+       err = virtio_find_vqs(portdev->vdev, nr_queues, vqs,
+                             io_callbacks,
+                             (const char **)io_names, NULL);
        if (err)
                goto free;
 
index 9356ab4b7d76e7c95057d76c83259d7a2fa2ce63..36cfea38135f6afc2266aecf19fee862e8110951 100644 (file)
@@ -47,6 +47,14 @@ config COMMON_CLK_RK808
          clocked at 32KHz each. Clkout1 is always on, Clkout2 can off
          by control register.
 
+config COMMON_CLK_HI655X
+       tristate "Clock driver for Hi655x"
+       depends on MFD_HI655X_PMIC || COMPILE_TEST
+       ---help---
+         This driver supports the hi655x PMIC clock. This
+         multi-function device has one fixed-rate oscillator, clocked
+         at 32KHz.
+
 config COMMON_CLK_SCPI
        tristate "Clock driver controlled via SCPI interface"
        depends on ARM_SCPI_PROTOCOL || COMPILE_TEST
index 92c12b86c2e86f2022faeb434bb961f2410faa3e..c19983afcb81c9d1ec8e5059a1a29d70e97a4ca1 100644 (file)
@@ -36,6 +36,7 @@ obj-$(CONFIG_COMMON_CLK_PALMAS)               += clk-palmas.o
 obj-$(CONFIG_COMMON_CLK_PWM)           += clk-pwm.o
 obj-$(CONFIG_CLK_QORIQ)                        += clk-qoriq.o
 obj-$(CONFIG_COMMON_CLK_RK808)         += clk-rk808.o
+obj-$(CONFIG_COMMON_CLK_HI655X)                += clk-hi655x.o
 obj-$(CONFIG_COMMON_CLK_S2MPS11)       += clk-s2mps11.o
 obj-$(CONFIG_COMMON_CLK_SCPI)           += clk-scpi.o
 obj-$(CONFIG_COMMON_CLK_SI5351)                += clk-si5351.o
index 45ad168e1496562fb79ccd2c4fceb0f5a9ea2087..7d3223fc71619f41252c4d47772ece1f909afc45 100644 (file)
@@ -399,18 +399,18 @@ of_at91_clk_pll_get_characteristics(struct device_node *np)
        if (!characteristics)
                return NULL;
 
-       output = kzalloc(sizeof(*output) * num_output, GFP_KERNEL);
+       output = kcalloc(num_output, sizeof(*output), GFP_KERNEL);
        if (!output)
                goto out_free_characteristics;
 
        if (num_cells > 2) {
-               out = kzalloc(sizeof(*out) * num_output, GFP_KERNEL);
+               out = kcalloc(num_output, sizeof(*out), GFP_KERNEL);
                if (!out)
                        goto out_free_output;
        }
 
        if (num_cells > 3) {
-               icpll = kzalloc(sizeof(*icpll) * num_output, GFP_KERNEL);
+               icpll = kcalloc(num_output, sizeof(*icpll), GFP_KERNEL);
                if (!icpll)
                        goto out_free_output;
        }
index e04634c46395b43f9a1d7e452d59dacecff4bce7..2d61893da0244d9acecc735afd02278cd5582108 100644 (file)
@@ -277,7 +277,7 @@ static int pll_set_rate(struct iproc_clk *clk, unsigned int rate_index,
        if (rate >= VCO_LOW && rate < VCO_HIGH) {
                ki = 4;
                kp_index = KP_BAND_MID;
-       } else if (rate >= VCO_HIGH && rate && rate < VCO_HIGH_HIGH) {
+       } else if (rate >= VCO_HIGH && rate < VCO_HIGH_HIGH) {
                ki = 3;
                kp_index = KP_BAND_HIGH;
        } else if (rate >= VCO_HIGH_HIGH && rate < VCO_MAX) {
index a564e9248814c19129b0f824f36e1511a98938cc..adc14145861a4f1309d1613ce9583fcbdddcb89e 100644 (file)
@@ -103,7 +103,7 @@ CLK_OF_DECLARE(ns2_genpll_src_clk, "brcm,ns2-genpll-scr",
 
 static const struct iproc_pll_ctrl genpll_sw = {
        .flags = IPROC_CLK_AON | IPROC_CLK_PLL_SPLIT_STAT_CTRL,
-       .aon = AON_VAL(0x0, 2, 9, 8),
+       .aon = AON_VAL(0x0, 1, 11, 10),
        .reset = RESET_VAL(0x4, 2, 1),
        .dig_filter = DF_VAL(0x0, 9, 3, 5, 4, 2, 3),
        .ndiv_int = REG_VAL(0x8, 4, 10),
index 3fca0526d940af68fc2a9b550b5951014f2a7dcc..c54baede4d68733ad2861b24e24c0f082aa5520e 100644 (file)
 
 /* DEVICE_CTRL */
 #define PLL_UNLOCK     (1 << 7)
+#define AUXOUTDIS      (1 << 1)
+#define CLKOUTDIS      (1 << 0)
 
 /* DEVICE_CFG1 */
 #define RSEL(x)                (((x) & 0x3) << 3)
 #define RSEL_MASK      RSEL(0x3)
 #define ENDEV1         (0x1)
 
+/* DEVICE_CFG2 */
+#define AUTORMOD       (1 << 3)
+#define LOCKCLK(x)     (((x) & 0x3) << 1)
+#define LOCKCLK_MASK   LOCKCLK(0x3)
+#define FRACNSRC_MASK  (1 << 0)
+#define FRACNSRC_STATIC                (0 << 0)
+#define FRACNSRC_DYNAMIC       (1 << 1)
+
 /* GLOBAL_CFG */
 #define ENDEV2         (0x1)
 
+/* FUNC_CFG1 */
+#define CLKSKIPEN      (1 << 7)
+#define REFCLKDIV(x)   (((x) & 0x3) << 3)
+#define REFCLKDIV_MASK REFCLKDIV(0x3)
+
+/* FUNC_CFG2 */
+#define LFRATIO_MASK   (1 << 3)
+#define LFRATIO_20_12  (0 << 3)
+#define LFRATIO_12_20  (1 << 3)
+
 #define CH_SIZE_ERR(ch)                ((ch < 0) || (ch >= CH_MAX))
 #define hw_to_priv(_hw)                container_of(_hw, struct cs2000_priv, hw)
 #define priv_to_client(priv)   (priv->client)
@@ -110,6 +130,17 @@ static int cs2000_enable_dev_config(struct cs2000_priv *priv, bool enable)
        if (ret < 0)
                return ret;
 
+       ret = cs2000_bset(priv, FUNC_CFG1, CLKSKIPEN,
+                         enable ? CLKSKIPEN : 0);
+       if (ret < 0)
+               return ret;
+
+       /* FIXME: for Static ratio mode */
+       ret = cs2000_bset(priv, FUNC_CFG2, LFRATIO_MASK,
+                         LFRATIO_12_20);
+       if (ret < 0)
+               return ret;
+
        return 0;
 }
 
@@ -127,7 +158,9 @@ static int cs2000_clk_in_bound_rate(struct cs2000_priv *priv,
        else
                return -EINVAL;
 
-       return cs2000_bset(priv, FUNC_CFG1, 0x3 << 3, val << 3);
+       return cs2000_bset(priv, FUNC_CFG1,
+                          REFCLKDIV_MASK,
+                          REFCLKDIV(val));
 }
 
 static int cs2000_wait_pll_lock(struct cs2000_priv *priv)
@@ -153,7 +186,10 @@ static int cs2000_wait_pll_lock(struct cs2000_priv *priv)
 static int cs2000_clk_out_enable(struct cs2000_priv *priv, bool enable)
 {
        /* enable both AUX_OUT, CLK_OUT */
-       return cs2000_write(priv, DEVICE_CTRL, enable ? 0 : 0x3);
+       return cs2000_bset(priv, DEVICE_CTRL,
+                          (AUXOUTDIS | CLKOUTDIS),
+                          enable ? 0 :
+                          (AUXOUTDIS | CLKOUTDIS));
 }
 
 static u32 cs2000_rate_to_ratio(u32 rate_in, u32 rate_out)
@@ -243,7 +279,9 @@ static int cs2000_ratio_select(struct cs2000_priv *priv, int ch)
        if (ret < 0)
                return ret;
 
-       ret = cs2000_write(priv, DEVICE_CFG2, 0x0);
+       ret = cs2000_bset(priv, DEVICE_CFG2,
+                         (AUTORMOD | LOCKCLK_MASK | FRACNSRC_MASK),
+                         (LOCKCLK(ch) | FRACNSRC_STATIC));
        if (ret < 0)
                return ret;
 
@@ -351,8 +389,7 @@ static const struct clk_ops cs2000_ops = {
 
 static int cs2000_clk_get(struct cs2000_priv *priv)
 {
-       struct i2c_client *client = priv_to_client(priv);
-       struct device *dev = &client->dev;
+       struct device *dev = priv_to_dev(priv);
        struct clk *clk_in, *ref_clk;
 
        clk_in = devm_clk_get(dev, "clk_in");
@@ -420,8 +457,7 @@ static int cs2000_clk_register(struct cs2000_priv *priv)
 
 static int cs2000_version_print(struct cs2000_priv *priv)
 {
-       struct i2c_client *client = priv_to_client(priv);
-       struct device *dev = &client->dev;
+       struct device *dev = priv_to_dev(priv);
        s32 val;
        const char *revision;
 
@@ -452,7 +488,7 @@ static int cs2000_version_print(struct cs2000_priv *priv)
 static int cs2000_remove(struct i2c_client *client)
 {
        struct cs2000_priv *priv = i2c_get_clientdata(client);
-       struct device *dev = &client->dev;
+       struct device *dev = priv_to_dev(priv);
        struct device_node *np = dev->of_node;
 
        of_clk_del_provider(np);
diff --git a/drivers/clk/clk-hi655x.c b/drivers/clk/clk-hi655x.c
new file mode 100644 (file)
index 0000000..403a018
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Clock driver for Hi655x
+ *
+ * Copyright (c) 2017, Linaro Ltd.
+ *
+ * Author: Daniel Lezcano <daniel.lezcano@linaro.org>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/hi655x-pmic.h>
+
+#define HI655X_CLK_BASE        HI655X_BUS_ADDR(0x1c)
+#define HI655X_CLK_SET BIT(6)
+
+struct hi655x_clk {
+       struct hi655x_pmic *hi655x;
+       struct clk_hw       clk_hw;
+};
+
+static unsigned long hi655x_clk_recalc_rate(struct clk_hw *hw,
+                                           unsigned long parent_rate)
+{
+       return 32768;
+}
+
+static int hi655x_clk_enable(struct clk_hw *hw, bool enable)
+{
+       struct hi655x_clk *hi655x_clk =
+               container_of(hw, struct hi655x_clk, clk_hw);
+
+       struct hi655x_pmic *hi655x = hi655x_clk->hi655x;
+
+       return regmap_update_bits(hi655x->regmap, HI655X_CLK_BASE,
+                                 HI655X_CLK_SET, enable ? HI655X_CLK_SET : 0);
+}
+
+static int hi655x_clk_prepare(struct clk_hw *hw)
+{
+       return hi655x_clk_enable(hw, true);
+}
+
+static void hi655x_clk_unprepare(struct clk_hw *hw)
+{
+       hi655x_clk_enable(hw, false);
+}
+
+static int hi655x_clk_is_prepared(struct clk_hw *hw)
+{
+       struct hi655x_clk *hi655x_clk =
+               container_of(hw, struct hi655x_clk, clk_hw);
+       struct hi655x_pmic *hi655x = hi655x_clk->hi655x;
+       int ret;
+       uint32_t val;
+
+       ret = regmap_read(hi655x->regmap, HI655X_CLK_BASE, &val);
+       if (ret < 0)
+               return ret;
+
+       return val & HI655X_CLK_BASE;
+}
+
+static const struct clk_ops hi655x_clk_ops = {
+       .prepare     = hi655x_clk_prepare,
+       .unprepare   = hi655x_clk_unprepare,
+       .is_prepared = hi655x_clk_is_prepared,
+       .recalc_rate = hi655x_clk_recalc_rate,
+};
+
+static int hi655x_clk_probe(struct platform_device *pdev)
+{
+       struct device *parent = pdev->dev.parent;
+       struct hi655x_pmic *hi655x = dev_get_drvdata(parent);
+       struct hi655x_clk *hi655x_clk;
+       const char *clk_name = "hi655x-clk";
+       struct clk_init_data init = {
+               .name = clk_name,
+               .ops = &hi655x_clk_ops
+       };
+       int ret;
+
+       hi655x_clk = devm_kzalloc(&pdev->dev, sizeof(*hi655x_clk), GFP_KERNEL);
+       if (!hi655x_clk)
+               return -ENOMEM;
+
+       of_property_read_string_index(parent->of_node, "clock-output-names",
+                                     0, &clk_name);
+
+       hi655x_clk->clk_hw.init = &init;
+       hi655x_clk->hi655x      = hi655x;
+
+       platform_set_drvdata(pdev, hi655x_clk);
+
+       ret = devm_clk_hw_register(&pdev->dev, &hi655x_clk->clk_hw);
+       if (ret)
+               return ret;
+
+       return of_clk_add_hw_provider(parent->of_node, of_clk_hw_simple_get,
+                                    &hi655x_clk->clk_hw);
+}
+
+static struct platform_driver hi655x_clk_driver = {
+       .probe =  hi655x_clk_probe,
+       .driver         = {
+               .name   = "hi655x-clk",
+       },
+};
+
+module_platform_driver(hi655x_clk_driver);
+
+MODULE_DESCRIPTION("Clk driver for the hi655x series PMICs");
+MODULE_AUTHOR("Daniel Lezcano <daniel.lezcano@linaro.org>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:hi655x-clk");
index 71677eb125656420482f9b6405fa3765d0c5bb80..13ad6d1e509082f12b0466acb127c3cffc858cba 100644 (file)
@@ -267,10 +267,8 @@ pll_clk_register(struct device *dev, const char *name,
        }
 
        pll = kzalloc(sizeof(*pll), GFP_KERNEL);
-       if (!pll) {
-               pr_err("%s: could not allocate PLL clk\n", __func__);
+       if (!pll)
                return ERR_PTR(-ENOMEM);
-       }
 
        init.name = name;
        init.ops = &pll_clk_ops;
@@ -356,11 +354,9 @@ src_clk_register(struct device *dev, const char *name,
        struct clk_init_data init;
 
        sclk = kzalloc(sizeof(*sclk), GFP_KERNEL);
-       if (!sclk) {
-               pr_err("could not allocate SRC clock %s\n",
-                       name);
+       if (!sclk)
                return ERR_PTR(-ENOMEM);
-       }
+
        init.name = name;
        init.ops = &src_clk_ops;
        /* Do not force-disable the static SDRAM controller */
@@ -467,7 +463,7 @@ static int nomadik_src_clk_show(struct seq_file *s, void *what)
        u32 src_pckensr0 = readl(src_base + SRC_PCKENSR0);
        u32 src_pckensr1 = readl(src_base + SRC_PCKENSR1);
 
-       seq_printf(s, "Clock:      Boot:   Now:    Request: ASKED:\n");
+       seq_puts(s, "Clock:      Boot:   Now:    Request: ASKED:\n");
        for (i = 0; i < ARRAY_SIZE(src_clk_names); i++) {
                u32 pcksrb = (i < 0x20) ? src_pcksr0_boot : src_pcksr1_boot;
                u32 pcksr = (i < 0x20) ? src_pcksr0 : src_pcksr1;
index b051db43fae1995f536bbf732b3a1729a6d214b0..2492442eea77aa0c5abcf540e9bedb81e36d62d3 100644 (file)
@@ -1354,10 +1354,8 @@ static int si5351_i2c_probe(struct i2c_client *client,
                return -EINVAL;
 
        drvdata = devm_kzalloc(&client->dev, sizeof(*drvdata), GFP_KERNEL);
-       if (drvdata == NULL) {
-               dev_err(&client->dev, "unable to allocate driver data\n");
+       if (!drvdata)
                return -ENOMEM;
-       }
 
        i2c_set_clientdata(client, drvdata);
        drvdata->client = client;
@@ -1535,9 +1533,9 @@ static int si5351_i2c_probe(struct i2c_client *client,
        else
                parent_names[1] = si5351_pll_names[1];
 
-       drvdata->msynth = devm_kzalloc(&client->dev, num_clocks *
+       drvdata->msynth = devm_kcalloc(&client->dev, num_clocks,
                                       sizeof(*drvdata->msynth), GFP_KERNEL);
-       drvdata->clkout = devm_kzalloc(&client->dev, num_clocks *
+       drvdata->clkout = devm_kcalloc(&client->dev, num_clocks,
                                       sizeof(*drvdata->clkout), GFP_KERNEL);
        drvdata->num_clkout = num_clocks;
 
index cf9449b3dbd9742bd8a3559c9939af9e057d9b5f..68e2a4e499f1d31ec490b29cb08eb16dcbf6d418 100644 (file)
@@ -531,19 +531,26 @@ static int stm32f4_pll_is_enabled(struct clk_hw *hw)
        return clk_gate_ops.is_enabled(hw);
 }
 
+#define PLL_TIMEOUT 10000
+
 static int stm32f4_pll_enable(struct clk_hw *hw)
 {
        struct clk_gate *gate = to_clk_gate(hw);
        struct stm32f4_pll *pll = to_stm32f4_pll(gate);
-       int ret = 0;
-       unsigned long reg;
+       int bit_status;
+       unsigned int timeout = PLL_TIMEOUT;
 
-       ret = clk_gate_ops.enable(hw);
+       if (clk_gate_ops.is_enabled(hw))
+               return 0;
+
+       clk_gate_ops.enable(hw);
 
-       ret = readl_relaxed_poll_timeout_atomic(base + STM32F4_RCC_CR, reg,
-                       reg & (1 << pll->bit_rdy_idx), 0, 10000);
+       do {
+               bit_status = !(readl(gate->reg) & BIT(pll->bit_rdy_idx));
 
-       return ret;
+       } while (bit_status && --timeout);
+
+       return bit_status;
 }
 
 static void stm32f4_pll_disable(struct clk_hw *hw)
@@ -834,24 +841,32 @@ struct stm32_rgate {
        u8      bit_rdy_idx;
 };
 
-#define RTC_TIMEOUT 1000000
+#define RGATE_TIMEOUT 50000
 
 static int rgclk_enable(struct clk_hw *hw)
 {
        struct clk_gate *gate = to_clk_gate(hw);
        struct stm32_rgate *rgate = to_rgclk(gate);
-       u32 reg;
-       int ret;
+       int bit_status;
+       unsigned int timeout = RGATE_TIMEOUT;
+
+       if (clk_gate_ops.is_enabled(hw))
+               return 0;
 
        disable_power_domain_write_protection();
 
        clk_gate_ops.enable(hw);
 
-       ret = readl_relaxed_poll_timeout_atomic(gate->reg, reg,
-                       reg & rgate->bit_rdy_idx, 1000, RTC_TIMEOUT);
+       do {
+               bit_status = !(readl(gate->reg) & BIT(rgate->bit_rdy_idx));
+               if (bit_status)
+                       udelay(100);
+
+       } while (bit_status && --timeout);
 
        enable_power_domain_write_protection();
-       return ret;
+
+       return bit_status;
 }
 
 static void rgclk_disable(struct clk_hw *hw)
@@ -1533,7 +1548,7 @@ static void __init stm32f4_rcc_init(struct device_node *np)
        }
 
        clks[CLK_LSI] = clk_register_rgate(NULL, "lsi", "clk-lsi", 0,
-                       base + STM32F4_RCC_CSR, 0, 2, 0, &stm32f4_clk_lock);
+                       base + STM32F4_RCC_CSR, 0, 1, 0, &stm32f4_clk_lock);
 
        if (IS_ERR(clks[CLK_LSI])) {
                pr_err("Unable to register lsi clock\n");
@@ -1541,7 +1556,7 @@ static void __init stm32f4_rcc_init(struct device_node *np)
        }
 
        clks[CLK_LSE] = clk_register_rgate(NULL, "lse", "clk-lse", 0,
-                       base + STM32F4_RCC_BDCR, 0, 2, 0, &stm32f4_clk_lock);
+                       base + STM32F4_RCC_BDCR, 0, 1, 0, &stm32f4_clk_lock);
 
        if (IS_ERR(clks[CLK_LSE])) {
                pr_err("Unable to register lse clock\n");
index 56741f3cf0a3bcad8c1e190d45ef90dc786de43e..ea7d552a2f2b11be9429574597ea3d7cf76249b0 100644 (file)
 #define VC5_MUX_IN_XIN         BIT(0)
 #define VC5_MUX_IN_CLKIN       BIT(1)
 
+/* Maximum number of clk_out supported by this driver */
+#define VC5_MAX_CLK_OUT_NUM    5
+
+/* Maximum number of FODs supported by this driver */
+#define VC5_MAX_FOD_NUM        4
+
+/* flags to describe chip features */
+/* chip has built-in oscilator */
+#define VC5_HAS_INTERNAL_XTAL  BIT(0)
+
 /* Supported IDT VC5 models. */
 enum vc5_model {
        IDT_VC5_5P49V5923,
        IDT_VC5_5P49V5933,
+       IDT_VC5_5P49V5935,
+};
+
+/* Structure to describe features of a particular VC5 model */
+struct vc5_chip_info {
+       const enum vc5_model    model;
+       const unsigned int      clk_fod_cnt;
+       const unsigned int      clk_out_cnt;
+       const u32               flags;
 };
 
 struct vc5_driver_data;
@@ -132,15 +151,15 @@ struct vc5_hw_data {
 struct vc5_driver_data {
        struct i2c_client       *client;
        struct regmap           *regmap;
-       enum vc5_model          model;
+       const struct vc5_chip_info      *chip_info;
 
        struct clk              *pin_xin;
        struct clk              *pin_clkin;
        unsigned char           clk_mux_ins;
        struct clk_hw           clk_mux;
        struct vc5_hw_data      clk_pll;
-       struct vc5_hw_data      clk_fod[2];
-       struct vc5_hw_data      clk_out[3];
+       struct vc5_hw_data      clk_fod[VC5_MAX_FOD_NUM];
+       struct vc5_hw_data      clk_out[VC5_MAX_CLK_OUT_NUM];
 };
 
 static const char * const vc5_mux_names[] = {
@@ -563,7 +582,7 @@ static struct clk_hw *vc5_of_clk_get(struct of_phandle_args *clkspec,
        struct vc5_driver_data *vc5 = data;
        unsigned int idx = clkspec->args[0];
 
-       if (idx > 2)
+       if (idx >= vc5->chip_info->clk_out_cnt)
                return ERR_PTR(-EINVAL);
 
        return &vc5->clk_out[idx].hw;
@@ -576,6 +595,7 @@ static int vc5_map_index_to_output(const enum vc5_model model,
        case IDT_VC5_5P49V5933:
                return (n == 0) ? 0 : 3;
        case IDT_VC5_5P49V5923:
+       case IDT_VC5_5P49V5935:
        default:
                return n;
        }
@@ -586,12 +606,10 @@ static const struct of_device_id clk_vc5_of_match[];
 static int vc5_probe(struct i2c_client *client,
                     const struct i2c_device_id *id)
 {
-       const struct of_device_id *of_id =
-               of_match_device(clk_vc5_of_match, &client->dev);
        struct vc5_driver_data *vc5;
        struct clk_init_data init;
        const char *parent_names[2];
-       unsigned int n, idx;
+       unsigned int n, idx = 0;
        int ret;
 
        vc5 = devm_kzalloc(&client->dev, sizeof(*vc5), GFP_KERNEL);
@@ -600,7 +618,7 @@ static int vc5_probe(struct i2c_client *client,
 
        i2c_set_clientdata(client, vc5);
        vc5->client = client;
-       vc5->model = (enum vc5_model)of_id->data;
+       vc5->chip_info = of_device_get_match_data(&client->dev);
 
        vc5->pin_xin = devm_clk_get(&client->dev, "xin");
        if (PTR_ERR(vc5->pin_xin) == -EPROBE_DEFER)
@@ -622,8 +640,7 @@ static int vc5_probe(struct i2c_client *client,
        if (!IS_ERR(vc5->pin_xin)) {
                vc5->clk_mux_ins |= VC5_MUX_IN_XIN;
                parent_names[init.num_parents++] = __clk_get_name(vc5->pin_xin);
-       } else if (vc5->model == IDT_VC5_5P49V5933) {
-               /* IDT VC5 5P49V5933 has built-in oscilator. */
+       } else if (vc5->chip_info->flags & VC5_HAS_INTERNAL_XTAL) {
                vc5->pin_xin = clk_register_fixed_rate(&client->dev,
                                                       "internal-xtal", NULL,
                                                       0, 25000000);
@@ -672,8 +689,8 @@ static int vc5_probe(struct i2c_client *client,
        }
 
        /* Register FODs */
-       for (n = 0; n < 2; n++) {
-               idx = vc5_map_index_to_output(vc5->model, n);
+       for (n = 0; n < vc5->chip_info->clk_fod_cnt; n++) {
+               idx = vc5_map_index_to_output(vc5->chip_info->model, n);
                memset(&init, 0, sizeof(init));
                init.name = vc5_fod_names[idx];
                init.ops = &vc5_fod_ops;
@@ -709,8 +726,8 @@ static int vc5_probe(struct i2c_client *client,
        }
 
        /* Register FOD-connected OUTx outputs */
-       for (n = 1; n < 3; n++) {
-               idx = vc5_map_index_to_output(vc5->model, n - 1);
+       for (n = 1; n < vc5->chip_info->clk_out_cnt; n++) {
+               idx = vc5_map_index_to_output(vc5->chip_info->model, n - 1);
                parent_names[0] = vc5_fod_names[idx];
                if (n == 1)
                        parent_names[1] = vc5_mux_names[0];
@@ -744,7 +761,7 @@ static int vc5_probe(struct i2c_client *client,
        return 0;
 
 err_clk:
-       if (vc5->model == IDT_VC5_5P49V5933)
+       if (vc5->chip_info->flags & VC5_HAS_INTERNAL_XTAL)
                clk_unregister_fixed_rate(vc5->pin_xin);
        return ret;
 }
@@ -755,22 +772,45 @@ static int vc5_remove(struct i2c_client *client)
 
        of_clk_del_provider(client->dev.of_node);
 
-       if (vc5->model == IDT_VC5_5P49V5933)
+       if (vc5->chip_info->flags & VC5_HAS_INTERNAL_XTAL)
                clk_unregister_fixed_rate(vc5->pin_xin);
 
        return 0;
 }
 
+static const struct vc5_chip_info idt_5p49v5923_info = {
+       .model = IDT_VC5_5P49V5923,
+       .clk_fod_cnt = 2,
+       .clk_out_cnt = 3,
+       .flags = 0,
+};
+
+static const struct vc5_chip_info idt_5p49v5933_info = {
+       .model = IDT_VC5_5P49V5933,
+       .clk_fod_cnt = 2,
+       .clk_out_cnt = 3,
+       .flags = VC5_HAS_INTERNAL_XTAL,
+};
+
+static const struct vc5_chip_info idt_5p49v5935_info = {
+       .model = IDT_VC5_5P49V5935,
+       .clk_fod_cnt = 4,
+       .clk_out_cnt = 5,
+       .flags = VC5_HAS_INTERNAL_XTAL,
+};
+
 static const struct i2c_device_id vc5_id[] = {
        { "5p49v5923", .driver_data = IDT_VC5_5P49V5923 },
        { "5p49v5933", .driver_data = IDT_VC5_5P49V5933 },
+       { "5p49v5935", .driver_data = IDT_VC5_5P49V5935 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, vc5_id);
 
 static const struct of_device_id clk_vc5_of_match[] = {
-       { .compatible = "idt,5p49v5923", .data = (void *)IDT_VC5_5P49V5923 },
-       { .compatible = "idt,5p49v5933", .data = (void *)IDT_VC5_5P49V5933 },
+       { .compatible = "idt,5p49v5923", .data = &idt_5p49v5923_info },
+       { .compatible = "idt,5p49v5933", .data = &idt_5p49v5933_info },
+       { .compatible = "idt,5p49v5935", .data = &idt_5p49v5935_info },
        { },
 };
 MODULE_DEVICE_TABLE(of, clk_vc5_of_match);
index 67201f67a14af7b07aec557308a7fb39d1432157..fc58c52a26b4d1de4802be06950f45469d5b807d 100644 (file)
@@ -966,6 +966,8 @@ static int __clk_notify(struct clk_core *core, unsigned long msg,
                        cnd.clk = cn->clk;
                        ret = srcu_notifier_call_chain(&cn->notifier_head, msg,
                                        &cnd);
+                       if (ret & NOTIFY_STOP_MASK)
+                               return ret;
                }
        }
 
@@ -2081,11 +2083,11 @@ static void clk_dump_subtree(struct seq_file *s, struct clk_core *c, int level)
        clk_dump_one(s, c, level);
 
        hlist_for_each_entry(child, &c->children, child_node) {
-               seq_printf(s, ",");
+               seq_putc(s, ',');
                clk_dump_subtree(s, child, level + 1);
        }
 
-       seq_printf(s, "}");
+       seq_putc(s, '}');
 }
 
 static int clk_dump(struct seq_file *s, void *data)
@@ -2094,14 +2096,13 @@ static int clk_dump(struct seq_file *s, void *data)
        bool first_node = true;
        struct hlist_head **lists = (struct hlist_head **)s->private;
 
-       seq_printf(s, "{");
-
+       seq_putc(s, '{');
        clk_prepare_lock();
 
        for (; *lists; lists++) {
                hlist_for_each_entry(c, *lists, child_node) {
                        if (!first_node)
-                               seq_puts(s, ",");
+                               seq_putc(s, ',');
                        first_node = false;
                        clk_dump_subtree(s, c, 0);
                }
@@ -2126,6 +2127,31 @@ static const struct file_operations clk_dump_fops = {
        .release        = single_release,
 };
 
+static int possible_parents_dump(struct seq_file *s, void *data)
+{
+       struct clk_core *core = s->private;
+       int i;
+
+       for (i = 0; i < core->num_parents - 1; i++)
+               seq_printf(s, "%s ", core->parent_names[i]);
+
+       seq_printf(s, "%s\n", core->parent_names[i]);
+
+       return 0;
+}
+
+static int possible_parents_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, possible_parents_dump, inode->i_private);
+}
+
+static const struct file_operations possible_parents_fops = {
+       .open           = possible_parents_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
 static int clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
 {
        struct dentry *d;
@@ -2177,6 +2203,13 @@ static int clk_debug_create_one(struct clk_core *core, struct dentry *pdentry)
        if (!d)
                goto err_out;
 
+       if (core->num_parents > 1) {
+               d = debugfs_create_file("clk_possible_parents", S_IRUGO,
+                               core->dentry, core, &possible_parents_fops);
+               if (!d)
+                       goto err_out;
+       }
+
        if (core->ops->debug_init) {
                ret = core->ops->debug_init(core->hw, core->dentry);
                if (ret)
@@ -2940,7 +2973,7 @@ int clk_notifier_register(struct clk *clk, struct notifier_block *nb)
 
        /* if clk wasn't in the notifier list, allocate new clk_notifier */
        if (cn->clk != clk) {
-               cn = kzalloc(sizeof(struct clk_notifier), GFP_KERNEL);
+               cn = kzalloc(sizeof(*cn), GFP_KERNEL);
                if (!cn)
                        goto out;
 
@@ -3088,7 +3121,7 @@ int of_clk_add_provider(struct device_node *np,
        struct of_clk_provider *cp;
        int ret;
 
-       cp = kzalloc(sizeof(struct of_clk_provider), GFP_KERNEL);
+       cp = kzalloc(sizeof(*cp), GFP_KERNEL);
        if (!cp)
                return -ENOMEM;
 
index d04a104ce1b4d2aa4409fcc217f3905c9d66e41f..fa0fba653898b462e6615549b1bd2e94553fffea 100644 (file)
@@ -144,7 +144,7 @@ static struct hisi_divider_clock hi3620_div_clks[] __initdata = {
        { HI3620_MMC3_DIV,     "mmc3_div",   "mmc3_mux",  0, 0x140, 5, 4, CLK_DIVIDER_HIWORD_MASK, NULL, },
 };
 
-static struct hisi_gate_clock hi3620_seperated_gate_clks[] __initdata = {
+static struct hisi_gate_clock hi3620_separated_gate_clks[] __initdata = {
        { HI3620_TIMERCLK01,   "timerclk01",   "timer_rclk01", CLK_SET_RATE_PARENT, 0x20, 0, 0, },
        { HI3620_TIMER_RCLK01, "timer_rclk01", "rclk_tcxo",    CLK_SET_RATE_PARENT, 0x20, 1, 0, },
        { HI3620_TIMERCLK23,   "timerclk23",   "timer_rclk23", CLK_SET_RATE_PARENT, 0x20, 2, 0, },
@@ -224,8 +224,8 @@ static void __init hi3620_clk_init(struct device_node *np)
                              clk_data);
        hisi_clk_register_divider(hi3620_div_clks, ARRAY_SIZE(hi3620_div_clks),
                                  clk_data);
-       hisi_clk_register_gate_sep(hi3620_seperated_gate_clks,
-                                  ARRAY_SIZE(hi3620_seperated_gate_clks),
+       hisi_clk_register_gate_sep(hi3620_separated_gate_clks,
+                                  ARRAY_SIZE(hi3620_separated_gate_clks),
                                   clk_data);
 }
 CLK_OF_DECLARE(hi3620_clk, "hisilicon,hi3620-clock", hi3620_clk_init);
@@ -430,10 +430,8 @@ static struct clk *hisi_register_clk_mmc(struct hisi_mmc_clock *mmc_clk,
        struct clk_init_data init;
 
        mclk = kzalloc(sizeof(*mclk), GFP_KERNEL);
-       if (!mclk) {
-               pr_err("%s: fail to allocate mmc clk\n", __func__);
+       if (!mclk)
                return ERR_PTR(-ENOMEM);
-       }
 
        init.name = mmc_clk->name;
        init.ops = &clk_mmc_ops;
@@ -482,11 +480,9 @@ static void __init hi3620_mmc_clk_init(struct device_node *node)
        if (WARN_ON(!clk_data))
                return;
 
-       clk_data->clks = kzalloc(sizeof(struct clk *) * num, GFP_KERNEL);
-       if (!clk_data->clks) {
-               pr_err("%s: fail to allocate mmc clk\n", __func__);
+       clk_data->clks = kcalloc(num, sizeof(*clk_data->clks), GFP_KERNEL);
+       if (!clk_data->clks)
                return;
-       }
 
        for (i = 0; i < num; i++) {
                struct hisi_mmc_clock *mmc_clk = &hi3620_mmc_clks[i];
index c0e8e1f196aae4f15c39bf39a725db8fd192f101..2ae151ce623a9602f389c09a6817eb5698c3a32e 100644 (file)
@@ -134,6 +134,7 @@ static struct hisi_gate_clock hi6220_separated_gate_clks_sys[] __initdata = {
        { HI6220_UART4_PCLK,    "uart4_pclk",    "uart4_src",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 8,  0, },
        { HI6220_SPI_CLK,       "spi_clk",       "clk_150m",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 9,  0, },
        { HI6220_TSENSOR_CLK,   "tsensor_clk",   "clk_bus",        CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x230, 12, 0, },
+       { HI6220_DAPB_CLK,      "dapb_clk",      "cs_dapb",        CLK_SET_RATE_PARENT|CLK_IS_CRITICAL,   0x230, 18, 0, },
        { HI6220_MMU_CLK,       "mmu_clk",       "ddrc_axi1",      CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x240, 11, 0, },
        { HI6220_HIFI_SEL,      "hifi_sel",      "hifi_src",       CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 0,  0, },
        { HI6220_MMC0_SYSPLL,   "mmc0_syspll",   "syspll",         CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x270, 1,  0, },
index 9ba2d91f4d3a0d7e37660c866f49c753be0c3e7f..b73c1dfae7f1ea0787ea7a23e64d895569458d2c 100644 (file)
@@ -54,8 +54,9 @@ struct hisi_clock_data *hisi_clk_alloc(struct platform_device *pdev,
        if (!clk_data->base)
                return NULL;
 
-       clk_table = devm_kmalloc(&pdev->dev, sizeof(struct clk *) * nr_clks,
-                               GFP_KERNEL);
+       clk_table = devm_kmalloc_array(&pdev->dev, nr_clks,
+                                      sizeof(*clk_table),
+                                      GFP_KERNEL);
        if (!clk_table)
                return NULL;
 
@@ -80,17 +81,14 @@ struct hisi_clock_data *hisi_clk_init(struct device_node *np,
        }
 
        clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
-       if (!clk_data) {
-               pr_err("%s: could not allocate clock data\n", __func__);
+       if (!clk_data)
                goto err;
-       }
-       clk_data->base = base;
 
-       clk_table = kzalloc(sizeof(struct clk *) * nr_clks, GFP_KERNEL);
-       if (!clk_table) {
-               pr_err("%s: could not allocate clock lookup table\n", __func__);
+       clk_data->base = base;
+       clk_table = kcalloc(nr_clks, sizeof(*clk_table), GFP_KERNEL);
+       if (!clk_table)
                goto err_data;
-       }
+
        clk_data->clk_data.clks = clk_table;
        clk_data->clk_data.clk_num = nr_clks;
        of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data->clk_data);
index 75c35fb12b608781e04a7a54c630b3509f68aecb..b4e0dff3c8c26b9c2a7eac10702b222e486bad96 100644 (file)
@@ -73,7 +73,7 @@ static struct clk *clks[IMX6UL_CLK_END];
 static struct clk_onecell_data clk_data;
 
 static int const clks_init_on[] __initconst = {
-       IMX6UL_CLK_AIPSTZ1, IMX6UL_CLK_AIPSTZ2, IMX6UL_CLK_AIPSTZ3,
+       IMX6UL_CLK_AIPSTZ1, IMX6UL_CLK_AIPSTZ2,
        IMX6UL_CLK_AXI, IMX6UL_CLK_ARM, IMX6UL_CLK_ROM,
        IMX6UL_CLK_MMDC_P0_FAST, IMX6UL_CLK_MMDC_P0_IPG,
 };
@@ -341,9 +341,7 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
        clks[IMX6UL_CLK_GPT2_SERIAL]    = imx_clk_gate2("gpt2_serial",  "perclk",       base + 0x68,    26);
        clks[IMX6UL_CLK_UART2_IPG]      = imx_clk_gate2("uart2_ipg",    "ipg",          base + 0x68,    28);
        clks[IMX6UL_CLK_UART2_SERIAL]   = imx_clk_gate2("uart2_serial", "uart_podf",    base + 0x68,    28);
-       if (clk_on_imx6ul())
-               clks[IMX6UL_CLK_AIPSTZ3]        = imx_clk_gate2("aips_tz3",     "ahb",          base + 0x68,    30);
-       else if (clk_on_imx6ull())
+       if (clk_on_imx6ull())
                clks[IMX6UL_CLK_AIPSTZ3]        = imx_clk_gate2("aips_tz3",     "ahb",           base + 0x80,   18);
 
        /* CCGR1 */
@@ -360,7 +358,7 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
        clks[IMX6UL_CLK_GPT1_BUS]       = imx_clk_gate2("gpt1_bus",     "perclk",       base + 0x6c,    20);
        clks[IMX6UL_CLK_GPT1_SERIAL]    = imx_clk_gate2("gpt1_serial",  "perclk",       base + 0x6c,    22);
        clks[IMX6UL_CLK_UART4_IPG]      = imx_clk_gate2("uart4_ipg",    "ipg",          base + 0x6c,    24);
-       clks[IMX6UL_CLK_UART4_SERIAL]   = imx_clk_gate2("uart4_serail", "uart_podf",    base + 0x6c,    24);
+       clks[IMX6UL_CLK_UART4_SERIAL]   = imx_clk_gate2("uart4_serial", "uart_podf",    base + 0x6c,    24);
 
        /* CCGR2 */
        if (clk_on_imx6ull()) {
@@ -482,6 +480,9 @@ static void __init imx6ul_clocks_init(struct device_node *ccm_node)
        for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
                clk_prepare_enable(clks[clks_init_on[i]]);
 
+       if (clk_on_imx6ull())
+               clk_prepare_enable(clks[IMX6UL_CLK_AIPSTZ3]);
+
        if (IS_ENABLED(CONFIG_USB_MXS_PHY)) {
                clk_prepare_enable(clks[IMX6UL_CLK_USBPHY1_GATE]);
                clk_prepare_enable(clks[IMX6UL_CLK_USBPHY2_GATE]);
index ae1d31be906e4d5a169500f91b9fdca5b29b6ac2..93b03640da9bef56d02dd513bf3d203e1eebd845 100644 (file)
@@ -386,7 +386,7 @@ static int const clks_init_on[] __initconst = {
        IMX7D_PLL_SYS_MAIN_480M_CLK, IMX7D_NAND_USDHC_BUS_ROOT_CLK,
        IMX7D_DRAM_PHYM_ROOT_CLK, IMX7D_DRAM_ROOT_CLK,
        IMX7D_DRAM_PHYM_ALT_ROOT_CLK, IMX7D_DRAM_ALT_ROOT_CLK,
-       IMX7D_AHB_CHANNEL_ROOT_CLK,
+       IMX7D_AHB_CHANNEL_ROOT_CLK, IMX7D_IPG_ROOT_CLK,
 };
 
 static struct clk_onecell_data clk_data;
@@ -724,8 +724,9 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
        clks[IMX7D_MAIN_AXI_ROOT_DIV] = imx_clk_divider2("axi_post_div", "axi_pre_div", base + 0x8800, 0, 6);
        clks[IMX7D_DISP_AXI_ROOT_DIV] = imx_clk_divider2("disp_axi_post_div", "disp_axi_pre_div", base + 0x8880, 0, 6);
        clks[IMX7D_ENET_AXI_ROOT_DIV] = imx_clk_divider2("enet_axi_post_div", "enet_axi_pre_div", base + 0x8900, 0, 6);
-       clks[IMX7D_NAND_USDHC_BUS_ROOT_DIV] = imx_clk_divider2("nand_usdhc_post_div", "nand_usdhc_pre_div", base + 0x8980, 0, 6);
-       clks[IMX7D_AHB_CHANNEL_ROOT_DIV] = imx_clk_divider2("ahb_post_div", "ahb_pre_div", base + 0x9000, 0, 6);
+       clks[IMX7D_NAND_USDHC_BUS_ROOT_CLK] = imx_clk_divider2("nand_usdhc_root_clk", "nand_usdhc_pre_div", base + 0x8980, 0, 6);
+       clks[IMX7D_AHB_CHANNEL_ROOT_DIV] = imx_clk_divider2("ahb_root_clk", "ahb_pre_div", base + 0x9000, 0, 6);
+       clks[IMX7D_IPG_ROOT_CLK] = imx_clk_divider2("ipg_root_clk", "ahb_root_clk", base + 0x9080, 0, 2);
        clks[IMX7D_DRAM_ROOT_DIV] = imx_clk_divider2("dram_post_div", "dram_cg", base + 0x9880, 0, 3);
        clks[IMX7D_DRAM_PHYM_ALT_ROOT_DIV] = imx_clk_divider2("dram_phym_alt_post_div", "dram_phym_alt_pre_div", base + 0xa000, 0, 3);
        clks[IMX7D_DRAM_ALT_ROOT_DIV] = imx_clk_divider2("dram_alt_post_div", "dram_alt_pre_div", base + 0xa080, 0, 3);
@@ -796,9 +797,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
        clks[IMX7D_DISP_AXI_ROOT_CLK] = imx_clk_gate4("disp_axi_root_clk", "disp_axi_post_div", base + 0x4050, 0);
        clks[IMX7D_ENET_AXI_ROOT_CLK] = imx_clk_gate4("enet_axi_root_clk", "enet_axi_post_div", base + 0x4060, 0);
        clks[IMX7D_OCRAM_CLK] = imx_clk_gate4("ocram_clk", "axi_post_div", base + 0x4110, 0);
-       clks[IMX7D_OCRAM_S_CLK] = imx_clk_gate4("ocram_s_clk", "ahb_post_div", base + 0x4120, 0);
-       clks[IMX7D_NAND_USDHC_BUS_ROOT_CLK] = imx_clk_gate4("nand_usdhc_root_clk", "nand_usdhc_post_div", base + 0x4130, 0);
-       clks[IMX7D_AHB_CHANNEL_ROOT_CLK] = imx_clk_gate4("ahb_root_clk", "ahb_post_div", base + 0x4200, 0);
+       clks[IMX7D_OCRAM_S_CLK] = imx_clk_gate4("ocram_s_clk", "ahb_root_clk", base + 0x4120, 0);
        clks[IMX7D_DRAM_ROOT_CLK] = imx_clk_gate4("dram_root_clk", "dram_post_div", base + 0x4130, 0);
        clks[IMX7D_DRAM_PHYM_ROOT_CLK] = imx_clk_gate4("dram_phym_root_clk", "dram_phym_cg", base + 0x4130, 0);
        clks[IMX7D_DRAM_PHYM_ALT_ROOT_CLK] = imx_clk_gate4("dram_phym_alt_root_clk", "dram_phym_alt_post_div", base + 0x4130, 0);
index a01ef7806aedc2e118c02c548d5d521313e319fb..28739a9a6e37da73a084196e94436e4d4bf95ed4 100644 (file)
@@ -50,6 +50,38 @@ config COMMON_CLK_MT2701_BDPSYS
        ---help---
          This driver supports Mediatek MT2701 bdpsys clocks.
 
+config COMMON_CLK_MT6797
+       bool "Clock driver for Mediatek MT6797"
+       depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
+       select COMMON_CLK_MEDIATEK
+       default ARCH_MEDIATEK && ARM64
+       ---help---
+         This driver supports Mediatek MT6797 basic clocks.
+
+config COMMON_CLK_MT6797_MMSYS
+       bool "Clock driver for Mediatek MT6797 mmsys"
+       depends on COMMON_CLK_MT6797
+       ---help---
+         This driver supports Mediatek MT6797 mmsys clocks.
+
+config COMMON_CLK_MT6797_IMGSYS
+       bool "Clock driver for Mediatek MT6797 imgsys"
+       depends on COMMON_CLK_MT6797
+       ---help---
+         This driver supports Mediatek MT6797 imgsys clocks.
+
+config COMMON_CLK_MT6797_VDECSYS
+       bool "Clock driver for Mediatek MT6797 vdecsys"
+       depends on COMMON_CLK_MT6797
+       ---help---
+         This driver supports Mediatek MT6797 vdecsys clocks.
+
+config COMMON_CLK_MT6797_VENCSYS
+       bool "Clock driver for Mediatek MT6797 vencsys"
+       depends on COMMON_CLK_MT6797
+       ---help---
+         This driver supports Mediatek MT6797 vencsys clocks.
+
 config COMMON_CLK_MT8135
        bool "Clock driver for Mediatek MT8135"
        depends on (ARCH_MEDIATEK && ARM) || COMPILE_TEST
index 19ae7ef79b5722ce4f63ba80832285a196c35231..5c3afb86b9ec6a0f29f443a9bf309f45aadee4b5 100644 (file)
@@ -1,5 +1,10 @@
 obj-$(CONFIG_COMMON_CLK_MEDIATEK) += clk-mtk.o clk-pll.o clk-gate.o clk-apmixed.o
 obj-$(CONFIG_RESET_CONTROLLER) += reset.o
+obj-$(CONFIG_COMMON_CLK_MT6797) += clk-mt6797.o
+obj-$(CONFIG_COMMON_CLK_MT6797_IMGSYS) += clk-mt6797-img.o
+obj-$(CONFIG_COMMON_CLK_MT6797_MMSYS) += clk-mt6797-mm.o
+obj-$(CONFIG_COMMON_CLK_MT6797_VDECSYS) += clk-mt6797-vdec.o
+obj-$(CONFIG_COMMON_CLK_MT6797_VENCSYS) += clk-mt6797-venc.o
 obj-$(CONFIG_COMMON_CLK_MT2701) += clk-mt2701.o
 obj-$(CONFIG_COMMON_CLK_MT2701_BDPSYS) += clk-mt2701-bdp.o
 obj-$(CONFIG_COMMON_CLK_MT2701_ETHSYS) += clk-mt2701-eth.o
index 877be8715afac308634ca500f266e3f56fc61c47..9251a65515221439d4dbfb92cdf3934aad098104 100644 (file)
@@ -66,6 +66,8 @@ static int clk_mt2701_eth_probe(struct platform_device *pdev)
                        "could not register clock provider: %s: %d\n",
                        pdev->name, r);
 
+       mtk_register_reset_controller(node, 1, 0x34);
+
        return r;
 }
 
diff --git a/drivers/clk/mediatek/clk-mt6797-img.c b/drivers/clk/mediatek/clk-mt6797-img.c
new file mode 100644 (file)
index 0000000..94cc480
--- /dev/null
@@ -0,0 +1,76 @@
+/* Copyright (c) 2017 MediaTek Inc.
+ * Author: Kevin Chen <kevin-cw.chen@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+#include <dt-bindings/clock/mt6797-clk.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+static const struct mtk_gate_regs img_cg_regs = {
+       .set_ofs = 0x0004,
+       .clr_ofs = 0x0008,
+       .sta_ofs = 0x0000,
+};
+
+#define GATE_IMG(_id, _name, _parent, _shift) {                \
+               .id = _id,                              \
+               .name = _name,                          \
+               .parent_name = _parent,                 \
+               .regs = &img_cg_regs,                   \
+               .shift = _shift,                        \
+               .ops = &mtk_clk_gate_ops_setclr,        \
+       }
+
+static const struct mtk_gate img_clks[] = {
+       GATE_IMG(CLK_IMG_FDVT, "img_fdvt", "mm_sel", 11),
+       GATE_IMG(CLK_IMG_DPE, "img_dpe", "mm_sel", 10),
+       GATE_IMG(CLK_IMG_DIP, "img_dip", "mm_sel", 6),
+       GATE_IMG(CLK_IMG_LARB6, "img_larb6", "mm_sel", 0),
+};
+
+static const struct of_device_id of_match_clk_mt6797_img[] = {
+       { .compatible = "mediatek,mt6797-imgsys", },
+       {}
+};
+
+static int clk_mt6797_img_probe(struct platform_device *pdev)
+{
+       struct clk_onecell_data *clk_data;
+       int r;
+       struct device_node *node = pdev->dev.of_node;
+
+       clk_data = mtk_alloc_clk_data(CLK_IMG_NR);
+
+       mtk_clk_register_gates(node, img_clks, ARRAY_SIZE(img_clks),
+                              clk_data);
+
+       r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+       if (r)
+               dev_err(&pdev->dev,
+                       "could not register clock provider: %s: %d\n",
+                       pdev->name, r);
+
+       return r;
+}
+
+static struct platform_driver clk_mt6797_img_drv = {
+       .probe = clk_mt6797_img_probe,
+       .driver = {
+               .name = "clk-mt6797-img",
+               .of_match_table = of_match_clk_mt6797_img,
+       },
+};
+
+builtin_platform_driver(clk_mt6797_img_drv);
diff --git a/drivers/clk/mediatek/clk-mt6797-mm.c b/drivers/clk/mediatek/clk-mt6797-mm.c
new file mode 100644 (file)
index 0000000..c57d3ee
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2017 MediaTek Inc.
+ * Author: Kevin Chen <kevin-cw.chen@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+#include <dt-bindings/clock/mt6797-clk.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+static const struct mtk_gate_regs mm0_cg_regs = {
+       .set_ofs = 0x0104,
+       .clr_ofs = 0x0108,
+       .sta_ofs = 0x0100,
+};
+
+static const struct mtk_gate_regs mm1_cg_regs = {
+       .set_ofs = 0x0114,
+       .clr_ofs = 0x0118,
+       .sta_ofs = 0x0110,
+};
+
+#define GATE_MM0(_id, _name, _parent, _shift) {                        \
+       .id = _id,                                      \
+       .name = _name,                                  \
+       .parent_name = _parent,                         \
+       .regs = &mm0_cg_regs,                           \
+       .shift = _shift,                                \
+       .ops = &mtk_clk_gate_ops_setclr,                \
+}
+
+#define GATE_MM1(_id, _name, _parent, _shift) {                        \
+       .id = _id,                                      \
+       .name = _name,                                  \
+       .parent_name = _parent,                         \
+       .regs = &mm1_cg_regs,                           \
+       .shift = _shift,                                \
+       .ops = &mtk_clk_gate_ops_setclr,                \
+}
+
+static const struct mtk_gate mm_clks[] = {
+       GATE_MM0(CLK_MM_SMI_COMMON, "mm_smi_common", "mm_sel", 0),
+       GATE_MM0(CLK_MM_SMI_LARB0, "mm_smi_larb0", "mm_sel", 1),
+       GATE_MM0(CLK_MM_SMI_LARB5, "mm_smi_larb5", "mm_sel", 2),
+       GATE_MM0(CLK_MM_CAM_MDP, "mm_cam_mdp", "mm_sel", 3),
+       GATE_MM0(CLK_MM_MDP_RDMA0, "mm_mdp_rdma0", "mm_sel", 4),
+       GATE_MM0(CLK_MM_MDP_RDMA1, "mm_mdp_rdma1", "mm_sel", 5),
+       GATE_MM0(CLK_MM_MDP_RSZ0, "mm_mdp_rsz0", "mm_sel", 6),
+       GATE_MM0(CLK_MM_MDP_RSZ1, "mm_mdp_rsz1", "mm_sel", 7),
+       GATE_MM0(CLK_MM_MDP_RSZ2, "mm_mdp_rsz2", "mm_sel", 8),
+       GATE_MM0(CLK_MM_MDP_TDSHP, "mm_mdp_tdshp", "mm_sel", 9),
+       GATE_MM0(CLK_MM_MDP_COLOR, "mm_mdp_color", "mm_sel", 10),
+       GATE_MM0(CLK_MM_MDP_WDMA, "mm_mdp_wdma", "mm_sel", 11),
+       GATE_MM0(CLK_MM_MDP_WROT0, "mm_mdp_wrot0", "mm_sel", 12),
+       GATE_MM0(CLK_MM_MDP_WROT1, "mm_mdp_wrot1", "mm_sel", 13),
+       GATE_MM0(CLK_MM_FAKE_ENG, "mm_fake_eng", "mm_sel", 14),
+       GATE_MM0(CLK_MM_DISP_OVL0, "mm_disp_ovl0", "mm_sel", 15),
+       GATE_MM0(CLK_MM_DISP_OVL1, "mm_disp_ovl1", "mm_sel", 16),
+       GATE_MM0(CLK_MM_DISP_OVL0_2L, "mm_disp_ovl0_2l", "mm_sel", 17),
+       GATE_MM0(CLK_MM_DISP_OVL1_2L, "mm_disp_ovl1_2l", "mm_sel", 18),
+       GATE_MM0(CLK_MM_DISP_RDMA0, "mm_disp_rdma0", "mm_sel", 19),
+       GATE_MM0(CLK_MM_DISP_RDMA1, "mm_disp_rdma1", "mm_sel", 20),
+       GATE_MM0(CLK_MM_DISP_WDMA0, "mm_disp_wdma0", "mm_sel", 21),
+       GATE_MM0(CLK_MM_DISP_WDMA1, "mm_disp_wdma1", "mm_sel", 22),
+       GATE_MM0(CLK_MM_DISP_COLOR, "mm_disp_color", "mm_sel", 23),
+       GATE_MM0(CLK_MM_DISP_CCORR, "mm_disp_ccorr", "mm_sel", 24),
+       GATE_MM0(CLK_MM_DISP_AAL, "mm_disp_aal", "mm_sel", 25),
+       GATE_MM0(CLK_MM_DISP_GAMMA, "mm_disp_gamma", "mm_sel", 26),
+       GATE_MM0(CLK_MM_DISP_OD, "mm_disp_od", "mm_sel", 27),
+       GATE_MM0(CLK_MM_DISP_DITHER, "mm_disp_dither", "mm_sel", 28),
+       GATE_MM0(CLK_MM_DISP_UFOE, "mm_disp_ufoe", "mm_sel", 29),
+       GATE_MM0(CLK_MM_DISP_DSC, "mm_disp_dsc", "mm_sel", 30),
+       GATE_MM0(CLK_MM_DISP_SPLIT, "mm_disp_split", "mm_sel", 31),
+       GATE_MM1(CLK_MM_DSI0_MM_CLOCK, "mm_dsi0_mm_clock", "mm_sel", 0),
+       GATE_MM1(CLK_MM_DSI1_MM_CLOCK, "mm_dsi1_mm_clock", "mm_sel", 2),
+       GATE_MM1(CLK_MM_DPI_MM_CLOCK, "mm_dpi_mm_clock", "mm_sel", 4),
+       GATE_MM1(CLK_MM_DPI_INTERFACE_CLOCK, "mm_dpi_interface_clock",
+                "dpi0_sel", 5),
+       GATE_MM1(CLK_MM_LARB4_AXI_ASIF_MM_CLOCK, "mm_larb4_axi_asif_mm_clock",
+                "mm_sel", 6),
+       GATE_MM1(CLK_MM_LARB4_AXI_ASIF_MJC_CLOCK, "mm_larb4_axi_asif_mjc_clock",
+                "mjc_sel", 7),
+       GATE_MM1(CLK_MM_DISP_OVL0_MOUT_CLOCK, "mm_disp_ovl0_mout_clock",
+                "mm_sel", 8),
+       GATE_MM1(CLK_MM_FAKE_ENG2, "mm_fake_eng2", "mm_sel", 9),
+       GATE_MM1(CLK_MM_DSI0_INTERFACE_CLOCK, "mm_dsi0_interface_clock",
+                "clk26m", 1),
+       GATE_MM1(CLK_MM_DSI1_INTERFACE_CLOCK, "mm_dsi1_interface_clock",
+                "clk26m", 3),
+};
+
+static const struct of_device_id of_match_clk_mt6797_mm[] = {
+       { .compatible = "mediatek,mt6797-mmsys", },
+       {}
+};
+
+static int clk_mt6797_mm_probe(struct platform_device *pdev)
+{
+       struct clk_onecell_data *clk_data;
+       int r;
+       struct device_node *node = pdev->dev.of_node;
+
+       clk_data = mtk_alloc_clk_data(CLK_MM_NR);
+
+       mtk_clk_register_gates(node, mm_clks, ARRAY_SIZE(mm_clks),
+                              clk_data);
+
+       r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+       if (r)
+               dev_err(&pdev->dev,
+                       "could not register clock provider: %s: %d\n",
+                       pdev->name, r);
+
+       return r;
+}
+
+static struct platform_driver clk_mt6797_mm_drv = {
+       .probe = clk_mt6797_mm_probe,
+       .driver = {
+               .name = "clk-mt6797-mm",
+               .of_match_table = of_match_clk_mt6797_mm,
+       },
+};
+
+builtin_platform_driver(clk_mt6797_mm_drv);
diff --git a/drivers/clk/mediatek/clk-mt6797-vdec.c b/drivers/clk/mediatek/clk-mt6797-vdec.c
new file mode 100644 (file)
index 0000000..7c402ca
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2017 MediaTek Inc.
+ * Author: Kevin-CW Chen <kevin-cw.chen@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt6797-clk.h>
+
+static const struct mtk_gate_regs vdec0_cg_regs = {
+       .set_ofs = 0x0000,
+       .clr_ofs = 0x0004,
+       .sta_ofs = 0x0000,
+};
+
+static const struct mtk_gate_regs vdec1_cg_regs = {
+       .set_ofs = 0x0008,
+       .clr_ofs = 0x000c,
+       .sta_ofs = 0x0008,
+};
+
+#define GATE_VDEC0(_id, _name, _parent, _shift) {              \
+       .id = _id,                                      \
+       .name = _name,                                  \
+       .parent_name = _parent,                         \
+       .regs = &vdec0_cg_regs,                         \
+       .shift = _shift,                                \
+       .ops = &mtk_clk_gate_ops_setclr_inv,            \
+}
+
+#define GATE_VDEC1(_id, _name, _parent, _shift) {              \
+       .id = _id,                                      \
+       .name = _name,                                  \
+       .parent_name = _parent,                         \
+       .regs = &vdec1_cg_regs,                         \
+       .shift = _shift,                                \
+       .ops = &mtk_clk_gate_ops_setclr_inv,            \
+}
+
+static const struct mtk_gate vdec_clks[] = {
+       GATE_VDEC0(CLK_VDEC_CKEN_ENG, "vdec_cken_eng", "vdec_sel", 8),
+       GATE_VDEC0(CLK_VDEC_ACTIVE, "vdec_active", "vdec_sel", 4),
+       GATE_VDEC0(CLK_VDEC_CKEN, "vdec_cken", "vdec_sel", 0),
+       GATE_VDEC1(CLK_VDEC_LARB1_CKEN, "vdec_larb1_cken", "mm_sel", 0),
+};
+
+static const struct of_device_id of_match_clk_mt6797_vdec[] = {
+       { .compatible = "mediatek,mt6797-vdecsys", },
+       {}
+};
+
+static int clk_mt6797_vdec_probe(struct platform_device *pdev)
+{
+       struct clk_onecell_data *clk_data;
+       int r;
+       struct device_node *node = pdev->dev.of_node;
+
+       clk_data = mtk_alloc_clk_data(CLK_VDEC_NR);
+
+       mtk_clk_register_gates(node, vdec_clks, ARRAY_SIZE(vdec_clks),
+                              clk_data);
+
+       r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+       if (r)
+               dev_err(&pdev->dev,
+                       "could not register clock provider: %s: %d\n",
+                       pdev->name, r);
+
+       return r;
+}
+
+static struct platform_driver clk_mt6797_vdec_drv = {
+       .probe = clk_mt6797_vdec_probe,
+       .driver = {
+               .name = "clk-mt6797-vdec",
+               .of_match_table = of_match_clk_mt6797_vdec,
+       },
+};
+
+builtin_platform_driver(clk_mt6797_vdec_drv);
diff --git a/drivers/clk/mediatek/clk-mt6797-venc.c b/drivers/clk/mediatek/clk-mt6797-venc.c
new file mode 100644 (file)
index 0000000..e73d517
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2017 MediaTek Inc.
+ * Author: Kevin Chen <kevin-cw.chen@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt6797-clk.h>
+
+static const struct mtk_gate_regs venc_cg_regs = {
+       .set_ofs = 0x0004,
+       .clr_ofs = 0x0008,
+       .sta_ofs = 0x0000,
+};
+
+#define GATE_VENC(_id, _name, _parent, _shift) {       \
+               .id = _id,                              \
+               .name = _name,                          \
+               .parent_name = _parent,                 \
+               .regs = &venc_cg_regs,                  \
+               .shift = _shift,                        \
+               .ops = &mtk_clk_gate_ops_setclr_inv,    \
+       }
+
+static const struct mtk_gate venc_clks[] = {
+       GATE_VENC(CLK_VENC_0, "venc_0", "mm_sel", 0),
+       GATE_VENC(CLK_VENC_1, "venc_1", "venc_sel", 4),
+       GATE_VENC(CLK_VENC_2, "venc_2", "venc_sel", 8),
+       GATE_VENC(CLK_VENC_3, "venc_3", "venc_sel", 12),
+};
+
+static const struct of_device_id of_match_clk_mt6797_venc[] = {
+       { .compatible = "mediatek,mt6797-vencsys", },
+       {}
+};
+
+static int clk_mt6797_venc_probe(struct platform_device *pdev)
+{
+       struct clk_onecell_data *clk_data;
+       int r;
+       struct device_node *node = pdev->dev.of_node;
+
+       clk_data = mtk_alloc_clk_data(CLK_VENC_NR);
+
+       mtk_clk_register_gates(node, venc_clks, ARRAY_SIZE(venc_clks),
+                              clk_data);
+
+       r = of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+       if (r)
+               dev_err(&pdev->dev,
+                       "could not register clock provider: %s: %d\n",
+                       pdev->name, r);
+
+       return r;
+}
+
+static struct platform_driver clk_mt6797_venc_drv = {
+       .probe = clk_mt6797_venc_probe,
+       .driver = {
+               .name = "clk-mt6797-venc",
+               .of_match_table = of_match_clk_mt6797_venc,
+       },
+};
+
+builtin_platform_driver(clk_mt6797_venc_drv);
diff --git a/drivers/clk/mediatek/clk-mt6797.c b/drivers/clk/mediatek/clk-mt6797.c
new file mode 100644 (file)
index 0000000..5702bc9
--- /dev/null
@@ -0,0 +1,714 @@
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ * Author: Kevin Chen <kevin-cw.chen@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-mtk.h"
+#include "clk-gate.h"
+
+#include <dt-bindings/clock/mt6797-clk.h>
+
+/*
+ * For some clocks, we don't care what their actual rates are. And these
+ * clocks may change their rate on different products or different scenarios.
+ * So we model these clocks' rate as 0, to denote it's not an actual rate.
+ */
+
+static DEFINE_SPINLOCK(mt6797_clk_lock);
+
+static const struct mtk_fixed_factor top_fixed_divs[] = {
+       FACTOR(CLK_TOP_SYSPLL_CK, "syspll_ck", "mainpll", 1, 1),
+       FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll", 1, 2),
+       FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "syspll_d2", 1, 2),
+       FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "syspll_d2", 1, 4),
+       FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "syspll_d2", 1, 8),
+       FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "syspll_d2", 1, 16),
+       FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "mainpll", 1, 3),
+       FACTOR(CLK_TOP_SYSPLL_D3_D3, "syspll_d3_d3", "syspll_d3", 1, 3),
+       FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "syspll_d3", 1, 2),
+       FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "syspll_d3", 1, 4),
+       FACTOR(CLK_TOP_SYSPLL2_D8, "syspll2_d8", "syspll_d3", 1, 8),
+       FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll", 1, 5),
+       FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "syspll_d5", 1, 2),
+       FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "syspll_d5", 1, 4),
+       FACTOR(CLK_TOP_SYSPLL_D7, "syspll_d7", "mainpll", 1, 7),
+       FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "syspll_d7", 1, 2),
+       FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "syspll_d7", 1, 4),
+       FACTOR(CLK_TOP_UNIVPLL_CK, "univpll_ck", "univpll", 1, 1),
+       FACTOR(CLK_TOP_UNIVPLL_D7, "univpll_d7", "univpll", 1, 7),
+       FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univpll", 1, 26),
+       FACTOR(CLK_TOP_SSUSB_PHY_48M_CK, "ssusb_phy_48m_ck", "univpll", 1, 1),
+       FACTOR(CLK_TOP_USB_PHY48M_CK, "usb_phy48m_ck", "univpll", 1, 1),
+       FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2),
+       FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll_d2", 1, 2),
+       FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll_d2", 1, 4),
+       FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll_d2", 1, 8),
+       FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3),
+       FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll", 1, 2),
+       FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll", 1, 4),
+       FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll", 1, 8),
+       FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5),
+       FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univpll_d5", 1, 2),
+       FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univpll_d5", 1, 4),
+       FACTOR(CLK_TOP_UNIVPLL3_D8, "univpll3_d8", "univpll_d5", 1, 8),
+       FACTOR(CLK_TOP_ULPOSC_CK_ORG, "ulposc_ck_org", "ulposc", 1, 1),
+       FACTOR(CLK_TOP_ULPOSC_CK, "ulposc_ck", "ulposc_ck_org", 1, 3),
+       FACTOR(CLK_TOP_ULPOSC_D2, "ulposc_d2", "ulposc_ck", 1, 2),
+       FACTOR(CLK_TOP_ULPOSC_D3, "ulposc_d3", "ulposc_ck", 1, 4),
+       FACTOR(CLK_TOP_ULPOSC_D4, "ulposc_d4", "ulposc_ck", 1, 8),
+       FACTOR(CLK_TOP_ULPOSC_D8, "ulposc_d8", "ulposc_ck", 1, 10),
+       FACTOR(CLK_TOP_ULPOSC_D10, "ulposc_d10", "ulposc_ck_org", 1, 1),
+       FACTOR(CLK_TOP_APLL1_CK, "apll1_ck", "apll1", 1, 1),
+       FACTOR(CLK_TOP_APLL2_CK, "apll2_ck", "apll2", 1, 1),
+       FACTOR(CLK_TOP_MFGPLL_CK, "mfgpll_ck", "mfgpll", 1, 1),
+       FACTOR(CLK_TOP_MFGPLL_D2, "mfgpll_d2", "mfgpll_ck", 1, 2),
+       FACTOR(CLK_TOP_IMGPLL_CK, "imgpll_ck", "imgpll", 1, 1),
+       FACTOR(CLK_TOP_IMGPLL_D2, "imgpll_d2", "imgpll_ck", 1, 2),
+       FACTOR(CLK_TOP_IMGPLL_D4, "imgpll_d4", "imgpll_ck", 1, 4),
+       FACTOR(CLK_TOP_CODECPLL_CK, "codecpll_ck", "codecpll", 1, 1),
+       FACTOR(CLK_TOP_CODECPLL_D2, "codecpll_d2", "codecpll_ck", 1, 2),
+       FACTOR(CLK_TOP_VDECPLL_CK, "vdecpll_ck", "vdecpll", 1, 1),
+       FACTOR(CLK_TOP_TVDPLL_CK, "tvdpll_ck", "tvdpll", 1, 1),
+       FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll_ck", 1, 2),
+       FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll_ck", 1, 4),
+       FACTOR(CLK_TOP_TVDPLL_D8, "tvdpll_d8", "tvdpll_ck", 1, 8),
+       FACTOR(CLK_TOP_TVDPLL_D16, "tvdpll_d16", "tvdpll_ck", 1, 16),
+       FACTOR(CLK_TOP_MSDCPLL_CK, "msdcpll_ck", "msdcpll", 1, 1),
+       FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll_ck", 1, 2),
+       FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll_ck", 1, 4),
+       FACTOR(CLK_TOP_MSDCPLL_D8, "msdcpll_d8", "msdcpll_ck", 1, 8),
+};
+
+static const char * const axi_parents[] = {
+       "clk26m",
+       "syspll_d7",
+       "ulposc_axi_ck_mux",
+};
+
+static const char * const ulposc_axi_ck_mux_parents[] = {
+       "syspll1_d4",
+       "ulposc_axi_ck_mux_pre",
+};
+
+static const char * const ulposc_axi_ck_mux_pre_parents[] = {
+       "ulposc_d2",
+       "ulposc_d3",
+};
+
+static const char * const ddrphycfg_parents[] = {
+       "clk26m",
+       "syspll3_d2",
+       "syspll2_d4",
+       "syspll1_d8",
+};
+
+static const char * const mm_parents[] = {
+       "clk26m",
+       "imgpll_ck",
+       "univpll1_d2",
+       "syspll1_d2",
+};
+
+static const char * const pwm_parents[] = {
+       "clk26m",
+       "univpll2_d4",
+       "ulposc_d2",
+       "ulposc_d3",
+       "ulposc_d8",
+       "ulposc_d10",
+       "ulposc_d4",
+};
+
+static const char * const vdec_parents[] = {
+       "clk26m",
+       "vdecpll_ck",
+       "imgpll_ck",
+       "syspll_d3",
+       "univpll_d5",
+       "clk26m",
+       "clk26m",
+};
+
+static const char * const venc_parents[] = {
+       "clk26m",
+       "codecpll_ck",
+       "syspll_d3",
+};
+
+static const char * const mfg_parents[] = {
+       "clk26m",
+       "mfgpll_ck",
+       "syspll_d3",
+       "univpll_d3",
+};
+
+static const char * const camtg[] = {
+       "clk26m",
+       "univpll_d26",
+       "univpll2_d2",
+};
+
+static const char * const uart_parents[] = {
+       "clk26m",
+       "univpll2_d8",
+};
+
+static const char * const spi_parents[] = {
+       "clk26m",
+       "syspll3_d2",
+       "syspll2_d4",
+       "ulposc_spi_ck_mux",
+};
+
+static const char * const ulposc_spi_ck_mux_parents[] = {
+       "ulposc_d2",
+       "ulposc_d3",
+};
+
+static const char * const usb20_parents[] = {
+       "clk26m",
+       "univpll1_d8",
+       "syspll4_d2",
+};
+
+static const char * const msdc50_0_hclk_parents[] = {
+       "clk26m",
+       "syspll1_d2",
+       "syspll2_d2",
+       "syspll4_d2",
+};
+
+static const char * const msdc50_0_parents[] = {
+       "clk26m",
+       "msdcpll",
+       "syspll_d3",
+       "univpll1_d4",
+       "syspll2_d2",
+       "syspll_d7",
+       "msdcpll_d2",
+       "univpll1_d2",
+       "univpll_d3",
+};
+
+static const char * const msdc30_1_parents[] = {
+       "clk26m",
+       "univpll2_d2",
+       "msdcpll_d2",
+       "univpll1_d4",
+       "syspll2_d2",
+       "syspll_d7",
+       "univpll_d7",
+};
+
+static const char * const msdc30_2_parents[] = {
+       "clk26m",
+       "univpll2_d8",
+       "syspll2_d8",
+       "syspll1_d8",
+       "msdcpll_d8",
+       "syspll3_d4",
+       "univpll_d26",
+};
+
+static const char * const audio_parents[] = {
+       "clk26m",
+       "syspll3_d4",
+       "syspll4_d4",
+       "syspll1_d16",
+};
+
+static const char * const aud_intbus_parents[] = {
+       "clk26m",
+       "syspll1_d4",
+       "syspll4_d2",
+};
+
+static const char * const pmicspi_parents[] = {
+       "clk26m",
+       "univpll_d26",
+       "syspll3_d4",
+       "syspll1_d8",
+       "ulposc_d4",
+       "ulposc_d8",
+       "syspll2_d8",
+};
+
+static const char * const scp_parents[] = {
+       "clk26m",
+       "syspll_d3",
+       "ulposc_ck",
+       "univpll_d5",
+};
+
+static const char * const atb_parents[] = {
+       "clk26m",
+       "syspll1_d2",
+       "syspll_d5",
+};
+
+static const char * const mjc_parents[] = {
+       "clk26m",
+       "imgpll_ck",
+       "univpll_d5",
+       "syspll1_d2",
+};
+
+static const char * const dpi0_parents[] = {
+       "clk26m",
+       "tvdpll_d2",
+       "tvdpll_d4",
+       "tvdpll_d8",
+       "tvdpll_d16",
+       "clk26m",
+       "clk26m",
+};
+
+static const char * const aud_1_parents[] = {
+       "clk26m",
+       "apll1_ck",
+};
+
+static const char * const aud_2_parents[] = {
+       "clk26m",
+       "apll2_ck",
+};
+
+static const char * const ssusb_top_sys_parents[] = {
+       "clk26m",
+       "univpll3_d2",
+};
+
+static const char * const spm_parents[] = {
+       "clk26m",
+       "syspll1_d8",
+};
+
+static const char * const bsi_spi_parents[] = {
+       "clk26m",
+       "syspll_d3_d3",
+       "syspll1_d4",
+       "syspll_d7",
+};
+
+static const char * const audio_h_parents[] = {
+       "clk26m",
+       "apll2_ck",
+       "apll1_ck",
+       "univpll_d7",
+};
+
+static const char * const mfg_52m_parents[] = {
+       "clk26m",
+       "univpll2_d8",
+       "univpll2_d4",
+       "univpll2_d4",
+};
+
+static const char * const anc_md32_parents[] = {
+       "clk26m",
+       "syspll1_d2",
+       "univpll_d5",
+};
+
+static const struct mtk_composite top_muxes[] = {
+       MUX(CLK_TOP_MUX_ULPOSC_AXI_CK_MUX_PRE, "ulposc_axi_ck_mux_pre",
+           ulposc_axi_ck_mux_pre_parents, 0x0040, 3, 1),
+       MUX(CLK_TOP_MUX_ULPOSC_AXI_CK_MUX, "ulposc_axi_ck_mux",
+           ulposc_axi_ck_mux_parents, 0x0040, 2, 1),
+       MUX(CLK_TOP_MUX_AXI, "axi_sel", axi_parents,
+           0x0040, 0, 2),
+       MUX(CLK_TOP_MUX_DDRPHYCFG, "ddrphycfg_sel", ddrphycfg_parents,
+           0x0040, 16, 2),
+       MUX(CLK_TOP_MUX_MM, "mm_sel", mm_parents,
+           0x0040, 24, 2),
+       MUX_GATE(CLK_TOP_MUX_PWM, "pwm_sel", pwm_parents, 0x0050, 0, 3, 7),
+       MUX_GATE(CLK_TOP_MUX_VDEC, "vdec_sel", vdec_parents, 0x0050, 8, 3, 15),
+       MUX_GATE(CLK_TOP_MUX_VENC, "venc_sel", venc_parents, 0x0050, 16, 2, 23),
+       MUX_GATE(CLK_TOP_MUX_MFG, "mfg_sel", mfg_parents, 0x0050, 24, 2, 31),
+       MUX_GATE(CLK_TOP_MUX_CAMTG, "camtg_sel", camtg, 0x0060, 0, 2, 7),
+       MUX_GATE(CLK_TOP_MUX_UART, "uart_sel", uart_parents, 0x0060, 8, 1, 15),
+       MUX_GATE(CLK_TOP_MUX_SPI, "spi_sel", spi_parents, 0x0060, 16, 2, 23),
+       MUX(CLK_TOP_MUX_ULPOSC_SPI_CK_MUX, "ulposc_spi_ck_mux",
+           ulposc_spi_ck_mux_parents, 0x0060, 18, 1),
+       MUX_GATE(CLK_TOP_MUX_USB20, "usb20_sel", usb20_parents,
+                0x0060, 24, 2, 31),
+       MUX(CLK_TOP_MUX_MSDC50_0_HCLK, "msdc50_0_hclk_sel",
+           msdc50_0_hclk_parents, 0x0070, 8, 2),
+       MUX_GATE(CLK_TOP_MUX_MSDC50_0, "msdc50_0_sel", msdc50_0_parents,
+                0x0070, 16, 4, 23),
+       MUX_GATE(CLK_TOP_MUX_MSDC30_1, "msdc30_1_sel", msdc30_1_parents,
+                0x0070, 24, 3, 31),
+       MUX_GATE(CLK_TOP_MUX_MSDC30_2, "msdc30_2_sel", msdc30_2_parents,
+                0x0080, 0, 3, 7),
+       MUX_GATE(CLK_TOP_MUX_AUDIO, "audio_sel", audio_parents,
+                0x0080, 16, 2, 23),
+       MUX(CLK_TOP_MUX_AUD_INTBUS, "aud_intbus_sel", aud_intbus_parents,
+           0x0080, 24, 2),
+       MUX(CLK_TOP_MUX_PMICSPI, "pmicspi_sel", pmicspi_parents,
+           0x0090, 0, 3),
+       MUX(CLK_TOP_MUX_SCP, "scp_sel", scp_parents,
+           0x0090, 8, 2),
+       MUX(CLK_TOP_MUX_ATB, "atb_sel", atb_parents,
+           0x0090, 16, 2),
+       MUX_GATE(CLK_TOP_MUX_MJC, "mjc_sel", mjc_parents, 0x0090, 24, 2, 31),
+       MUX_GATE(CLK_TOP_MUX_DPI0, "dpi0_sel", dpi0_parents, 0x00A0, 0, 3, 7),
+       MUX_GATE(CLK_TOP_MUX_AUD_1, "aud_1_sel", aud_1_parents,
+                0x00A0, 16, 1, 23),
+       MUX_GATE(CLK_TOP_MUX_AUD_2, "aud_2_sel", aud_2_parents,
+                0x00A0, 24, 1, 31),
+       MUX(CLK_TOP_MUX_SSUSB_TOP_SYS, "ssusb_top_sys_sel",
+           ssusb_top_sys_parents, 0x00B0, 8, 1),
+       MUX(CLK_TOP_MUX_SPM, "spm_sel", spm_parents,
+           0x00C0, 0, 1),
+       MUX(CLK_TOP_MUX_BSI_SPI, "bsi_spi_sel", bsi_spi_parents,
+           0x00C0, 8, 2),
+       MUX_GATE(CLK_TOP_MUX_AUDIO_H, "audio_h_sel", audio_h_parents,
+                0x00C0, 16, 2, 23),
+       MUX_GATE(CLK_TOP_MUX_ANC_MD32, "anc_md32_sel", anc_md32_parents,
+                0x00C0, 24, 2, 31),
+       MUX(CLK_TOP_MUX_MFG_52M, "mfg_52m_sel", mfg_52m_parents,
+           0x0104, 1, 2),
+};
+
+static int mtk_topckgen_init(struct platform_device *pdev)
+{
+       struct clk_onecell_data *clk_data;
+       void __iomem *base;
+       struct device_node *node = pdev->dev.of_node;
+       struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+       base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       clk_data = mtk_alloc_clk_data(CLK_TOP_NR);
+
+       mtk_clk_register_factors(top_fixed_divs, ARRAY_SIZE(top_fixed_divs),
+                                clk_data);
+
+       mtk_clk_register_composites(top_muxes, ARRAY_SIZE(top_muxes), base,
+                                   &mt6797_clk_lock, clk_data);
+
+       return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+static const struct mtk_gate_regs infra0_cg_regs = {
+       .set_ofs = 0x0080,
+       .clr_ofs = 0x0084,
+       .sta_ofs = 0x0090,
+};
+
+static const struct mtk_gate_regs infra1_cg_regs = {
+       .set_ofs = 0x0088,
+       .clr_ofs = 0x008c,
+       .sta_ofs = 0x0094,
+};
+
+static const struct mtk_gate_regs infra2_cg_regs = {
+       .set_ofs = 0x00a8,
+       .clr_ofs = 0x00ac,
+       .sta_ofs = 0x00b0,
+};
+
+#define GATE_ICG0(_id, _name, _parent, _shift) {       \
+       .id = _id,                                      \
+       .name = _name,                                  \
+       .parent_name = _parent,                         \
+       .regs = &infra0_cg_regs,                        \
+       .shift = _shift,                                \
+       .ops = &mtk_clk_gate_ops_setclr,                \
+}
+
+#define GATE_ICG1(_id, _name, _parent, _shift) {       \
+       .id = _id,                                      \
+       .name = _name,                                  \
+       .parent_name = _parent,                         \
+       .regs = &infra1_cg_regs,                        \
+       .shift = _shift,                                \
+       .ops = &mtk_clk_gate_ops_setclr,                \
+}
+
+#define GATE_ICG2(_id, _name, _parent, _shift) {       \
+       .id = _id,                                      \
+       .name = _name,                                  \
+       .parent_name = _parent,                         \
+       .regs = &infra2_cg_regs,                        \
+       .shift = _shift,                                \
+       .ops = &mtk_clk_gate_ops_setclr,                \
+}
+
+static const struct mtk_gate infra_clks[] = {
+       GATE_ICG0(CLK_INFRA_PMIC_TMR, "infra_pmic_tmr", "ulposc", 0),
+       GATE_ICG0(CLK_INFRA_PMIC_AP, "infra_pmic_ap", "pmicspi_sel", 1),
+       GATE_ICG0(CLK_INFRA_PMIC_MD, "infra_pmic_md", "pmicspi_sel", 2),
+       GATE_ICG0(CLK_INFRA_PMIC_CONN, "infra_pmic_conn", "pmicspi_sel", 3),
+       GATE_ICG0(CLK_INFRA_SCP, "infra_scp", "scp_sel", 4),
+       GATE_ICG0(CLK_INFRA_SEJ, "infra_sej", "axi_sel", 5),
+       GATE_ICG0(CLK_INFRA_APXGPT, "infra_apxgpt", "axi_sel", 6),
+       GATE_ICG0(CLK_INFRA_SEJ_13M, "infra_sej_13m", "clk26m", 7),
+       GATE_ICG0(CLK_INFRA_ICUSB, "infra_icusb", "usb20_sel", 8),
+       GATE_ICG0(CLK_INFRA_GCE, "infra_gce", "axi_sel", 9),
+       GATE_ICG0(CLK_INFRA_THERM, "infra_therm", "axi_sel", 10),
+       GATE_ICG0(CLK_INFRA_I2C0, "infra_i2c0", "axi_sel", 11),
+       GATE_ICG0(CLK_INFRA_I2C1, "infra_i2c1", "axi_sel", 12),
+       GATE_ICG0(CLK_INFRA_I2C2, "infra_i2c2", "axi_sel", 13),
+       GATE_ICG0(CLK_INFRA_I2C3, "infra_i2c3", "axi_sel", 14),
+       GATE_ICG0(CLK_INFRA_PWM_HCLK, "infra_pwm_hclk", "axi_sel", 15),
+       GATE_ICG0(CLK_INFRA_PWM1, "infra_pwm1", "axi_sel", 16),
+       GATE_ICG0(CLK_INFRA_PWM2, "infra_pwm2", "axi_sel", 17),
+       GATE_ICG0(CLK_INFRA_PWM3, "infra_pwm3", "axi_sel", 18),
+       GATE_ICG0(CLK_INFRA_PWM4, "infra_pwm4", "axi_sel", 19),
+       GATE_ICG0(CLK_INFRA_PWM, "infra_pwm", "axi_sel", 21),
+       GATE_ICG0(CLK_INFRA_UART0, "infra_uart0", "uart_sel", 22),
+       GATE_ICG0(CLK_INFRA_UART1, "infra_uart1", "uart_sel", 23),
+       GATE_ICG0(CLK_INFRA_UART2, "infra_uart2", "uart_sel", 24),
+       GATE_ICG0(CLK_INFRA_UART3, "infra_uart3", "uart_sel", 25),
+       GATE_ICG0(CLK_INFRA_MD2MD_CCIF_0, "infra_md2md_ccif_0", "axi_sel", 27),
+       GATE_ICG0(CLK_INFRA_MD2MD_CCIF_1, "infra_md2md_ccif_1", "axi_sel", 28),
+       GATE_ICG0(CLK_INFRA_MD2MD_CCIF_2, "infra_md2md_ccif_2", "axi_sel", 29),
+       GATE_ICG0(CLK_INFRA_FHCTL, "infra_fhctl", "clk26m", 30),
+       GATE_ICG0(CLK_INFRA_BTIF, "infra_btif", "axi_sel", 31),
+       GATE_ICG1(CLK_INFRA_MD2MD_CCIF_3, "infra_md2md_ccif_3", "axi_sel", 0),
+       GATE_ICG1(CLK_INFRA_SPI, "infra_spi", "spi_sel", 1),
+       GATE_ICG1(CLK_INFRA_MSDC0, "infra_msdc0", "msdc50_0_sel", 2),
+       GATE_ICG1(CLK_INFRA_MD2MD_CCIF_4, "infra_md2md_ccif_4", "axi_sel", 3),
+       GATE_ICG1(CLK_INFRA_MSDC1, "infra_msdc1", "msdc30_1_sel", 4),
+       GATE_ICG1(CLK_INFRA_MSDC2, "infra_msdc2", "msdc30_2_sel", 5),
+       GATE_ICG1(CLK_INFRA_MD2MD_CCIF_5, "infra_md2md_ccif_5", "axi_sel", 7),
+       GATE_ICG1(CLK_INFRA_GCPU, "infra_gcpu", "axi_sel", 8),
+       GATE_ICG1(CLK_INFRA_TRNG, "infra_trng", "axi_sel", 9),
+       GATE_ICG1(CLK_INFRA_AUXADC, "infra_auxadc", "clk26m", 10),
+       GATE_ICG1(CLK_INFRA_CPUM, "infra_cpum", "axi_sel", 11),
+       GATE_ICG1(CLK_INFRA_AP_C2K_CCIF_0, "infra_ap_c2k_ccif_0",
+                 "axi_sel", 12),
+       GATE_ICG1(CLK_INFRA_AP_C2K_CCIF_1, "infra_ap_c2k_ccif_1",
+                 "axi_sel", 13),
+       GATE_ICG1(CLK_INFRA_CLDMA, "infra_cldma", "axi_sel", 16),
+       GATE_ICG1(CLK_INFRA_DISP_PWM, "infra_disp_pwm", "pwm_sel", 17),
+       GATE_ICG1(CLK_INFRA_AP_DMA, "infra_ap_dma", "axi_sel", 18),
+       GATE_ICG1(CLK_INFRA_DEVICE_APC, "infra_device_apc", "axi_sel", 20),
+       GATE_ICG1(CLK_INFRA_L2C_SRAM, "infra_l2c_sram", "mm_sel", 22),
+       GATE_ICG1(CLK_INFRA_CCIF_AP, "infra_ccif_ap", "axi_sel", 23),
+       GATE_ICG1(CLK_INFRA_AUDIO, "infra_audio", "axi_sel", 25),
+       GATE_ICG1(CLK_INFRA_CCIF_MD, "infra_ccif_md", "axi_sel", 26),
+       GATE_ICG1(CLK_INFRA_DRAMC_F26M, "infra_dramc_f26m", "clk26m", 31),
+       GATE_ICG2(CLK_INFRA_I2C4, "infra_i2c4", "axi_sel", 0),
+       GATE_ICG2(CLK_INFRA_I2C_APPM, "infra_i2c_appm", "axi_sel", 1),
+       GATE_ICG2(CLK_INFRA_I2C_GPUPM, "infra_i2c_gpupm", "axi_sel", 2),
+       GATE_ICG2(CLK_INFRA_I2C2_IMM, "infra_i2c2_imm", "axi_sel", 3),
+       GATE_ICG2(CLK_INFRA_I2C2_ARB, "infra_i2c2_arb", "axi_sel", 4),
+       GATE_ICG2(CLK_INFRA_I2C3_IMM, "infra_i2c3_imm", "axi_sel", 5),
+       GATE_ICG2(CLK_INFRA_I2C3_ARB, "infra_i2c3_arb", "axi_sel", 6),
+       GATE_ICG2(CLK_INFRA_I2C5, "infra_i2c5", "axi_sel", 7),
+       GATE_ICG2(CLK_INFRA_SYS_CIRQ, "infra_sys_cirq", "axi_sel", 8),
+       GATE_ICG2(CLK_INFRA_SPI1, "infra_spi1", "spi_sel", 10),
+       GATE_ICG2(CLK_INFRA_DRAMC_B_F26M, "infra_dramc_b_f26m", "clk26m", 11),
+       GATE_ICG2(CLK_INFRA_ANC_MD32, "infra_anc_md32", "anc_md32_sel", 12),
+       GATE_ICG2(CLK_INFRA_ANC_MD32_32K, "infra_anc_md32_32k", "clk26m", 13),
+       GATE_ICG2(CLK_INFRA_DVFS_SPM1, "infra_dvfs_spm1", "axi_sel", 15),
+       GATE_ICG2(CLK_INFRA_AES_TOP0, "infra_aes_top0", "axi_sel", 16),
+       GATE_ICG2(CLK_INFRA_AES_TOP1, "infra_aes_top1", "axi_sel", 17),
+       GATE_ICG2(CLK_INFRA_SSUSB_BUS, "infra_ssusb_bus", "axi_sel", 18),
+       GATE_ICG2(CLK_INFRA_SPI2, "infra_spi2", "spi_sel", 19),
+       GATE_ICG2(CLK_INFRA_SPI3, "infra_spi3", "spi_sel", 20),
+       GATE_ICG2(CLK_INFRA_SPI4, "infra_spi4", "spi_sel", 21),
+       GATE_ICG2(CLK_INFRA_SPI5, "infra_spi5", "spi_sel", 22),
+       GATE_ICG2(CLK_INFRA_IRTX, "infra_irtx", "spi_sel", 23),
+       GATE_ICG2(CLK_INFRA_SSUSB_SYS, "infra_ssusb_sys",
+                 "ssusb_top_sys_sel", 24),
+       GATE_ICG2(CLK_INFRA_SSUSB_REF, "infra_ssusb_ref", "clk26m", 9),
+       GATE_ICG2(CLK_INFRA_AUDIO_26M, "infra_audio_26m", "clk26m", 26),
+       GATE_ICG2(CLK_INFRA_AUDIO_26M_PAD_TOP, "infra_audio_26m_pad_top",
+                 "clk26m", 27),
+       GATE_ICG2(CLK_INFRA_MODEM_TEMP_SHARE, "infra_modem_temp_share",
+                 "axi_sel", 28),
+       GATE_ICG2(CLK_INFRA_VAD_WRAP_SOC, "infra_vad_wrap_soc", "axi_sel", 29),
+       GATE_ICG2(CLK_INFRA_DRAMC_CONF, "infra_dramc_conf", "axi_sel", 30),
+       GATE_ICG2(CLK_INFRA_DRAMC_B_CONF, "infra_dramc_b_conf", "axi_sel", 31),
+       GATE_ICG1(CLK_INFRA_MFG_VCG, "infra_mfg_vcg", "mfg_52m_sel", 14),
+};
+
+static const struct mtk_fixed_factor infra_fixed_divs[] = {
+       FACTOR(CLK_INFRA_13M, "clk13m", "clk26m", 1, 2),
+};
+
+static struct clk_onecell_data *infra_clk_data;
+
+static void mtk_infrasys_init_early(struct device_node *node)
+{
+       int r, i;
+
+       if (!infra_clk_data) {
+               infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
+
+               for (i = 0; i < CLK_INFRA_NR; i++)
+                       infra_clk_data->clks[i] = ERR_PTR(-EPROBE_DEFER);
+       }
+
+       mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs),
+                                infra_clk_data);
+
+       r = of_clk_add_provider(node, of_clk_src_onecell_get, infra_clk_data);
+       if (r)
+               pr_err("%s(): could not register clock provider: %d\n",
+                      __func__, r);
+}
+
+CLK_OF_DECLARE_DRIVER(mtk_infra, "mediatek,mt6797-infracfg",
+                     mtk_infrasys_init_early);
+
+static int mtk_infrasys_init(struct platform_device *pdev)
+{
+       int r, i;
+       struct device_node *node = pdev->dev.of_node;
+
+       if (!infra_clk_data) {
+               infra_clk_data = mtk_alloc_clk_data(CLK_INFRA_NR);
+       } else {
+               for (i = 0; i < CLK_INFRA_NR; i++) {
+                       if (infra_clk_data->clks[i] == ERR_PTR(-EPROBE_DEFER))
+                               infra_clk_data->clks[i] = ERR_PTR(-ENOENT);
+               }
+       }
+
+       mtk_clk_register_gates(node, infra_clks, ARRAY_SIZE(infra_clks),
+                              infra_clk_data);
+       mtk_clk_register_factors(infra_fixed_divs, ARRAY_SIZE(infra_fixed_divs),
+                                infra_clk_data);
+
+       r = of_clk_add_provider(node, of_clk_src_onecell_get, infra_clk_data);
+       if (r)
+               return r;
+
+       return 0;
+}
+
+#define MT6797_PLL_FMAX                (3000UL * MHZ)
+
+#define CON0_MT6797_RST_BAR    BIT(24)
+
+#define PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits,  \
+                       _pd_reg, _pd_shift, _tuner_reg, _pcw_reg,       \
+                       _pcw_shift, _div_table) {                       \
+       .id = _id,                                              \
+       .name = _name,                                          \
+       .reg = _reg,                                            \
+       .pwr_reg = _pwr_reg,                                    \
+       .en_mask = _en_mask,                                    \
+       .flags = _flags,                                        \
+       .rst_bar_mask = CON0_MT6797_RST_BAR,                    \
+       .fmax = MT6797_PLL_FMAX,                                \
+       .pcwbits = _pcwbits,                                    \
+       .pd_reg = _pd_reg,                                      \
+       .pd_shift = _pd_shift,                                  \
+       .tuner_reg = _tuner_reg,                                \
+       .pcw_reg = _pcw_reg,                                    \
+       .pcw_shift = _pcw_shift,                                \
+       .div_table = _div_table,                                \
+}
+
+#define PLL(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits,    \
+                       _pd_reg, _pd_shift, _tuner_reg, _pcw_reg,       \
+                       _pcw_shift)                                     \
+               PLL_B(_id, _name, _reg, _pwr_reg, _en_mask, _flags, _pcwbits, \
+                       _pd_reg, _pd_shift, _tuner_reg, _pcw_reg, _pcw_shift, \
+                       NULL)
+
+static const struct mtk_pll_data plls[] = {
+       PLL(CLK_APMIXED_MAINPLL, "mainpll", 0x0220, 0x022C, 0xF0000101, PLL_AO,
+           21, 0x220, 4, 0x0, 0x224, 0),
+       PLL(CLK_APMIXED_UNIVPLL, "univpll", 0x0230, 0x023C, 0xFE000011, 0, 7,
+           0x230, 4, 0x0, 0x234, 14),
+       PLL(CLK_APMIXED_MFGPLL, "mfgpll", 0x0240, 0x024C, 0x00000101, 0, 21,
+           0x244, 24, 0x0, 0x244, 0),
+       PLL(CLK_APMIXED_MSDCPLL, "msdcpll", 0x0250, 0x025C, 0x00000121, 0, 21,
+           0x250, 4, 0x0, 0x254, 0),
+       PLL(CLK_APMIXED_IMGPLL, "imgpll", 0x0260, 0x026C, 0x00000121, 0, 21,
+           0x260, 4, 0x0, 0x264, 0),
+       PLL(CLK_APMIXED_TVDPLL, "tvdpll", 0x0270, 0x027C, 0xC0000121, 0, 21,
+           0x270, 4, 0x0, 0x274, 0),
+       PLL(CLK_APMIXED_CODECPLL, "codecpll", 0x0290, 0x029C, 0x00000121, 0, 21,
+           0x290, 4, 0x0, 0x294, 0),
+       PLL(CLK_APMIXED_VDECPLL, "vdecpll", 0x02E4, 0x02F0, 0x00000121, 0, 21,
+           0x2E4, 4, 0x0, 0x2E8, 0),
+       PLL(CLK_APMIXED_APLL1, "apll1", 0x02A0, 0x02B0, 0x00000131, 0, 31,
+           0x2A0, 4, 0x2A8, 0x2A4, 0),
+       PLL(CLK_APMIXED_APLL2, "apll2", 0x02B4, 0x02C4, 0x00000131, 0, 31,
+           0x2B4, 4, 0x2BC, 0x2B8, 0),
+};
+
+static int mtk_apmixedsys_init(struct platform_device *pdev)
+{
+       struct clk_onecell_data *clk_data;
+       struct device_node *node = pdev->dev.of_node;
+
+       clk_data = mtk_alloc_clk_data(CLK_APMIXED_NR);
+       if (!clk_data)
+               return -ENOMEM;
+
+       mtk_clk_register_plls(node, plls, ARRAY_SIZE(plls), clk_data);
+
+       return of_clk_add_provider(node, of_clk_src_onecell_get, clk_data);
+}
+
+static const struct of_device_id of_match_clk_mt6797[] = {
+       {
+               .compatible = "mediatek,mt6797-topckgen",
+               .data = mtk_topckgen_init,
+       }, {
+               .compatible = "mediatek,mt6797-infracfg",
+               .data = mtk_infrasys_init,
+       }, {
+               .compatible = "mediatek,mt6797-apmixedsys",
+               .data = mtk_apmixedsys_init,
+       }, {
+               /* sentinel */
+       }
+};
+
+static int clk_mt6797_probe(struct platform_device *pdev)
+{
+       int (*clk_init)(struct platform_device *);
+       int r;
+
+       clk_init = of_device_get_match_data(&pdev->dev);
+       if (!clk_init)
+               return -EINVAL;
+
+       r = clk_init(pdev);
+       if (r)
+               dev_err(&pdev->dev,
+                       "could not register clock provider: %s: %d\n",
+                       pdev->name, r);
+
+       return r;
+}
+
+static struct platform_driver clk_mt6797_drv = {
+       .probe = clk_mt6797_probe,
+       .driver = {
+               .name = "clk-mt6797",
+               .of_match_table = of_match_clk_mt6797,
+       },
+};
+
+static int __init clk_mt6797_init(void)
+{
+       return platform_driver_register(&clk_mt6797_drv);
+}
+
+arch_initcall(clk_mt6797_init);
index 349583405b7c0b3c765cb06cb00a40efbbdea288..83b6d9d65aa1fd5914bbcc4ef4890f5409c6fa06 100644 (file)
@@ -2,6 +2,6 @@
 # Makefile for Meson specific clk
 #
 
-obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-cpu.o clk-mpll.o
+obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-cpu.o clk-mpll.o clk-audio-divider.o
 obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o
 obj-$(CONFIG_COMMON_CLK_GXBB)   += gxbb.o gxbb-aoclk.o
diff --git a/drivers/clk/meson/clk-audio-divider.c b/drivers/clk/meson/clk-audio-divider.c
new file mode 100644 (file)
index 0000000..6c07db0
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2017 AmLogic, Inc.
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * i2s master clock divider: The algorithm of the generic clk-divider used with
+ * a very precise clock parent such as the mpll tends to select a low divider
+ * factor. This gives poor results with this particular divider, especially with
+ * high frequencies (> 100 MHz)
+ *
+ * This driver try to select the maximum possible divider with the rate the
+ * upstream clock can provide.
+ */
+
+#include <linux/clk-provider.h>
+#include "clkc.h"
+
+#define to_meson_clk_audio_divider(_hw) container_of(_hw, \
+                               struct meson_clk_audio_divider, hw)
+
+static int _div_round(unsigned long parent_rate, unsigned long rate,
+                     unsigned long flags)
+{
+       if (flags & CLK_DIVIDER_ROUND_CLOSEST)
+               return DIV_ROUND_CLOSEST_ULL((u64)parent_rate, rate);
+
+       return DIV_ROUND_UP_ULL((u64)parent_rate, rate);
+}
+
+static int _get_val(unsigned long parent_rate, unsigned long rate)
+{
+       return DIV_ROUND_UP_ULL((u64)parent_rate, rate) - 1;
+}
+
+static int _valid_divider(struct clk_hw *hw, int divider)
+{
+       struct meson_clk_audio_divider *adiv =
+               to_meson_clk_audio_divider(hw);
+       int max_divider;
+       u8 width;
+
+       width = adiv->div.width;
+       max_divider = 1 << width;
+
+       return clamp(divider, 1, max_divider);
+}
+
+static unsigned long audio_divider_recalc_rate(struct clk_hw *hw,
+                                              unsigned long parent_rate)
+{
+       struct meson_clk_audio_divider *adiv =
+               to_meson_clk_audio_divider(hw);
+       struct parm *p;
+       unsigned long reg, divider;
+
+       p = &adiv->div;
+       reg = readl(adiv->base + p->reg_off);
+       divider = PARM_GET(p->width, p->shift, reg) + 1;
+
+       return DIV_ROUND_UP_ULL((u64)parent_rate, divider);
+}
+
+static long audio_divider_round_rate(struct clk_hw *hw,
+                                    unsigned long rate,
+                                    unsigned long *parent_rate)
+{
+       struct meson_clk_audio_divider *adiv =
+               to_meson_clk_audio_divider(hw);
+       unsigned long max_prate;
+       int divider;
+
+       if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) {
+               divider = _div_round(*parent_rate, rate, adiv->flags);
+               divider = _valid_divider(hw, divider);
+               return DIV_ROUND_UP_ULL((u64)*parent_rate, divider);
+       }
+
+       /* Get the maximum parent rate */
+       max_prate = clk_hw_round_rate(clk_hw_get_parent(hw), ULONG_MAX);
+
+       /* Get the corresponding rounded down divider */
+       divider = max_prate / rate;
+       divider = _valid_divider(hw, divider);
+
+       /* Get actual rate of the parent */
+       *parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
+                                        divider * rate);
+
+       return DIV_ROUND_UP_ULL((u64)*parent_rate, divider);
+}
+
+static int audio_divider_set_rate(struct clk_hw *hw,
+                                 unsigned long rate,
+                                 unsigned long parent_rate)
+{
+       struct meson_clk_audio_divider *adiv =
+               to_meson_clk_audio_divider(hw);
+       struct parm *p;
+       unsigned long reg, flags = 0;
+       int val;
+
+       val = _get_val(parent_rate, rate);
+
+       if (adiv->lock)
+               spin_lock_irqsave(adiv->lock, flags);
+       else
+               __acquire(adiv->lock);
+
+       p = &adiv->div;
+       reg = readl(adiv->base + p->reg_off);
+       reg = PARM_SET(p->width, p->shift, reg, val);
+       writel(reg, adiv->base + p->reg_off);
+
+       if (adiv->lock)
+               spin_unlock_irqrestore(adiv->lock, flags);
+       else
+               __release(adiv->lock);
+
+       return 0;
+}
+
+const struct clk_ops meson_clk_audio_divider_ro_ops = {
+       .recalc_rate    = audio_divider_recalc_rate,
+       .round_rate     = audio_divider_round_rate,
+};
+
+const struct clk_ops meson_clk_audio_divider_ops = {
+       .recalc_rate    = audio_divider_recalc_rate,
+       .round_rate     = audio_divider_round_rate,
+       .set_rate       = audio_divider_set_rate,
+};
index 03af79005ddb4eef1bafce8090c218b359a6def2..39eab69fe51a8a76791029ae718c575f16843630 100644 (file)
 #include <linux/clk-provider.h>
 #include "clkc.h"
 
-#define SDM_MAX 16384
+#define SDM_DEN 16384
+#define N2_MIN 4
+#define N2_MAX 511
 
 #define to_meson_clk_mpll(_hw) container_of(_hw, struct meson_clk_mpll, hw)
 
+static long rate_from_params(unsigned long parent_rate,
+                                     unsigned long sdm,
+                                     unsigned long n2)
+{
+       unsigned long divisor = (SDM_DEN * n2) + sdm;
+
+       if (n2 < N2_MIN)
+               return -EINVAL;
+
+       return DIV_ROUND_UP_ULL((u64)parent_rate * SDM_DEN, divisor);
+}
+
+static void params_from_rate(unsigned long requested_rate,
+                            unsigned long parent_rate,
+                            unsigned long *sdm,
+                            unsigned long *n2)
+{
+       uint64_t div = parent_rate;
+       unsigned long rem = do_div(div, requested_rate);
+
+       if (div < N2_MIN) {
+               *n2 = N2_MIN;
+               *sdm = 0;
+       } else if (div > N2_MAX) {
+               *n2 = N2_MAX;
+               *sdm = SDM_DEN - 1;
+       } else {
+               *n2 = div;
+               *sdm = DIV_ROUND_UP(rem * SDM_DEN, requested_rate);
+       }
+}
+
 static unsigned long mpll_recalc_rate(struct clk_hw *hw,
                unsigned long parent_rate)
 {
        struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
        struct parm *p;
-       unsigned long rate = 0;
        unsigned long reg, sdm, n2;
+       long rate;
 
        p = &mpll->sdm;
        reg = readl(mpll->base + p->reg_off);
@@ -84,11 +118,123 @@ static unsigned long mpll_recalc_rate(struct clk_hw *hw,
        reg = readl(mpll->base + p->reg_off);
        n2 = PARM_GET(p->width, p->shift, reg);
 
-       rate = (parent_rate * SDM_MAX) / ((SDM_MAX * n2) + sdm);
+       rate = rate_from_params(parent_rate, sdm, n2);
+       if (rate < 0)
+               return 0;
 
        return rate;
 }
 
+static long mpll_round_rate(struct clk_hw *hw,
+                           unsigned long rate,
+                           unsigned long *parent_rate)
+{
+       unsigned long sdm, n2;
+
+       params_from_rate(rate, *parent_rate, &sdm, &n2);
+       return rate_from_params(*parent_rate, sdm, n2);
+}
+
+static int mpll_set_rate(struct clk_hw *hw,
+                        unsigned long rate,
+                        unsigned long parent_rate)
+{
+       struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
+       struct parm *p;
+       unsigned long reg, sdm, n2;
+       unsigned long flags = 0;
+
+       params_from_rate(rate, parent_rate, &sdm, &n2);
+
+       if (mpll->lock)
+               spin_lock_irqsave(mpll->lock, flags);
+       else
+               __acquire(mpll->lock);
+
+       p = &mpll->sdm;
+       reg = readl(mpll->base + p->reg_off);
+       reg = PARM_SET(p->width, p->shift, reg, sdm);
+       writel(reg, mpll->base + p->reg_off);
+
+       p = &mpll->sdm_en;
+       reg = readl(mpll->base + p->reg_off);
+       reg = PARM_SET(p->width, p->shift, reg, 1);
+       writel(reg, mpll->base + p->reg_off);
+
+       p = &mpll->n2;
+       reg = readl(mpll->base + p->reg_off);
+       reg = PARM_SET(p->width, p->shift, reg, n2);
+       writel(reg, mpll->base + p->reg_off);
+
+       if (mpll->lock)
+               spin_unlock_irqrestore(mpll->lock, flags);
+       else
+               __release(mpll->lock);
+
+       return 0;
+}
+
+static void mpll_enable_core(struct clk_hw *hw, int enable)
+{
+       struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
+       struct parm *p;
+       unsigned long reg;
+       unsigned long flags = 0;
+
+       if (mpll->lock)
+               spin_lock_irqsave(mpll->lock, flags);
+       else
+               __acquire(mpll->lock);
+
+       p = &mpll->en;
+       reg = readl(mpll->base + p->reg_off);
+       reg = PARM_SET(p->width, p->shift, reg, enable ? 1 : 0);
+       writel(reg, mpll->base + p->reg_off);
+
+       if (mpll->lock)
+               spin_unlock_irqrestore(mpll->lock, flags);
+       else
+               __release(mpll->lock);
+}
+
+
+static int mpll_enable(struct clk_hw *hw)
+{
+       mpll_enable_core(hw, 1);
+
+       return 0;
+}
+
+static void mpll_disable(struct clk_hw *hw)
+{
+       mpll_enable_core(hw, 0);
+}
+
+static int mpll_is_enabled(struct clk_hw *hw)
+{
+       struct meson_clk_mpll *mpll = to_meson_clk_mpll(hw);
+       struct parm *p;
+       unsigned long reg;
+       int en;
+
+       p = &mpll->en;
+       reg = readl(mpll->base + p->reg_off);
+       en = PARM_GET(p->width, p->shift, reg);
+
+       return en;
+}
+
 const struct clk_ops meson_clk_mpll_ro_ops = {
-       .recalc_rate = mpll_recalc_rate,
+       .recalc_rate    = mpll_recalc_rate,
+       .round_rate     = mpll_round_rate,
+       .is_enabled     = mpll_is_enabled,
+};
+
+const struct clk_ops meson_clk_mpll_ops = {
+       .recalc_rate    = mpll_recalc_rate,
+       .round_rate     = mpll_round_rate,
+       .set_rate       = mpll_set_rate,
+       .enable         = mpll_enable,
+       .disable        = mpll_disable,
+       .is_enabled     = mpll_is_enabled,
 };
index 4adc1e89212c9a944587117ee8d1a8b9eae63d4d..01341553f50b77cde511388e3f36443c89b45c00 100644 (file)
@@ -116,6 +116,30 @@ static const struct pll_rate_table *meson_clk_get_pll_settings(struct meson_clk_
        return NULL;
 }
 
+/* Specific wait loop for GXL/GXM GP0 PLL */
+static int meson_clk_pll_wait_lock_reset(struct meson_clk_pll *pll,
+                                        struct parm *p_n)
+{
+       int delay = 100;
+       u32 reg;
+
+       while (delay > 0) {
+               reg = readl(pll->base + p_n->reg_off);
+               writel(reg | MESON_PLL_RESET, pll->base + p_n->reg_off);
+               udelay(10);
+               writel(reg & ~MESON_PLL_RESET, pll->base + p_n->reg_off);
+
+               /* This delay comes from AMLogic tree clk-gp0-gxl driver */
+               mdelay(1);
+
+               reg = readl(pll->base + p_n->reg_off);
+               if (reg & MESON_PLL_LOCK)
+                       return 0;
+               delay--;
+       }
+       return -ETIMEDOUT;
+}
+
 static int meson_clk_pll_wait_lock(struct meson_clk_pll *pll,
                                   struct parm *p_n)
 {
@@ -132,6 +156,15 @@ static int meson_clk_pll_wait_lock(struct meson_clk_pll *pll,
        return -ETIMEDOUT;
 }
 
+static void meson_clk_pll_init_params(struct meson_clk_pll *pll)
+{
+       int i;
+
+       for (i = 0 ; i < pll->params.params_count ; ++i)
+               writel(pll->params.params_table[i].value,
+                      pll->base + pll->params.params_table[i].reg_off);
+}
+
 static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
                                  unsigned long parent_rate)
 {
@@ -151,10 +184,16 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
        if (!rate_set)
                return -EINVAL;
 
+       /* Initialize the PLL in a clean state if specified */
+       if (pll->params.params_count)
+               meson_clk_pll_init_params(pll);
+
        /* PLL reset */
        p = &pll->n;
        reg = readl(pll->base + p->reg_off);
-       writel(reg | MESON_PLL_RESET, pll->base + p->reg_off);
+       /* If no_init_reset is provided, avoid resetting at this point */
+       if (!pll->params.no_init_reset)
+               writel(reg | MESON_PLL_RESET, pll->base + p->reg_off);
 
        reg = PARM_SET(p->width, p->shift, reg, rate_set->n);
        writel(reg, pll->base + p->reg_off);
@@ -184,7 +223,17 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
        }
 
        p = &pll->n;
-       ret = meson_clk_pll_wait_lock(pll, p);
+       /* If clear_reset_for_lock is provided, remove the reset bit here */
+       if (pll->params.clear_reset_for_lock) {
+               reg = readl(pll->base + p->reg_off);
+               writel(reg & ~MESON_PLL_RESET, pll->base + p->reg_off);
+       }
+
+       /* If reset_lock_loop, use a special loop including resetting */
+       if (pll->params.reset_lock_loop)
+               ret = meson_clk_pll_wait_lock_reset(pll, p);
+       else
+               ret = meson_clk_pll_wait_lock(pll, p);
        if (ret) {
                pr_warn("%s: pll did not lock, trying to restore old rate %lu\n",
                        __func__, old_rate);
index 9bb70e7a7d6aeb6b02e48dd8cff52ebaa921c770..d6feafe8bd6cea9ff9d61b0416f7c5d7858a044a 100644 (file)
@@ -25,7 +25,7 @@
 #define PARM_GET(width, shift, reg)                                    \
        (((reg) & SETPMASK(width, shift)) >> (shift))
 #define PARM_SET(width, shift, reg, val)                               \
-       (((reg) & CLRPMASK(width, shift)) | (val << (shift)))
+       (((reg) & CLRPMASK(width, shift)) | ((val) << (shift)))
 
 #define MESON_PARM_APPLICABLE(p)               (!!((p)->width))
 
@@ -62,6 +62,28 @@ struct pll_rate_table {
                .frac           = (_frac),                              \
        }                                                               \
 
+struct pll_params_table {
+       unsigned int reg_off;
+       unsigned int value;
+};
+
+#define PLL_PARAM(_reg, _val)                                          \
+       {                                                               \
+               .reg_off        = (_reg),                               \
+               .value          = (_val),                               \
+       }
+
+struct pll_setup_params {
+       struct pll_params_table *params_table;
+       unsigned int params_count;
+       /* Workaround for GP0, do not reset before configuring */
+       bool no_init_reset;
+       /* Workaround for GP0, unreset right before checking for lock */
+       bool clear_reset_for_lock;
+       /* Workaround for GXL GP0, reset in the lock checking loop */
+       bool reset_lock_loop;
+};
+
 struct meson_clk_pll {
        struct clk_hw hw;
        void __iomem *base;
@@ -70,6 +92,7 @@ struct meson_clk_pll {
        struct parm frac;
        struct parm od;
        struct parm od2;
+       const struct pll_setup_params params;
        const struct pll_rate_table *rate_table;
        unsigned int rate_count;
        spinlock_t *lock;
@@ -92,8 +115,17 @@ struct meson_clk_mpll {
        struct clk_hw hw;
        void __iomem *base;
        struct parm sdm;
+       struct parm sdm_en;
        struct parm n2;
-       /* FIXME ssen gate control? */
+       struct parm en;
+       spinlock_t *lock;
+};
+
+struct meson_clk_audio_divider {
+       struct clk_hw hw;
+       void __iomem *base;
+       struct parm div;
+       u8 flags;
        spinlock_t *lock;
 };
 
@@ -116,5 +148,8 @@ extern const struct clk_ops meson_clk_pll_ro_ops;
 extern const struct clk_ops meson_clk_pll_ops;
 extern const struct clk_ops meson_clk_cpu_ops;
 extern const struct clk_ops meson_clk_mpll_ro_ops;
+extern const struct clk_ops meson_clk_mpll_ops;
+extern const struct clk_ops meson_clk_audio_divider_ro_ops;
+extern const struct clk_ops meson_clk_audio_divider_ops;
 
 #endif /* __CLKC_H */
index 1c1ec137a3cc72e8712e172b4eca862e90aa69eb..ad5f027af1a20cf1738adbdcb3a1496c793bf5ec 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/of_address.h>
+#include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/init.h>
 
@@ -120,7 +121,7 @@ static const struct pll_rate_table sys_pll_rate_table[] = {
        { /* sentinel */ },
 };
 
-static const struct pll_rate_table gp0_pll_rate_table[] = {
+static const struct pll_rate_table gxbb_gp0_pll_rate_table[] = {
        PLL_RATE(96000000, 32, 1, 3),
        PLL_RATE(99000000, 33, 1, 3),
        PLL_RATE(102000000, 34, 1, 3),
@@ -248,6 +249,35 @@ static const struct pll_rate_table gp0_pll_rate_table[] = {
        { /* sentinel */ },
 };
 
+static const struct pll_rate_table gxl_gp0_pll_rate_table[] = {
+       PLL_RATE(504000000, 42, 1, 1),
+       PLL_RATE(516000000, 43, 1, 1),
+       PLL_RATE(528000000, 44, 1, 1),
+       PLL_RATE(540000000, 45, 1, 1),
+       PLL_RATE(552000000, 46, 1, 1),
+       PLL_RATE(564000000, 47, 1, 1),
+       PLL_RATE(576000000, 48, 1, 1),
+       PLL_RATE(588000000, 49, 1, 1),
+       PLL_RATE(600000000, 50, 1, 1),
+       PLL_RATE(612000000, 51, 1, 1),
+       PLL_RATE(624000000, 52, 1, 1),
+       PLL_RATE(636000000, 53, 1, 1),
+       PLL_RATE(648000000, 54, 1, 1),
+       PLL_RATE(660000000, 55, 1, 1),
+       PLL_RATE(672000000, 56, 1, 1),
+       PLL_RATE(684000000, 57, 1, 1),
+       PLL_RATE(696000000, 58, 1, 1),
+       PLL_RATE(708000000, 59, 1, 1),
+       PLL_RATE(720000000, 60, 1, 1),
+       PLL_RATE(732000000, 61, 1, 1),
+       PLL_RATE(744000000, 62, 1, 1),
+       PLL_RATE(756000000, 63, 1, 1),
+       PLL_RATE(768000000, 64, 1, 1),
+       PLL_RATE(780000000, 65, 1, 1),
+       PLL_RATE(792000000, 66, 1, 1),
+       { /* sentinel */ },
+};
+
 static const struct clk_div_table cpu_div_table[] = {
        { .val = 1, .div = 1 },
        { .val = 2, .div = 2 },
@@ -352,6 +382,13 @@ static struct meson_clk_pll gxbb_sys_pll = {
        },
 };
 
+struct pll_params_table gxbb_gp0_params_table[] = {
+       PLL_PARAM(HHI_GP0_PLL_CNTL, 0x6a000228),
+       PLL_PARAM(HHI_GP0_PLL_CNTL2, 0x69c80000),
+       PLL_PARAM(HHI_GP0_PLL_CNTL3, 0x0a5590c4),
+       PLL_PARAM(HHI_GP0_PLL_CNTL4, 0x0000500d),
+};
+
 static struct meson_clk_pll gxbb_gp0_pll = {
        .m = {
                .reg_off = HHI_GP0_PLL_CNTL,
@@ -368,8 +405,57 @@ static struct meson_clk_pll gxbb_gp0_pll = {
                .shift   = 16,
                .width   = 2,
        },
-       .rate_table = gp0_pll_rate_table,
-       .rate_count = ARRAY_SIZE(gp0_pll_rate_table),
+       .params = {
+               .params_table = gxbb_gp0_params_table,
+               .params_count = ARRAY_SIZE(gxbb_gp0_params_table),
+               .no_init_reset = true,
+               .clear_reset_for_lock = true,
+       },
+       .rate_table = gxbb_gp0_pll_rate_table,
+       .rate_count = ARRAY_SIZE(gxbb_gp0_pll_rate_table),
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "gp0_pll",
+               .ops = &meson_clk_pll_ops,
+               .parent_names = (const char *[]){ "xtal" },
+               .num_parents = 1,
+               .flags = CLK_GET_RATE_NOCACHE,
+       },
+};
+
+struct pll_params_table gxl_gp0_params_table[] = {
+       PLL_PARAM(HHI_GP0_PLL_CNTL, 0x40010250),
+       PLL_PARAM(HHI_GP0_PLL_CNTL1, 0xc084a000),
+       PLL_PARAM(HHI_GP0_PLL_CNTL2, 0xb75020be),
+       PLL_PARAM(HHI_GP0_PLL_CNTL3, 0x0a59a288),
+       PLL_PARAM(HHI_GP0_PLL_CNTL4, 0xc000004d),
+       PLL_PARAM(HHI_GP0_PLL_CNTL5, 0x00078000),
+};
+
+static struct meson_clk_pll gxl_gp0_pll = {
+       .m = {
+               .reg_off = HHI_GP0_PLL_CNTL,
+               .shift   = 0,
+               .width   = 9,
+       },
+       .n = {
+               .reg_off = HHI_GP0_PLL_CNTL,
+               .shift   = 9,
+               .width   = 5,
+       },
+       .od = {
+               .reg_off = HHI_GP0_PLL_CNTL,
+               .shift   = 16,
+               .width   = 2,
+       },
+       .params = {
+               .params_table = gxl_gp0_params_table,
+               .params_count = ARRAY_SIZE(gxl_gp0_params_table),
+               .no_init_reset = true,
+               .reset_lock_loop = true,
+       },
+       .rate_table = gxl_gp0_pll_rate_table,
+       .rate_count = ARRAY_SIZE(gxl_gp0_pll_rate_table),
        .lock = &clk_lock,
        .hw.init = &(struct clk_init_data){
                .name = "gp0_pll",
@@ -441,15 +527,25 @@ static struct meson_clk_mpll gxbb_mpll0 = {
                .shift   = 0,
                .width   = 14,
        },
+       .sdm_en = {
+               .reg_off = HHI_MPLL_CNTL7,
+               .shift   = 15,
+               .width   = 1,
+       },
        .n2 = {
                .reg_off = HHI_MPLL_CNTL7,
                .shift   = 16,
                .width   = 9,
        },
+       .en = {
+               .reg_off = HHI_MPLL_CNTL7,
+               .shift   = 14,
+               .width   = 1,
+       },
        .lock = &clk_lock,
        .hw.init = &(struct clk_init_data){
                .name = "mpll0",
-               .ops = &meson_clk_mpll_ro_ops,
+               .ops = &meson_clk_mpll_ops,
                .parent_names = (const char *[]){ "fixed_pll" },
                .num_parents = 1,
        },
@@ -461,15 +557,25 @@ static struct meson_clk_mpll gxbb_mpll1 = {
                .shift   = 0,
                .width   = 14,
        },
+       .sdm_en = {
+               .reg_off = HHI_MPLL_CNTL8,
+               .shift   = 15,
+               .width   = 1,
+       },
        .n2 = {
                .reg_off = HHI_MPLL_CNTL8,
                .shift   = 16,
                .width   = 9,
        },
+       .en = {
+               .reg_off = HHI_MPLL_CNTL8,
+               .shift   = 14,
+               .width   = 1,
+       },
        .lock = &clk_lock,
        .hw.init = &(struct clk_init_data){
                .name = "mpll1",
-               .ops = &meson_clk_mpll_ro_ops,
+               .ops = &meson_clk_mpll_ops,
                .parent_names = (const char *[]){ "fixed_pll" },
                .num_parents = 1,
        },
@@ -481,15 +587,25 @@ static struct meson_clk_mpll gxbb_mpll2 = {
                .shift   = 0,
                .width   = 14,
        },
+       .sdm_en = {
+               .reg_off = HHI_MPLL_CNTL9,
+               .shift   = 15,
+               .width   = 1,
+       },
        .n2 = {
                .reg_off = HHI_MPLL_CNTL9,
                .shift   = 16,
                .width   = 9,
        },
+       .en = {
+               .reg_off = HHI_MPLL_CNTL9,
+               .shift   = 14,
+               .width   = 1,
+       },
        .lock = &clk_lock,
        .hw.init = &(struct clk_init_data){
                .name = "mpll2",
-               .ops = &meson_clk_mpll_ro_ops,
+               .ops = &meson_clk_mpll_ops,
                .parent_names = (const char *[]){ "fixed_pll" },
                .num_parents = 1,
        },
@@ -604,6 +720,237 @@ static struct clk_gate gxbb_sar_adc_clk = {
        },
 };
 
+/*
+ * The MALI IP is clocked by two identical clocks (mali_0 and mali_1)
+ * muxed by a glitch-free switch.
+ */
+
+static u32 mux_table_mali_0_1[] = {0, 1, 2, 3, 4, 5, 6, 7};
+static const char *gxbb_mali_0_1_parent_names[] = {
+       "xtal", "gp0_pll", "mpll2", "mpll1", "fclk_div7",
+       "fclk_div4", "fclk_div3", "fclk_div5"
+};
+
+static struct clk_mux gxbb_mali_0_sel = {
+       .reg = (void *)HHI_MALI_CLK_CNTL,
+       .mask = 0x7,
+       .shift = 9,
+       .table = mux_table_mali_0_1,
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "mali_0_sel",
+               .ops = &clk_mux_ops,
+               /*
+                * bits 10:9 selects from 8 possible parents:
+                * xtal, gp0_pll, mpll2, mpll1, fclk_div7,
+                * fclk_div4, fclk_div3, fclk_div5
+                */
+               .parent_names = gxbb_mali_0_1_parent_names,
+               .num_parents = 8,
+               .flags = CLK_SET_RATE_NO_REPARENT,
+       },
+};
+
+static struct clk_divider gxbb_mali_0_div = {
+       .reg = (void *)HHI_MALI_CLK_CNTL,
+       .shift = 0,
+       .width = 7,
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "mali_0_div",
+               .ops = &clk_divider_ops,
+               .parent_names = (const char *[]){ "mali_0_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_NO_REPARENT,
+       },
+};
+
+static struct clk_gate gxbb_mali_0 = {
+       .reg = (void *)HHI_MALI_CLK_CNTL,
+       .bit_idx = 8,
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "mali_0",
+               .ops = &clk_gate_ops,
+               .parent_names = (const char *[]){ "mali_0_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_mux gxbb_mali_1_sel = {
+       .reg = (void *)HHI_MALI_CLK_CNTL,
+       .mask = 0x7,
+       .shift = 25,
+       .table = mux_table_mali_0_1,
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "mali_1_sel",
+               .ops = &clk_mux_ops,
+               /*
+                * bits 10:9 selects from 8 possible parents:
+                * xtal, gp0_pll, mpll2, mpll1, fclk_div7,
+                * fclk_div4, fclk_div3, fclk_div5
+                */
+               .parent_names = gxbb_mali_0_1_parent_names,
+               .num_parents = 8,
+               .flags = CLK_SET_RATE_NO_REPARENT,
+       },
+};
+
+static struct clk_divider gxbb_mali_1_div = {
+       .reg = (void *)HHI_MALI_CLK_CNTL,
+       .shift = 16,
+       .width = 7,
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "mali_1_div",
+               .ops = &clk_divider_ops,
+               .parent_names = (const char *[]){ "mali_1_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_NO_REPARENT,
+       },
+};
+
+static struct clk_gate gxbb_mali_1 = {
+       .reg = (void *)HHI_MALI_CLK_CNTL,
+       .bit_idx = 24,
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "mali_1",
+               .ops = &clk_gate_ops,
+               .parent_names = (const char *[]){ "mali_1_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static u32 mux_table_mali[] = {0, 1};
+static const char *gxbb_mali_parent_names[] = {
+       "mali_0", "mali_1"
+};
+
+static struct clk_mux gxbb_mali = {
+       .reg = (void *)HHI_MALI_CLK_CNTL,
+       .mask = 1,
+       .shift = 31,
+       .table = mux_table_mali,
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "mali",
+               .ops = &clk_mux_ops,
+               .parent_names = gxbb_mali_parent_names,
+               .num_parents = 2,
+               .flags = CLK_SET_RATE_NO_REPARENT,
+       },
+};
+
+static struct clk_mux gxbb_cts_amclk_sel = {
+       .reg = (void *) HHI_AUD_CLK_CNTL,
+       .mask = 0x3,
+       .shift = 9,
+       /* Default parent unknown (register reset value: 0) */
+       .table = (u32[]){ 1, 2, 3 },
+       .lock = &clk_lock,
+               .hw.init = &(struct clk_init_data){
+               .name = "cts_amclk_sel",
+               .ops = &clk_mux_ops,
+               .parent_names = (const char *[]){ "mpll0", "mpll1", "mpll2" },
+               .num_parents = 3,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct meson_clk_audio_divider gxbb_cts_amclk_div = {
+       .div = {
+               .reg_off = HHI_AUD_CLK_CNTL,
+               .shift   = 0,
+               .width   = 8,
+       },
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "cts_amclk_div",
+               .ops = &meson_clk_audio_divider_ops,
+               .parent_names = (const char *[]){ "cts_amclk_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_DIVIDER_ROUND_CLOSEST,
+       },
+};
+
+static struct clk_gate gxbb_cts_amclk = {
+       .reg = (void *) HHI_AUD_CLK_CNTL,
+       .bit_idx = 8,
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "cts_amclk",
+               .ops = &clk_gate_ops,
+               .parent_names = (const char *[]){ "cts_amclk_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_mux gxbb_cts_mclk_i958_sel = {
+       .reg = (void *)HHI_AUD_CLK_CNTL2,
+       .mask = 0x3,
+       .shift = 25,
+       /* Default parent unknown (register reset value: 0) */
+       .table = (u32[]){ 1, 2, 3 },
+       .lock = &clk_lock,
+               .hw.init = &(struct clk_init_data){
+               .name = "cts_mclk_i958_sel",
+               .ops = &clk_mux_ops,
+               .parent_names = (const char *[]){ "mpll0", "mpll1", "mpll2" },
+               .num_parents = 3,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_divider gxbb_cts_mclk_i958_div = {
+       .reg = (void *)HHI_AUD_CLK_CNTL2,
+       .shift = 16,
+       .width = 8,
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "cts_mclk_i958_div",
+               .ops = &clk_divider_ops,
+               .parent_names = (const char *[]){ "cts_mclk_i958_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_DIVIDER_ROUND_CLOSEST,
+       },
+};
+
+static struct clk_gate gxbb_cts_mclk_i958 = {
+       .reg = (void *)HHI_AUD_CLK_CNTL2,
+       .bit_idx = 24,
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "cts_mclk_i958",
+               .ops = &clk_gate_ops,
+               .parent_names = (const char *[]){ "cts_mclk_i958_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_mux gxbb_cts_i958 = {
+       .reg = (void *)HHI_AUD_CLK_CNTL2,
+       .mask = 0x1,
+       .shift = 27,
+       .lock = &clk_lock,
+               .hw.init = &(struct clk_init_data){
+               .name = "cts_i958",
+               .ops = &clk_mux_ops,
+               .parent_names = (const char *[]){ "cts_amclk", "cts_mclk_i958" },
+               .num_parents = 2,
+               /*
+                *The parent is specific to origin of the audio data. Let the
+                * consumer choose the appropriate parent
+                */
+               .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
+       },
+};
+
 /* Everything Else (EE) domain gates */
 static MESON_GATE(gxbb_ddr, HHI_GCLK_MPEG0, 0);
 static MESON_GATE(gxbb_dos, HHI_GCLK_MPEG0, 1);
@@ -797,6 +1144,140 @@ static struct clk_hw_onecell_data gxbb_hw_onecell_data = {
                [CLKID_SAR_ADC_CLK]         = &gxbb_sar_adc_clk.hw,
                [CLKID_SAR_ADC_SEL]         = &gxbb_sar_adc_clk_sel.hw,
                [CLKID_SAR_ADC_DIV]         = &gxbb_sar_adc_clk_div.hw,
+               [CLKID_MALI_0_SEL]          = &gxbb_mali_0_sel.hw,
+               [CLKID_MALI_0_DIV]          = &gxbb_mali_0_div.hw,
+               [CLKID_MALI_0]              = &gxbb_mali_0.hw,
+               [CLKID_MALI_1_SEL]          = &gxbb_mali_1_sel.hw,
+               [CLKID_MALI_1_DIV]          = &gxbb_mali_1_div.hw,
+               [CLKID_MALI_1]              = &gxbb_mali_1.hw,
+               [CLKID_MALI]                = &gxbb_mali.hw,
+               [CLKID_CTS_AMCLK]           = &gxbb_cts_amclk.hw,
+               [CLKID_CTS_AMCLK_SEL]       = &gxbb_cts_amclk_sel.hw,
+               [CLKID_CTS_AMCLK_DIV]       = &gxbb_cts_amclk_div.hw,
+               [CLKID_CTS_MCLK_I958]       = &gxbb_cts_mclk_i958.hw,
+               [CLKID_CTS_MCLK_I958_SEL]   = &gxbb_cts_mclk_i958_sel.hw,
+               [CLKID_CTS_MCLK_I958_DIV]   = &gxbb_cts_mclk_i958_div.hw,
+               [CLKID_CTS_I958]            = &gxbb_cts_i958.hw,
+       },
+       .num = NR_CLKS,
+};
+
+static struct clk_hw_onecell_data gxl_hw_onecell_data = {
+       .hws = {
+               [CLKID_SYS_PLL]             = &gxbb_sys_pll.hw,
+               [CLKID_CPUCLK]              = &gxbb_cpu_clk.hw,
+               [CLKID_HDMI_PLL]            = &gxbb_hdmi_pll.hw,
+               [CLKID_FIXED_PLL]           = &gxbb_fixed_pll.hw,
+               [CLKID_FCLK_DIV2]           = &gxbb_fclk_div2.hw,
+               [CLKID_FCLK_DIV3]           = &gxbb_fclk_div3.hw,
+               [CLKID_FCLK_DIV4]           = &gxbb_fclk_div4.hw,
+               [CLKID_FCLK_DIV5]           = &gxbb_fclk_div5.hw,
+               [CLKID_FCLK_DIV7]           = &gxbb_fclk_div7.hw,
+               [CLKID_GP0_PLL]             = &gxl_gp0_pll.hw,
+               [CLKID_MPEG_SEL]            = &gxbb_mpeg_clk_sel.hw,
+               [CLKID_MPEG_DIV]            = &gxbb_mpeg_clk_div.hw,
+               [CLKID_CLK81]               = &gxbb_clk81.hw,
+               [CLKID_MPLL0]               = &gxbb_mpll0.hw,
+               [CLKID_MPLL1]               = &gxbb_mpll1.hw,
+               [CLKID_MPLL2]               = &gxbb_mpll2.hw,
+               [CLKID_DDR]                 = &gxbb_ddr.hw,
+               [CLKID_DOS]                 = &gxbb_dos.hw,
+               [CLKID_ISA]                 = &gxbb_isa.hw,
+               [CLKID_PL301]               = &gxbb_pl301.hw,
+               [CLKID_PERIPHS]             = &gxbb_periphs.hw,
+               [CLKID_SPICC]               = &gxbb_spicc.hw,
+               [CLKID_I2C]                 = &gxbb_i2c.hw,
+               [CLKID_SAR_ADC]             = &gxbb_sar_adc.hw,
+               [CLKID_SMART_CARD]          = &gxbb_smart_card.hw,
+               [CLKID_RNG0]                = &gxbb_rng0.hw,
+               [CLKID_UART0]               = &gxbb_uart0.hw,
+               [CLKID_SDHC]                = &gxbb_sdhc.hw,
+               [CLKID_STREAM]              = &gxbb_stream.hw,
+               [CLKID_ASYNC_FIFO]          = &gxbb_async_fifo.hw,
+               [CLKID_SDIO]                = &gxbb_sdio.hw,
+               [CLKID_ABUF]                = &gxbb_abuf.hw,
+               [CLKID_HIU_IFACE]           = &gxbb_hiu_iface.hw,
+               [CLKID_ASSIST_MISC]         = &gxbb_assist_misc.hw,
+               [CLKID_SPI]                 = &gxbb_spi.hw,
+               [CLKID_I2S_SPDIF]           = &gxbb_i2s_spdif.hw,
+               [CLKID_ETH]                 = &gxbb_eth.hw,
+               [CLKID_DEMUX]               = &gxbb_demux.hw,
+               [CLKID_AIU_GLUE]            = &gxbb_aiu_glue.hw,
+               [CLKID_IEC958]              = &gxbb_iec958.hw,
+               [CLKID_I2S_OUT]             = &gxbb_i2s_out.hw,
+               [CLKID_AMCLK]               = &gxbb_amclk.hw,
+               [CLKID_AIFIFO2]             = &gxbb_aififo2.hw,
+               [CLKID_MIXER]               = &gxbb_mixer.hw,
+               [CLKID_MIXER_IFACE]         = &gxbb_mixer_iface.hw,
+               [CLKID_ADC]                 = &gxbb_adc.hw,
+               [CLKID_BLKMV]               = &gxbb_blkmv.hw,
+               [CLKID_AIU]                 = &gxbb_aiu.hw,
+               [CLKID_UART1]               = &gxbb_uart1.hw,
+               [CLKID_G2D]                 = &gxbb_g2d.hw,
+               [CLKID_USB0]                = &gxbb_usb0.hw,
+               [CLKID_USB1]                = &gxbb_usb1.hw,
+               [CLKID_RESET]               = &gxbb_reset.hw,
+               [CLKID_NAND]                = &gxbb_nand.hw,
+               [CLKID_DOS_PARSER]          = &gxbb_dos_parser.hw,
+               [CLKID_USB]                 = &gxbb_usb.hw,
+               [CLKID_VDIN1]               = &gxbb_vdin1.hw,
+               [CLKID_AHB_ARB0]            = &gxbb_ahb_arb0.hw,
+               [CLKID_EFUSE]               = &gxbb_efuse.hw,
+               [CLKID_BOOT_ROM]            = &gxbb_boot_rom.hw,
+               [CLKID_AHB_DATA_BUS]        = &gxbb_ahb_data_bus.hw,
+               [CLKID_AHB_CTRL_BUS]        = &gxbb_ahb_ctrl_bus.hw,
+               [CLKID_HDMI_INTR_SYNC]      = &gxbb_hdmi_intr_sync.hw,
+               [CLKID_HDMI_PCLK]           = &gxbb_hdmi_pclk.hw,
+               [CLKID_USB1_DDR_BRIDGE]     = &gxbb_usb1_ddr_bridge.hw,
+               [CLKID_USB0_DDR_BRIDGE]     = &gxbb_usb0_ddr_bridge.hw,
+               [CLKID_MMC_PCLK]            = &gxbb_mmc_pclk.hw,
+               [CLKID_DVIN]                = &gxbb_dvin.hw,
+               [CLKID_UART2]               = &gxbb_uart2.hw,
+               [CLKID_SANA]                = &gxbb_sana.hw,
+               [CLKID_VPU_INTR]            = &gxbb_vpu_intr.hw,
+               [CLKID_SEC_AHB_AHB3_BRIDGE] = &gxbb_sec_ahb_ahb3_bridge.hw,
+               [CLKID_CLK81_A53]           = &gxbb_clk81_a53.hw,
+               [CLKID_VCLK2_VENCI0]        = &gxbb_vclk2_venci0.hw,
+               [CLKID_VCLK2_VENCI1]        = &gxbb_vclk2_venci1.hw,
+               [CLKID_VCLK2_VENCP0]        = &gxbb_vclk2_vencp0.hw,
+               [CLKID_VCLK2_VENCP1]        = &gxbb_vclk2_vencp1.hw,
+               [CLKID_GCLK_VENCI_INT0]     = &gxbb_gclk_venci_int0.hw,
+               [CLKID_GCLK_VENCI_INT]      = &gxbb_gclk_vencp_int.hw,
+               [CLKID_DAC_CLK]             = &gxbb_dac_clk.hw,
+               [CLKID_AOCLK_GATE]          = &gxbb_aoclk_gate.hw,
+               [CLKID_IEC958_GATE]         = &gxbb_iec958_gate.hw,
+               [CLKID_ENC480P]             = &gxbb_enc480p.hw,
+               [CLKID_RNG1]                = &gxbb_rng1.hw,
+               [CLKID_GCLK_VENCI_INT1]     = &gxbb_gclk_venci_int1.hw,
+               [CLKID_VCLK2_VENCLMCC]      = &gxbb_vclk2_venclmcc.hw,
+               [CLKID_VCLK2_VENCL]         = &gxbb_vclk2_vencl.hw,
+               [CLKID_VCLK_OTHER]          = &gxbb_vclk_other.hw,
+               [CLKID_EDP]                 = &gxbb_edp.hw,
+               [CLKID_AO_MEDIA_CPU]        = &gxbb_ao_media_cpu.hw,
+               [CLKID_AO_AHB_SRAM]         = &gxbb_ao_ahb_sram.hw,
+               [CLKID_AO_AHB_BUS]          = &gxbb_ao_ahb_bus.hw,
+               [CLKID_AO_IFACE]            = &gxbb_ao_iface.hw,
+               [CLKID_AO_I2C]              = &gxbb_ao_i2c.hw,
+               [CLKID_SD_EMMC_A]           = &gxbb_emmc_a.hw,
+               [CLKID_SD_EMMC_B]           = &gxbb_emmc_b.hw,
+               [CLKID_SD_EMMC_C]           = &gxbb_emmc_c.hw,
+               [CLKID_SAR_ADC_CLK]         = &gxbb_sar_adc_clk.hw,
+               [CLKID_SAR_ADC_SEL]         = &gxbb_sar_adc_clk_sel.hw,
+               [CLKID_SAR_ADC_DIV]         = &gxbb_sar_adc_clk_div.hw,
+               [CLKID_MALI_0_SEL]          = &gxbb_mali_0_sel.hw,
+               [CLKID_MALI_0_DIV]          = &gxbb_mali_0_div.hw,
+               [CLKID_MALI_0]              = &gxbb_mali_0.hw,
+               [CLKID_MALI_1_SEL]          = &gxbb_mali_1_sel.hw,
+               [CLKID_MALI_1_DIV]          = &gxbb_mali_1_div.hw,
+               [CLKID_MALI_1]              = &gxbb_mali_1.hw,
+               [CLKID_MALI]                = &gxbb_mali.hw,
+               [CLKID_CTS_AMCLK]           = &gxbb_cts_amclk.hw,
+               [CLKID_CTS_AMCLK_SEL]       = &gxbb_cts_amclk_sel.hw,
+               [CLKID_CTS_AMCLK_DIV]       = &gxbb_cts_amclk_div.hw,
+               [CLKID_CTS_MCLK_I958]       = &gxbb_cts_mclk_i958.hw,
+               [CLKID_CTS_MCLK_I958_SEL]   = &gxbb_cts_mclk_i958_sel.hw,
+               [CLKID_CTS_MCLK_I958_DIV]   = &gxbb_cts_mclk_i958_div.hw,
+               [CLKID_CTS_I958]            = &gxbb_cts_i958.hw,
        },
        .num = NR_CLKS,
 };
@@ -810,13 +1291,20 @@ static struct meson_clk_pll *const gxbb_clk_plls[] = {
        &gxbb_gp0_pll,
 };
 
+static struct meson_clk_pll *const gxl_clk_plls[] = {
+       &gxbb_fixed_pll,
+       &gxbb_hdmi_pll,
+       &gxbb_sys_pll,
+       &gxl_gp0_pll,
+};
+
 static struct meson_clk_mpll *const gxbb_clk_mplls[] = {
        &gxbb_mpll0,
        &gxbb_mpll1,
        &gxbb_mpll2,
 };
 
-static struct clk_gate *gxbb_clk_gates[] = {
+static struct clk_gate *const gxbb_clk_gates[] = {
        &gxbb_clk81,
        &gxbb_ddr,
        &gxbb_dos,
@@ -900,16 +1388,105 @@ static struct clk_gate *gxbb_clk_gates[] = {
        &gxbb_emmc_b,
        &gxbb_emmc_c,
        &gxbb_sar_adc_clk,
+       &gxbb_mali_0,
+       &gxbb_mali_1,
+       &gxbb_cts_amclk,
+       &gxbb_cts_mclk_i958,
+};
+
+static struct clk_mux *const gxbb_clk_muxes[] = {
+       &gxbb_mpeg_clk_sel,
+       &gxbb_sar_adc_clk_sel,
+       &gxbb_mali_0_sel,
+       &gxbb_mali_1_sel,
+       &gxbb_mali,
+       &gxbb_cts_amclk_sel,
+       &gxbb_cts_mclk_i958_sel,
+       &gxbb_cts_i958,
+};
+
+static struct clk_divider *const gxbb_clk_dividers[] = {
+       &gxbb_mpeg_clk_div,
+       &gxbb_sar_adc_clk_div,
+       &gxbb_mali_0_div,
+       &gxbb_mali_1_div,
+       &gxbb_cts_mclk_i958_div,
+};
+
+static struct meson_clk_audio_divider *const gxbb_audio_dividers[] = {
+       &gxbb_cts_amclk_div,
+};
+
+struct clkc_data {
+       struct clk_gate *const *clk_gates;
+       unsigned int clk_gates_count;
+       struct meson_clk_mpll *const *clk_mplls;
+       unsigned int clk_mplls_count;
+       struct meson_clk_pll *const *clk_plls;
+       unsigned int clk_plls_count;
+       struct clk_mux *const *clk_muxes;
+       unsigned int clk_muxes_count;
+       struct clk_divider *const *clk_dividers;
+       unsigned int clk_dividers_count;
+       struct meson_clk_audio_divider *const *clk_audio_dividers;
+       unsigned int clk_audio_dividers_count;
+       struct meson_clk_cpu *cpu_clk;
+       struct clk_hw_onecell_data *hw_onecell_data;
+};
+
+static const struct clkc_data gxbb_clkc_data = {
+       .clk_gates = gxbb_clk_gates,
+       .clk_gates_count = ARRAY_SIZE(gxbb_clk_gates),
+       .clk_mplls = gxbb_clk_mplls,
+       .clk_mplls_count = ARRAY_SIZE(gxbb_clk_mplls),
+       .clk_plls = gxbb_clk_plls,
+       .clk_plls_count = ARRAY_SIZE(gxbb_clk_plls),
+       .clk_muxes = gxbb_clk_muxes,
+       .clk_muxes_count = ARRAY_SIZE(gxbb_clk_muxes),
+       .clk_dividers = gxbb_clk_dividers,
+       .clk_dividers_count = ARRAY_SIZE(gxbb_clk_dividers),
+       .clk_audio_dividers = gxbb_audio_dividers,
+       .clk_audio_dividers_count = ARRAY_SIZE(gxbb_audio_dividers),
+       .cpu_clk = &gxbb_cpu_clk,
+       .hw_onecell_data = &gxbb_hw_onecell_data,
+};
+
+static const struct clkc_data gxl_clkc_data = {
+       .clk_gates = gxbb_clk_gates,
+       .clk_gates_count = ARRAY_SIZE(gxbb_clk_gates),
+       .clk_mplls = gxbb_clk_mplls,
+       .clk_mplls_count = ARRAY_SIZE(gxbb_clk_mplls),
+       .clk_plls = gxl_clk_plls,
+       .clk_plls_count = ARRAY_SIZE(gxl_clk_plls),
+       .clk_muxes = gxbb_clk_muxes,
+       .clk_muxes_count = ARRAY_SIZE(gxbb_clk_muxes),
+       .clk_dividers = gxbb_clk_dividers,
+       .clk_dividers_count = ARRAY_SIZE(gxbb_clk_dividers),
+       .clk_audio_dividers = gxbb_audio_dividers,
+       .clk_audio_dividers_count = ARRAY_SIZE(gxbb_audio_dividers),
+       .cpu_clk = &gxbb_cpu_clk,
+       .hw_onecell_data = &gxl_hw_onecell_data,
+};
+
+static const struct of_device_id clkc_match_table[] = {
+       { .compatible = "amlogic,gxbb-clkc", .data = &gxbb_clkc_data },
+       { .compatible = "amlogic,gxl-clkc", .data = &gxl_clkc_data },
+       {},
 };
 
 static int gxbb_clkc_probe(struct platform_device *pdev)
 {
+       const struct clkc_data *clkc_data;
        void __iomem *clk_base;
        int ret, clkid, i;
        struct clk_hw *parent_hw;
        struct clk *parent_clk;
        struct device *dev = &pdev->dev;
 
+       clkc_data = of_device_get_match_data(&pdev->dev);
+       if (!clkc_data)
+               return -EINVAL;
+
        /*  Generic clocks and PLLs */
        clk_base = of_iomap(dev->of_node, 0);
        if (!clk_base) {
@@ -918,34 +1495,45 @@ static int gxbb_clkc_probe(struct platform_device *pdev)
        }
 
        /* Populate base address for PLLs */
-       for (i = 0; i < ARRAY_SIZE(gxbb_clk_plls); i++)
-               gxbb_clk_plls[i]->base = clk_base;
+       for (i = 0; i < clkc_data->clk_plls_count; i++)
+               clkc_data->clk_plls[i]->base = clk_base;
 
        /* Populate base address for MPLLs */
-       for (i = 0; i < ARRAY_SIZE(gxbb_clk_mplls); i++)
-               gxbb_clk_mplls[i]->base = clk_base;
+       for (i = 0; i < clkc_data->clk_mplls_count; i++)
+               clkc_data->clk_mplls[i]->base = clk_base;
 
        /* Populate the base address for CPU clk */
-       gxbb_cpu_clk.base = clk_base;
+       clkc_data->cpu_clk->base = clk_base;
+
+       /* Populate base address for gates */
+       for (i = 0; i < clkc_data->clk_gates_count; i++)
+               clkc_data->clk_gates[i]->reg = clk_base +
+                       (u64)clkc_data->clk_gates[i]->reg;
 
-       /* Populate the base address for the MPEG clks */
-       gxbb_mpeg_clk_sel.reg = clk_base + (u64)gxbb_mpeg_clk_sel.reg;
-       gxbb_mpeg_clk_div.reg = clk_base + (u64)gxbb_mpeg_clk_div.reg;
+       /* Populate base address for muxes */
+       for (i = 0; i < clkc_data->clk_muxes_count; i++)
+               clkc_data->clk_muxes[i]->reg = clk_base +
+                       (u64)clkc_data->clk_muxes[i]->reg;
 
-       /* Populate the base address for the SAR ADC clks */
-       gxbb_sar_adc_clk_sel.reg = clk_base + (u64)gxbb_sar_adc_clk_sel.reg;
-       gxbb_sar_adc_clk_div.reg = clk_base + (u64)gxbb_sar_adc_clk_div.reg;
+       /* Populate base address for dividers */
+       for (i = 0; i < clkc_data->clk_dividers_count; i++)
+               clkc_data->clk_dividers[i]->reg = clk_base +
+                       (u64)clkc_data->clk_dividers[i]->reg;
 
-       /* Populate base address for gates */
-       for (i = 0; i < ARRAY_SIZE(gxbb_clk_gates); i++)
-               gxbb_clk_gates[i]->reg = clk_base +
-                       (u64)gxbb_clk_gates[i]->reg;
+       /* Populate base address for the audio dividers */
+       for (i = 0; i < clkc_data->clk_audio_dividers_count; i++)
+               clkc_data->clk_audio_dividers[i]->base = clk_base;
 
        /*
         * register all clks
         */
-       for (clkid = 0; clkid < NR_CLKS; clkid++) {
-               ret = devm_clk_hw_register(dev, gxbb_hw_onecell_data.hws[clkid]);
+       for (clkid = 0; clkid < clkc_data->hw_onecell_data->num; clkid++) {
+               /* array might be sparse */
+               if (!clkc_data->hw_onecell_data->hws[clkid])
+                       continue;
+
+               ret = devm_clk_hw_register(dev,
+                                       clkc_data->hw_onecell_data->hws[clkid]);
                if (ret)
                        goto iounmap;
        }
@@ -964,9 +1552,9 @@ static int gxbb_clkc_probe(struct platform_device *pdev)
         * a new clk_hw, and this hack will no longer work. Releasing the ccr
         * feature before that time solves the problem :-)
         */
-       parent_hw = clk_hw_get_parent(&gxbb_cpu_clk.hw);
+       parent_hw = clk_hw_get_parent(&clkc_data->cpu_clk->hw);
        parent_clk = parent_hw->clk;
-       ret = clk_notifier_register(parent_clk, &gxbb_cpu_clk.clk_nb);
+       ret = clk_notifier_register(parent_clk, &clkc_data->cpu_clk->clk_nb);
        if (ret) {
                pr_err("%s: failed to register clock notifier for cpu_clk\n",
                                __func__);
@@ -974,23 +1562,18 @@ static int gxbb_clkc_probe(struct platform_device *pdev)
        }
 
        return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
-                       &gxbb_hw_onecell_data);
+                       clkc_data->hw_onecell_data);
 
 iounmap:
        iounmap(clk_base);
        return ret;
 }
 
-static const struct of_device_id gxbb_clkc_match_table[] = {
-       { .compatible = "amlogic,gxbb-clkc" },
-       { }
-};
-
 static struct platform_driver gxbb_driver = {
        .probe          = gxbb_clkc_probe,
        .driver         = {
                .name   = "gxbb-clkc",
-               .of_match_table = gxbb_clkc_match_table,
+               .of_match_table = clkc_match_table,
        },
 };
 
index cbd62e46bb5b8fd8be7d73176470a7b7c9fd016c..93b8f07ee7af8c4ddda7077c80013632a716e748 100644 (file)
@@ -71,6 +71,8 @@
 #define HHI_GP0_PLL_CNTL2              0x44 /* 0x11 offset in data sheet */
 #define HHI_GP0_PLL_CNTL3              0x48 /* 0x12 offset in data sheet */
 #define HHI_GP0_PLL_CNTL4              0x4c /* 0x13 offset in data sheet */
+#define        HHI_GP0_PLL_CNTL5               0x50 /* 0x14 offset in data sheet */
+#define        HHI_GP0_PLL_CNTL1               0x58 /* 0x16 offset in data sheet */
 
 #define HHI_XTAL_DIVN_CNTL             0xbc /* 0x2f offset in data sheet */
 #define HHI_TIMER90K                   0xec /* 0x3b offset in data sheet */
 /* CLKID_FCLK_DIV4 */
 #define CLKID_FCLK_DIV5                  7
 #define CLKID_FCLK_DIV7                  8
-#define CLKID_GP0_PLL            9
+/* CLKID_GP0_PLL */
 #define CLKID_MPEG_SEL           10
 #define CLKID_MPEG_DIV           11
 /* CLKID_CLK81 */
 #define CLKID_I2S_SPDIF                  35
 /* CLKID_ETH */
 #define CLKID_DEMUX              37
-#define CLKID_AIU_GLUE           38
+/* CLKID_AIU_GLUE */
 #define CLKID_IEC958             39
-#define CLKID_I2S_OUT            40
+/* CLKID_I2S_OUT */
 #define CLKID_AMCLK              41
 #define CLKID_AIFIFO2            42
 #define CLKID_MIXER              43
-#define CLKID_MIXER_IFACE        44
+/* CLKID_MIXER_IFACE */
 #define CLKID_ADC                45
 #define CLKID_BLKMV              46
-#define CLKID_AIU                47
+/* CLKID_AIU */
 #define CLKID_UART1              48
 #define CLKID_G2D                49
 /* CLKID_USB0 */
 /* CLKID_GCLK_VENCI_INT0 */
 #define CLKID_GCLK_VENCI_INT     78
 #define CLKID_DAC_CLK            79
-#define CLKID_AOCLK_GATE         80
+/* CLKID_AOCLK_GATE */
 #define CLKID_IEC958_GATE        81
 #define CLKID_ENC480P            82
 #define CLKID_RNG1               83
 /* CLKID_SAR_ADC_CLK */
 /* CLKID_SAR_ADC_SEL */
 #define CLKID_SAR_ADC_DIV        99
+/* CLKID_MALI_0_SEL */
+#define CLKID_MALI_0_DIV        101
+/* CLKID_MALI_0        */
+/* CLKID_MALI_1_SEL */
+#define CLKID_MALI_1_DIV        104
+/* CLKID_MALI_1        */
+/* CLKID_MALI  */
+#define CLKID_CTS_AMCLK                  107
+#define CLKID_CTS_AMCLK_SEL      108
+#define CLKID_CTS_AMCLK_DIV      109
+#define CLKID_CTS_MCLK_I958      110
+#define CLKID_CTS_MCLK_I958_SEL          111
+#define CLKID_CTS_MCLK_I958_DIV          112
+#define CLKID_CTS_I958           113
 
-#define NR_CLKS                          100
+#define NR_CLKS                          114
 
 /* include the CLKIDs that have been made part of the stable DT binding */
 #include <dt-bindings/clock/gxbb-clkc.h>
index 888494d4fb8acb108ad40f271aa4a5d9dd709d3a..e9985503165ce87a1e1aabd179e49281ce22f145 100644 (file)
@@ -245,6 +245,96 @@ static struct clk_fixed_factor meson8b_fclk_div7 = {
        },
 };
 
+static struct meson_clk_mpll meson8b_mpll0 = {
+       .sdm = {
+               .reg_off = HHI_MPLL_CNTL7,
+               .shift   = 0,
+               .width   = 14,
+       },
+       .sdm_en = {
+               .reg_off = HHI_MPLL_CNTL7,
+               .shift   = 15,
+               .width   = 1,
+       },
+       .n2 = {
+               .reg_off = HHI_MPLL_CNTL7,
+               .shift   = 16,
+               .width   = 9,
+       },
+       .en = {
+               .reg_off = HHI_MPLL_CNTL7,
+               .shift   = 14,
+               .width   = 1,
+       },
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "mpll0",
+               .ops = &meson_clk_mpll_ops,
+               .parent_names = (const char *[]){ "fixed_pll" },
+               .num_parents = 1,
+       },
+};
+
+static struct meson_clk_mpll meson8b_mpll1 = {
+       .sdm = {
+               .reg_off = HHI_MPLL_CNTL8,
+               .shift   = 0,
+               .width   = 14,
+       },
+       .sdm_en = {
+               .reg_off = HHI_MPLL_CNTL8,
+               .shift   = 15,
+               .width   = 1,
+       },
+       .n2 = {
+               .reg_off = HHI_MPLL_CNTL8,
+               .shift   = 16,
+               .width   = 9,
+       },
+       .en = {
+               .reg_off = HHI_MPLL_CNTL8,
+               .shift   = 14,
+               .width   = 1,
+       },
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "mpll1",
+               .ops = &meson_clk_mpll_ops,
+               .parent_names = (const char *[]){ "fixed_pll" },
+               .num_parents = 1,
+       },
+};
+
+static struct meson_clk_mpll meson8b_mpll2 = {
+       .sdm = {
+               .reg_off = HHI_MPLL_CNTL9,
+               .shift   = 0,
+               .width   = 14,
+       },
+       .sdm_en = {
+               .reg_off = HHI_MPLL_CNTL9,
+               .shift   = 15,
+               .width   = 1,
+       },
+       .n2 = {
+               .reg_off = HHI_MPLL_CNTL9,
+               .shift   = 16,
+               .width   = 9,
+       },
+       .en = {
+               .reg_off = HHI_MPLL_CNTL9,
+               .shift   = 14,
+               .width   = 1,
+       },
+       .lock = &clk_lock,
+       .hw.init = &(struct clk_init_data){
+               .name = "mpll2",
+               .ops = &meson_clk_mpll_ops,
+               .parent_names = (const char *[]){ "fixed_pll" },
+               .num_parents = 1,
+       },
+};
+
 /*
  * FIXME cpu clocks and the legacy composite clocks (e.g. clk81) are both PLL
  * post-dividers and should be modeled with their respective PLLs via the
@@ -491,6 +581,9 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
                [CLKID_AO_AHB_SRAM]         = &meson8b_ao_ahb_sram.hw,
                [CLKID_AO_AHB_BUS]          = &meson8b_ao_ahb_bus.hw,
                [CLKID_AO_IFACE]            = &meson8b_ao_iface.hw,
+               [CLKID_MPLL0]               = &meson8b_mpll0.hw,
+               [CLKID_MPLL1]               = &meson8b_mpll1.hw,
+               [CLKID_MPLL2]               = &meson8b_mpll2.hw,
        },
        .num = CLK_NR_CLKS,
 };
@@ -501,7 +594,13 @@ static struct meson_clk_pll *const meson8b_clk_plls[] = {
        &meson8b_sys_pll,
 };
 
-static struct clk_gate *meson8b_clk_gates[] = {
+static struct meson_clk_mpll *const meson8b_clk_mplls[] = {
+       &meson8b_mpll0,
+       &meson8b_mpll1,
+       &meson8b_mpll2,
+};
+
+static struct clk_gate *const meson8b_clk_gates[] = {
        &meson8b_clk81,
        &meson8b_ddr,
        &meson8b_dos,
@@ -582,6 +681,14 @@ static struct clk_gate *meson8b_clk_gates[] = {
        &meson8b_ao_iface,
 };
 
+static struct clk_mux *const meson8b_clk_muxes[] = {
+       &meson8b_mpeg_clk_sel,
+};
+
+static struct clk_divider *const meson8b_clk_dividers[] = {
+       &meson8b_mpeg_clk_div,
+};
+
 static int meson8b_clkc_probe(struct platform_device *pdev)
 {
        void __iomem *clk_base;
@@ -601,18 +708,28 @@ static int meson8b_clkc_probe(struct platform_device *pdev)
        for (i = 0; i < ARRAY_SIZE(meson8b_clk_plls); i++)
                meson8b_clk_plls[i]->base = clk_base;
 
+       /* Populate base address for MPLLs */
+       for (i = 0; i < ARRAY_SIZE(meson8b_clk_mplls); i++)
+               meson8b_clk_mplls[i]->base = clk_base;
+
        /* Populate the base address for CPU clk */
        meson8b_cpu_clk.base = clk_base;
 
-       /* Populate the base address for the MPEG clks */
-       meson8b_mpeg_clk_sel.reg = clk_base + (u32)meson8b_mpeg_clk_sel.reg;
-       meson8b_mpeg_clk_div.reg = clk_base + (u32)meson8b_mpeg_clk_div.reg;
-
        /* Populate base address for gates */
        for (i = 0; i < ARRAY_SIZE(meson8b_clk_gates); i++)
                meson8b_clk_gates[i]->reg = clk_base +
                        (u32)meson8b_clk_gates[i]->reg;
 
+       /* Populate base address for muxes */
+       for (i = 0; i < ARRAY_SIZE(meson8b_clk_muxes); i++)
+               meson8b_clk_muxes[i]->reg = clk_base +
+                       (u32)meson8b_clk_muxes[i]->reg;
+
+       /* Populate base address for dividers */
+       for (i = 0; i < ARRAY_SIZE(meson8b_clk_dividers); i++)
+               meson8b_clk_dividers[i]->reg = clk_base +
+                       (u32)meson8b_clk_dividers[i]->reg;
+
        /*
         * register all clks
         * CLKID_UNUSED = 0, so skip it and start with CLKID_XTAL = 1
index 010e9582888d8b9f36c2a6723e3bd885b398bd6a..3881defc8644aebb06a37b80ee6a6997a878554a 100644 (file)
 #define HHI_SYS_PLL_CNTL               0x300 /* 0xc0 offset in data sheet */
 #define HHI_VID_PLL_CNTL               0x320 /* 0xc8 offset in data sheet */
 
+/*
+ * MPLL register offeset taken from the S905 datasheet. Vendor kernel source
+ * confirm these are the same for the S805.
+ */
+#define HHI_MPLL_CNTL                  0x280 /* 0xa0 offset in data sheet */
+#define HHI_MPLL_CNTL2                 0x284 /* 0xa1 offset in data sheet */
+#define HHI_MPLL_CNTL3                 0x288 /* 0xa2 offset in data sheet */
+#define HHI_MPLL_CNTL4                 0x28C /* 0xa3 offset in data sheet */
+#define HHI_MPLL_CNTL5                 0x290 /* 0xa4 offset in data sheet */
+#define HHI_MPLL_CNTL6                 0x294 /* 0xa5 offset in data sheet */
+#define HHI_MPLL_CNTL7                 0x298 /* 0xa6 offset in data sheet */
+#define HHI_MPLL_CNTL8                 0x29C /* 0xa7 offset in data sheet */
+#define HHI_MPLL_CNTL9                 0x2A0 /* 0xa8 offset in data sheet */
+#define HHI_MPLL_CNTL10                        0x2A4 /* 0xa9 offset in data sheet */
+
 /*
  * CLKID index values
  *
 #define CLKID_AO_AHB_SRAM      90
 #define CLKID_AO_AHB_BUS       91
 #define CLKID_AO_IFACE         92
+#define CLKID_MPLL0            93
+#define CLKID_MPLL1            94
+#define CLKID_MPLL2            95
 
-#define CLK_NR_CLKS            93
+#define CLK_NR_CLKS            96
 
 /* include the CLKIDs that have been made part of the stable DT binding */
 #include <dt-bindings/clock/meson8b-clkc.h>
index 044892b6534d93ed3427ea405f78117349136cf7..072aa38374ce9a2db26103b4ed83cfa8bcb70434 100644 (file)
@@ -186,11 +186,11 @@ static void __init of_cpu_clk_setup(struct device_node *node)
        for_each_node_by_type(dn, "cpu")
                ncpus++;
 
-       cpuclk = kzalloc(ncpus * sizeof(*cpuclk), GFP_KERNEL);
+       cpuclk = kcalloc(ncpus, sizeof(*cpuclk), GFP_KERNEL);
        if (WARN_ON(!cpuclk))
                goto cpuclk_out;
 
-       clks = kzalloc(ncpus * sizeof(*clks), GFP_KERNEL);
+       clks = kcalloc(ncpus, sizeof(*clks), GFP_KERNEL);
        if (WARN_ON(!clks))
                goto clks_out;
 
index 66be2e0c82b488df5c8be50d1f0bd28367e4eb5d..472c88b90256945e1d70b7c5574a6b38a237c432 100644 (file)
@@ -126,7 +126,7 @@ void __init mvebu_coreclk_setup(struct device_node *np,
        if (desc->get_refclk_freq)
                clk_data.clk_num += 1;
 
-       clk_data.clks = kzalloc(clk_data.clk_num * sizeof(struct clk *),
+       clk_data.clks = kcalloc(clk_data.clk_num, sizeof(*clk_data.clks),
                                GFP_KERNEL);
        if (WARN_ON(!clk_data.clks)) {
                iounmap(base);
@@ -270,7 +270,7 @@ void __init mvebu_clk_gating_setup(struct device_node *np,
                n++;
 
        ctrl->num_gates = n;
-       ctrl->gates = kzalloc(ctrl->num_gates * sizeof(struct clk *),
+       ctrl->gates = kcalloc(ctrl->num_gates, sizeof(*ctrl->gates),
                              GFP_KERNEL);
        if (WARN_ON(!ctrl->gates))
                goto gates_out;
index 3487c267833e40afbed8e31ecc93ed859785fa90..d990fe44aef33986609fd4d0e7398b3732228b86 100644 (file)
@@ -165,7 +165,7 @@ static int clk_smd_rpm_handoff(struct clk_smd_rpm *r)
        struct clk_smd_rpm_req req = {
                .key = cpu_to_le32(r->rpm_key),
                .nbytes = cpu_to_le32(sizeof(u32)),
-               .value = cpu_to_le32(INT_MAX),
+               .value = cpu_to_le32(r->branch ? 1 : INT_MAX),
        };
 
        ret = qcom_rpm_smd_write(r->rpm, QCOM_SMD_RPM_ACTIVE_STATE,
index 03f9d316f969126c201a42227180103b7d97903d..d523991c945f9d4cbcd047c8a7edbb405d0e85ba 100644 (file)
@@ -128,7 +128,7 @@ static void qcom_cc_gdsc_unregister(void *data)
 
 /*
  * Backwards compatibility with old DTs. Register a pass-through factor 1/1
- * clock to translate 'path' clk into 'name' clk and regsiter the 'path'
+ * clock to translate 'path' clk into 'name' clk and register the 'path'
  * clk as a fixed rate clock if it isn't present.
  */
 static int _qcom_cc_register_board_clk(struct device *dev, const char *path,
index 9b97246287a7305f6b54ff9e4809fda1e748abc7..352394d8fd8c2bd2dc61ffabc9fae5665c2620e7 100644 (file)
@@ -2944,6 +2944,7 @@ static struct gdsc venus_core0_gdsc = {
        .pd = {
                .name = "venus_core0",
        },
+       .parent = &venus_gdsc.pd,
        .pwrsts = PWRSTS_OFF_ON,
        .flags = HW_CTRL,
 };
@@ -2955,6 +2956,7 @@ static struct gdsc venus_core1_gdsc = {
        .pd = {
                .name = "venus_core1",
        },
+       .parent = &venus_gdsc.pd,
        .pwrsts = PWRSTS_OFF_ON,
        .flags = HW_CTRL,
 };
@@ -2986,7 +2988,7 @@ static struct gdsc vfe1_gdsc = {
        .cxcs = (unsigned int []){ 0x36ac },
        .cxc_count = 1,
        .pd = {
-               .name = "vfe0",
+               .name = "vfe1",
        },
        .parent = &camss_gdsc.pd,
        .pwrsts = PWRSTS_OFF_ON,
index bfffdb00df97254771b3c518a0fd824ffaf647b8..eaa98b488f015944c847274d7430205ec3cdf4a0 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/soc/renesas/rcar-rst.h>
+#include <linux/sys_soc.h>
 
 #include <dt-bindings/clock/r8a7795-cpg-mssr.h>
 
@@ -24,7 +25,7 @@
 
 enum clk_ids {
        /* Core Clock Outputs exported to DT */
-       LAST_DT_CORE_CLK = R8A7795_CLK_OSC,
+       LAST_DT_CORE_CLK = R8A7795_CLK_S0D12,
 
        /* External Input Clocks */
        CLK_EXTAL,
@@ -51,10 +52,10 @@ enum clk_ids {
        MOD_CLK_BASE
 };
 
-static const struct cpg_core_clk r8a7795_core_clks[] __initconst = {
+static struct cpg_core_clk r8a7795_core_clks[] __initdata = {
        /* External Clock Inputs */
-       DEF_INPUT("extal",  CLK_EXTAL),
-       DEF_INPUT("extalr", CLK_EXTALR),
+       DEF_INPUT("extal",      CLK_EXTAL),
+       DEF_INPUT("extalr",     CLK_EXTALR),
 
        /* Internal Core Clocks */
        DEF_BASE(".main",       CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL),
@@ -78,7 +79,12 @@ static const struct cpg_core_clk r8a7795_core_clks[] __initconst = {
        DEF_FIXED("zt",         R8A7795_CLK_ZT,    CLK_PLL1_DIV2,  4, 1),
        DEF_FIXED("zx",         R8A7795_CLK_ZX,    CLK_PLL1_DIV2,  2, 1),
        DEF_FIXED("s0d1",       R8A7795_CLK_S0D1,  CLK_S0,         1, 1),
+       DEF_FIXED("s0d2",       R8A7795_CLK_S0D2,  CLK_S0,         2, 1),
+       DEF_FIXED("s0d3",       R8A7795_CLK_S0D3,  CLK_S0,         3, 1),
        DEF_FIXED("s0d4",       R8A7795_CLK_S0D4,  CLK_S0,         4, 1),
+       DEF_FIXED("s0d6",       R8A7795_CLK_S0D6,  CLK_S0,         6, 1),
+       DEF_FIXED("s0d8",       R8A7795_CLK_S0D8,  CLK_S0,         8, 1),
+       DEF_FIXED("s0d12",      R8A7795_CLK_S0D12, CLK_S0,        12, 1),
        DEF_FIXED("s1d1",       R8A7795_CLK_S1D1,  CLK_S1,         1, 1),
        DEF_FIXED("s1d2",       R8A7795_CLK_S1D2,  CLK_S1,         2, 1),
        DEF_FIXED("s1d4",       R8A7795_CLK_S1D4,  CLK_S1,         4, 1),
@@ -89,29 +95,29 @@ static const struct cpg_core_clk r8a7795_core_clks[] __initconst = {
        DEF_FIXED("s3d2",       R8A7795_CLK_S3D2,  CLK_S3,         2, 1),
        DEF_FIXED("s3d4",       R8A7795_CLK_S3D4,  CLK_S3,         4, 1),
 
-       DEF_GEN3_SD("sd0",      R8A7795_CLK_SD0,   CLK_SDSRC,     0x0074),
-       DEF_GEN3_SD("sd1",      R8A7795_CLK_SD1,   CLK_SDSRC,     0x0078),
-       DEF_GEN3_SD("sd2",      R8A7795_CLK_SD2,   CLK_SDSRC,     0x0268),
-       DEF_GEN3_SD("sd3",      R8A7795_CLK_SD3,   CLK_SDSRC,     0x026c),
+       DEF_GEN3_SD("sd0",      R8A7795_CLK_SD0,   CLK_SDSRC,     0x074),
+       DEF_GEN3_SD("sd1",      R8A7795_CLK_SD1,   CLK_SDSRC,     0x078),
+       DEF_GEN3_SD("sd2",      R8A7795_CLK_SD2,   CLK_SDSRC,     0x268),
+       DEF_GEN3_SD("sd3",      R8A7795_CLK_SD3,   CLK_SDSRC,     0x26c),
 
        DEF_FIXED("cl",         R8A7795_CLK_CL,    CLK_PLL1_DIV2, 48, 1),
        DEF_FIXED("cp",         R8A7795_CLK_CP,    CLK_EXTAL,      2, 1),
 
-       DEF_DIV6P1("mso",       R8A7795_CLK_MSO,   CLK_PLL1_DIV4, 0x014),
-       DEF_DIV6P1("hdmi",      R8A7795_CLK_HDMI,  CLK_PLL1_DIV4, 0x250),
        DEF_DIV6P1("canfd",     R8A7795_CLK_CANFD, CLK_PLL1_DIV4, 0x244),
        DEF_DIV6P1("csi0",      R8A7795_CLK_CSI0,  CLK_PLL1_DIV4, 0x00c),
+       DEF_DIV6P1("mso",       R8A7795_CLK_MSO,   CLK_PLL1_DIV4, 0x014),
+       DEF_DIV6P1("hdmi",      R8A7795_CLK_HDMI,  CLK_PLL1_DIV4, 0x250),
 
-       DEF_DIV6_RO("osc",      R8A7795_CLK_OSC,   CLK_EXTAL, CPG_RCKCR, 8),
+       DEF_DIV6_RO("osc",      R8A7795_CLK_OSC,   CLK_EXTAL, CPG_RCKCR,  8),
        DEF_DIV6_RO("r_int",    CLK_RINT,          CLK_EXTAL, CPG_RCKCR, 32),
 
-       DEF_BASE("r",           R8A7795_CLK_R, CLK_TYPE_GEN3_R, CLK_RINT),
+       DEF_BASE("r",           R8A7795_CLK_R,     CLK_TYPE_GEN3_R, CLK_RINT),
 };
 
-static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = {
-       DEF_MOD("fdp1-2",                117,   R8A7795_CLK_S2D1),
-       DEF_MOD("fdp1-1",                118,   R8A7795_CLK_S2D1),
-       DEF_MOD("fdp1-0",                119,   R8A7795_CLK_S2D1),
+static struct mssr_mod_clk r8a7795_mod_clks[] __initdata = {
+       DEF_MOD("fdp1-2",                117,   R8A7795_CLK_S2D1), /* ES1.x */
+       DEF_MOD("fdp1-1",                118,   R8A7795_CLK_S0D1),
+       DEF_MOD("fdp1-0",                119,   R8A7795_CLK_S0D1),
        DEF_MOD("scif5",                 202,   R8A7795_CLK_S3D4),
        DEF_MOD("scif4",                 203,   R8A7795_CLK_S3D4),
        DEF_MOD("scif3",                 204,   R8A7795_CLK_S3D4),
@@ -121,9 +127,9 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = {
        DEF_MOD("msiof2",                209,   R8A7795_CLK_MSO),
        DEF_MOD("msiof1",                210,   R8A7795_CLK_MSO),
        DEF_MOD("msiof0",                211,   R8A7795_CLK_MSO),
-       DEF_MOD("sys-dmac2",             217,   R8A7795_CLK_S3D1),
-       DEF_MOD("sys-dmac1",             218,   R8A7795_CLK_S3D1),
-       DEF_MOD("sys-dmac0",             219,   R8A7795_CLK_S3D1),
+       DEF_MOD("sys-dmac2",             217,   R8A7795_CLK_S0D3),
+       DEF_MOD("sys-dmac1",             218,   R8A7795_CLK_S0D3),
+       DEF_MOD("sys-dmac0",             219,   R8A7795_CLK_S0D3),
        DEF_MOD("cmt3",                  300,   R8A7795_CLK_R),
        DEF_MOD("cmt2",                  301,   R8A7795_CLK_R),
        DEF_MOD("cmt1",                  302,   R8A7795_CLK_R),
@@ -135,15 +141,15 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = {
        DEF_MOD("sdif0",                 314,   R8A7795_CLK_SD0),
        DEF_MOD("pcie1",                 318,   R8A7795_CLK_S3D1),
        DEF_MOD("pcie0",                 319,   R8A7795_CLK_S3D1),
-       DEF_MOD("usb3-if1",              327,   R8A7795_CLK_S3D1),
+       DEF_MOD("usb3-if1",              327,   R8A7795_CLK_S3D1), /* ES1.x */
        DEF_MOD("usb3-if0",              328,   R8A7795_CLK_S3D1),
        DEF_MOD("usb-dmac0",             330,   R8A7795_CLK_S3D1),
        DEF_MOD("usb-dmac1",             331,   R8A7795_CLK_S3D1),
-       DEF_MOD("rwdt0",                 402,   R8A7795_CLK_R),
+       DEF_MOD("rwdt",                  402,   R8A7795_CLK_R),
        DEF_MOD("intc-ex",               407,   R8A7795_CLK_CP),
        DEF_MOD("intc-ap",               408,   R8A7795_CLK_S3D1),
-       DEF_MOD("audmac0",               502,   R8A7795_CLK_S3D4),
-       DEF_MOD("audmac1",               501,   R8A7795_CLK_S3D4),
+       DEF_MOD("audmac1",               501,   R8A7795_CLK_S0D3),
+       DEF_MOD("audmac0",               502,   R8A7795_CLK_S0D3),
        DEF_MOD("drif7",                 508,   R8A7795_CLK_S3D2),
        DEF_MOD("drif6",                 509,   R8A7795_CLK_S3D2),
        DEF_MOD("drif5",                 510,   R8A7795_CLK_S3D2),
@@ -159,35 +165,35 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = {
        DEF_MOD("hscif0",                520,   R8A7795_CLK_S3D1),
        DEF_MOD("thermal",               522,   R8A7795_CLK_CP),
        DEF_MOD("pwm",                   523,   R8A7795_CLK_S3D4),
-       DEF_MOD("fcpvd3",                600,   R8A7795_CLK_S2D1),
-       DEF_MOD("fcpvd2",                601,   R8A7795_CLK_S2D1),
-       DEF_MOD("fcpvd1",                602,   R8A7795_CLK_S2D1),
-       DEF_MOD("fcpvd0",                603,   R8A7795_CLK_S2D1),
-       DEF_MOD("fcpvb1",                606,   R8A7795_CLK_S2D1),
-       DEF_MOD("fcpvb0",                607,   R8A7795_CLK_S2D1),
-       DEF_MOD("fcpvi2",                609,   R8A7795_CLK_S2D1),
-       DEF_MOD("fcpvi1",                610,   R8A7795_CLK_S2D1),
-       DEF_MOD("fcpvi0",                611,   R8A7795_CLK_S2D1),
-       DEF_MOD("fcpf2",                 613,   R8A7795_CLK_S2D1),
-       DEF_MOD("fcpf1",                 614,   R8A7795_CLK_S2D1),
-       DEF_MOD("fcpf0",                 615,   R8A7795_CLK_S2D1),
-       DEF_MOD("fcpci1",                616,   R8A7795_CLK_S2D1),
-       DEF_MOD("fcpci0",                617,   R8A7795_CLK_S2D1),
-       DEF_MOD("fcpcs",                 619,   R8A7795_CLK_S2D1),
-       DEF_MOD("vspd3",                 620,   R8A7795_CLK_S2D1),
-       DEF_MOD("vspd2",                 621,   R8A7795_CLK_S2D1),
-       DEF_MOD("vspd1",                 622,   R8A7795_CLK_S2D1),
-       DEF_MOD("vspd0",                 623,   R8A7795_CLK_S2D1),
-       DEF_MOD("vspbc",                 624,   R8A7795_CLK_S2D1),
-       DEF_MOD("vspbd",                 626,   R8A7795_CLK_S2D1),
-       DEF_MOD("vspi2",                 629,   R8A7795_CLK_S2D1),
-       DEF_MOD("vspi1",                 630,   R8A7795_CLK_S2D1),
-       DEF_MOD("vspi0",                 631,   R8A7795_CLK_S2D1),
+       DEF_MOD("fcpvd3",                600,   R8A7795_CLK_S2D1), /* ES1.x */
+       DEF_MOD("fcpvd2",                601,   R8A7795_CLK_S0D2),
+       DEF_MOD("fcpvd1",                602,   R8A7795_CLK_S0D2),
+       DEF_MOD("fcpvd0",                603,   R8A7795_CLK_S0D2),
+       DEF_MOD("fcpvb1",                606,   R8A7795_CLK_S0D1),
+       DEF_MOD("fcpvb0",                607,   R8A7795_CLK_S0D1),
+       DEF_MOD("fcpvi2",                609,   R8A7795_CLK_S2D1), /* ES1.x */
+       DEF_MOD("fcpvi1",                610,   R8A7795_CLK_S0D1),
+       DEF_MOD("fcpvi0",                611,   R8A7795_CLK_S0D1),
+       DEF_MOD("fcpf2",                 613,   R8A7795_CLK_S2D1), /* ES1.x */
+       DEF_MOD("fcpf1",                 614,   R8A7795_CLK_S0D1),
+       DEF_MOD("fcpf0",                 615,   R8A7795_CLK_S0D1),
+       DEF_MOD("fcpci1",                616,   R8A7795_CLK_S2D1), /* ES1.x */
+       DEF_MOD("fcpci0",                617,   R8A7795_CLK_S2D1), /* ES1.x */
+       DEF_MOD("fcpcs",                 619,   R8A7795_CLK_S0D1),
+       DEF_MOD("vspd3",                 620,   R8A7795_CLK_S2D1), /* ES1.x */
+       DEF_MOD("vspd2",                 621,   R8A7795_CLK_S0D2),
+       DEF_MOD("vspd1",                 622,   R8A7795_CLK_S0D2),
+       DEF_MOD("vspd0",                 623,   R8A7795_CLK_S0D2),
+       DEF_MOD("vspbc",                 624,   R8A7795_CLK_S0D1),
+       DEF_MOD("vspbd",                 626,   R8A7795_CLK_S0D1),
+       DEF_MOD("vspi2",                 629,   R8A7795_CLK_S2D1), /* ES1.x */
+       DEF_MOD("vspi1",                 630,   R8A7795_CLK_S0D1),
+       DEF_MOD("vspi0",                 631,   R8A7795_CLK_S0D1),
        DEF_MOD("ehci2",                 701,   R8A7795_CLK_S3D4),
        DEF_MOD("ehci1",                 702,   R8A7795_CLK_S3D4),
        DEF_MOD("ehci0",                 703,   R8A7795_CLK_S3D4),
        DEF_MOD("hsusb",                 704,   R8A7795_CLK_S3D4),
-       DEF_MOD("csi21",                 713,   R8A7795_CLK_CSI0),
+       DEF_MOD("csi21",                 713,   R8A7795_CLK_CSI0), /* ES1.x */
        DEF_MOD("csi20",                 714,   R8A7795_CLK_CSI0),
        DEF_MOD("csi41",                 715,   R8A7795_CLK_CSI0),
        DEF_MOD("csi40",                 716,   R8A7795_CLK_CSI0),
@@ -198,16 +204,20 @@ static const struct mssr_mod_clk r8a7795_mod_clks[] __initconst = {
        DEF_MOD("lvds",                  727,   R8A7795_CLK_S0D4),
        DEF_MOD("hdmi1",                 728,   R8A7795_CLK_HDMI),
        DEF_MOD("hdmi0",                 729,   R8A7795_CLK_HDMI),
-       DEF_MOD("vin7",                  804,   R8A7795_CLK_S2D1),
-       DEF_MOD("vin6",                  805,   R8A7795_CLK_S2D1),
-       DEF_MOD("vin5",                  806,   R8A7795_CLK_S2D1),
-       DEF_MOD("vin4",                  807,   R8A7795_CLK_S2D1),
-       DEF_MOD("vin3",                  808,   R8A7795_CLK_S2D1),
-       DEF_MOD("vin2",                  809,   R8A7795_CLK_S2D1),
-       DEF_MOD("vin1",                  810,   R8A7795_CLK_S2D1),
-       DEF_MOD("vin0",                  811,   R8A7795_CLK_S2D1),
-       DEF_MOD("etheravb",              812,   R8A7795_CLK_S3D2),
+       DEF_MOD("vin7",                  804,   R8A7795_CLK_S0D2),
+       DEF_MOD("vin6",                  805,   R8A7795_CLK_S0D2),
+       DEF_MOD("vin5",                  806,   R8A7795_CLK_S0D2),
+       DEF_MOD("vin4",                  807,   R8A7795_CLK_S0D2),
+       DEF_MOD("vin3",                  808,   R8A7795_CLK_S0D2),
+       DEF_MOD("vin2",                  809,   R8A7795_CLK_S0D2),
+       DEF_MOD("vin1",                  810,   R8A7795_CLK_S0D2),
+       DEF_MOD("vin0",                  811,   R8A7795_CLK_S0D2),
+       DEF_MOD("etheravb",              812,   R8A7795_CLK_S0D6),
        DEF_MOD("sata0",                 815,   R8A7795_CLK_S3D2),
+       DEF_MOD("imr3",                  820,   R8A7795_CLK_S0D2),
+       DEF_MOD("imr2",                  821,   R8A7795_CLK_S0D2),
+       DEF_MOD("imr1",                  822,   R8A7795_CLK_S0D2),
+       DEF_MOD("imr0",                  823,   R8A7795_CLK_S0D2),
        DEF_MOD("gpio7",                 905,   R8A7795_CLK_CP),
        DEF_MOD("gpio6",                 906,   R8A7795_CLK_CP),
        DEF_MOD("gpio5",                 907,   R8A7795_CLK_CP),
@@ -310,6 +320,82 @@ static const struct rcar_gen3_cpg_pll_config cpg_pll_configs[16] __initconst = {
        { 2,            192,            192,    },
 };
 
+static const struct soc_device_attribute r8a7795es1[] __initconst = {
+       { .soc_id = "r8a7795", .revision = "ES1.*" },
+       { /* sentinel */ }
+};
+
+
+       /*
+        * Fixups for R-Car H3 ES1.x
+        */
+
+static const unsigned int r8a7795es1_mod_nullify[] __initconst = {
+       MOD_CLK_ID(326),                        /* USB-DMAC3-0 */
+       MOD_CLK_ID(329),                        /* USB-DMAC3-1 */
+       MOD_CLK_ID(700),                        /* EHCI/OHCI3 */
+       MOD_CLK_ID(705),                        /* HS-USB-IF3 */
+
+};
+
+static const struct mssr_mod_reparent r8a7795es1_mod_reparent[] __initconst = {
+       { MOD_CLK_ID(118), R8A7795_CLK_S2D1 },  /* FDP1-1 */
+       { MOD_CLK_ID(119), R8A7795_CLK_S2D1 },  /* FDP1-0 */
+       { MOD_CLK_ID(217), R8A7795_CLK_S3D1 },  /* SYS-DMAC2 */
+       { MOD_CLK_ID(218), R8A7795_CLK_S3D1 },  /* SYS-DMAC1 */
+       { MOD_CLK_ID(219), R8A7795_CLK_S3D1 },  /* SYS-DMAC0 */
+       { MOD_CLK_ID(501), R8A7795_CLK_S3D1 },  /* AUDMAC1 */
+       { MOD_CLK_ID(502), R8A7795_CLK_S3D1 },  /* AUDMAC0 */
+       { MOD_CLK_ID(601), R8A7795_CLK_S2D1 },  /* FCPVD2 */
+       { MOD_CLK_ID(602), R8A7795_CLK_S2D1 },  /* FCPVD1 */
+       { MOD_CLK_ID(603), R8A7795_CLK_S2D1 },  /* FCPVD0 */
+       { MOD_CLK_ID(606), R8A7795_CLK_S2D1 },  /* FCPVB1 */
+       { MOD_CLK_ID(607), R8A7795_CLK_S2D1 },  /* FCPVB0 */
+       { MOD_CLK_ID(610), R8A7795_CLK_S2D1 },  /* FCPVI1 */
+       { MOD_CLK_ID(611), R8A7795_CLK_S2D1 },  /* FCPVI0 */
+       { MOD_CLK_ID(614), R8A7795_CLK_S2D1 },  /* FCPF1 */
+       { MOD_CLK_ID(615), R8A7795_CLK_S2D1 },  /* FCPF0 */
+       { MOD_CLK_ID(619), R8A7795_CLK_S2D1 },  /* FCPCS */
+       { MOD_CLK_ID(621), R8A7795_CLK_S2D1 },  /* VSPD2 */
+       { MOD_CLK_ID(622), R8A7795_CLK_S2D1 },  /* VSPD1 */
+       { MOD_CLK_ID(623), R8A7795_CLK_S2D1 },  /* VSPD0 */
+       { MOD_CLK_ID(624), R8A7795_CLK_S2D1 },  /* VSPBC */
+       { MOD_CLK_ID(626), R8A7795_CLK_S2D1 },  /* VSPBD */
+       { MOD_CLK_ID(630), R8A7795_CLK_S2D1 },  /* VSPI1 */
+       { MOD_CLK_ID(631), R8A7795_CLK_S2D1 },  /* VSPI0 */
+       { MOD_CLK_ID(804), R8A7795_CLK_S2D1 },  /* VIN7 */
+       { MOD_CLK_ID(805), R8A7795_CLK_S2D1 },  /* VIN6 */
+       { MOD_CLK_ID(806), R8A7795_CLK_S2D1 },  /* VIN5 */
+       { MOD_CLK_ID(807), R8A7795_CLK_S2D1 },  /* VIN4 */
+       { MOD_CLK_ID(808), R8A7795_CLK_S2D1 },  /* VIN3 */
+       { MOD_CLK_ID(809), R8A7795_CLK_S2D1 },  /* VIN2 */
+       { MOD_CLK_ID(810), R8A7795_CLK_S2D1 },  /* VIN1 */
+       { MOD_CLK_ID(811), R8A7795_CLK_S2D1 },  /* VIN0 */
+       { MOD_CLK_ID(812), R8A7795_CLK_S3D2 },  /* EAVB-IF */
+       { MOD_CLK_ID(820), R8A7795_CLK_S2D1 },  /* IMR3 */
+       { MOD_CLK_ID(821), R8A7795_CLK_S2D1 },  /* IMR2 */
+       { MOD_CLK_ID(822), R8A7795_CLK_S2D1 },  /* IMR1 */
+       { MOD_CLK_ID(823), R8A7795_CLK_S2D1 },  /* IMR0 */
+};
+
+
+       /*
+        * Fixups for R-Car H3 ES2.x
+        */
+
+static const unsigned int r8a7795es2_mod_nullify[] __initconst = {
+       MOD_CLK_ID(117),                        /* FDP1-2 */
+       MOD_CLK_ID(327),                        /* USB3-IF1 */
+       MOD_CLK_ID(600),                        /* FCPVD3 */
+       MOD_CLK_ID(609),                        /* FCPVI2 */
+       MOD_CLK_ID(613),                        /* FCPF2 */
+       MOD_CLK_ID(616),                        /* FCPCI1 */
+       MOD_CLK_ID(617),                        /* FCPCI0 */
+       MOD_CLK_ID(620),                        /* VSPD3 */
+       MOD_CLK_ID(629),                        /* VSPI2 */
+       MOD_CLK_ID(713),                        /* CSI21 */
+};
+
 static int __init r8a7795_cpg_mssr_init(struct device *dev)
 {
        const struct rcar_gen3_cpg_pll_config *cpg_pll_config;
@@ -326,7 +412,26 @@ static int __init r8a7795_cpg_mssr_init(struct device *dev)
                return -EINVAL;
        }
 
-       return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR);
+       if (soc_device_match(r8a7795es1)) {
+               cpg_core_nullify_range(r8a7795_core_clks,
+                                      ARRAY_SIZE(r8a7795_core_clks),
+                                      R8A7795_CLK_S0D2, R8A7795_CLK_S0D12);
+               mssr_mod_nullify(r8a7795_mod_clks,
+                                ARRAY_SIZE(r8a7795_mod_clks),
+                                r8a7795es1_mod_nullify,
+                                ARRAY_SIZE(r8a7795es1_mod_nullify));
+               mssr_mod_reparent(r8a7795_mod_clks,
+                                 ARRAY_SIZE(r8a7795_mod_clks),
+                                 r8a7795es1_mod_reparent,
+                                 ARRAY_SIZE(r8a7795es1_mod_reparent));
+       } else {
+               mssr_mod_nullify(r8a7795_mod_clks,
+                                ARRAY_SIZE(r8a7795_mod_clks),
+                                r8a7795es2_mod_nullify,
+                                ARRAY_SIZE(r8a7795es2_mod_nullify));
+       }
+
+       return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode);
 }
 
 const struct cpg_mssr_info r8a7795_cpg_mssr_info __initconst = {
index 11e084a56b0d9005746e788843d27fc1ae21f466..9d114b31b0731b5ec691717a8519bc8ba2614218 100644 (file)
@@ -54,8 +54,8 @@ enum clk_ids {
 
 static const struct cpg_core_clk r8a7796_core_clks[] __initconst = {
        /* External Clock Inputs */
-       DEF_INPUT("extal",  CLK_EXTAL),
-       DEF_INPUT("extalr", CLK_EXTALR),
+       DEF_INPUT("extal",      CLK_EXTAL),
+       DEF_INPUT("extalr",     CLK_EXTALR),
 
        /* Internal Core Clocks */
        DEF_BASE(".main",       CLK_MAIN, CLK_TYPE_GEN3_MAIN, CLK_EXTAL),
@@ -95,10 +95,10 @@ static const struct cpg_core_clk r8a7796_core_clks[] __initconst = {
        DEF_FIXED("s3d2",       R8A7796_CLK_S3D2,  CLK_S3,         2, 1),
        DEF_FIXED("s3d4",       R8A7796_CLK_S3D4,  CLK_S3,         4, 1),
 
-       DEF_GEN3_SD("sd0",      R8A7796_CLK_SD0,   CLK_SDSRC,    0x0074),
-       DEF_GEN3_SD("sd1",      R8A7796_CLK_SD1,   CLK_SDSRC,    0x0078),
-       DEF_GEN3_SD("sd2",      R8A7796_CLK_SD2,   CLK_SDSRC,    0x0268),
-       DEF_GEN3_SD("sd3",      R8A7796_CLK_SD3,   CLK_SDSRC,    0x026c),
+       DEF_GEN3_SD("sd0",      R8A7796_CLK_SD0,   CLK_SDSRC,     0x074),
+       DEF_GEN3_SD("sd1",      R8A7796_CLK_SD1,   CLK_SDSRC,     0x078),
+       DEF_GEN3_SD("sd2",      R8A7796_CLK_SD2,   CLK_SDSRC,     0x268),
+       DEF_GEN3_SD("sd3",      R8A7796_CLK_SD3,   CLK_SDSRC,     0x26c),
 
        DEF_FIXED("cl",         R8A7796_CLK_CL,    CLK_PLL1_DIV2, 48, 1),
        DEF_FIXED("cp",         R8A7796_CLK_CP,    CLK_EXTAL,      2, 1),
@@ -135,7 +135,7 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = {
        DEF_MOD("sdif2",                 312,   R8A7796_CLK_SD2),
        DEF_MOD("sdif1",                 313,   R8A7796_CLK_SD1),
        DEF_MOD("sdif0",                 314,   R8A7796_CLK_SD0),
-       DEF_MOD("rwdt0",                 402,   R8A7796_CLK_R),
+       DEF_MOD("rwdt",                  402,   R8A7796_CLK_R),
        DEF_MOD("intc-ap",               408,   R8A7796_CLK_S3D1),
        DEF_MOD("drif7",                 508,   R8A7796_CLK_S3D2),
        DEF_MOD("drif6",                 509,   R8A7796_CLK_S3D2),
@@ -179,6 +179,8 @@ static const struct mssr_mod_clk r8a7796_mod_clks[] __initconst = {
        DEF_MOD("vin1",                  810,   R8A7796_CLK_S0D2),
        DEF_MOD("vin0",                  811,   R8A7796_CLK_S0D2),
        DEF_MOD("etheravb",              812,   R8A7796_CLK_S0D6),
+       DEF_MOD("imr1",                  822,   R8A7796_CLK_S0D2),
+       DEF_MOD("imr0",                  823,   R8A7796_CLK_S0D2),
        DEF_MOD("gpio7",                 905,   R8A7796_CLK_S3D4),
        DEF_MOD("gpio6",                 906,   R8A7796_CLK_S3D4),
        DEF_MOD("gpio5",                 907,   R8A7796_CLK_S3D4),
@@ -271,7 +273,7 @@ static int __init r8a7796_cpg_mssr_init(struct device *dev)
                return -EINVAL;
        }
 
-       return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR);
+       return rcar_gen3_cpg_init(cpg_pll_config, CLK_EXTALR, cpg_mode);
 }
 
 const struct cpg_mssr_info r8a7796_cpg_mssr_info __initconst = {
index 742f6dc7c15653ef5b51bc9d4f3da9b1ebe75c47..3dee900522b703bd650c5265b2314c1d3c522741 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/sys_soc.h>
 
 #include "renesas-cpg-mssr.h"
 #include "rcar-gen3-cpg.h"
@@ -247,6 +248,27 @@ static struct clk * __init cpg_sd_clk_register(const struct cpg_core_clk *core,
 
 static const struct rcar_gen3_cpg_pll_config *cpg_pll_config __initdata;
 static unsigned int cpg_clk_extalr __initdata;
+static u32 cpg_mode __initdata;
+static u32 cpg_quirks __initdata;
+
+#define PLL_ERRATA     BIT(0)          /* Missing PLL0/2/4 post-divider */
+#define RCKCR_CKSEL    BIT(1)          /* Manual RCLK parent selection */
+
+static const struct soc_device_attribute cpg_quirks_match[] __initconst = {
+       {
+               .soc_id = "r8a7795", .revision = "ES1.0",
+               .data = (void *)(PLL_ERRATA | RCKCR_CKSEL),
+       },
+       {
+               .soc_id = "r8a7795", .revision = "ES1.*",
+               .data = (void *)RCKCR_CKSEL,
+       },
+       {
+               .soc_id = "r8a7796", .revision = "ES1.0",
+               .data = (void *)RCKCR_CKSEL,
+       },
+       { /* sentinel */ }
+};
 
 struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev,
        const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
@@ -275,6 +297,8 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev,
                 */
                value = readl(base + CPG_PLL0CR);
                mult = (((value >> 24) & 0x7f) + 1) * 2;
+               if (cpg_quirks & PLL_ERRATA)
+                       mult *= 2;
                break;
 
        case CLK_TYPE_GEN3_PLL1:
@@ -290,6 +314,8 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev,
                 */
                value = readl(base + CPG_PLL2CR);
                mult = (((value >> 24) & 0x7f) + 1) * 2;
+               if (cpg_quirks & PLL_ERRATA)
+                       mult *= 2;
                break;
 
        case CLK_TYPE_GEN3_PLL3:
@@ -305,24 +331,33 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev,
                 */
                value = readl(base + CPG_PLL4CR);
                mult = (((value >> 24) & 0x7f) + 1) * 2;
+               if (cpg_quirks & PLL_ERRATA)
+                       mult *= 2;
                break;
 
        case CLK_TYPE_GEN3_SD:
                return cpg_sd_clk_register(core, base, __clk_get_name(parent));
 
        case CLK_TYPE_GEN3_R:
-               /*
-                * RINT is default.
-                * Only if EXTALR is populated, we switch to it.
-                */
-               value = readl(base + CPG_RCKCR) & 0x3f;
-
-               if (clk_get_rate(clks[cpg_clk_extalr])) {
-                       parent = clks[cpg_clk_extalr];
-                       value |= BIT(15);
+               if (cpg_quirks & RCKCR_CKSEL) {
+                       /*
+                        * RINT is default.
+                        * Only if EXTALR is populated, we switch to it.
+                        */
+                       value = readl(base + CPG_RCKCR) & 0x3f;
+
+                       if (clk_get_rate(clks[cpg_clk_extalr])) {
+                               parent = clks[cpg_clk_extalr];
+                               value |= BIT(15);
+                       }
+
+                       writel(value, base + CPG_RCKCR);
+                       break;
                }
 
-               writel(value, base + CPG_RCKCR);
+               /* Select parent clock of RCLK by MD28 */
+               if (cpg_mode & BIT(28))
+                       parent = clks[cpg_clk_extalr];
                break;
 
        default:
@@ -334,9 +369,16 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev,
 }
 
 int __init rcar_gen3_cpg_init(const struct rcar_gen3_cpg_pll_config *config,
-                             unsigned int clk_extalr)
+                             unsigned int clk_extalr, u32 mode)
 {
+       const struct soc_device_attribute *attr;
+
        cpg_pll_config = config;
        cpg_clk_extalr = clk_extalr;
+       cpg_mode = mode;
+       attr = soc_device_match(cpg_quirks_match);
+       if (attr)
+               cpg_quirks = (uintptr_t)attr->data;
+       pr_debug("%s: mode = 0x%x quirks = 0x%x\n", __func__, mode, cpg_quirks);
        return 0;
 }
index f788f481dd42cdf65ddfac1d4067836e87093f59..073be54b5d038ae39995c0450310fdbfe468091f 100644 (file)
@@ -37,6 +37,6 @@ struct clk *rcar_gen3_cpg_clk_register(struct device *dev,
        const struct cpg_core_clk *core, const struct cpg_mssr_info *info,
        struct clk **clks, void __iomem *base);
 int rcar_gen3_cpg_init(const struct rcar_gen3_cpg_pll_config *config,
-                      unsigned int clk_extalr);
+                      unsigned int clk_extalr, u32 mode);
 
 #endif
index eadcbd43ff88319ba68d99c0daa27b6908315b87..99eeec6f24ec6c6b29b60de7ad4c5644b37630d4 100644 (file)
@@ -265,6 +265,11 @@ static void __init cpg_mssr_register_core_clk(const struct cpg_core_clk *core,
        WARN_DEBUG(id >= priv->num_core_clks);
        WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT);
 
+       if (!core->name) {
+               /* Skip NULLified clock */
+               return;
+       }
+
        switch (core->type) {
        case CLK_TYPE_IN:
                clk = of_clk_get_by_name(priv->dev->of_node, core->name);
@@ -335,6 +340,11 @@ static void __init cpg_mssr_register_mod_clk(const struct mssr_mod_clk *mod,
        WARN_DEBUG(mod->parent >= priv->num_core_clks + priv->num_mod_clks);
        WARN_DEBUG(PTR_ERR(priv->clks[id]) != -ENOENT);
 
+       if (!mod->name) {
+               /* Skip NULLified clock */
+               return;
+       }
+
        parent = priv->clks[mod->parent];
        if (IS_ERR(parent)) {
                clk = parent;
@@ -734,5 +744,45 @@ static int __init cpg_mssr_init(void)
 
 subsys_initcall(cpg_mssr_init);
 
+void __init cpg_core_nullify_range(struct cpg_core_clk *core_clks,
+                                  unsigned int num_core_clks,
+                                  unsigned int first_clk,
+                                  unsigned int last_clk)
+{
+       unsigned int i;
+
+       for (i = 0; i < num_core_clks; i++)
+               if (core_clks[i].id >= first_clk &&
+                   core_clks[i].id <= last_clk)
+                       core_clks[i].name = NULL;
+}
+
+void __init mssr_mod_nullify(struct mssr_mod_clk *mod_clks,
+                            unsigned int num_mod_clks,
+                            const unsigned int *clks, unsigned int n)
+{
+       unsigned int i, j;
+
+       for (i = 0, j = 0; i < num_mod_clks && j < n; i++)
+               if (mod_clks[i].id == clks[j]) {
+                       mod_clks[i].name = NULL;
+                       j++;
+               }
+}
+
+void __init mssr_mod_reparent(struct mssr_mod_clk *mod_clks,
+                             unsigned int num_mod_clks,
+                             const struct mssr_mod_reparent *clks,
+                             unsigned int n)
+{
+       unsigned int i, j;
+
+       for (i = 0, j = 0; i < num_mod_clks && j < n; i++)
+               if (mod_clks[i].id == clks[j].clk) {
+                       mod_clks[i].parent = clks[j].parent;
+                       j++;
+               }
+}
+
 MODULE_DESCRIPTION("Renesas CPG/MSSR Driver");
 MODULE_LICENSE("GPL v2");
index 4bb7a80c6469e12eebed9f0dee0916657bad3477..148f4f0aa2a487b05da154fcde6e7d626bdd58fc 100644 (file)
@@ -134,4 +134,26 @@ extern const struct cpg_mssr_info r8a7743_cpg_mssr_info;
 extern const struct cpg_mssr_info r8a7745_cpg_mssr_info;
 extern const struct cpg_mssr_info r8a7795_cpg_mssr_info;
 extern const struct cpg_mssr_info r8a7796_cpg_mssr_info;
+
+
+    /*
+     * Helpers for fixing up clock tables depending on SoC revision
+     */
+
+struct mssr_mod_reparent {
+       unsigned int clk, parent;
+};
+
+
+extern void cpg_core_nullify_range(struct cpg_core_clk *core_clks,
+                                  unsigned int num_core_clks,
+                                  unsigned int first_clk,
+                                  unsigned int last_clk);
+extern void mssr_mod_nullify(struct mssr_mod_clk *mod_clks,
+                            unsigned int num_mod_clks,
+                            const unsigned int *clks, unsigned int n);
+extern void mssr_mod_reparent(struct mssr_mod_clk *mod_clks,
+                             unsigned int num_mod_clks,
+                             const struct mssr_mod_reparent *clks,
+                             unsigned int n);
 #endif
index 141971488f409c91f0bafc63b71c52ab98019cef..26b220c988b29cd74104b46bc5598701b79565c4 100644 (file)
@@ -12,7 +12,7 @@ obj-y += clk-muxgrf.o
 obj-y  += clk-ddr.o
 obj-$(CONFIG_RESET_CONTROLLER) += softrst.o
 
-obj-y  += clk-rk1108.o
+obj-y  += clk-rv1108.o
 obj-y  += clk-rk3036.o
 obj-y  += clk-rk3188.o
 obj-y  += clk-rk3228.o
index eec51893a7e66532ef9680a3406017ea1b0cf9f4..dd0433d4753e8838a3de6426807249660f4271f7 100644 (file)
@@ -269,6 +269,7 @@ static int rockchip_rk3036_pll_enable(struct clk_hw *hw)
 
        writel(HIWORD_UPDATE(0, RK3036_PLLCON1_PWRDOWN, 0),
               pll->reg_base + RK3036_PLLCON(1));
+       rockchip_pll_wait_lock(pll);
 
        return 0;
 }
@@ -501,6 +502,7 @@ static int rockchip_rk3066_pll_enable(struct clk_hw *hw)
 
        writel(HIWORD_UPDATE(0, RK3066_PLLCON3_PWRDOWN, 0),
               pll->reg_base + RK3066_PLLCON(3));
+       rockchip_pll_wait_lock(pll);
 
        return 0;
 }
@@ -746,6 +748,7 @@ static int rockchip_rk3399_pll_enable(struct clk_hw *hw)
 
        writel(HIWORD_UPDATE(0, RK3399_PLLCON3_PWRDOWN, 0),
               pll->reg_base + RK3399_PLLCON(3));
+       rockchip_rk3399_pll_wait_lock(pll);
 
        return 0;
 }
index 1e384e143504c70f62d8f010422eb532e6eca553..b04f29774ee73c53924ecd1d4a7aae6f2116e419 100644 (file)
@@ -20,6 +20,7 @@
 #include <dt-bindings/clock/rk3328-cru.h>
 #include "clk.h"
 
+#define RK3328_GRF_SOC_CON4            0x410
 #define RK3328_GRF_SOC_STATUS0         0x480
 #define RK3328_GRF_MAC_CON1            0x904
 #define RK3328_GRF_MAC_CON2            0x908
@@ -214,6 +215,8 @@ PNAME(mux_mac2io_src_p)             = { "clk_mac2io_src",
                                    "gmac_clkin" };
 PNAME(mux_mac2phy_src_p)       = { "clk_mac2phy_src",
                                    "phy_50m_out" };
+PNAME(mux_mac2io_ext_p)                = { "clk_mac2io",
+                                   "gmac_clkin" };
 
 static struct rockchip_pll_clock rk3328_pll_clks[] __initdata = {
        [apll] = PLL(pll_rk3328, PLL_APLL, "apll", mux_pll_p,
@@ -680,6 +683,10 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
        COMPOSITE(SCLK_MAC2IO_OUT, "clk_mac2io_out", mux_2plls_p, 0,
                        RK3328_CLKSEL_CON(27), 15, 1, MFLAGS, 8, 5, DFLAGS,
                        RK3328_CLKGATE_CON(3), 5, GFLAGS),
+       MUXGRF(SCLK_MAC2IO, "clk_mac2io", mux_mac2io_src_p, CLK_SET_RATE_NO_REPARENT,
+                       RK3328_GRF_MAC_CON1, 10, 1, MFLAGS),
+       MUXGRF(SCLK_MAC2IO_EXT, "clk_mac2io_ext", mux_mac2io_ext_p, CLK_SET_RATE_NO_REPARENT,
+                       RK3328_GRF_SOC_CON4, 14, 1, MFLAGS),
 
        COMPOSITE(SCLK_MAC2PHY_SRC, "clk_mac2phy_src", mux_2plls_p, 0,
                        RK3328_CLKSEL_CON(26), 7, 1, MFLAGS, 0, 5, DFLAGS,
@@ -691,6 +698,8 @@ static struct rockchip_clk_branch rk3328_clk_branches[] __initdata = {
        COMPOSITE_NOMUX(SCLK_MAC2PHY_OUT, "clk_mac2phy_out", "clk_mac2phy", 0,
                        RK3328_CLKSEL_CON(26), 8, 2, DFLAGS,
                        RK3328_CLKGATE_CON(9), 2, GFLAGS),
+       MUXGRF(SCLK_MAC2PHY, "clk_mac2phy", mux_mac2phy_src_p, CLK_SET_RATE_NO_REPARENT,
+                       RK3328_GRF_MAC_CON2, 10, 1, MFLAGS),
 
        FACTOR(0, "xin12m", "xin24m", 0, 1, 2),
 
index 6cb474c593e7b111fa9da58e93bce5412b586422..024762d3214d6a01ad9e85236c6d6942129c5bd1 100644 (file)
@@ -835,18 +835,18 @@ static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = {
        GATE(PCLK_PMU, "pclk_pmu", "pclk_pd_pmu", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(23), 0, GFLAGS),
 
        /* timer gates */
-       GATE(0, "sclk_timer15", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 11, GFLAGS),
-       GATE(0, "sclk_timer14", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 10, GFLAGS),
-       GATE(0, "sclk_timer13", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 9, GFLAGS),
-       GATE(0, "sclk_timer12", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 8, GFLAGS),
-       GATE(0, "sclk_timer11", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 7, GFLAGS),
-       GATE(0, "sclk_timer10", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 6, GFLAGS),
-       GATE(0, "sclk_timer05", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 5, GFLAGS),
-       GATE(0, "sclk_timer04", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 4, GFLAGS),
-       GATE(0, "sclk_timer03", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 3, GFLAGS),
-       GATE(0, "sclk_timer02", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 2, GFLAGS),
-       GATE(0, "sclk_timer01", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 1, GFLAGS),
-       GATE(0, "sclk_timer00", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 0, GFLAGS),
+       GATE(SCLK_TIMER15, "sclk_timer15", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 11, GFLAGS),
+       GATE(SCLK_TIMER14, "sclk_timer14", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 10, GFLAGS),
+       GATE(SCLK_TIMER13, "sclk_timer13", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 9, GFLAGS),
+       GATE(SCLK_TIMER12, "sclk_timer12", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 8, GFLAGS),
+       GATE(SCLK_TIMER11, "sclk_timer11", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 7, GFLAGS),
+       GATE(SCLK_TIMER10, "sclk_timer10", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 6, GFLAGS),
+       GATE(SCLK_TIMER05, "sclk_timer05", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 5, GFLAGS),
+       GATE(SCLK_TIMER04, "sclk_timer04", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 4, GFLAGS),
+       GATE(SCLK_TIMER03, "sclk_timer03", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 3, GFLAGS),
+       GATE(SCLK_TIMER02, "sclk_timer02", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 2, GFLAGS),
+       GATE(SCLK_TIMER01, "sclk_timer01", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 1, GFLAGS),
+       GATE(SCLK_TIMER00, "sclk_timer00", "xin24m", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(24), 0, GFLAGS),
 };
 
 static const char *const rk3368_critical_clocks[] __initconst = {
@@ -858,6 +858,9 @@ static const char *const rk3368_critical_clocks[] __initconst = {
         */
        "pclk_pwm1",
        "pclk_pd_pmu",
+       "pclk_pd_alive",
+       "pclk_peri",
+       "hclk_peri",
 };
 
 static void __init rk3368_clk_init(struct device_node *np)
index 73121b1446348d06e4c5a19030976855dac4c523..fa3cbef0877632de2954c6861eccb457e4da105a 100644 (file)
@@ -1477,10 +1477,10 @@ static struct rockchip_clk_branch rk3399_clk_pmu_branches[] __initdata = {
        GATE(PCLK_UART4_PMU, "pclk_uart4_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 14, GFLAGS),
        GATE(PCLK_WDT_M0_PMU, "pclk_wdt_m0_pmu", "pclk_pmu_src", 0, RK3399_PMU_CLKGATE_CON(1), 15, GFLAGS),
 
-       GATE(FCLK_CM0S_PMU, "fclk_cm0s_pmu", "fclk_cm0s_src_pmu", 0, RK3399_PMU_CLKGATE_CON(2), 0, GFLAGS),
-       GATE(SCLK_CM0S_PMU, "sclk_cm0s_pmu", "fclk_cm0s_src_pmu", 0, RK3399_PMU_CLKGATE_CON(2), 1, GFLAGS),
-       GATE(HCLK_CM0S_PMU, "hclk_cm0s_pmu", "fclk_cm0s_src_pmu", 0, RK3399_PMU_CLKGATE_CON(2), 2, GFLAGS),
-       GATE(DCLK_CM0S_PMU, "dclk_cm0s_pmu", "fclk_cm0s_src_pmu", 0, RK3399_PMU_CLKGATE_CON(2), 3, GFLAGS),
+       GATE(FCLK_CM0S_PMU, "fclk_cm0s_pmu", "fclk_cm0s_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(2), 0, GFLAGS),
+       GATE(SCLK_CM0S_PMU, "sclk_cm0s_pmu", "fclk_cm0s_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(2), 1, GFLAGS),
+       GATE(HCLK_CM0S_PMU, "hclk_cm0s_pmu", "fclk_cm0s_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(2), 2, GFLAGS),
+       GATE(DCLK_CM0S_PMU, "dclk_cm0s_pmu", "fclk_cm0s_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(2), 3, GFLAGS),
        GATE(HCLK_NOC_PMU, "hclk_noc_pmu", "fclk_cm0s_src_pmu", CLK_IGNORE_UNUSED, RK3399_PMU_CLKGATE_CON(2), 5, GFLAGS),
 };
 
similarity index 57%
rename from drivers/clk/rockchip/clk-rk1108.c
rename to drivers/clk/rockchip/clk-rv1108.c
index 92750d798e5d44f0c5eee9c295b1a918945c0bce..7c05ab366348f73f8ccc0cc20fa7d8263b5ba021 100644 (file)
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/syscore_ops.h>
-#include <dt-bindings/clock/rk1108-cru.h>
+#include <dt-bindings/clock/rv1108-cru.h>
 #include "clk.h"
 
-#define RK1108_GRF_SOC_STATUS0 0x480
+#define RV1108_GRF_SOC_STATUS0 0x480
 
-enum rk1108_plls {
+enum rv1108_plls {
        apll, dpll, gpll,
 };
 
-static struct rockchip_pll_rate_table rk1108_pll_rates[] = {
+static struct rockchip_pll_rate_table rv1108_pll_rates[] = {
        /* _mhz, _refdiv, _fbdiv, _postdiv1, _postdiv2, _dsmpd, _frac */
        RK3036_PLL_RATE(1608000000, 1, 67, 1, 1, 1, 0),
        RK3036_PLL_RATE(1584000000, 1, 66, 1, 1, 1, 0),
@@ -74,32 +74,32 @@ static struct rockchip_pll_rate_table rk1108_pll_rates[] = {
        { /* sentinel */ },
 };
 
-#define RK1108_DIV_CORE_MASK           0xf
-#define RK1108_DIV_CORE_SHIFT          4
+#define RV1108_DIV_CORE_MASK           0xf
+#define RV1108_DIV_CORE_SHIFT          4
 
-#define RK1108_CLKSEL0(_core_peri_div) \
+#define RV1108_CLKSEL0(_core_peri_div) \
        {                               \
-               .reg = RK1108_CLKSEL_CON(1),    \
-               .val = HIWORD_UPDATE(_core_peri_div, RK1108_DIV_CORE_MASK,\
-                               RK1108_DIV_CORE_SHIFT)  \
+               .reg = RV1108_CLKSEL_CON(1),    \
+               .val = HIWORD_UPDATE(_core_peri_div, RV1108_DIV_CORE_MASK,\
+                               RV1108_DIV_CORE_SHIFT)  \
        }
 
-#define RK1108_CPUCLK_RATE(_prate, _core_peri_div)                     \
+#define RV1108_CPUCLK_RATE(_prate, _core_peri_div)                     \
        {                                                               \
                .prate = _prate,                                        \
                .divs = {                                               \
-                       RK1108_CLKSEL0(_core_peri_div),         \
+                       RV1108_CLKSEL0(_core_peri_div),         \
                },                                                      \
        }
 
-static struct rockchip_cpuclk_rate_table rk1108_cpuclk_rates[] __initdata = {
-       RK1108_CPUCLK_RATE(816000000, 4),
-       RK1108_CPUCLK_RATE(600000000, 4),
-       RK1108_CPUCLK_RATE(312000000, 4),
+static struct rockchip_cpuclk_rate_table rv1108_cpuclk_rates[] __initdata = {
+       RV1108_CPUCLK_RATE(816000000, 4),
+       RV1108_CPUCLK_RATE(600000000, 4),
+       RV1108_CPUCLK_RATE(312000000, 4),
 };
 
-static const struct rockchip_cpuclk_reg_data rk1108_cpuclk_data = {
-       .core_reg = RK1108_CLKSEL_CON(0),
+static const struct rockchip_cpuclk_reg_data rv1108_cpuclk_data = {
+       .core_reg = RV1108_CLKSEL_CON(0),
        .div_core_shift = 0,
        .div_core_mask = 0x1f,
        .mux_core_alt = 1,
@@ -131,13 +131,13 @@ PNAME(mux_i2s_out_p)              = { "i2s0_pre", "xin12m" };
 PNAME(mux_i2s1_p)              = { "i2s1_src", "i2s1_frac", "xin12m" };
 PNAME(mux_i2s2_p)              = { "i2s2_src", "i2s2_frac", "xin12m" };
 
-static struct rockchip_pll_clock rk1108_pll_clks[] __initdata = {
-       [apll] = PLL(pll_rk3399, PLL_APLL, "apll", mux_pll_p, 0, RK1108_PLL_CON(0),
-                    RK1108_PLL_CON(3), 8, 31, 0, rk1108_pll_rates),
-       [dpll] = PLL(pll_rk3399, PLL_DPLL, "dpll", mux_pll_p, 0, RK1108_PLL_CON(8),
-                    RK1108_PLL_CON(11), 8, 31, 0, NULL),
-       [gpll] = PLL(pll_rk3399, PLL_GPLL, "gpll", mux_pll_p, 0, RK1108_PLL_CON(16),
-                    RK1108_PLL_CON(19), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rk1108_pll_rates),
+static struct rockchip_pll_clock rv1108_pll_clks[] __initdata = {
+       [apll] = PLL(pll_rk3399, PLL_APLL, "apll", mux_pll_p, 0, RV1108_PLL_CON(0),
+                    RV1108_PLL_CON(3), 8, 31, 0, rv1108_pll_rates),
+       [dpll] = PLL(pll_rk3399, PLL_DPLL, "dpll", mux_pll_p, 0, RV1108_PLL_CON(8),
+                    RV1108_PLL_CON(11), 8, 31, 0, NULL),
+       [gpll] = PLL(pll_rk3399, PLL_GPLL, "gpll", mux_pll_p, 0, RV1108_PLL_CON(16),
+                    RV1108_PLL_CON(19), 8, 31, ROCKCHIP_PLL_SYNC_RATE, rv1108_pll_rates),
 };
 
 #define MFLAGS CLK_MUX_HIWORD_MASK
@@ -145,56 +145,56 @@ static struct rockchip_pll_clock rk1108_pll_clks[] __initdata = {
 #define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE)
 #define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK
 
-static struct rockchip_clk_branch rk1108_uart0_fracmux __initdata =
+static struct rockchip_clk_branch rv1108_uart0_fracmux __initdata =
        MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, CLK_SET_RATE_PARENT,
-                       RK1108_CLKSEL_CON(13), 8, 2, MFLAGS);
+                       RV1108_CLKSEL_CON(13), 8, 2, MFLAGS);
 
-static struct rockchip_clk_branch rk1108_uart1_fracmux __initdata =
+static struct rockchip_clk_branch rv1108_uart1_fracmux __initdata =
        MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, CLK_SET_RATE_PARENT,
-                       RK1108_CLKSEL_CON(14), 8, 2, MFLAGS);
+                       RV1108_CLKSEL_CON(14), 8, 2, MFLAGS);
 
-static struct rockchip_clk_branch rk1108_uart2_fracmux __initdata =
+static struct rockchip_clk_branch rv1108_uart2_fracmux __initdata =
        MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT,
-                       RK1108_CLKSEL_CON(15), 8, 2, MFLAGS);
+                       RV1108_CLKSEL_CON(15), 8, 2, MFLAGS);
 
-static struct rockchip_clk_branch rk1108_i2s0_fracmux __initdata =
+static struct rockchip_clk_branch rv1108_i2s0_fracmux __initdata =
        MUX(0, "i2s0_pre", mux_i2s0_pre_p, CLK_SET_RATE_PARENT,
-                       RK1108_CLKSEL_CON(5), 12, 2, MFLAGS);
+                       RV1108_CLKSEL_CON(5), 12, 2, MFLAGS);
 
-static struct rockchip_clk_branch rk1108_i2s1_fracmux __initdata =
+static struct rockchip_clk_branch rv1108_i2s1_fracmux __initdata =
        MUX(0, "i2s1_pre", mux_i2s1_p, CLK_SET_RATE_PARENT,
-                       RK1108_CLKSEL_CON(6), 12, 2, MFLAGS);
+                       RV1108_CLKSEL_CON(6), 12, 2, MFLAGS);
 
-static struct rockchip_clk_branch rk1108_i2s2_fracmux __initdata =
+static struct rockchip_clk_branch rv1108_i2s2_fracmux __initdata =
        MUX(0, "i2s2_pre", mux_i2s2_p, CLK_SET_RATE_PARENT,
-                       RK1108_CLKSEL_CON(7), 12, 2, MFLAGS);
+                       RV1108_CLKSEL_CON(7), 12, 2, MFLAGS);
 
-static struct rockchip_clk_branch rk1108_clk_branches[] __initdata = {
+static struct rockchip_clk_branch rv1108_clk_branches[] __initdata = {
        MUX(0, "hdmi_phy", mux_hdmiphy_phy_p, CLK_SET_RATE_PARENT,
-                       RK1108_MISC_CON, 13, 2, MFLAGS),
+                       RV1108_MISC_CON, 13, 2, MFLAGS),
        MUX(0, "usb480m", mux_usb480m_pre_p, CLK_SET_RATE_PARENT,
-                       RK1108_MISC_CON, 15, 2, MFLAGS),
+                       RV1108_MISC_CON, 15, 2, MFLAGS),
        /*
         * Clock-Architecture Diagram 2
         */
 
        /* PD_CORE */
        GATE(0, "dpll_core", "dpll", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(0), 1, GFLAGS),
+                       RV1108_CLKGATE_CON(0), 1, GFLAGS),
        GATE(0, "apll_core", "apll", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(0), 0, GFLAGS),
+                       RV1108_CLKGATE_CON(0), 0, GFLAGS),
        GATE(0, "gpll_core", "gpll", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(0), 2, GFLAGS),
+                       RV1108_CLKGATE_CON(0), 2, GFLAGS),
        COMPOSITE_NOMUX(0, "pclken_dbg", "armclk", CLK_IGNORE_UNUSED,
-                       RK1108_CLKSEL_CON(1), 4, 4, DFLAGS | CLK_DIVIDER_READ_ONLY,
-                       RK1108_CLKGATE_CON(0), 5, GFLAGS),
+                       RV1108_CLKSEL_CON(1), 4, 4, DFLAGS | CLK_DIVIDER_READ_ONLY,
+                       RV1108_CLKGATE_CON(0), 5, GFLAGS),
        COMPOSITE_NOMUX(ACLK_ENMCORE, "aclkenm_core", "armclk", CLK_IGNORE_UNUSED,
-                       RK1108_CLKSEL_CON(1), 0, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
-                       RK1108_CLKGATE_CON(0), 4, GFLAGS),
+                       RV1108_CLKSEL_CON(1), 0, 3, DFLAGS | CLK_DIVIDER_READ_ONLY,
+                       RV1108_CLKGATE_CON(0), 4, GFLAGS),
        GATE(ACLK_CORE, "aclk_core", "aclkenm_core", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(11), 0, GFLAGS),
+                       RV1108_CLKGATE_CON(11), 0, GFLAGS),
        GATE(0, "pclk_dbg", "pclken_dbg", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(11), 1, GFLAGS),
+                       RV1108_CLKGATE_CON(11), 1, GFLAGS),
 
        /* PD_RKVENC */
 
@@ -202,58 +202,58 @@ static struct rockchip_clk_branch rk1108_clk_branches[] __initdata = {
 
        /* PD_PMU_wrapper */
        COMPOSITE_NOMUX(0, "pmu_24m_ena", "gpll", CLK_IGNORE_UNUSED,
-                       RK1108_CLKSEL_CON(38), 0, 5, DFLAGS,
-                       RK1108_CLKGATE_CON(8), 12, GFLAGS),
+                       RV1108_CLKSEL_CON(38), 0, 5, DFLAGS,
+                       RV1108_CLKGATE_CON(8), 12, GFLAGS),
        GATE(0, "pmu", "pmu_24m_ena", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(10), 0, GFLAGS),
+                       RV1108_CLKGATE_CON(10), 0, GFLAGS),
        GATE(0, "intmem1", "pmu_24m_ena", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(10), 1, GFLAGS),
+                       RV1108_CLKGATE_CON(10), 1, GFLAGS),
        GATE(0, "gpio0_pmu", "pmu_24m_ena", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(10), 2, GFLAGS),
+                       RV1108_CLKGATE_CON(10), 2, GFLAGS),
        GATE(0, "pmugrf", "pmu_24m_ena", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(10), 3, GFLAGS),
+                       RV1108_CLKGATE_CON(10), 3, GFLAGS),
        GATE(0, "pmu_noc", "pmu_24m_ena", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(10), 4, GFLAGS),
+                       RV1108_CLKGATE_CON(10), 4, GFLAGS),
        GATE(0, "i2c0_pmu_pclk", "pmu_24m_ena", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(10), 5, GFLAGS),
+                       RV1108_CLKGATE_CON(10), 5, GFLAGS),
        GATE(0, "pwm0_pmu_pclk", "pmu_24m_ena", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(10), 6, GFLAGS),
+                       RV1108_CLKGATE_CON(10), 6, GFLAGS),
        COMPOSITE(0, "pwm0_pmu_clk", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
-                       RK1108_CLKSEL_CON(12), 7, 1, MFLAGS, 0, 7, DFLAGS,
-                       RK1108_CLKGATE_CON(8), 15, GFLAGS),
+                       RV1108_CLKSEL_CON(12), 7, 1, MFLAGS, 0, 7, DFLAGS,
+                       RV1108_CLKGATE_CON(8), 15, GFLAGS),
        COMPOSITE(0, "i2c0_pmu_clk", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
-                       RK1108_CLKSEL_CON(19), 7, 1, MFLAGS, 0, 7, DFLAGS,
-                       RK1108_CLKGATE_CON(8), 14, GFLAGS),
+                       RV1108_CLKSEL_CON(19), 7, 1, MFLAGS, 0, 7, DFLAGS,
+                       RV1108_CLKGATE_CON(8), 14, GFLAGS),
        GATE(0, "pvtm_pmu", "xin24m", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(8), 13, GFLAGS),
+                       RV1108_CLKGATE_CON(8), 13, GFLAGS),
 
        /*
         * Clock-Architecture Diagram 4
         */
        COMPOSITE(0, "aclk_vio0_2wrap_occ", mux_pll_src_4plls_p, CLK_IGNORE_UNUSED,
-                       RK1108_CLKSEL_CON(28), 6, 2, MFLAGS, 0, 5, DFLAGS,
-                       RK1108_CLKGATE_CON(6), 0, GFLAGS),
+                       RV1108_CLKSEL_CON(28), 6, 2, MFLAGS, 0, 5, DFLAGS,
+                       RV1108_CLKGATE_CON(6), 0, GFLAGS),
        GATE(0, "aclk_vio0_pre", "aclk_vio0_2wrap_occ", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(17), 0, GFLAGS),
+                       RV1108_CLKGATE_CON(17), 0, GFLAGS),
        COMPOSITE_NOMUX(0, "hclk_vio_pre", "aclk_vio0_pre", 0,
-                       RK1108_CLKSEL_CON(29), 0, 5, DFLAGS,
-                       RK1108_CLKGATE_CON(7), 2, GFLAGS),
+                       RV1108_CLKSEL_CON(29), 0, 5, DFLAGS,
+                       RV1108_CLKGATE_CON(7), 2, GFLAGS),
        COMPOSITE_NOMUX(0, "pclk_vio_pre", "aclk_vio0_pre", 0,
-                       RK1108_CLKSEL_CON(29), 8, 5, DFLAGS,
-                       RK1108_CLKGATE_CON(7), 3, GFLAGS),
+                       RV1108_CLKSEL_CON(29), 8, 5, DFLAGS,
+                       RV1108_CLKGATE_CON(7), 3, GFLAGS),
 
        INVERTER(0, "pclk_vip", "ext_vip",
-                       RK1108_CLKSEL_CON(31), 8, IFLAGS),
+                       RV1108_CLKSEL_CON(31), 8, IFLAGS),
        GATE(0, "pclk_isp_pre", "pclk_vip", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(7), 6, GFLAGS),
+                       RV1108_CLKGATE_CON(7), 6, GFLAGS),
        GATE(0, "pclk_isp", "pclk_isp_pre", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(18), 10, GFLAGS),
+                       RV1108_CLKGATE_CON(18), 10, GFLAGS),
        GATE(0, "dclk_hdmiphy_src_gpll", "gpll", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(6), 5, GFLAGS),
+                       RV1108_CLKGATE_CON(6), 5, GFLAGS),
        GATE(0, "dclk_hdmiphy_src_dpll", "dpll", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(6), 4, GFLAGS),
+                       RV1108_CLKGATE_CON(6), 4, GFLAGS),
        COMPOSITE_NOGATE(0, "dclk_hdmiphy", mux_dclk_hdmiphy_pre_p, 0,
-                       RK1108_CLKSEL_CON(32), 6, 2, MFLAGS, 8, 6, DFLAGS),
+                       RV1108_CLKSEL_CON(32), 6, 2, MFLAGS, 8, 6, DFLAGS),
 
        /*
         * Clock-Architecture Diagram 5
@@ -262,153 +262,153 @@ static struct rockchip_clk_branch rk1108_clk_branches[] __initdata = {
        FACTOR(0, "xin12m", "xin24m", 0, 1, 2),
 
        COMPOSITE(0, "i2s0_src", mux_pll_src_2plls_p, 0,
-                       RK1108_CLKSEL_CON(5), 8, 1, MFLAGS, 0, 7, DFLAGS,
-                       RK1108_CLKGATE_CON(2), 0, GFLAGS),
+                       RV1108_CLKSEL_CON(5), 8, 1, MFLAGS, 0, 7, DFLAGS,
+                       RV1108_CLKGATE_CON(2), 0, GFLAGS),
        COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT,
-                       RK1108_CLKSEL_CON(8), 0,
-                       RK1108_CLKGATE_CON(2), 1, GFLAGS,
-                       &rk1108_i2s0_fracmux),
+                       RV1108_CLKSEL_CON(8), 0,
+                       RV1108_CLKGATE_CON(2), 1, GFLAGS,
+                       &rv1108_i2s0_fracmux),
        GATE(SCLK_I2S0, "sclk_i2s0", "i2s0_pre", CLK_SET_RATE_PARENT,
-                       RK1108_CLKGATE_CON(2), 2, GFLAGS),
+                       RV1108_CLKGATE_CON(2), 2, GFLAGS),
        COMPOSITE_NODIV(0, "i2s_out", mux_i2s_out_p, 0,
-                       RK1108_CLKSEL_CON(5), 15, 1, MFLAGS,
-                       RK1108_CLKGATE_CON(2), 3, GFLAGS),
+                       RV1108_CLKSEL_CON(5), 15, 1, MFLAGS,
+                       RV1108_CLKGATE_CON(2), 3, GFLAGS),
 
        COMPOSITE(0, "i2s1_src", mux_pll_src_2plls_p, 0,
-                       RK1108_CLKSEL_CON(6), 8, 1, MFLAGS, 0, 7, DFLAGS,
-                       RK1108_CLKGATE_CON(2), 4, GFLAGS),
+                       RV1108_CLKSEL_CON(6), 8, 1, MFLAGS, 0, 7, DFLAGS,
+                       RV1108_CLKGATE_CON(2), 4, GFLAGS),
        COMPOSITE_FRACMUX(0, "i2s1_frac", "i2s1_src", CLK_SET_RATE_PARENT,
                        RK2928_CLKSEL_CON(9), 0,
                        RK2928_CLKGATE_CON(2), 5, GFLAGS,
-                       &rk1108_i2s1_fracmux),
+                       &rv1108_i2s1_fracmux),
        GATE(SCLK_I2S1, "sclk_i2s1", "i2s1_pre", CLK_SET_RATE_PARENT,
-                       RK1108_CLKGATE_CON(2), 6, GFLAGS),
+                       RV1108_CLKGATE_CON(2), 6, GFLAGS),
 
        COMPOSITE(0, "i2s2_src", mux_pll_src_2plls_p, 0,
-                       RK1108_CLKSEL_CON(7), 8, 1, MFLAGS, 0, 7, DFLAGS,
-                       RK1108_CLKGATE_CON(3), 8, GFLAGS),
+                       RV1108_CLKSEL_CON(7), 8, 1, MFLAGS, 0, 7, DFLAGS,
+                       RV1108_CLKGATE_CON(3), 8, GFLAGS),
        COMPOSITE_FRACMUX(0, "i2s2_frac", "i2s2_src", CLK_SET_RATE_PARENT,
-                       RK1108_CLKSEL_CON(10), 0,
-                       RK1108_CLKGATE_CON(2), 9, GFLAGS,
-                       &rk1108_i2s2_fracmux),
+                       RV1108_CLKSEL_CON(10), 0,
+                       RV1108_CLKGATE_CON(2), 9, GFLAGS,
+                       &rv1108_i2s2_fracmux),
        GATE(SCLK_I2S2, "sclk_i2s2", "i2s2_pre", CLK_SET_RATE_PARENT,
-                       RK1108_CLKGATE_CON(2), 10, GFLAGS),
+                       RV1108_CLKGATE_CON(2), 10, GFLAGS),
 
        /* PD_BUS */
        GATE(0, "aclk_bus_src_gpll", "gpll", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(1), 0, GFLAGS),
+                       RV1108_CLKGATE_CON(1), 0, GFLAGS),
        GATE(0, "aclk_bus_src_apll", "apll", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(1), 1, GFLAGS),
+                       RV1108_CLKGATE_CON(1), 1, GFLAGS),
        GATE(0, "aclk_bus_src_dpll", "dpll", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(1), 2, GFLAGS),
+                       RV1108_CLKGATE_CON(1), 2, GFLAGS),
        COMPOSITE_NOGATE(ACLK_PRE, "aclk_bus_pre", mux_aclk_bus_src_p, 0,
-                       RK1108_CLKSEL_CON(2), 8, 2, MFLAGS, 0, 5, DFLAGS),
+                       RV1108_CLKSEL_CON(2), 8, 2, MFLAGS, 0, 5, DFLAGS),
        COMPOSITE_NOMUX(0, "hclk_bus_pre", "aclk_bus_2wrap_occ", 0,
-                       RK1108_CLKSEL_CON(3), 0, 5, DFLAGS,
-                       RK1108_CLKGATE_CON(1), 4, GFLAGS),
+                       RV1108_CLKSEL_CON(3), 0, 5, DFLAGS,
+                       RV1108_CLKGATE_CON(1), 4, GFLAGS),
        COMPOSITE_NOMUX(0, "pclken_bus", "aclk_bus_2wrap_occ", 0,
-                       RK1108_CLKSEL_CON(3), 8, 5, DFLAGS,
-                       RK1108_CLKGATE_CON(1), 5, GFLAGS),
+                       RV1108_CLKSEL_CON(3), 8, 5, DFLAGS,
+                       RV1108_CLKGATE_CON(1), 5, GFLAGS),
        GATE(0, "pclk_bus_pre", "pclken_bus", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(1), 6, GFLAGS),
+                       RV1108_CLKGATE_CON(1), 6, GFLAGS),
        GATE(0, "pclk_top_pre", "pclken_bus", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(1), 7, GFLAGS),
+                       RV1108_CLKGATE_CON(1), 7, GFLAGS),
        GATE(0, "pclk_ddr_pre", "pclken_bus", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(1), 8, GFLAGS),
+                       RV1108_CLKGATE_CON(1), 8, GFLAGS),
        GATE(0, "clk_timer0", "mux_pll_p", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(1), 9, GFLAGS),
+                       RV1108_CLKGATE_CON(1), 9, GFLAGS),
        GATE(0, "clk_timer1", "mux_pll_p", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(1), 10, GFLAGS),
+                       RV1108_CLKGATE_CON(1), 10, GFLAGS),
        GATE(0, "pclk_timer", "pclk_bus_pre", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(13), 4, GFLAGS),
+                       RV1108_CLKGATE_CON(13), 4, GFLAGS),
 
        COMPOSITE(0, "uart0_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,
-                       RK1108_CLKSEL_CON(13), 12, 2, MFLAGS, 0, 7, DFLAGS,
-                       RK1108_CLKGATE_CON(3), 1, GFLAGS),
+                       RV1108_CLKSEL_CON(13), 12, 2, MFLAGS, 0, 7, DFLAGS,
+                       RV1108_CLKGATE_CON(3), 1, GFLAGS),
        COMPOSITE(0, "uart1_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,
-                       RK1108_CLKSEL_CON(14), 12, 2, MFLAGS, 0, 7, DFLAGS,
-                       RK1108_CLKGATE_CON(3), 3, GFLAGS),
+                       RV1108_CLKSEL_CON(14), 12, 2, MFLAGS, 0, 7, DFLAGS,
+                       RV1108_CLKGATE_CON(3), 3, GFLAGS),
        COMPOSITE(0, "uart21_src", mux_pll_src_dpll_gpll_usb480m_p, CLK_IGNORE_UNUSED,
-                       RK1108_CLKSEL_CON(15), 12, 2, MFLAGS, 0, 7, DFLAGS,
-                       RK1108_CLKGATE_CON(3), 5, GFLAGS),
+                       RV1108_CLKSEL_CON(15), 12, 2, MFLAGS, 0, 7, DFLAGS,
+                       RV1108_CLKGATE_CON(3), 5, GFLAGS),
 
        COMPOSITE_FRACMUX(0, "uart0_frac", "uart0_src", CLK_SET_RATE_PARENT,
-                       RK1108_CLKSEL_CON(16), 0,
-                       RK1108_CLKGATE_CON(3), 2, GFLAGS,
-                       &rk1108_uart0_fracmux),
+                       RV1108_CLKSEL_CON(16), 0,
+                       RV1108_CLKGATE_CON(3), 2, GFLAGS,
+                       &rv1108_uart0_fracmux),
        COMPOSITE_FRACMUX(0, "uart1_frac", "uart1_src", CLK_SET_RATE_PARENT,
-                       RK1108_CLKSEL_CON(17), 0,
-                       RK1108_CLKGATE_CON(3), 4, GFLAGS,
-                       &rk1108_uart1_fracmux),
+                       RV1108_CLKSEL_CON(17), 0,
+                       RV1108_CLKGATE_CON(3), 4, GFLAGS,
+                       &rv1108_uart1_fracmux),
        COMPOSITE_FRACMUX(0, "uart2_frac", "uart2_src", CLK_SET_RATE_PARENT,
-                       RK1108_CLKSEL_CON(18), 0,
-                       RK1108_CLKGATE_CON(3), 6, GFLAGS,
-                       &rk1108_uart2_fracmux),
+                       RV1108_CLKSEL_CON(18), 0,
+                       RV1108_CLKGATE_CON(3), 6, GFLAGS,
+                       &rv1108_uart2_fracmux),
        GATE(PCLK_UART0, "pclk_uart0", "pclk_bus_pre", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(13), 10, GFLAGS),
+                       RV1108_CLKGATE_CON(13), 10, GFLAGS),
        GATE(PCLK_UART1, "pclk_uart1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(13), 11, GFLAGS),
+                       RV1108_CLKGATE_CON(13), 11, GFLAGS),
        GATE(PCLK_UART2, "pclk_uart2", "pclk_bus_pre", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(13), 12, GFLAGS),
+                       RV1108_CLKGATE_CON(13), 12, GFLAGS),
 
        COMPOSITE(0, "clk_i2c1", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
-                       RK1108_CLKSEL_CON(19), 15, 2, MFLAGS, 8, 7, DFLAGS,
-                       RK1108_CLKGATE_CON(3), 7, GFLAGS),
+                       RV1108_CLKSEL_CON(19), 15, 2, MFLAGS, 8, 7, DFLAGS,
+                       RV1108_CLKGATE_CON(3), 7, GFLAGS),
        COMPOSITE(0, "clk_i2c2", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
-                       RK1108_CLKSEL_CON(20), 7, 2, MFLAGS, 0, 7, DFLAGS,
-                       RK1108_CLKGATE_CON(3), 8, GFLAGS),
+                       RV1108_CLKSEL_CON(20), 7, 2, MFLAGS, 0, 7, DFLAGS,
+                       RV1108_CLKGATE_CON(3), 8, GFLAGS),
        COMPOSITE(0, "clk_i2c3", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
-                       RK1108_CLKSEL_CON(20), 15, 2, MFLAGS, 8, 7, DFLAGS,
-                       RK1108_CLKGATE_CON(3), 9, GFLAGS),
+                       RV1108_CLKSEL_CON(20), 15, 2, MFLAGS, 8, 7, DFLAGS,
+                       RV1108_CLKGATE_CON(3), 9, GFLAGS),
        GATE(0, "pclk_i2c1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(13), 0, GFLAGS),
+                       RV1108_CLKGATE_CON(13), 0, GFLAGS),
        GATE(0, "pclk_i2c2", "pclk_bus_pre", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(13), 1, GFLAGS),
+                       RV1108_CLKGATE_CON(13), 1, GFLAGS),
        GATE(0, "pclk_i2c3", "pclk_bus_pre", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(13), 2, GFLAGS),
+                       RV1108_CLKGATE_CON(13), 2, GFLAGS),
        COMPOSITE(0, "clk_pwm1", mux_pll_src_2plls_p, CLK_IGNORE_UNUSED,
-                       RK1108_CLKSEL_CON(12), 15, 2, MFLAGS, 8, 7, DFLAGS,
-                       RK1108_CLKGATE_CON(3), 10, GFLAGS),
+                       RV1108_CLKSEL_CON(12), 15, 2, MFLAGS, 8, 7, DFLAGS,
+                       RV1108_CLKGATE_CON(3), 10, GFLAGS),
        GATE(0, "pclk_pwm1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(13), 6, GFLAGS),
+                       RV1108_CLKGATE_CON(13), 6, GFLAGS),
        GATE(0, "pclk_wdt", "pclk_bus_pre", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(13), 3, GFLAGS),
+                       RV1108_CLKGATE_CON(13), 3, GFLAGS),
        GATE(0, "pclk_gpio1", "pclk_bus_pre", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(13), 7, GFLAGS),
+                       RV1108_CLKGATE_CON(13), 7, GFLAGS),
        GATE(0, "pclk_gpio2", "pclk_bus_pre", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(13), 8, GFLAGS),
+                       RV1108_CLKGATE_CON(13), 8, GFLAGS),
        GATE(0, "pclk_gpio3", "pclk_bus_pre", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(13), 9, GFLAGS),
+                       RV1108_CLKGATE_CON(13), 9, GFLAGS),
 
        GATE(0, "pclk_grf", "pclk_bus_pre", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(14), 0, GFLAGS),
+                       RV1108_CLKGATE_CON(14), 0, GFLAGS),
 
        GATE(ACLK_DMAC, "aclk_dmac", "aclk_bus_pre", 0,
-            RK1108_CLKGATE_CON(12), 2, GFLAGS),
+            RV1108_CLKGATE_CON(12), 2, GFLAGS),
        GATE(0, "hclk_rom", "hclk_bus_pre", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(12), 3, GFLAGS),
+                       RV1108_CLKGATE_CON(12), 3, GFLAGS),
        GATE(0, "aclk_intmem", "aclk_bus_pre", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(12), 1, GFLAGS),
+                       RV1108_CLKGATE_CON(12), 1, GFLAGS),
 
        /* PD_DDR */
        GATE(0, "apll_ddr", "apll", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(0), 8, GFLAGS),
+                       RV1108_CLKGATE_CON(0), 8, GFLAGS),
        GATE(0, "dpll_ddr", "dpll", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(0), 9, GFLAGS),
+                       RV1108_CLKGATE_CON(0), 9, GFLAGS),
        GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(0), 10, GFLAGS),
+                       RV1108_CLKGATE_CON(0), 10, GFLAGS),
        COMPOSITE(0, "ddrphy4x", mux_ddrphy_p, CLK_IGNORE_UNUSED,
-                       RK1108_CLKSEL_CON(4), 8, 2, MFLAGS, 0, 3,
+                       RV1108_CLKSEL_CON(4), 8, 2, MFLAGS, 0, 3,
                        DFLAGS | CLK_DIVIDER_POWER_OF_TWO,
-                       RK1108_CLKGATE_CON(10), 9, GFLAGS),
+                       RV1108_CLKGATE_CON(10), 9, GFLAGS),
        GATE(0, "ddrupctl", "ddrphy_pre", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(12), 4, GFLAGS),
+                       RV1108_CLKGATE_CON(12), 4, GFLAGS),
        GATE(0, "ddrc", "ddrphy", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(12), 5, GFLAGS),
+                       RV1108_CLKGATE_CON(12), 5, GFLAGS),
        GATE(0, "ddrmon", "ddrphy_pre", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(12), 6, GFLAGS),
+                       RV1108_CLKGATE_CON(12), 6, GFLAGS),
        GATE(0, "timer_clk", "xin24m", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(0), 11, GFLAGS),
+                       RV1108_CLKGATE_CON(0), 11, GFLAGS),
 
        /*
         * Clock-Architecture Diagram 6
@@ -416,73 +416,73 @@ static struct rockchip_clk_branch rk1108_clk_branches[] __initdata = {
 
        /* PD_PERI */
        COMPOSITE_NOMUX(0, "pclk_periph_pre", "gpll", 0,
-                       RK1108_CLKSEL_CON(23), 10, 5, DFLAGS,
-                       RK1108_CLKGATE_CON(4), 5, GFLAGS),
+                       RV1108_CLKSEL_CON(23), 10, 5, DFLAGS,
+                       RV1108_CLKGATE_CON(4), 5, GFLAGS),
        GATE(0, "pclk_periph", "pclk_periph_pre", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(15), 13, GFLAGS),
+                       RV1108_CLKGATE_CON(15), 13, GFLAGS),
        COMPOSITE_NOMUX(0, "hclk_periph_pre", "gpll", 0,
-                       RK1108_CLKSEL_CON(23), 5, 5, DFLAGS,
-                       RK1108_CLKGATE_CON(4), 4, GFLAGS),
+                       RV1108_CLKSEL_CON(23), 5, 5, DFLAGS,
+                       RV1108_CLKGATE_CON(4), 4, GFLAGS),
        GATE(0, "hclk_periph", "hclk_periph_pre", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(15), 12, GFLAGS),
+                       RV1108_CLKGATE_CON(15), 12, GFLAGS),
 
        GATE(0, "aclk_peri_src_dpll", "dpll", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(4), 1, GFLAGS),
+                       RV1108_CLKGATE_CON(4), 1, GFLAGS),
        GATE(0, "aclk_peri_src_gpll", "gpll", CLK_IGNORE_UNUSED,
-                       RK1108_CLKGATE_CON(4), 2, GFLAGS),
+                       RV1108_CLKGATE_CON(4), 2, GFLAGS),
        COMPOSITE(0, "aclk_periph", mux_aclk_peri_src_p, CLK_IGNORE_UNUSED,
-                       RK1108_CLKSEL_CON(23), 15, 2, MFLAGS, 0, 5, DFLAGS,
-                       RK1108_CLKGATE_CON(15), 11, GFLAGS),
+                       RV1108_CLKSEL_CON(23), 15, 2, MFLAGS, 0, 5, DFLAGS,
+                       RV1108_CLKGATE_CON(15), 11, GFLAGS),
 
        COMPOSITE(SCLK_SDMMC, "sclk_sdmmc0", mux_mmc_src_p, 0,
-                       RK1108_CLKSEL_CON(25), 8, 2, MFLAGS, 0, 8, DFLAGS,
-                       RK1108_CLKGATE_CON(5), 0, GFLAGS),
+                       RV1108_CLKSEL_CON(25), 8, 2, MFLAGS, 0, 8, DFLAGS,
+                       RV1108_CLKGATE_CON(5), 0, GFLAGS),
 
        COMPOSITE_NODIV(0, "sclk_sdio_src", mux_mmc_src_p, 0,
-                       RK1108_CLKSEL_CON(25), 10, 2, MFLAGS,
-                       RK1108_CLKGATE_CON(5), 2, GFLAGS),
+                       RV1108_CLKSEL_CON(25), 10, 2, MFLAGS,
+                       RV1108_CLKGATE_CON(5), 2, GFLAGS),
        DIV(SCLK_SDIO, "sclk_sdio", "sclk_sdio_src", 0,
-                       RK1108_CLKSEL_CON(26), 0, 8, DFLAGS),
+                       RV1108_CLKSEL_CON(26), 0, 8, DFLAGS),
 
        COMPOSITE_NODIV(0, "sclk_emmc_src", mux_mmc_src_p, 0,
-                       RK1108_CLKSEL_CON(25), 12, 2, MFLAGS,
-                       RK1108_CLKGATE_CON(5), 1, GFLAGS),
+                       RV1108_CLKSEL_CON(25), 12, 2, MFLAGS,
+                       RV1108_CLKGATE_CON(5), 1, GFLAGS),
        DIV(SCLK_EMMC, "sclk_emmc", "sclk_emmc_src", 0,
                        RK2928_CLKSEL_CON(26), 8, 8, DFLAGS),
-       GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 0, GFLAGS),
-       GATE(HCLK_SDIO, "hclk_sdio", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 1, GFLAGS),
-       GATE(HCLK_EMMC, "hclk_emmc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 2, GFLAGS),
+       GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_periph", 0, RV1108_CLKGATE_CON(15), 0, GFLAGS),
+       GATE(HCLK_SDIO, "hclk_sdio", "hclk_periph", 0, RV1108_CLKGATE_CON(15), 1, GFLAGS),
+       GATE(HCLK_EMMC, "hclk_emmc", "hclk_periph", 0, RV1108_CLKGATE_CON(15), 2, GFLAGS),
 
        COMPOSITE(SCLK_NANDC, "sclk_nandc", mux_pll_src_2plls_p, 0,
-                       RK1108_CLKSEL_CON(27), 14, 2, MFLAGS, 8, 5, DFLAGS,
-                       RK1108_CLKGATE_CON(5), 3, GFLAGS),
-       GATE(HCLK_NANDC, "hclk_nandc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 3, GFLAGS),
+                       RV1108_CLKSEL_CON(27), 14, 2, MFLAGS, 8, 5, DFLAGS,
+                       RV1108_CLKGATE_CON(5), 3, GFLAGS),
+       GATE(HCLK_NANDC, "hclk_nandc", "hclk_periph", 0, RV1108_CLKGATE_CON(15), 3, GFLAGS),
 
        COMPOSITE(SCLK_SFC, "sclk_sfc", mux_pll_src_2plls_p, 0,
-                       RK1108_CLKSEL_CON(27), 7, 2, MFLAGS, 0, 7, DFLAGS,
-                       RK1108_CLKGATE_CON(5), 4, GFLAGS),
-       GATE(HCLK_SFC, "hclk_sfc", "hclk_periph", 0, RK1108_CLKGATE_CON(15), 10, GFLAGS),
+                       RV1108_CLKSEL_CON(27), 7, 2, MFLAGS, 0, 7, DFLAGS,
+                       RV1108_CLKGATE_CON(5), 4, GFLAGS),
+       GATE(HCLK_SFC, "hclk_sfc", "hclk_periph", 0, RV1108_CLKGATE_CON(15), 10, GFLAGS),
 
        COMPOSITE(0, "sclk_macphy_pre", mux_pll_src_apll_gpll_p, 0,
-                       RK1108_CLKSEL_CON(24), 12, 2, MFLAGS, 0, 5, DFLAGS,
-                       RK1108_CLKGATE_CON(4), 10, GFLAGS),
+                       RV1108_CLKSEL_CON(24), 12, 2, MFLAGS, 0, 5, DFLAGS,
+                       RV1108_CLKGATE_CON(4), 10, GFLAGS),
        MUX(0, "sclk_macphy", mux_sclk_macphy_p, CLK_SET_RATE_PARENT,
-                       RK1108_CLKSEL_CON(24), 8, 2, MFLAGS),
-       GATE(0, "sclk_macphy_rx", "sclk_macphy", 0, RK1108_CLKGATE_CON(4), 8, GFLAGS),
-       GATE(0, "sclk_mac_ref", "sclk_macphy", 0, RK1108_CLKGATE_CON(4), 6, GFLAGS),
-       GATE(0, "sclk_mac_refout", "sclk_macphy", 0, RK1108_CLKGATE_CON(4), 7, GFLAGS),
+                       RV1108_CLKSEL_CON(24), 8, 2, MFLAGS),
+       GATE(0, "sclk_macphy_rx", "sclk_macphy", 0, RV1108_CLKGATE_CON(4), 8, GFLAGS),
+       GATE(0, "sclk_mac_ref", "sclk_macphy", 0, RV1108_CLKGATE_CON(4), 6, GFLAGS),
+       GATE(0, "sclk_mac_refout", "sclk_macphy", 0, RV1108_CLKGATE_CON(4), 7, GFLAGS),
 
-       MMC(SCLK_SDMMC_DRV,    "sdmmc_drv",    "sclk_sdmmc", RK1108_SDMMC_CON0, 1),
-       MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RK1108_SDMMC_CON1, 1),
+       MMC(SCLK_SDMMC_DRV,    "sdmmc_drv",    "sclk_sdmmc", RV1108_SDMMC_CON0, 1),
+       MMC(SCLK_SDMMC_SAMPLE, "sdmmc_sample", "sclk_sdmmc", RV1108_SDMMC_CON1, 1),
 
-       MMC(SCLK_SDIO_DRV,     "sdio_drv",     "sclk_sdio",  RK1108_SDIO_CON0,  1),
-       MMC(SCLK_SDIO_SAMPLE,  "sdio_sample",  "sclk_sdio",  RK1108_SDIO_CON1,  1),
+       MMC(SCLK_SDIO_DRV,     "sdio_drv",     "sclk_sdio",  RV1108_SDIO_CON0,  1),
+       MMC(SCLK_SDIO_SAMPLE,  "sdio_sample",  "sclk_sdio",  RV1108_SDIO_CON1,  1),
 
-       MMC(SCLK_EMMC_DRV,     "emmc_drv",     "sclk_emmc",  RK1108_EMMC_CON0,  1),
-       MMC(SCLK_EMMC_SAMPLE,  "emmc_sample",  "sclk_emmc",  RK1108_EMMC_CON1,  1),
+       MMC(SCLK_EMMC_DRV,     "emmc_drv",     "sclk_emmc",  RV1108_EMMC_CON0,  1),
+       MMC(SCLK_EMMC_SAMPLE,  "emmc_sample",  "sclk_emmc",  RV1108_EMMC_CON1,  1),
 };
 
-static const char *const rk1108_critical_clocks[] __initconst = {
+static const char *const rv1108_critical_clocks[] __initconst = {
        "aclk_core",
        "aclk_bus_src_gpll",
        "aclk_periph",
@@ -490,7 +490,7 @@ static const char *const rk1108_critical_clocks[] __initconst = {
        "pclk_periph",
 };
 
-static void __init rk1108_clk_init(struct device_node *np)
+static void __init rv1108_clk_init(struct device_node *np)
 {
        struct rockchip_clk_provider *ctx;
        void __iomem *reg_base;
@@ -508,24 +508,24 @@ static void __init rk1108_clk_init(struct device_node *np)
                return;
        }
 
-       rockchip_clk_register_plls(ctx, rk1108_pll_clks,
-                                  ARRAY_SIZE(rk1108_pll_clks),
-                                  RK1108_GRF_SOC_STATUS0);
-       rockchip_clk_register_branches(ctx, rk1108_clk_branches,
-                                 ARRAY_SIZE(rk1108_clk_branches));
-       rockchip_clk_protect_critical(rk1108_critical_clocks,
-                                     ARRAY_SIZE(rk1108_critical_clocks));
+       rockchip_clk_register_plls(ctx, rv1108_pll_clks,
+                                  ARRAY_SIZE(rv1108_pll_clks),
+                                  RV1108_GRF_SOC_STATUS0);
+       rockchip_clk_register_branches(ctx, rv1108_clk_branches,
+                                 ARRAY_SIZE(rv1108_clk_branches));
+       rockchip_clk_protect_critical(rv1108_critical_clocks,
+                                     ARRAY_SIZE(rv1108_critical_clocks));
 
        rockchip_clk_register_armclk(ctx, ARMCLK, "armclk",
                        mux_armclk_p, ARRAY_SIZE(mux_armclk_p),
-                       &rk1108_cpuclk_data, rk1108_cpuclk_rates,
-                       ARRAY_SIZE(rk1108_cpuclk_rates));
+                       &rv1108_cpuclk_data, rv1108_cpuclk_rates,
+                       ARRAY_SIZE(rv1108_cpuclk_rates));
 
-       rockchip_register_softrst(np, 13, reg_base + RK1108_SOFTRST_CON(0),
+       rockchip_register_softrst(np, 13, reg_base + RV1108_SOFTRST_CON(0),
                                  ROCKCHIP_SOFTRST_HIWORD_MASK);
 
-       rockchip_register_restart_notifier(ctx, RK1108_GLB_SRST_FST, NULL);
+       rockchip_register_restart_notifier(ctx, RV1108_GLB_SRST_FST, NULL);
 
        rockchip_clk_of_add_provider(np, ctx);
 }
-CLK_OF_DECLARE(rk1108_cru, "rockchip,rk1108-cru", rk1108_clk_init);
+CLK_OF_DECLARE(rv1108_cru, "rockchip,rv1108-cru", rv1108_clk_init);
index 7c15473ea72b233070238201100bc10c8c2de240..ef601dded32c49c217b625e893c1ddac20d78cd1 100644 (file)
@@ -34,20 +34,20 @@ struct clk;
 #define HIWORD_UPDATE(val, mask, shift) \
                ((val) << (shift) | (mask) << ((shift) + 16))
 
-/* register positions shared by RK1108, RK2928, RK3036, RK3066, RK3188 and RK3228 */
-#define RK1108_PLL_CON(x)              ((x) * 0x4)
-#define RK1108_CLKSEL_CON(x)           ((x) * 0x4 + 0x60)
-#define RK1108_CLKGATE_CON(x)          ((x) * 0x4 + 0x120)
-#define RK1108_SOFTRST_CON(x)          ((x) * 0x4 + 0x180)
-#define RK1108_GLB_SRST_FST            0x1c0
-#define RK1108_GLB_SRST_SND            0x1c4
-#define RK1108_MISC_CON                        0x1cc
-#define RK1108_SDMMC_CON0              0x1d8
-#define RK1108_SDMMC_CON1              0x1dc
-#define RK1108_SDIO_CON0               0x1e0
-#define RK1108_SDIO_CON1               0x1e4
-#define RK1108_EMMC_CON0               0x1e8
-#define RK1108_EMMC_CON1               0x1ec
+/* register positions shared by RV1108, RK2928, RK3036, RK3066, RK3188 and RK3228 */
+#define RV1108_PLL_CON(x)              ((x) * 0x4)
+#define RV1108_CLKSEL_CON(x)           ((x) * 0x4 + 0x60)
+#define RV1108_CLKGATE_CON(x)          ((x) * 0x4 + 0x120)
+#define RV1108_SOFTRST_CON(x)          ((x) * 0x4 + 0x180)
+#define RV1108_GLB_SRST_FST            0x1c0
+#define RV1108_GLB_SRST_SND            0x1c4
+#define RV1108_MISC_CON                        0x1cc
+#define RV1108_SDMMC_CON0              0x1d8
+#define RV1108_SDMMC_CON1              0x1dc
+#define RV1108_SDIO_CON0               0x1e0
+#define RV1108_SDIO_CON1               0x1e4
+#define RV1108_EMMC_CON0               0x1e8
+#define RV1108_EMMC_CON1               0x1ec
 
 #define RK2928_PLL_CON(x)              ((x) * 0x4)
 #define RK2928_MODE_CON                0x40
index 7c9383c3c2c6085ab4e2ae18dff0b8e3df8ee372..f911d9f7776320a602a7894c664d5f875cf3be44 100644 (file)
@@ -313,7 +313,7 @@ void __init spear6xx_clk_init(void __iomem *misc_base)
        /* clock derived from apb clk */
        clk = clk_register_gate(NULL, "adc_clk", "apb_clk", 0, PERIP1_CLK_ENB,
                        ADC_CLK_ENB, 0, &_lock);
-       clk_register_clkdev(clk, NULL, "adc");
+       clk_register_clkdev(clk, NULL, "d820b000.adc");
 
        clk = clk_register_fixed_factor(NULL, "gpio0_clk", "apb_clk", 0, 1, 1);
        clk_register_clkdev(clk, NULL, "f0100000.gpio");
index a077ab6edffae759564362b85fd596887ea7e89a..b0d551a8efe4d6d31114bc4f2cb3347173606cd9 100644 (file)
@@ -64,6 +64,7 @@ config SUN50I_A64_CCU
        select SUNXI_CCU_MP
        select SUNXI_CCU_PHASE
        default ARM64 && ARCH_SUNXI
+       depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST
 
 config SUN5I_CCU
        bool "Support for the Allwinner sun5i family CCM"
@@ -75,6 +76,7 @@ config SUN5I_CCU
        select SUNXI_CCU_MP
        select SUNXI_CCU_PHASE
        default MACH_SUN5I
+       depends on MACH_SUN5I || COMPILE_TEST
 
 config SUN6I_A31_CCU
        bool "Support for the Allwinner A31/A31s CCU"
@@ -86,6 +88,7 @@ config SUN6I_A31_CCU
        select SUNXI_CCU_MP
        select SUNXI_CCU_PHASE
        default MACH_SUN6I
+       depends on MACH_SUN6I || COMPILE_TEST
 
 config SUN8I_A23_CCU
        bool "Support for the Allwinner A23 CCU"
@@ -98,6 +101,7 @@ config SUN8I_A23_CCU
        select SUNXI_CCU_MP
        select SUNXI_CCU_PHASE
        default MACH_SUN8I
+       depends on MACH_SUN8I || COMPILE_TEST
 
 config SUN8I_A33_CCU
        bool "Support for the Allwinner A33 CCU"
@@ -110,6 +114,7 @@ config SUN8I_A33_CCU
        select SUNXI_CCU_MP
        select SUNXI_CCU_PHASE
        default MACH_SUN8I
+       depends on MACH_SUN8I || COMPILE_TEST
 
 config SUN8I_H3_CCU
        bool "Support for the Allwinner H3 CCU"
@@ -120,7 +125,8 @@ config SUN8I_H3_CCU
        select SUNXI_CCU_NM
        select SUNXI_CCU_MP
        select SUNXI_CCU_PHASE
-       default MACH_SUN8I
+       default MACH_SUN8I || (ARM64 && ARCH_SUNXI)
+       depends on MACH_SUN8I || (ARM64 && ARCH_SUNXI) || COMPILE_TEST
 
 config SUN8I_V3S_CCU
        bool "Support for the Allwinner V3s CCU"
@@ -132,6 +138,7 @@ config SUN8I_V3S_CCU
        select SUNXI_CCU_MP
        select SUNXI_CCU_PHASE
        default MACH_SUN8I
+       depends on MACH_SUN8I || COMPILE_TEST
 
 config SUN9I_A80_CCU
        bool "Support for the Allwinner A80 CCU"
@@ -143,5 +150,12 @@ config SUN9I_A80_CCU
        select SUNXI_CCU_MP
        select SUNXI_CCU_PHASE
        default MACH_SUN9I
+       depends on MACH_SUN9I || COMPILE_TEST
+
+config SUN8I_R_CCU
+       bool "Support for Allwinner SoCs' PRCM CCUs"
+       select SUNXI_CCU_DIV
+       select SUNXI_CCU_GATE
+       default MACH_SUN8I || (ARCH_SUNXI && ARM64)
 
 endif
index 6feaac0c5600f883f18f7f3adc99d03abcdb2d75..0ec02fe14c502c595ede0139aae8c4095cd8869d 100644 (file)
@@ -25,6 +25,7 @@ obj-$(CONFIG_SUN8I_A23_CCU)   += ccu-sun8i-a23.o
 obj-$(CONFIG_SUN8I_A33_CCU)    += ccu-sun8i-a33.o
 obj-$(CONFIG_SUN8I_H3_CCU)     += ccu-sun8i-h3.o
 obj-$(CONFIG_SUN8I_V3S_CCU)    += ccu-sun8i-v3s.o
+obj-$(CONFIG_SUN8I_R_CCU)      += ccu-sun8i-r.o
 obj-$(CONFIG_SUN9I_A80_CCU)    += ccu-sun9i-a80.o
 obj-$(CONFIG_SUN9I_A80_CCU)    += ccu-sun9i-a80-de.o
 obj-$(CONFIG_SUN9I_A80_CCU)    += ccu-sun9i-a80-usb.o
index 06edaa523479ca82c81dc052806596707159bea2..5c476f966a7220c468799f5011b9994eb23c3ad4 100644 (file)
@@ -469,7 +469,7 @@ static const char * const csi_parents[] = { "hosc", "pll-video0", "pll-video1",
 static const u8 csi_table[] = { 0, 1, 2, 5, 6 };
 static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(csi_clk, "csi",
                                       csi_parents, csi_table,
-                                      0x134, 0, 5, 24, 2, BIT(31), 0);
+                                      0x134, 0, 5, 24, 3, BIT(31), 0);
 
 static SUNXI_CCU_GATE(ve_clk,          "ve",           "pll-ve",
                      0x13c, BIT(31), CLK_SET_RATE_PARENT);
index 2c69b631967aea3ae81389d29b20e8014c3030e1..8d38e6510e2959646a3959222e590f8fd4adc9a2 100644 (file)
@@ -159,13 +159,17 @@ static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK(pll_de_clk, "pll-de",
                                        BIT(28),        /* lock */
                                        CLK_SET_RATE_UNGATE);
 
-/* TODO: Fix N */
-static SUNXI_CCU_N_WITH_GATE_LOCK(pll_ddr1_clk, "pll-ddr1",
-                                 "osc24M", 0x04c,
-                                 8, 6,                 /* N */
-                                 BIT(31),              /* gate */
-                                 BIT(28),              /* lock */
-                                 CLK_SET_RATE_UNGATE);
+static struct ccu_mult pll_ddr1_clk = {
+       .enable = BIT(31),
+       .lock   = BIT(28),
+       .mult   = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 6, 0, 12, 0),
+       .common = {
+               .reg            = 0x04c,
+               .hw.init        = CLK_HW_INIT("pll-ddr1", "osc24M",
+                                             &ccu_mult_ops,
+                                             CLK_SET_RATE_UNGATE),
+       },
+};
 
 static const char * const cpux_parents[] = { "osc32k", "osc24M",
                                             "pll-cpux" , "pll-cpux" };
index a26c8a19fe93a2b8f1f768b414cb678f364d5542..4cbc1b701b7cf51d1131f34b934a533e48472a63 100644 (file)
@@ -300,8 +300,10 @@ static SUNXI_CCU_GATE(bus_uart2_clk,       "bus-uart2",    "apb2",
                      0x06c, BIT(18), 0);
 static SUNXI_CCU_GATE(bus_uart3_clk,   "bus-uart3",    "apb2",
                      0x06c, BIT(19), 0);
-static SUNXI_CCU_GATE(bus_scr_clk,     "bus-scr",      "apb2",
+static SUNXI_CCU_GATE(bus_scr0_clk,    "bus-scr0",     "apb2",
                      0x06c, BIT(20), 0);
+static SUNXI_CCU_GATE(bus_scr1_clk,    "bus-scr1",     "apb2",
+                     0x06c, BIT(21), 0);
 
 static SUNXI_CCU_GATE(bus_ephy_clk,    "bus-ephy",     "ahb1",
                      0x070, BIT(0), 0);
@@ -546,7 +548,7 @@ static struct ccu_common *sun8i_h3_ccu_clks[] = {
        &bus_uart1_clk.common,
        &bus_uart2_clk.common,
        &bus_uart3_clk.common,
-       &bus_scr_clk.common,
+       &bus_scr0_clk.common,
        &bus_ephy_clk.common,
        &bus_dbg_clk.common,
        &ths_clk.common,
@@ -597,6 +599,114 @@ static struct ccu_common *sun8i_h3_ccu_clks[] = {
        &gpu_clk.common,
 };
 
+static struct ccu_common *sun50i_h5_ccu_clks[] = {
+       &pll_cpux_clk.common,
+       &pll_audio_base_clk.common,
+       &pll_video_clk.common,
+       &pll_ve_clk.common,
+       &pll_ddr_clk.common,
+       &pll_periph0_clk.common,
+       &pll_gpu_clk.common,
+       &pll_periph1_clk.common,
+       &pll_de_clk.common,
+       &cpux_clk.common,
+       &axi_clk.common,
+       &ahb1_clk.common,
+       &apb1_clk.common,
+       &apb2_clk.common,
+       &ahb2_clk.common,
+       &bus_ce_clk.common,
+       &bus_dma_clk.common,
+       &bus_mmc0_clk.common,
+       &bus_mmc1_clk.common,
+       &bus_mmc2_clk.common,
+       &bus_nand_clk.common,
+       &bus_dram_clk.common,
+       &bus_emac_clk.common,
+       &bus_ts_clk.common,
+       &bus_hstimer_clk.common,
+       &bus_spi0_clk.common,
+       &bus_spi1_clk.common,
+       &bus_otg_clk.common,
+       &bus_ehci0_clk.common,
+       &bus_ehci1_clk.common,
+       &bus_ehci2_clk.common,
+       &bus_ehci3_clk.common,
+       &bus_ohci0_clk.common,
+       &bus_ohci1_clk.common,
+       &bus_ohci2_clk.common,
+       &bus_ohci3_clk.common,
+       &bus_ve_clk.common,
+       &bus_tcon0_clk.common,
+       &bus_tcon1_clk.common,
+       &bus_deinterlace_clk.common,
+       &bus_csi_clk.common,
+       &bus_tve_clk.common,
+       &bus_hdmi_clk.common,
+       &bus_de_clk.common,
+       &bus_gpu_clk.common,
+       &bus_msgbox_clk.common,
+       &bus_spinlock_clk.common,
+       &bus_codec_clk.common,
+       &bus_spdif_clk.common,
+       &bus_pio_clk.common,
+       &bus_ths_clk.common,
+       &bus_i2s0_clk.common,
+       &bus_i2s1_clk.common,
+       &bus_i2s2_clk.common,
+       &bus_i2c0_clk.common,
+       &bus_i2c1_clk.common,
+       &bus_i2c2_clk.common,
+       &bus_uart0_clk.common,
+       &bus_uart1_clk.common,
+       &bus_uart2_clk.common,
+       &bus_uart3_clk.common,
+       &bus_scr0_clk.common,
+       &bus_scr1_clk.common,
+       &bus_ephy_clk.common,
+       &bus_dbg_clk.common,
+       &ths_clk.common,
+       &nand_clk.common,
+       &mmc0_clk.common,
+       &mmc1_clk.common,
+       &mmc2_clk.common,
+       &ts_clk.common,
+       &ce_clk.common,
+       &spi0_clk.common,
+       &spi1_clk.common,
+       &i2s0_clk.common,
+       &i2s1_clk.common,
+       &i2s2_clk.common,
+       &spdif_clk.common,
+       &usb_phy0_clk.common,
+       &usb_phy1_clk.common,
+       &usb_phy2_clk.common,
+       &usb_phy3_clk.common,
+       &usb_ohci0_clk.common,
+       &usb_ohci1_clk.common,
+       &usb_ohci2_clk.common,
+       &usb_ohci3_clk.common,
+       &dram_clk.common,
+       &dram_ve_clk.common,
+       &dram_csi_clk.common,
+       &dram_deinterlace_clk.common,
+       &dram_ts_clk.common,
+       &de_clk.common,
+       &tcon_clk.common,
+       &tve_clk.common,
+       &deinterlace_clk.common,
+       &csi_misc_clk.common,
+       &csi_sclk_clk.common,
+       &csi_mclk_clk.common,
+       &ve_clk.common,
+       &ac_dig_clk.common,
+       &avs_clk.common,
+       &hdmi_clk.common,
+       &hdmi_ddc_clk.common,
+       &mbus_clk.common,
+       &gpu_clk.common,
+};
+
 /* We hardcode the divider to 4 for now */
 static CLK_FIXED_FACTOR(pll_audio_clk, "pll-audio",
                        "pll-audio-base", 4, 1, CLK_SET_RATE_PARENT);
@@ -677,7 +787,7 @@ static struct clk_hw_onecell_data sun8i_h3_hw_clks = {
                [CLK_BUS_UART1]         = &bus_uart1_clk.common.hw,
                [CLK_BUS_UART2]         = &bus_uart2_clk.common.hw,
                [CLK_BUS_UART3]         = &bus_uart3_clk.common.hw,
-               [CLK_BUS_SCR]           = &bus_scr_clk.common.hw,
+               [CLK_BUS_SCR0]          = &bus_scr0_clk.common.hw,
                [CLK_BUS_EPHY]          = &bus_ephy_clk.common.hw,
                [CLK_BUS_DBG]           = &bus_dbg_clk.common.hw,
                [CLK_THS]               = &ths_clk.common.hw,
@@ -727,7 +837,123 @@ static struct clk_hw_onecell_data sun8i_h3_hw_clks = {
                [CLK_MBUS]              = &mbus_clk.common.hw,
                [CLK_GPU]               = &gpu_clk.common.hw,
        },
-       .num    = CLK_NUMBER,
+       .num    = CLK_NUMBER_H3,
+};
+
+static struct clk_hw_onecell_data sun50i_h5_hw_clks = {
+       .hws    = {
+               [CLK_PLL_CPUX]          = &pll_cpux_clk.common.hw,
+               [CLK_PLL_AUDIO_BASE]    = &pll_audio_base_clk.common.hw,
+               [CLK_PLL_AUDIO]         = &pll_audio_clk.hw,
+               [CLK_PLL_AUDIO_2X]      = &pll_audio_2x_clk.hw,
+               [CLK_PLL_AUDIO_4X]      = &pll_audio_4x_clk.hw,
+               [CLK_PLL_AUDIO_8X]      = &pll_audio_8x_clk.hw,
+               [CLK_PLL_VIDEO]         = &pll_video_clk.common.hw,
+               [CLK_PLL_VE]            = &pll_ve_clk.common.hw,
+               [CLK_PLL_DDR]           = &pll_ddr_clk.common.hw,
+               [CLK_PLL_PERIPH0]       = &pll_periph0_clk.common.hw,
+               [CLK_PLL_PERIPH0_2X]    = &pll_periph0_2x_clk.hw,
+               [CLK_PLL_GPU]           = &pll_gpu_clk.common.hw,
+               [CLK_PLL_PERIPH1]       = &pll_periph1_clk.common.hw,
+               [CLK_PLL_DE]            = &pll_de_clk.common.hw,
+               [CLK_CPUX]              = &cpux_clk.common.hw,
+               [CLK_AXI]               = &axi_clk.common.hw,
+               [CLK_AHB1]              = &ahb1_clk.common.hw,
+               [CLK_APB1]              = &apb1_clk.common.hw,
+               [CLK_APB2]              = &apb2_clk.common.hw,
+               [CLK_AHB2]              = &ahb2_clk.common.hw,
+               [CLK_BUS_CE]            = &bus_ce_clk.common.hw,
+               [CLK_BUS_DMA]           = &bus_dma_clk.common.hw,
+               [CLK_BUS_MMC0]          = &bus_mmc0_clk.common.hw,
+               [CLK_BUS_MMC1]          = &bus_mmc1_clk.common.hw,
+               [CLK_BUS_MMC2]          = &bus_mmc2_clk.common.hw,
+               [CLK_BUS_NAND]          = &bus_nand_clk.common.hw,
+               [CLK_BUS_DRAM]          = &bus_dram_clk.common.hw,
+               [CLK_BUS_EMAC]          = &bus_emac_clk.common.hw,
+               [CLK_BUS_TS]            = &bus_ts_clk.common.hw,
+               [CLK_BUS_HSTIMER]       = &bus_hstimer_clk.common.hw,
+               [CLK_BUS_SPI0]          = &bus_spi0_clk.common.hw,
+               [CLK_BUS_SPI1]          = &bus_spi1_clk.common.hw,
+               [CLK_BUS_OTG]           = &bus_otg_clk.common.hw,
+               [CLK_BUS_EHCI0]         = &bus_ehci0_clk.common.hw,
+               [CLK_BUS_EHCI1]         = &bus_ehci1_clk.common.hw,
+               [CLK_BUS_EHCI2]         = &bus_ehci2_clk.common.hw,
+               [CLK_BUS_EHCI3]         = &bus_ehci3_clk.common.hw,
+               [CLK_BUS_OHCI0]         = &bus_ohci0_clk.common.hw,
+               [CLK_BUS_OHCI1]         = &bus_ohci1_clk.common.hw,
+               [CLK_BUS_OHCI2]         = &bus_ohci2_clk.common.hw,
+               [CLK_BUS_OHCI3]         = &bus_ohci3_clk.common.hw,
+               [CLK_BUS_VE]            = &bus_ve_clk.common.hw,
+               [CLK_BUS_TCON0]         = &bus_tcon0_clk.common.hw,
+               [CLK_BUS_TCON1]         = &bus_tcon1_clk.common.hw,
+               [CLK_BUS_DEINTERLACE]   = &bus_deinterlace_clk.common.hw,
+               [CLK_BUS_CSI]           = &bus_csi_clk.common.hw,
+               [CLK_BUS_TVE]           = &bus_tve_clk.common.hw,
+               [CLK_BUS_HDMI]          = &bus_hdmi_clk.common.hw,
+               [CLK_BUS_DE]            = &bus_de_clk.common.hw,
+               [CLK_BUS_GPU]           = &bus_gpu_clk.common.hw,
+               [CLK_BUS_MSGBOX]        = &bus_msgbox_clk.common.hw,
+               [CLK_BUS_SPINLOCK]      = &bus_spinlock_clk.common.hw,
+               [CLK_BUS_CODEC]         = &bus_codec_clk.common.hw,
+               [CLK_BUS_SPDIF]         = &bus_spdif_clk.common.hw,
+               [CLK_BUS_PIO]           = &bus_pio_clk.common.hw,
+               [CLK_BUS_THS]           = &bus_ths_clk.common.hw,
+               [CLK_BUS_I2S0]          = &bus_i2s0_clk.common.hw,
+               [CLK_BUS_I2S1]          = &bus_i2s1_clk.common.hw,
+               [CLK_BUS_I2S2]          = &bus_i2s2_clk.common.hw,
+               [CLK_BUS_I2C0]          = &bus_i2c0_clk.common.hw,
+               [CLK_BUS_I2C1]          = &bus_i2c1_clk.common.hw,
+               [CLK_BUS_I2C2]          = &bus_i2c2_clk.common.hw,
+               [CLK_BUS_UART0]         = &bus_uart0_clk.common.hw,
+               [CLK_BUS_UART1]         = &bus_uart1_clk.common.hw,
+               [CLK_BUS_UART2]         = &bus_uart2_clk.common.hw,
+               [CLK_BUS_UART3]         = &bus_uart3_clk.common.hw,
+               [CLK_BUS_SCR0]          = &bus_scr0_clk.common.hw,
+               [CLK_BUS_SCR1]          = &bus_scr1_clk.common.hw,
+               [CLK_BUS_EPHY]          = &bus_ephy_clk.common.hw,
+               [CLK_BUS_DBG]           = &bus_dbg_clk.common.hw,
+               [CLK_THS]               = &ths_clk.common.hw,
+               [CLK_NAND]              = &nand_clk.common.hw,
+               [CLK_MMC0]              = &mmc0_clk.common.hw,
+               [CLK_MMC1]              = &mmc1_clk.common.hw,
+               [CLK_MMC2]              = &mmc2_clk.common.hw,
+               [CLK_TS]                = &ts_clk.common.hw,
+               [CLK_CE]                = &ce_clk.common.hw,
+               [CLK_SPI0]              = &spi0_clk.common.hw,
+               [CLK_SPI1]              = &spi1_clk.common.hw,
+               [CLK_I2S0]              = &i2s0_clk.common.hw,
+               [CLK_I2S1]              = &i2s1_clk.common.hw,
+               [CLK_I2S2]              = &i2s2_clk.common.hw,
+               [CLK_SPDIF]             = &spdif_clk.common.hw,
+               [CLK_USB_PHY0]          = &usb_phy0_clk.common.hw,
+               [CLK_USB_PHY1]          = &usb_phy1_clk.common.hw,
+               [CLK_USB_PHY2]          = &usb_phy2_clk.common.hw,
+               [CLK_USB_PHY3]          = &usb_phy3_clk.common.hw,
+               [CLK_USB_OHCI0]         = &usb_ohci0_clk.common.hw,
+               [CLK_USB_OHCI1]         = &usb_ohci1_clk.common.hw,
+               [CLK_USB_OHCI2]         = &usb_ohci2_clk.common.hw,
+               [CLK_USB_OHCI3]         = &usb_ohci3_clk.common.hw,
+               [CLK_DRAM]              = &dram_clk.common.hw,
+               [CLK_DRAM_VE]           = &dram_ve_clk.common.hw,
+               [CLK_DRAM_CSI]          = &dram_csi_clk.common.hw,
+               [CLK_DRAM_DEINTERLACE]  = &dram_deinterlace_clk.common.hw,
+               [CLK_DRAM_TS]           = &dram_ts_clk.common.hw,
+               [CLK_DE]                = &de_clk.common.hw,
+               [CLK_TCON0]             = &tcon_clk.common.hw,
+               [CLK_TVE]               = &tve_clk.common.hw,
+               [CLK_DEINTERLACE]       = &deinterlace_clk.common.hw,
+               [CLK_CSI_MISC]          = &csi_misc_clk.common.hw,
+               [CLK_CSI_SCLK]          = &csi_sclk_clk.common.hw,
+               [CLK_CSI_MCLK]          = &csi_mclk_clk.common.hw,
+               [CLK_VE]                = &ve_clk.common.hw,
+               [CLK_AC_DIG]            = &ac_dig_clk.common.hw,
+               [CLK_AVS]               = &avs_clk.common.hw,
+               [CLK_HDMI]              = &hdmi_clk.common.hw,
+               [CLK_HDMI_DDC]          = &hdmi_ddc_clk.common.hw,
+               [CLK_MBUS]              = &mbus_clk.common.hw,
+               [CLK_GPU]               = &gpu_clk.common.hw,
+       },
+       .num    = CLK_NUMBER_H5,
 };
 
 static struct ccu_reset_map sun8i_h3_ccu_resets[] = {
@@ -790,7 +1016,71 @@ static struct ccu_reset_map sun8i_h3_ccu_resets[] = {
        [RST_BUS_UART1]         =  { 0x2d8, BIT(17) },
        [RST_BUS_UART2]         =  { 0x2d8, BIT(18) },
        [RST_BUS_UART3]         =  { 0x2d8, BIT(19) },
-       [RST_BUS_SCR]           =  { 0x2d8, BIT(20) },
+       [RST_BUS_SCR0]          =  { 0x2d8, BIT(20) },
+};
+
+static struct ccu_reset_map sun50i_h5_ccu_resets[] = {
+       [RST_USB_PHY0]          =  { 0x0cc, BIT(0) },
+       [RST_USB_PHY1]          =  { 0x0cc, BIT(1) },
+       [RST_USB_PHY2]          =  { 0x0cc, BIT(2) },
+       [RST_USB_PHY3]          =  { 0x0cc, BIT(3) },
+
+       [RST_MBUS]              =  { 0x0fc, BIT(31) },
+
+       [RST_BUS_CE]            =  { 0x2c0, BIT(5) },
+       [RST_BUS_DMA]           =  { 0x2c0, BIT(6) },
+       [RST_BUS_MMC0]          =  { 0x2c0, BIT(8) },
+       [RST_BUS_MMC1]          =  { 0x2c0, BIT(9) },
+       [RST_BUS_MMC2]          =  { 0x2c0, BIT(10) },
+       [RST_BUS_NAND]          =  { 0x2c0, BIT(13) },
+       [RST_BUS_DRAM]          =  { 0x2c0, BIT(14) },
+       [RST_BUS_EMAC]          =  { 0x2c0, BIT(17) },
+       [RST_BUS_TS]            =  { 0x2c0, BIT(18) },
+       [RST_BUS_HSTIMER]       =  { 0x2c0, BIT(19) },
+       [RST_BUS_SPI0]          =  { 0x2c0, BIT(20) },
+       [RST_BUS_SPI1]          =  { 0x2c0, BIT(21) },
+       [RST_BUS_OTG]           =  { 0x2c0, BIT(23) },
+       [RST_BUS_EHCI0]         =  { 0x2c0, BIT(24) },
+       [RST_BUS_EHCI1]         =  { 0x2c0, BIT(25) },
+       [RST_BUS_EHCI2]         =  { 0x2c0, BIT(26) },
+       [RST_BUS_EHCI3]         =  { 0x2c0, BIT(27) },
+       [RST_BUS_OHCI0]         =  { 0x2c0, BIT(28) },
+       [RST_BUS_OHCI1]         =  { 0x2c0, BIT(29) },
+       [RST_BUS_OHCI2]         =  { 0x2c0, BIT(30) },
+       [RST_BUS_OHCI3]         =  { 0x2c0, BIT(31) },
+
+       [RST_BUS_VE]            =  { 0x2c4, BIT(0) },
+       [RST_BUS_TCON0]         =  { 0x2c4, BIT(3) },
+       [RST_BUS_TCON1]         =  { 0x2c4, BIT(4) },
+       [RST_BUS_DEINTERLACE]   =  { 0x2c4, BIT(5) },
+       [RST_BUS_CSI]           =  { 0x2c4, BIT(8) },
+       [RST_BUS_TVE]           =  { 0x2c4, BIT(9) },
+       [RST_BUS_HDMI0]         =  { 0x2c4, BIT(10) },
+       [RST_BUS_HDMI1]         =  { 0x2c4, BIT(11) },
+       [RST_BUS_DE]            =  { 0x2c4, BIT(12) },
+       [RST_BUS_GPU]           =  { 0x2c4, BIT(20) },
+       [RST_BUS_MSGBOX]        =  { 0x2c4, BIT(21) },
+       [RST_BUS_SPINLOCK]      =  { 0x2c4, BIT(22) },
+       [RST_BUS_DBG]           =  { 0x2c4, BIT(31) },
+
+       [RST_BUS_EPHY]          =  { 0x2c8, BIT(2) },
+
+       [RST_BUS_CODEC]         =  { 0x2d0, BIT(0) },
+       [RST_BUS_SPDIF]         =  { 0x2d0, BIT(1) },
+       [RST_BUS_THS]           =  { 0x2d0, BIT(8) },
+       [RST_BUS_I2S0]          =  { 0x2d0, BIT(12) },
+       [RST_BUS_I2S1]          =  { 0x2d0, BIT(13) },
+       [RST_BUS_I2S2]          =  { 0x2d0, BIT(14) },
+
+       [RST_BUS_I2C0]          =  { 0x2d8, BIT(0) },
+       [RST_BUS_I2C1]          =  { 0x2d8, BIT(1) },
+       [RST_BUS_I2C2]          =  { 0x2d8, BIT(2) },
+       [RST_BUS_UART0]         =  { 0x2d8, BIT(16) },
+       [RST_BUS_UART1]         =  { 0x2d8, BIT(17) },
+       [RST_BUS_UART2]         =  { 0x2d8, BIT(18) },
+       [RST_BUS_UART3]         =  { 0x2d8, BIT(19) },
+       [RST_BUS_SCR0]          =  { 0x2d8, BIT(20) },
+       [RST_BUS_SCR1]          =  { 0x2d8, BIT(20) },
 };
 
 static const struct sunxi_ccu_desc sun8i_h3_ccu_desc = {
@@ -803,6 +1093,16 @@ static const struct sunxi_ccu_desc sun8i_h3_ccu_desc = {
        .num_resets     = ARRAY_SIZE(sun8i_h3_ccu_resets),
 };
 
+static const struct sunxi_ccu_desc sun50i_h5_ccu_desc = {
+       .ccu_clks       = sun50i_h5_ccu_clks,
+       .num_ccu_clks   = ARRAY_SIZE(sun50i_h5_ccu_clks),
+
+       .hw_clks        = &sun50i_h5_hw_clks,
+
+       .resets         = sun50i_h5_ccu_resets,
+       .num_resets     = ARRAY_SIZE(sun50i_h5_ccu_resets),
+};
+
 static struct ccu_mux_nb sun8i_h3_cpu_nb = {
        .common         = &cpux_clk.common,
        .cm             = &cpux_clk.mux,
@@ -810,7 +1110,8 @@ static struct ccu_mux_nb sun8i_h3_cpu_nb = {
        .bypass_index   = 1, /* index of 24 MHz oscillator */
 };
 
-static void __init sun8i_h3_ccu_setup(struct device_node *node)
+static void __init sunxi_h3_h5_ccu_init(struct device_node *node,
+                                       const struct sunxi_ccu_desc *desc)
 {
        void __iomem *reg;
        u32 val;
@@ -827,10 +1128,22 @@ static void __init sun8i_h3_ccu_setup(struct device_node *node)
        val &= ~GENMASK(19, 16);
        writel(val | (3 << 16), reg + SUN8I_H3_PLL_AUDIO_REG);
 
-       sunxi_ccu_probe(node, reg, &sun8i_h3_ccu_desc);
+       sunxi_ccu_probe(node, reg, desc);
 
        ccu_mux_notifier_register(pll_cpux_clk.common.hw.clk,
                                  &sun8i_h3_cpu_nb);
 }
+
+static void __init sun8i_h3_ccu_setup(struct device_node *node)
+{
+       sunxi_h3_h5_ccu_init(node, &sun8i_h3_ccu_desc);
+}
 CLK_OF_DECLARE(sun8i_h3_ccu, "allwinner,sun8i-h3-ccu",
               sun8i_h3_ccu_setup);
+
+static void __init sun50i_h5_ccu_setup(struct device_node *node)
+{
+       sunxi_h3_h5_ccu_init(node, &sun50i_h5_ccu_desc);
+}
+CLK_OF_DECLARE(sun50i_h5_ccu, "allwinner,sun50i-h5-ccu",
+              sun50i_h5_ccu_setup);
index 78be712c74871948908fb6999412c805562f5451..85973d1e8165f9a085d9e574cc1f822430802c68 100644 (file)
@@ -57,6 +57,7 @@
 
 /* And the GPU module clock is exported */
 
-#define CLK_NUMBER             (CLK_GPU + 1)
+#define CLK_NUMBER_H3          (CLK_GPU + 1)
+#define CLK_NUMBER_H5          (CLK_BUS_SCR1 + 1)
 
 #endif /* _CCU_SUN8I_H3_H_ */
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r.c b/drivers/clk/sunxi-ng/ccu-sun8i-r.c
new file mode 100644 (file)
index 0000000..119f47b
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2016 Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+
+#include "ccu_common.h"
+#include "ccu_reset.h"
+
+#include "ccu_div.h"
+#include "ccu_gate.h"
+#include "ccu_mp.h"
+#include "ccu_nm.h"
+
+#include "ccu-sun8i-r.h"
+
+static const char * const ar100_parents[] = { "osc32k", "osc24M",
+                                            "pll-periph0", "iosc" };
+
+static struct ccu_div ar100_clk = {
+       .div            = _SUNXI_CCU_DIV_FLAGS(4, 2, CLK_DIVIDER_POWER_OF_TWO),
+
+       .mux            = {
+               .shift  = 16,
+               .width  = 2,
+
+               .variable_prediv        = {
+                       .index  = 2,
+                       .shift  = 8,
+                       .width  = 5,
+               },
+       },
+
+       .common         = {
+               .reg            = 0x00,
+               .features       = CCU_FEATURE_VARIABLE_PREDIV,
+               .hw.init        = CLK_HW_INIT_PARENTS("ar100",
+                                                     ar100_parents,
+                                                     &ccu_div_ops,
+                                                     0),
+       },
+};
+
+static CLK_FIXED_FACTOR(ahb0_clk, "ahb0", "ar100", 1, 1, 0);
+
+static struct ccu_div apb0_clk = {
+       .div            = _SUNXI_CCU_DIV_FLAGS(0, 2, CLK_DIVIDER_POWER_OF_TWO),
+
+       .common         = {
+               .reg            = 0x0c,
+               .hw.init        = CLK_HW_INIT("apb0",
+                                             "ahb0",
+                                             &ccu_div_ops,
+                                             0),
+       },
+};
+
+static SUNXI_CCU_GATE(apb0_pio_clk,    "apb0-pio",     "apb0",
+                     0x28, BIT(0), 0);
+static SUNXI_CCU_GATE(apb0_ir_clk,     "apb0-ir",      "apb0",
+                     0x28, BIT(1), 0);
+static SUNXI_CCU_GATE(apb0_timer_clk,  "apb0-timer",   "apb0",
+                     0x28, BIT(2), 0);
+static SUNXI_CCU_GATE(apb0_rsb_clk,    "apb0-rsb",     "apb0",
+                     0x28, BIT(3), 0);
+static SUNXI_CCU_GATE(apb0_uart_clk,   "apb0-uart",    "apb0",
+                     0x28, BIT(4), 0);
+static SUNXI_CCU_GATE(apb0_i2c_clk,    "apb0-i2c",     "apb0",
+                     0x28, BIT(6), 0);
+static SUNXI_CCU_GATE(apb0_twd_clk,    "apb0-twd",     "apb0",
+                     0x28, BIT(7), 0);
+
+static const char * const r_mod0_default_parents[] = { "osc32k", "osc24M" };
+static SUNXI_CCU_MP_WITH_MUX_GATE(ir_clk, "ir",
+                                 r_mod0_default_parents, 0x54,
+                                 0, 4,         /* M */
+                                 16, 2,        /* P */
+                                 24, 2,        /* mux */
+                                 BIT(31),      /* gate */
+                                 0);
+
+static struct ccu_common *sun8i_h3_r_ccu_clks[] = {
+       &ar100_clk.common,
+       &apb0_clk.common,
+       &apb0_pio_clk.common,
+       &apb0_ir_clk.common,
+       &apb0_timer_clk.common,
+       &apb0_uart_clk.common,
+       &apb0_i2c_clk.common,
+       &apb0_twd_clk.common,
+       &ir_clk.common,
+};
+
+static struct ccu_common *sun50i_a64_r_ccu_clks[] = {
+       &ar100_clk.common,
+       &apb0_clk.common,
+       &apb0_pio_clk.common,
+       &apb0_ir_clk.common,
+       &apb0_timer_clk.common,
+       &apb0_rsb_clk.common,
+       &apb0_uart_clk.common,
+       &apb0_i2c_clk.common,
+       &apb0_twd_clk.common,
+       &ir_clk.common,
+};
+
+static struct clk_hw_onecell_data sun8i_h3_r_hw_clks = {
+       .hws    = {
+               [CLK_AR100]             = &ar100_clk.common.hw,
+               [CLK_AHB0]              = &ahb0_clk.hw,
+               [CLK_APB0]              = &apb0_clk.common.hw,
+               [CLK_APB0_PIO]          = &apb0_pio_clk.common.hw,
+               [CLK_APB0_IR]           = &apb0_ir_clk.common.hw,
+               [CLK_APB0_TIMER]        = &apb0_timer_clk.common.hw,
+               [CLK_APB0_UART]         = &apb0_uart_clk.common.hw,
+               [CLK_APB0_I2C]          = &apb0_i2c_clk.common.hw,
+               [CLK_APB0_TWD]          = &apb0_twd_clk.common.hw,
+               [CLK_IR]                = &ir_clk.common.hw,
+       },
+       .num    = CLK_NUMBER,
+};
+
+static struct clk_hw_onecell_data sun50i_a64_r_hw_clks = {
+       .hws    = {
+               [CLK_AR100]             = &ar100_clk.common.hw,
+               [CLK_AHB0]              = &ahb0_clk.hw,
+               [CLK_APB0]              = &apb0_clk.common.hw,
+               [CLK_APB0_PIO]          = &apb0_pio_clk.common.hw,
+               [CLK_APB0_IR]           = &apb0_ir_clk.common.hw,
+               [CLK_APB0_TIMER]        = &apb0_timer_clk.common.hw,
+               [CLK_APB0_RSB]          = &apb0_rsb_clk.common.hw,
+               [CLK_APB0_UART]         = &apb0_uart_clk.common.hw,
+               [CLK_APB0_I2C]          = &apb0_i2c_clk.common.hw,
+               [CLK_APB0_TWD]          = &apb0_twd_clk.common.hw,
+               [CLK_IR]                = &ir_clk.common.hw,
+       },
+       .num    = CLK_NUMBER,
+};
+
+static struct ccu_reset_map sun8i_h3_r_ccu_resets[] = {
+       [RST_APB0_IR]           =  { 0xb0, BIT(1) },
+       [RST_APB0_TIMER]        =  { 0xb0, BIT(2) },
+       [RST_APB0_UART]         =  { 0xb0, BIT(4) },
+       [RST_APB0_I2C]          =  { 0xb0, BIT(6) },
+};
+
+static struct ccu_reset_map sun50i_a64_r_ccu_resets[] = {
+       [RST_APB0_IR]           =  { 0xb0, BIT(1) },
+       [RST_APB0_TIMER]        =  { 0xb0, BIT(2) },
+       [RST_APB0_RSB]          =  { 0xb0, BIT(3) },
+       [RST_APB0_UART]         =  { 0xb0, BIT(4) },
+       [RST_APB0_I2C]          =  { 0xb0, BIT(6) },
+};
+
+static const struct sunxi_ccu_desc sun8i_h3_r_ccu_desc = {
+       .ccu_clks       = sun8i_h3_r_ccu_clks,
+       .num_ccu_clks   = ARRAY_SIZE(sun8i_h3_r_ccu_clks),
+
+       .hw_clks        = &sun8i_h3_r_hw_clks,
+
+       .resets         = sun8i_h3_r_ccu_resets,
+       .num_resets     = ARRAY_SIZE(sun8i_h3_r_ccu_resets),
+};
+
+static const struct sunxi_ccu_desc sun50i_a64_r_ccu_desc = {
+       .ccu_clks       = sun50i_a64_r_ccu_clks,
+       .num_ccu_clks   = ARRAY_SIZE(sun50i_a64_r_ccu_clks),
+
+       .hw_clks        = &sun50i_a64_r_hw_clks,
+
+       .resets         = sun50i_a64_r_ccu_resets,
+       .num_resets     = ARRAY_SIZE(sun50i_a64_r_ccu_resets),
+};
+
+static void __init sunxi_r_ccu_init(struct device_node *node,
+                                   const struct sunxi_ccu_desc *desc)
+{
+       void __iomem *reg;
+
+       reg = of_io_request_and_map(node, 0, of_node_full_name(node));
+       if (IS_ERR(reg)) {
+               pr_err("%s: Could not map the clock registers\n",
+                      of_node_full_name(node));
+               return;
+       }
+
+       sunxi_ccu_probe(node, reg, desc);
+}
+
+static void __init sun8i_h3_r_ccu_setup(struct device_node *node)
+{
+       sunxi_r_ccu_init(node, &sun8i_h3_r_ccu_desc);
+}
+CLK_OF_DECLARE(sun8i_h3_r_ccu, "allwinner,sun8i-h3-r-ccu",
+              sun8i_h3_r_ccu_setup);
+
+static void __init sun50i_a64_r_ccu_setup(struct device_node *node)
+{
+       sunxi_r_ccu_init(node, &sun50i_a64_r_ccu_desc);
+}
+CLK_OF_DECLARE(sun50i_a64_r_ccu, "allwinner,sun50i-a64-r-ccu",
+              sun50i_a64_r_ccu_setup);
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r.h b/drivers/clk/sunxi-ng/ccu-sun8i-r.h
new file mode 100644 (file)
index 0000000..a7a407f
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2016 Icenowy <icenowy@aosc.xyz>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CCU_SUN8I_R_H
+#define _CCU_SUN8I_R_H_
+
+#include <dt-bindings/clock/sun8i-r-ccu.h>
+#include <dt-bindings/reset/sun8i-r-ccu.h>
+
+/* AHB/APB bus clocks are not exported */
+#define CLK_AHB0       1
+#define CLK_APB0       2
+
+#define CLK_NUMBER     (CLK_IR + 1)
+
+#endif /* _CCU_SUN8I_R_H */
index e13e313ce4f5638e426c8a7c9e002648cd63b949..8936ef87652c093aade64063c9aa710d8064fbc7 100644 (file)
 
 #define CCU_SUN9I_LOCK_REG     0x09c
 
-static struct clk_div_table pll_cpux_p_div_table[] = {
-       { .val = 0, .div = 1 },
-       { .val = 1, .div = 4 },
-       { /* Sentinel */ },
-};
-
 /*
- * The CPU PLLs are actually NP clocks, but P is /1 or /4, so here we
- * use the NM clocks with a divider table for M.
+ * The CPU PLLs are actually NP clocks, with P being /1 or /4. However
+ * P should only be used for output frequencies lower than 228 MHz.
+ * Neither mainline Linux, U-boot, nor the vendor BSPs use these.
+ *
+ * For now we can just model it as a multiplier clock, and force P to /1.
  */
-static struct ccu_nm pll_c0cpux_clk = {
+#define SUN9I_A80_PLL_C0CPUX_REG       0x000
+#define SUN9I_A80_PLL_C1CPUX_REG       0x004
+
+static struct ccu_mult pll_c0cpux_clk = {
        .enable         = BIT(31),
        .lock           = BIT(0),
-       .n              = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
-       .m              = _SUNXI_CCU_DIV_TABLE(16, 1, pll_cpux_p_div_table),
+       .mult           = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
        .common         = {
-               .reg            = 0x000,
+               .reg            = SUN9I_A80_PLL_C0CPUX_REG,
                .lock_reg       = CCU_SUN9I_LOCK_REG,
                .features       = CCU_FEATURE_LOCK_REG,
                .hw.init        = CLK_HW_INIT("pll-c0cpux", "osc24M",
-                                             &ccu_nm_ops, CLK_SET_RATE_UNGATE),
+                                             &ccu_mult_ops,
+                                             CLK_SET_RATE_UNGATE),
        },
 };
 
-static struct ccu_nm pll_c1cpux_clk = {
+static struct ccu_mult pll_c1cpux_clk = {
        .enable         = BIT(31),
        .lock           = BIT(1),
-       .n              = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
-       .m              = _SUNXI_CCU_DIV_TABLE(16, 1, pll_cpux_p_div_table),
+       .mult           = _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
        .common         = {
-               .reg            = 0x004,
+               .reg            = SUN9I_A80_PLL_C1CPUX_REG,
                .lock_reg       = CCU_SUN9I_LOCK_REG,
                .features       = CCU_FEATURE_LOCK_REG,
                .hw.init        = CLK_HW_INIT("pll-c1cpux", "osc24M",
-                                             &ccu_nm_ops, CLK_SET_RATE_UNGATE),
+                                             &ccu_mult_ops,
+                                             CLK_SET_RATE_UNGATE),
        },
 };
 
 /*
  * The Audio PLL has d1, d2 dividers in addition to the usual N, M
  * factors. Since we only need 2 frequencies from this PLL: 22.5792 MHz
- * and 24.576 MHz, ignore them for now. Enforce the default for them,
- * which is d1 = 0, d2 = 1.
+ * and 24.576 MHz, ignore them for now. Enforce d1 = 0 and d2 = 0.
  */
 #define SUN9I_A80_PLL_AUDIO_REG        0x008
 
@@ -1189,6 +1188,36 @@ static const struct sunxi_ccu_desc sun9i_a80_ccu_desc = {
        .num_resets     = ARRAY_SIZE(sun9i_a80_ccu_resets),
 };
 
+#define SUN9I_A80_PLL_P_SHIFT  16
+#define SUN9I_A80_PLL_N_SHIFT  8
+#define SUN9I_A80_PLL_N_WIDTH  8
+
+static void sun9i_a80_cpu_pll_fixup(void __iomem *reg)
+{
+       u32 val = readl(reg);
+
+       /* bail out if P divider is not used */
+       if (!(val & BIT(SUN9I_A80_PLL_P_SHIFT)))
+               return;
+
+       /*
+        * If P is used, output should be less than 288 MHz. When we
+        * set P to 1, we should also decrease the multiplier so the
+        * output doesn't go out of range, but not too much such that
+        * the multiplier stays above 12, the minimal operation value.
+        *
+        * To keep it simple, set the multiplier to 17, the reset value.
+        */
+       val &= ~GENMASK(SUN9I_A80_PLL_N_SHIFT + SUN9I_A80_PLL_N_WIDTH - 1,
+                       SUN9I_A80_PLL_N_SHIFT);
+       val |= 17 << SUN9I_A80_PLL_N_SHIFT;
+
+       /* And clear P */
+       val &= ~BIT(SUN9I_A80_PLL_P_SHIFT);
+
+       writel(val, reg);
+}
+
 static int sun9i_a80_ccu_probe(struct platform_device *pdev)
 {
        struct resource *res;
@@ -1205,6 +1234,10 @@ static int sun9i_a80_ccu_probe(struct platform_device *pdev)
        val &= (BIT(16) & BIT(18));
        writel(val, reg + SUN9I_A80_PLL_AUDIO_REG);
 
+       /* Enforce P = 1 for both CPU cluster PLLs */
+       sun9i_a80_cpu_pll_fixup(reg + SUN9I_A80_PLL_C0CPUX_REG);
+       sun9i_a80_cpu_pll_fixup(reg + SUN9I_A80_PLL_C1CPUX_REG);
+
        return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun9i_a80_ccu_desc);
 }
 
index 9d8724715a4352ddd07a411945bc1cd58367053d..40aac316128f950e7cac3b469beb4d9d30ed1ba7 100644 (file)
@@ -112,8 +112,8 @@ int sunxi_ccu_probe(struct device_node *node, void __iomem *reg,
 
                ret = clk_hw_register(NULL, hw);
                if (ret) {
-                       pr_err("Couldn't register clock %s\n",
-                              clk_hw_get_name(hw));
+                       pr_err("Couldn't register clock %d - %s\n",
+                              i, clk_hw_get_name(hw));
                        goto err_clk_unreg;
                }
        }
index 8a81f9d4a89fc9b5e8a109fca1daca3771e38cf3..cd069d5da2150e116d043a06e86597e4a2264f85 100644 (file)
@@ -75,8 +75,55 @@ static int ccu_gate_is_enabled(struct clk_hw *hw)
        return ccu_gate_helper_is_enabled(&cg->common, cg->enable);
 }
 
+static unsigned long ccu_gate_recalc_rate(struct clk_hw *hw,
+                                         unsigned long parent_rate)
+{
+       struct ccu_gate *cg = hw_to_ccu_gate(hw);
+       unsigned long rate = parent_rate;
+
+       if (cg->common.features & CCU_FEATURE_ALL_PREDIV)
+               rate /= cg->common.prediv;
+
+       return rate;
+}
+
+static long ccu_gate_round_rate(struct clk_hw *hw, unsigned long rate,
+                               unsigned long *prate)
+{
+       struct ccu_gate *cg = hw_to_ccu_gate(hw);
+       int div = 1;
+
+       if (cg->common.features & CCU_FEATURE_ALL_PREDIV)
+               div = cg->common.prediv;
+
+       if (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) {
+               unsigned long best_parent = rate;
+
+               if (cg->common.features & CCU_FEATURE_ALL_PREDIV)
+                       best_parent *= div;
+               *prate = clk_hw_round_rate(clk_hw_get_parent(hw), best_parent);
+       }
+
+       return *prate / div;
+}
+
+static int ccu_gate_set_rate(struct clk_hw *hw, unsigned long rate,
+                            unsigned long parent_rate)
+{
+       /*
+        * We must report success but we can do so unconditionally because
+        * clk_factor_round_rate returns values that ensure this call is a
+        * nop.
+        */
+
+       return 0;
+}
+
 const struct clk_ops ccu_gate_ops = {
        .disable        = ccu_gate_disable,
        .enable         = ccu_gate_enable,
        .is_enabled     = ccu_gate_is_enabled,
+       .round_rate     = ccu_gate_round_rate,
+       .set_rate       = ccu_gate_set_rate,
+       .recalc_rate    = ccu_gate_recalc_rate,
 };
index 8724c01171b1758f00d1151a55e86ffea593c344..671141359895290a9dc6d6ea20efa9e8347eb421 100644 (file)
@@ -137,6 +137,8 @@ static int ccu_mult_set_rate(struct clk_hw *hw, unsigned long rate,
 
        spin_unlock_irqrestore(cm->common.lock, flags);
 
+       ccu_helper_wait_for_lock(&cm->common, cm->lock);
+
        return 0;
 }
 
index 524acddfcb2eaf480b992b4f9761ad9b46fb8d70..f9c37b987d72b560d096faf7b24356863fd17cbc 100644 (file)
@@ -33,6 +33,7 @@ struct ccu_mult_internal {
 
 struct ccu_mult {
        u32                     enable;
+       u32                     lock;
 
        struct ccu_frac_internal        frac;
        struct ccu_mult_internal        mult;
@@ -45,6 +46,7 @@ struct ccu_mult {
                                   _flags)                              \
        struct ccu_mult _struct = {                                     \
                .enable = _gate,                                        \
+               .lock   = _lock,                                        \
                .mult   = _SUNXI_CCU_MULT(_mshift, _mwidth),            \
                .common = {                                             \
                        .reg            = _reg,                         \
index b9e9b8a9d1b458cb44376ef40f55fbb2e0ab334e..2485bda87a9a99851f2113fd4867406374bcdf6c 100644 (file)
@@ -102,9 +102,9 @@ static long ccu_nk_round_rate(struct clk_hw *hw, unsigned long rate,
        if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV)
                rate *= nk->fixed_post_div;
 
-       _nk.min_n = nk->n.min;
+       _nk.min_n = nk->n.min ?: 1;
        _nk.max_n = nk->n.max ?: 1 << nk->n.width;
-       _nk.min_k = nk->k.min;
+       _nk.min_k = nk->k.min ?: 1;
        _nk.max_k = nk->k.max ?: 1 << nk->k.width;
 
        ccu_nk_find_best(*parent_rate, rate, &_nk);
@@ -127,9 +127,9 @@ static int ccu_nk_set_rate(struct clk_hw *hw, unsigned long rate,
        if (nk->common.features & CCU_FEATURE_FIXED_POSTDIV)
                rate = rate * nk->fixed_post_div;
 
-       _nk.min_n = nk->n.min;
+       _nk.min_n = nk->n.min ?: 1;
        _nk.max_n = nk->n.max ?: 1 << nk->n.width;
-       _nk.min_k = nk->k.min;
+       _nk.min_k = nk->k.min ?: 1;
        _nk.max_k = nk->k.max ?: 1 << nk->k.width;
 
        ccu_nk_find_best(parent_rate, rate, &_nk);
index 71f81e95a061e9cebfae12a6ccefc023538e3265..cba84afe1cf1d4a1a60294f118a91561168355f2 100644 (file)
@@ -109,9 +109,9 @@ static unsigned long ccu_nkm_round_rate(struct ccu_mux_internal *mux,
        struct ccu_nkm *nkm = data;
        struct _ccu_nkm _nkm;
 
-       _nkm.min_n = nkm->n.min;
+       _nkm.min_n = nkm->n.min ?: 1;
        _nkm.max_n = nkm->n.max ?: 1 << nkm->n.width;
-       _nkm.min_k = nkm->k.min;
+       _nkm.min_k = nkm->k.min ?: 1;
        _nkm.max_k = nkm->k.max ?: 1 << nkm->k.width;
        _nkm.min_m = 1;
        _nkm.max_m = nkm->m.max ?: 1 << nkm->m.width;
@@ -138,9 +138,9 @@ static int ccu_nkm_set_rate(struct clk_hw *hw, unsigned long rate,
        unsigned long flags;
        u32 reg;
 
-       _nkm.min_n = nkm->n.min;
+       _nkm.min_n = nkm->n.min ?: 1;
        _nkm.max_n = nkm->n.max ?: 1 << nkm->n.width;
-       _nkm.min_k = nkm->k.min;
+       _nkm.min_k = nkm->k.min ?: 1;
        _nkm.max_k = nkm->k.max ?: 1 << nkm->k.width;
        _nkm.min_m = 1;
        _nkm.max_m = nkm->m.max ?: 1 << nkm->m.width;
index 488055ed944f2b9dff8ca1baa5059ea22879328b..e58c95787f94c7c6cb7c1ca96330d4680940bc74 100644 (file)
@@ -116,9 +116,9 @@ static long ccu_nkmp_round_rate(struct clk_hw *hw, unsigned long rate,
        struct ccu_nkmp *nkmp = hw_to_ccu_nkmp(hw);
        struct _ccu_nkmp _nkmp;
 
-       _nkmp.min_n = nkmp->n.min;
+       _nkmp.min_n = nkmp->n.min ?: 1;
        _nkmp.max_n = nkmp->n.max ?: 1 << nkmp->n.width;
-       _nkmp.min_k = nkmp->k.min;
+       _nkmp.min_k = nkmp->k.min ?: 1;
        _nkmp.max_k = nkmp->k.max ?: 1 << nkmp->k.width;
        _nkmp.min_m = 1;
        _nkmp.max_m = nkmp->m.max ?: 1 << nkmp->m.width;
@@ -138,9 +138,9 @@ static int ccu_nkmp_set_rate(struct clk_hw *hw, unsigned long rate,
        unsigned long flags;
        u32 reg;
 
-       _nkmp.min_n = 1;
+       _nkmp.min_n = nkmp->n.min ?: 1;
        _nkmp.max_n = nkmp->n.max ?: 1 << nkmp->n.width;
-       _nkmp.min_k = 1;
+       _nkmp.min_k = nkmp->k.min ?: 1;
        _nkmp.max_k = nkmp->k.max ?: 1 << nkmp->k.width;
        _nkmp.min_m = 1;
        _nkmp.max_m = nkmp->m.max ?: 1 << nkmp->m.width;
index af71b1909cd9f6f3816ce19dc81464425c37ff17..5e5e90a4a50c8bd80a9ca0ea1fc91ccee9a3428e 100644 (file)
@@ -99,7 +99,7 @@ static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate,
        struct ccu_nm *nm = hw_to_ccu_nm(hw);
        struct _ccu_nm _nm;
 
-       _nm.min_n = nm->n.min;
+       _nm.min_n = nm->n.min ?: 1;
        _nm.max_n = nm->n.max ?: 1 << nm->n.width;
        _nm.min_m = 1;
        _nm.max_m = nm->m.max ?: 1 << nm->m.width;
@@ -122,7 +122,7 @@ static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate,
        else
                ccu_frac_helper_disable(&nm->common, &nm->frac);
 
-       _nm.min_n = 1;
+       _nm.min_n = nm->n.min ?: 1;
        _nm.max_n = nm->n.max ?: 1 << nm->n.width;
        _nm.min_m = 1;
        _nm.max_m = nm->m.max ?: 1 << nm->m.width;
index 5738635c52741c555e68f3feaba1ed28a5c3cdcf..689f344377a7aad3604be95f457b27a7585547bb 100644 (file)
@@ -307,6 +307,23 @@ enum clk_id {
        tegra_clk_xusb_ssp_src,
        tegra_clk_sclk_mux,
        tegra_clk_sor_safe,
+       tegra_clk_cec,
+       tegra_clk_ispa,
+       tegra_clk_dmic1,
+       tegra_clk_dmic2,
+       tegra_clk_dmic3,
+       tegra_clk_dmic1_sync_clk,
+       tegra_clk_dmic2_sync_clk,
+       tegra_clk_dmic3_sync_clk,
+       tegra_clk_dmic1_sync_clk_mux,
+       tegra_clk_dmic2_sync_clk_mux,
+       tegra_clk_dmic3_sync_clk_mux,
+       tegra_clk_iqc1,
+       tegra_clk_iqc2,
+       tegra_clk_pll_a_out_adsp,
+       tegra_clk_pll_a_out0_out_adsp,
+       tegra_clk_adsp,
+       tegra_clk_adsp_neon,
        tegra_clk_max,
 };
 
index 88127828befea3456132dfbaa4389064a458cdb6..303ef32ee3f1304040042dcda96bd43e06008afc 100644 (file)
@@ -159,6 +159,9 @@ struct clk *tegra_clk_register_periph_gate(const char *name,
        gate->enable_refcnt = enable_refcnt;
        gate->regs = pregs;
 
+       if (read_enb(gate) & periph_clk_to_bit(gate))
+               enable_refcnt[clk_num]++;
+
        /* Data in .init is copied by clk_register(), so stack variable OK */
        gate->hw.init = &init;
 
index a17ca6d7f649bf931d5a81b203a6e8e874b8818a..cf80831de79d63260eb94b1208b76c216c5a20b8 100644 (file)
@@ -138,7 +138,7 @@ static const struct clk_ops tegra_clk_periph_no_gate_ops = {
 };
 
 static struct clk *_tegra_clk_register_periph(const char *name,
-                       const char **parent_names, int num_parents,
+                       const char * const *parent_names, int num_parents,
                        struct tegra_clk_periph *periph,
                        void __iomem *clk_base, u32 offset,
                        unsigned long flags)
@@ -186,7 +186,7 @@ static struct clk *_tegra_clk_register_periph(const char *name,
 }
 
 struct clk *tegra_clk_register_periph(const char *name,
-               const char **parent_names, int num_parents,
+               const char * const *parent_names, int num_parents,
                struct tegra_clk_periph *periph, void __iomem *clk_base,
                u32 offset, unsigned long flags)
 {
@@ -195,7 +195,7 @@ struct clk *tegra_clk_register_periph(const char *name,
 }
 
 struct clk *tegra_clk_register_periph_nodiv(const char *name,
-               const char **parent_names, int num_parents,
+               const char * const *parent_names, int num_parents,
                struct tegra_clk_periph *periph, void __iomem *clk_base,
                u32 offset)
 {
index b3855360d6bc0d64121abc127f50e58411b67db7..159a854779e6def3c4a0a61e20607cce79f10f04 100644 (file)
@@ -2517,152 +2517,6 @@ static int clk_plle_tegra210_is_enabled(struct clk_hw *hw)
        return val & PLLE_BASE_ENABLE ? 1 : 0;
 }
 
-static int clk_pllu_tegra210_enable(struct clk_hw *hw)
-{
-       struct tegra_clk_pll *pll = to_clk_pll(hw);
-       struct clk_hw *pll_ref = clk_hw_get_parent(hw);
-       struct clk_hw *osc = clk_hw_get_parent(pll_ref);
-       const struct utmi_clk_param *params = NULL;
-       unsigned long flags = 0, input_rate;
-       unsigned int i;
-       int ret = 0;
-       u32 value;
-
-       if (!osc) {
-               pr_err("%s: failed to get OSC clock\n", __func__);
-               return -EINVAL;
-       }
-
-       input_rate = clk_hw_get_rate(osc);
-
-       if (pll->lock)
-               spin_lock_irqsave(pll->lock, flags);
-
-       _clk_pll_enable(hw);
-
-       ret = clk_pll_wait_for_lock(pll);
-       if (ret < 0)
-               goto out;
-
-       for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) {
-               if (input_rate == utmi_parameters[i].osc_frequency) {
-                       params = &utmi_parameters[i];
-                       break;
-               }
-       }
-
-       if (!params) {
-               pr_err("%s: unexpected input rate %lu Hz\n", __func__,
-                      input_rate);
-               ret = -EINVAL;
-               goto out;
-       }
-
-       value = pll_readl_base(pll);
-       value &= ~PLLU_BASE_OVERRIDE;
-       pll_writel_base(value, pll);
-
-       /* Put PLLU under HW control */
-       value = readl_relaxed(pll->clk_base + PLLU_HW_PWRDN_CFG0);
-       value |= PLLU_HW_PWRDN_CFG0_IDDQ_PD_INCLUDE |
-                PLLU_HW_PWRDN_CFG0_USE_SWITCH_DETECT |
-                PLLU_HW_PWRDN_CFG0_USE_LOCKDET;
-       value &= ~(PLLU_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL |
-                  PLLU_HW_PWRDN_CFG0_CLK_SWITCH_SWCTL);
-       writel_relaxed(value, pll->clk_base + PLLU_HW_PWRDN_CFG0);
-
-       value = readl_relaxed(pll->clk_base + XUSB_PLL_CFG0);
-       value &= ~XUSB_PLL_CFG0_PLLU_LOCK_DLY;
-       writel_relaxed(value, pll->clk_base + XUSB_PLL_CFG0);
-
-       udelay(1);
-
-       value = readl_relaxed(pll->clk_base + PLLU_HW_PWRDN_CFG0);
-       value |= PLLU_HW_PWRDN_CFG0_SEQ_ENABLE;
-       writel_relaxed(value, pll->clk_base + PLLU_HW_PWRDN_CFG0);
-
-       udelay(1);
-
-       /* Disable PLLU clock branch to UTMIPLL since it uses OSC */
-       value = pll_readl_base(pll);
-       value &= ~PLLU_BASE_CLKENABLE_USB;
-       pll_writel_base(value, pll);
-
-       value = readl_relaxed(pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
-       if (value & UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE) {
-               pr_debug("UTMIPLL already enabled\n");
-               goto out;
-       }
-
-       value &= ~UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE;
-       writel_relaxed(value, pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
-
-       /* Program UTMIP PLL stable and active counts */
-       value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG2);
-       value &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0);
-       value |= UTMIP_PLL_CFG2_STABLE_COUNT(params->stable_count);
-       value &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0);
-       value |= UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(params->active_delay_count);
-       value |= UTMIP_PLL_CFG2_PHY_XTAL_CLOCKEN;
-       writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG2);
-
-       /* Program UTMIP PLL delay and oscillator frequency counts */
-       value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG1);
-       value &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0);
-       value |= UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(params->enable_delay_count);
-       value &= ~UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(~0);
-       value |= UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(params->xtal_freq_count);
-       writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG1);
-
-       /* Remove power downs from UTMIP PLL control bits */
-       value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG1);
-       value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
-       value |= UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP;
-       writel(value, pll->clk_base + UTMIP_PLL_CFG1);
-
-       udelay(1);
-
-       /* Enable samplers for SNPS, XUSB_HOST, XUSB_DEV */
-       value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG2);
-       value |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERUP;
-       value |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERUP;
-       value |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERUP;
-       value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN;
-       value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN;
-       value &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERDOWN;
-       writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG2);
-
-       /* Setup HW control of UTMIPLL */
-       value = readl_relaxed(pll->clk_base + UTMIP_PLL_CFG1);
-       value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP;
-       value &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
-       writel_relaxed(value, pll->clk_base + UTMIP_PLL_CFG1);
-
-       value = readl_relaxed(pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
-       value |= UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET;
-       value &= ~UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL;
-       writel_relaxed(value, pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
-
-       udelay(1);
-
-       value = readl_relaxed(pll->clk_base + XUSB_PLL_CFG0);
-       value &= ~XUSB_PLL_CFG0_UTMIPLL_LOCK_DLY;
-       writel_relaxed(value, pll->clk_base + XUSB_PLL_CFG0);
-
-       udelay(1);
-
-       /* Enable HW control of UTMIPLL */
-       value = readl_relaxed(pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
-       value |= UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE;
-       writel_relaxed(value, pll->clk_base + UTMIPLL_HW_PWRDN_CFG0);
-
-out:
-       if (pll->lock)
-               spin_unlock_irqrestore(pll->lock, flags);
-
-       return ret;
-}
-
 static const struct clk_ops tegra_clk_plle_tegra210_ops = {
        .is_enabled =  clk_plle_tegra210_is_enabled,
        .enable = clk_plle_tegra210_enable,
@@ -2670,13 +2524,6 @@ static const struct clk_ops tegra_clk_plle_tegra210_ops = {
        .recalc_rate = clk_pll_recalc_rate,
 };
 
-static const struct clk_ops tegra_clk_pllu_tegra210_ops = {
-       .is_enabled =  clk_pll_is_enabled,
-       .enable = clk_pllu_tegra210_enable,
-       .disable = clk_pll_disable,
-       .recalc_rate = clk_pllre_recalc_rate,
-};
-
 struct clk *tegra_clk_register_plle_tegra210(const char *name,
                                const char *parent_name,
                                void __iomem *clk_base, unsigned long flags,
@@ -2918,25 +2765,4 @@ struct clk *tegra_clk_register_pllmb(const char *name, const char *parent_name,
        return clk;
 }
 
-struct clk *tegra_clk_register_pllu_tegra210(const char *name,
-               const char *parent_name, void __iomem *clk_base,
-               unsigned long flags, struct tegra_clk_pll_params *pll_params,
-               spinlock_t *lock)
-{
-       struct tegra_clk_pll *pll;
-       struct clk *clk;
-
-       pll_params->flags |= TEGRA_PLLU;
-
-       pll = _tegra_init_pll(clk_base, NULL, pll_params, lock);
-       if (IS_ERR(pll))
-               return ERR_CAST(pll);
-
-       clk = _tegra_clk_register_pll(pll, name, parent_name, flags,
-                                     &tegra_clk_pllu_tegra210_ops);
-       if (IS_ERR(clk))
-               kfree(pll);
-
-       return clk;
-}
 #endif
index 131d1b5085e287a1f3b72d83f79370cd380a7b9e..84267cfc44332e556d79b8dd8d889bd3235fabd6 100644 (file)
@@ -121,9 +121,50 @@ out:
        return err;
 }
 
+const struct clk_ops tegra_clk_super_mux_ops = {
+       .get_parent = clk_super_get_parent,
+       .set_parent = clk_super_set_parent,
+};
+
+static long clk_super_round_rate(struct clk_hw *hw, unsigned long rate,
+                                unsigned long *parent_rate)
+{
+       struct tegra_clk_super_mux *super = to_clk_super_mux(hw);
+       struct clk_hw *div_hw = &super->frac_div.hw;
+
+       __clk_hw_set_clk(div_hw, hw);
+
+       return super->div_ops->round_rate(div_hw, rate, parent_rate);
+}
+
+static unsigned long clk_super_recalc_rate(struct clk_hw *hw,
+                                          unsigned long parent_rate)
+{
+       struct tegra_clk_super_mux *super = to_clk_super_mux(hw);
+       struct clk_hw *div_hw = &super->frac_div.hw;
+
+       __clk_hw_set_clk(div_hw, hw);
+
+       return super->div_ops->recalc_rate(div_hw, parent_rate);
+}
+
+static int clk_super_set_rate(struct clk_hw *hw, unsigned long rate,
+                             unsigned long parent_rate)
+{
+       struct tegra_clk_super_mux *super = to_clk_super_mux(hw);
+       struct clk_hw *div_hw = &super->frac_div.hw;
+
+       __clk_hw_set_clk(div_hw, hw);
+
+       return super->div_ops->set_rate(div_hw, rate, parent_rate);
+}
+
 const struct clk_ops tegra_clk_super_ops = {
        .get_parent = clk_super_get_parent,
        .set_parent = clk_super_set_parent,
+       .set_rate = clk_super_set_rate,
+       .round_rate = clk_super_round_rate,
+       .recalc_rate = clk_super_recalc_rate,
 };
 
 struct clk *tegra_clk_register_super_mux(const char *name,
@@ -136,13 +177,11 @@ struct clk *tegra_clk_register_super_mux(const char *name,
        struct clk_init_data init;
 
        super = kzalloc(sizeof(*super), GFP_KERNEL);
-       if (!super) {
-               pr_err("%s: could not allocate super clk\n", __func__);
+       if (!super)
                return ERR_PTR(-ENOMEM);
-       }
 
        init.name = name;
-       init.ops = &tegra_clk_super_ops;
+       init.ops = &tegra_clk_super_mux_ops;
        init.flags = flags;
        init.parent_names = parent_names;
        init.num_parents = num_parents;
@@ -163,3 +202,43 @@ struct clk *tegra_clk_register_super_mux(const char *name,
 
        return clk;
 }
+
+struct clk *tegra_clk_register_super_clk(const char *name,
+               const char * const *parent_names, u8 num_parents,
+               unsigned long flags, void __iomem *reg, u8 clk_super_flags,
+               spinlock_t *lock)
+{
+       struct tegra_clk_super_mux *super;
+       struct clk *clk;
+       struct clk_init_data init;
+
+       super = kzalloc(sizeof(*super), GFP_KERNEL);
+       if (!super)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = name;
+       init.ops = &tegra_clk_super_ops;
+       init.flags = flags;
+       init.parent_names = parent_names;
+       init.num_parents = num_parents;
+
+       super->reg = reg;
+       super->lock = lock;
+       super->width = 4;
+       super->flags = clk_super_flags;
+       super->frac_div.reg = reg + 4;
+       super->frac_div.shift = 16;
+       super->frac_div.width = 8;
+       super->frac_div.frac_width = 1;
+       super->frac_div.lock = lock;
+       super->div_ops = &tegra_clk_frac_div_ops;
+
+       /* Data in .init is copied by clk_register(), so stack variable OK */
+       super->hw.init = &init;
+
+       clk = clk_register(NULL, &super->hw);
+       if (IS_ERR(clk))
+               kfree(super);
+
+       return clk;
+}
index e2bfa9b368f6b7205f33051e5d05558846991b18..b37cae7af26da031c01a6fb584802bb4640ba099 100644 (file)
@@ -31,6 +31,9 @@
 #define AUDIO_SYNC_CLK_I2S3 0x4ac
 #define AUDIO_SYNC_CLK_I2S4 0x4b0
 #define AUDIO_SYNC_CLK_SPDIF 0x4b4
+#define AUDIO_SYNC_CLK_DMIC1 0x560
+#define AUDIO_SYNC_CLK_DMIC2 0x564
+#define AUDIO_SYNC_CLK_DMIC3 0x6b8
 
 #define AUDIO_SYNC_DOUBLER 0x49c
 
@@ -91,8 +94,14 @@ struct tegra_audio2x_clk_initdata {
 
 static DEFINE_SPINLOCK(clk_doubler_lock);
 
-static const char *mux_audio_sync_clk[] = { "spdif_in_sync", "i2s0_sync",
-       "i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "vimclk_sync",
+static const char * const mux_audio_sync_clk[] = { "spdif_in_sync",
+       "i2s0_sync", "i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync",
+       "pll_a_out0", "vimclk_sync",
+};
+
+static const char * const mux_dmic_sync_clk[] = { "unused", "i2s0_sync",
+       "i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "pll_a_out0",
+       "vimclk_sync",
 };
 
 static struct tegra_sync_source_initdata sync_source_clks[] __initdata = {
@@ -114,6 +123,12 @@ static struct tegra_audio_clk_initdata audio_clks[] = {
        AUDIO(spdif, AUDIO_SYNC_CLK_SPDIF),
 };
 
+static struct tegra_audio_clk_initdata dmic_clks[] = {
+       AUDIO(dmic1_sync_clk, AUDIO_SYNC_CLK_DMIC1),
+       AUDIO(dmic2_sync_clk, AUDIO_SYNC_CLK_DMIC2),
+       AUDIO(dmic3_sync_clk, AUDIO_SYNC_CLK_DMIC3),
+};
+
 static struct tegra_audio2x_clk_initdata audio2x_clks[] = {
        AUDIO2X(audio0, 113, 24),
        AUDIO2X(audio1, 114, 25),
@@ -123,6 +138,41 @@ static struct tegra_audio2x_clk_initdata audio2x_clks[] = {
        AUDIO2X(spdif, 118, 29),
 };
 
+static void __init tegra_audio_sync_clk_init(void __iomem *clk_base,
+                                     struct tegra_clk *tegra_clks,
+                                     struct tegra_audio_clk_initdata *sync,
+                                     int num_sync_clks,
+                                     const char * const *mux_names,
+                                     int num_mux_inputs)
+{
+       struct clk *clk;
+       struct clk **dt_clk;
+       struct tegra_audio_clk_initdata *data;
+       int i;
+
+       for (i = 0, data = sync; i < num_sync_clks; i++, data++) {
+               dt_clk = tegra_lookup_dt_id(data->mux_clk_id, tegra_clks);
+               if (!dt_clk)
+                       continue;
+
+               clk = clk_register_mux(NULL, data->mux_name, mux_names,
+                                       num_mux_inputs,
+                                       CLK_SET_RATE_NO_REPARENT,
+                                       clk_base + data->offset, 0, 3, 0,
+                                       NULL);
+               *dt_clk = clk;
+
+               dt_clk = tegra_lookup_dt_id(data->gate_clk_id, tegra_clks);
+               if (!dt_clk)
+                       continue;
+
+               clk = clk_register_gate(NULL, data->gate_name, data->mux_name,
+                                       0, clk_base + data->offset, 4,
+                                       CLK_GATE_SET_TO_DISABLE, NULL);
+               *dt_clk = clk;
+       }
+}
+
 void __init tegra_audio_clk_init(void __iomem *clk_base,
                        void __iomem *pmc_base, struct tegra_clk *tegra_clks,
                        struct tegra_audio_clk_info *audio_info,
@@ -176,30 +226,17 @@ void __init tegra_audio_clk_init(void __iomem *clk_base,
                *dt_clk = clk;
        }
 
-       for (i = 0; i < ARRAY_SIZE(audio_clks); i++) {
-               struct tegra_audio_clk_initdata *data;
+       tegra_audio_sync_clk_init(clk_base, tegra_clks, audio_clks,
+                                 ARRAY_SIZE(audio_clks), mux_audio_sync_clk,
+                                 ARRAY_SIZE(mux_audio_sync_clk));
 
-               data = &audio_clks[i];
-               dt_clk = tegra_lookup_dt_id(data->mux_clk_id, tegra_clks);
+       /* make sure the DMIC sync clocks have a valid parent */
+       for (i = 0; i < ARRAY_SIZE(dmic_clks); i++)
+               writel_relaxed(1, clk_base + dmic_clks[i].offset);
 
-               if (!dt_clk)
-                       continue;
-               clk = clk_register_mux(NULL, data->mux_name, mux_audio_sync_clk,
-                                       ARRAY_SIZE(mux_audio_sync_clk),
-                                       CLK_SET_RATE_NO_REPARENT,
-                                       clk_base + data->offset, 0, 3, 0,
-                                       NULL);
-               *dt_clk = clk;
-
-               dt_clk = tegra_lookup_dt_id(data->gate_clk_id, tegra_clks);
-               if (!dt_clk)
-                       continue;
-
-               clk = clk_register_gate(NULL, data->gate_name, data->mux_name,
-                                       0, clk_base + data->offset, 4,
-                                       CLK_GATE_SET_TO_DISABLE, NULL);
-               *dt_clk = clk;
-       }
+       tegra_audio_sync_clk_init(clk_base, tegra_clks, dmic_clks,
+                                 ARRAY_SIZE(dmic_clks), mux_dmic_sync_clk,
+                                 ARRAY_SIZE(mux_dmic_sync_clk));
 
        for (i = 0; i < ARRAY_SIZE(audio2x_clks); i++) {
                struct tegra_audio2x_clk_initdata *data;
index 4ce4e7fb1124d0aa38323454af5a782edffae42c..294bfe40a4f509dbf56672f9beaeafaf514ace06 100644 (file)
 #define CLK_SOURCE_TSECB 0x6d8
 #define CLK_SOURCE_MAUD 0x6d4
 #define CLK_SOURCE_USB2_HSIC_TRK 0x6cc
+#define CLK_SOURCE_DMIC1 0x64c
+#define CLK_SOURCE_DMIC2 0x650
+#define CLK_SOURCE_DMIC3 0x6bc
 
 #define MASK(x) (BIT(x) - 1)
 
                              0, TEGRA_PERIPH_NO_GATE, _clk_id,\
                              _parents##_idx, 0, _lock)
 
+#define MUX8_NOGATE(_name, _parents, _offset, _clk_id) \
+       TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,     \
+                             29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP,\
+                             0, TEGRA_PERIPH_NO_GATE, _clk_id,\
+                             _parents##_idx, 0, NULL)
+
 #define INT(_name, _parents, _offset,  \
                            _clk_num, _gate_flags, _clk_id)     \
        TEGRA_INIT_DATA_TABLE(_name, NULL, NULL, _parents, _offset,\
@@ -619,6 +628,21 @@ static const char *mux_clkm_plldp_sor0lvds[] = {
 };
 #define mux_clkm_plldp_sor0lvds_idx NULL
 
+static const char * const mux_dmic1[] = {
+       "pll_a_out0", "dmic1_sync_clk", "pll_p", "clk_m"
+};
+#define mux_dmic1_idx NULL
+
+static const char * const mux_dmic2[] = {
+       "pll_a_out0", "dmic2_sync_clk", "pll_p", "clk_m"
+};
+#define mux_dmic2_idx NULL
+
+static const char * const mux_dmic3[] = {
+       "pll_a_out0", "dmic3_sync_clk", "pll_p", "clk_m"
+};
+#define mux_dmic3_idx NULL
+
 static struct tegra_periph_init_data periph_clks[] = {
        AUDIO("d_audio", CLK_SOURCE_D_AUDIO, 106, TEGRA_PERIPH_ON_APB, tegra_clk_d_audio),
        AUDIO("dam0", CLK_SOURCE_DAM0, 108, TEGRA_PERIPH_ON_APB, tegra_clk_dam0),
@@ -739,7 +763,7 @@ static struct tegra_periph_init_data periph_clks[] = {
        MUX8("soc_therm", mux_clkm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, TEGRA_PERIPH_ON_APB, tegra_clk_soc_therm_8),
        MUX8("vi_sensor", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 164, TEGRA_PERIPH_NO_RESET, tegra_clk_vi_sensor_8),
        MUX8("isp", mux_pllm_pllc_pllp_plla_clkm_pllc4, CLK_SOURCE_ISP, 23, TEGRA_PERIPH_ON_APB, tegra_clk_isp_8),
-       MUX8("isp", mux_pllc_pllp_plla1_pllc2_c3_clkm_pllc4, CLK_SOURCE_ISP, 23, TEGRA_PERIPH_ON_APB, tegra_clk_isp_9),
+       MUX8_NOGATE("isp", mux_pllc_pllp_plla1_pllc2_c3_clkm_pllc4, CLK_SOURCE_ISP, tegra_clk_isp_9),
        MUX8("entropy", mux_pllp_clkm1, CLK_SOURCE_ENTROPY, 149,  0, tegra_clk_entropy),
        MUX8("entropy", mux_pllp_clkm_clk32_plle, CLK_SOURCE_ENTROPY, 149,  0, tegra_clk_entropy_8),
        MUX8("hdmi_audio", mux_pllp3_pllc_clkm, CLK_SOURCE_HDMI_AUDIO, 176, TEGRA_PERIPH_NO_RESET, tegra_clk_hdmi_audio),
@@ -788,6 +812,9 @@ static struct tegra_periph_init_data periph_clks[] = {
        MUX("uartape", mux_pllp_pllc_clkm, CLK_SOURCE_UARTAPE, 212, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_uartape),
        MUX8("tsecb", mux_pllp_pllc2_c_c3_clkm, CLK_SOURCE_TSECB, 206, 0, tegra_clk_tsecb),
        MUX8("maud", mux_pllp_pllp_out3_clkm_clk32k_plla, CLK_SOURCE_MAUD, 202, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_maud),
+       MUX8("dmic1", mux_dmic1, CLK_SOURCE_DMIC1, 161, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_dmic1),
+       MUX8("dmic2", mux_dmic2, CLK_SOURCE_DMIC2, 162, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_dmic2),
+       MUX8("dmic3", mux_dmic3, CLK_SOURCE_DMIC3, 197, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_dmic3),
 };
 
 static struct tegra_periph_init_data gate_clks[] = {
@@ -809,7 +836,7 @@ static struct tegra_periph_init_data gate_clks[] = {
        GATE("usb2", "clk_m", 58, 0, tegra_clk_usb2, 0),
        GATE("usb3", "clk_m", 59, 0, tegra_clk_usb3, 0),
        GATE("csi", "pll_p_out3", 52, 0, tegra_clk_csi, 0),
-       GATE("afi", "clk_m", 72, 0, tegra_clk_afi, 0),
+       GATE("afi", "mselect", 72, 0, tegra_clk_afi, 0),
        GATE("csus", "clk_m", 92, TEGRA_PERIPH_NO_RESET, tegra_clk_csus, 0),
        GATE("dds", "clk_m", 150, TEGRA_PERIPH_ON_APB, tegra_clk_dds, 0),
        GATE("dp2", "clk_m", 152, TEGRA_PERIPH_ON_APB, tegra_clk_dp2, 0),
@@ -819,7 +846,8 @@ static struct tegra_periph_init_data gate_clks[] = {
        GATE("xusb_dev", "xusb_dev_src", 95, 0, tegra_clk_xusb_dev, 0),
        GATE("emc", "emc_mux", 57, 0, tegra_clk_emc, CLK_IGNORE_UNUSED),
        GATE("sata_cold", "clk_m", 129, TEGRA_PERIPH_ON_APB, tegra_clk_sata_cold, 0),
-       GATE("ispb", "clk_m", 3, 0, tegra_clk_ispb, 0),
+       GATE("ispa", "isp", 23, 0, tegra_clk_ispa, 0),
+       GATE("ispb", "isp", 3, 0, tegra_clk_ispb, 0),
        GATE("vim2_clk", "clk_m", 11, 0, tegra_clk_vim2_clk, 0),
        GATE("pcie", "clk_m", 70, 0, tegra_clk_pcie, 0),
        GATE("gpu", "pll_ref", 184, 0, tegra_clk_gpu, 0),
@@ -830,6 +858,13 @@ static struct tegra_periph_init_data gate_clks[] = {
        GATE("pll_p_out_cpu", "pll_p", 223, 0, tegra_clk_pll_p_out_cpu, 0),
        GATE("pll_p_out_adsp", "pll_p", 187, 0, tegra_clk_pll_p_out_adsp, 0),
        GATE("apb2ape", "clk_m", 107, 0, tegra_clk_apb2ape, 0),
+       GATE("cec", "pclk", 136, 0, tegra_clk_cec, 0),
+       GATE("iqc1", "clk_m", 221, 0, tegra_clk_iqc1, 0),
+       GATE("iqc2", "clk_m", 220, 0, tegra_clk_iqc1, 0),
+       GATE("pll_a_out_adsp", "pll_a", 188, 0, tegra_clk_pll_a_out_adsp, 0),
+       GATE("pll_a_out0_out_adsp", "pll_a", 188, 0, tegra_clk_pll_a_out0_out_adsp, 0),
+       GATE("adsp", "aclk", 199, 0, tegra_clk_adsp, 0),
+       GATE("adsp_neon", "aclk", 218, 0, tegra_clk_adsp_neon, 0),
 };
 
 static struct tegra_periph_init_data div_clks[] = {
index 91377abfefa19189f82ba32e12a6e0484ed8f9c9..a35579a3f884fbd3fa920e6d30950144c385c3f2 100644 (file)
@@ -95,7 +95,8 @@ void __init tegra_pmc_clk_init(void __iomem *pmc_base,
                        continue;
 
                clk = clk_register_mux(NULL, data->mux_name, data->parents,
-                               data->num_parents, CLK_SET_RATE_NO_REPARENT,
+                               data->num_parents,
+                               CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT,
                                pmc_base + PMC_CLK_OUT_CNTRL, data->mux_shift,
                                3, 0, &clk_out_lock);
                *dt_clk = clk;
@@ -106,7 +107,8 @@ void __init tegra_pmc_clk_init(void __iomem *pmc_base,
                        continue;
 
                clk = clk_register_gate(NULL, data->gate_name, data->mux_name,
-                                       0, pmc_base + PMC_CLK_OUT_CNTRL,
+                                       CLK_SET_RATE_PARENT,
+                                       pmc_base + PMC_CLK_OUT_CNTRL,
                                        data->gate_shift, 0, &clk_out_lock);
                *dt_clk = clk;
                clk_register_clkdev(clk, data->dev_name, data->gate_name);
index 933b5dd698b8cc86ddc924fd65aee483b53a2aec..fd1a99c05c2dc20214d575313fcf2a3964ac945f 100644 (file)
@@ -819,6 +819,7 @@ static struct tegra_clk tegra114_clks[tegra_clk_max] __initdata = {
        [tegra_clk_clk_out_3_mux] = { .dt_id = TEGRA114_CLK_CLK_OUT_3_MUX, .present = true },
        [tegra_clk_dsia_mux] = { .dt_id = TEGRA114_CLK_DSIA_MUX, .present = true },
        [tegra_clk_dsib_mux] = { .dt_id = TEGRA114_CLK_DSIB_MUX, .present = true },
+       [tegra_clk_cec] = { .dt_id = TEGRA114_CLK_CEC, .present = true },
 };
 
 static struct tegra_devclk devclks[] __initdata = {
index a112d3d2bff11ee2bf135e10d78d2584705fb073..e81ea5b11577144da660ed3f0f9dd829d4486f98 100644 (file)
@@ -928,6 +928,7 @@ static struct tegra_clk tegra124_clks[tegra_clk_max] __initdata = {
        [tegra_clk_clk_out_1_mux] = { .dt_id = TEGRA124_CLK_CLK_OUT_1_MUX, .present = true },
        [tegra_clk_clk_out_2_mux] = { .dt_id = TEGRA124_CLK_CLK_OUT_2_MUX, .present = true },
        [tegra_clk_clk_out_3_mux] = { .dt_id = TEGRA124_CLK_CLK_OUT_3_MUX, .present = true },
+       [tegra_clk_cec] = { .dt_id = TEGRA124_CLK_CEC, .present = true },
 };
 
 static struct tegra_devclk devclks[] __initdata = {
index 2896d2e783cecc363ec4966bdd8bb408bc9faee4..1024e853ea65aaae2329c53f0015ecfae9df24e1 100644 (file)
@@ -24,6 +24,8 @@
 #include <linux/export.h>
 #include <linux/clk/tegra.h>
 #include <dt-bindings/clock/tegra210-car.h>
+#include <dt-bindings/reset/tegra210-car.h>
+#include <linux/iopoll.h>
 
 #include "clk.h"
 #include "clk-id.h"
 #define PMC_PLLM_WB0_OVERRIDE 0x1dc
 #define PMC_PLLM_WB0_OVERRIDE_2 0x2b0
 
+#define UTMIP_PLL_CFG2 0x488
+#define UTMIP_PLL_CFG2_STABLE_COUNT(x) (((x) & 0xfff) << 6)
+#define UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(x) (((x) & 0x3f) << 18)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN BIT(0)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERUP BIT(1)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN BIT(2)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERUP BIT(3)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN BIT(4)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERUP BIT(5)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERDOWN BIT(24)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERUP BIT(25)
+
+#define UTMIP_PLL_CFG1 0x484
+#define UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 27)
+#define UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0)
+#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERUP BIT(17)
+#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN BIT(16)
+#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP BIT(15)
+#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN BIT(14)
+#define UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN BIT(12)
+
 #define SATA_PLL_CFG0                          0x490
 #define SATA_PLL_CFG0_PADPLL_RESET_SWCTL       BIT(0)
 #define SATA_PLL_CFG0_PADPLL_USE_LOCKDET       BIT(2)
+#define SATA_PLL_CFG0_SATA_SEQ_IN_SWCTL                BIT(4)
+#define SATA_PLL_CFG0_SATA_SEQ_RESET_INPUT_VALUE       BIT(5)
+#define SATA_PLL_CFG0_SATA_SEQ_LANE_PD_INPUT_VALUE     BIT(6)
+#define SATA_PLL_CFG0_SATA_SEQ_PADPLL_PD_INPUT_VALUE   BIT(7)
+
 #define SATA_PLL_CFG0_PADPLL_SLEEP_IDDQ                BIT(13)
 #define SATA_PLL_CFG0_SEQ_ENABLE               BIT(24)
 
 #define CLK_M_DIVISOR_SHIFT 2
 #define CLK_M_DIVISOR_MASK 0x3
 
+#define RST_DFLL_DVCO 0x2f4
+#define DVFS_DFLL_RESET_SHIFT 0
+
+#define CLK_RST_CONTROLLER_RST_DEV_Y_SET 0x2a8
+#define CLK_RST_CONTROLLER_RST_DEV_Y_CLR 0x2ac
+
 /*
  * SDM fractional divisor is 16-bit 2's complement signed number within
  * (-2^12 ... 2^12-1) range. Represented in PLL data structure as unsigned
@@ -454,6 +488,26 @@ void tegra210_sata_pll_hw_sequence_start(void)
 }
 EXPORT_SYMBOL_GPL(tegra210_sata_pll_hw_sequence_start);
 
+void tegra210_set_sata_pll_seq_sw(bool state)
+{
+       u32 val;
+
+       val = readl_relaxed(clk_base + SATA_PLL_CFG0);
+       if (state) {
+               val |= SATA_PLL_CFG0_SATA_SEQ_IN_SWCTL;
+               val |= SATA_PLL_CFG0_SATA_SEQ_RESET_INPUT_VALUE;
+               val |= SATA_PLL_CFG0_SATA_SEQ_LANE_PD_INPUT_VALUE;
+               val |= SATA_PLL_CFG0_SATA_SEQ_PADPLL_PD_INPUT_VALUE;
+       } else {
+               val &= ~SATA_PLL_CFG0_SATA_SEQ_IN_SWCTL;
+               val &= ~SATA_PLL_CFG0_SATA_SEQ_RESET_INPUT_VALUE;
+               val &= ~SATA_PLL_CFG0_SATA_SEQ_LANE_PD_INPUT_VALUE;
+               val &= ~SATA_PLL_CFG0_SATA_SEQ_PADPLL_PD_INPUT_VALUE;
+       }
+       writel_relaxed(val, clk_base + SATA_PLL_CFG0);
+}
+EXPORT_SYMBOL_GPL(tegra210_set_sata_pll_seq_sw);
+
 static inline void _pll_misc_chk_default(void __iomem *base,
                                        struct tegra_clk_pll_params *params,
                                        u8 misc_num, u32 default_val, u32 mask)
@@ -501,12 +555,12 @@ static void tegra210_pllcx_set_defaults(const char *name,
 {
        pllcx->params->defaults_set = true;
 
-       if (readl_relaxed(clk_base + pllcx->params->base_reg) &
-                       PLL_ENABLE) {
+       if (readl_relaxed(clk_base + pllcx->params->base_reg) & PLL_ENABLE) {
                /* PLL is ON: only check if defaults already set */
                pllcx_check_defaults(pllcx->params);
-               pr_warn("%s already enabled. Postponing set full defaults\n",
-                       name);
+               if (!pllcx->params->defaults_set)
+                       pr_warn("%s already enabled. Postponing set full defaults\n",
+                               name);
                return;
        }
 
@@ -608,7 +662,6 @@ static void tegra210_plld_set_defaults(struct tegra_clk_pll *plld)
 
        if (readl_relaxed(clk_base + plld->params->base_reg) &
                        PLL_ENABLE) {
-               pr_warn("PLL_D already enabled. Postponing set full defaults\n");
 
                /*
                 * PLL is ON: check if defaults already set, then set those
@@ -625,6 +678,9 @@ static void tegra210_plld_set_defaults(struct tegra_clk_pll *plld)
                _pll_misc_chk_default(clk_base, plld->params, 0, val,
                                ~mask & PLLD_MISC0_WRITE_MASK);
 
+               if (!plld->params->defaults_set)
+                       pr_warn("PLL_D already enabled. Postponing set full defaults\n");
+
                /* Enable lock detect */
                mask = PLLD_MISC0_LOCK_ENABLE | PLLD_MISC0_LOCK_OVERRIDE;
                val = readl_relaxed(clk_base + plld->params->ext_misc_reg[0]);
@@ -896,7 +952,6 @@ static void tegra210_pllx_set_defaults(struct tegra_clk_pll *pllx)
        val |= step_b << PLLX_MISC2_DYNRAMP_STEPB_SHIFT;
 
        if (readl_relaxed(clk_base + pllx->params->base_reg) & PLL_ENABLE) {
-               pr_warn("PLL_X already enabled. Postponing set full defaults\n");
 
                /*
                 * PLL is ON: check if defaults already set, then set those
@@ -904,6 +959,8 @@ static void tegra210_pllx_set_defaults(struct tegra_clk_pll *pllx)
                 */
                pllx_check_defaults(pllx);
 
+               if (!pllx->params->defaults_set)
+                       pr_warn("PLL_X already enabled. Postponing set full defaults\n");
                /* Configure dyn ramp, disable lock override */
                writel_relaxed(val, clk_base + pllx->params->ext_misc_reg[2]);
 
@@ -948,7 +1005,6 @@ static void tegra210_pllmb_set_defaults(struct tegra_clk_pll *pllmb)
        pllmb->params->defaults_set = true;
 
        if (val & PLL_ENABLE) {
-               pr_warn("PLL_MB already enabled. Postponing set full defaults\n");
 
                /*
                 * PLL is ON: check if defaults already set, then set those
@@ -959,6 +1015,8 @@ static void tegra210_pllmb_set_defaults(struct tegra_clk_pll *pllmb)
                _pll_misc_chk_default(clk_base, pllmb->params, 0, val,
                                ~mask & PLLMB_MISC1_WRITE_MASK);
 
+               if (!pllmb->params->defaults_set)
+                       pr_warn("PLL_MB already enabled. Postponing set full defaults\n");
                /* Enable lock detect */
                val = readl_relaxed(clk_base + pllmb->params->ext_misc_reg[0]);
                val &= ~mask;
@@ -1008,13 +1066,14 @@ static void tegra210_pllp_set_defaults(struct tegra_clk_pll *pllp)
        pllp->params->defaults_set = true;
 
        if (val & PLL_ENABLE) {
-               pr_warn("PLL_P already enabled. Postponing set full defaults\n");
 
                /*
                 * PLL is ON: check if defaults already set, then set those
                 * that can be updated in flight.
                 */
                pllp_check_defaults(pllp, true);
+               if (!pllp->params->defaults_set)
+                       pr_warn("PLL_P already enabled. Postponing set full defaults\n");
 
                /* Enable lock detect */
                val = readl_relaxed(clk_base + pllp->params->ext_misc_reg[0]);
@@ -1046,47 +1105,49 @@ static void tegra210_pllp_set_defaults(struct tegra_clk_pll *pllp)
  * Both VCO and post-divider output rates are fixed at 480MHz and 240MHz,
  * respectively.
  */
-static void pllu_check_defaults(struct tegra_clk_pll *pll, bool hw_control)
+static void pllu_check_defaults(struct tegra_clk_pll_params *params,
+                               bool hw_control)
 {
        u32 val, mask;
 
        /* Ignore lock enable (will be set) and IDDQ if under h/w control */
        val = PLLU_MISC0_DEFAULT_VALUE & (~PLLU_MISC0_IDDQ);
        mask = PLLU_MISC0_LOCK_ENABLE | (hw_control ? PLLU_MISC0_IDDQ : 0);
-       _pll_misc_chk_default(clk_base, pll->params, 0, val,
+       _pll_misc_chk_default(clk_base, params, 0, val,
                        ~mask & PLLU_MISC0_WRITE_MASK);
 
        val = PLLU_MISC1_DEFAULT_VALUE;
        mask = PLLU_MISC1_LOCK_OVERRIDE;
-       _pll_misc_chk_default(clk_base, pll->params, 1, val,
+       _pll_misc_chk_default(clk_base, params, 1, val,
                        ~mask & PLLU_MISC1_WRITE_MASK);
 }
 
-static void tegra210_pllu_set_defaults(struct tegra_clk_pll *pllu)
+static void tegra210_pllu_set_defaults(struct tegra_clk_pll_params *pllu)
 {
-       u32 val = readl_relaxed(clk_base + pllu->params->base_reg);
+       u32 val = readl_relaxed(clk_base + pllu->base_reg);
 
-       pllu->params->defaults_set = true;
+       pllu->defaults_set = true;
 
        if (val & PLL_ENABLE) {
-               pr_warn("PLL_U already enabled. Postponing set full defaults\n");
 
                /*
                 * PLL is ON: check if defaults already set, then set those
                 * that can be updated in flight.
                 */
                pllu_check_defaults(pllu, false);
+               if (!pllu->defaults_set)
+                       pr_warn("PLL_U already enabled. Postponing set full defaults\n");
 
                /* Enable lock detect */
-               val = readl_relaxed(clk_base + pllu->params->ext_misc_reg[0]);
+               val = readl_relaxed(clk_base + pllu->ext_misc_reg[0]);
                val &= ~PLLU_MISC0_LOCK_ENABLE;
                val |= PLLU_MISC0_DEFAULT_VALUE & PLLU_MISC0_LOCK_ENABLE;
-               writel_relaxed(val, clk_base + pllu->params->ext_misc_reg[0]);
+               writel_relaxed(val, clk_base + pllu->ext_misc_reg[0]);
 
-               val = readl_relaxed(clk_base + pllu->params->ext_misc_reg[1]);
+               val = readl_relaxed(clk_base + pllu->ext_misc_reg[1]);
                val &= ~PLLU_MISC1_LOCK_OVERRIDE;
                val |= PLLU_MISC1_DEFAULT_VALUE & PLLU_MISC1_LOCK_OVERRIDE;
-               writel_relaxed(val, clk_base + pllu->params->ext_misc_reg[1]);
+               writel_relaxed(val, clk_base + pllu->ext_misc_reg[1]);
                udelay(1);
 
                return;
@@ -1094,9 +1155,9 @@ static void tegra210_pllu_set_defaults(struct tegra_clk_pll *pllu)
 
        /* set IDDQ, enable lock detect */
        writel_relaxed(PLLU_MISC0_DEFAULT_VALUE,
-                       clk_base + pllu->params->ext_misc_reg[0]);
+                       clk_base + pllu->ext_misc_reg[0]);
        writel_relaxed(PLLU_MISC1_DEFAULT_VALUE,
-                       clk_base + pllu->params->ext_misc_reg[1]);
+                       clk_base + pllu->ext_misc_reg[1]);
        udelay(1);
 }
 
@@ -1216,6 +1277,7 @@ static int tegra210_pll_fixed_mdiv_cfg(struct clk_hw *hw,
        cfg->n = p_rate / cf;
 
        cfg->sdm_data = 0;
+       cfg->output_rate = input_rate;
        if (params->sdm_ctrl_reg) {
                unsigned long rem = p_rate - cf * cfg->n;
                /* If ssc is enabled SDM enabled as well, even for integer n */
@@ -1226,10 +1288,15 @@ static int tegra210_pll_fixed_mdiv_cfg(struct clk_hw *hw,
                        s -= PLL_SDM_COEFF / 2;
                        cfg->sdm_data = sdin_din_to_data(s);
                }
+               cfg->output_rate *= cfg->n * PLL_SDM_COEFF + PLL_SDM_COEFF/2 +
+                                       sdin_data_to_din(cfg->sdm_data);
+               cfg->output_rate /= p * cfg->m * PLL_SDM_COEFF;
+       } else {
+               cfg->output_rate *= cfg->n;
+               cfg->output_rate /= p * cfg->m;
        }
 
        cfg->input_rate = input_rate;
-       cfg->output_rate = rate;
 
        return 0;
 }
@@ -1772,7 +1839,7 @@ static struct tegra_clk_pll_params pll_a1_params = {
        .misc_reg = PLLA1_MISC0,
        .lock_mask = PLLCX_BASE_LOCK,
        .lock_delay = 300,
-       .iddq_reg = PLLA1_MISC0,
+       .iddq_reg = PLLA1_MISC1,
        .iddq_bit_idx = PLLCX_IDDQ_BIT,
        .reset_reg = PLLA1_MISC0,
        .reset_bit_idx = PLLCX_RESET_BIT,
@@ -1987,9 +2054,9 @@ static struct div_nmp pllu_nmp = {
 };
 
 static struct tegra_clk_pll_freq_table pll_u_freq_table[] = {
-       { 12000000, 480000000, 40, 1, 1, 0 },
-       { 13000000, 480000000, 36, 1, 1, 0 }, /* actual: 468.0 MHz */
-       { 38400000, 480000000, 25, 2, 1, 0 },
+       { 12000000, 480000000, 40, 1, 0, 0 },
+       { 13000000, 480000000, 36, 1, 0, 0 }, /* actual: 468.0 MHz */
+       { 38400000, 480000000, 25, 2, 0, 0 },
        {        0,         0,  0, 0, 0, 0 },
 };
 
@@ -2013,8 +2080,47 @@ static struct tegra_clk_pll_params pll_u_vco_params = {
        .div_nmp = &pllu_nmp,
        .freq_table = pll_u_freq_table,
        .flags = TEGRA_PLLU | TEGRA_PLL_USE_LOCK | TEGRA_PLL_VCO_OUT,
-       .set_defaults = tegra210_pllu_set_defaults,
-       .calc_rate = tegra210_pll_fixed_mdiv_cfg,
+};
+
+struct utmi_clk_param {
+       /* Oscillator Frequency in KHz */
+       u32 osc_frequency;
+       /* UTMIP PLL Enable Delay Count  */
+       u8 enable_delay_count;
+       /* UTMIP PLL Stable count */
+       u16 stable_count;
+       /*  UTMIP PLL Active delay count */
+       u8 active_delay_count;
+       /* UTMIP PLL Xtal frequency count */
+       u16 xtal_freq_count;
+};
+
+static const struct utmi_clk_param utmi_parameters[] = {
+       {
+               .osc_frequency = 38400000, .enable_delay_count = 0x0,
+               .stable_count = 0x0, .active_delay_count = 0x6,
+               .xtal_freq_count = 0x80
+       }, {
+               .osc_frequency = 13000000, .enable_delay_count = 0x02,
+               .stable_count = 0x33, .active_delay_count = 0x05,
+               .xtal_freq_count = 0x7f
+       }, {
+               .osc_frequency = 19200000, .enable_delay_count = 0x03,
+               .stable_count = 0x4b, .active_delay_count = 0x06,
+               .xtal_freq_count = 0xbb
+       }, {
+               .osc_frequency = 12000000, .enable_delay_count = 0x02,
+               .stable_count = 0x2f, .active_delay_count = 0x08,
+               .xtal_freq_count = 0x76
+       }, {
+               .osc_frequency = 26000000, .enable_delay_count = 0x04,
+               .stable_count = 0x66, .active_delay_count = 0x09,
+               .xtal_freq_count = 0xfe
+       }, {
+               .osc_frequency = 16800000, .enable_delay_count = 0x03,
+               .stable_count = 0x41, .active_delay_count = 0x0a,
+               .xtal_freq_count = 0xa4
+       },
 };
 
 static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = {
@@ -2115,7 +2221,6 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = {
        [tegra_clk_pll_c2] = { .dt_id = TEGRA210_CLK_PLL_C2, .present = true },
        [tegra_clk_pll_c3] = { .dt_id = TEGRA210_CLK_PLL_C3, .present = true },
        [tegra_clk_pll_m] = { .dt_id = TEGRA210_CLK_PLL_M, .present = true },
-       [tegra_clk_pll_m_out1] = { .dt_id = TEGRA210_CLK_PLL_M_OUT1, .present = true },
        [tegra_clk_pll_p] = { .dt_id = TEGRA210_CLK_PLL_P, .present = true },
        [tegra_clk_pll_p_out1] = { .dt_id = TEGRA210_CLK_PLL_P_OUT1, .present = true },
        [tegra_clk_pll_p_out3] = { .dt_id = TEGRA210_CLK_PLL_P_OUT3, .present = true },
@@ -2209,6 +2314,25 @@ static struct tegra_clk tegra210_clks[tegra_clk_max] __initdata = {
        [tegra_clk_pll_c4_out2] = { .dt_id = TEGRA210_CLK_PLL_C4_OUT2, .present = true },
        [tegra_clk_pll_c4_out3] = { .dt_id = TEGRA210_CLK_PLL_C4_OUT3, .present = true },
        [tegra_clk_apb2ape] = { .dt_id = TEGRA210_CLK_APB2APE, .present = true },
+       [tegra_clk_pll_a1] = { .dt_id = TEGRA210_CLK_PLL_A1, .present = true },
+       [tegra_clk_ispa] = { .dt_id = TEGRA210_CLK_ISPA, .present = true },
+       [tegra_clk_cec] = { .dt_id = TEGRA210_CLK_CEC, .present = true },
+       [tegra_clk_dmic1] = { .dt_id = TEGRA210_CLK_DMIC1, .present = true },
+       [tegra_clk_dmic2] = { .dt_id = TEGRA210_CLK_DMIC2, .present = true },
+       [tegra_clk_dmic3] = { .dt_id = TEGRA210_CLK_DMIC3, .present = true },
+       [tegra_clk_dmic1_sync_clk] = { .dt_id = TEGRA210_CLK_DMIC1_SYNC_CLK, .present = true },
+       [tegra_clk_dmic2_sync_clk] = { .dt_id = TEGRA210_CLK_DMIC2_SYNC_CLK, .present = true },
+       [tegra_clk_dmic3_sync_clk] = { .dt_id = TEGRA210_CLK_DMIC3_SYNC_CLK, .present = true },
+       [tegra_clk_dmic1_sync_clk_mux] = { .dt_id = TEGRA210_CLK_DMIC1_SYNC_CLK_MUX, .present = true },
+       [tegra_clk_dmic2_sync_clk_mux] = { .dt_id = TEGRA210_CLK_DMIC2_SYNC_CLK_MUX, .present = true },
+       [tegra_clk_dmic3_sync_clk_mux] = { .dt_id = TEGRA210_CLK_DMIC3_SYNC_CLK_MUX, .present = true },
+       [tegra_clk_dp2] = { .dt_id = TEGRA210_CLK_DP2, .present = true },
+       [tegra_clk_iqc1] = { .dt_id = TEGRA210_CLK_IQC1, .present = true },
+       [tegra_clk_iqc2] = { .dt_id = TEGRA210_CLK_IQC2, .present = true },
+       [tegra_clk_pll_a_out_adsp] = { .dt_id = TEGRA210_CLK_PLL_A_OUT_ADSP, .present = true },
+       [tegra_clk_pll_a_out0_out_adsp] = { .dt_id = TEGRA210_CLK_PLL_A_OUT0_OUT_ADSP, .present = true },
+       [tegra_clk_adsp] = { .dt_id = TEGRA210_CLK_ADSP, .present = true },
+       [tegra_clk_adsp_neon] = { .dt_id = TEGRA210_CLK_ADSP_NEON, .present = true },
 };
 
 static struct tegra_devclk devclks[] __initdata = {
@@ -2227,7 +2351,6 @@ static struct tegra_devclk devclks[] __initdata = {
        { .con_id = "pll_p_out3", .dt_id = TEGRA210_CLK_PLL_P_OUT3 },
        { .con_id = "pll_p_out4", .dt_id = TEGRA210_CLK_PLL_P_OUT4 },
        { .con_id = "pll_m", .dt_id = TEGRA210_CLK_PLL_M },
-       { .con_id = "pll_m_out1", .dt_id = TEGRA210_CLK_PLL_M_OUT1 },
        { .con_id = "pll_x", .dt_id = TEGRA210_CLK_PLL_X },
        { .con_id = "pll_x_out0", .dt_id = TEGRA210_CLK_PLL_X_OUT0 },
        { .con_id = "pll_u", .dt_id = TEGRA210_CLK_PLL_U },
@@ -2286,6 +2409,221 @@ static struct tegra_audio_clk_info tegra210_audio_plls[] = {
 
 static struct clk **clks;
 
+static const char * const aclk_parents[] = {
+       "pll_a1", "pll_c", "pll_p", "pll_a_out0", "pll_c2", "pll_c3",
+       "clk_m"
+};
+
+void tegra210_put_utmipll_in_iddq(void)
+{
+       u32 reg;
+
+       reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0);
+
+       if (reg & UTMIPLL_HW_PWRDN_CFG0_UTMIPLL_LOCK) {
+               pr_err("trying to assert IDDQ while UTMIPLL is locked\n");
+               return;
+       }
+
+       reg |= UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE;
+       writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0);
+}
+EXPORT_SYMBOL_GPL(tegra210_put_utmipll_in_iddq);
+
+void tegra210_put_utmipll_out_iddq(void)
+{
+       u32 reg;
+
+       reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0);
+       reg &= ~UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE;
+       writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0);
+}
+EXPORT_SYMBOL_GPL(tegra210_put_utmipll_out_iddq);
+
+static void tegra210_utmi_param_configure(void)
+{
+       u32 reg;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) {
+               if (osc_freq == utmi_parameters[i].osc_frequency)
+                       break;
+       }
+
+       if (i >= ARRAY_SIZE(utmi_parameters)) {
+               pr_err("%s: Unexpected oscillator freq %lu\n", __func__,
+                       osc_freq);
+               return;
+       }
+
+       reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0);
+       reg &= ~UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE;
+       writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0);
+
+       udelay(10);
+
+       reg = readl_relaxed(clk_base + UTMIP_PLL_CFG2);
+
+       /* Program UTMIP PLL stable and active counts */
+       /* [FIXME] arclk_rst.h says WRONG! This should be 1ms -> 0x50 Check! */
+       reg &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0);
+       reg |= UTMIP_PLL_CFG2_STABLE_COUNT(utmi_parameters[i].stable_count);
+
+       reg &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0);
+
+       reg |=
+       UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(utmi_parameters[i].active_delay_count);
+       writel_relaxed(reg, clk_base + UTMIP_PLL_CFG2);
+
+       /* Program UTMIP PLL delay and oscillator frequency counts */
+       reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1);
+       reg &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0);
+
+       reg |=
+       UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(utmi_parameters[i].enable_delay_count);
+
+       reg &= ~UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(~0);
+       reg |=
+       UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(utmi_parameters[i].xtal_freq_count);
+
+       reg |= UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN;
+       writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1);
+
+       /* Remove power downs from UTMIP PLL control bits */
+       reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1);
+       reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
+       reg |= UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP;
+       writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1);
+       udelay(1);
+
+       /* Enable samplers for SNPS, XUSB_HOST, XUSB_DEV */
+       reg = readl_relaxed(clk_base + UTMIP_PLL_CFG2);
+       reg |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERUP;
+       reg |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERUP;
+       reg |= UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERUP;
+       reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN;
+       reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN;
+       reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_D_POWERDOWN;
+       writel_relaxed(reg, clk_base + UTMIP_PLL_CFG2);
+
+       /* Setup HW control of UTMIPLL */
+       reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1);
+       reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
+       reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP;
+       writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1);
+
+       reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0);
+       reg |= UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET;
+       reg &= ~UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL;
+       writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0);
+
+       udelay(1);
+
+       reg = readl_relaxed(clk_base + XUSB_PLL_CFG0);
+       reg &= ~XUSB_PLL_CFG0_UTMIPLL_LOCK_DLY;
+       writel_relaxed(reg, clk_base + XUSB_PLL_CFG0);
+
+       udelay(1);
+
+       /* Enable HW control UTMIPLL */
+       reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0);
+       reg |= UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE;
+       writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0);
+}
+
+static int tegra210_enable_pllu(void)
+{
+       struct tegra_clk_pll_freq_table *fentry;
+       struct tegra_clk_pll pllu;
+       u32 reg;
+
+       for (fentry = pll_u_freq_table; fentry->input_rate; fentry++) {
+               if (fentry->input_rate == pll_ref_freq)
+                       break;
+       }
+
+       if (!fentry->input_rate) {
+               pr_err("Unknown PLL_U reference frequency %lu\n", pll_ref_freq);
+               return -EINVAL;
+       }
+
+       /* clear IDDQ bit */
+       pllu.params = &pll_u_vco_params;
+       reg = readl_relaxed(clk_base + pllu.params->ext_misc_reg[0]);
+       reg &= ~BIT(pllu.params->iddq_bit_idx);
+       writel_relaxed(reg, clk_base + pllu.params->ext_misc_reg[0]);
+
+       reg = readl_relaxed(clk_base + PLLU_BASE);
+       reg &= ~GENMASK(20, 0);
+       reg |= fentry->m;
+       reg |= fentry->n << 8;
+       reg |= fentry->p << 16;
+       writel(reg, clk_base + PLLU_BASE);
+       reg |= PLL_ENABLE;
+       writel(reg, clk_base + PLLU_BASE);
+
+       readl_relaxed_poll_timeout(clk_base + PLLU_BASE, reg,
+                                  reg & PLL_BASE_LOCK, 2, 1000);
+       if (!(reg & PLL_BASE_LOCK)) {
+               pr_err("Timed out waiting for PLL_U to lock\n");
+               return -ETIMEDOUT;
+       }
+
+       return 0;
+}
+
+static int tegra210_init_pllu(void)
+{
+       u32 reg;
+       int err;
+
+       tegra210_pllu_set_defaults(&pll_u_vco_params);
+       /* skip initialization when pllu is in hw controlled mode */
+       reg = readl_relaxed(clk_base + PLLU_BASE);
+       if (reg & PLLU_BASE_OVERRIDE) {
+               if (!(reg & PLL_ENABLE)) {
+                       err = tegra210_enable_pllu();
+                       if (err < 0) {
+                               WARN_ON(1);
+                               return err;
+                       }
+               }
+               /* enable hw controlled mode */
+               reg = readl_relaxed(clk_base + PLLU_BASE);
+               reg &= ~PLLU_BASE_OVERRIDE;
+               writel(reg, clk_base + PLLU_BASE);
+
+               reg = readl_relaxed(clk_base + PLLU_HW_PWRDN_CFG0);
+               reg |= PLLU_HW_PWRDN_CFG0_IDDQ_PD_INCLUDE |
+                      PLLU_HW_PWRDN_CFG0_USE_SWITCH_DETECT |
+                      PLLU_HW_PWRDN_CFG0_USE_LOCKDET;
+               reg &= ~(PLLU_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL |
+                       PLLU_HW_PWRDN_CFG0_CLK_SWITCH_SWCTL);
+               writel_relaxed(reg, clk_base + PLLU_HW_PWRDN_CFG0);
+
+               reg = readl_relaxed(clk_base + XUSB_PLL_CFG0);
+               reg &= ~XUSB_PLL_CFG0_PLLU_LOCK_DLY_MASK;
+               writel_relaxed(reg, clk_base + XUSB_PLL_CFG0);
+               udelay(1);
+
+               reg = readl_relaxed(clk_base + PLLU_HW_PWRDN_CFG0);
+               reg |= PLLU_HW_PWRDN_CFG0_SEQ_ENABLE;
+               writel_relaxed(reg, clk_base + PLLU_HW_PWRDN_CFG0);
+               udelay(1);
+
+               reg = readl_relaxed(clk_base + PLLU_BASE);
+               reg &= ~PLLU_BASE_CLKENABLE_USB;
+               writel_relaxed(reg, clk_base + PLLU_BASE);
+       }
+
+       /* enable UTMIPLL hw control if not yet done by the bootloader */
+       reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0);
+       if (!(reg & UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE))
+               tegra210_utmi_param_configure();
+
+       return 0;
+}
+
 static __init void tegra210_periph_clk_init(void __iomem *clk_base,
                                            void __iomem *pmc_base)
 {
@@ -2347,6 +2685,11 @@ static __init void tegra210_periph_clk_init(void __iomem *clk_base,
        clk_register_clkdev(clk, "cml1", NULL);
        clks[TEGRA210_CLK_CML1] = clk;
 
+       clk = tegra_clk_register_super_clk("aclk", aclk_parents,
+                               ARRAY_SIZE(aclk_parents), 0, clk_base + 0x6e0,
+                               0, NULL);
+       clks[TEGRA210_CLK_ACLK] = clk;
+
        tegra_periph_clk_init(clk_base, pmc_base, tegra210_clks, &pll_p_params);
 }
 
@@ -2402,9 +2745,6 @@ static void __init tegra210_pll_init(void __iomem *clk_base,
        clk_register_clkdev(clk, "pll_mb", NULL);
        clks[TEGRA210_CLK_PLL_MB] = clk;
 
-       clk_register_clkdev(clk, "pll_m_out1", NULL);
-       clks[TEGRA210_CLK_PLL_M_OUT1] = clk;
-
        /* PLLM_UD */
        clk = clk_register_fixed_factor(NULL, "pll_m_ud", "pll_m",
                                        CLK_SET_RATE_PARENT, 1, 1);
@@ -2412,11 +2752,12 @@ static void __init tegra210_pll_init(void __iomem *clk_base,
        clks[TEGRA210_CLK_PLL_M_UD] = clk;
 
        /* PLLU_VCO */
-       clk = tegra_clk_register_pllu_tegra210("pll_u_vco", "pll_ref",
-                                              clk_base, 0, &pll_u_vco_params,
-                                              &pll_u_lock);
-       clk_register_clkdev(clk, "pll_u_vco", NULL);
-       clks[TEGRA210_CLK_PLL_U] = clk;
+       if (!tegra210_init_pllu()) {
+               clk = clk_register_fixed_rate(NULL, "pll_u_vco", "pll_ref", 0,
+                                             480*1000*1000);
+               clk_register_clkdev(clk, "pll_u_vco", NULL);
+               clks[TEGRA210_CLK_PLL_U] = clk;
+       }
 
        /* PLLU_OUT */
        clk = clk_register_divider_table(NULL, "pll_u_out", "pll_u_vco", 0,
@@ -2651,6 +2992,8 @@ static struct tegra_clk_init_table init_table[] __initdata = {
        { TEGRA210_CLK_EMC, TEGRA210_CLK_CLK_MAX, 0, 1 },
        { TEGRA210_CLK_MSELECT, TEGRA210_CLK_CLK_MAX, 0, 1 },
        { TEGRA210_CLK_CSITE, TEGRA210_CLK_CLK_MAX, 0, 1 },
+       /* TODO find a way to enable this on-demand */
+       { TEGRA210_CLK_DBGAPB, TEGRA210_CLK_CLK_MAX, 0, 1 },
        { TEGRA210_CLK_TSENSOR, TEGRA210_CLK_CLK_M, 400000, 0 },
        { TEGRA210_CLK_I2C1, TEGRA210_CLK_PLL_P, 0, 0 },
        { TEGRA210_CLK_I2C2, TEGRA210_CLK_PLL_P, 0, 0 },
@@ -2661,6 +3004,8 @@ static struct tegra_clk_init_table init_table[] __initdata = {
        { TEGRA210_CLK_PLL_DP, TEGRA210_CLK_CLK_MAX, 270000000, 0 },
        { TEGRA210_CLK_SOC_THERM, TEGRA210_CLK_PLL_P, 51000000, 0 },
        { TEGRA210_CLK_CCLK_G, TEGRA210_CLK_CLK_MAX, 0, 1 },
+       { TEGRA210_CLK_PLL_U_OUT1, TEGRA210_CLK_CLK_MAX, 48000000, 1 },
+       { TEGRA210_CLK_PLL_U_OUT2, TEGRA210_CLK_CLK_MAX, 60000000, 1 },
        /* This MUST be the last entry. */
        { TEGRA210_CLK_CLK_MAX, TEGRA210_CLK_CLK_MAX, 0, 0 },
 };
@@ -2678,6 +3023,81 @@ static void __init tegra210_clock_apply_init_table(void)
        tegra_init_from_table(init_table, clks, TEGRA210_CLK_CLK_MAX);
 }
 
+/**
+ * tegra210_car_barrier - wait for pending writes to the CAR to complete
+ *
+ * Wait for any outstanding writes to the CAR MMIO space from this CPU
+ * to complete before continuing execution.  No return value.
+ */
+static void tegra210_car_barrier(void)
+{
+       readl_relaxed(clk_base + RST_DFLL_DVCO);
+}
+
+/**
+ * tegra210_clock_assert_dfll_dvco_reset - assert the DFLL's DVCO reset
+ *
+ * Assert the reset line of the DFLL's DVCO.  No return value.
+ */
+static void tegra210_clock_assert_dfll_dvco_reset(void)
+{
+       u32 v;
+
+       v = readl_relaxed(clk_base + RST_DFLL_DVCO);
+       v |= (1 << DVFS_DFLL_RESET_SHIFT);
+       writel_relaxed(v, clk_base + RST_DFLL_DVCO);
+       tegra210_car_barrier();
+}
+
+/**
+ * tegra210_clock_deassert_dfll_dvco_reset - deassert the DFLL's DVCO reset
+ *
+ * Deassert the reset line of the DFLL's DVCO, allowing the DVCO to
+ * operate.  No return value.
+ */
+static void tegra210_clock_deassert_dfll_dvco_reset(void)
+{
+       u32 v;
+
+       v = readl_relaxed(clk_base + RST_DFLL_DVCO);
+       v &= ~(1 << DVFS_DFLL_RESET_SHIFT);
+       writel_relaxed(v, clk_base + RST_DFLL_DVCO);
+       tegra210_car_barrier();
+}
+
+static int tegra210_reset_assert(unsigned long id)
+{
+       if (id == TEGRA210_RST_DFLL_DVCO)
+               tegra210_clock_assert_dfll_dvco_reset();
+       else if (id == TEGRA210_RST_ADSP)
+               writel(GENMASK(26, 21) | BIT(7),
+                       clk_base + CLK_RST_CONTROLLER_RST_DEV_Y_SET);
+       else
+               return -EINVAL;
+
+       return 0;
+}
+
+static int tegra210_reset_deassert(unsigned long id)
+{
+       if (id == TEGRA210_RST_DFLL_DVCO)
+               tegra210_clock_deassert_dfll_dvco_reset();
+       else if (id == TEGRA210_RST_ADSP) {
+               writel(BIT(21), clk_base + CLK_RST_CONTROLLER_RST_DEV_Y_CLR);
+               /*
+                * Considering adsp cpu clock (min: 12.5MHZ, max: 1GHz)
+                * a delay of 5us ensures that it's at least
+                * 6 * adsp_cpu_cycle_period long.
+                */
+               udelay(5);
+               writel(GENMASK(26, 22) | BIT(7),
+                       clk_base + CLK_RST_CONTROLLER_RST_DEV_Y_CLR);
+       } else
+               return -EINVAL;
+
+       return 0;
+}
+
 /**
  * tegra210_clock_init - Tegra210-specific clock initialization
  * @np: struct device_node * of the DT node for the SoC CAR IP block
@@ -2742,6 +3162,9 @@ static void __init tegra210_clock_init(struct device_node *np)
 
        tegra_super_clk_gen5_init(clk_base, pmc_base, tegra210_clks,
                                  &pll_x_params);
+       tegra_init_special_resets(2, tegra210_reset_assert,
+                                 tegra210_reset_deassert);
+
        tegra_add_of_provider(np);
        tegra_register_devclks(devclks, ARRAY_SIZE(devclks));
 
index 8e2db5ead8da683500826a2968bd165ca88943b6..a2d163f759b4502df2ad4f1f4e5d738904da67a7 100644 (file)
@@ -817,6 +817,7 @@ static struct tegra_clk tegra30_clks[tegra_clk_max] __initdata = {
        [tegra_clk_pll_p_out4] = { .dt_id = TEGRA30_CLK_PLL_P_OUT4, .present = true },
        [tegra_clk_pll_a] = { .dt_id = TEGRA30_CLK_PLL_A, .present = true },
        [tegra_clk_pll_a_out0] = { .dt_id = TEGRA30_CLK_PLL_A_OUT0, .present = true },
+       [tegra_clk_cec] = { .dt_id = TEGRA30_CLK_CEC, .present = true },
 };
 
 static const char *pll_e_parents[] = { "pll_ref", "pll_p" };
index b2cdd9a235f435355a18efd06601b8ddfde9bce1..ba923f0d5953585ab17f6769f082a2efa1fb4be5 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/clkdev.h>
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
+#include <linux/delay.h>
 #include <linux/of.h>
 #include <linux/clk/tegra.h>
 #include <linux/reset-controller.h>
@@ -182,6 +183,20 @@ static int tegra_clk_rst_deassert(struct reset_controller_dev *rcdev,
        return -EINVAL;
 }
 
+static int tegra_clk_rst_reset(struct reset_controller_dev *rcdev,
+               unsigned long id)
+{
+       int err;
+
+       err = tegra_clk_rst_assert(rcdev, id);
+       if (err)
+               return err;
+
+       udelay(1);
+
+       return tegra_clk_rst_deassert(rcdev, id);
+}
+
 const struct tegra_clk_periph_regs *get_reg_bank(int clkid)
 {
        int reg_bank = clkid / 32;
@@ -274,6 +289,7 @@ void __init tegra_init_from_table(struct tegra_clk_init_table *tbl,
 static const struct reset_control_ops rst_ops = {
        .assert = tegra_clk_rst_assert,
        .deassert = tegra_clk_rst_deassert,
+       .reset = tegra_clk_rst_reset,
 };
 
 static struct reset_controller_dev rst_ctlr = {
index 6ba82ecffd4d40fdf4a00b366d8aaea5c12e3671..945b07093afa61c826b30d4259124df53f9e4adf 100644 (file)
@@ -116,7 +116,7 @@ struct tegra_clk_pll_freq_table {
        unsigned long   input_rate;
        unsigned long   output_rate;
        u32             n;
-       u16             m;
+       u32             m;
        u8              p;
        u8              cpcon;
        u16             sdm_data;
@@ -586,11 +586,11 @@ struct tegra_clk_periph {
 
 extern const struct clk_ops tegra_clk_periph_ops;
 struct clk *tegra_clk_register_periph(const char *name,
-               const char **parent_names, int num_parents,
+               const char * const *parent_names, int num_parents,
                struct tegra_clk_periph *periph, void __iomem *clk_base,
                u32 offset, unsigned long flags);
 struct clk *tegra_clk_register_periph_nodiv(const char *name,
-               const char **parent_names, int num_parents,
+               const char * const *parent_names, int num_parents,
                struct tegra_clk_periph *periph, void __iomem *clk_base,
                u32 offset);
 
@@ -626,7 +626,7 @@ struct tegra_periph_init_data {
        const char *name;
        int clk_id;
        union {
-               const char **parent_names;
+               const char *const *parent_names;
                const char *parent_name;
        } p;
        int num_parents;
@@ -686,6 +686,8 @@ struct tegra_periph_init_data {
 struct tegra_clk_super_mux {
        struct clk_hw   hw;
        void __iomem    *reg;
+       struct tegra_clk_frac_div frac_div;
+       const struct clk_ops    *div_ops;
        u8              width;
        u8              flags;
        u8              div2_index;
@@ -702,7 +704,10 @@ struct clk *tegra_clk_register_super_mux(const char *name,
                const char **parent_names, u8 num_parents,
                unsigned long flags, void __iomem *reg, u8 clk_super_flags,
                u8 width, u8 pllx_index, u8 div2_index, spinlock_t *lock);
-
+struct clk *tegra_clk_register_super_clk(const char *name,
+               const char * const *parent_names, u8 num_parents,
+               unsigned long flags, void __iomem *reg, u8 clk_super_flags,
+               spinlock_t *lock);
 /**
  * struct clk_init_table - clock initialization table
  * @clk_id:    clock id as mentioned in device tree bindings
index 6411e132faa2b01e25598edbdd2139b3e6185a5d..06f486b3488cb435d3a3b96c8f5d475c9d3b26c3 100644 (file)
@@ -55,20 +55,20 @@ static int dra7_apll_enable(struct clk_hw *hw)
        state <<= __ffs(ad->idlest_mask);
 
        /* Check is already locked */
-       v = ti_clk_ll_ops->clk_readl(ad->idlest_reg);
+       v = ti_clk_ll_ops->clk_readl(&ad->idlest_reg);
 
        if ((v & ad->idlest_mask) == state)
                return r;
 
-       v = ti_clk_ll_ops->clk_readl(ad->control_reg);
+       v = ti_clk_ll_ops->clk_readl(&ad->control_reg);
        v &= ~ad->enable_mask;
        v |= APLL_FORCE_LOCK << __ffs(ad->enable_mask);
-       ti_clk_ll_ops->clk_writel(v, ad->control_reg);
+       ti_clk_ll_ops->clk_writel(v, &ad->control_reg);
 
        state <<= __ffs(ad->idlest_mask);
 
        while (1) {
-               v = ti_clk_ll_ops->clk_readl(ad->idlest_reg);
+               v = ti_clk_ll_ops->clk_readl(&ad->idlest_reg);
                if ((v & ad->idlest_mask) == state)
                        break;
                if (i > MAX_APLL_WAIT_TRIES)
@@ -99,10 +99,10 @@ static void dra7_apll_disable(struct clk_hw *hw)
 
        state <<= __ffs(ad->idlest_mask);
 
-       v = ti_clk_ll_ops->clk_readl(ad->control_reg);
+       v = ti_clk_ll_ops->clk_readl(&ad->control_reg);
        v &= ~ad->enable_mask;
        v |= APLL_AUTO_IDLE << __ffs(ad->enable_mask);
-       ti_clk_ll_ops->clk_writel(v, ad->control_reg);
+       ti_clk_ll_ops->clk_writel(v, &ad->control_reg);
 }
 
 static int dra7_apll_is_enabled(struct clk_hw *hw)
@@ -113,7 +113,7 @@ static int dra7_apll_is_enabled(struct clk_hw *hw)
 
        ad = clk->dpll_data;
 
-       v = ti_clk_ll_ops->clk_readl(ad->control_reg);
+       v = ti_clk_ll_ops->clk_readl(&ad->control_reg);
        v &= ad->enable_mask;
 
        v >>= __ffs(ad->enable_mask);
@@ -164,7 +164,7 @@ static void __init omap_clk_register_apll(struct clk_hw *hw,
 
        ad->clk_bypass = __clk_get_hw(clk);
 
-       clk = clk_register(NULL, &clk_hw->hw);
+       clk = ti_clk_register(NULL, &clk_hw->hw, node->name);
        if (!IS_ERR(clk)) {
                of_clk_add_provider(node, of_clk_src_simple_get, clk);
                kfree(clk_hw->hw.init->parent_names);
@@ -185,6 +185,7 @@ static void __init of_dra7_apll_setup(struct device_node *node)
        struct clk_hw_omap *clk_hw = NULL;
        struct clk_init_data *init = NULL;
        const char **parent_names = NULL;
+       int ret;
 
        ad = kzalloc(sizeof(*ad), GFP_KERNEL);
        clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
@@ -194,7 +195,6 @@ static void __init of_dra7_apll_setup(struct device_node *node)
 
        clk_hw->dpll_data = ad;
        clk_hw->hw.init = init;
-       clk_hw->flags = MEMMAP_ADDRESSING;
 
        init->name = node->name;
        init->ops = &apll_ck_ops;
@@ -213,10 +213,10 @@ static void __init of_dra7_apll_setup(struct device_node *node)
 
        init->parent_names = parent_names;
 
-       ad->control_reg = ti_clk_get_reg_addr(node, 0);
-       ad->idlest_reg = ti_clk_get_reg_addr(node, 1);
+       ret = ti_clk_get_reg_addr(node, 0, &ad->control_reg);
+       ret |= ti_clk_get_reg_addr(node, 1, &ad->idlest_reg);
 
-       if (IS_ERR(ad->control_reg) || IS_ERR(ad->idlest_reg))
+       if (ret)
                goto cleanup;
 
        ad->idlest_mask = 0x1;
@@ -242,7 +242,7 @@ static int omap2_apll_is_enabled(struct clk_hw *hw)
        struct dpll_data *ad = clk->dpll_data;
        u32 v;
 
-       v = ti_clk_ll_ops->clk_readl(ad->control_reg);
+       v = ti_clk_ll_ops->clk_readl(&ad->control_reg);
        v &= ad->enable_mask;
 
        v >>= __ffs(ad->enable_mask);
@@ -268,13 +268,13 @@ static int omap2_apll_enable(struct clk_hw *hw)
        u32 v;
        int i = 0;
 
-       v = ti_clk_ll_ops->clk_readl(ad->control_reg);
+       v = ti_clk_ll_ops->clk_readl(&ad->control_reg);
        v &= ~ad->enable_mask;
        v |= OMAP2_EN_APLL_LOCKED << __ffs(ad->enable_mask);
-       ti_clk_ll_ops->clk_writel(v, ad->control_reg);
+       ti_clk_ll_ops->clk_writel(v, &ad->control_reg);
 
        while (1) {
-               v = ti_clk_ll_ops->clk_readl(ad->idlest_reg);
+               v = ti_clk_ll_ops->clk_readl(&ad->idlest_reg);
                if (v & ad->idlest_mask)
                        break;
                if (i > MAX_APLL_WAIT_TRIES)
@@ -298,10 +298,10 @@ static void omap2_apll_disable(struct clk_hw *hw)
        struct dpll_data *ad = clk->dpll_data;
        u32 v;
 
-       v = ti_clk_ll_ops->clk_readl(ad->control_reg);
+       v = ti_clk_ll_ops->clk_readl(&ad->control_reg);
        v &= ~ad->enable_mask;
        v |= OMAP2_EN_APLL_STOPPED << __ffs(ad->enable_mask);
-       ti_clk_ll_ops->clk_writel(v, ad->control_reg);
+       ti_clk_ll_ops->clk_writel(v, &ad->control_reg);
 }
 
 static struct clk_ops omap2_apll_ops = {
@@ -316,10 +316,10 @@ static void omap2_apll_set_autoidle(struct clk_hw_omap *clk, u32 val)
        struct dpll_data *ad = clk->dpll_data;
        u32 v;
 
-       v = ti_clk_ll_ops->clk_readl(ad->autoidle_reg);
+       v = ti_clk_ll_ops->clk_readl(&ad->autoidle_reg);
        v &= ~ad->autoidle_mask;
        v |= val << __ffs(ad->autoidle_mask);
-       ti_clk_ll_ops->clk_writel(v, ad->control_reg);
+       ti_clk_ll_ops->clk_writel(v, &ad->control_reg);
 }
 
 #define OMAP2_APLL_AUTOIDLE_LOW_POWER_STOP     0x3
@@ -348,6 +348,7 @@ static void __init of_omap2_apll_setup(struct device_node *node)
        struct clk *clk;
        const char *parent_name;
        u32 val;
+       int ret;
 
        ad = kzalloc(sizeof(*ad), GFP_KERNEL);
        clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
@@ -393,12 +394,11 @@ static void __init of_omap2_apll_setup(struct device_node *node)
 
        ad->idlest_mask = 1 << val;
 
-       ad->control_reg = ti_clk_get_reg_addr(node, 0);
-       ad->autoidle_reg = ti_clk_get_reg_addr(node, 1);
-       ad->idlest_reg = ti_clk_get_reg_addr(node, 2);
+       ret = ti_clk_get_reg_addr(node, 0, &ad->control_reg);
+       ret |= ti_clk_get_reg_addr(node, 1, &ad->autoidle_reg);
+       ret |= ti_clk_get_reg_addr(node, 2, &ad->idlest_reg);
 
-       if (IS_ERR(ad->control_reg) || IS_ERR(ad->autoidle_reg) ||
-           IS_ERR(ad->idlest_reg))
+       if (ret)
                goto cleanup;
 
        clk = clk_register(NULL, &clk_hw->hw);
index 345af43465f0f9a27aeedc431b51d0733bc4b896..7bb9afbe4058974112ac7a025a136777d67e414e 100644 (file)
@@ -25,7 +25,7 @@
 #include "clock.h"
 
 struct clk_ti_autoidle {
-       void __iomem            *reg;
+       struct clk_omap_reg     reg;
        u8                      shift;
        u8                      flags;
        const char              *name;
@@ -73,28 +73,28 @@ static void _allow_autoidle(struct clk_ti_autoidle *clk)
 {
        u32 val;
 
-       val = ti_clk_ll_ops->clk_readl(clk->reg);
+       val = ti_clk_ll_ops->clk_readl(&clk->reg);
 
        if (clk->flags & AUTOIDLE_LOW)
                val &= ~(1 << clk->shift);
        else
                val |= (1 << clk->shift);
 
-       ti_clk_ll_ops->clk_writel(val, clk->reg);
+       ti_clk_ll_ops->clk_writel(val, &clk->reg);
 }
 
 static void _deny_autoidle(struct clk_ti_autoidle *clk)
 {
        u32 val;
 
-       val = ti_clk_ll_ops->clk_readl(clk->reg);
+       val = ti_clk_ll_ops->clk_readl(&clk->reg);
 
        if (clk->flags & AUTOIDLE_LOW)
                val |= (1 << clk->shift);
        else
                val &= ~(1 << clk->shift);
 
-       ti_clk_ll_ops->clk_writel(val, clk->reg);
+       ti_clk_ll_ops->clk_writel(val, &clk->reg);
 }
 
 /**
@@ -140,6 +140,7 @@ int __init of_ti_clk_autoidle_setup(struct device_node *node)
 {
        u32 shift;
        struct clk_ti_autoidle *clk;
+       int ret;
 
        /* Check if this clock has autoidle support or not */
        if (of_property_read_u32(node, "ti,autoidle-shift", &shift))
@@ -152,11 +153,10 @@ int __init of_ti_clk_autoidle_setup(struct device_node *node)
 
        clk->shift = shift;
        clk->name = node->name;
-       clk->reg = ti_clk_get_reg_addr(node, 0);
-
-       if (IS_ERR(clk->reg)) {
+       ret = ti_clk_get_reg_addr(node, 0, &clk->reg);
+       if (ret) {
                kfree(clk);
-               return -EINVAL;
+               return ret;
        }
 
        if (of_property_read_bool(node, "ti,invert-autoidle-bit"))
index 11d8aa3ec18604a7ce5c04ddded50ff660f554c1..b1251cae98b882291f0baceb41aae46df0d94070 100644 (file)
  * @idlest_reg and @idlest_bit.  No return value.
  */
 static void omap3430es2_clk_ssi_find_idlest(struct clk_hw_omap *clk,
-                                           void __iomem **idlest_reg,
+                                           struct clk_omap_reg *idlest_reg,
                                            u8 *idlest_bit,
                                            u8 *idlest_val)
 {
-       u32 r;
-
-       r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
-       *idlest_reg = (__force void __iomem *)r;
+       memcpy(idlest_reg, &clk->enable_reg, sizeof(*idlest_reg));
+       idlest_reg->offset &= ~0xf0;
+       idlest_reg->offset |= 0x20;
        *idlest_bit = OMAP3430ES2_ST_SSI_IDLE_SHIFT;
        *idlest_val = OMAP34XX_CM_IDLEST_VAL;
 }
@@ -85,15 +84,15 @@ const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_ssi_wait = {
  * default find_idlest code assumes that they are at the same
  * position.)  No return value.
  */
-static void omap3430es2_clk_dss_usbhost_find_idlest(struct clk_hw_omap *clk,
-                                                   void __iomem **idlest_reg,
-                                                   u8 *idlest_bit,
-                                                   u8 *idlest_val)
+static void
+omap3430es2_clk_dss_usbhost_find_idlest(struct clk_hw_omap *clk,
+                                       struct clk_omap_reg *idlest_reg,
+                                       u8 *idlest_bit, u8 *idlest_val)
 {
-       u32 r;
+       memcpy(idlest_reg, &clk->enable_reg, sizeof(*idlest_reg));
 
-       r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
-       *idlest_reg = (__force void __iomem *)r;
+       idlest_reg->offset &= ~0xf0;
+       idlest_reg->offset |= 0x20;
        /* USBHOST_IDLE has same shift */
        *idlest_bit = OMAP3430ES2_ST_DSS_IDLE_SHIFT;
        *idlest_val = OMAP34XX_CM_IDLEST_VAL;
@@ -122,15 +121,15 @@ const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_dss_usbhost_wait = {
  * shift from the CM_{I,F}CLKEN bit.  Pass back the correct info via
  * @idlest_reg and @idlest_bit.  No return value.
  */
-static void omap3430es2_clk_hsotgusb_find_idlest(struct clk_hw_omap *clk,
-                                                void __iomem **idlest_reg,
-                                                u8 *idlest_bit,
-                                                u8 *idlest_val)
+static void
+omap3430es2_clk_hsotgusb_find_idlest(struct clk_hw_omap *clk,
+                                    struct clk_omap_reg *idlest_reg,
+                                    u8 *idlest_bit,
+                                    u8 *idlest_val)
 {
-       u32 r;
-
-       r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
-       *idlest_reg = (__force void __iomem *)r;
+       memcpy(idlest_reg, &clk->enable_reg, sizeof(*idlest_reg));
+       idlest_reg->offset &= ~0xf0;
+       idlest_reg->offset |= 0x20;
        *idlest_bit = OMAP3430ES2_ST_HSOTGUSB_IDLE_SHIFT;
        *idlest_val = OMAP34XX_CM_IDLEST_VAL;
 }
@@ -154,11 +153,11 @@ const struct clk_hw_omap_ops clkhwops_omap3430es2_iclk_hsotgusb_wait = {
  * bit. A value of 1 indicates that clock is enabled.
  */
 static void am35xx_clk_find_idlest(struct clk_hw_omap *clk,
-                                  void __iomem **idlest_reg,
+                                  struct clk_omap_reg *idlest_reg,
                                   u8 *idlest_bit,
                                   u8 *idlest_val)
 {
-       *idlest_reg = (__force void __iomem *)(clk->enable_reg);
+       memcpy(idlest_reg, &clk->enable_reg, sizeof(*idlest_reg));
        *idlest_bit = clk->enable_bit + AM35XX_IPSS_ICK_EN_ACK_OFFSET;
        *idlest_val = AM35XX_IPSS_CLK_IDLEST_VAL;
 }
@@ -178,10 +177,10 @@ static void am35xx_clk_find_idlest(struct clk_hw_omap *clk,
  * avoid this issue, and remove the casts.  No return value.
  */
 static void am35xx_clk_find_companion(struct clk_hw_omap *clk,
-                                     void __iomem **other_reg,
+                                     struct clk_omap_reg *other_reg,
                                      u8 *other_bit)
 {
-       *other_reg = (__force void __iomem *)(clk->enable_reg);
+       memcpy(other_reg, &clk->enable_reg, sizeof(*other_reg));
        if (clk->enable_bit & AM35XX_IPSS_ICK_MASK)
                *other_bit = clk->enable_bit + AM35XX_IPSS_ICK_FCK_OFFSET;
        else
@@ -205,14 +204,14 @@ const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait = {
  * and @idlest_bit.  No return value.
  */
 static void am35xx_clk_ipss_find_idlest(struct clk_hw_omap *clk,
-                                       void __iomem **idlest_reg,
+                                       struct clk_omap_reg *idlest_reg,
                                        u8 *idlest_bit,
                                        u8 *idlest_val)
 {
-       u32 r;
+       memcpy(idlest_reg, &clk->enable_reg, sizeof(*idlest_reg));
 
-       r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
-       *idlest_reg = (__force void __iomem *)r;
+       idlest_reg->offset &= ~0xf0;
+       idlest_reg->offset |= 0x20;
        *idlest_bit = AM35XX_ST_IPSS_SHIFT;
        *idlest_val = OMAP34XX_CM_IDLEST_VAL;
 }
index 7a8b51b35f9fe799388a24d8d8b67ea7eabfbd8a..1c8bb83003bfe344fe15e34ad50f1b6953e39c32 100644 (file)
 #define OMAP4_DPLL_USB_DEFFREQ                         960000000
 
 static struct ti_dt_clk omap44xx_clks[] = {
-       DT_CLK(NULL, "extalt_clkin_ck", "extalt_clkin_ck"),
-       DT_CLK(NULL, "pad_clks_src_ck", "pad_clks_src_ck"),
-       DT_CLK(NULL, "pad_clks_ck", "pad_clks_ck"),
-       DT_CLK(NULL, "pad_slimbus_core_clks_ck", "pad_slimbus_core_clks_ck"),
-       DT_CLK(NULL, "secure_32k_clk_src_ck", "secure_32k_clk_src_ck"),
-       DT_CLK(NULL, "slimbus_src_clk", "slimbus_src_clk"),
-       DT_CLK(NULL, "slimbus_clk", "slimbus_clk"),
-       DT_CLK(NULL, "sys_32k_ck", "sys_32k_ck"),
-       DT_CLK(NULL, "virt_12000000_ck", "virt_12000000_ck"),
-       DT_CLK(NULL, "virt_13000000_ck", "virt_13000000_ck"),
-       DT_CLK(NULL, "virt_16800000_ck", "virt_16800000_ck"),
-       DT_CLK(NULL, "virt_19200000_ck", "virt_19200000_ck"),
-       DT_CLK(NULL, "virt_26000000_ck", "virt_26000000_ck"),
-       DT_CLK(NULL, "virt_27000000_ck", "virt_27000000_ck"),
-       DT_CLK(NULL, "virt_38400000_ck", "virt_38400000_ck"),
-       DT_CLK(NULL, "sys_clkin_ck", "sys_clkin_ck"),
-       DT_CLK(NULL, "tie_low_clock_ck", "tie_low_clock_ck"),
-       DT_CLK(NULL, "utmi_phy_clkout_ck", "utmi_phy_clkout_ck"),
-       DT_CLK(NULL, "xclk60mhsp1_ck", "xclk60mhsp1_ck"),
-       DT_CLK(NULL, "xclk60mhsp2_ck", "xclk60mhsp2_ck"),
-       DT_CLK(NULL, "xclk60motg_ck", "xclk60motg_ck"),
-       DT_CLK(NULL, "abe_dpll_bypass_clk_mux_ck", "abe_dpll_bypass_clk_mux_ck"),
-       DT_CLK(NULL, "abe_dpll_refclk_mux_ck", "abe_dpll_refclk_mux_ck"),
-       DT_CLK(NULL, "dpll_abe_ck", "dpll_abe_ck"),
-       DT_CLK(NULL, "dpll_abe_x2_ck", "dpll_abe_x2_ck"),
-       DT_CLK(NULL, "dpll_abe_m2x2_ck", "dpll_abe_m2x2_ck"),
-       DT_CLK(NULL, "abe_24m_fclk", "abe_24m_fclk"),
-       DT_CLK(NULL, "abe_clk", "abe_clk"),
-       DT_CLK(NULL, "aess_fclk", "aess_fclk"),
-       DT_CLK(NULL, "dpll_abe_m3x2_ck", "dpll_abe_m3x2_ck"),
-       DT_CLK(NULL, "core_hsd_byp_clk_mux_ck", "core_hsd_byp_clk_mux_ck"),
-       DT_CLK(NULL, "dpll_core_ck", "dpll_core_ck"),
-       DT_CLK(NULL, "dpll_core_x2_ck", "dpll_core_x2_ck"),
-       DT_CLK(NULL, "dpll_core_m6x2_ck", "dpll_core_m6x2_ck"),
-       DT_CLK(NULL, "dbgclk_mux_ck", "dbgclk_mux_ck"),
-       DT_CLK(NULL, "dpll_core_m2_ck", "dpll_core_m2_ck"),
-       DT_CLK(NULL, "ddrphy_ck", "ddrphy_ck"),
-       DT_CLK(NULL, "dpll_core_m5x2_ck", "dpll_core_m5x2_ck"),
-       DT_CLK(NULL, "div_core_ck", "div_core_ck"),
-       DT_CLK(NULL, "div_iva_hs_clk", "div_iva_hs_clk"),
-       DT_CLK(NULL, "div_mpu_hs_clk", "div_mpu_hs_clk"),
-       DT_CLK(NULL, "dpll_core_m4x2_ck", "dpll_core_m4x2_ck"),
-       DT_CLK(NULL, "dll_clk_div_ck", "dll_clk_div_ck"),
-       DT_CLK(NULL, "dpll_abe_m2_ck", "dpll_abe_m2_ck"),
-       DT_CLK(NULL, "dpll_core_m3x2_ck", "dpll_core_m3x2_ck"),
-       DT_CLK(NULL, "dpll_core_m7x2_ck", "dpll_core_m7x2_ck"),
-       DT_CLK(NULL, "iva_hsd_byp_clk_mux_ck", "iva_hsd_byp_clk_mux_ck"),
-       DT_CLK(NULL, "dpll_iva_ck", "dpll_iva_ck"),
-       DT_CLK(NULL, "dpll_iva_x2_ck", "dpll_iva_x2_ck"),
-       DT_CLK(NULL, "dpll_iva_m4x2_ck", "dpll_iva_m4x2_ck"),
-       DT_CLK(NULL, "dpll_iva_m5x2_ck", "dpll_iva_m5x2_ck"),
-       DT_CLK(NULL, "dpll_mpu_ck", "dpll_mpu_ck"),
-       DT_CLK(NULL, "dpll_mpu_m2_ck", "dpll_mpu_m2_ck"),
-       DT_CLK(NULL, "per_hs_clk_div_ck", "per_hs_clk_div_ck"),
-       DT_CLK(NULL, "per_hsd_byp_clk_mux_ck", "per_hsd_byp_clk_mux_ck"),
-       DT_CLK(NULL, "dpll_per_ck", "dpll_per_ck"),
-       DT_CLK(NULL, "dpll_per_m2_ck", "dpll_per_m2_ck"),
-       DT_CLK(NULL, "dpll_per_x2_ck", "dpll_per_x2_ck"),
-       DT_CLK(NULL, "dpll_per_m2x2_ck", "dpll_per_m2x2_ck"),
-       DT_CLK(NULL, "dpll_per_m3x2_ck", "dpll_per_m3x2_ck"),
-       DT_CLK(NULL, "dpll_per_m4x2_ck", "dpll_per_m4x2_ck"),
-       DT_CLK(NULL, "dpll_per_m5x2_ck", "dpll_per_m5x2_ck"),
-       DT_CLK(NULL, "dpll_per_m6x2_ck", "dpll_per_m6x2_ck"),
-       DT_CLK(NULL, "dpll_per_m7x2_ck", "dpll_per_m7x2_ck"),
-       DT_CLK(NULL, "usb_hs_clk_div_ck", "usb_hs_clk_div_ck"),
-       DT_CLK(NULL, "dpll_usb_ck", "dpll_usb_ck"),
-       DT_CLK(NULL, "dpll_usb_clkdcoldo_ck", "dpll_usb_clkdcoldo_ck"),
-       DT_CLK(NULL, "dpll_usb_m2_ck", "dpll_usb_m2_ck"),
-       DT_CLK(NULL, "ducati_clk_mux_ck", "ducati_clk_mux_ck"),
-       DT_CLK(NULL, "func_12m_fclk", "func_12m_fclk"),
-       DT_CLK(NULL, "func_24m_clk", "func_24m_clk"),
-       DT_CLK(NULL, "func_24mc_fclk", "func_24mc_fclk"),
-       DT_CLK(NULL, "func_48m_fclk", "func_48m_fclk"),
-       DT_CLK(NULL, "func_48mc_fclk", "func_48mc_fclk"),
-       DT_CLK(NULL, "func_64m_fclk", "func_64m_fclk"),
-       DT_CLK(NULL, "func_96m_fclk", "func_96m_fclk"),
-       DT_CLK(NULL, "init_60m_fclk", "init_60m_fclk"),
-       DT_CLK(NULL, "l3_div_ck", "l3_div_ck"),
-       DT_CLK(NULL, "l4_div_ck", "l4_div_ck"),
-       DT_CLK(NULL, "lp_clk_div_ck", "lp_clk_div_ck"),
-       DT_CLK(NULL, "l4_wkup_clk_mux_ck", "l4_wkup_clk_mux_ck"),
        DT_CLK("smp_twd", NULL, "mpu_periphclk"),
-       DT_CLK(NULL, "ocp_abe_iclk", "ocp_abe_iclk"),
-       DT_CLK(NULL, "per_abe_24m_fclk", "per_abe_24m_fclk"),
-       DT_CLK(NULL, "per_abe_nc_fclk", "per_abe_nc_fclk"),
-       DT_CLK(NULL, "syc_clk_div_ck", "syc_clk_div_ck"),
-       DT_CLK(NULL, "aes1_fck", "aes1_fck"),
-       DT_CLK(NULL, "aes2_fck", "aes2_fck"),
-       DT_CLK(NULL, "dmic_sync_mux_ck", "dmic_sync_mux_ck"),
-       DT_CLK(NULL, "func_dmic_abe_gfclk", "func_dmic_abe_gfclk"),
-       DT_CLK(NULL, "dss_sys_clk", "dss_sys_clk"),
-       DT_CLK(NULL, "dss_tv_clk", "dss_tv_clk"),
-       DT_CLK(NULL, "dss_dss_clk", "dss_dss_clk"),
-       DT_CLK(NULL, "dss_48mhz_clk", "dss_48mhz_clk"),
-       DT_CLK(NULL, "dss_fck", "dss_fck"),
        DT_CLK("omapdss_dss", "ick", "dss_fck"),
-       DT_CLK(NULL, "fdif_fck", "fdif_fck"),
-       DT_CLK(NULL, "gpio1_dbclk", "gpio1_dbclk"),
-       DT_CLK(NULL, "gpio2_dbclk", "gpio2_dbclk"),
-       DT_CLK(NULL, "gpio3_dbclk", "gpio3_dbclk"),
-       DT_CLK(NULL, "gpio4_dbclk", "gpio4_dbclk"),
-       DT_CLK(NULL, "gpio5_dbclk", "gpio5_dbclk"),
-       DT_CLK(NULL, "gpio6_dbclk", "gpio6_dbclk"),
-       DT_CLK(NULL, "sgx_clk_mux", "sgx_clk_mux"),
-       DT_CLK(NULL, "hsi_fck", "hsi_fck"),
-       DT_CLK(NULL, "iss_ctrlclk", "iss_ctrlclk"),
-       DT_CLK(NULL, "mcasp_sync_mux_ck", "mcasp_sync_mux_ck"),
-       DT_CLK(NULL, "func_mcasp_abe_gfclk", "func_mcasp_abe_gfclk"),
-       DT_CLK(NULL, "mcbsp1_sync_mux_ck", "mcbsp1_sync_mux_ck"),
-       DT_CLK(NULL, "func_mcbsp1_gfclk", "func_mcbsp1_gfclk"),
-       DT_CLK(NULL, "mcbsp2_sync_mux_ck", "mcbsp2_sync_mux_ck"),
-       DT_CLK(NULL, "func_mcbsp2_gfclk", "func_mcbsp2_gfclk"),
-       DT_CLK(NULL, "mcbsp3_sync_mux_ck", "mcbsp3_sync_mux_ck"),
-       DT_CLK(NULL, "func_mcbsp3_gfclk", "func_mcbsp3_gfclk"),
-       DT_CLK(NULL, "mcbsp4_sync_mux_ck", "mcbsp4_sync_mux_ck"),
-       DT_CLK(NULL, "per_mcbsp4_gfclk", "per_mcbsp4_gfclk"),
-       DT_CLK(NULL, "hsmmc1_fclk", "hsmmc1_fclk"),
-       DT_CLK(NULL, "hsmmc2_fclk", "hsmmc2_fclk"),
-       DT_CLK(NULL, "ocp2scp_usb_phy_phy_48m", "ocp2scp_usb_phy_phy_48m"),
-       DT_CLK(NULL, "sha2md5_fck", "sha2md5_fck"),
-       DT_CLK(NULL, "slimbus1_fclk_1", "slimbus1_fclk_1"),
-       DT_CLK(NULL, "slimbus1_fclk_0", "slimbus1_fclk_0"),
-       DT_CLK(NULL, "slimbus1_fclk_2", "slimbus1_fclk_2"),
-       DT_CLK(NULL, "slimbus1_slimbus_clk", "slimbus1_slimbus_clk"),
-       DT_CLK(NULL, "slimbus2_fclk_1", "slimbus2_fclk_1"),
-       DT_CLK(NULL, "slimbus2_fclk_0", "slimbus2_fclk_0"),
-       DT_CLK(NULL, "slimbus2_slimbus_clk", "slimbus2_slimbus_clk"),
-       DT_CLK(NULL, "smartreflex_core_fck", "smartreflex_core_fck"),
-       DT_CLK(NULL, "smartreflex_iva_fck", "smartreflex_iva_fck"),
-       DT_CLK(NULL, "smartreflex_mpu_fck", "smartreflex_mpu_fck"),
-       DT_CLK(NULL, "dmt1_clk_mux", "dmt1_clk_mux"),
-       DT_CLK(NULL, "cm2_dm10_mux", "cm2_dm10_mux"),
-       DT_CLK(NULL, "cm2_dm11_mux", "cm2_dm11_mux"),
-       DT_CLK(NULL, "cm2_dm2_mux", "cm2_dm2_mux"),
-       DT_CLK(NULL, "cm2_dm3_mux", "cm2_dm3_mux"),
-       DT_CLK(NULL, "cm2_dm4_mux", "cm2_dm4_mux"),
-       DT_CLK(NULL, "timer5_sync_mux", "timer5_sync_mux"),
-       DT_CLK(NULL, "timer6_sync_mux", "timer6_sync_mux"),
-       DT_CLK(NULL, "timer7_sync_mux", "timer7_sync_mux"),
-       DT_CLK(NULL, "timer8_sync_mux", "timer8_sync_mux"),
-       DT_CLK(NULL, "cm2_dm9_mux", "cm2_dm9_mux"),
-       DT_CLK(NULL, "usb_host_fs_fck", "usb_host_fs_fck"),
        DT_CLK("usbhs_omap", "fs_fck", "usb_host_fs_fck"),
-       DT_CLK(NULL, "utmi_p1_gfclk", "utmi_p1_gfclk"),
-       DT_CLK(NULL, "usb_host_hs_utmi_p1_clk", "usb_host_hs_utmi_p1_clk"),
-       DT_CLK(NULL, "utmi_p2_gfclk", "utmi_p2_gfclk"),
-       DT_CLK(NULL, "usb_host_hs_utmi_p2_clk", "usb_host_hs_utmi_p2_clk"),
-       DT_CLK(NULL, "usb_host_hs_utmi_p3_clk", "usb_host_hs_utmi_p3_clk"),
-       DT_CLK(NULL, "usb_host_hs_hsic480m_p1_clk", "usb_host_hs_hsic480m_p1_clk"),
-       DT_CLK(NULL, "usb_host_hs_hsic60m_p1_clk", "usb_host_hs_hsic60m_p1_clk"),
-       DT_CLK(NULL, "usb_host_hs_hsic60m_p2_clk", "usb_host_hs_hsic60m_p2_clk"),
-       DT_CLK(NULL, "usb_host_hs_hsic480m_p2_clk", "usb_host_hs_hsic480m_p2_clk"),
-       DT_CLK(NULL, "usb_host_hs_func48mclk", "usb_host_hs_func48mclk"),
-       DT_CLK(NULL, "usb_host_hs_fck", "usb_host_hs_fck"),
        DT_CLK("usbhs_omap", "hs_fck", "usb_host_hs_fck"),
-       DT_CLK(NULL, "otg_60m_gfclk", "otg_60m_gfclk"),
-       DT_CLK(NULL, "usb_otg_hs_xclk", "usb_otg_hs_xclk"),
-       DT_CLK(NULL, "usb_otg_hs_ick", "usb_otg_hs_ick"),
        DT_CLK("musb-omap2430", "ick", "usb_otg_hs_ick"),
-       DT_CLK(NULL, "usb_phy_cm_clk32k", "usb_phy_cm_clk32k"),
-       DT_CLK(NULL, "usb_tll_hs_usb_ch2_clk", "usb_tll_hs_usb_ch2_clk"),
-       DT_CLK(NULL, "usb_tll_hs_usb_ch0_clk", "usb_tll_hs_usb_ch0_clk"),
-       DT_CLK(NULL, "usb_tll_hs_usb_ch1_clk", "usb_tll_hs_usb_ch1_clk"),
-       DT_CLK(NULL, "usb_tll_hs_ick", "usb_tll_hs_ick"),
        DT_CLK("usbhs_omap", "usbtll_ick", "usb_tll_hs_ick"),
        DT_CLK("usbhs_tll", "usbtll_ick", "usb_tll_hs_ick"),
-       DT_CLK(NULL, "usim_ck", "usim_ck"),
-       DT_CLK(NULL, "usim_fclk", "usim_fclk"),
-       DT_CLK(NULL, "pmd_stm_clock_mux_ck", "pmd_stm_clock_mux_ck"),
-       DT_CLK(NULL, "pmd_trace_clk_mux_ck", "pmd_trace_clk_mux_ck"),
-       DT_CLK(NULL, "stm_clk_div_ck", "stm_clk_div_ck"),
-       DT_CLK(NULL, "trace_clk_div_ck", "trace_clk_div_ck"),
-       DT_CLK(NULL, "auxclk0_src_ck", "auxclk0_src_ck"),
-       DT_CLK(NULL, "auxclk0_ck", "auxclk0_ck"),
-       DT_CLK(NULL, "auxclkreq0_ck", "auxclkreq0_ck"),
-       DT_CLK(NULL, "auxclk1_src_ck", "auxclk1_src_ck"),
-       DT_CLK(NULL, "auxclk1_ck", "auxclk1_ck"),
-       DT_CLK(NULL, "auxclkreq1_ck", "auxclkreq1_ck"),
-       DT_CLK(NULL, "auxclk2_src_ck", "auxclk2_src_ck"),
-       DT_CLK(NULL, "auxclk2_ck", "auxclk2_ck"),
-       DT_CLK(NULL, "auxclkreq2_ck", "auxclkreq2_ck"),
-       DT_CLK(NULL, "auxclk3_src_ck", "auxclk3_src_ck"),
-       DT_CLK(NULL, "auxclk3_ck", "auxclk3_ck"),
-       DT_CLK(NULL, "auxclkreq3_ck", "auxclkreq3_ck"),
-       DT_CLK(NULL, "auxclk4_src_ck", "auxclk4_src_ck"),
-       DT_CLK(NULL, "auxclk4_ck", "auxclk4_ck"),
-       DT_CLK(NULL, "auxclkreq4_ck", "auxclkreq4_ck"),
-       DT_CLK(NULL, "auxclk5_src_ck", "auxclk5_src_ck"),
-       DT_CLK(NULL, "auxclk5_ck", "auxclk5_ck"),
-       DT_CLK(NULL, "auxclkreq5_ck", "auxclkreq5_ck"),
        DT_CLK("omap_i2c.1", "ick", "dummy_ck"),
        DT_CLK("omap_i2c.2", "ick", "dummy_ck"),
        DT_CLK("omap_i2c.3", "ick", "dummy_ck"),
@@ -263,9 +80,6 @@ static struct ti_dt_clk omap44xx_clks[] = {
        DT_CLK("4013c000.timer", "timer_sys_ck", "syc_clk_div_ck"),
        DT_CLK("4013e000.timer", "timer_sys_ck", "syc_clk_div_ck"),
        DT_CLK(NULL, "cpufreq_ck", "dpll_mpu_ck"),
-       DT_CLK(NULL, "bandgap_fclk", "bandgap_fclk"),
-       DT_CLK(NULL, "div_ts_ck", "div_ts_ck"),
-       DT_CLK(NULL, "bandgap_ts_fclk", "bandgap_ts_fclk"),
        { .node_name = NULL },
 };
 
@@ -278,6 +92,8 @@ int __init omap4xxx_dt_clk_init(void)
 
        omap2_clk_disable_autoidle_all();
 
+       ti_clk_add_aliases();
+
        /*
         * Lock USB DPLL on OMAP4 devices so that the L3INIT power
         * domain can transition to retention state when not in use.
index 45d05339d583fad8c3beee9755534eb4ebe4f0cd..13eb04f72389bbf68e26a12f71b74188910e8ab8 100644 (file)
@@ -24,6 +24,9 @@
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
+#include <linux/clk/ti.h>
+
+#include "clock.h"
 
 #define DRA7_ATL_INSTANCES     4
 
@@ -171,6 +174,7 @@ static void __init of_dra7_atl_clock_setup(struct device_node *node)
        struct clk_init_data init = { NULL };
        const char **parent_names = NULL;
        struct clk *clk;
+       int ret;
 
        clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
        if (!clk_hw) {
@@ -200,9 +204,14 @@ static void __init of_dra7_atl_clock_setup(struct device_node *node)
 
        init.parent_names = parent_names;
 
-       clk = clk_register(NULL, &clk_hw->hw);
+       clk = ti_clk_register(NULL, &clk_hw->hw, node->name);
 
        if (!IS_ERR(clk)) {
+               ret = ti_clk_add_alias(NULL, clk, node->name);
+               if (ret) {
+                       clk_unregister(clk);
+                       goto cleanup;
+               }
                of_clk_add_provider(node, of_clk_src_simple_get, clk);
                kfree(parent_names);
                return;
index 5fcf247759ac413a94c155571d8833bc8261a974..e5a1c8297a1d256fd1d6fc006121b97a6d89e821 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/list.h>
 #include <linux/regmap.h>
 #include <linux/bootmem.h>
+#include <linux/device.h>
 
 #include "clock.h"
 
@@ -42,27 +43,29 @@ struct clk_iomap {
 
 static struct clk_iomap *clk_memmaps[CLK_MAX_MEMMAPS];
 
-static void clk_memmap_writel(u32 val, void __iomem *reg)
+static void clk_memmap_writel(u32 val, const struct clk_omap_reg *reg)
 {
-       struct clk_omap_reg *r = (struct clk_omap_reg *)&reg;
-       struct clk_iomap *io = clk_memmaps[r->index];
+       struct clk_iomap *io = clk_memmaps[reg->index];
 
-       if (io->regmap)
-               regmap_write(io->regmap, r->offset, val);
+       if (reg->ptr)
+               writel_relaxed(val, reg->ptr);
+       else if (io->regmap)
+               regmap_write(io->regmap, reg->offset, val);
        else
-               writel_relaxed(val, io->mem + r->offset);
+               writel_relaxed(val, io->mem + reg->offset);
 }
 
-static u32 clk_memmap_readl(void __iomem *reg)
+static u32 clk_memmap_readl(const struct clk_omap_reg *reg)
 {
        u32 val;
-       struct clk_omap_reg *r = (struct clk_omap_reg *)&reg;
-       struct clk_iomap *io = clk_memmaps[r->index];
+       struct clk_iomap *io = clk_memmaps[reg->index];
 
-       if (io->regmap)
-               regmap_read(io->regmap, r->offset, &val);
+       if (reg->ptr)
+               val = readl_relaxed(reg->ptr);
+       else if (io->regmap)
+               regmap_read(io->regmap, reg->offset, &val);
        else
-               val = readl_relaxed(io->mem + r->offset);
+               val = readl_relaxed(io->mem + reg->offset);
 
        return val;
 }
@@ -161,20 +164,18 @@ int __init ti_clk_retry_init(struct device_node *node, struct clk_hw *hw,
  * ti_clk_get_reg_addr - get register address for a clock register
  * @node: device node for the clock
  * @index: register index from the clock node
+ * @reg: pointer to target register struct
  *
- * Builds clock register address from device tree information. This
- * is a struct of type clk_omap_reg. Returns a pointer to the register
- * address, or a pointer error value in failure.
+ * Builds clock register address from device tree information, and returns
+ * the data via the provided output pointer @reg. Returns 0 on success,
+ * negative error value on failure.
  */
-void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index)
+int ti_clk_get_reg_addr(struct device_node *node, int index,
+                       struct clk_omap_reg *reg)
 {
-       struct clk_omap_reg *reg;
        u32 val;
-       u32 tmp;
        int i;
 
-       reg = (struct clk_omap_reg *)&tmp;
-
        for (i = 0; i < CLK_MAX_MEMMAPS; i++) {
                if (clocks_node_ptr[i] == node->parent)
                        break;
@@ -182,19 +183,20 @@ void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index)
 
        if (i == CLK_MAX_MEMMAPS) {
                pr_err("clk-provider not found for %s!\n", node->name);
-               return IOMEM_ERR_PTR(-ENOENT);
+               return -ENOENT;
        }
 
        reg->index = i;
 
        if (of_property_read_u32_index(node, "reg", index, &val)) {
                pr_err("%s must have reg[%d]!\n", node->name, index);
-               return IOMEM_ERR_PTR(-EINVAL);
+               return -EINVAL;
        }
 
        reg->offset = val;
+       reg->ptr = NULL;
 
-       return (__force void __iomem *)tmp;
+       return 0;
 }
 
 /**
@@ -297,6 +299,7 @@ struct clk __init *ti_clk_register_clk(struct ti_clk *setup)
        struct ti_clk_fixed *fixed;
        struct ti_clk_fixed_factor *fixed_factor;
        struct clk_hw *clk_hw;
+       int ret;
 
        if (setup->clk)
                return setup->clk;
@@ -307,6 +310,13 @@ struct clk __init *ti_clk_register_clk(struct ti_clk *setup)
 
                clk = clk_register_fixed_rate(NULL, setup->name, NULL, 0,
                                              fixed->frequency);
+               if (!IS_ERR(clk)) {
+                       ret = ti_clk_add_alias(NULL, clk, setup->name);
+                       if (ret) {
+                               clk_unregister(clk);
+                               clk = ERR_PTR(ret);
+                       }
+               }
                break;
        case TI_CLK_MUX:
                clk = ti_clk_register_mux(setup);
@@ -324,6 +334,13 @@ struct clk __init *ti_clk_register_clk(struct ti_clk *setup)
                                                fixed_factor->parent,
                                                0, fixed_factor->mult,
                                                fixed_factor->div);
+               if (!IS_ERR(clk)) {
+                       ret = ti_clk_add_alias(NULL, clk, setup->name);
+                       if (ret) {
+                               clk_unregister(clk);
+                               clk = ERR_PTR(ret);
+                       }
+               }
                break;
        case TI_CLK_GATE:
                clk = ti_clk_register_gate(setup);
@@ -371,9 +388,6 @@ int __init ti_clk_register_legacy_clks(struct ti_clk_alias *clks)
                                       clks->clk->name, PTR_ERR(clk));
                                return PTR_ERR(clk);
                        }
-               } else {
-                       clks->lk.clk = clk;
-                       clkdev_add(&clks->lk);
                }
                clks++;
        }
@@ -396,8 +410,6 @@ int __init ti_clk_register_legacy_clks(struct ti_clk_alias *clks)
                                }
                        } else {
                                retry = true;
-                               retry_clk->lk.clk = clk;
-                               clkdev_add(&retry_clk->lk);
                                list_del(&retry_clk->link);
                        }
                }
@@ -407,6 +419,32 @@ int __init ti_clk_register_legacy_clks(struct ti_clk_alias *clks)
 }
 #endif
 
+static const struct of_device_id simple_clk_match_table[] __initconst = {
+       { .compatible = "fixed-clock" },
+       { .compatible = "fixed-factor-clock" },
+       { }
+};
+
+/**
+ * ti_clk_add_aliases - setup clock aliases
+ *
+ * Sets up any missing clock aliases. No return value.
+ */
+void __init ti_clk_add_aliases(void)
+{
+       struct device_node *np;
+       struct clk *clk;
+
+       for_each_matching_node(np, simple_clk_match_table) {
+               struct of_phandle_args clkspec;
+
+               clkspec.np = np;
+               clk = of_clk_get_from_provider(&clkspec);
+
+               ti_clk_add_alias(NULL, clk, np->name);
+       }
+}
+
 /**
  * ti_clk_setup_features - setup clock features flags
  * @features: features definition to use
@@ -453,3 +491,66 @@ void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks)
                clk_prepare_enable(init_clk);
        }
 }
+
+/**
+ * ti_clk_add_alias - add a clock alias for a TI clock
+ * @dev: device alias for this clock
+ * @clk: clock handle to create alias for
+ * @con: connection ID for this clock
+ *
+ * Creates a clock alias for a TI clock. Allocates the clock lookup entry
+ * and assigns the data to it. Returns 0 if successful, negative error
+ * value otherwise.
+ */
+int ti_clk_add_alias(struct device *dev, struct clk *clk, const char *con)
+{
+       struct clk_lookup *cl;
+
+       if (!clk)
+               return 0;
+
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+
+       cl = kzalloc(sizeof(*cl), GFP_KERNEL);
+       if (!cl)
+               return -ENOMEM;
+
+       if (dev)
+               cl->dev_id = dev_name(dev);
+       cl->con_id = con;
+       cl->clk = clk;
+
+       clkdev_add(cl);
+
+       return 0;
+}
+
+/**
+ * ti_clk_register - register a TI clock to the common clock framework
+ * @dev: device for this clock
+ * @hw: hardware clock handle
+ * @con: connection ID for this clock
+ *
+ * Registers a TI clock to the common clock framework, and adds a clock
+ * alias for it. Returns a handle to the registered clock if successful,
+ * ERR_PTR value in failure.
+ */
+struct clk *ti_clk_register(struct device *dev, struct clk_hw *hw,
+                           const char *con)
+{
+       struct clk *clk;
+       int ret;
+
+       clk = clk_register(dev, hw);
+       if (IS_ERR(clk))
+               return clk;
+
+       ret = ti_clk_add_alias(dev, clk, con);
+       if (ret) {
+               clk_unregister(clk);
+               return ERR_PTR(ret);
+       }
+
+       return clk;
+}
index c6ae563801d716636da5b96b178ca40e45ec12fb..91751dd26b16429b6365f2f3ac7cfd2d44e23b40 100644 (file)
@@ -55,7 +55,8 @@
  * elapsed.  XXX Deprecated - should be moved into drivers for the
  * individual IP block that the IDLEST register exists in.
  */
-static int _wait_idlest_generic(struct clk_hw_omap *clk, void __iomem *reg,
+static int _wait_idlest_generic(struct clk_hw_omap *clk,
+                               struct clk_omap_reg *reg,
                                u32 mask, u8 idlest, const char *name)
 {
        int i = 0, ena = 0;
@@ -91,7 +92,7 @@ static int _wait_idlest_generic(struct clk_hw_omap *clk, void __iomem *reg,
  */
 static void _omap2_module_wait_ready(struct clk_hw_omap *clk)
 {
-       void __iomem *companion_reg, *idlest_reg;
+       struct clk_omap_reg companion_reg, idlest_reg;
        u8 other_bit, idlest_bit, idlest_val, idlest_reg_id;
        s16 prcm_mod;
        int r;
@@ -99,17 +100,17 @@ static void _omap2_module_wait_ready(struct clk_hw_omap *clk)
        /* Not all modules have multiple clocks that their IDLEST depends on */
        if (clk->ops->find_companion) {
                clk->ops->find_companion(clk, &companion_reg, &other_bit);
-               if (!(ti_clk_ll_ops->clk_readl(companion_reg) &
+               if (!(ti_clk_ll_ops->clk_readl(&companion_reg) &
                      (1 << other_bit)))
                        return;
        }
 
        clk->ops->find_idlest(clk, &idlest_reg, &idlest_bit, &idlest_val);
-       r = ti_clk_ll_ops->cm_split_idlest_reg(idlest_reg, &prcm_mod,
+       r = ti_clk_ll_ops->cm_split_idlest_reg(&idlest_reg, &prcm_mod,
                                               &idlest_reg_id);
        if (r) {
                /* IDLEST register not in the CM module */
-               _wait_idlest_generic(clk, idlest_reg, (1 << idlest_bit),
+               _wait_idlest_generic(clk, &idlest_reg, (1 << idlest_bit),
                                     idlest_val, clk_hw_get_name(&clk->hw));
        } else {
                ti_clk_ll_ops->cm_wait_module_ready(0, prcm_mod, idlest_reg_id,
@@ -139,17 +140,17 @@ static void _omap2_module_wait_ready(struct clk_hw_omap *clk)
  * avoid this issue, and remove the casts.  No return value.
  */
 void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk,
-                                  void __iomem **other_reg, u8 *other_bit)
+                                  struct clk_omap_reg *other_reg,
+                                  u8 *other_bit)
 {
-       u32 r;
+       memcpy(other_reg, &clk->enable_reg, sizeof(*other_reg));
 
        /*
         * Convert CM_ICLKEN* <-> CM_FCLKEN*.  This conversion assumes
         * it's just a matter of XORing the bits.
         */
-       r = ((__force u32)clk->enable_reg ^ (CM_FCLKEN ^ CM_ICLKEN));
+       other_reg->offset ^= (CM_FCLKEN ^ CM_ICLKEN);
 
-       *other_reg = (__force void __iomem *)r;
        *other_bit = clk->enable_bit;
 }
 
@@ -168,13 +169,14 @@ void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk,
  * CM_IDLEST2).  This is not true for all modules.  No return value.
  */
 void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk,
-                               void __iomem **idlest_reg, u8 *idlest_bit,
+                               struct clk_omap_reg *idlest_reg, u8 *idlest_bit,
                                u8 *idlest_val)
 {
-       u32 r;
+       memcpy(idlest_reg, &clk->enable_reg, sizeof(*idlest_reg));
+
+       idlest_reg->offset &= ~0xf0;
+       idlest_reg->offset |= 0x20;
 
-       r = (((__force u32)clk->enable_reg & ~0xf0) | 0x20);
-       *idlest_reg = (__force void __iomem *)r;
        *idlest_bit = clk->enable_bit;
 
        /*
@@ -222,31 +224,19 @@ int omap2_dflt_clk_enable(struct clk_hw *hw)
                }
        }
 
-       if (IS_ERR(clk->enable_reg)) {
-               pr_err("%s: %s missing enable_reg\n", __func__,
-                      clk_hw_get_name(hw));
-               ret = -EINVAL;
-               goto err;
-       }
-
        /* FIXME should not have INVERT_ENABLE bit here */
-       v = ti_clk_ll_ops->clk_readl(clk->enable_reg);
+       v = ti_clk_ll_ops->clk_readl(&clk->enable_reg);
        if (clk->flags & INVERT_ENABLE)
                v &= ~(1 << clk->enable_bit);
        else
                v |= (1 << clk->enable_bit);
-       ti_clk_ll_ops->clk_writel(v, clk->enable_reg);
-       v = ti_clk_ll_ops->clk_readl(clk->enable_reg); /* OCP barrier */
+       ti_clk_ll_ops->clk_writel(v, &clk->enable_reg);
+       v = ti_clk_ll_ops->clk_readl(&clk->enable_reg); /* OCP barrier */
 
        if (clk->ops && clk->ops->find_idlest)
                _omap2_module_wait_ready(clk);
 
        return 0;
-
-err:
-       if (clkdm_control && clk->clkdm)
-               ti_clk_ll_ops->clkdm_clk_disable(clk->clkdm, hw->clk);
-       return ret;
 }
 
 /**
@@ -264,22 +254,13 @@ void omap2_dflt_clk_disable(struct clk_hw *hw)
        u32 v;
 
        clk = to_clk_hw_omap(hw);
-       if (IS_ERR(clk->enable_reg)) {
-               /*
-                * 'independent' here refers to a clock which is not
-                * controlled by its parent.
-                */
-               pr_err("%s: independent clock %s has no enable_reg\n",
-                      __func__, clk_hw_get_name(hw));
-               return;
-       }
 
-       v = ti_clk_ll_ops->clk_readl(clk->enable_reg);
+       v = ti_clk_ll_ops->clk_readl(&clk->enable_reg);
        if (clk->flags & INVERT_ENABLE)
                v |= (1 << clk->enable_bit);
        else
                v &= ~(1 << clk->enable_bit);
-       ti_clk_ll_ops->clk_writel(v, clk->enable_reg);
+       ti_clk_ll_ops->clk_writel(v, &clk->enable_reg);
        /* No OCP barrier needed here since it is a disable operation */
 
        if (!(ti_clk_get_features()->flags & TI_CLK_DISABLE_CLKDM_CONTROL) &&
@@ -300,7 +281,7 @@ int omap2_dflt_clk_is_enabled(struct clk_hw *hw)
        struct clk_hw_omap *clk = to_clk_hw_omap(hw);
        u32 v;
 
-       v = ti_clk_ll_ops->clk_readl(clk->enable_reg);
+       v = ti_clk_ll_ops->clk_readl(&clk->enable_reg);
 
        if (clk->flags & INVERT_ENABLE)
                v ^= BIT(clk->enable_bit);
index b919fdfe82560ed96cab55995e1f83e968d08edb..ce98da2c10beedc0014cbc908fd62b82d1aa3154 100644 (file)
@@ -213,7 +213,7 @@ u8 omap2_init_dpll_parent(struct clk_hw *hw)
        if (!dd)
                return -EINVAL;
 
-       v = ti_clk_ll_ops->clk_readl(dd->control_reg);
+       v = ti_clk_ll_ops->clk_readl(&dd->control_reg);
        v &= dd->enable_mask;
        v >>= __ffs(dd->enable_mask);
 
@@ -249,14 +249,14 @@ unsigned long omap2_get_dpll_rate(struct clk_hw_omap *clk)
                return 0;
 
        /* Return bypass rate if DPLL is bypassed */
-       v = ti_clk_ll_ops->clk_readl(dd->control_reg);
+       v = ti_clk_ll_ops->clk_readl(&dd->control_reg);
        v &= dd->enable_mask;
        v >>= __ffs(dd->enable_mask);
 
        if (_omap2_dpll_is_in_bypass(v))
                return clk_hw_get_rate(dd->clk_bypass);
 
-       v = ti_clk_ll_ops->clk_readl(dd->mult_div1_reg);
+       v = ti_clk_ll_ops->clk_readl(&dd->mult_div1_reg);
        dpll_mult = v & dd->mult_mask;
        dpll_mult >>= __ffs(dd->mult_mask);
        dpll_div = v & dd->div1_mask;
index 38c36908cf88ec85a916741dc351567a2601977e..60b583d7db3325e4d1ea4c4ff69542338f1bed2d 100644 (file)
 void omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk)
 {
        u32 v;
-       void __iomem *r;
+       struct clk_omap_reg r;
 
-       r = (__force void __iomem *)
-               ((__force u32)clk->enable_reg ^ (CM_AUTOIDLE ^ CM_ICLKEN));
+       memcpy(&r, &clk->enable_reg, sizeof(r));
+       r.offset ^= (CM_AUTOIDLE ^ CM_ICLKEN);
 
-       v = ti_clk_ll_ops->clk_readl(r);
+       v = ti_clk_ll_ops->clk_readl(&r);
        v |= (1 << clk->enable_bit);
-       ti_clk_ll_ops->clk_writel(v, r);
+       ti_clk_ll_ops->clk_writel(v, &r);
 }
 
 /* XXX */
 void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk)
 {
        u32 v;
-       void __iomem *r;
+       struct clk_omap_reg r;
 
-       r = (__force void __iomem *)
-               ((__force u32)clk->enable_reg ^ (CM_AUTOIDLE ^ CM_ICLKEN));
+       memcpy(&r, &clk->enable_reg, sizeof(r));
 
-       v = ti_clk_ll_ops->clk_readl(r);
+       r.offset ^= (CM_AUTOIDLE ^ CM_ICLKEN);
+
+       v = ti_clk_ll_ops->clk_readl(&r);
        v &= ~(1 << clk->enable_bit);
-       ti_clk_ll_ops->clk_writel(v, r);
+       ti_clk_ll_ops->clk_writel(v, &r);
 }
 
 /**
@@ -68,14 +69,12 @@ void omap2_clkt_iclk_deny_idle(struct clk_hw_omap *clk)
  * modules.  No return value.
  */
 static void omap2430_clk_i2chs_find_idlest(struct clk_hw_omap *clk,
-                                          void __iomem **idlest_reg,
+                                          struct clk_omap_reg *idlest_reg,
                                           u8 *idlest_bit,
                                           u8 *idlest_val)
 {
-       u32 r;
-
-       r = ((__force u32)clk->enable_reg ^ (OMAP24XX_CM_FCLKEN2 ^ CM_IDLEST));
-       *idlest_reg = (__force void __iomem *)r;
+       memcpy(idlest_reg, &clk->enable_reg, sizeof(*idlest_reg));
+       idlest_reg->offset ^= (OMAP24XX_CM_FCLKEN2 ^ CM_IDLEST);
        *idlest_bit = clk->enable_bit;
        *idlest_val = OMAP24XX_CM_IDLEST_VAL;
 }
index 13c37f48d9d69d6f4b950671cc735b1ed49fefba..3f7b26540be86d01ad5d7d2a93884a445290ff84 100644 (file)
 #ifndef __DRIVERS_CLK_TI_CLOCK__
 #define __DRIVERS_CLK_TI_CLOCK__
 
+struct clk_omap_divider {
+       struct clk_hw           hw;
+       struct clk_omap_reg     reg;
+       u8                      shift;
+       u8                      width;
+       u8                      flags;
+       const struct clk_div_table      *table;
+};
+
+#define to_clk_omap_divider(_hw) container_of(_hw, struct clk_omap_divider, hw)
+
+struct clk_omap_mux {
+       struct clk_hw           hw;
+       struct clk_omap_reg     reg;
+       u32                     *table;
+       u32                     mask;
+       u8                      shift;
+       u8                      flags;
+};
+
+#define to_clk_omap_mux(_hw) container_of(_hw, struct clk_omap_mux, hw)
+
 enum {
        TI_CLK_FIXED,
        TI_CLK_MUX,
@@ -86,7 +108,7 @@ struct ti_clk_mux {
        int num_parents;
        u16 reg;
        u8 module;
-       const char **parents;
+       const char * const *parents;
        u16 flags;
 };
 
@@ -189,16 +211,25 @@ struct clk *ti_clk_register_mux(struct ti_clk *setup);
 struct clk *ti_clk_register_divider(struct ti_clk *setup);
 struct clk *ti_clk_register_composite(struct ti_clk *setup);
 struct clk *ti_clk_register_dpll(struct ti_clk *setup);
+struct clk *ti_clk_register(struct device *dev, struct clk_hw *hw,
+                           const char *con);
+int ti_clk_add_alias(struct device *dev, struct clk *clk, const char *con);
+void ti_clk_add_aliases(void);
 
 struct clk_hw *ti_clk_build_component_div(struct ti_clk_divider *setup);
 struct clk_hw *ti_clk_build_component_gate(struct ti_clk_gate *setup);
 struct clk_hw *ti_clk_build_component_mux(struct ti_clk_mux *setup);
 
+int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div,
+                             u8 flags, u8 *width,
+                             const struct clk_div_table **table);
+
 void ti_clk_patch_legacy_clks(struct ti_clk **patch);
 struct clk *ti_clk_register_clk(struct ti_clk *setup);
 int ti_clk_register_legacy_clks(struct ti_clk_alias *clks);
 
-void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index);
+int ti_clk_get_reg_addr(struct device_node *node, int index,
+                       struct clk_omap_reg *reg);
 void ti_dt_clocks_register(struct ti_dt_clk *oclks);
 int ti_clk_retry_init(struct device_node *node, struct clk_hw *hw,
                      ti_of_clk_init_cb_t func);
@@ -223,7 +254,9 @@ extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_wait;
 
 extern const struct clk_ops ti_clk_divider_ops;
 extern const struct clk_ops ti_clk_mux_ops;
+extern const struct clk_ops omap_gate_clk_ops;
 
+void omap2_init_clk_clkdm(struct clk_hw *hw);
 int omap2_clkops_enable_clkdm(struct clk_hw *hw);
 void omap2_clkops_disable_clkdm(struct clk_hw *hw);
 
@@ -231,10 +264,10 @@ int omap2_dflt_clk_enable(struct clk_hw *hw);
 void omap2_dflt_clk_disable(struct clk_hw *hw);
 int omap2_dflt_clk_is_enabled(struct clk_hw *hw);
 void omap2_clk_dflt_find_companion(struct clk_hw_omap *clk,
-                                  void __iomem **other_reg,
+                                  struct clk_omap_reg *other_reg,
                                   u8 *other_bit);
 void omap2_clk_dflt_find_idlest(struct clk_hw_omap *clk,
-                               void __iomem **idlest_reg,
+                               struct clk_omap_reg *idlest_reg,
                                u8 *idlest_bit, u8 *idlest_val);
 
 void omap2_clkt_iclk_allow_idle(struct clk_hw_omap *clk);
index 6cf9dd189a924e9d74472a260f7e816585b0d43b..fbedc6a9fed005569b98b7424abb3e969736849e 100644 (file)
@@ -52,10 +52,6 @@ int omap2_clkops_enable_clkdm(struct clk_hw *hw)
                return -EINVAL;
        }
 
-       if (unlikely(clk->enable_reg))
-               pr_err("%s: %s: should use dflt_clk_enable ?!\n", __func__,
-                      clk_hw_get_name(hw));
-
        if (ti_clk_get_features()->flags & TI_CLK_DISABLE_CLKDM_CONTROL) {
                pr_err("%s: %s: clkfw-based clockdomain control disabled ?!\n",
                       __func__, clk_hw_get_name(hw));
@@ -90,10 +86,6 @@ void omap2_clkops_disable_clkdm(struct clk_hw *hw)
                return;
        }
 
-       if (unlikely(clk->enable_reg))
-               pr_err("%s: %s: should use dflt_clk_disable ?!\n", __func__,
-                      clk_hw_get_name(hw));
-
        if (ti_clk_get_features()->flags & TI_CLK_DISABLE_CLKDM_CONTROL) {
                pr_err("%s: %s: clkfw-based clockdomain control disabled ?!\n",
                       __func__, clk_hw_get_name(hw));
@@ -103,6 +95,36 @@ void omap2_clkops_disable_clkdm(struct clk_hw *hw)
        ti_clk_ll_ops->clkdm_clk_disable(clk->clkdm, hw->clk);
 }
 
+/**
+ * omap2_init_clk_clkdm - look up a clockdomain name, store pointer in clk
+ * @clk: OMAP clock struct ptr to use
+ *
+ * Convert a clockdomain name stored in a struct clk 'clk' into a
+ * clockdomain pointer, and save it into the struct clk.  Intended to be
+ * called during clk_register().  No return value.
+ */
+void omap2_init_clk_clkdm(struct clk_hw *hw)
+{
+       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+       struct clockdomain *clkdm;
+       const char *clk_name;
+
+       if (!clk->clkdm_name)
+               return;
+
+       clk_name = __clk_get_name(hw->clk);
+
+       clkdm = ti_clk_ll_ops->clkdm_lookup(clk->clkdm_name);
+       if (clkdm) {
+               pr_debug("clock: associated clk %s to clkdm %s\n",
+                        clk_name, clk->clkdm_name);
+               clk->clkdm = clkdm;
+       } else {
+               pr_debug("clock: could not associate clk %s to clkdm %s\n",
+                        clk_name, clk->clkdm_name);
+       }
+}
+
 static void __init of_ti_clockdomain_setup(struct device_node *node)
 {
        struct clk *clk;
index 1cf70f452e1e660b594a5a92b99db21008abc28d..beea89463ca2cfd996693a27926d9ea324c40eb3 100644 (file)
@@ -124,8 +124,9 @@ struct clk *ti_clk_register_composite(struct ti_clk *setup)
        struct clk_hw *mux;
        struct clk_hw *div;
        int num_parents = 1;
-       const char **parent_names = NULL;
+       const char * const *parent_names = NULL;
        struct clk *clk;
+       int ret;
 
        comp = setup->data;
 
@@ -150,6 +151,12 @@ struct clk *ti_clk_register_composite(struct ti_clk *setup)
                                     &ti_composite_divider_ops, gate,
                                     &ti_composite_gate_ops, 0);
 
+       ret = ti_clk_add_alias(NULL, clk, setup->name);
+       if (ret) {
+               clk_unregister(clk);
+               return ERR_PTR(ret);
+       }
+
        return clk;
 }
 #endif
@@ -163,6 +170,7 @@ static void __init _register_composite(struct clk_hw *hw,
        int num_parents = 0;
        const char **parent_names = NULL;
        int i;
+       int ret;
 
        /* Check for presence of each component clock */
        for (i = 0; i < CLK_COMPONENT_TYPE_MAX; i++) {
@@ -217,8 +225,14 @@ static void __init _register_composite(struct clk_hw *hw,
                                     _get_hw(cclk, CLK_COMPONENT_TYPE_GATE),
                                     &ti_composite_gate_ops, 0);
 
-       if (!IS_ERR(clk))
+       if (!IS_ERR(clk)) {
+               ret = ti_clk_add_alias(NULL, clk, node->name);
+               if (ret) {
+                       clk_unregister(clk);
+                       goto cleanup;
+               }
                of_clk_add_provider(node, of_clk_src_simple_get, clk);
+       }
 
 cleanup:
        /* Free component clock list entries */
index 6bb87784a0d6ef82c411bf7ba566412a4059dd20..88f04a4cb890be4f68025d04d4bfaec4597dfda7 100644 (file)
@@ -39,7 +39,7 @@ static unsigned int _get_table_maxdiv(const struct clk_div_table *table)
        return maxdiv;
 }
 
-static unsigned int _get_maxdiv(struct clk_divider *divider)
+static unsigned int _get_maxdiv(struct clk_omap_divider *divider)
 {
        if (divider->flags & CLK_DIVIDER_ONE_BASED)
                return div_mask(divider);
@@ -61,7 +61,7 @@ static unsigned int _get_table_div(const struct clk_div_table *table,
        return 0;
 }
 
-static unsigned int _get_div(struct clk_divider *divider, unsigned int val)
+static unsigned int _get_div(struct clk_omap_divider *divider, unsigned int val)
 {
        if (divider->flags & CLK_DIVIDER_ONE_BASED)
                return val;
@@ -83,7 +83,7 @@ static unsigned int _get_table_val(const struct clk_div_table *table,
        return 0;
 }
 
-static unsigned int _get_val(struct clk_divider *divider, u8 div)
+static unsigned int _get_val(struct clk_omap_divider *divider, u8 div)
 {
        if (divider->flags & CLK_DIVIDER_ONE_BASED)
                return div;
@@ -97,10 +97,10 @@ static unsigned int _get_val(struct clk_divider *divider, u8 div)
 static unsigned long ti_clk_divider_recalc_rate(struct clk_hw *hw,
                                                unsigned long parent_rate)
 {
-       struct clk_divider *divider = to_clk_divider(hw);
+       struct clk_omap_divider *divider = to_clk_omap_divider(hw);
        unsigned int div, val;
 
-       val = ti_clk_ll_ops->clk_readl(divider->reg) >> divider->shift;
+       val = ti_clk_ll_ops->clk_readl(&divider->reg) >> divider->shift;
        val &= div_mask(divider);
 
        div = _get_div(divider, val);
@@ -131,7 +131,7 @@ static bool _is_valid_table_div(const struct clk_div_table *table,
        return false;
 }
 
-static bool _is_valid_div(struct clk_divider *divider, unsigned int div)
+static bool _is_valid_div(struct clk_omap_divider *divider, unsigned int div)
 {
        if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
                return is_power_of_2(div);
@@ -172,7 +172,7 @@ static int _div_round(const struct clk_div_table *table,
 static int ti_clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
                                  unsigned long *best_parent_rate)
 {
-       struct clk_divider *divider = to_clk_divider(hw);
+       struct clk_omap_divider *divider = to_clk_omap_divider(hw);
        int i, bestdiv = 0;
        unsigned long parent_rate, best = 0, now, maxdiv;
        unsigned long parent_rate_saved = *best_parent_rate;
@@ -239,14 +239,14 @@ static long ti_clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
 static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
                                   unsigned long parent_rate)
 {
-       struct clk_divider *divider;
+       struct clk_omap_divider *divider;
        unsigned int div, value;
        u32 val;
 
        if (!hw || !rate)
                return -EINVAL;
 
-       divider = to_clk_divider(hw);
+       divider = to_clk_omap_divider(hw);
 
        div = DIV_ROUND_UP(parent_rate, rate);
        value = _get_val(divider, div);
@@ -257,11 +257,11 @@ static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
        if (divider->flags & CLK_DIVIDER_HIWORD_MASK) {
                val = div_mask(divider) << (divider->shift + 16);
        } else {
-               val = ti_clk_ll_ops->clk_readl(divider->reg);
+               val = ti_clk_ll_ops->clk_readl(&divider->reg);
                val &= ~(div_mask(divider) << divider->shift);
        }
        val |= value << divider->shift;
-       ti_clk_ll_ops->clk_writel(val, divider->reg);
+       ti_clk_ll_ops->clk_writel(val, &divider->reg);
 
        return 0;
 }
@@ -274,11 +274,12 @@ const struct clk_ops ti_clk_divider_ops = {
 
 static struct clk *_register_divider(struct device *dev, const char *name,
                                     const char *parent_name,
-                                    unsigned long flags, void __iomem *reg,
+                                    unsigned long flags,
+                                    struct clk_omap_reg *reg,
                                     u8 shift, u8 width, u8 clk_divider_flags,
                                     const struct clk_div_table *table)
 {
-       struct clk_divider *div;
+       struct clk_omap_divider *div;
        struct clk *clk;
        struct clk_init_data init;
 
@@ -303,7 +304,7 @@ static struct clk *_register_divider(struct device *dev, const char *name,
        init.num_parents = (parent_name ? 1 : 0);
 
        /* struct clk_divider assignments */
-       div->reg = reg;
+       memcpy(&div->reg, reg, sizeof(*reg));
        div->shift = shift;
        div->width = width;
        div->flags = clk_divider_flags;
@@ -311,7 +312,7 @@ static struct clk *_register_divider(struct device *dev, const char *name,
        div->table = table;
 
        /* register the clock */
-       clk = clk_register(dev, &div->hw);
+       clk = ti_clk_register(dev, &div->hw, name);
 
        if (IS_ERR(clk))
                kfree(div);
@@ -319,20 +320,17 @@ static struct clk *_register_divider(struct device *dev, const char *name,
        return clk;
 }
 
-static struct clk_div_table *
-_get_div_table_from_setup(struct ti_clk_divider *setup, u8 *width)
+int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div,
+                             u8 flags, u8 *width,
+                             const struct clk_div_table **table)
 {
        int valid_div = 0;
-       struct clk_div_table *table;
-       int i;
-       int div;
        u32 val;
-       u8 flags;
-
-       if (!setup->num_dividers) {
-               /* Clk divider table not provided, determine min/max divs */
-               flags = setup->flags;
+       int div;
+       int i;
+       struct clk_div_table *tmp;
 
+       if (!div_table) {
                if (flags & CLKF_INDEX_STARTS_AT_ONE)
                        val = 1;
                else
@@ -340,7 +338,7 @@ _get_div_table_from_setup(struct ti_clk_divider *setup, u8 *width)
 
                div = 1;
 
-               while (div < setup->max_div) {
+               while (div < max_div) {
                        if (flags & CLKF_INDEX_POWER_OF_TWO)
                                div <<= 1;
                        else
@@ -349,37 +347,59 @@ _get_div_table_from_setup(struct ti_clk_divider *setup, u8 *width)
                }
 
                *width = fls(val);
+               *table = NULL;
 
-               return NULL;
+               return 0;
        }
 
-       for (i = 0; i < setup->num_dividers; i++)
-               if (setup->dividers[i])
+       i = 0;
+
+       while (!num_dividers || i < num_dividers) {
+               if (div_table[i] == -1)
+                       break;
+               if (div_table[i])
                        valid_div++;
+               i++;
+       }
 
-       table = kzalloc(sizeof(*table) * (valid_div + 1), GFP_KERNEL);
-       if (!table)
-               return ERR_PTR(-ENOMEM);
+       num_dividers = i;
+
+       tmp = kzalloc(sizeof(*tmp) * (valid_div + 1), GFP_KERNEL);
+       if (!tmp)
+               return -ENOMEM;
 
        valid_div = 0;
        *width = 0;
 
-       for (i = 0; i < setup->num_dividers; i++)
-               if (setup->dividers[i]) {
-                       table[valid_div].div = setup->dividers[i];
-                       table[valid_div].val = i;
+       for (i = 0; i < num_dividers; i++)
+               if (div_table[i] > 0) {
+                       tmp[valid_div].div = div_table[i];
+                       tmp[valid_div].val = i;
                        valid_div++;
                        *width = i;
                }
 
        *width = fls(*width);
+       *table = tmp;
+
+       return 0;
+}
+
+static const struct clk_div_table *
+_get_div_table_from_setup(struct ti_clk_divider *setup, u8 *width)
+{
+       const struct clk_div_table *table = NULL;
+
+       ti_clk_parse_divider_data(setup->dividers, setup->num_dividers,
+                                 setup->max_div, setup->flags, width,
+                                 &table);
 
        return table;
 }
 
 struct clk_hw *ti_clk_build_component_div(struct ti_clk_divider *setup)
 {
-       struct clk_divider *div;
+       struct clk_omap_divider *div;
        struct clk_omap_reg *reg;
 
        if (!setup)
@@ -408,22 +428,17 @@ struct clk_hw *ti_clk_build_component_div(struct ti_clk_divider *setup)
 
 struct clk *ti_clk_register_divider(struct ti_clk *setup)
 {
-       struct ti_clk_divider *div;
-       struct clk_omap_reg *reg_setup;
-       u32 reg;
+       struct ti_clk_divider *div = setup->data;
+       struct clk_omap_reg reg = {
+               .index = div->module,
+               .offset = div->reg,
+       };
        u8 width;
        u32 flags = 0;
        u8 div_flags = 0;
-       struct clk_div_table *table;
+       const struct clk_div_table *table;
        struct clk *clk;
 
-       div = setup->data;
-
-       reg_setup = (struct clk_omap_reg *)&reg;
-
-       reg_setup->index = div->module;
-       reg_setup->offset = div->reg;
-
        if (div->flags & CLKF_INDEX_STARTS_AT_ONE)
                div_flags |= CLK_DIVIDER_ONE_BASED;
 
@@ -438,7 +453,7 @@ struct clk *ti_clk_register_divider(struct ti_clk *setup)
                return (struct clk *)table;
 
        clk = _register_divider(NULL, setup->name, div->parent,
-                               flags, (void __iomem *)reg, div->bit_shift,
+                               flags, &reg, div->bit_shift,
                                width, div_flags, table);
 
        if (IS_ERR(clk))
@@ -542,14 +557,15 @@ static int _get_divider_width(struct device_node *node,
 }
 
 static int __init ti_clk_divider_populate(struct device_node *node,
-       void __iomem **reg, const struct clk_div_table **table,
+       struct clk_omap_reg *reg, const struct clk_div_table **table,
        u32 *flags, u8 *div_flags, u8 *width, u8 *shift)
 {
        u32 val;
+       int ret;
 
-       *reg = ti_clk_get_reg_addr(node, 0);
-       if (IS_ERR(*reg))
-               return PTR_ERR(*reg);
+       ret = ti_clk_get_reg_addr(node, 0, reg);
+       if (ret)
+               return ret;
 
        if (!of_property_read_u32(node, "ti,bit-shift", &val))
                *shift = val;
@@ -588,7 +604,7 @@ static void __init of_ti_divider_clk_setup(struct device_node *node)
 {
        struct clk *clk;
        const char *parent_name;
-       void __iomem *reg;
+       struct clk_omap_reg reg;
        u8 clk_divider_flags = 0;
        u8 width = 0;
        u8 shift = 0;
@@ -601,7 +617,7 @@ static void __init of_ti_divider_clk_setup(struct device_node *node)
                                    &clk_divider_flags, &width, &shift))
                goto cleanup;
 
-       clk = _register_divider(NULL, node->name, parent_name, flags, reg,
+       clk = _register_divider(NULL, node->name, parent_name, flags, &reg,
                                shift, width, clk_divider_flags, table);
 
        if (!IS_ERR(clk)) {
@@ -617,7 +633,7 @@ CLK_OF_DECLARE(divider_clk, "ti,divider-clock", of_ti_divider_clk_setup);
 
 static void __init of_ti_composite_divider_clk_setup(struct device_node *node)
 {
-       struct clk_divider *div;
+       struct clk_omap_divider *div;
        u32 val;
 
        div = kzalloc(sizeof(*div), GFP_KERNEL);
index 4b9a419d8e14133d04bb405b84d79da9b6bc5be5..d4e4444bc5ca3687aa07fa1c6c19b8ad77f955d7 100644 (file)
@@ -185,7 +185,7 @@ static void __init _register_dpll(struct clk_hw *hw,
        dd->clk_bypass = __clk_get_hw(clk);
 
        /* register the clock */
-       clk = clk_register(NULL, &clk_hw->hw);
+       clk = ti_clk_register(NULL, &clk_hw->hw, node->name);
 
        if (!IS_ERR(clk)) {
                omap2_init_clk_hw_omap_clocks(&clk_hw->hw);
@@ -203,17 +203,10 @@ cleanup:
 }
 
 #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_ATAGS)
-static void __iomem *_get_reg(u8 module, u16 offset)
+void _get_reg(u8 module, u16 offset, struct clk_omap_reg *reg)
 {
-       u32 reg;
-       struct clk_omap_reg *reg_setup;
-
-       reg_setup = (struct clk_omap_reg *)&reg;
-
-       reg_setup->index = module;
-       reg_setup->offset = offset;
-
-       return (void __iomem *)reg;
+       reg->index = module;
+       reg->offset = offset;
 }
 
 struct clk *ti_clk_register_dpll(struct ti_clk *setup)
@@ -248,7 +241,6 @@ struct clk *ti_clk_register_dpll(struct ti_clk *setup)
        clk_hw->dpll_data = dd;
        clk_hw->ops = &clkhwops_omap3_dpll;
        clk_hw->hw.init = &init;
-       clk_hw->flags = MEMMAP_ADDRESSING;
 
        init.name = setup->name;
        init.ops = ops;
@@ -256,10 +248,10 @@ struct clk *ti_clk_register_dpll(struct ti_clk *setup)
        init.num_parents = dpll->num_parents;
        init.parent_names = dpll->parents;
 
-       dd->control_reg = _get_reg(dpll->module, dpll->control_reg);
-       dd->idlest_reg = _get_reg(dpll->module, dpll->idlest_reg);
-       dd->mult_div1_reg = _get_reg(dpll->module, dpll->mult_div1_reg);
-       dd->autoidle_reg = _get_reg(dpll->module, dpll->autoidle_reg);
+       _get_reg(dpll->module, dpll->control_reg, &dd->control_reg);
+       _get_reg(dpll->module, dpll->idlest_reg, &dd->idlest_reg);
+       _get_reg(dpll->module, dpll->mult_div1_reg, &dd->mult_div1_reg);
+       _get_reg(dpll->module, dpll->autoidle_reg, &dd->autoidle_reg);
 
        dd->modes = dpll->modes;
        dd->div1_mask = dpll->div1_mask;
@@ -288,7 +280,7 @@ struct clk *ti_clk_register_dpll(struct ti_clk *setup)
        if (dpll->flags & CLKF_J_TYPE)
                dd->flags |= DPLL_J_TYPE;
 
-       clk = clk_register(NULL, &clk_hw->hw);
+       clk = ti_clk_register(NULL, &clk_hw->hw, setup->name);
 
        if (!IS_ERR(clk))
                return clk;
@@ -339,8 +331,24 @@ static void _register_dpll_x2(struct device_node *node,
        init.parent_names = &parent_name;
        init.num_parents = 1;
 
+#if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \
+       defined(CONFIG_SOC_DRA7XX)
+       if (hw_ops == &clkhwops_omap4_dpllmx) {
+               int ret;
+
+               /* Check if register defined, if not, drop hw-ops */
+               ret = of_property_count_elems_of_size(node, "reg", 1);
+               if (ret <= 0) {
+                       clk_hw->ops = NULL;
+               } else if (ti_clk_get_reg_addr(node, 0, &clk_hw->clksel_reg)) {
+                       kfree(clk_hw);
+                       return;
+               }
+       }
+#endif
+
        /* register the clock */
-       clk = clk_register(NULL, &clk_hw->hw);
+       clk = ti_clk_register(NULL, &clk_hw->hw, name);
 
        if (IS_ERR(clk)) {
                kfree(clk_hw);
@@ -380,7 +388,6 @@ static void __init of_ti_dpll_setup(struct device_node *node,
        clk_hw->dpll_data = dd;
        clk_hw->ops = &clkhwops_omap3_dpll;
        clk_hw->hw.init = init;
-       clk_hw->flags = MEMMAP_ADDRESSING;
 
        init->name = node->name;
        init->ops = ops;
@@ -399,7 +406,8 @@ static void __init of_ti_dpll_setup(struct device_node *node,
 
        init->parent_names = parent_names;
 
-       dd->control_reg = ti_clk_get_reg_addr(node, 0);
+       if (ti_clk_get_reg_addr(node, 0, &dd->control_reg))
+               goto cleanup;
 
        /*
         * Special case for OMAP2 DPLL, register order is different due to
@@ -407,25 +415,22 @@ static void __init of_ti_dpll_setup(struct device_node *node,
         * missing idlest_mask.
         */
        if (!dd->idlest_mask) {
-               dd->mult_div1_reg = ti_clk_get_reg_addr(node, 1);
+               if (ti_clk_get_reg_addr(node, 1, &dd->mult_div1_reg))
+                       goto cleanup;
 #ifdef CONFIG_ARCH_OMAP2
                clk_hw->ops = &clkhwops_omap2xxx_dpll;
                omap2xxx_clkt_dpllcore_init(&clk_hw->hw);
 #endif
        } else {
-               dd->idlest_reg = ti_clk_get_reg_addr(node, 1);
-               if (IS_ERR(dd->idlest_reg))
+               if (ti_clk_get_reg_addr(node, 1, &dd->idlest_reg))
                        goto cleanup;
 
-               dd->mult_div1_reg = ti_clk_get_reg_addr(node, 2);
+               if (ti_clk_get_reg_addr(node, 2, &dd->mult_div1_reg))
+                       goto cleanup;
        }
 
-       if (IS_ERR(dd->control_reg) || IS_ERR(dd->mult_div1_reg))
-               goto cleanup;
-
        if (dd->autoidle_mask) {
-               dd->autoidle_reg = ti_clk_get_reg_addr(node, 3);
-               if (IS_ERR(dd->autoidle_reg))
+               if (ti_clk_get_reg_addr(node, 3, &dd->autoidle_reg))
                        goto cleanup;
        }
 
index 4cdd28a25584424f5d5bc9730abf5e7a1d8b6bb7..4534de2ef455d6e734c592062d4bcf92d4a404d7 100644 (file)
@@ -54,10 +54,10 @@ static void _omap3_dpll_write_clken(struct clk_hw_omap *clk, u8 clken_bits)
 
        dd = clk->dpll_data;
 
-       v = ti_clk_ll_ops->clk_readl(dd->control_reg);
+       v = ti_clk_ll_ops->clk_readl(&dd->control_reg);
        v &= ~dd->enable_mask;
        v |= clken_bits << __ffs(dd->enable_mask);
-       ti_clk_ll_ops->clk_writel(v, dd->control_reg);
+       ti_clk_ll_ops->clk_writel(v, &dd->control_reg);
 }
 
 /* _omap3_wait_dpll_status: wait for a DPLL to enter a specific state */
@@ -73,7 +73,7 @@ static int _omap3_wait_dpll_status(struct clk_hw_omap *clk, u8 state)
 
        state <<= __ffs(dd->idlest_mask);
 
-       while (((ti_clk_ll_ops->clk_readl(dd->idlest_reg) & dd->idlest_mask)
+       while (((ti_clk_ll_ops->clk_readl(&dd->idlest_reg) & dd->idlest_mask)
                != state) && i < MAX_DPLL_WAIT_TRIES) {
                i++;
                udelay(1);
@@ -151,7 +151,7 @@ static int _omap3_noncore_dpll_lock(struct clk_hw_omap *clk)
        state <<= __ffs(dd->idlest_mask);
 
        /* Check if already locked */
-       if ((ti_clk_ll_ops->clk_readl(dd->idlest_reg) & dd->idlest_mask) ==
+       if ((ti_clk_ll_ops->clk_readl(&dd->idlest_reg) & dd->idlest_mask) ==
            state)
                goto done;
 
@@ -317,14 +317,14 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)
         * only since freqsel field is no longer present on other devices.
         */
        if (ti_clk_get_features()->flags & TI_CLK_DPLL_HAS_FREQSEL) {
-               v = ti_clk_ll_ops->clk_readl(dd->control_reg);
+               v = ti_clk_ll_ops->clk_readl(&dd->control_reg);
                v &= ~dd->freqsel_mask;
                v |= freqsel << __ffs(dd->freqsel_mask);
-               ti_clk_ll_ops->clk_writel(v, dd->control_reg);
+               ti_clk_ll_ops->clk_writel(v, &dd->control_reg);
        }
 
        /* Set DPLL multiplier, divider */
-       v = ti_clk_ll_ops->clk_readl(dd->mult_div1_reg);
+       v = ti_clk_ll_ops->clk_readl(&dd->mult_div1_reg);
 
        /* Handle Duty Cycle Correction */
        if (dd->dcc_mask) {
@@ -370,11 +370,11 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)
                }
        }
 
-       ti_clk_ll_ops->clk_writel(v, dd->mult_div1_reg);
+       ti_clk_ll_ops->clk_writel(v, &dd->mult_div1_reg);
 
        /* Set 4X multiplier and low-power mode */
        if (dd->m4xen_mask || dd->lpmode_mask) {
-               v = ti_clk_ll_ops->clk_readl(dd->control_reg);
+               v = ti_clk_ll_ops->clk_readl(&dd->control_reg);
 
                if (dd->m4xen_mask) {
                        if (dd->last_rounded_m4xen)
@@ -390,7 +390,7 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)
                                v &= ~dd->lpmode_mask;
                }
 
-               ti_clk_ll_ops->clk_writel(v, dd->control_reg);
+               ti_clk_ll_ops->clk_writel(v, &dd->control_reg);
        }
 
        /* We let the clock framework set the other output dividers later */
@@ -652,10 +652,10 @@ static u32 omap3_dpll_autoidle_read(struct clk_hw_omap *clk)
 
        dd = clk->dpll_data;
 
-       if (!dd->autoidle_reg)
+       if (!dd->autoidle_mask)
                return -EINVAL;
 
-       v = ti_clk_ll_ops->clk_readl(dd->autoidle_reg);
+       v = ti_clk_ll_ops->clk_readl(&dd->autoidle_reg);
        v &= dd->autoidle_mask;
        v >>= __ffs(dd->autoidle_mask);
 
@@ -681,7 +681,7 @@ static void omap3_dpll_allow_idle(struct clk_hw_omap *clk)
 
        dd = clk->dpll_data;
 
-       if (!dd->autoidle_reg)
+       if (!dd->autoidle_mask)
                return;
 
        /*
@@ -689,10 +689,10 @@ static void omap3_dpll_allow_idle(struct clk_hw_omap *clk)
         * by writing 0x5 instead of 0x1.  Add some mechanism to
         * optionally enter this mode.
         */
-       v = ti_clk_ll_ops->clk_readl(dd->autoidle_reg);
+       v = ti_clk_ll_ops->clk_readl(&dd->autoidle_reg);
        v &= ~dd->autoidle_mask;
        v |= DPLL_AUTOIDLE_LOW_POWER_STOP << __ffs(dd->autoidle_mask);
-       ti_clk_ll_ops->clk_writel(v, dd->autoidle_reg);
+       ti_clk_ll_ops->clk_writel(v, &dd->autoidle_reg);
 }
 
 /**
@@ -711,13 +711,13 @@ static void omap3_dpll_deny_idle(struct clk_hw_omap *clk)
 
        dd = clk->dpll_data;
 
-       if (!dd->autoidle_reg)
+       if (!dd->autoidle_mask)
                return;
 
-       v = ti_clk_ll_ops->clk_readl(dd->autoidle_reg);
+       v = ti_clk_ll_ops->clk_readl(&dd->autoidle_reg);
        v &= ~dd->autoidle_mask;
        v |= DPLL_AUTOIDLE_DISABLE << __ffs(dd->autoidle_mask);
-       ti_clk_ll_ops->clk_writel(v, dd->autoidle_reg);
+       ti_clk_ll_ops->clk_writel(v, &dd->autoidle_reg);
 }
 
 /* Clock control for DPLL outputs */
@@ -773,7 +773,7 @@ unsigned long omap3_clkoutx2_recalc(struct clk_hw *hw,
 
        WARN_ON(!dd->enable_mask);
 
-       v = ti_clk_ll_ops->clk_readl(dd->control_reg) & dd->enable_mask;
+       v = ti_clk_ll_ops->clk_readl(&dd->control_reg) & dd->enable_mask;
        v >>= __ffs(dd->enable_mask);
        if ((v != OMAP3XXX_EN_DPLL_LOCKED) || (dd->flags & DPLL_J_TYPE))
                rate = parent_rate;
index 82c05b55a7be83808b20e5da172900ba63c0a26e..d7a3f7ec8d77012317c1d386a8fe98afda7be600 100644 (file)
@@ -42,17 +42,17 @@ static void omap4_dpllmx_allow_gatectrl(struct clk_hw_omap *clk)
        u32 v;
        u32 mask;
 
-       if (!clk || !clk->clksel_reg)
+       if (!clk)
                return;
 
        mask = clk->flags & CLOCK_CLKOUTX2 ?
                        OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK :
                        OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK;
 
-       v = ti_clk_ll_ops->clk_readl(clk->clksel_reg);
+       v = ti_clk_ll_ops->clk_readl(&clk->clksel_reg);
        /* Clear the bit to allow gatectrl */
        v &= ~mask;
-       ti_clk_ll_ops->clk_writel(v, clk->clksel_reg);
+       ti_clk_ll_ops->clk_writel(v, &clk->clksel_reg);
 }
 
 static void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk)
@@ -60,17 +60,17 @@ static void omap4_dpllmx_deny_gatectrl(struct clk_hw_omap *clk)
        u32 v;
        u32 mask;
 
-       if (!clk || !clk->clksel_reg)
+       if (!clk)
                return;
 
        mask = clk->flags & CLOCK_CLKOUTX2 ?
                        OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK :
                        OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK;
 
-       v = ti_clk_ll_ops->clk_readl(clk->clksel_reg);
+       v = ti_clk_ll_ops->clk_readl(&clk->clksel_reg);
        /* Set the bit to deny gatectrl */
        v |= mask;
-       ti_clk_ll_ops->clk_writel(v, clk->clksel_reg);
+       ti_clk_ll_ops->clk_writel(v, &clk->clksel_reg);
 }
 
 const struct clk_hw_omap_ops clkhwops_omap4_dpllmx = {
@@ -128,7 +128,7 @@ unsigned long omap4_dpll_regm4xen_recalc(struct clk_hw *hw,
        rate = omap2_get_dpll_rate(clk);
 
        /* regm4xen adds a multiplier of 4 to DPLL calculations */
-       v = ti_clk_ll_ops->clk_readl(dd->control_reg);
+       v = ti_clk_ll_ops->clk_readl(&dd->control_reg);
        if (v & OMAP4430_DPLL_REGM4XEN_MASK)
                rate *= OMAP4430_REGM4XEN_MULT;
 
index 3cd40676890969b1853256d32061b8bfd29093a7..0174a51a4ba6c11dfa4cec9b2a57bc44e156ef67 100644 (file)
@@ -62,6 +62,7 @@ static void __init of_ti_fixed_factor_clk_setup(struct device_node *node)
        if (!IS_ERR(clk)) {
                of_clk_add_provider(node, of_clk_src_simple_get, clk);
                of_ti_clk_autoidle_setup(node);
+               ti_clk_add_alias(NULL, clk, clk_name);
        }
 }
 CLK_OF_DECLARE(ti_fixed_factor_clk, "ti,fixed-factor-clock",
index bc05f276f32b90039a0eed1879d7a1201930ea97..7151ec3a1b07f1620938ae2a4de0f8d5483e8aad 100644 (file)
@@ -35,7 +35,7 @@ static const struct clk_ops omap_gate_clkdm_clk_ops = {
        .disable        = &omap2_clkops_disable_clkdm,
 };
 
-static const struct clk_ops omap_gate_clk_ops = {
+const struct clk_ops omap_gate_clk_ops = {
        .init           = &omap2_init_clk_clkdm,
        .enable         = &omap2_dflt_clk_enable,
        .disable        = &omap2_dflt_clk_disable,
@@ -62,7 +62,7 @@ static const struct clk_ops omap_gate_clk_hsdiv_restore_ops = {
  */
 static int omap36xx_gate_clk_enable_with_hsdiv_restore(struct clk_hw *hw)
 {
-       struct clk_divider *parent;
+       struct clk_omap_divider *parent;
        struct clk_hw *parent_hw;
        u32 dummy_v, orig_v;
        int ret;
@@ -72,19 +72,19 @@ static int omap36xx_gate_clk_enable_with_hsdiv_restore(struct clk_hw *hw)
 
        /* Parent is the x2 node, get parent of parent for the m2 div */
        parent_hw = clk_hw_get_parent(clk_hw_get_parent(hw));
-       parent = to_clk_divider(parent_hw);
+       parent = to_clk_omap_divider(parent_hw);
 
        /* Restore the dividers */
        if (!ret) {
-               orig_v = ti_clk_ll_ops->clk_readl(parent->reg);
+               orig_v = ti_clk_ll_ops->clk_readl(&parent->reg);
                dummy_v = orig_v;
 
                /* Write any other value different from the Read value */
                dummy_v ^= (1 << parent->shift);
-               ti_clk_ll_ops->clk_writel(dummy_v, parent->reg);
+               ti_clk_ll_ops->clk_writel(dummy_v, &parent->reg);
 
                /* Write the original divider */
-               ti_clk_ll_ops->clk_writel(orig_v, parent->reg);
+               ti_clk_ll_ops->clk_writel(orig_v, &parent->reg);
        }
 
        return ret;
@@ -92,7 +92,7 @@ static int omap36xx_gate_clk_enable_with_hsdiv_restore(struct clk_hw *hw)
 
 static struct clk *_register_gate(struct device *dev, const char *name,
                                  const char *parent_name, unsigned long flags,
-                                 void __iomem *reg, u8 bit_idx,
+                                 struct clk_omap_reg *reg, u8 bit_idx,
                                  u8 clk_gate_flags, const struct clk_ops *ops,
                                  const struct clk_hw_omap_ops *hw_ops)
 {
@@ -109,18 +109,18 @@ static struct clk *_register_gate(struct device *dev, const char *name,
        init.name = name;
        init.ops = ops;
 
-       clk_hw->enable_reg = reg;
+       memcpy(&clk_hw->enable_reg, reg, sizeof(*reg));
        clk_hw->enable_bit = bit_idx;
        clk_hw->ops = hw_ops;
 
-       clk_hw->flags = MEMMAP_ADDRESSING | clk_gate_flags;
+       clk_hw->flags = clk_gate_flags;
 
        init.parent_names = &parent_name;
        init.num_parents = 1;
 
        init.flags = flags;
 
-       clk = clk_register(NULL, &clk_hw->hw);
+       clk = ti_clk_register(NULL, &clk_hw->hw, name);
 
        if (IS_ERR(clk))
                kfree(clk_hw);
@@ -133,8 +133,7 @@ struct clk *ti_clk_register_gate(struct ti_clk *setup)
 {
        const struct clk_ops *ops = &omap_gate_clk_ops;
        const struct clk_hw_omap_ops *hw_ops = NULL;
-       u32 reg;
-       struct clk_omap_reg *reg_setup;
+       struct clk_omap_reg reg;
        u32 flags = 0;
        u8 clk_gate_flags = 0;
        struct ti_clk_gate *gate;
@@ -144,8 +143,6 @@ struct clk *ti_clk_register_gate(struct ti_clk *setup)
        if (gate->flags & CLKF_INTERFACE)
                return ti_clk_register_interface(setup);
 
-       reg_setup = (struct clk_omap_reg *)&reg;
-
        if (gate->flags & CLKF_SET_RATE_PARENT)
                flags |= CLK_SET_RATE_PARENT;
 
@@ -169,11 +166,12 @@ struct clk *ti_clk_register_gate(struct ti_clk *setup)
        if (gate->flags & CLKF_AM35XX)
                hw_ops = &clkhwops_am35xx_ipss_module_wait;
 
-       reg_setup->index = gate->module;
-       reg_setup->offset = gate->reg;
+       reg.index = gate->module;
+       reg.offset = gate->reg;
+       reg.ptr = NULL;
 
        return _register_gate(NULL, setup->name, gate->parent, flags,
-                             (void __iomem *)reg, gate->bit_shift,
+                             &reg, gate->bit_shift,
                              clk_gate_flags, ops, hw_ops);
 }
 
@@ -203,7 +201,6 @@ struct clk_hw *ti_clk_build_component_gate(struct ti_clk_gate *setup)
                ops = &clkhwops_iclk_wait;
 
        gate->ops = ops;
-       gate->flags = MEMMAP_ADDRESSING;
 
        return &gate->hw;
 }
@@ -215,15 +212,14 @@ static void __init _of_ti_gate_clk_setup(struct device_node *node,
 {
        struct clk *clk;
        const char *parent_name;
-       void __iomem *reg = NULL;
+       struct clk_omap_reg reg;
        u8 enable_bit = 0;
        u32 val;
        u32 flags = 0;
        u8 clk_gate_flags = 0;
 
        if (ops != &omap_gate_clkdm_clk_ops) {
-               reg = ti_clk_get_reg_addr(node, 0);
-               if (IS_ERR(reg))
+               if (ti_clk_get_reg_addr(node, 0, &reg))
                        return;
 
                if (!of_property_read_u32(node, "ti,bit-shift", &val))
@@ -243,7 +239,7 @@ static void __init _of_ti_gate_clk_setup(struct device_node *node,
        if (of_property_read_bool(node, "ti,set-bit-to-disable"))
                clk_gate_flags |= INVERT_ENABLE;
 
-       clk = _register_gate(NULL, node->name, parent_name, flags, reg,
+       clk = _register_gate(NULL, node->name, parent_name, flags, &reg,
                             enable_bit, clk_gate_flags, ops, hw_ops);
 
        if (!IS_ERR(clk))
@@ -261,15 +257,13 @@ _of_ti_composite_gate_clk_setup(struct device_node *node,
        if (!gate)
                return;
 
-       gate->enable_reg = ti_clk_get_reg_addr(node, 0);
-       if (IS_ERR(gate->enable_reg))
+       if (ti_clk_get_reg_addr(node, 0, &gate->enable_reg))
                goto cleanup;
 
        of_property_read_u32(node, "ti,bit-shift", &val);
 
        gate->enable_bit = val;
        gate->ops = hw_ops;
-       gate->flags = MEMMAP_ADDRESSING;
 
        if (!ti_clk_add_component(node, &gate->hw, CLK_COMPONENT_TYPE_GATE))
                return;
index e505e6f8228da6ada5ccb4beffd7aa0de78f1f1d..62cf50c1e1e32ce416df61c20ebde0c5fe855880 100644 (file)
@@ -34,7 +34,7 @@ static const struct clk_ops ti_interface_clk_ops = {
 
 static struct clk *_register_interface(struct device *dev, const char *name,
                                       const char *parent_name,
-                                      void __iomem *reg, u8 bit_idx,
+                                      struct clk_omap_reg *reg, u8 bit_idx,
                                       const struct clk_hw_omap_ops *ops)
 {
        struct clk_init_data init = { NULL };
@@ -47,8 +47,7 @@ static struct clk *_register_interface(struct device *dev, const char *name,
 
        clk_hw->hw.init = &init;
        clk_hw->ops = ops;
-       clk_hw->flags = MEMMAP_ADDRESSING;
-       clk_hw->enable_reg = reg;
+       memcpy(&clk_hw->enable_reg, reg, sizeof(*reg));
        clk_hw->enable_bit = bit_idx;
 
        init.name = name;
@@ -58,7 +57,7 @@ static struct clk *_register_interface(struct device *dev, const char *name,
        init.num_parents = 1;
        init.parent_names = &parent_name;
 
-       clk = clk_register(NULL, &clk_hw->hw);
+       clk = ti_clk_register(NULL, &clk_hw->hw, name);
 
        if (IS_ERR(clk))
                kfree(clk_hw);
@@ -72,14 +71,13 @@ static struct clk *_register_interface(struct device *dev, const char *name,
 struct clk *ti_clk_register_interface(struct ti_clk *setup)
 {
        const struct clk_hw_omap_ops *ops = &clkhwops_iclk_wait;
-       u32 reg;
-       struct clk_omap_reg *reg_setup;
+       struct clk_omap_reg reg;
        struct ti_clk_gate *gate;
 
        gate = setup->data;
-       reg_setup = (struct clk_omap_reg *)&reg;
-       reg_setup->index = gate->module;
-       reg_setup->offset = gate->reg;
+       reg.index = gate->module;
+       reg.offset = gate->reg;
+       reg.ptr = NULL;
 
        if (gate->flags & CLKF_NO_WAIT)
                ops = &clkhwops_iclk;
@@ -97,7 +95,7 @@ struct clk *ti_clk_register_interface(struct ti_clk *setup)
                ops = &clkhwops_am35xx_ipss_wait;
 
        return _register_interface(NULL, setup->name, gate->parent,
-                                  (void __iomem *)reg, gate->bit_shift, ops);
+                                  &reg, gate->bit_shift, ops);
 }
 #endif
 
@@ -106,12 +104,11 @@ static void __init _of_ti_interface_clk_setup(struct device_node *node,
 {
        struct clk *clk;
        const char *parent_name;
-       void __iomem *reg;
+       struct clk_omap_reg reg;
        u8 enable_bit = 0;
        u32 val;
 
-       reg = ti_clk_get_reg_addr(node, 0);
-       if (IS_ERR(reg))
+       if (ti_clk_get_reg_addr(node, 0, &reg))
                return;
 
        if (!of_property_read_u32(node, "ti,bit-shift", &val))
@@ -123,7 +120,7 @@ static void __init _of_ti_interface_clk_setup(struct device_node *node,
                return;
        }
 
-       clk = _register_interface(NULL, node->name, parent_name, reg,
+       clk = _register_interface(NULL, node->name, parent_name, &reg,
                                  enable_bit, ops);
 
        if (!IS_ERR(clk))
index 44777ab6fdeb3b6f8d0fcd5386790c506f39d300..18c267b38461dc96ff1d5dd26f518136a342ffb3 100644 (file)
@@ -28,7 +28,7 @@
 
 static u8 ti_clk_mux_get_parent(struct clk_hw *hw)
 {
-       struct clk_mux *mux = to_clk_mux(hw);
+       struct clk_omap_mux *mux = to_clk_omap_mux(hw);
        int num_parents = clk_hw_get_num_parents(hw);
        u32 val;
 
@@ -39,7 +39,7 @@ static u8 ti_clk_mux_get_parent(struct clk_hw *hw)
         * OTOH, pmd_trace_clk_mux_ck uses a separate bit for each clock, so
         * val = 0x4 really means "bit 2, index starts at bit 0"
         */
-       val = ti_clk_ll_ops->clk_readl(mux->reg) >> mux->shift;
+       val = ti_clk_ll_ops->clk_readl(&mux->reg) >> mux->shift;
        val &= mux->mask;
 
        if (mux->table) {
@@ -65,7 +65,7 @@ static u8 ti_clk_mux_get_parent(struct clk_hw *hw)
 
 static int ti_clk_mux_set_parent(struct clk_hw *hw, u8 index)
 {
-       struct clk_mux *mux = to_clk_mux(hw);
+       struct clk_omap_mux *mux = to_clk_omap_mux(hw);
        u32 val;
 
        if (mux->table) {
@@ -81,11 +81,11 @@ static int ti_clk_mux_set_parent(struct clk_hw *hw, u8 index)
        if (mux->flags & CLK_MUX_HIWORD_MASK) {
                val = mux->mask << (mux->shift + 16);
        } else {
-               val = ti_clk_ll_ops->clk_readl(mux->reg);
+               val = ti_clk_ll_ops->clk_readl(&mux->reg);
                val &= ~(mux->mask << mux->shift);
        }
        val |= index << mux->shift;
-       ti_clk_ll_ops->clk_writel(val, mux->reg);
+       ti_clk_ll_ops->clk_writel(val, &mux->reg);
 
        return 0;
 }
@@ -97,12 +97,12 @@ const struct clk_ops ti_clk_mux_ops = {
 };
 
 static struct clk *_register_mux(struct device *dev, const char *name,
-                                const char **parent_names, u8 num_parents,
-                                unsigned long flags, void __iomem *reg,
-                                u8 shift, u32 mask, u8 clk_mux_flags,
-                                u32 *table)
+                                const char * const *parent_names,
+                                u8 num_parents, unsigned long flags,
+                                struct clk_omap_reg *reg, u8 shift, u32 mask,
+                                u8 clk_mux_flags, u32 *table)
 {
-       struct clk_mux *mux;
+       struct clk_omap_mux *mux;
        struct clk *clk;
        struct clk_init_data init;
 
@@ -120,14 +120,14 @@ static struct clk *_register_mux(struct device *dev, const char *name,
        init.num_parents = num_parents;
 
        /* struct clk_mux assignments */
-       mux->reg = reg;
+       memcpy(&mux->reg, reg, sizeof(*reg));
        mux->shift = shift;
        mux->mask = mask;
        mux->flags = clk_mux_flags;
        mux->table = table;
        mux->hw.init = &init;
 
-       clk = clk_register(dev, &mux->hw);
+       clk = ti_clk_register(dev, &mux->hw, name);
 
        if (IS_ERR(clk))
                kfree(mux);
@@ -140,12 +140,9 @@ struct clk *ti_clk_register_mux(struct ti_clk *setup)
        struct ti_clk_mux *mux;
        u32 flags;
        u8 mux_flags = 0;
-       struct clk_omap_reg *reg_setup;
-       u32 reg;
+       struct clk_omap_reg reg;
        u32 mask;
 
-       reg_setup = (struct clk_omap_reg *)&reg;
-
        mux = setup->data;
        flags = CLK_SET_RATE_NO_REPARENT;
 
@@ -154,8 +151,9 @@ struct clk *ti_clk_register_mux(struct ti_clk *setup)
                mask--;
 
        mask = (1 << fls(mask)) - 1;
-       reg_setup->index = mux->module;
-       reg_setup->offset = mux->reg;
+       reg.index = mux->module;
+       reg.offset = mux->reg;
+       reg.ptr = NULL;
 
        if (mux->flags & CLKF_INDEX_STARTS_AT_ONE)
                mux_flags |= CLK_MUX_INDEX_ONE;
@@ -164,7 +162,7 @@ struct clk *ti_clk_register_mux(struct ti_clk *setup)
                flags |= CLK_SET_RATE_PARENT;
 
        return _register_mux(NULL, setup->name, mux->parents, mux->num_parents,
-                            flags, (void __iomem *)reg, mux->bit_shift, mask,
+                            flags, &reg, mux->bit_shift, mask,
                             mux_flags, NULL);
 }
 
@@ -177,7 +175,7 @@ struct clk *ti_clk_register_mux(struct ti_clk *setup)
 static void of_mux_clk_setup(struct device_node *node)
 {
        struct clk *clk;
-       void __iomem *reg;
+       struct clk_omap_reg reg;
        unsigned int num_parents;
        const char **parent_names;
        u8 clk_mux_flags = 0;
@@ -196,9 +194,7 @@ static void of_mux_clk_setup(struct device_node *node)
 
        of_clk_parent_fill(node, parent_names, num_parents);
 
-       reg = ti_clk_get_reg_addr(node, 0);
-
-       if (IS_ERR(reg))
+       if (ti_clk_get_reg_addr(node, 0, &reg))
                goto cleanup;
 
        of_property_read_u32(node, "ti,bit-shift", &shift);
@@ -217,7 +213,7 @@ static void of_mux_clk_setup(struct device_node *node)
        mask = (1 << fls(mask)) - 1;
 
        clk = _register_mux(NULL, node->name, parent_names, num_parents,
-                           flags, reg, shift, mask, clk_mux_flags, NULL);
+                           flags, &reg, shift, mask, clk_mux_flags, NULL);
 
        if (!IS_ERR(clk))
                of_clk_add_provider(node, of_clk_src_simple_get, clk);
@@ -229,8 +225,7 @@ CLK_OF_DECLARE(mux_clk, "ti,mux-clock", of_mux_clk_setup);
 
 struct clk_hw *ti_clk_build_component_mux(struct ti_clk_mux *setup)
 {
-       struct clk_mux *mux;
-       struct clk_omap_reg *reg;
+       struct clk_omap_mux *mux;
        int num_parents;
 
        if (!setup)
@@ -240,12 +235,10 @@ struct clk_hw *ti_clk_build_component_mux(struct ti_clk_mux *setup)
        if (!mux)
                return ERR_PTR(-ENOMEM);
 
-       reg = (struct clk_omap_reg *)&mux->reg;
-
        mux->shift = setup->bit_shift;
 
-       reg->index = setup->module;
-       reg->offset = setup->reg;
+       mux->reg.index = setup->module;
+       mux->reg.offset = setup->reg;
 
        if (setup->flags & CLKF_INDEX_STARTS_AT_ONE)
                mux->flags |= CLK_MUX_INDEX_ONE;
@@ -260,7 +253,7 @@ struct clk_hw *ti_clk_build_component_mux(struct ti_clk_mux *setup)
 
 static void __init of_ti_composite_mux_clk_setup(struct device_node *node)
 {
-       struct clk_mux *mux;
+       struct clk_omap_mux *mux;
        unsigned int num_parents;
        u32 val;
 
@@ -268,9 +261,7 @@ static void __init of_ti_composite_mux_clk_setup(struct device_node *node)
        if (!mux)
                return;
 
-       mux->reg = ti_clk_get_reg_addr(node, 0);
-
-       if (IS_ERR(mux->reg))
+       if (ti_clk_get_reg_addr(node, 0, &mux->reg))
                goto cleanup;
 
        if (!of_property_read_u32(node, "ti,bit-shift", &val))
index a6da2aa09f831ff512a11b0253d45588f3bee614..8aa875f252391907d0a00ad66840975f4f02a021 100644 (file)
@@ -1,3 +1,6 @@
+config ICST
+       bool
+
 config COMMON_CLK_VERSATILE
        bool "Clock driver for ARM Reference designs"
        depends on ARCH_INTEGRATOR || ARCH_REALVIEW || \
index 8ff03744fe9890e1ec9069c31ac37dc2d4a329f4..794130402c8dca01985d9142fdeea2be2a1f013a 100644 (file)
@@ -1,5 +1,5 @@
 # Makefile for Versatile-specific clocks
-obj-$(CONFIG_ICST)             += clk-icst.o clk-versatile.o
+obj-$(CONFIG_ICST)             += icst.o clk-icst.o clk-versatile.o
 obj-$(CONFIG_INTEGRATOR_IMPD1) += clk-impd1.o
 obj-$(CONFIG_ARCH_REALVIEW)    += clk-realview.o
 obj-$(CONFIG_CLK_SP810)                += clk-sp810.o
index 4faa94440779bcfadd11f75dc78ae7f416c2df39..09fbe66f1f11cb41507f104a7458ed38d83e75cd 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/regmap.h>
 #include <linux/mfd/syscon.h>
 
+#include "icst.h"
 #include "clk-icst.h"
 
 /* Magic unlocking token used on all Versatile boards */
index 04e6f0aef5889ad260aaced2b427f7487240dd37..5add02ebec5d0af809b1a6c5c2eae4481217d634 100644 (file)
@@ -1,5 +1,3 @@
-#include <asm/hardware/icst.h>
-
 /**
  * struct clk_icst_desc - descriptor for the ICST VCO
  * @params: ICST parameters
index 74c3216dbb0045273cc40793caa88bc78e9d4c8e..401558bfc409c01c59582df9c6d3e8ed6fc24aff 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/io.h>
 #include <linux/platform_data/clk-integrator.h>
 
+#include "icst.h"
 #include "clk-icst.h"
 
 #define IMPD1_OSC1     0x00
index c56efc70ac16c40502aeccb0e5bf459d40659682..6fdfee3232f445f5eda439e78e58a2f3967fe8c0 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/io.h>
 #include <linux/clk-provider.h>
 
+#include "icst.h"
 #include "clk-icst.h"
 
 #define REALVIEW_SYS_OSC0_OFFSET             0x0C
index a89a927567e0cfae45df95b8aed7cc2218509fc3..d6960de64d4a08dbae5cdcd2bb9a27b16803b2e3 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 
+#include "icst.h"
 #include "clk-icst.h"
 
 #define INTEGRATOR_HDR_LOCK_OFFSET     0x14
similarity index 98%
rename from arch/arm/common/icst.c
rename to drivers/clk/versatile/icst.c
index d7ed252708c57fa86cff5d51887bd756b53b48e7..de2af63a3aad52e740228e8b6ef7b8346f5e7770 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <asm/div64.h>
-#include <asm/hardware/icst.h>
+#include "icst.h"
 
 /*
  * Divisors for each OD setting.
similarity index 94%
rename from arch/arm/include/asm/hardware/icst.h
rename to drivers/clk/versatile/icst.h
index 794220b087d2392ce3807b61f5103f8429f55364..7519bba03b04574b20558ff827757389ad7bf32c 100644 (file)
@@ -1,6 +1,4 @@
 /*
- *  arch/arm/include/asm/hardware/icst.h
- *
  *  Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -11,8 +9,8 @@
  *  clock generators.  See http://www.idt.com/ for more information
  *  on these devices.
  */
-#ifndef ASMARM_HARDWARE_ICST_H
-#define ASMARM_HARDWARE_ICST_H
+#ifndef ICST_H
+#define ICST_H
 
 struct icst_params {
        unsigned long   ref;
index 2b60577703ef3888f36ad7c01c4d20e8aefe93ab..f99abc1106f0cb725ff7c63e9bc84b75596a4e75 100644 (file)
@@ -54,6 +54,7 @@ struct clk_plt_data {
        struct clk_plt_fixed **parents;
        u8 nparents;
        struct clk_plt *clks[PMC_CLK_NUM];
+       struct clk_lookup *mclk_lookup;
 };
 
 /* Return an index in parent table */
@@ -337,6 +338,11 @@ static int plt_clk_probe(struct platform_device *pdev)
                        goto err_unreg_clk_plt;
                }
        }
+       data->mclk_lookup = clkdev_hw_create(&data->clks[3]->hw, "mclk", NULL);
+       if (!data->mclk_lookup) {
+               err = -ENOMEM;
+               goto err_unreg_clk_plt;
+       }
 
        plt_clk_free_parent_names_loop(parent_names, data->nparents);
 
@@ -356,6 +362,7 @@ static int plt_clk_remove(struct platform_device *pdev)
 
        data = platform_get_drvdata(pdev);
 
+       clkdev_drop(data->mclk_lookup);
        plt_clk_unregister_loop(data, PMC_CLK_NUM);
        plt_clk_unregister_parents(data);
        return 0;
index 2f7c668643fe2ca9aaa693d91eba55f579e42c67..a10962988ba8efd9441ca22c327899d0fbc05fb1 100644 (file)
 
 static DEFINE_SPINLOCK(clk_lock);
 
-static struct zx_pll_config pll_cpu_table[] = {
+static const struct zx_pll_config pll_cpu_table[] = {
        PLL_RATE(1312000000, 0x00103621, 0x04aaaaaa),
        PLL_RATE(1407000000, 0x00103a21, 0x04aaaaaa),
        PLL_RATE(1503000000, 0x00103e21, 0x04aaaaaa),
        PLL_RATE(1600000000, 0x00104221, 0x04aaaaaa),
 };
 
+static const struct zx_pll_config pll_vga_table[] = {
+       PLL_RATE(36000000,  0x00102464, 0x04000000), /* 800x600@56 */
+       PLL_RATE(40000000,  0x00102864, 0x04000000), /* 800x600@60 */
+       PLL_RATE(49500000,  0x00103164, 0x04800000), /* 800x600@75 */
+       PLL_RATE(50000000,  0x00103264, 0x04000000), /* 800x600@72 */
+       PLL_RATE(56250000,  0x00103864, 0x04400000), /* 800x600@85 */
+       PLL_RATE(65000000,  0x00104164, 0x04000000), /* 1024x768@60 */
+       PLL_RATE(74375000,  0x00104a64, 0x04600000), /* 1280x720@60 */
+       PLL_RATE(75000000,  0x00104b64, 0x04800000), /* 1024x768@70 */
+       PLL_RATE(78750000,  0x00104e64, 0x04c00000), /* 1024x768@75 */
+       PLL_RATE(85500000,  0x00105564, 0x04800000), /* 1360x768@60 */
+       PLL_RATE(106500000, 0x00106a64, 0x04800000), /* 1440x900@60 */
+       PLL_RATE(108000000, 0x00106c64, 0x04000000), /* 1280x1024@60 */
+       PLL_RATE(110000000, 0x00106e64, 0x04000000), /* 1024x768@85 */
+       PLL_RATE(135000000, 0x00105a44, 0x04000000), /* 1280x1024@75 */
+       PLL_RATE(136750000, 0x00104462, 0x04600000), /* 1440x900@75 */
+       PLL_RATE(148500000, 0x00104a62, 0x04400000), /* 1920x1080@60 */
+       PLL_RATE(157000000, 0x00104e62, 0x04800000), /* 1440x900@85 */
+       PLL_RATE(157500000, 0x00104e62, 0x04c00000), /* 1280x1024@85 */
+       PLL_RATE(162000000, 0x00105162, 0x04000000), /* 1600x1200@60 */
+       PLL_RATE(193250000, 0x00106062, 0x04a00000), /* 1920x1200@60 */
+};
+
 PNAME(osc) = {
        "osc24m",
        "osc32k",
@@ -369,6 +392,7 @@ PNAME(wdt_ares_p) = {
 
 static struct clk_zx_pll zx296718_pll_clk[] = {
        ZX296718_PLL("pll_cpu", "osc24m",       PLL_CPU_REG,    pll_cpu_table),
+       ZX296718_PLL("pll_vga", "osc24m",       PLL_VGA_REG,    pll_vga_table),
 };
 
 static struct zx_clk_fixed_factor top_ffactor_clk[] = {
@@ -409,7 +433,7 @@ static struct zx_clk_fixed_factor top_ffactor_clk[] = {
        FFACTOR(0, "clk54m",            "pll_mm1", 1, 24, 0),
        /* vga */
        FFACTOR(0, "pll_vga_1800m",     "pll_vga", 1, 1, 0),
-       FFACTOR(0, "clk_vga",           "pll_vga", 1, 2, 0),
+       FFACTOR(0, "clk_vga",           "pll_vga", 1, 1, CLK_SET_RATE_PARENT),
        /* pll ddr */
        FFACTOR(0, "clk466m",           "pll_ddr", 1, 2, 0),
 
@@ -458,8 +482,8 @@ static struct zx_clk_mux top_mux_clk[] = {
        MUX(0, "sappu_a_mux",    sappu_aclk_p,    TOP_CLK_MUX5,  4, 2),
        MUX(0, "sappu_w_mux",    sappu_wclk_p,    TOP_CLK_MUX5,  8, 3),
        MUX(0, "vou_a_mux",      vou_aclk_p,      TOP_CLK_MUX7,  0, 3),
-       MUX(0, "vou_main_w_mux", vou_main_wclk_p, TOP_CLK_MUX7,  4, 3),
-       MUX(0, "vou_aux_w_mux",  vou_aux_wclk_p,  TOP_CLK_MUX7,  8, 3),
+       MUX_F(0, "vou_main_w_mux", vou_main_wclk_p, TOP_CLK_MUX7,  4, 3, CLK_SET_RATE_PARENT, 0),
+       MUX_F(0, "vou_aux_w_mux",  vou_aux_wclk_p,  TOP_CLK_MUX7,  8, 3, CLK_SET_RATE_PARENT, 0),
        MUX(0, "vou_ppu_w_mux",  vou_ppu_wclk_p,  TOP_CLK_MUX7, 12, 3),
        MUX(0, "vga_i2c_mux",    vga_i2c_wclk_p,  TOP_CLK_MUX7, 16, 1),
        MUX(0, "viu_m0_a_mux",   viu_m0_aclk_p,   TOP_CLK_MUX6,  0, 3),
index 878d879b23ff183b838aa7944d0f8a6b338e389d..b82031766ffa11a8176a29f202d5b2d677d1d4ea 100644 (file)
@@ -52,7 +52,10 @@ static int hw_to_idx(struct clk_zx_pll *zx_pll)
 
        /* For matching the value in lookup table */
        hw_cfg0 &= ~BIT(zx_pll->lock_bit);
-       hw_cfg0 |= BIT(zx_pll->pd_bit);
+
+       /* Check availability of pd_bit */
+       if (zx_pll->pd_bit < 32)
+               hw_cfg0 |= BIT(zx_pll->pd_bit);
 
        for (i = 0; i < zx_pll->count; i++) {
                if (hw_cfg0 == config[i].cfg0 && hw_cfg1 == config[i].cfg1)
@@ -108,6 +111,10 @@ static int zx_pll_enable(struct clk_hw *hw)
        struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw);
        u32 reg;
 
+       /* If pd_bit is not available, simply return success. */
+       if (zx_pll->pd_bit > 31)
+               return 0;
+
        reg = readl_relaxed(zx_pll->reg_base);
        writel_relaxed(reg & ~BIT(zx_pll->pd_bit), zx_pll->reg_base);
 
@@ -120,6 +127,9 @@ static void zx_pll_disable(struct clk_hw *hw)
        struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw);
        u32 reg;
 
+       if (zx_pll->pd_bit > 31)
+               return;
+
        reg = readl_relaxed(zx_pll->reg_base);
        writel_relaxed(reg | BIT(zx_pll->pd_bit), zx_pll->reg_base);
 }
index 84a55a3e2bd440660d91511c69af9d7e75355320..4df0f121b56d7cf622cf6ca9103d3200ca7f6c2c 100644 (file)
@@ -66,8 +66,12 @@ struct clk_zx_pll {
                                CLK_GET_RATE_NOCACHE),                  \
 }
 
+/*
+ * The pd_bit is not available on ZX296718, so let's pass something
+ * bigger than 31, e.g. 0xff, to indicate that.
+ */
 #define ZX296718_PLL(_name, _parent, _reg, _table)                     \
-ZX_PLL(_name, _parent, _reg, _table, 0, 30)
+ZX_PLL(_name, _parent, _reg, _table, 0xff, 30)
 
 struct zx_clk_gate {
        struct clk_gate gate;
index a1fb918b80219239abe04e7d6146b8c54cebb4d0..4bed671e490e0b15d79fd432f3d85dacfd094a96 100644 (file)
@@ -1268,7 +1268,7 @@ arch_timer_mem_find_best_frame(struct arch_timer_mem *timer_mem)
                pr_err("Unable to find a suitable frame in timer @ %pa\n",
                        &timer_mem->cntctlbase);
 
-       return frame;
+       return best_frame;
 }
 
 static int __init
index 9a7e37cf56b01a601e022b8ba5c6495d895b9898..a1df588343f2dac1fb1c6acb8f579f3688ad6938 100644 (file)
@@ -22,7 +22,7 @@
 #define DRV_NAME "cs5535-clockevt"
 
 static int timer_irq;
-module_param_named(irq, timer_irq, int, 0644);
+module_param_hw_named(irq, timer_irq, int, irq, 0644);
 MODULE_PARM_DESC(irq, "Which IRQ to use for the clock source MFGPT ticks.");
 
 /*
index 6bbdac1065ff544dcf7ccc1b5b67971513718288..9ac27b22476cd10437c13a870cc383b7441b9ff0 100644 (file)
@@ -51,19 +51,12 @@ static int loongson2_cpu_freq_notifier(struct notifier_block *nb,
 static int loongson2_cpufreq_target(struct cpufreq_policy *policy,
                                     unsigned int index)
 {
-       unsigned int cpu = policy->cpu;
-       cpumask_t cpus_allowed;
        unsigned int freq;
 
-       cpus_allowed = current->cpus_allowed;
-       set_cpus_allowed_ptr(current, cpumask_of(cpu));
-
        freq =
            ((cpu_clock_freq / 1000) *
             loongson2_clockmod_table[index].driver_data) / 8;
 
-       set_cpus_allowed_ptr(current, &cpus_allowed);
-
        /* setting the cpu frequency */
        clk_set_rate(policy->clk, freq * 1000);
 
index 0b5bf135b0907491a226353f2127cc51c9c13cde..062d71434e470eeb452edcc10417aae7e4d809cc 100644 (file)
@@ -1171,7 +1171,8 @@ static struct cpufreq_driver cpufreq_amd64_driver = {
 
 static void __request_acpi_cpufreq(void)
 {
-       const char *cur_drv, *drv = "acpi-cpufreq";
+       const char drv[] = "acpi-cpufreq";
+       const char *cur_drv;
 
        cur_drv = cpufreq_get_current_driver();
        if (!cur_drv)
index 770a9ae1999a96a7fa02f747662a56b173532e5f..37b30071c220e456c72985bf50147c12f2edcc67 100644 (file)
@@ -378,7 +378,7 @@ static void __exit speedstep_exit(void)
        cpufreq_unregister_driver(&speedstep_driver);
 }
 
-module_param(smi_port, int, 0444);
+module_param_hw(smi_port, int, ioport, 0444);
 module_param(smi_cmd,  int, 0444);
 module_param(smi_sig, uint, 0444);
 
index a7db9011d5fec57fbf71849fce133a37f88d4a94..d2d0430d09d4ddcaa3626319741cdb3ef66ef3aa 100644 (file)
@@ -236,7 +236,7 @@ use_defaults:
        return 0;
 }
 
-static int sti_cpufreq_fetch_syscon_regsiters(void)
+static int sti_cpufreq_fetch_syscon_registers(void)
 {
        struct device *dev = ddata.cpu;
        struct device_node *np = dev->of_node;
@@ -275,7 +275,7 @@ static int sti_cpufreq_init(void)
                goto skip_voltage_scaling;
        }
 
-       ret = sti_cpufreq_fetch_syscon_regsiters();
+       ret = sti_cpufreq_fetch_syscon_registers();
        if (ret)
                goto skip_voltage_scaling;
 
index 548b90be76854850bc4a0aec6863ca898fe1a941..2706be7ed3340fe41ad174d75dc27a9e010e4412 100644 (file)
@@ -111,7 +111,8 @@ void cpuidle_use_deepest_state(bool enable)
 
        preempt_disable();
        dev = cpuidle_get_device();
-       dev->use_deepest_state = enable;
+       if (dev)
+               dev->use_deepest_state = enable;
        preempt_enable();
 }
 
index 21472e427f6fe723f757a83f98c42c2f3ec78d68..a111cd72797b19e8a589ef846101d4589e90e199 100644 (file)
@@ -119,8 +119,7 @@ static int virtcrypto_find_vqs(struct virtio_crypto *vi)
                names[i] = vi->data_vq[i].name;
        }
 
-       ret = vi->vdev->config->find_vqs(vi->vdev, total_vqs, vqs, callbacks,
-                                        names, NULL);
+       ret = virtio_find_vqs(vi->vdev, total_vqs, vqs, callbacks, names, NULL);
        if (ret)
                goto err_find;
 
index b7053eafd88e72104955e1c7c86770d64ca4aa7a..b79aa8f7a49714441fe5cb204f45a48fe4c6034f 100644 (file)
@@ -19,7 +19,7 @@ config DEV_DAX
 
 config DEV_DAX_PMEM
        tristate "PMEM DAX: direct access to persistent memory"
-       depends on LIBNVDIMM && NVDIMM_DAX
+       depends on LIBNVDIMM && NVDIMM_DAX && DEV_DAX
        default DEV_DAX
        help
          Support raw access to persistent memory.  Note that this
@@ -28,9 +28,4 @@ config DEV_DAX_PMEM
 
          Say Y if unsure
 
-config NR_DEV_DAX
-       int "Maximum number of Device-DAX instances"
-       default 32768
-       range 256 2147483647
-
 endif
index 465dcd7317d5f620c1b7c1fcf67597afae1fb9f0..6ed32aac8bbeec9f139d0ba622d4b5fb6d1aca4b 100644 (file)
 #include <linux/module.h>
 #include <linux/mount.h>
 #include <linux/magic.h>
+#include <linux/genhd.h>
 #include <linux/cdev.h>
 #include <linux/hash.h>
 #include <linux/slab.h>
 #include <linux/dax.h>
 #include <linux/fs.h>
 
-static int nr_dax = CONFIG_NR_DEV_DAX;
-module_param(nr_dax, int, S_IRUGO);
-MODULE_PARM_DESC(nr_dax, "max number of dax device instances");
-
 static dev_t dax_devt;
 DEFINE_STATIC_SRCU(dax_srcu);
 static struct vfsmount *dax_mnt;
@@ -47,6 +44,77 @@ void dax_read_unlock(int id)
 }
 EXPORT_SYMBOL_GPL(dax_read_unlock);
 
+#ifdef CONFIG_BLOCK
+int bdev_dax_pgoff(struct block_device *bdev, sector_t sector, size_t size,
+               pgoff_t *pgoff)
+{
+       phys_addr_t phys_off = (get_start_sect(bdev) + sector) * 512;
+
+       if (pgoff)
+               *pgoff = PHYS_PFN(phys_off);
+       if (phys_off % PAGE_SIZE || size % PAGE_SIZE)
+               return -EINVAL;
+       return 0;
+}
+EXPORT_SYMBOL(bdev_dax_pgoff);
+
+/**
+ * __bdev_dax_supported() - Check if the device supports dax for filesystem
+ * @sb: The superblock of the device
+ * @blocksize: The block size of the device
+ *
+ * This is a library function for filesystems to check if the block device
+ * can be mounted with dax option.
+ *
+ * Return: negative errno if unsupported, 0 if supported.
+ */
+int __bdev_dax_supported(struct super_block *sb, int blocksize)
+{
+       struct block_device *bdev = sb->s_bdev;
+       struct dax_device *dax_dev;
+       pgoff_t pgoff;
+       int err, id;
+       void *kaddr;
+       pfn_t pfn;
+       long len;
+
+       if (blocksize != PAGE_SIZE) {
+               pr_err("VFS (%s): error: unsupported blocksize for dax\n",
+                               sb->s_id);
+               return -EINVAL;
+       }
+
+       err = bdev_dax_pgoff(bdev, 0, PAGE_SIZE, &pgoff);
+       if (err) {
+               pr_err("VFS (%s): error: unaligned partition for dax\n",
+                               sb->s_id);
+               return err;
+       }
+
+       dax_dev = dax_get_by_host(bdev->bd_disk->disk_name);
+       if (!dax_dev) {
+               pr_err("VFS (%s): error: device does not support dax\n",
+                               sb->s_id);
+               return -EOPNOTSUPP;
+       }
+
+       id = dax_read_lock();
+       len = dax_direct_access(dax_dev, pgoff, 1, &kaddr, &pfn);
+       dax_read_unlock(id);
+
+       put_dax(dax_dev);
+
+       if (len < 1) {
+               pr_err("VFS (%s): error: dax access failed (%ld)",
+                               sb->s_id, len);
+               return len < 0 ? len : -EIO;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(__bdev_dax_supported);
+#endif
+
 /**
  * struct dax_device - anchor object for dax services
  * @inode: core vfs
@@ -261,7 +329,7 @@ struct dax_device *alloc_dax(void *private, const char *__host,
        if (__host && !host)
                return NULL;
 
-       minor = ida_simple_get(&dax_minor_ida, 0, nr_dax, GFP_KERNEL);
+       minor = ida_simple_get(&dax_minor_ida, 0, MINORMASK+1, GFP_KERNEL);
        if (minor < 0)
                goto err_minor;
 
@@ -405,8 +473,7 @@ static int __init dax_fs_init(void)
        if (rc)
                return rc;
 
-       nr_dax = max(nr_dax, 256);
-       rc = alloc_chrdev_region(&dax_devt, 0, nr_dax, "dax");
+       rc = alloc_chrdev_region(&dax_devt, 0, MINORMASK+1, "dax");
        if (rc)
                __dax_fs_exit();
        return rc;
@@ -414,7 +481,7 @@ static int __init dax_fs_init(void)
 
 static void __exit dax_fs_exit(void)
 {
-       unregister_chrdev_region(dax_devt, nr_dax);
+       unregister_chrdev_region(dax_devt, MINORMASK+1);
        ida_destroy(&dax_minor_ida);
        __dax_fs_exit();
 }
index d01d59812cf3ec8f171e09641ae2c1c787e0de06..24e8597b2c3ed3fa6857c2e1aa9cc191c2cad2e2 100644 (file)
@@ -514,12 +514,12 @@ config TIMB_DMA
          Enable support for the Timberdale FPGA DMA engine.
 
 config TI_CPPI41
-       tristate "AM33xx CPPI41 DMA support"
-       depends on ARCH_OMAP
+       tristate "CPPI 4.1 DMA support"
+       depends on (ARCH_OMAP || ARCH_DAVINCI_DA8XX)
        select DMA_ENGINE
        help
          The Communications Port Programming Interface (CPPI) 4.1 DMA engine
-         is currently used by the USB driver on AM335x platforms.
+         is currently used by the USB driver on AM335x and DA8xx platforms.
 
 config TI_DMA_CROSSBAR
        bool
@@ -608,6 +608,7 @@ config ASYNC_TX_DMA
 config DMATEST
        tristate "DMA Test client"
        depends on DMA_ENGINE
+       select DMA_ENGINE_RAID
        help
          Simple DMA test client. Say N unless you're debugging a
          DMA Device driver.
index 0b7c6ce629a69f79dc3ac95dfb73cdbcdfeb7635..6bb8813ca2753838d36b188aed1e20e0afb44d58 100644 (file)
@@ -106,6 +106,7 @@ struct pl08x_driver_data;
 
 /**
  * struct vendor_data - vendor-specific config parameters for PL08x derivatives
+ * @config_offset: offset to the configuration register
  * @channels: the number of channels available in this variant
  * @signals: the number of request signals available from the hardware
  * @dualmaster: whether this version supports dual AHB masters or not.
@@ -145,6 +146,8 @@ struct pl08x_bus_data {
 /**
  * struct pl08x_phy_chan - holder for the physical channels
  * @id: physical index to this channel
+ * @base: memory base address for this physical channel
+ * @reg_config: configuration address for this physical channel
  * @lock: a lock to use when altering an instance of this struct
  * @serving: the virtual channel currently being served by this physical
  * channel
@@ -203,7 +206,7 @@ struct pl08x_txd {
 };
 
 /**
- * struct pl08x_dma_chan_state - holds the PL08x specific virtual channel
+ * enum pl08x_dma_chan_state - holds the PL08x specific virtual channel
  * states
  * @PL08X_CHAN_IDLE: the channel is idle
  * @PL08X_CHAN_RUNNING: the channel has allocated a physical transport
@@ -226,9 +229,8 @@ enum pl08x_dma_chan_state {
  * @phychan: the physical channel utilized by this channel, if there is one
  * @name: name of channel
  * @cd: channel platform data
- * @runtime_addr: address for RX/TX according to the runtime config
+ * @cfg: slave configuration
  * @at: active transaction on this channel
- * @lock: a lock for this channel data
  * @host: a pointer to the host (internal use)
  * @state: whether the channel is idle, paused, running etc
  * @slave: whether this channel is a device (slave) or for memcpy
@@ -262,7 +264,7 @@ struct pl08x_dma_chan {
  * @lli_buses: bitmask to or in to LLI pointer selecting AHB port for LLI
  * fetches
  * @mem_buses: set to indicate memory transfers on AHB2.
- * @lock: a spinlock for this struct
+ * @lli_words: how many words are used in each LLI item for this variant
  */
 struct pl08x_driver_data {
        struct dma_device slave;
@@ -417,7 +419,7 @@ static void pl08x_start_next_txd(struct pl08x_dma_chan *plchan)
 
        /* Enable the DMA channel */
        /* Do not access config register until channel shows as disabled */
-       while (readl(pl08x->base + PL080_EN_CHAN) & (1 << phychan->id))
+       while (readl(pl08x->base + PL080_EN_CHAN) & BIT(phychan->id))
                cpu_relax();
 
        /* Do not access config register until channel shows as inactive */
@@ -484,8 +486,8 @@ static void pl08x_terminate_phy_chan(struct pl08x_driver_data *pl08x,
 
        writel(val, ch->reg_config);
 
-       writel(1 << ch->id, pl08x->base + PL080_ERR_CLEAR);
-       writel(1 << ch->id, pl08x->base + PL080_TC_CLEAR);
+       writel(BIT(ch->id), pl08x->base + PL080_ERR_CLEAR);
+       writel(BIT(ch->id), pl08x->base + PL080_TC_CLEAR);
 }
 
 static inline u32 get_bytes_in_cctl(u32 cctl)
@@ -1834,7 +1836,7 @@ static irqreturn_t pl08x_irq(int irq, void *dev)
                return IRQ_NONE;
 
        for (i = 0; i < pl08x->vd->channels; i++) {
-               if (((1 << i) & err) || ((1 << i) & tc)) {
+               if ((BIT(i) & err) || (BIT(i) & tc)) {
                        /* Locate physical channel */
                        struct pl08x_phy_chan *phychan = &pl08x->phy_chans[i];
                        struct pl08x_dma_chan *plchan = phychan->serving;
@@ -1872,7 +1874,7 @@ static irqreturn_t pl08x_irq(int irq, void *dev)
                        }
                        spin_unlock(&plchan->vc.lock);
 
-                       mask |= (1 << i);
+                       mask |= BIT(i);
                }
        }
 
index d74cee077842ec92cc5611827905790b386ae69c..f7e965f632747aa4c4a5532cd010d847917bbb67 100644 (file)
@@ -68,7 +68,6 @@
 #define QMGR_MEMCTRL_IDX_SH    16
 #define QMGR_MEMCTRL_DESC_SH   8
 
-#define QMGR_NUM_PEND  5
 #define QMGR_PEND(x)   (0x90 + (x) * 4)
 
 #define QMGR_PENDING_SLOT_Q(x) (x / 32)
@@ -131,7 +130,6 @@ struct cppi41_dd {
        u32 first_td_desc;
        struct cppi41_channel *chan_busy[ALLOC_DECS_NUM];
 
-       void __iomem *usbss_mem;
        void __iomem *ctrl_mem;
        void __iomem *sched_mem;
        void __iomem *qmgr_mem;
@@ -139,6 +137,10 @@ struct cppi41_dd {
        const struct chan_queues *queues_rx;
        const struct chan_queues *queues_tx;
        struct chan_queues td_queue;
+       u16 first_completion_queue;
+       u16 qmgr_num_pend;
+       u32 n_chans;
+       u8 platform;
 
        struct list_head pending;       /* Pending queued transfers */
        spinlock_t lock;                /* Lock for pending list */
@@ -149,8 +151,7 @@ struct cppi41_dd {
        bool is_suspended;
 };
 
-#define FIST_COMPLETION_QUEUE  93
-static struct chan_queues usb_queues_tx[] = {
+static struct chan_queues am335x_usb_queues_tx[] = {
        /* USB0 ENDP 1 */
        [ 0] = { .submit = 32, .complete =  93},
        [ 1] = { .submit = 34, .complete =  94},
@@ -186,7 +187,7 @@ static struct chan_queues usb_queues_tx[] = {
        [29] = { .submit = 90, .complete = 139},
 };
 
-static const struct chan_queues usb_queues_rx[] = {
+static const struct chan_queues am335x_usb_queues_rx[] = {
        /* USB0 ENDP 1 */
        [ 0] = { .submit =  1, .complete = 109},
        [ 1] = { .submit =  2, .complete = 110},
@@ -222,11 +223,26 @@ static const struct chan_queues usb_queues_rx[] = {
        [29] = { .submit = 30, .complete = 155},
 };
 
+static const struct chan_queues da8xx_usb_queues_tx[] = {
+       [0] = { .submit =  16, .complete = 24},
+       [1] = { .submit =  18, .complete = 24},
+       [2] = { .submit =  20, .complete = 24},
+       [3] = { .submit =  22, .complete = 24},
+};
+
+static const struct chan_queues da8xx_usb_queues_rx[] = {
+       [0] = { .submit =  1, .complete = 26},
+       [1] = { .submit =  3, .complete = 26},
+       [2] = { .submit =  5, .complete = 26},
+       [3] = { .submit =  7, .complete = 26},
+};
+
 struct cppi_glue_infos {
-       irqreturn_t (*isr)(int irq, void *data);
        const struct chan_queues *queues_rx;
        const struct chan_queues *queues_tx;
        struct chan_queues td_queue;
+       u16 first_completion_queue;
+       u16 qmgr_num_pend;
 };
 
 static struct cppi41_channel *to_cpp41_chan(struct dma_chan *c)
@@ -285,19 +301,21 @@ static u32 cppi41_pop_desc(struct cppi41_dd *cdd, unsigned queue_num)
 static irqreturn_t cppi41_irq(int irq, void *data)
 {
        struct cppi41_dd *cdd = data;
+       u16 first_completion_queue = cdd->first_completion_queue;
+       u16 qmgr_num_pend = cdd->qmgr_num_pend;
        struct cppi41_channel *c;
        int i;
 
-       for (i = QMGR_PENDING_SLOT_Q(FIST_COMPLETION_QUEUE); i < QMGR_NUM_PEND;
+       for (i = QMGR_PENDING_SLOT_Q(first_completion_queue); i < qmgr_num_pend;
                        i++) {
                u32 val;
                u32 q_num;
 
                val = cppi_readl(cdd->qmgr_mem + QMGR_PEND(i));
-               if (i == QMGR_PENDING_SLOT_Q(FIST_COMPLETION_QUEUE) && val) {
+               if (i == QMGR_PENDING_SLOT_Q(first_completion_queue) && val) {
                        u32 mask;
                        /* set corresponding bit for completetion Q 93 */
-                       mask = 1 << QMGR_PENDING_BIT_Q(FIST_COMPLETION_QUEUE);
+                       mask = 1 << QMGR_PENDING_BIT_Q(first_completion_queue);
                        /* not set all bits for queues less than Q 93 */
                        mask--;
                        /* now invert and keep only Q 93+ set */
@@ -402,11 +420,9 @@ static enum dma_status cppi41_dma_tx_status(struct dma_chan *chan,
        struct cppi41_channel *c = to_cpp41_chan(chan);
        enum dma_status ret;
 
-       /* lock */
        ret = dma_cookie_status(chan, cookie, txstate);
-       if (txstate && ret == DMA_COMPLETE)
-               txstate->residue = c->residue;
-       /* unlock */
+
+       dma_set_residue(txstate, c->residue);
 
        return ret;
 }
@@ -630,7 +646,7 @@ static int cppi41_tear_down_chan(struct cppi41_channel *c)
                if (!c->is_tx) {
                        reg |= GCR_STARV_RETRY;
                        reg |= GCR_DESC_TYPE_HOST;
-                       reg |= c->q_comp_num;
+                       reg |= cdd->td_queue.complete;
                }
                reg |= GCR_TEARDOWN;
                cppi_writel(reg, c->gcr_reg);
@@ -641,7 +657,7 @@ static int cppi41_tear_down_chan(struct cppi41_channel *c)
        if (!c->td_seen || !c->td_desc_seen) {
 
                desc_phys = cppi41_pop_desc(cdd, cdd->td_queue.complete);
-               if (!desc_phys)
+               if (!desc_phys && c->is_tx)
                        desc_phys = cppi41_pop_desc(cdd, c->q_comp_num);
 
                if (desc_phys == c->desc_phys) {
@@ -723,39 +739,24 @@ static int cppi41_stop_chan(struct dma_chan *chan)
        return 0;
 }
 
-static void cleanup_chans(struct cppi41_dd *cdd)
-{
-       while (!list_empty(&cdd->ddev.channels)) {
-               struct cppi41_channel *cchan;
-
-               cchan = list_first_entry(&cdd->ddev.channels,
-                               struct cppi41_channel, chan.device_node);
-               list_del(&cchan->chan.device_node);
-               kfree(cchan);
-       }
-}
-
 static int cppi41_add_chans(struct device *dev, struct cppi41_dd *cdd)
 {
-       struct cppi41_channel *cchan;
+       struct cppi41_channel *cchan, *chans;
        int i;
-       int ret;
-       u32 n_chans;
+       u32 n_chans = cdd->n_chans;
 
-       ret = of_property_read_u32(dev->of_node, "#dma-channels",
-                       &n_chans);
-       if (ret)
-               return ret;
        /*
         * The channels can only be used as TX or as RX. So we add twice
         * that much dma channels because USB can only do RX or TX.
         */
        n_chans *= 2;
 
+       chans = devm_kcalloc(dev, n_chans, sizeof(*chans), GFP_KERNEL);
+       if (!chans)
+               return -ENOMEM;
+
        for (i = 0; i < n_chans; i++) {
-               cchan = kzalloc(sizeof(*cchan), GFP_KERNEL);
-               if (!cchan)
-                       goto err;
+               cchan = &chans[i];
 
                cchan->cdd = cdd;
                if (i & 1) {
@@ -775,9 +776,6 @@ static int cppi41_add_chans(struct device *dev, struct cppi41_dd *cdd)
        cdd->first_td_desc = n_chans;
 
        return 0;
-err:
-       cleanup_chans(cdd);
-       return -ENOMEM;
 }
 
 static void purge_descs(struct device *dev, struct cppi41_dd *cdd)
@@ -859,7 +857,7 @@ static void init_sched(struct cppi41_dd *cdd)
 
        word = 0;
        cppi_writel(0, cdd->sched_mem + DMA_SCHED_CTRL);
-       for (ch = 0; ch < 15 * 2; ch += 2) {
+       for (ch = 0; ch < cdd->n_chans; ch += 2) {
 
                reg = SCHED_ENTRY0_CHAN(ch);
                reg |= SCHED_ENTRY1_CHAN(ch) | SCHED_ENTRY1_IS_RX;
@@ -869,7 +867,7 @@ static void init_sched(struct cppi41_dd *cdd)
                cppi_writel(reg, cdd->sched_mem + DMA_SCHED_WORD(word));
                word++;
        }
-       reg = 15 * 2 * 2 - 1;
+       reg = cdd->n_chans * 2 - 1;
        reg |= DMA_SCHED_CTRL_EN;
        cppi_writel(reg, cdd->sched_mem + DMA_SCHED_CTRL);
 }
@@ -885,7 +883,7 @@ static int init_cppi41(struct device *dev, struct cppi41_dd *cdd)
                return -ENOMEM;
 
        cppi_writel(cdd->scratch_phys, cdd->qmgr_mem + QMGR_LRAM0_BASE);
-       cppi_writel(QMGR_SCRATCH_SIZE, cdd->qmgr_mem + QMGR_LRAM_SIZE);
+       cppi_writel(TOTAL_DESCS_NUM, cdd->qmgr_mem + QMGR_LRAM_SIZE);
        cppi_writel(0, cdd->qmgr_mem + QMGR_LRAM1_BASE);
 
        ret = init_descs(dev, cdd);
@@ -894,6 +892,7 @@ static int init_cppi41(struct device *dev, struct cppi41_dd *cdd)
 
        cppi_writel(cdd->td_queue.submit, cdd->ctrl_mem + DMA_TDFDQ);
        init_sched(cdd);
+
        return 0;
 err_td:
        deinit_cppi41(dev, cdd);
@@ -933,8 +932,9 @@ static bool cpp41_dma_filter_fn(struct dma_chan *chan, void *param)
        else
                queues = cdd->queues_rx;
 
-       BUILD_BUG_ON(ARRAY_SIZE(usb_queues_rx) != ARRAY_SIZE(usb_queues_tx));
-       if (WARN_ON(cchan->port_num > ARRAY_SIZE(usb_queues_rx)))
+       BUILD_BUG_ON(ARRAY_SIZE(am335x_usb_queues_rx) !=
+                    ARRAY_SIZE(am335x_usb_queues_tx));
+       if (WARN_ON(cchan->port_num > ARRAY_SIZE(am335x_usb_queues_rx)))
                return false;
 
        cchan->q_num = queues[cchan->port_num].submit;
@@ -962,15 +962,25 @@ static struct dma_chan *cppi41_dma_xlate(struct of_phandle_args *dma_spec,
                        &dma_spec->args[0]);
 }
 
-static const struct cppi_glue_infos usb_infos = {
-       .isr = cppi41_irq,
-       .queues_rx = usb_queues_rx,
-       .queues_tx = usb_queues_tx,
+static const struct cppi_glue_infos am335x_usb_infos = {
+       .queues_rx = am335x_usb_queues_rx,
+       .queues_tx = am335x_usb_queues_tx,
        .td_queue = { .submit = 31, .complete = 0 },
+       .first_completion_queue = 93,
+       .qmgr_num_pend = 5,
+};
+
+static const struct cppi_glue_infos da8xx_usb_infos = {
+       .queues_rx = da8xx_usb_queues_rx,
+       .queues_tx = da8xx_usb_queues_tx,
+       .td_queue = { .submit = 31, .complete = 0 },
+       .first_completion_queue = 24,
+       .qmgr_num_pend = 2,
 };
 
 static const struct of_device_id cppi41_dma_ids[] = {
-       { .compatible = "ti,am3359-cppi41", .data = &usb_infos},
+       { .compatible = "ti,am3359-cppi41", .data = &am335x_usb_infos},
+       { .compatible = "ti,da830-cppi41", .data = &da8xx_usb_infos},
        {},
 };
 MODULE_DEVICE_TABLE(of, cppi41_dma_ids);
@@ -995,6 +1005,8 @@ static int cppi41_dma_probe(struct platform_device *pdev)
        struct cppi41_dd *cdd;
        struct device *dev = &pdev->dev;
        const struct cppi_glue_infos *glue_info;
+       struct resource *mem;
+       int index;
        int irq;
        int ret;
 
@@ -1021,19 +1033,31 @@ static int cppi41_dma_probe(struct platform_device *pdev)
        INIT_LIST_HEAD(&cdd->ddev.channels);
        cpp41_dma_info.dma_cap = cdd->ddev.cap_mask;
 
-       cdd->usbss_mem = of_iomap(dev->of_node, 0);
-       cdd->ctrl_mem = of_iomap(dev->of_node, 1);
-       cdd->sched_mem = of_iomap(dev->of_node, 2);
-       cdd->qmgr_mem = of_iomap(dev->of_node, 3);
+       index = of_property_match_string(dev->of_node,
+                                        "reg-names", "controller");
+       if (index < 0)
+               return index;
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, index);
+       cdd->ctrl_mem = devm_ioremap_resource(dev, mem);
+       if (IS_ERR(cdd->ctrl_mem))
+               return PTR_ERR(cdd->ctrl_mem);
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, index + 1);
+       cdd->sched_mem = devm_ioremap_resource(dev, mem);
+       if (IS_ERR(cdd->sched_mem))
+               return PTR_ERR(cdd->sched_mem);
+
+       mem = platform_get_resource(pdev, IORESOURCE_MEM, index + 2);
+       cdd->qmgr_mem = devm_ioremap_resource(dev, mem);
+       if (IS_ERR(cdd->qmgr_mem))
+               return PTR_ERR(cdd->qmgr_mem);
+
        spin_lock_init(&cdd->lock);
        INIT_LIST_HEAD(&cdd->pending);
 
        platform_set_drvdata(pdev, cdd);
 
-       if (!cdd->usbss_mem || !cdd->ctrl_mem || !cdd->sched_mem ||
-                       !cdd->qmgr_mem)
-               return -ENXIO;
-
        pm_runtime_enable(dev);
        pm_runtime_set_autosuspend_delay(dev, 100);
        pm_runtime_use_autosuspend(dev);
@@ -1044,6 +1068,13 @@ static int cppi41_dma_probe(struct platform_device *pdev)
        cdd->queues_rx = glue_info->queues_rx;
        cdd->queues_tx = glue_info->queues_tx;
        cdd->td_queue = glue_info->td_queue;
+       cdd->qmgr_num_pend = glue_info->qmgr_num_pend;
+       cdd->first_completion_queue = glue_info->first_completion_queue;
+
+       ret = of_property_read_u32(dev->of_node,
+                                  "#dma-channels", &cdd->n_chans);
+       if (ret)
+               goto err_get_n_chans;
 
        ret = init_cppi41(dev, cdd);
        if (ret)
@@ -1056,18 +1087,18 @@ static int cppi41_dma_probe(struct platform_device *pdev)
        irq = irq_of_parse_and_map(dev->of_node, 0);
        if (!irq) {
                ret = -EINVAL;
-               goto err_irq;
+               goto err_chans;
        }
 
-       ret = devm_request_irq(&pdev->dev, irq, glue_info->isr, IRQF_SHARED,
+       ret = devm_request_irq(&pdev->dev, irq, cppi41_irq, IRQF_SHARED,
                        dev_name(dev), cdd);
        if (ret)
-               goto err_irq;
+               goto err_chans;
        cdd->irq = irq;
 
        ret = dma_async_device_register(&cdd->ddev);
        if (ret)
-               goto err_dma_reg;
+               goto err_chans;
 
        ret = of_dma_controller_register(dev->of_node,
                        cppi41_dma_xlate, &cpp41_dma_info);
@@ -1080,20 +1111,14 @@ static int cppi41_dma_probe(struct platform_device *pdev)
        return 0;
 err_of:
        dma_async_device_unregister(&cdd->ddev);
-err_dma_reg:
-err_irq:
-       cleanup_chans(cdd);
 err_chans:
        deinit_cppi41(dev, cdd);
 err_init_cppi:
        pm_runtime_dont_use_autosuspend(dev);
+err_get_n_chans:
 err_get_sync:
        pm_runtime_put_sync(dev);
        pm_runtime_disable(dev);
-       iounmap(cdd->usbss_mem);
-       iounmap(cdd->ctrl_mem);
-       iounmap(cdd->sched_mem);
-       iounmap(cdd->qmgr_mem);
        return ret;
 }
 
@@ -1110,12 +1135,7 @@ static int cppi41_dma_remove(struct platform_device *pdev)
        dma_async_device_unregister(&cdd->ddev);
 
        devm_free_irq(&pdev->dev, cdd->irq, cdd);
-       cleanup_chans(cdd);
        deinit_cppi41(&pdev->dev, cdd);
-       iounmap(cdd->usbss_mem);
-       iounmap(cdd->ctrl_mem);
-       iounmap(cdd->sched_mem);
-       iounmap(cdd->qmgr_mem);
        pm_runtime_dont_use_autosuspend(&pdev->dev);
        pm_runtime_put_sync(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
index 54d581d407aa72077a3ab7b1feaefd13b88d7cc5..a07ef3d6b3ec42b471003d8a52fe86c11286c615 100644 (file)
@@ -535,6 +535,13 @@ static int dmatest_func(void *data)
 
                total_tests++;
 
+               /* Check if buffer count fits into map count variable (u8) */
+               if ((src_cnt + dst_cnt) >= 255) {
+                       pr_err("too many buffers (%d of 255 supported)\n",
+                              src_cnt + dst_cnt);
+                       break;
+               }
+
                if (1 << align > params->buf_size) {
                        pr_err("%u-byte buffer too small for %d-byte alignment\n",
                               params->buf_size, 1 << align);
@@ -585,7 +592,7 @@ static int dmatest_func(void *data)
                for (i = 0; i < src_cnt; i++) {
                        void *buf = thread->srcs[i];
                        struct page *pg = virt_to_page(buf);
-                       unsigned pg_off = (unsigned long) buf & ~PAGE_MASK;
+                       unsigned long pg_off = offset_in_page(buf);
 
                        um->addr[i] = dma_map_page(dev->dev, pg, pg_off,
                                                   um->len, DMA_TO_DEVICE);
@@ -605,7 +612,7 @@ static int dmatest_func(void *data)
                for (i = 0; i < dst_cnt; i++) {
                        void *buf = thread->dsts[i];
                        struct page *pg = virt_to_page(buf);
-                       unsigned pg_off = (unsigned long) buf & ~PAGE_MASK;
+                       unsigned long pg_off = offset_in_page(buf);
 
                        dsts[i] = dma_map_page(dev->dev, pg, pg_off, um->len,
                                               DMA_BIDIRECTIONAL);
index d1651a50c3491e5ddd6a0ed908453713733bcc62..085993cb2ccc580a390e11dfb3ee4b2a964c7272 100644 (file)
@@ -937,6 +937,21 @@ static int sdma_disable_channel(struct dma_chan *chan)
        return 0;
 }
 
+static int sdma_disable_channel_with_delay(struct dma_chan *chan)
+{
+       sdma_disable_channel(chan);
+
+       /*
+        * According to NXP R&D team a delay of one BD SDMA cost time
+        * (maximum is 1ms) should be added after disable of the channel
+        * bit, to ensure SDMA core has really been stopped after SDMA
+        * clients call .device_terminate_all.
+        */
+       mdelay(1);
+
+       return 0;
+}
+
 static void sdma_set_watermarklevel_for_p2p(struct sdma_channel *sdmac)
 {
        struct sdma_engine *sdma = sdmac->sdma;
@@ -1828,11 +1843,11 @@ static int sdma_probe(struct platform_device *pdev)
        sdma->dma_device.device_prep_slave_sg = sdma_prep_slave_sg;
        sdma->dma_device.device_prep_dma_cyclic = sdma_prep_dma_cyclic;
        sdma->dma_device.device_config = sdma_config;
-       sdma->dma_device.device_terminate_all = sdma_disable_channel;
+       sdma->dma_device.device_terminate_all = sdma_disable_channel_with_delay;
        sdma->dma_device.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
        sdma->dma_device.dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
        sdma->dma_device.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
-       sdma->dma_device.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;
+       sdma->dma_device.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT;
        sdma->dma_device.device_issue_pending = sdma_issue_pending;
        sdma->dma_device.dev->dma_parms = &sdma->dma_parms;
        dma_set_max_seg_size(sdma->dma_device.dev, 65535);
index cc5259b881d47ffa48322e2a537397317e8b8be1..6ad4384b3fa871cccb8c46cf8e934a10a6b4452b 100644 (file)
@@ -760,9 +760,7 @@ ioat_init_channel(struct ioatdma_device *ioat_dma,
        dma_cookie_init(&ioat_chan->dma_chan);
        list_add_tail(&ioat_chan->dma_chan.device_node, &dma->channels);
        ioat_dma->idx[idx] = ioat_chan;
-       init_timer(&ioat_chan->timer);
-       ioat_chan->timer.function = ioat_timer_event;
-       ioat_chan->timer.data = data;
+       setup_timer(&ioat_chan->timer, ioat_timer_event, data);
        tasklet_init(&ioat_chan->cleanup_task, ioat_cleanup_event, data);
 }
 
index 0cb951b743a6037cd6e4d0af05b1c63295e90dcd..25bc5b103aa2415b99dfa14b2f39bc3449ca6a82 100644 (file)
@@ -960,7 +960,7 @@ static int mv_chan_memcpy_self_test(struct mv_xor_chan *mv_chan)
        }
 
        src_dma = dma_map_page(dma_chan->device->dev, virt_to_page(src),
-                              (size_t)src & ~PAGE_MASK, PAGE_SIZE,
+                              offset_in_page(src), PAGE_SIZE,
                               DMA_TO_DEVICE);
        unmap->addr[0] = src_dma;
 
@@ -972,7 +972,7 @@ static int mv_chan_memcpy_self_test(struct mv_xor_chan *mv_chan)
        unmap->to_cnt = 1;
 
        dest_dma = dma_map_page(dma_chan->device->dev, virt_to_page(dest),
-                               (size_t)dest & ~PAGE_MASK, PAGE_SIZE,
+                               offset_in_page(dest), PAGE_SIZE,
                                DMA_FROM_DEVICE);
        unmap->addr[1] = dest_dma;
 
@@ -1580,11 +1580,6 @@ static int mv_xor_probe(struct platform_device *pdev)
                        int irq;
 
                        cd = &pdata->channels[i];
-                       if (!cd) {
-                               ret = -ENODEV;
-                               goto err_channel_add;
-                       }
-
                        irq = platform_get_irq(pdev, i);
                        if (irq < 0) {
                                ret = irq;
index f37f4978dabbb2e43dab75d95255cafa398b0c73..8b0da7fa520d27ac514228130c354f121a12b848 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
 #include <linux/amba/bus.h>
-#include <linux/amba/pl330.h>
 #include <linux/scatterlist.h>
 #include <linux/of.h>
 #include <linux/of_dma.h>
@@ -2077,18 +2076,6 @@ static void pl330_tasklet(unsigned long data)
        }
 }
 
-bool pl330_filter(struct dma_chan *chan, void *param)
-{
-       u8 *peri_id;
-
-       if (chan->device->dev->driver != &pl330_driver.drv)
-               return false;
-
-       peri_id = chan->private;
-       return *peri_id == (unsigned long)param;
-}
-EXPORT_SYMBOL(pl330_filter);
-
 static struct dma_chan *of_dma_pl330_xlate(struct of_phandle_args *dma_spec,
                                                struct of_dma *ofdma)
 {
@@ -2833,7 +2820,6 @@ static SIMPLE_DEV_PM_OPS(pl330_pm, pl330_suspend, pl330_resume);
 static int
 pl330_probe(struct amba_device *adev, const struct amba_id *id)
 {
-       struct dma_pl330_platdata *pdat;
        struct pl330_config *pcfg;
        struct pl330_dmac *pl330;
        struct dma_pl330_chan *pch, *_p;
@@ -2843,8 +2829,6 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
        int num_chan;
        struct device_node *np = adev->dev.of_node;
 
-       pdat = dev_get_platdata(&adev->dev);
-
        ret = dma_set_mask_and_coherent(&adev->dev, DMA_BIT_MASK(32));
        if (ret)
                return ret;
@@ -2857,7 +2841,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
        pd = &pl330->ddma;
        pd->dev = &adev->dev;
 
-       pl330->mcbufsz = pdat ? pdat->mcbuf_sz : 0;
+       pl330->mcbufsz = 0;
 
        /* get quirk */
        for (i = 0; i < ARRAY_SIZE(of_quirks); i++)
@@ -2901,10 +2885,7 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
        INIT_LIST_HEAD(&pd->channels);
 
        /* Initialize channel parameters */
-       if (pdat)
-               num_chan = max_t(int, pdat->nr_valid_peri, pcfg->num_chan);
-       else
-               num_chan = max_t(int, pcfg->num_peri, pcfg->num_chan);
+       num_chan = max_t(int, pcfg->num_peri, pcfg->num_chan);
 
        pl330->num_peripherals = num_chan;
 
@@ -2916,11 +2897,8 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
 
        for (i = 0; i < num_chan; i++) {
                pch = &pl330->peripherals[i];
-               if (!adev->dev.of_node)
-                       pch->chan.private = pdat ? &pdat->peri_id[i] : NULL;
-               else
-                       pch->chan.private = adev->dev.of_node;
 
+               pch->chan.private = adev->dev.of_node;
                INIT_LIST_HEAD(&pch->submitted_list);
                INIT_LIST_HEAD(&pch->work_list);
                INIT_LIST_HEAD(&pch->completed_list);
@@ -2933,15 +2911,11 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
                list_add_tail(&pch->chan.device_node, &pd->channels);
        }
 
-       if (pdat) {
-               pd->cap_mask = pdat->cap_mask;
-       } else {
-               dma_cap_set(DMA_MEMCPY, pd->cap_mask);
-               if (pcfg->num_peri) {
-                       dma_cap_set(DMA_SLAVE, pd->cap_mask);
-                       dma_cap_set(DMA_CYCLIC, pd->cap_mask);
-                       dma_cap_set(DMA_PRIVATE, pd->cap_mask);
-               }
+       dma_cap_set(DMA_MEMCPY, pd->cap_mask);
+       if (pcfg->num_peri) {
+               dma_cap_set(DMA_SLAVE, pd->cap_mask);
+               dma_cap_set(DMA_CYCLIC, pd->cap_mask);
+               dma_cap_set(DMA_PRIVATE, pd->cap_mask);
        }
 
        pd->device_alloc_chan_resources = pl330_alloc_chan_resources;
index 3c982c96b4b7ccc4f65bec3ed048163be6c86bf8..5072a7d306d480724bb5d233f72c3bbf01d0efde 100644 (file)
@@ -865,6 +865,20 @@ bailout:
        return rc;
 }
 
+static void hidma_shutdown(struct platform_device *pdev)
+{
+       struct hidma_dev *dmadev = platform_get_drvdata(pdev);
+
+       dev_info(dmadev->ddev.dev, "HI-DMA engine shutdown\n");
+
+       pm_runtime_get_sync(dmadev->ddev.dev);
+       if (hidma_ll_disable(dmadev->lldev))
+               dev_warn(dmadev->ddev.dev, "channel did not stop\n");
+       pm_runtime_mark_last_busy(dmadev->ddev.dev);
+       pm_runtime_put_autosuspend(dmadev->ddev.dev);
+
+}
+
 static int hidma_remove(struct platform_device *pdev)
 {
        struct hidma_dev *dmadev = platform_get_drvdata(pdev);
@@ -908,6 +922,7 @@ MODULE_DEVICE_TABLE(of, hidma_match);
 static struct platform_driver hidma_driver = {
        .probe = hidma_probe,
        .remove = hidma_remove,
+       .shutdown = hidma_shutdown,
        .driver = {
                   .name = "hidma",
                   .of_match_table = hidma_match,
index 6645bdf0d151eafe4fa21c2fc1656554653a9920..1530a661518d7f2d41b7fe029377384b09e71271 100644 (file)
@@ -499,6 +499,9 @@ int hidma_ll_enable(struct hidma_lldev *lldev)
        lldev->trch_state = HIDMA_CH_ENABLED;
        lldev->evch_state = HIDMA_CH_ENABLED;
 
+       /* enable irqs */
+       writel(ENABLE_IRQS, lldev->evca + HIDMA_EVCA_IRQ_EN_REG);
+
        return 0;
 }
 
@@ -596,6 +599,9 @@ int hidma_ll_disable(struct hidma_lldev *lldev)
 
        lldev->trch_state = HIDMA_CH_SUSPENDED;
        lldev->evch_state = HIDMA_CH_SUSPENDED;
+
+       /* disable interrupts */
+       writel(0, lldev->evca + HIDMA_EVCA_IRQ_EN_REG);
        return 0;
 }
 
index 48b22d5c860260988f052c331f0c3050854b288c..db41795fe42ae6ed355de41f12b5c90ea661bde4 100644 (file)
@@ -344,13 +344,19 @@ static void rcar_dmac_chan_start_xfer(struct rcar_dmac_chan *chan)
                rcar_dmac_chan_write(chan, RCAR_DMARS, chan->mid_rid);
 
        if (desc->hwdescs.use) {
-               struct rcar_dmac_xfer_chunk *chunk;
+               struct rcar_dmac_xfer_chunk *chunk =
+                       list_first_entry(&desc->chunks,
+                                        struct rcar_dmac_xfer_chunk, node);
 
                dev_dbg(chan->chan.device->dev,
                        "chan%u: queue desc %p: %u@%pad\n",
                        chan->index, desc, desc->nchunks, &desc->hwdescs.dma);
 
 #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+               rcar_dmac_chan_write(chan, RCAR_DMAFIXSAR,
+                                    chunk->src_addr >> 32);
+               rcar_dmac_chan_write(chan, RCAR_DMAFIXDAR,
+                                    chunk->dst_addr >> 32);
                rcar_dmac_chan_write(chan, RCAR_DMAFIXDPBASE,
                                     desc->hwdescs.dma >> 32);
 #endif
@@ -368,8 +374,6 @@ static void rcar_dmac_chan_start_xfer(struct rcar_dmac_chan *chan)
                 * should. Initialize it manually with the destination address
                 * of the first chunk.
                 */
-               chunk = list_first_entry(&desc->chunks,
-                                        struct rcar_dmac_xfer_chunk, node);
                rcar_dmac_chan_write(chan, RCAR_DMADAR,
                                     chunk->dst_addr & 0xffffffff);
 
@@ -855,8 +859,12 @@ rcar_dmac_chan_prep_sg(struct rcar_dmac_chan *chan, struct scatterlist *sgl,
        unsigned int nchunks = 0;
        unsigned int max_chunk_size;
        unsigned int full_size = 0;
-       bool highmem = false;
+       bool cross_boundary = false;
        unsigned int i;
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+       u32 high_dev_addr;
+       u32 high_mem_addr;
+#endif
 
        desc = rcar_dmac_desc_get(chan);
        if (!desc)
@@ -882,6 +890,16 @@ rcar_dmac_chan_prep_sg(struct rcar_dmac_chan *chan, struct scatterlist *sgl,
 
                full_size += len;
 
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+               if (i == 0) {
+                       high_dev_addr = dev_addr >> 32;
+                       high_mem_addr = mem_addr >> 32;
+               }
+
+               if ((dev_addr >> 32 != high_dev_addr) ||
+                   (mem_addr >> 32 != high_mem_addr))
+                       cross_boundary = true;
+#endif
                while (len) {
                        unsigned int size = min(len, max_chunk_size);
 
@@ -890,18 +908,14 @@ rcar_dmac_chan_prep_sg(struct rcar_dmac_chan *chan, struct scatterlist *sgl,
                         * Prevent individual transfers from crossing 4GB
                         * boundaries.
                         */
-                       if (dev_addr >> 32 != (dev_addr + size - 1) >> 32)
+                       if (dev_addr >> 32 != (dev_addr + size - 1) >> 32) {
                                size = ALIGN(dev_addr, 1ULL << 32) - dev_addr;
-                       if (mem_addr >> 32 != (mem_addr + size - 1) >> 32)
+                               cross_boundary = true;
+                       }
+                       if (mem_addr >> 32 != (mem_addr + size - 1) >> 32) {
                                size = ALIGN(mem_addr, 1ULL << 32) - mem_addr;
-
-                       /*
-                        * Check if either of the source or destination address
-                        * can't be expressed in 32 bits. If so we can't use
-                        * hardware descriptor lists.
-                        */
-                       if (dev_addr >> 32 || mem_addr >> 32)
-                               highmem = true;
+                               cross_boundary = true;
+                       }
 #endif
 
                        chunk = rcar_dmac_xfer_chunk_get(chan);
@@ -943,13 +957,11 @@ rcar_dmac_chan_prep_sg(struct rcar_dmac_chan *chan, struct scatterlist *sgl,
         * Use hardware descriptor lists if possible when more than one chunk
         * needs to be transferred (otherwise they don't make much sense).
         *
-        * The highmem check currently covers the whole transfer. As an
-        * optimization we could use descriptor lists for consecutive lowmem
-        * chunks and direct manual mode for highmem chunks. Whether the
-        * performance improvement would be significant enough compared to the
-        * additional complexity remains to be investigated.
+        * Source/Destination address should be located in same 4GiB region
+        * in the 40bit address space when it uses Hardware descriptor,
+        * and cross_boundary is checking it.
         */
-       desc->hwdescs.use = !highmem && nchunks > 1;
+       desc->hwdescs.use = !cross_boundary && nchunks > 1;
        if (desc->hwdescs.use) {
                if (rcar_dmac_fill_hwdesc(chan, desc) < 0)
                        desc->hwdescs.use = false;
index 49f86cabcfec1e04b6d63f4dfb77d6f4a74654a4..786fc8fcc38ed6a2f2442a18a36bc4ab6ad4c273 100644 (file)
@@ -1008,7 +1008,7 @@ static struct dma_chan *stm32_dma_of_xlate(struct of_phandle_args *dma_spec,
 
        c = dma_get_slave_channel(&chan->vchan.chan);
        if (!c) {
-               dev_err(dev, "No more channel avalaible\n");
+               dev_err(dev, "No more channels available\n");
                return NULL;
        }
 
index 57aa227bfadb3eae97cb348372cacdf6eafc4586..f4ed3f17607cf7e79691469a8d40556b8db00258 100644 (file)
@@ -238,7 +238,7 @@ static struct sun4i_dma_pchan *find_and_use_pchan(struct sun4i_dma_dev *priv,
        }
 
        spin_lock_irqsave(&priv->lock, flags);
-       for_each_clear_bit_from(i, &priv->pchans_used, max) {
+       for_each_clear_bit_from(i, priv->pchans_used, max) {
                pchan = &pchans[i];
                pchan->vchan = vchan;
                set_bit(i, priv->pchans_used);
index e47fc9b0944f10001a7214ae2bd3f6b961848982..545e972790834018e11522ea18de1d19e43dbcd0 100644 (file)
@@ -86,7 +86,7 @@ EXPORT_SYMBOL_GPL(vchan_find_desc);
 static void vchan_complete(unsigned long arg)
 {
        struct virt_dma_chan *vc = (struct virt_dma_chan *)arg;
-       struct virt_dma_desc *vd;
+       struct virt_dma_desc *vd, *_vd;
        struct dmaengine_desc_callback cb;
        LIST_HEAD(head);
 
@@ -103,8 +103,7 @@ static void vchan_complete(unsigned long arg)
 
        dmaengine_desc_callback_invoke(&cb, NULL);
 
-       while (!list_empty(&head)) {
-               vd = list_first_entry(&head, struct virt_dma_desc, node);
+       list_for_each_entry_safe(vd, _vd, &head, node) {
                dmaengine_desc_get_callback(&vd->tx, &cb);
 
                list_del(&vd->node);
@@ -119,9 +118,9 @@ static void vchan_complete(unsigned long arg)
 
 void vchan_dma_desc_free_list(struct virt_dma_chan *vc, struct list_head *head)
 {
-       while (!list_empty(head)) {
-               struct virt_dma_desc *vd = list_first_entry(head,
-                       struct virt_dma_desc, node);
+       struct virt_dma_desc *vd, *_vd;
+
+       list_for_each_entry_safe(vd, _vd, head, node) {
                if (dmaengine_desc_test_reuse(&vd->tx)) {
                        list_move_tail(&vd->node, &vc->desc_allocated);
                } else {
index 8288fe4d17c38ec7b3094080bb409392ebaa5651..8cf87b1a284b300219f2adfdccb4d7ca57823d91 100644 (file)
@@ -331,6 +331,7 @@ struct xilinx_dma_tx_descriptor {
  * @seg_v: Statically allocated segments base
  * @cyclic_seg_v: Statically allocated segment base for cyclic transfers
  * @start_transfer: Differentiate b/w DMA IP's transfer
+ * @stop_transfer: Differentiate b/w DMA IP's quiesce
  */
 struct xilinx_dma_chan {
        struct xilinx_dma_device *xdev;
@@ -361,6 +362,7 @@ struct xilinx_dma_chan {
        struct xilinx_axidma_tx_segment *seg_v;
        struct xilinx_axidma_tx_segment *cyclic_seg_v;
        void (*start_transfer)(struct xilinx_dma_chan *chan);
+       int (*stop_transfer)(struct xilinx_dma_chan *chan);
        u16 tdest;
 };
 
@@ -946,26 +948,32 @@ static bool xilinx_dma_is_idle(struct xilinx_dma_chan *chan)
 }
 
 /**
- * xilinx_dma_halt - Halt DMA channel
+ * xilinx_dma_stop_transfer - Halt DMA channel
  * @chan: Driver specific DMA channel
  */
-static void xilinx_dma_halt(struct xilinx_dma_chan *chan)
+static int xilinx_dma_stop_transfer(struct xilinx_dma_chan *chan)
 {
-       int err;
        u32 val;
 
        dma_ctrl_clr(chan, XILINX_DMA_REG_DMACR, XILINX_DMA_DMACR_RUNSTOP);
 
        /* Wait for the hardware to halt */
-       err = xilinx_dma_poll_timeout(chan, XILINX_DMA_REG_DMASR, val,
-                                     (val & XILINX_DMA_DMASR_HALTED), 0,
-                                     XILINX_DMA_LOOP_COUNT);
+       return xilinx_dma_poll_timeout(chan, XILINX_DMA_REG_DMASR, val,
+                                      val & XILINX_DMA_DMASR_HALTED, 0,
+                                      XILINX_DMA_LOOP_COUNT);
+}
 
-       if (err) {
-               dev_err(chan->dev, "Cannot stop channel %p: %x\n",
-                       chan, dma_ctrl_read(chan, XILINX_DMA_REG_DMASR));
-               chan->err = true;
-       }
+/**
+ * xilinx_cdma_stop_transfer - Wait for the current transfer to complete
+ * @chan: Driver specific DMA channel
+ */
+static int xilinx_cdma_stop_transfer(struct xilinx_dma_chan *chan)
+{
+       u32 val;
+
+       return xilinx_dma_poll_timeout(chan, XILINX_DMA_REG_DMASR, val,
+                                      val & XILINX_DMA_DMASR_IDLE, 0,
+                                      XILINX_DMA_LOOP_COUNT);
 }
 
 /**
@@ -1653,7 +1661,7 @@ xilinx_cdma_prep_memcpy(struct dma_chan *dchan, dma_addr_t dma_dst,
 {
        struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
        struct xilinx_dma_tx_descriptor *desc;
-       struct xilinx_cdma_tx_segment *segment, *prev;
+       struct xilinx_cdma_tx_segment *segment;
        struct xilinx_cdma_desc_hw *hw;
 
        if (!len || len > XILINX_DMA_MAX_TRANS_LEN)
@@ -1680,21 +1688,11 @@ xilinx_cdma_prep_memcpy(struct dma_chan *dchan, dma_addr_t dma_dst,
                hw->dest_addr_msb = upper_32_bits(dma_dst);
        }
 
-       /* Fill the previous next descriptor with current */
-       prev = list_last_entry(&desc->segments,
-                              struct xilinx_cdma_tx_segment, node);
-       prev->hw.next_desc = segment->phys;
-
        /* Insert the segment into the descriptor segments list. */
        list_add_tail(&segment->node, &desc->segments);
 
-       prev = segment;
-
-       /* Link the last hardware descriptor with the first. */
-       segment = list_first_entry(&desc->segments,
-                               struct xilinx_cdma_tx_segment, node);
        desc->async_tx.phys = segment->phys;
-       prev->hw.next_desc = segment->phys;
+       hw->next_desc = segment->phys;
 
        return &desc->async_tx;
 
@@ -2003,12 +2001,17 @@ static int xilinx_dma_terminate_all(struct dma_chan *dchan)
 {
        struct xilinx_dma_chan *chan = to_xilinx_chan(dchan);
        u32 reg;
+       int err;
 
        if (chan->cyclic)
                xilinx_dma_chan_reset(chan);
 
-       /* Halt the DMA engine */
-       xilinx_dma_halt(chan);
+       err = chan->stop_transfer(chan);
+       if (err) {
+               dev_err(chan->dev, "Cannot stop channel %p: %x\n",
+                       chan, dma_ctrl_read(chan, XILINX_DMA_REG_DMASR));
+               chan->err = true;
+       }
 
        /* Remove and free all of the descriptors in the lists */
        xilinx_dma_free_descriptors(chan);
@@ -2397,12 +2400,16 @@ static int xilinx_dma_chan_probe(struct xilinx_dma_device *xdev,
                return err;
        }
 
-       if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA)
+       if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
                chan->start_transfer = xilinx_dma_start_transfer;
-       else if (xdev->dma_config->dmatype == XDMA_TYPE_CDMA)
+               chan->stop_transfer = xilinx_dma_stop_transfer;
+       } else if (xdev->dma_config->dmatype == XDMA_TYPE_CDMA) {
                chan->start_transfer = xilinx_cdma_start_transfer;
-       else
+               chan->stop_transfer = xilinx_cdma_stop_transfer;
+       } else {
                chan->start_transfer = xilinx_vdma_start_transfer;
+               chan->stop_transfer = xilinx_dma_stop_transfer;
+       }
 
        /* Initialize the tasklet */
        tasklet_init(&chan->tasklet, xilinx_dma_do_tasklet,
index 82dab1692264d04baeb409622d54bbd895e013ff..3aea5569816557b9b55503fb7fd654e9b088b6df 100644 (file)
@@ -782,24 +782,26 @@ static void debug_dump_dramcfg_low(struct amd64_pvt *pvt, u32 dclr, int chan)
 
 static void debug_display_dimm_sizes_df(struct amd64_pvt *pvt, u8 ctrl)
 {
-       u32 *dcsb = ctrl ? pvt->csels[1].csbases : pvt->csels[0].csbases;
-       int dimm, size0, size1;
+       int dimm, size0, size1, cs0, cs1;
 
        edac_printk(KERN_DEBUG, EDAC_MC, "UMC%d chip selects:\n", ctrl);
 
        for (dimm = 0; dimm < 4; dimm++) {
                size0 = 0;
+               cs0 = dimm * 2;
 
-               if (dcsb[dimm*2] & DCSB_CS_ENABLE)
-                       size0 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, dimm);
+               if (csrow_enabled(cs0, ctrl, pvt))
+                       size0 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, cs0);
 
                size1 = 0;
-               if (dcsb[dimm*2 + 1] & DCSB_CS_ENABLE)
-                       size1 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, dimm);
+               cs1 = dimm * 2 + 1;
+
+               if (csrow_enabled(cs1, ctrl, pvt))
+                       size1 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, cs1);
 
                amd64_info(EDAC_MC ": %d: %5dMB %d: %5dMB\n",
-                               dimm * 2,     size0,
-                               dimm * 2 + 1, size1);
+                               cs0,    size0,
+                               cs1,    size1);
        }
 }
 
@@ -2756,26 +2758,22 @@ skip:
  *     encompasses
  *
  */
-static u32 get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr)
+static u32 get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr_orig)
 {
-       u32 cs_mode, nr_pages;
        u32 dbam = dct ? pvt->dbam1 : pvt->dbam0;
+       int csrow_nr = csrow_nr_orig;
+       u32 cs_mode, nr_pages;
 
+       if (!pvt->umc)
+               csrow_nr >>= 1;
 
-       /*
-        * The math on this doesn't look right on the surface because x/2*4 can
-        * be simplified to x*2 but this expression makes use of the fact that
-        * it is integral math where 1/2=0. This intermediate value becomes the
-        * number of bits to shift the DBAM register to extract the proper CSROW
-        * field.
-        */
-       cs_mode = DBAM_DIMM(csrow_nr / 2, dbam);
+       cs_mode = DBAM_DIMM(csrow_nr, dbam);
 
-       nr_pages = pvt->ops->dbam_to_cs(pvt, dct, cs_mode, (csrow_nr / 2))
-                                                          << (20 - PAGE_SHIFT);
+       nr_pages   = pvt->ops->dbam_to_cs(pvt, dct, cs_mode, csrow_nr);
+       nr_pages <<= 20 - PAGE_SHIFT;
 
        edac_dbg(0, "csrow: %d, channel: %d, DBAM idx: %d\n",
-                   csrow_nr, dct,  cs_mode);
+                   csrow_nr_orig, dct,  cs_mode);
        edac_dbg(0, "nr_pages/channel: %u\n", nr_pages);
 
        return nr_pages;
index 9ad0b1934be9a31173ede1ed6c1c3705cc0c1e05..f6cfc31d34c71578623258bbe7443e4023b8a485 100644 (file)
@@ -538,7 +538,7 @@ static int scpi_send_message(u8 idx, void *tx_buf, unsigned int tx_len,
        msg->tx_len = tx_len;
        msg->rx_buf = rx_buf;
        msg->rx_len = rx_len;
-       init_completion(&msg->done);
+       reinit_completion(&msg->done);
 
        ret = mbox_send_message(scpi_chan->chan, msg);
        if (ret < 0 || !rx_buf)
@@ -872,8 +872,11 @@ static int scpi_alloc_xfer_list(struct device *dev, struct scpi_chan *ch)
                return -ENOMEM;
 
        ch->xfers = xfers;
-       for (i = 0; i < MAX_SCPI_XFERS; i++, xfers++)
+       for (i = 0; i < MAX_SCPI_XFERS; i++, xfers++) {
+               init_completion(&xfers->done);
                list_add_tail(&xfers->node, &ch->xfers_list);
+       }
+
        return 0;
 }
 
index ed3137c1ceb0c0ed0fcbb1c94bffdf1a4811bf41..ab3a951a17e6c182dfa1c68b579ee003b3c1c44a 100644 (file)
@@ -155,19 +155,14 @@ static int efi_pstore_scan_sysfs_exit(struct efivar_entry *pos,
  * efi_pstore_sysfs_entry_iter
  *
  * @record: pstore record to pass to callback
- * @pos: entry to begin iterating from
  *
  * You MUST call efivar_enter_iter_begin() before this function, and
  * efivar_entry_iter_end() afterwards.
  *
- * It is possible to begin iteration from an arbitrary entry within
- * the list by passing @pos. @pos is updated on return to point to
- * the next entry of the last one passed to efi_pstore_read_func().
- * To begin iterating from the beginning of the list @pos must be %NULL.
  */
-static int efi_pstore_sysfs_entry_iter(struct pstore_record *record,
-                                      struct efivar_entry **pos)
+static int efi_pstore_sysfs_entry_iter(struct pstore_record *record)
 {
+       struct efivar_entry **pos = (struct efivar_entry **)&record->psi->data;
        struct efivar_entry *entry, *n;
        struct list_head *head = &efivar_sysfs_list;
        int size = 0;
@@ -218,7 +213,6 @@ static int efi_pstore_sysfs_entry_iter(struct pstore_record *record,
  */
 static ssize_t efi_pstore_read(struct pstore_record *record)
 {
-       struct efivar_entry *entry = (struct efivar_entry *)record->psi->data;
        ssize_t size;
 
        record->buf = kzalloc(EFIVARS_DATA_SIZE_MAX, GFP_KERNEL);
@@ -229,7 +223,7 @@ static ssize_t efi_pstore_read(struct pstore_record *record)
                size = -EINTR;
                goto out;
        }
-       size = efi_pstore_sysfs_entry_iter(record, &entry);
+       size = efi_pstore_sysfs_entry_iter(record);
        efivar_entry_iter_end();
 
 out:
index b0d254930ed35cd86efa782d631582bcabda22b4..ff204421117b8bd9c836a41e6f439f592f21c565 100644 (file)
@@ -127,6 +127,7 @@ EXPORT_SYMBOL(meson_sm_call);
  * meson_sm_call_read - retrieve data from secure-monitor
  *
  * @buffer:    Buffer to store the retrieved data
+ * @bsize:     Size of the buffer
  * @cmd_index: Index of the SMC32 function ID
  * @arg0:      SMC32 Argument 0
  * @arg1:      SMC32 Argument 1
@@ -135,11 +136,14 @@ EXPORT_SYMBOL(meson_sm_call);
  * @arg4:      SMC32 Argument 4
  *
  * Return:     size of read data on success, a negative value on error
+ *             When 0 is returned there is no guarantee about the amount of
+ *             data read and bsize bytes are copied in buffer.
  */
-int meson_sm_call_read(void *buffer, unsigned int cmd_index, u32 arg0,
-                      u32 arg1, u32 arg2, u32 arg3, u32 arg4)
+int meson_sm_call_read(void *buffer, unsigned int bsize, unsigned int cmd_index,
+                      u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4)
 {
        u32 size;
+       int ret;
 
        if (!fw.chip)
                return -ENOENT;
@@ -147,16 +151,24 @@ int meson_sm_call_read(void *buffer, unsigned int cmd_index, u32 arg0,
        if (!fw.chip->cmd_shmem_out_base)
                return -EINVAL;
 
+       if (bsize > fw.chip->shmem_size)
+               return -EINVAL;
+
        if (meson_sm_call(cmd_index, &size, arg0, arg1, arg2, arg3, arg4) < 0)
                return -EINVAL;
 
-       if (!size || size > fw.chip->shmem_size)
+       if (size > bsize)
                return -EINVAL;
 
+       ret = size;
+
+       if (!size)
+               size = bsize;
+
        if (buffer)
                memcpy(buffer, fw.sm_shmem_out_base, size);
 
-       return size;
+       return ret;
 }
 EXPORT_SYMBOL(meson_sm_call_read);
 
index 8ad226c60374cd9a2697268c4137212d63673f7f..93e3b96b6dfafa181db0a2910f29ed493777c06f 100644 (file)
@@ -578,3 +578,21 @@ int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id)
 
        return ret ? : le32_to_cpu(scm_ret);
 }
+
+int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id,
+                              u32 spare)
+{
+       return -ENODEV;
+}
+
+int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare,
+                                     size_t *size)
+{
+       return -ENODEV;
+}
+
+int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size,
+                                     u32 spare)
+{
+       return -ENODEV;
+}
index c9332590e8c662d3ed79c7986ab759fd0a0a7699..6e6d561708e28c5da0fd6f7f95eb3b39f5e609e6 100644 (file)
@@ -381,3 +381,61 @@ int __qcom_scm_set_remote_state(struct device *dev, u32 state, u32 id)
 
        return ret ? : res.a1;
 }
+
+int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id, u32 spare)
+{
+       struct qcom_scm_desc desc = {0};
+       struct arm_smccc_res res;
+       int ret;
+
+       desc.args[0] = device_id;
+       desc.args[1] = spare;
+       desc.arginfo = QCOM_SCM_ARGS(2);
+
+       ret = qcom_scm_call(dev, QCOM_SCM_SVC_MP, QCOM_SCM_RESTORE_SEC_CFG,
+                           &desc, &res);
+
+       return ret ? : res.a1;
+}
+
+int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare,
+                                     size_t *size)
+{
+       struct qcom_scm_desc desc = {0};
+       struct arm_smccc_res res;
+       int ret;
+
+       desc.args[0] = spare;
+       desc.arginfo = QCOM_SCM_ARGS(1);
+
+       ret = qcom_scm_call(dev, QCOM_SCM_SVC_MP,
+                           QCOM_SCM_IOMMU_SECURE_PTBL_SIZE, &desc, &res);
+
+       if (size)
+               *size = res.a1;
+
+       return ret ? : res.a2;
+}
+
+int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr, u32 size,
+                                     u32 spare)
+{
+       struct qcom_scm_desc desc = {0};
+       struct arm_smccc_res res;
+       int ret;
+
+       desc.args[0] = addr;
+       desc.args[1] = size;
+       desc.args[2] = spare;
+       desc.arginfo = QCOM_SCM_ARGS(3, QCOM_SCM_RW, QCOM_SCM_VAL,
+                                    QCOM_SCM_VAL);
+
+       ret = qcom_scm_call(dev, QCOM_SCM_SVC_MP,
+                           QCOM_SCM_IOMMU_SECURE_PTBL_INIT, &desc, &res);
+
+       /* the pg table has been initialized already, ignore the error */
+       if (ret == -EPERM)
+               ret = 0;
+
+       return ret;
+}
index d987bcc7489d981ee4b9784a6293fa6fd6ce175a..bb16510d75baa94f84f8e2a7993fe9bccde258dd 100644 (file)
@@ -315,6 +315,24 @@ static const struct reset_control_ops qcom_scm_pas_reset_ops = {
        .deassert = qcom_scm_pas_reset_deassert,
 };
 
+int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare)
+{
+       return __qcom_scm_restore_sec_cfg(__scm->dev, device_id, spare);
+}
+EXPORT_SYMBOL(qcom_scm_restore_sec_cfg);
+
+int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size)
+{
+       return __qcom_scm_iommu_secure_ptbl_size(__scm->dev, spare, size);
+}
+EXPORT_SYMBOL(qcom_scm_iommu_secure_ptbl_size);
+
+int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare)
+{
+       return __qcom_scm_iommu_secure_ptbl_init(__scm->dev, addr, size, spare);
+}
+EXPORT_SYMBOL(qcom_scm_iommu_secure_ptbl_init);
+
 /**
  * qcom_scm_is_available() - Checks if SCM is available
  */
index 6a0f15469344e0b960747a3d06f4236467da942f..9bea691f30fb8dd3a7906035a62af8e2c8766a93 100644 (file)
@@ -85,4 +85,15 @@ static inline int qcom_scm_remap_error(int err)
        return -EINVAL;
 }
 
+#define QCOM_SCM_SVC_MP                        0xc
+#define QCOM_SCM_RESTORE_SEC_CFG       2
+extern int __qcom_scm_restore_sec_cfg(struct device *dev, u32 device_id,
+                                     u32 spare);
+#define QCOM_SCM_IOMMU_SECURE_PTBL_SIZE        3
+#define QCOM_SCM_IOMMU_SECURE_PTBL_INIT        4
+extern int __qcom_scm_iommu_secure_ptbl_size(struct device *dev, u32 spare,
+                                            size_t *size);
+extern int __qcom_scm_iommu_secure_ptbl_init(struct device *dev, u64 addr,
+                                            u32 size, u32 spare);
+
 #endif
index 874ff32db36668919c50eb6eda3d744327ee5dd6..00cfed3c3e1a20b7bbea4b1a93e59fcd09afc2dd 100644 (file)
@@ -202,7 +202,8 @@ static int ti_sci_debugfs_create(struct platform_device *pdev,
        info->debug_buffer[info->debug_region_size] = 0;
 
        info->d = debugfs_create_file(strncat(debug_name, dev_name(dev),
-                                             sizeof(debug_name)),
+                                             sizeof(debug_name) -
+                                             sizeof("ti_sci_debug@")),
                                      0444, NULL, info, &ti_sci_debug_fops);
        if (IS_ERR(info->d))
                return PTR_ERR(info->d);
index 61b50c40b87bba9469fa650a4fd6858607312092..598e209efa2de9d923d86a37b43958e0c1b5dcd3 100644 (file)
 
 static unsigned int base[MAX_NUM_DIO48E];
 static unsigned int num_dio48e;
-module_param_array(base, uint, &num_dio48e, 0);
+module_param_hw_array(base, uint, ioport, &num_dio48e, 0);
 MODULE_PARM_DESC(base, "ACCES 104-DIO-48E base addresses");
 
 static unsigned int irq[MAX_NUM_DIO48E];
-module_param_array(irq, uint, NULL, 0);
+module_param_hw_array(irq, uint, irq, NULL, 0);
 MODULE_PARM_DESC(irq, "ACCES 104-DIO-48E interrupt line numbers");
 
 /**
index 337c048168d82d90c68f2da6425621763a993146..51f046e29ff79873c21497f1dfa8a5cd8cfdeb09 100644 (file)
 
 static unsigned int base[MAX_NUM_IDI_48];
 static unsigned int num_idi_48;
-module_param_array(base, uint, &num_idi_48, 0);
+module_param_hw_array(base, uint, ioport, &num_idi_48, 0);
 MODULE_PARM_DESC(base, "ACCES 104-IDI-48 base addresses");
 
 static unsigned int irq[MAX_NUM_IDI_48];
-module_param_array(irq, uint, NULL, 0);
+module_param_hw_array(irq, uint, irq, NULL, 0);
 MODULE_PARM_DESC(irq, "ACCES 104-IDI-48 interrupt line numbers");
 
 /**
index 5281e1cedb01d8937373cdda3c804c25f3f342e1..ec2ce34ff47371d877385c48c9209dc3ce57f9dc 100644 (file)
 
 static unsigned int base[MAX_NUM_IDIO_16];
 static unsigned int num_idio_16;
-module_param_array(base, uint, &num_idio_16, 0);
+module_param_hw_array(base, uint, ioport, &num_idio_16, 0);
 MODULE_PARM_DESC(base, "ACCES 104-IDIO-16 base addresses");
 
 static unsigned int irq[MAX_NUM_IDIO_16];
-module_param_array(irq, uint, NULL, 0);
+module_param_hw_array(irq, uint, irq, NULL, 0);
 MODULE_PARM_DESC(irq, "ACCES 104-IDIO-16 interrupt line numbers");
 
 /**
index fa4baa2543db0edab2fa1b509552e44e9e9cfd91..11ade5b288f8547e817336ce8d2c35ca002ecfc8 100644 (file)
@@ -31,7 +31,7 @@
 
 static unsigned int base[MAX_NUM_GPIOMM];
 static unsigned int num_gpiomm;
-module_param_array(base, uint, &num_gpiomm, 0);
+module_param_hw_array(base, uint, ioport, &num_gpiomm, 0);
 MODULE_PARM_DESC(base, "Diamond Systems GPIO-MM base addresses");
 
 /**
index 87d63695dfcf796d73c04c795ab2eaf17d2acb74..5037974ac06356d0e4cba43f99923860f53b4706 100644 (file)
 
 static unsigned int base[MAX_NUM_WS16C48];
 static unsigned int num_ws16c48;
-module_param_array(base, uint, &num_ws16c48, 0);
+module_param_hw_array(base, uint, ioport, &num_ws16c48, 0);
 MODULE_PARM_DESC(base, "WinSystems WS16C48 base addresses");
 
 static unsigned int irq[MAX_NUM_WS16C48];
-module_param_array(irq, uint, NULL, 0);
+module_param_hw_array(irq, uint, irq, NULL, 0);
 MODULE_PARM_DESC(irq, "WinSystems WS16C48 interrupt line numbers");
 
 /**
index 6a8129949333e9e395d8e5d5b78469c639438b27..833c3c16501a0221da5161eaec189a5576292abc 100644 (file)
@@ -110,6 +110,7 @@ extern int amdgpu_pos_buf_per_se;
 extern int amdgpu_cntl_sb_buf_per_se;
 extern int amdgpu_param_buf_per_se;
 
+#define AMDGPU_DEFAULT_GTT_SIZE_MB             3072ULL /* 3GB by default */
 #define AMDGPU_WAIT_IDLE_TIMEOUT_IN_MS         3000
 #define AMDGPU_MAX_USEC_TIMEOUT                        100000  /* 100 ms */
 #define AMDGPU_FENCE_JIFFIES_TIMEOUT           (HZ / 2)
@@ -966,6 +967,8 @@ struct amdgpu_gfx_config {
        unsigned mc_arb_ramcfg;
        unsigned gb_addr_config;
        unsigned num_rbs;
+       unsigned gs_vgt_table_depth;
+       unsigned gs_prim_buffer_depth;
 
        uint32_t tile_mode_array[32];
        uint32_t macrotile_mode_array[16];
@@ -980,6 +983,7 @@ struct amdgpu_gfx_config {
 struct amdgpu_cu_info {
        uint32_t number; /* total active CU number */
        uint32_t ao_cu_mask;
+       uint32_t wave_front_size;
        uint32_t bitmap[4][4];
 };
 
@@ -1000,10 +1004,10 @@ struct amdgpu_ngg_buf {
 };
 
 enum {
-       PRIM = 0,
-       POS,
-       CNTL,
-       PARAM,
+       NGG_PRIM = 0,
+       NGG_POS,
+       NGG_CNTL,
+       NGG_PARAM,
        NGG_BUF_MAX
 };
 
@@ -1125,6 +1129,7 @@ struct amdgpu_job {
        void                    *owner;
        uint64_t                fence_ctx; /* the fence_context this job uses */
        bool                    vm_needs_flush;
+       bool                    need_pipeline_sync;
        unsigned                vm_id;
        uint64_t                vm_pd_addr;
        uint32_t                gds_base, gds_size;
@@ -1704,9 +1709,6 @@ void amdgpu_mm_wdoorbell64(struct amdgpu_device *adev, u32 index, u64 v);
 #define WREG32_FIELD_OFFSET(reg, offset, field, val)   \
        WREG32(mm##reg + offset, (RREG32(mm##reg + offset) & ~REG_FIELD_MASK(reg, field)) | (val) << REG_FIELD_SHIFT(reg, field))
 
-#define WREG32_FIELD15(ip, idx, reg, field, val)       \
-       WREG32(SOC15_REG_OFFSET(ip, idx, mm##reg), (RREG32(SOC15_REG_OFFSET(ip, idx, mm##reg)) & ~REG_FIELD_MASK(reg, field)) | (val) << REG_FIELD_SHIFT(reg, field))
-
 /*
  * BIOS helpers.
  */
index ad4329922f7953ad7b6a032644832ad757d80598..1cf78f4dd339f93ddd971088ec42a5146b9820fe 100644 (file)
@@ -1727,6 +1727,12 @@ void amdgpu_atombios_scratch_regs_restore(struct amdgpu_device *adev)
 {
        int i;
 
+       /*
+        * VBIOS will check ASIC_INIT_COMPLETE bit to decide if
+        * execute ASIC_Init posting via driver
+        */
+       adev->bios_scratch[7] &= ~ATOM_S7_ASIC_INIT_COMPLETE_MASK;
+
        for (i = 0; i < AMDGPU_BIOS_NUM_SCRATCH; i++)
                WREG32(mmBIOS_SCRATCH_0 + i, adev->bios_scratch[i]);
 }
index 4b9abd68e04f85eb6e837e7d884a25013e7d9369..4bdda56fcceea36b8229d74ac3b76fe706919a77 100644 (file)
@@ -26,6 +26,7 @@
 #include "atomfirmware.h"
 #include "amdgpu_atomfirmware.h"
 #include "atom.h"
+#include "atombios.h"
 
 #define get_index_into_master_table(master_table, table_name) (offsetof(struct master_table, table_name) / sizeof(uint16_t))
 
@@ -77,10 +78,29 @@ void amdgpu_atomfirmware_scratch_regs_restore(struct amdgpu_device *adev)
 {
        int i;
 
+       /*
+        * VBIOS will check ASIC_INIT_COMPLETE bit to decide if
+        * execute ASIC_Init posting via driver
+        */
+       adev->bios_scratch[7] &= ~ATOM_S7_ASIC_INIT_COMPLETE_MASK;
+
        for (i = 0; i < AMDGPU_BIOS_NUM_SCRATCH; i++)
                WREG32(adev->bios_scratch_reg_offset + i, adev->bios_scratch[i]);
 }
 
+void amdgpu_atomfirmware_scratch_regs_engine_hung(struct amdgpu_device *adev,
+                                                 bool hung)
+{
+       u32 tmp = RREG32(adev->bios_scratch_reg_offset + 3);
+
+       if (hung)
+               tmp |= ATOM_S3_ASIC_GUI_ENGINE_HUNG;
+       else
+               tmp &= ~ATOM_S3_ASIC_GUI_ENGINE_HUNG;
+
+       WREG32(adev->bios_scratch_reg_offset + 3, tmp);
+}
+
 int amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device *adev)
 {
        struct atom_context *ctx = adev->mode_info.atom_context;
index d0c4dcd7fa962beab4ba5417df75c9e52834f656..a2c3ebe22c713aeacff5036d431ffc1e157f5f7e 100644 (file)
@@ -28,6 +28,8 @@ bool amdgpu_atomfirmware_gpu_supports_virtualization(struct amdgpu_device *adev)
 void amdgpu_atomfirmware_scratch_regs_init(struct amdgpu_device *adev);
 void amdgpu_atomfirmware_scratch_regs_save(struct amdgpu_device *adev);
 void amdgpu_atomfirmware_scratch_regs_restore(struct amdgpu_device *adev);
+void amdgpu_atomfirmware_scratch_regs_engine_hung(struct amdgpu_device *adev,
+                                                 bool hung);
 int amdgpu_atomfirmware_allocate_fb_scratch(struct amdgpu_device *adev);
 
 #endif
index cc97eee9322640bf5c881aef67d0e8cbb0efc2d5..1beae5b930d0e10d407501708a0585e56001181e 100644 (file)
@@ -117,8 +117,13 @@ static void amdgpu_benchmark_move(struct amdgpu_device *adev, unsigned size,
        }
 
 out_cleanup:
+       /* Check error value now. The value can be overwritten when clean up.*/
+       if (r) {
+               DRM_ERROR("Error while benchmarking BO move.\n");
+       }
+
        if (sobj) {
-               r = amdgpu_bo_reserve(sobj, false);
+               r = amdgpu_bo_reserve(sobj, true);
                if (likely(r == 0)) {
                        amdgpu_bo_unpin(sobj);
                        amdgpu_bo_unreserve(sobj);
@@ -126,17 +131,13 @@ out_cleanup:
                amdgpu_bo_unref(&sobj);
        }
        if (dobj) {
-               r = amdgpu_bo_reserve(dobj, false);
+               r = amdgpu_bo_reserve(dobj, true);
                if (likely(r == 0)) {
                        amdgpu_bo_unpin(dobj);
                        amdgpu_bo_unreserve(dobj);
                }
                amdgpu_bo_unref(&dobj);
        }
-
-       if (r) {
-               DRM_ERROR("Error while benchmarking BO move.\n");
-       }
 }
 
 void amdgpu_benchmark(struct amdgpu_device *adev, int test_number)
index 1c7e6c28f93ae68b5cef862b239b6806b0b44b8d..c6dba1eaefbd463a2330386ae41773a659139051 100644 (file)
@@ -42,82 +42,6 @@ struct amdgpu_cgs_device {
        struct amdgpu_device *adev =                                    \
                ((struct amdgpu_cgs_device *)cgs_device)->adev
 
-static int amdgpu_cgs_gpu_mem_info(struct cgs_device *cgs_device, enum cgs_gpu_mem_type type,
-                                  uint64_t *mc_start, uint64_t *mc_size,
-                                  uint64_t *mem_size)
-{
-       CGS_FUNC_ADEV;
-       switch(type) {
-       case CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB:
-       case CGS_GPU_MEM_TYPE__VISIBLE_FB:
-               *mc_start = 0;
-               *mc_size = adev->mc.visible_vram_size;
-               *mem_size = adev->mc.visible_vram_size - adev->vram_pin_size;
-               break;
-       case CGS_GPU_MEM_TYPE__INVISIBLE_CONTIG_FB:
-       case CGS_GPU_MEM_TYPE__INVISIBLE_FB:
-               *mc_start = adev->mc.visible_vram_size;
-               *mc_size = adev->mc.real_vram_size - adev->mc.visible_vram_size;
-               *mem_size = *mc_size;
-               break;
-       case CGS_GPU_MEM_TYPE__GART_CACHEABLE:
-       case CGS_GPU_MEM_TYPE__GART_WRITECOMBINE:
-               *mc_start = adev->mc.gtt_start;
-               *mc_size = adev->mc.gtt_size;
-               *mem_size = adev->mc.gtt_size - adev->gart_pin_size;
-               break;
-       default:
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static int amdgpu_cgs_gmap_kmem(struct cgs_device *cgs_device, void *kmem,
-                               uint64_t size,
-                               uint64_t min_offset, uint64_t max_offset,
-                               cgs_handle_t *kmem_handle, uint64_t *mcaddr)
-{
-       CGS_FUNC_ADEV;
-       int ret;
-       struct amdgpu_bo *bo;
-       struct page *kmem_page = vmalloc_to_page(kmem);
-       int npages = ALIGN(size, PAGE_SIZE) >> PAGE_SHIFT;
-
-       struct sg_table *sg = drm_prime_pages_to_sg(&kmem_page, npages);
-       ret = amdgpu_bo_create(adev, size, PAGE_SIZE, false,
-                              AMDGPU_GEM_DOMAIN_GTT, 0, sg, NULL, &bo);
-       if (ret)
-               return ret;
-       ret = amdgpu_bo_reserve(bo, false);
-       if (unlikely(ret != 0))
-               return ret;
-
-       /* pin buffer into GTT */
-       ret = amdgpu_bo_pin_restricted(bo, AMDGPU_GEM_DOMAIN_GTT,
-                                      min_offset, max_offset, mcaddr);
-       amdgpu_bo_unreserve(bo);
-
-       *kmem_handle = (cgs_handle_t)bo;
-       return ret;
-}
-
-static int amdgpu_cgs_gunmap_kmem(struct cgs_device *cgs_device, cgs_handle_t kmem_handle)
-{
-       struct amdgpu_bo *obj = (struct amdgpu_bo *)kmem_handle;
-
-       if (obj) {
-               int r = amdgpu_bo_reserve(obj, false);
-               if (likely(r == 0)) {
-                       amdgpu_bo_unpin(obj);
-                       amdgpu_bo_unreserve(obj);
-               }
-               amdgpu_bo_unref(&obj);
-
-       }
-       return 0;
-}
-
 static int amdgpu_cgs_alloc_gpu_mem(struct cgs_device *cgs_device,
                                    enum cgs_gpu_mem_type type,
                                    uint64_t size, uint64_t align,
@@ -215,7 +139,7 @@ static int amdgpu_cgs_free_gpu_mem(struct cgs_device *cgs_device, cgs_handle_t h
        struct amdgpu_bo *obj = (struct amdgpu_bo *)handle;
 
        if (obj) {
-               int r = amdgpu_bo_reserve(obj, false);
+               int r = amdgpu_bo_reserve(obj, true);
                if (likely(r == 0)) {
                        amdgpu_bo_kunmap(obj);
                        amdgpu_bo_unpin(obj);
@@ -239,7 +163,7 @@ static int amdgpu_cgs_gmap_gpu_mem(struct cgs_device *cgs_device, cgs_handle_t h
        min_offset = obj->placements[0].fpfn << PAGE_SHIFT;
        max_offset = obj->placements[0].lpfn << PAGE_SHIFT;
 
-       r = amdgpu_bo_reserve(obj, false);
+       r = amdgpu_bo_reserve(obj, true);
        if (unlikely(r != 0))
                return r;
        r = amdgpu_bo_pin_restricted(obj, obj->prefered_domains,
@@ -252,7 +176,7 @@ static int amdgpu_cgs_gunmap_gpu_mem(struct cgs_device *cgs_device, cgs_handle_t
 {
        int r;
        struct amdgpu_bo *obj = (struct amdgpu_bo *)handle;
-       r = amdgpu_bo_reserve(obj, false);
+       r = amdgpu_bo_reserve(obj, true);
        if (unlikely(r != 0))
                return r;
        r = amdgpu_bo_unpin(obj);
@@ -265,7 +189,7 @@ static int amdgpu_cgs_kmap_gpu_mem(struct cgs_device *cgs_device, cgs_handle_t h
 {
        int r;
        struct amdgpu_bo *obj = (struct amdgpu_bo *)handle;
-       r = amdgpu_bo_reserve(obj, false);
+       r = amdgpu_bo_reserve(obj, true);
        if (unlikely(r != 0))
                return r;
        r = amdgpu_bo_kmap(obj, map);
@@ -277,7 +201,7 @@ static int amdgpu_cgs_kunmap_gpu_mem(struct cgs_device *cgs_device, cgs_handle_t
 {
        int r;
        struct amdgpu_bo *obj = (struct amdgpu_bo *)handle;
-       r = amdgpu_bo_reserve(obj, false);
+       r = amdgpu_bo_reserve(obj, true);
        if (unlikely(r != 0))
                return r;
        amdgpu_bo_kunmap(obj);
@@ -349,62 +273,6 @@ static void amdgpu_cgs_write_ind_register(struct cgs_device *cgs_device,
        WARN(1, "Invalid indirect register space");
 }
 
-static uint8_t amdgpu_cgs_read_pci_config_byte(struct cgs_device *cgs_device, unsigned addr)
-{
-       CGS_FUNC_ADEV;
-       uint8_t val;
-       int ret = pci_read_config_byte(adev->pdev, addr, &val);
-       if (WARN(ret, "pci_read_config_byte error"))
-               return 0;
-       return val;
-}
-
-static uint16_t amdgpu_cgs_read_pci_config_word(struct cgs_device *cgs_device, unsigned addr)
-{
-       CGS_FUNC_ADEV;
-       uint16_t val;
-       int ret = pci_read_config_word(adev->pdev, addr, &val);
-       if (WARN(ret, "pci_read_config_word error"))
-               return 0;
-       return val;
-}
-
-static uint32_t amdgpu_cgs_read_pci_config_dword(struct cgs_device *cgs_device,
-                                                unsigned addr)
-{
-       CGS_FUNC_ADEV;
-       uint32_t val;
-       int ret = pci_read_config_dword(adev->pdev, addr, &val);
-       if (WARN(ret, "pci_read_config_dword error"))
-               return 0;
-       return val;
-}
-
-static void amdgpu_cgs_write_pci_config_byte(struct cgs_device *cgs_device, unsigned addr,
-                                            uint8_t value)
-{
-       CGS_FUNC_ADEV;
-       int ret = pci_write_config_byte(adev->pdev, addr, value);
-       WARN(ret, "pci_write_config_byte error");
-}
-
-static void amdgpu_cgs_write_pci_config_word(struct cgs_device *cgs_device, unsigned addr,
-                                            uint16_t value)
-{
-       CGS_FUNC_ADEV;
-       int ret = pci_write_config_word(adev->pdev, addr, value);
-       WARN(ret, "pci_write_config_word error");
-}
-
-static void amdgpu_cgs_write_pci_config_dword(struct cgs_device *cgs_device, unsigned addr,
-                                             uint32_t value)
-{
-       CGS_FUNC_ADEV;
-       int ret = pci_write_config_dword(adev->pdev, addr, value);
-       WARN(ret, "pci_write_config_dword error");
-}
-
-
 static int amdgpu_cgs_get_pci_resource(struct cgs_device *cgs_device,
                                       enum cgs_resource_type resource_type,
                                       uint64_t size,
@@ -477,56 +345,6 @@ static int amdgpu_cgs_atom_exec_cmd_table(struct cgs_device *cgs_device, unsigne
                adev->mode_info.atom_context, table, args);
 }
 
-static int amdgpu_cgs_create_pm_request(struct cgs_device *cgs_device, cgs_handle_t *request)
-{
-       /* TODO */
-       return 0;
-}
-
-static int amdgpu_cgs_destroy_pm_request(struct cgs_device *cgs_device, cgs_handle_t request)
-{
-       /* TODO */
-       return 0;
-}
-
-static int amdgpu_cgs_set_pm_request(struct cgs_device *cgs_device, cgs_handle_t request,
-                                    int active)
-{
-       /* TODO */
-       return 0;
-}
-
-static int amdgpu_cgs_pm_request_clock(struct cgs_device *cgs_device, cgs_handle_t request,
-                                      enum cgs_clock clock, unsigned freq)
-{
-       /* TODO */
-       return 0;
-}
-
-static int amdgpu_cgs_pm_request_engine(struct cgs_device *cgs_device, cgs_handle_t request,
-                                       enum cgs_engine engine, int powered)
-{
-       /* TODO */
-       return 0;
-}
-
-
-
-static int amdgpu_cgs_pm_query_clock_limits(struct cgs_device *cgs_device,
-                                           enum cgs_clock clock,
-                                           struct cgs_clock_limits *limits)
-{
-       /* TODO */
-       return 0;
-}
-
-static int amdgpu_cgs_set_camera_voltages(struct cgs_device *cgs_device, uint32_t mask,
-                                         const uint32_t *voltages)
-{
-       DRM_ERROR("not implemented");
-       return -EPERM;
-}
-
 struct cgs_irq_params {
        unsigned src_id;
        cgs_irq_source_set_func_t set;
@@ -1269,9 +1087,6 @@ static int amdgpu_cgs_call_acpi_method(struct cgs_device *cgs_device,
 }
 
 static const struct cgs_ops amdgpu_cgs_ops = {
-       .gpu_mem_info = amdgpu_cgs_gpu_mem_info,
-       .gmap_kmem = amdgpu_cgs_gmap_kmem,
-       .gunmap_kmem = amdgpu_cgs_gunmap_kmem,
        .alloc_gpu_mem = amdgpu_cgs_alloc_gpu_mem,
        .free_gpu_mem = amdgpu_cgs_free_gpu_mem,
        .gmap_gpu_mem = amdgpu_cgs_gmap_gpu_mem,
@@ -1282,23 +1097,10 @@ static const struct cgs_ops amdgpu_cgs_ops = {
        .write_register = amdgpu_cgs_write_register,
        .read_ind_register = amdgpu_cgs_read_ind_register,
        .write_ind_register = amdgpu_cgs_write_ind_register,
-       .read_pci_config_byte = amdgpu_cgs_read_pci_config_byte,
-       .read_pci_config_word = amdgpu_cgs_read_pci_config_word,
-       .read_pci_config_dword = amdgpu_cgs_read_pci_config_dword,
-       .write_pci_config_byte = amdgpu_cgs_write_pci_config_byte,
-       .write_pci_config_word = amdgpu_cgs_write_pci_config_word,
-       .write_pci_config_dword = amdgpu_cgs_write_pci_config_dword,
        .get_pci_resource = amdgpu_cgs_get_pci_resource,
        .atom_get_data_table = amdgpu_cgs_atom_get_data_table,
        .atom_get_cmd_table_revs = amdgpu_cgs_atom_get_cmd_table_revs,
        .atom_exec_cmd_table = amdgpu_cgs_atom_exec_cmd_table,
-       .create_pm_request = amdgpu_cgs_create_pm_request,
-       .destroy_pm_request = amdgpu_cgs_destroy_pm_request,
-       .set_pm_request = amdgpu_cgs_set_pm_request,
-       .pm_request_clock = amdgpu_cgs_pm_request_clock,
-       .pm_request_engine = amdgpu_cgs_pm_request_engine,
-       .pm_query_clock_limits = amdgpu_cgs_pm_query_clock_limits,
-       .set_camera_voltages = amdgpu_cgs_set_camera_voltages,
        .get_firmware_info = amdgpu_cgs_get_firmware_info,
        .rel_firmware = amdgpu_cgs_rel_firmware,
        .set_powergating_state = amdgpu_cgs_set_powergating_state,
index ec71b93205616a980ed4b32d406e538b20e676dd..4e6b9501ab0aac6cd4b33412f47ce23cf3301e47 100644 (file)
@@ -1074,6 +1074,7 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
        cs->out.handle = amdgpu_ctx_add_fence(p->ctx, ring, p->fence);
        job->uf_sequence = cs->out.handle;
        amdgpu_job_free_resources(job);
+       amdgpu_cs_parser_fini(p, 0, true);
 
        trace_amdgpu_cs_ioctl(job);
        amd_sched_entity_push_job(&job->base);
@@ -1129,7 +1130,10 @@ int amdgpu_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
                goto out;
 
        r = amdgpu_cs_submit(&parser, cs);
+       if (r)
+               goto out;
 
+       return 0;
 out:
        amdgpu_cs_parser_fini(&parser, r, reserved_buffers);
        return r;
index cf05006713531ce920c62ca105929907b7457fcd..90d1ac8a80f8b872dfbb15ac1b00d6a4c2e7c24b 100644 (file)
@@ -273,6 +273,9 @@ struct dma_fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx,
 
        spin_lock(&ctx->ring_lock);
 
+       if (seq == ~0ull)
+               seq = ctx->rings[ring->idx].sequence - 1;
+
        if (seq >= cring->sequence) {
                spin_unlock(&ctx->ring_lock);
                return ERR_PTR(-EINVAL);
index 483660742f75c9a9521a3bdef9f9bf3016639209..43ca16b6eee28e44e92944eaa8e398f4ccbc825e 100644 (file)
@@ -53,7 +53,6 @@
 #include "bif/bif_4_1_d.h"
 #include <linux/pci.h>
 #include <linux/firmware.h>
-#include "amdgpu_pm.h"
 
 static int amdgpu_debugfs_regs_init(struct amdgpu_device *adev);
 static void amdgpu_debugfs_regs_cleanup(struct amdgpu_device *adev);
@@ -350,7 +349,7 @@ static void amdgpu_vram_scratch_fini(struct amdgpu_device *adev)
        if (adev->vram_scratch.robj == NULL) {
                return;
        }
-       r = amdgpu_bo_reserve(adev->vram_scratch.robj, false);
+       r = amdgpu_bo_reserve(adev->vram_scratch.robj, true);
        if (likely(r == 0)) {
                amdgpu_bo_kunmap(adev->vram_scratch.robj);
                amdgpu_bo_unpin(adev->vram_scratch.robj);
@@ -422,12 +421,11 @@ static int amdgpu_doorbell_init(struct amdgpu_device *adev)
        if (adev->doorbell.num_doorbells == 0)
                return -EINVAL;
 
-       adev->doorbell.ptr = ioremap(adev->doorbell.base, adev->doorbell.num_doorbells * sizeof(u32));
-       if (adev->doorbell.ptr == NULL) {
+       adev->doorbell.ptr = ioremap(adev->doorbell.base,
+                                    adev->doorbell.num_doorbells *
+                                    sizeof(u32));
+       if (adev->doorbell.ptr == NULL)
                return -ENOMEM;
-       }
-       DRM_INFO("doorbell mmio base: 0x%08X\n", (uint32_t)adev->doorbell.base);
-       DRM_INFO("doorbell mmio size: %u\n", (unsigned)adev->doorbell.size);
 
        return 0;
 }
@@ -1584,9 +1582,6 @@ static int amdgpu_late_init(struct amdgpu_device *adev)
                }
        }
 
-       amdgpu_dpm_enable_uvd(adev, false);
-       amdgpu_dpm_enable_vce(adev, false);
-
        return 0;
 }
 
@@ -1854,7 +1849,6 @@ int amdgpu_device_init(struct amdgpu_device *adev,
 
        /* mutex initialization are all done here so we
         * can recall function without having locking issues */
-       mutex_init(&adev->vm_manager.lock);
        atomic_set(&adev->irq.ih.lock, 0);
        mutex_init(&adev->firmware.mutex);
        mutex_init(&adev->pm.mutex);
@@ -2071,7 +2065,8 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
 
        DRM_INFO("amdgpu: finishing device.\n");
        adev->shutdown = true;
-       drm_crtc_force_disable_all(adev->ddev);
+       if (adev->mode_info.mode_config_initialized)
+               drm_crtc_force_disable_all(adev->ddev);
        /* evict vram memory */
        amdgpu_bo_evict_vram(adev);
        amdgpu_ib_pool_fini(adev);
@@ -2146,7 +2141,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon)
 
                if (amdgpu_crtc->cursor_bo) {
                        struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
-                       r = amdgpu_bo_reserve(aobj, false);
+                       r = amdgpu_bo_reserve(aobj, true);
                        if (r == 0) {
                                amdgpu_bo_unpin(aobj);
                                amdgpu_bo_unreserve(aobj);
@@ -2159,7 +2154,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon)
                robj = gem_to_amdgpu_bo(rfb->obj);
                /* don't unpin kernel fb objects */
                if (!amdgpu_fbdev_robj_is_fb(adev, robj)) {
-                       r = amdgpu_bo_reserve(robj, false);
+                       r = amdgpu_bo_reserve(robj, true);
                        if (r == 0) {
                                amdgpu_bo_unpin(robj);
                                amdgpu_bo_unreserve(robj);
@@ -2216,7 +2211,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)
        struct drm_connector *connector;
        struct amdgpu_device *adev = dev->dev_private;
        struct drm_crtc *crtc;
-       int r;
+       int r = 0;
 
        if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
                return 0;
@@ -2228,11 +2223,8 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)
                pci_set_power_state(dev->pdev, PCI_D0);
                pci_restore_state(dev->pdev);
                r = pci_enable_device(dev->pdev);
-               if (r) {
-                       if (fbcon)
-                               console_unlock();
-                       return r;
-               }
+               if (r)
+                       goto unlock;
        }
        if (adev->is_atom_fw)
                amdgpu_atomfirmware_scratch_regs_restore(adev);
@@ -2249,7 +2241,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)
        r = amdgpu_resume(adev);
        if (r) {
                DRM_ERROR("amdgpu_resume failed (%d).\n", r);
-               return r;
+               goto unlock;
        }
        amdgpu_fence_driver_resume(adev);
 
@@ -2260,11 +2252,8 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)
        }
 
        r = amdgpu_late_init(adev);
-       if (r) {
-               if (fbcon)
-                       console_unlock();
-               return r;
-       }
+       if (r)
+               goto unlock;
 
        /* pin cursors */
        list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
@@ -2272,7 +2261,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)
 
                if (amdgpu_crtc->cursor_bo) {
                        struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
-                       r = amdgpu_bo_reserve(aobj, false);
+                       r = amdgpu_bo_reserve(aobj, true);
                        if (r == 0) {
                                r = amdgpu_bo_pin(aobj,
                                                  AMDGPU_GEM_DOMAIN_VRAM,
@@ -2314,12 +2303,14 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)
        dev->dev->power.disable_depth--;
 #endif
 
-       if (fbcon) {
+       if (fbcon)
                amdgpu_fbdev_set_suspend(adev, 0);
+
+unlock:
+       if (fbcon)
                console_unlock();
-       }
 
-       return 0;
+       return r;
 }
 
 static bool amdgpu_check_soft_reset(struct amdgpu_device *adev)
@@ -2430,25 +2421,37 @@ static int amdgpu_recover_vram_from_shadow(struct amdgpu_device *adev,
        uint32_t domain;
        int r;
 
-       if (!bo->shadow)
-               return 0;
+       if (!bo->shadow)
+               return 0;
+
+       r = amdgpu_bo_reserve(bo, true);
+       if (r)
+               return r;
+       domain = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type);
+       /* if bo has been evicted, then no need to recover */
+       if (domain == AMDGPU_GEM_DOMAIN_VRAM) {
+               r = amdgpu_bo_validate(bo->shadow);
+               if (r) {
+                       DRM_ERROR("bo validate failed!\n");
+                       goto err;
+               }
 
-       r = amdgpu_bo_reserve(bo, false);
-       if (r)
-               return r;
-       domain = amdgpu_mem_type_to_domain(bo->tbo.mem.mem_type);
-       /* if bo has been evicted, then no need to recover */
-       if (domain == AMDGPU_GEM_DOMAIN_VRAM) {
-               r = amdgpu_bo_restore_from_shadow(adev, ring, bo,
+               r = amdgpu_ttm_bind(&bo->shadow->tbo, &bo->shadow->tbo.mem);
+               if (r) {
+                       DRM_ERROR("%p bind failed\n", bo->shadow);
+                       goto err;
+               }
+
+               r = amdgpu_bo_restore_from_shadow(adev, ring, bo,
                                                 NULL, fence, true);
-               if (r) {
-                       DRM_ERROR("recover page table failed!\n");
-                       goto err;
-               }
-       }
+               if (r) {
+                       DRM_ERROR("recover page table failed!\n");
+                       goto err;
+               }
+       }
 err:
-       amdgpu_bo_unreserve(bo);
-       return r;
+       amdgpu_bo_unreserve(bo);
+       return r;
 }
 
 /**
@@ -2520,6 +2523,7 @@ int amdgpu_sriov_gpu_reset(struct amdgpu_device *adev, bool voluntary)
        ring = adev->mman.buffer_funcs_ring;
        mutex_lock(&adev->shadow_list_lock);
        list_for_each_entry_safe(bo, tmp, &adev->shadow_list, shadow_list) {
+               next = NULL;
                amdgpu_recover_vram_from_shadow(adev, ring, bo, &next);
                if (fence) {
                        r = dma_fence_wait(fence, false);
@@ -2593,7 +2597,7 @@ int amdgpu_gpu_reset(struct amdgpu_device *adev)
        for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
                struct amdgpu_ring *ring = adev->rings[i];
 
-               if (!ring)
+               if (!ring || !ring->sched.thread)
                        continue;
                kthread_park(ring->sched.thread);
                amd_sched_hw_job_reset(&ring->sched);
@@ -2666,6 +2670,7 @@ retry:
                        DRM_INFO("recover vram bo from shadow\n");
                        mutex_lock(&adev->shadow_list_lock);
                        list_for_each_entry_safe(bo, tmp, &adev->shadow_list, shadow_list) {
+                               next = NULL;
                                amdgpu_recover_vram_from_shadow(adev, ring, bo, &next);
                                if (fence) {
                                        r = dma_fence_wait(fence, false);
@@ -2688,7 +2693,8 @@ retry:
                }
                for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
                        struct amdgpu_ring *ring = adev->rings[i];
-                       if (!ring)
+
+                       if (!ring || !ring->sched.thread)
                                continue;
 
                        amd_sched_job_recovery(&ring->sched);
@@ -2697,7 +2703,7 @@ retry:
        } else {
                dev_err(adev->dev, "asic resume failed (%d).\n", r);
                for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
-                       if (adev->rings[i]) {
+                       if (adev->rings[i] && adev->rings[i]->sched.thread) {
                                kthread_unpark(adev->rings[i]->sched.thread);
                        }
                }
index 96926a221bd5280e668ec45c48c07a96e103286a..cdf2ab20166a2f1b86beb7a2d84e7d68cb2b5d6c 100644 (file)
@@ -123,7 +123,7 @@ static void amdgpu_unpin_work_func(struct work_struct *__work)
        int r;
 
        /* unpin of the old buffer */
-       r = amdgpu_bo_reserve(work->old_abo, false);
+       r = amdgpu_bo_reserve(work->old_abo, true);
        if (likely(r == 0)) {
                r = amdgpu_bo_unpin(work->old_abo);
                if (unlikely(r != 0)) {
@@ -138,52 +138,11 @@ static void amdgpu_unpin_work_func(struct work_struct *__work)
        kfree(work);
 }
 
-
-static void amdgpu_flip_work_cleanup(struct amdgpu_flip_work *work)
-{
-       int i;
-
-       amdgpu_bo_unref(&work->old_abo);
-       dma_fence_put(work->excl);
-       for (i = 0; i < work->shared_count; ++i)
-               dma_fence_put(work->shared[i]);
-       kfree(work->shared);
-       kfree(work);
-}
-
-static void amdgpu_flip_cleanup_unreserve(struct amdgpu_flip_work *work,
-                                         struct amdgpu_bo *new_abo)
-{
-       amdgpu_bo_unreserve(new_abo);
-       amdgpu_flip_work_cleanup(work);
-}
-
-static void amdgpu_flip_cleanup_unpin(struct amdgpu_flip_work *work,
-                                     struct amdgpu_bo *new_abo)
-{
-       if (unlikely(amdgpu_bo_unpin(new_abo) != 0))
-               DRM_ERROR("failed to unpin new abo in error path\n");
-       amdgpu_flip_cleanup_unreserve(work, new_abo);
-}
-
-void amdgpu_crtc_cleanup_flip_ctx(struct amdgpu_flip_work *work,
-                                 struct amdgpu_bo *new_abo)
-{
-       if (unlikely(amdgpu_bo_reserve(new_abo, false) != 0)) {
-               DRM_ERROR("failed to reserve new abo in error path\n");
-               amdgpu_flip_work_cleanup(work);
-               return;
-       }
-       amdgpu_flip_cleanup_unpin(work, new_abo);
-}
-
-int amdgpu_crtc_prepare_flip(struct drm_crtc *crtc,
-                            struct drm_framebuffer *fb,
-                            struct drm_pending_vblank_event *event,
-                            uint32_t page_flip_flags,
-                            uint32_t target,
-                            struct amdgpu_flip_work **work_p,
-                            struct amdgpu_bo **new_abo_p)
+int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc,
+                                struct drm_framebuffer *fb,
+                                struct drm_pending_vblank_event *event,
+                                uint32_t page_flip_flags, uint32_t target,
+                                struct drm_modeset_acquire_ctx *ctx)
 {
        struct drm_device *dev = crtc->dev;
        struct amdgpu_device *adev = dev->dev_private;
@@ -196,7 +155,7 @@ int amdgpu_crtc_prepare_flip(struct drm_crtc *crtc,
        unsigned long flags;
        u64 tiling_flags;
        u64 base;
-       int r;
+       int i, r;
 
        work = kzalloc(sizeof *work, GFP_KERNEL);
        if (work == NULL)
@@ -257,80 +216,41 @@ int amdgpu_crtc_prepare_flip(struct drm_crtc *crtc,
                spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
                r = -EBUSY;
                goto pflip_cleanup;
-
        }
-       spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
-
-       *work_p = work;
-       *new_abo_p = new_abo;
-
-       return 0;
-
-pflip_cleanup:
-       amdgpu_crtc_cleanup_flip_ctx(work, new_abo);
-       return r;
-
-unpin:
-       amdgpu_flip_cleanup_unpin(work, new_abo);
-       return r;
-
-unreserve:
-       amdgpu_flip_cleanup_unreserve(work, new_abo);
-       return r;
 
-cleanup:
-       amdgpu_flip_work_cleanup(work);
-       return r;
-
-}
-
-void amdgpu_crtc_submit_flip(struct drm_crtc *crtc,
-                            struct drm_framebuffer *fb,
-                            struct amdgpu_flip_work *work,
-                            struct amdgpu_bo *new_abo)
-{
-       unsigned long flags;
-       struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
-
-       spin_lock_irqsave(&crtc->dev->event_lock, flags);
        amdgpu_crtc->pflip_status = AMDGPU_FLIP_PENDING;
        amdgpu_crtc->pflip_works = work;
 
+
+       DRM_DEBUG_DRIVER("crtc:%d[%p], pflip_stat:AMDGPU_FLIP_PENDING, work: %p,\n",
+                                        amdgpu_crtc->crtc_id, amdgpu_crtc, work);
        /* update crtc fb */
        crtc->primary->fb = fb;
        spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
-
-       DRM_DEBUG_DRIVER(
-                       "crtc:%d[%p], pflip_stat:AMDGPU_FLIP_PENDING, work: %p,\n",
-                       amdgpu_crtc->crtc_id, amdgpu_crtc, work);
-
        amdgpu_flip_work_func(&work->flip_work.work);
-}
-
-int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc,
-                                struct drm_framebuffer *fb,
-                                struct drm_pending_vblank_event *event,
-                                uint32_t page_flip_flags,
-                                uint32_t target,
-                                struct drm_modeset_acquire_ctx *ctx)
-{
-       struct amdgpu_bo *new_abo;
-       struct amdgpu_flip_work *work;
-       int r;
+       return 0;
 
-       r = amdgpu_crtc_prepare_flip(crtc,
-                                    fb,
-                                    event,
-                                    page_flip_flags,
-                                    target,
-                                    &work,
-                                    &new_abo);
-       if (r)
-               return r;
+pflip_cleanup:
+       if (unlikely(amdgpu_bo_reserve(new_abo, false) != 0)) {
+               DRM_ERROR("failed to reserve new abo in error path\n");
+               goto cleanup;
+       }
+unpin:
+       if (unlikely(amdgpu_bo_unpin(new_abo) != 0)) {
+               DRM_ERROR("failed to unpin new abo in error path\n");
+       }
+unreserve:
+       amdgpu_bo_unreserve(new_abo);
 
-       amdgpu_crtc_submit_flip(crtc, fb, work, new_abo);
+cleanup:
+       amdgpu_bo_unref(&work->old_abo);
+       dma_fence_put(work->excl);
+       for (i = 0; i < work->shared_count; ++i)
+               dma_fence_put(work->shared[i]);
+       kfree(work->shared);
+       kfree(work);
 
-       return 0;
+       return r;
 }
 
 int amdgpu_crtc_set_config(struct drm_mode_set *set,
index 4e0f7d2d87f19f26ddf0900c3d5587f32cd62bce..f2d705e6a75aa4f092d3d98ff739927e15b6f26b 100644 (file)
  * - 3.11.0 - Add support for sensor query info (clocks, temp, etc).
  * - 3.12.0 - Add query for double offchip LDS buffers
  * - 3.13.0 - Add PRT support
+ * - 3.14.0 - Fix race in amdgpu_ctx_get_fence() and note new functionality
+ * - 3.15.0 - Export more gpu info for gfx9
  */
 #define KMS_DRIVER_MAJOR       3
-#define KMS_DRIVER_MINOR       13
+#define KMS_DRIVER_MINOR       15
 #define KMS_DRIVER_PATCHLEVEL  0
 
 int amdgpu_vram_limit = 0;
@@ -453,7 +455,9 @@ static const struct pci_device_id pciidlist[] = {
        {0x1002, 0x6861, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT},
        {0x1002, 0x6862, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT},
        {0x1002, 0x6863, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT},
+       {0x1002, 0x6864, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT},
        {0x1002, 0x6867, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT},
+       {0x1002, 0x6868, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT},
        {0x1002, 0x686c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT},
        {0x1002, 0x687f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_VEGA10|AMD_EXP_HW_SUPPORT},
        {0, 0, 0}
index a48142d930c641437fa2695e4793e7b3a814ec46..236d9950221b62665e8728941faa5793fc757980 100644 (file)
@@ -112,7 +112,7 @@ static void amdgpufb_destroy_pinned_object(struct drm_gem_object *gobj)
        struct amdgpu_bo *abo = gem_to_amdgpu_bo(gobj);
        int ret;
 
-       ret = amdgpu_bo_reserve(abo, false);
+       ret = amdgpu_bo_reserve(abo, true);
        if (likely(ret == 0)) {
                amdgpu_bo_kunmap(abo);
                amdgpu_bo_unpin(abo);
index 6d691abe889c82f94a1ff1eda95c8992916a8560..902e6015abca377bb10b057dbb0c8479b66be394 100644 (file)
@@ -27,6 +27,9 @@
  */
 #include <drm/drmP.h>
 #include <drm/amdgpu_drm.h>
+#ifdef CONFIG_X86
+#include <asm/set_memory.h>
+#endif
 #include "amdgpu.h"
 
 /*
@@ -183,7 +186,7 @@ void amdgpu_gart_table_vram_unpin(struct amdgpu_device *adev)
        if (adev->gart.robj == NULL) {
                return;
        }
-       r = amdgpu_bo_reserve(adev->gart.robj, false);
+       r = amdgpu_bo_reserve(adev->gart.robj, true);
        if (likely(r == 0)) {
                amdgpu_bo_kunmap(adev->gart.robj);
                amdgpu_bo_unpin(adev->gart.robj);
index 03a9c5cad222ab97748196ce699136ccbaceb129..94cb91cf93eb8b0b6652b6a271ca56063e0ab912 100644 (file)
@@ -139,6 +139,35 @@ int amdgpu_gem_object_open(struct drm_gem_object *obj,
        return 0;
 }
 
+static int amdgpu_gem_vm_check(void *param, struct amdgpu_bo *bo)
+{
+       /* if anything is swapped out don't swap it in here,
+          just abort and wait for the next CS */
+       if (!amdgpu_bo_gpu_accessible(bo))
+               return -ERESTARTSYS;
+
+       if (bo->shadow && !amdgpu_bo_gpu_accessible(bo->shadow))
+               return -ERESTARTSYS;
+
+       return 0;
+}
+
+static bool amdgpu_gem_vm_ready(struct amdgpu_device *adev,
+                               struct amdgpu_vm *vm,
+                               struct list_head *list)
+{
+       struct ttm_validate_buffer *entry;
+
+       list_for_each_entry(entry, list, head) {
+               struct amdgpu_bo *bo =
+                       container_of(entry->bo, struct amdgpu_bo, tbo);
+               if (amdgpu_gem_vm_check(NULL, bo))
+                       return false;
+       }
+
+       return !amdgpu_vm_validate_pt_bos(adev, vm, amdgpu_gem_vm_check, NULL);
+}
+
 void amdgpu_gem_object_close(struct drm_gem_object *obj,
                             struct drm_file *file_priv)
 {
@@ -148,15 +177,13 @@ void amdgpu_gem_object_close(struct drm_gem_object *obj,
        struct amdgpu_vm *vm = &fpriv->vm;
 
        struct amdgpu_bo_list_entry vm_pd;
-       struct list_head list, duplicates;
+       struct list_head list;
        struct ttm_validate_buffer tv;
        struct ww_acquire_ctx ticket;
        struct amdgpu_bo_va *bo_va;
-       struct dma_fence *fence = NULL;
        int r;
 
        INIT_LIST_HEAD(&list);
-       INIT_LIST_HEAD(&duplicates);
 
        tv.bo = &bo->tbo;
        tv.shared = true;
@@ -164,16 +191,18 @@ void amdgpu_gem_object_close(struct drm_gem_object *obj,
 
        amdgpu_vm_get_pd_bo(vm, &list, &vm_pd);
 
-       r = ttm_eu_reserve_buffers(&ticket, &list, false, &duplicates);
+       r = ttm_eu_reserve_buffers(&ticket, &list, false, NULL);
        if (r) {
                dev_err(adev->dev, "leaking bo va because "
                        "we fail to reserve bo (%d)\n", r);
                return;
        }
        bo_va = amdgpu_vm_bo_find(vm, bo);
-       if (bo_va) {
-               if (--bo_va->ref_count == 0) {
-                       amdgpu_vm_bo_rmv(adev, bo_va);
+       if (bo_va && --bo_va->ref_count == 0) {
+               amdgpu_vm_bo_rmv(adev, bo_va);
+
+               if (amdgpu_gem_vm_ready(adev, vm, &list)) {
+                       struct dma_fence *fence = NULL;
 
                        r = amdgpu_vm_clear_freed(adev, vm, &fence);
                        if (unlikely(r)) {
@@ -502,19 +531,6 @@ out:
        return r;
 }
 
-static int amdgpu_gem_va_check(void *param, struct amdgpu_bo *bo)
-{
-       /* if anything is swapped out don't swap it in here,
-          just abort and wait for the next CS */
-       if (!amdgpu_bo_gpu_accessible(bo))
-               return -ERESTARTSYS;
-
-       if (bo->shadow && !amdgpu_bo_gpu_accessible(bo->shadow))
-               return -ERESTARTSYS;
-
-       return 0;
-}
-
 /**
  * amdgpu_gem_va_update_vm -update the bo_va in its VM
  *
@@ -533,19 +549,9 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev,
                                    struct list_head *list,
                                    uint32_t operation)
 {
-       struct ttm_validate_buffer *entry;
        int r = -ERESTARTSYS;
 
-       list_for_each_entry(entry, list, head) {
-               struct amdgpu_bo *bo =
-                       container_of(entry->bo, struct amdgpu_bo, tbo);
-               if (amdgpu_gem_va_check(NULL, bo))
-                       goto error;
-       }
-
-       r = amdgpu_vm_validate_pt_bos(adev, vm, amdgpu_gem_va_check,
-                                     NULL);
-       if (r)
+       if (!amdgpu_gem_vm_ready(adev, vm, list))
                goto error;
 
        r = amdgpu_vm_update_directories(adev, vm);
index 0335c2f331e9b9fa356eede6d6428344d7c5b70b..f7d22c44034d43cce77ecd096c953e18aadc955d 100644 (file)
@@ -134,6 +134,15 @@ int amdgpu_gtt_mgr_alloc(struct ttm_mem_type_manager *man,
        return r;
 }
 
+void amdgpu_gtt_mgr_print(struct seq_file *m, struct ttm_mem_type_manager *man)
+{
+       struct amdgpu_device *adev = amdgpu_ttm_adev(man->bdev);
+       struct amdgpu_gtt_mgr *mgr = man->priv;
+
+       seq_printf(m, "man size:%llu pages, gtt available:%llu pages, usage:%lluMB\n",
+                  man->size, mgr->available, (u64)atomic64_read(&adev->gtt_usage) >> 20);
+
+}
 /**
  * amdgpu_gtt_mgr_new - allocate a new node
  *
index aab857d89d03fa3fb8b2e19dc73e19409cca42c0..6e4ae0d983c21db9ffac65340994ed6869407caf 100644 (file)
@@ -160,6 +160,8 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
                dev_err(adev->dev, "scheduling IB failed (%d).\n", r);
                return r;
        }
+       if (ring->funcs->emit_pipeline_sync && job && job->need_pipeline_sync)
+               amdgpu_ring_emit_pipeline_sync(ring);
 
        if (vm) {
                r = amdgpu_vm_flush(ring, job);
@@ -217,7 +219,8 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned num_ibs,
        if (r) {
                dev_err(adev->dev, "failed to emit fence (%d)\n", r);
                if (job && job->vm_id)
-                       amdgpu_vm_reset_id(adev, job->vm_id);
+                       amdgpu_vm_reset_id(adev, ring->funcs->vmhub,
+                                          job->vm_id);
                amdgpu_ring_undo(ring);
                return r;
        }
index 86a12424c162ca6eeec8412e7fc8fb8292e3f7ab..7570f2439a1175b6509b76121dbd4c5628502fbb 100644 (file)
@@ -57,6 +57,7 @@ int amdgpu_job_alloc(struct amdgpu_device *adev, unsigned num_ibs,
        (*job)->vm = vm;
        (*job)->ibs = (void *)&(*job)[1];
        (*job)->num_ibs = num_ibs;
+       (*job)->need_pipeline_sync = false;
 
        amdgpu_sync_create(&(*job)->sync);
 
@@ -139,7 +140,7 @@ static struct dma_fence *amdgpu_job_dependency(struct amd_sched_job *sched_job)
 
        struct dma_fence *fence = amdgpu_sync_get_fence(&job->sync);
 
-       if (fence == NULL && vm && !job->vm_id) {
+       while (fence == NULL && vm && !job->vm_id) {
                struct amdgpu_ring *ring = job->ring;
                int r;
 
@@ -152,6 +153,9 @@ static struct dma_fence *amdgpu_job_dependency(struct amd_sched_job *sched_job)
                fence = amdgpu_sync_get_fence(&job->sync);
        }
 
+       if (amd_sched_dependency_optimized(fence, sched_job->s_entity))
+               job->need_pipeline_sync = true;
+
        return fence;
 }
 
index 832be632478f0b36795eefec37a937cb014eb28e..96c34167078253b26d1ac0cfbc2f2036c07c487d 100644 (file)
@@ -545,11 +545,22 @@ static int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file
                        adev->gfx.config.double_offchip_lds_buf;
 
                if (amdgpu_ngg) {
-                       dev_info.prim_buf_gpu_addr = adev->gfx.ngg.buf[PRIM].gpu_addr;
-                       dev_info.pos_buf_gpu_addr = adev->gfx.ngg.buf[POS].gpu_addr;
-                       dev_info.cntl_sb_buf_gpu_addr = adev->gfx.ngg.buf[CNTL].gpu_addr;
-                       dev_info.param_buf_gpu_addr = adev->gfx.ngg.buf[PARAM].gpu_addr;
+                       dev_info.prim_buf_gpu_addr = adev->gfx.ngg.buf[NGG_PRIM].gpu_addr;
+                       dev_info.prim_buf_size = adev->gfx.ngg.buf[NGG_PRIM].size;
+                       dev_info.pos_buf_gpu_addr = adev->gfx.ngg.buf[NGG_POS].gpu_addr;
+                       dev_info.pos_buf_size = adev->gfx.ngg.buf[NGG_POS].size;
+                       dev_info.cntl_sb_buf_gpu_addr = adev->gfx.ngg.buf[NGG_CNTL].gpu_addr;
+                       dev_info.cntl_sb_buf_size = adev->gfx.ngg.buf[NGG_CNTL].size;
+                       dev_info.param_buf_gpu_addr = adev->gfx.ngg.buf[NGG_PARAM].gpu_addr;
+                       dev_info.param_buf_size = adev->gfx.ngg.buf[NGG_PARAM].size;
                }
+               dev_info.wave_front_size = adev->gfx.cu_info.wave_front_size;
+               dev_info.num_shader_visible_vgprs = adev->gfx.config.max_gprs;
+               dev_info.num_cu_per_sh = adev->gfx.config.max_cu_per_sh;
+               dev_info.num_tcc_blocks = adev->gfx.config.max_texture_channel_caches;
+               dev_info.gs_vgt_table_depth = adev->gfx.config.gs_vgt_table_depth;
+               dev_info.gs_prim_buffer_depth = adev->gfx.config.gs_prim_buffer_depth;
+               dev_info.max_gs_waves_per_vgt = adev->gfx.config.max_gs_threads;
 
                return copy_to_user(out, &dev_info,
                                    min((size_t)size, sizeof(dev_info))) ? -EFAULT : 0;
@@ -810,7 +821,7 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev,
 
        if (amdgpu_sriov_vf(adev)) {
                /* TODO: how to handle reserve failure */
-               BUG_ON(amdgpu_bo_reserve(adev->virt.csa_obj, false));
+               BUG_ON(amdgpu_bo_reserve(adev->virt.csa_obj, true));
                amdgpu_vm_bo_rmv(adev, fpriv->vm.csa_bo_va);
                fpriv->vm.csa_bo_va = NULL;
                amdgpu_bo_unreserve(adev->virt.csa_obj);
index db8f8dda209c7880b0ede9e79268a7c9726b3b5c..dbd10618ec20859ca2699529708c1490354d85c4 100644 (file)
@@ -597,21 +597,6 @@ int amdgpu_crtc_page_flip_target(struct drm_crtc *crtc,
                                 struct drm_pending_vblank_event *event,
                                 uint32_t page_flip_flags, uint32_t target,
                                 struct drm_modeset_acquire_ctx *ctx);
-void amdgpu_crtc_cleanup_flip_ctx(struct amdgpu_flip_work *work,
-                                 struct amdgpu_bo *new_abo);
-int amdgpu_crtc_prepare_flip(struct drm_crtc *crtc,
-                            struct drm_framebuffer *fb,
-                            struct drm_pending_vblank_event *event,
-                            uint32_t page_flip_flags,
-                            uint32_t target,
-                            struct amdgpu_flip_work **work,
-                            struct amdgpu_bo **new_abo);
-
-void amdgpu_crtc_submit_flip(struct drm_crtc *crtc,
-                            struct drm_framebuffer *fb,
-                            struct amdgpu_flip_work *work,
-                            struct amdgpu_bo *new_abo);
-
 extern const struct drm_mode_config_funcs amdgpu_mode_funcs;
 
 #endif
index cb89fff863c04c9536ec6b9667d58abb06c1b5a1..365883d7948d2ab8ab2bea71163f1eae2c1b2eb6 100644 (file)
@@ -295,7 +295,7 @@ void amdgpu_bo_free_kernel(struct amdgpu_bo **bo, u64 *gpu_addr,
        if (*bo == NULL)
                return;
 
-       if (likely(amdgpu_bo_reserve(*bo, false) == 0)) {
+       if (likely(amdgpu_bo_reserve(*bo, true) == 0)) {
                if (cpu_addr)
                        amdgpu_bo_kunmap(*bo);
 
@@ -543,6 +543,27 @@ err:
        return r;
 }
 
+int amdgpu_bo_validate(struct amdgpu_bo *bo)
+{
+       uint32_t domain;
+       int r;
+
+       if (bo->pin_count)
+               return 0;
+
+       domain = bo->prefered_domains;
+
+retry:
+       amdgpu_ttm_placement_from_domain(bo, domain);
+       r = ttm_bo_validate(&bo->tbo, &bo->placement, false, false);
+       if (unlikely(r == -ENOMEM) && domain != bo->allowed_domains) {
+               domain = bo->allowed_domains;
+               goto retry;
+       }
+
+       return r;
+}
+
 int amdgpu_bo_restore_from_shadow(struct amdgpu_device *adev,
                                  struct amdgpu_ring *ring,
                                  struct amdgpu_bo *bo,
index 15a723adca764903f21ef0f220852c70093b0a36..382485115b0641b059602d21fa92be33281ac8de 100644 (file)
@@ -175,6 +175,7 @@ int amdgpu_bo_backup_to_shadow(struct amdgpu_device *adev,
                               struct amdgpu_bo *bo,
                               struct reservation_object *resv,
                               struct dma_fence **fence, bool direct);
+int amdgpu_bo_validate(struct amdgpu_bo *bo);
 int amdgpu_bo_restore_from_shadow(struct amdgpu_device *adev,
                                  struct amdgpu_ring *ring,
                                  struct amdgpu_bo *bo,
index 990fde2cf4fd366504ea30ad0b4039bb938c77f4..7df503aedb692b86c7111bd81f63ac60eba793c4 100644 (file)
@@ -867,8 +867,7 @@ static ssize_t amdgpu_hwmon_get_pwm1_enable(struct device *dev,
 
        pwm_mode = amdgpu_dpm_get_fan_control_mode(adev);
 
-       /* never 0 (full-speed), fuse or smc-controlled always */
-       return sprintf(buf, "%i\n", pwm_mode == FDO_PWM_MODE_STATIC ? 1 : 2);
+       return sprintf(buf, "%i\n", pwm_mode);
 }
 
 static ssize_t amdgpu_hwmon_set_pwm1_enable(struct device *dev,
@@ -887,14 +886,7 @@ static ssize_t amdgpu_hwmon_set_pwm1_enable(struct device *dev,
        if (err)
                return err;
 
-       switch (value) {
-       case 1: /* manual, percent-based */
-               amdgpu_dpm_set_fan_control_mode(adev, FDO_PWM_MODE_STATIC);
-               break;
-       default: /* disable */
-               amdgpu_dpm_set_fan_control_mode(adev, 0);
-               break;
-       }
+       amdgpu_dpm_set_fan_control_mode(adev, value);
 
        return count;
 }
index 3826d5aea0a6a55d00d9aae2bda9f7b04489ec60..6bdc866570ab8d67575ac3734d1f67573978df79 100644 (file)
@@ -113,7 +113,7 @@ void amdgpu_gem_prime_unpin(struct drm_gem_object *obj)
        struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj);
        int ret = 0;
 
-       ret = amdgpu_bo_reserve(bo, false);
+       ret = amdgpu_bo_reserve(bo, true);
        if (unlikely(ret != 0))
                return;
 
index ed6e5799016e3eb0931baa261af65e7b36b4f80f..ac5e92e5d59d3c69c46b36992558d683ac56f7c5 100644 (file)
@@ -55,6 +55,8 @@ static int psp_sw_init(void *handle)
                psp->bootloader_load_sos = psp_v3_1_bootloader_load_sos;
                psp->prep_cmd_buf = psp_v3_1_prep_cmd_buf;
                psp->ring_init = psp_v3_1_ring_init;
+               psp->ring_create = psp_v3_1_ring_create;
+               psp->ring_destroy = psp_v3_1_ring_destroy;
                psp->cmd_submit = psp_v3_1_cmd_submit;
                psp->compare_sram_data = psp_v3_1_compare_sram_data;
                psp->smu_reload_quirk = psp_v3_1_smu_reload_quirk;
@@ -152,11 +154,6 @@ static void psp_prep_tmr_cmd_buf(struct psp_gfx_cmd_resp *cmd,
 static int psp_tmr_init(struct psp_context *psp)
 {
        int ret;
-       struct psp_gfx_cmd_resp *cmd;
-
-       cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
-       if (!cmd)
-               return -ENOMEM;
 
        /*
         * Allocate 3M memory aligned to 1M from Frame Buffer (local
@@ -168,22 +165,30 @@ static int psp_tmr_init(struct psp_context *psp)
        ret = amdgpu_bo_create_kernel(psp->adev, 0x300000, 0x100000,
                                      AMDGPU_GEM_DOMAIN_VRAM,
                                      &psp->tmr_bo, &psp->tmr_mc_addr, &psp->tmr_buf);
-       if (ret)
-               goto failed;
+
+       return ret;
+}
+
+static int psp_tmr_load(struct psp_context *psp)
+{
+       int ret;
+       struct psp_gfx_cmd_resp *cmd;
+
+       cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
+       if (!cmd)
+               return -ENOMEM;
 
        psp_prep_tmr_cmd_buf(cmd, psp->tmr_mc_addr, 0x300000);
 
        ret = psp_cmd_submit_buf(psp, NULL, cmd,
                                 psp->fence_buf_mc_addr, 1);
        if (ret)
-               goto failed_mem;
+               goto failed;
 
        kfree(cmd);
 
        return 0;
 
-failed_mem:
-       amdgpu_bo_free_kernel(&psp->tmr_bo, &psp->tmr_mc_addr, &psp->tmr_buf);
 failed:
        kfree(cmd);
        return ret;
@@ -203,104 +208,78 @@ static void psp_prep_asd_cmd_buf(struct psp_gfx_cmd_resp *cmd,
        cmd->cmd.cmd_load_ta.cmd_buf_len = shared_size;
 }
 
-static int psp_asd_load(struct psp_context *psp)
+static int psp_asd_init(struct psp_context *psp)
 {
        int ret;
-       struct amdgpu_bo *asd_bo, *asd_shared_bo;
-       uint64_t asd_mc_addr, asd_shared_mc_addr;
-       void *asd_buf, *asd_shared_buf;
-       struct psp_gfx_cmd_resp *cmd;
-
-       cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
-       if (!cmd)
-               return -ENOMEM;
 
        /*
         * Allocate 16k memory aligned to 4k from Frame Buffer (local
         * physical) for shared ASD <-> Driver
         */
-       ret = amdgpu_bo_create_kernel(psp->adev, PSP_ASD_SHARED_MEM_SIZE, PAGE_SIZE,
-                                     AMDGPU_GEM_DOMAIN_VRAM,
-                                     &asd_shared_bo, &asd_shared_mc_addr, &asd_buf);
-       if (ret)
-               goto failed;
+       ret = amdgpu_bo_create_kernel(psp->adev, PSP_ASD_SHARED_MEM_SIZE,
+                                     PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM,
+                                     &psp->asd_shared_bo,
+                                     &psp->asd_shared_mc_addr,
+                                     &psp->asd_shared_buf);
 
-       /*
-        * Allocate 256k memory aligned to 4k from Frame Buffer (local
-        * physical) for ASD firmware
-        */
-       ret = amdgpu_bo_create_kernel(psp->adev, PSP_ASD_BIN_SIZE, PAGE_SIZE,
-                                     AMDGPU_GEM_DOMAIN_VRAM,
-                                     &asd_bo, &asd_mc_addr, &asd_buf);
-       if (ret)
-               goto failed_mem;
+       return ret;
+}
+
+static int psp_asd_load(struct psp_context *psp)
+{
+       int ret;
+       struct psp_gfx_cmd_resp *cmd;
+
+       cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
+       if (!cmd)
+               return -ENOMEM;
 
-       memcpy(asd_buf, psp->asd_start_addr, psp->asd_ucode_size);
+       memset(psp->fw_pri_buf, 0, PSP_1_MEG);
+       memcpy(psp->fw_pri_buf, psp->asd_start_addr, psp->asd_ucode_size);
 
-       psp_prep_asd_cmd_buf(cmd, asd_mc_addr, asd_shared_mc_addr,
+       psp_prep_asd_cmd_buf(cmd, psp->fw_pri_mc_addr, psp->asd_shared_mc_addr,
                             psp->asd_ucode_size, PSP_ASD_SHARED_MEM_SIZE);
 
        ret = psp_cmd_submit_buf(psp, NULL, cmd,
                                 psp->fence_buf_mc_addr, 2);
-       if (ret)
-               goto failed_mem1;
 
-       amdgpu_bo_free_kernel(&asd_bo, &asd_mc_addr, &asd_buf);
-       amdgpu_bo_free_kernel(&asd_shared_bo, &asd_shared_mc_addr, &asd_shared_buf);
        kfree(cmd);
 
-       return 0;
-
-failed_mem1:
-       amdgpu_bo_free_kernel(&asd_bo, &asd_mc_addr, &asd_buf);
-failed_mem:
-       amdgpu_bo_free_kernel(&asd_shared_bo, &asd_shared_mc_addr, &asd_shared_buf);
-failed:
-       kfree(cmd);
        return ret;
 }
 
-static int psp_load_fw(struct amdgpu_device *adev)
+static int psp_hw_start(struct psp_context *psp)
 {
        int ret;
-       struct psp_gfx_cmd_resp *cmd;
-       int i;
-       struct amdgpu_firmware_info *ucode;
-       struct psp_context *psp = &adev->psp;
-
-       cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
-       if (!cmd)
-               return -ENOMEM;
 
        ret = psp_bootloader_load_sysdrv(psp);
        if (ret)
-               goto failed;
+               return ret;
 
        ret = psp_bootloader_load_sos(psp);
        if (ret)
-               goto failed;
-
-       ret = psp_ring_init(psp, PSP_RING_TYPE__KM);
-       if (ret)
-               goto failed;
+               return ret;
 
-       ret = amdgpu_bo_create_kernel(adev, PSP_FENCE_BUFFER_SIZE, PAGE_SIZE,
-                                     AMDGPU_GEM_DOMAIN_VRAM,
-                                     &psp->fence_buf_bo,
-                                     &psp->fence_buf_mc_addr,
-                                     &psp->fence_buf);
+       ret = psp_ring_create(psp, PSP_RING_TYPE__KM);
        if (ret)
-               goto failed;
-
-       memset(psp->fence_buf, 0, PSP_FENCE_BUFFER_SIZE);
+               return ret;
 
-       ret = psp_tmr_init(psp);
+       ret = psp_tmr_load(psp);
        if (ret)
-               goto failed_mem;
+               return ret;
 
        ret = psp_asd_load(psp);
        if (ret)
-               goto failed_mem;
+               return ret;
+
+       return 0;
+}
+
+static int psp_np_fw_load(struct psp_context *psp)
+{
+       int i, ret;
+       struct amdgpu_firmware_info *ucode;
+       struct amdgpu_device* adev = psp->adev;
 
        for (i = 0; i < adev->firmware.max_ucodes; i++) {
                ucode = &adev->firmware.ucode[i];
@@ -310,15 +289,21 @@ static int psp_load_fw(struct amdgpu_device *adev)
                if (ucode->ucode_id == AMDGPU_UCODE_ID_SMC &&
                    psp_smu_reload_quirk(psp))
                        continue;
+               if (amdgpu_sriov_vf(adev) &&
+                  (ucode->ucode_id == AMDGPU_UCODE_ID_SDMA0
+                   || ucode->ucode_id == AMDGPU_UCODE_ID_SDMA1
+                   || ucode->ucode_id == AMDGPU_UCODE_ID_RLC_G))
+                       /*skip ucode loading in SRIOV VF */
+                       continue;
 
-               ret = psp_prep_cmd_buf(ucode, cmd);
+               ret = psp_prep_cmd_buf(ucode, psp->cmd);
                if (ret)
-                       goto failed_mem;
+                       return ret;
 
-               ret = psp_cmd_submit_buf(psp, ucode, cmd,
+               ret = psp_cmd_submit_buf(psp, ucode, psp->cmd,
                                         psp->fence_buf_mc_addr, i + 3);
                if (ret)
-                       goto failed_mem;
+                       return ret;
 
 #if 0
                /* check if firmware loaded sucessfully */
@@ -327,8 +312,59 @@ static int psp_load_fw(struct amdgpu_device *adev)
 #endif
        }
 
-       amdgpu_bo_free_kernel(&psp->fence_buf_bo,
-                             &psp->fence_buf_mc_addr, &psp->fence_buf);
+       return 0;
+}
+
+static int psp_load_fw(struct amdgpu_device *adev)
+{
+       int ret;
+       struct psp_context *psp = &adev->psp;
+       struct psp_gfx_cmd_resp *cmd;
+
+       cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
+       if (!cmd)
+               return -ENOMEM;
+
+       psp->cmd = cmd;
+
+       ret = amdgpu_bo_create_kernel(adev, PSP_1_MEG, PSP_1_MEG,
+                                     AMDGPU_GEM_DOMAIN_GTT,
+                                     &psp->fw_pri_bo,
+                                     &psp->fw_pri_mc_addr,
+                                     &psp->fw_pri_buf);
+       if (ret)
+               goto failed;
+
+       ret = amdgpu_bo_create_kernel(adev, PSP_FENCE_BUFFER_SIZE, PAGE_SIZE,
+                                     AMDGPU_GEM_DOMAIN_VRAM,
+                                     &psp->fence_buf_bo,
+                                     &psp->fence_buf_mc_addr,
+                                     &psp->fence_buf);
+       if (ret)
+               goto failed_mem1;
+
+       memset(psp->fence_buf, 0, PSP_FENCE_BUFFER_SIZE);
+
+       ret = psp_ring_init(psp, PSP_RING_TYPE__KM);
+       if (ret)
+               goto failed_mem1;
+
+       ret = psp_tmr_init(psp);
+       if (ret)
+               goto failed_mem;
+
+       ret = psp_asd_init(psp);
+       if (ret)
+               goto failed_mem;
+
+       ret = psp_hw_start(psp);
+       if (ret)
+               goto failed_mem;
+
+       ret = psp_np_fw_load(psp);
+       if (ret)
+               goto failed_mem;
+
        kfree(cmd);
 
        return 0;
@@ -336,6 +372,9 @@ static int psp_load_fw(struct amdgpu_device *adev)
 failed_mem:
        amdgpu_bo_free_kernel(&psp->fence_buf_bo,
                              &psp->fence_buf_mc_addr, &psp->fence_buf);
+failed_mem1:
+       amdgpu_bo_free_kernel(&psp->fw_pri_bo,
+                             &psp->fw_pri_mc_addr, &psp->fw_pri_buf);
 failed:
        kfree(cmd);
        return ret;
@@ -379,12 +418,24 @@ static int psp_hw_fini(void *handle)
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        struct psp_context *psp = &adev->psp;
 
-       if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP)
-               amdgpu_ucode_fini_bo(adev);
+       if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
+               return 0;
+
+       amdgpu_ucode_fini_bo(adev);
+
+       psp_ring_destroy(psp, PSP_RING_TYPE__KM);
 
        if (psp->tmr_buf)
                amdgpu_bo_free_kernel(&psp->tmr_bo, &psp->tmr_mc_addr, &psp->tmr_buf);
 
+       if (psp->fw_pri_buf)
+               amdgpu_bo_free_kernel(&psp->fw_pri_bo,
+                                     &psp->fw_pri_mc_addr, &psp->fw_pri_buf);
+
+       if (psp->fence_buf_bo)
+               amdgpu_bo_free_kernel(&psp->fence_buf_bo,
+                                     &psp->fence_buf_mc_addr, &psp->fence_buf);
+
        return 0;
 }
 
@@ -397,18 +448,30 @@ static int psp_resume(void *handle)
 {
        int ret;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+       struct psp_context *psp = &adev->psp;
 
        if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
                return 0;
 
+       DRM_INFO("PSP is resuming...\n");
+
        mutex_lock(&adev->firmware.mutex);
 
-       ret = psp_load_fw(adev);
+       ret = psp_hw_start(psp);
        if (ret)
-               DRM_ERROR("PSP resume failed\n");
+               goto failed;
+
+       ret = psp_np_fw_load(psp);
+       if (ret)
+               goto failed;
 
        mutex_unlock(&adev->firmware.mutex);
 
+       return 0;
+
+failed:
+       DRM_ERROR("PSP resume failed\n");
+       mutex_unlock(&adev->firmware.mutex);
        return ret;
 }
 
index e9f35e025b59f88d3e6515e76eb1df7ab3e4ff34..0301e4e0b2975945ebe788af79bfa497729b1fee 100644 (file)
@@ -30,8 +30,8 @@
 
 #define PSP_FENCE_BUFFER_SIZE  0x1000
 #define PSP_CMD_BUFFER_SIZE    0x1000
-#define PSP_ASD_BIN_SIZE       0x40000
 #define PSP_ASD_SHARED_MEM_SIZE        0x4000
+#define PSP_1_MEG              0x100000
 
 enum psp_ring_type
 {
@@ -57,6 +57,7 @@ struct psp_context
 {
        struct amdgpu_device            *adev;
        struct psp_ring                 km_ring;
+       struct psp_gfx_cmd_resp         *cmd;
 
        int (*init_microcode)(struct psp_context *psp);
        int (*bootloader_load_sysdrv)(struct psp_context *psp);
@@ -64,6 +65,9 @@ struct psp_context
        int (*prep_cmd_buf)(struct amdgpu_firmware_info *ucode,
                            struct psp_gfx_cmd_resp *cmd);
        int (*ring_init)(struct psp_context *psp, enum psp_ring_type ring_type);
+       int (*ring_create)(struct psp_context *psp, enum psp_ring_type ring_type);
+       int (*ring_destroy)(struct psp_context *psp,
+                           enum psp_ring_type ring_type);
        int (*cmd_submit)(struct psp_context *psp, struct amdgpu_firmware_info *ucode,
                          uint64_t cmd_buf_mc_addr, uint64_t fence_mc_addr, int index);
        bool (*compare_sram_data)(struct psp_context *psp,
@@ -71,6 +75,11 @@ struct psp_context
                                  enum AMDGPU_UCODE_ID ucode_type);
        bool (*smu_reload_quirk)(struct psp_context *psp);
 
+       /* fence buffer */
+       struct amdgpu_bo                *fw_pri_bo;
+       uint64_t                        fw_pri_mc_addr;
+       void                            *fw_pri_buf;
+
        /* sos firmware */
        const struct firmware           *sos_fw;
        uint32_t                        sos_fw_version;
@@ -85,12 +94,15 @@ struct psp_context
        uint64_t                        tmr_mc_addr;
        void                            *tmr_buf;
 
-       /* asd firmware */
+       /* asd firmware and buffer */
        const struct firmware           *asd_fw;
        uint32_t                        asd_fw_version;
        uint32_t                        asd_feature_version;
        uint32_t                        asd_ucode_size;
        uint8_t                         *asd_start_addr;
+       struct amdgpu_bo                *asd_shared_bo;
+       uint64_t                        asd_shared_mc_addr;
+       void                            *asd_shared_buf;
 
        /* fence buffer */
        struct amdgpu_bo                *fence_buf_bo;
@@ -105,6 +117,8 @@ struct amdgpu_psp_funcs {
 
 #define psp_prep_cmd_buf(ucode, type) (psp)->prep_cmd_buf((ucode), (type))
 #define psp_ring_init(psp, type) (psp)->ring_init((psp), (type))
+#define psp_ring_create(psp, type) (psp)->ring_create((psp), (type))
+#define psp_ring_destroy(psp, type) ((psp)->ring_destroy((psp), (type)))
 #define psp_cmd_submit(psp, ucode, cmd_mc, fence_mc, index) \
                (psp)->cmd_submit((psp), (ucode), (cmd_mc), (fence_mc), (index))
 #define psp_compare_sram_data(psp, ucode, type) \
index 63e56398ca9ae0c873589a740582c459ffe4c5a1..944443c5b90a20018f3f804c163ac5ef10fe32c2 100644 (file)
@@ -99,6 +99,7 @@ struct amdgpu_ring_funcs {
        uint32_t                align_mask;
        u32                     nop;
        bool                    support_64bit_ptrs;
+       unsigned                vmhub;
 
        /* ring read/write ptr handling */
        u64 (*get_rptr)(struct amdgpu_ring *ring);
@@ -178,6 +179,7 @@ struct amdgpu_ring {
        unsigned                cond_exe_offs;
        u64                     cond_exe_gpu_addr;
        volatile u32            *cond_exe_cpu_addr;
+       unsigned                vm_inv_eng;
 #if defined(CONFIG_DEBUG_FS)
        struct dentry *ent;
 #endif
index de9f919ae33695a010eb67f8d1eda118ed5444de..5ca75a456ad2ad94e81773fc209e1977dc18aa9f 100644 (file)
@@ -130,7 +130,7 @@ int amdgpu_sa_bo_manager_suspend(struct amdgpu_device *adev,
                return -EINVAL;
        }
 
-       r = amdgpu_bo_reserve(sa_manager->bo, false);
+       r = amdgpu_bo_reserve(sa_manager->bo, true);
        if (!r) {
                amdgpu_bo_kunmap(sa_manager->bo);
                amdgpu_bo_unpin(sa_manager->bo);
index ee9d0f346d75341197c9a50747c664d1c3bc77c4..8601904e670ae7cf094a341c19abb76404fb3ec6 100644 (file)
@@ -190,26 +190,29 @@ TRACE_EVENT(amdgpu_sched_run_job,
 
 
 TRACE_EVENT(amdgpu_vm_grab_id,
-           TP_PROTO(struct amdgpu_vm *vm, int ring, struct amdgpu_job *job),
+           TP_PROTO(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
+                    struct amdgpu_job *job),
            TP_ARGS(vm, ring, job),
            TP_STRUCT__entry(
                             __field(struct amdgpu_vm *, vm)
                             __field(u32, ring)
-                            __field(u32, vmid)
+                            __field(u32, vm_id)
+                            __field(u32, vm_hub)
                             __field(u64, pd_addr)
                             __field(u32, needs_flush)
                             ),
 
            TP_fast_assign(
                           __entry->vm = vm;
-                          __entry->ring = ring;
-                          __entry->vmid = job->vm_id;
+                          __entry->ring = ring->idx;
+                          __entry->vm_id = job->vm_id;
+                          __entry->vm_hub = ring->funcs->vmhub,
                           __entry->pd_addr = job->vm_pd_addr;
                           __entry->needs_flush = job->vm_needs_flush;
                           ),
-           TP_printk("vm=%p, ring=%u, id=%u, pd_addr=%010Lx needs_flush=%u",
-                     __entry->vm, __entry->ring, __entry->vmid,
-                     __entry->pd_addr, __entry->needs_flush)
+           TP_printk("vm=%p, ring=%u, id=%u, hub=%u, pd_addr=%010Lx needs_flush=%u",
+                     __entry->vm, __entry->ring, __entry->vm_id,
+                     __entry->vm_hub, __entry->pd_addr, __entry->needs_flush)
 );
 
 TRACE_EVENT(amdgpu_vm_bo_map,
@@ -331,21 +334,25 @@ TRACE_EVENT(amdgpu_vm_copy_ptes,
 );
 
 TRACE_EVENT(amdgpu_vm_flush,
-           TP_PROTO(uint64_t pd_addr, unsigned ring, unsigned id),
-           TP_ARGS(pd_addr, ring, id),
+           TP_PROTO(struct amdgpu_ring *ring, unsigned vm_id,
+                    uint64_t pd_addr),
+           TP_ARGS(ring, vm_id, pd_addr),
            TP_STRUCT__entry(
-                            __field(u64, pd_addr)
                             __field(u32, ring)
-                            __field(u32, id)
+                            __field(u32, vm_id)
+                            __field(u32, vm_hub)
+                            __field(u64, pd_addr)
                             ),
 
            TP_fast_assign(
+                          __entry->ring = ring->idx;
+                          __entry->vm_id = vm_id;
+                          __entry->vm_hub = ring->funcs->vmhub;
                           __entry->pd_addr = pd_addr;
-                          __entry->ring = ring;
-                          __entry->id = id;
                           ),
-           TP_printk("ring=%u, id=%u, pd_addr=%010Lx",
-                     __entry->ring, __entry->id, __entry->pd_addr)
+           TP_printk("ring=%u, id=%u, hub=%u, pd_addr=%010Lx",
+                     __entry->ring, __entry->vm_id,
+                     __entry->vm_hub,__entry->pd_addr)
 );
 
 TRACE_EVENT(amdgpu_bo_list_set,
index 35d53a0d9ba685d3b2ce038506481d94321fb1a8..5db0230e45c6db9c2604547346aa715afcb8cdd0 100644 (file)
@@ -203,7 +203,9 @@ static void amdgpu_evict_flags(struct ttm_buffer_object *bo,
        abo = container_of(bo, struct amdgpu_bo, tbo);
        switch (bo->mem.mem_type) {
        case TTM_PL_VRAM:
-               if (adev->mman.buffer_funcs_ring->ready == false) {
+               if (adev->mman.buffer_funcs &&
+                   adev->mman.buffer_funcs_ring &&
+                   adev->mman.buffer_funcs_ring->ready == false) {
                        amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_CPU);
                } else {
                        amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_GTT);
@@ -763,7 +765,7 @@ int amdgpu_ttm_recover_gart(struct amdgpu_device *adev)
 {
        struct amdgpu_ttm_tt *gtt, *tmp;
        struct ttm_mem_reg bo_mem;
-       uint32_t flags;
+       uint64_t flags;
        int r;
 
        bo_mem.mem_type = TTM_PL_TT;
@@ -1038,11 +1040,17 @@ uint64_t amdgpu_ttm_tt_pte_flags(struct amdgpu_device *adev, struct ttm_tt *ttm,
 static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo,
                                            const struct ttm_place *place)
 {
-       if (bo->mem.mem_type == TTM_PL_VRAM &&
-           bo->mem.start == AMDGPU_BO_INVALID_OFFSET) {
-               unsigned long num_pages = bo->mem.num_pages;
-               struct drm_mm_node *node = bo->mem.mm_node;
+       unsigned long num_pages = bo->mem.num_pages;
+       struct drm_mm_node *node = bo->mem.mm_node;
+
+       if (bo->mem.start != AMDGPU_BO_INVALID_OFFSET)
+               return ttm_bo_eviction_valuable(bo, place);
+
+       switch (bo->mem.mem_type) {
+       case TTM_PL_TT:
+               return true;
 
+       case TTM_PL_VRAM:
                /* Check each drm MM node individually */
                while (num_pages) {
                        if (place->fpfn < (node->start + node->size) &&
@@ -1052,8 +1060,10 @@ static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo,
                        num_pages -= node->size;
                        ++node;
                }
+               break;
 
-               return false;
+       default:
+               break;
        }
 
        return ttm_bo_eviction_valuable(bo, place);
@@ -1188,7 +1198,7 @@ void amdgpu_ttm_fini(struct amdgpu_device *adev)
                return;
        amdgpu_ttm_debugfs_fini(adev);
        if (adev->stollen_vga_memory) {
-               r = amdgpu_bo_reserve(adev->stollen_vga_memory, false);
+               r = amdgpu_bo_reserve(adev->stollen_vga_memory, true);
                if (r == 0) {
                        amdgpu_bo_unpin(adev->stollen_vga_memory);
                        amdgpu_bo_unreserve(adev->stollen_vga_memory);
@@ -1401,6 +1411,8 @@ error_free:
 
 #if defined(CONFIG_DEBUG_FS)
 
+extern void amdgpu_gtt_mgr_print(struct seq_file *m, struct ttm_mem_type_manager
+                                *man);
 static int amdgpu_mm_dump_table(struct seq_file *m, void *data)
 {
        struct drm_info_node *node = (struct drm_info_node *)m->private;
@@ -1414,11 +1426,17 @@ static int amdgpu_mm_dump_table(struct seq_file *m, void *data)
        spin_lock(&glob->lru_lock);
        drm_mm_print(mm, &p);
        spin_unlock(&glob->lru_lock);
-       if (ttm_pl == TTM_PL_VRAM)
+       switch (ttm_pl) {
+       case TTM_PL_VRAM:
                seq_printf(m, "man size:%llu pages, ram usage:%lluMB, vis usage:%lluMB\n",
                           adev->mman.bdev.man[ttm_pl].size,
                           (u64)atomic64_read(&adev->vram_usage) >> 20,
                           (u64)atomic64_read(&adev->vram_vis_usage) >> 20);
+               break;
+       case TTM_PL_TT:
+               amdgpu_gtt_mgr_print(m, &adev->mman.bdev.man[TTM_PL_TT]);
+               break;
+       }
        return 0;
 }
 
index a1891c93cdbf8780f110c5064ac2332c4b46467c..dfd1c98efa7c2116cf1fdb54c7d2a5443367023e 100644 (file)
@@ -382,10 +382,14 @@ int amdgpu_ucode_init_bo(struct amdgpu_device *adev)
         * if SMU loaded firmware, it needn't add SMC, UVD, and VCE
         * ucode info here
         */
-       if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
-               adev->firmware.max_ucodes = AMDGPU_UCODE_ID_MAXIMUM - 4;
-       else
+       if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP) {
+               if (amdgpu_sriov_vf(adev))
+                       adev->firmware.max_ucodes = AMDGPU_UCODE_ID_MAXIMUM - 3;
+               else
+                       adev->firmware.max_ucodes = AMDGPU_UCODE_ID_MAXIMUM - 4;
+       } else {
                adev->firmware.max_ucodes = AMDGPU_UCODE_ID_MAXIMUM;
+       }
 
        for (i = 0; i < adev->firmware.max_ucodes; i++) {
                ucode = &adev->firmware.ucode[i];
index c853400805d1c66c98496b548ae2c30c3f640987..735c38d7db0d7da44eff5239d448095d677be6b6 100644 (file)
@@ -955,11 +955,11 @@ int amdgpu_vce_ring_test_ring(struct amdgpu_ring *ring)
        struct amdgpu_device *adev = ring->adev;
        uint32_t rptr = amdgpu_ring_get_rptr(ring);
        unsigned i;
-       int r;
+       int r, timeout = adev->usec_timeout;
 
-       /* TODO: remove it if VCE can work for sriov */
+       /* workaround VCE ring test slow issue for sriov*/
        if (amdgpu_sriov_vf(adev))
-               return 0;
+               timeout *= 10;
 
        r = amdgpu_ring_alloc(ring, 16);
        if (r) {
@@ -970,13 +970,13 @@ int amdgpu_vce_ring_test_ring(struct amdgpu_ring *ring)
        amdgpu_ring_write(ring, VCE_CMD_END);
        amdgpu_ring_commit(ring);
 
-       for (i = 0; i < adev->usec_timeout; i++) {
+       for (i = 0; i < timeout; i++) {
                if (amdgpu_ring_get_rptr(ring) != rptr)
                        break;
                DRM_UDELAY(1);
        }
 
-       if (i < adev->usec_timeout) {
+       if (i < timeout) {
                DRM_INFO("ring test on %d succeeded in %d usecs\n",
                         ring->idx, i);
        } else {
@@ -999,10 +999,6 @@ int amdgpu_vce_ring_test_ib(struct amdgpu_ring *ring, long timeout)
        struct dma_fence *fence = NULL;
        long r;
 
-       /* TODO: remove it if VCE can work for sriov */
-       if (amdgpu_sriov_vf(ring->adev))
-               return 0;
-
        /* skip vce ring1/2 ib test for now, since it's not reliable */
        if (ring != &ring->adev->vce.ring[0])
                return 0;
index ba8b8ae6234f583bef4ec5030d7888fbf6cfabb2..6bf5cea294f2e01212151688ffa10758a1756b8e 100644 (file)
@@ -225,3 +225,49 @@ int amdgpu_virt_reset_gpu(struct amdgpu_device *adev)
 
        return 0;
 }
+
+/**
+ * amdgpu_virt_alloc_mm_table() - alloc memory for mm table
+ * @amdgpu:    amdgpu device.
+ * MM table is used by UVD and VCE for its initialization
+ * Return: Zero if allocate success.
+ */
+int amdgpu_virt_alloc_mm_table(struct amdgpu_device *adev)
+{
+       int r;
+
+       if (!amdgpu_sriov_vf(adev) || adev->virt.mm_table.gpu_addr)
+               return 0;
+
+       r = amdgpu_bo_create_kernel(adev, PAGE_SIZE, PAGE_SIZE,
+                                   AMDGPU_GEM_DOMAIN_VRAM,
+                                   &adev->virt.mm_table.bo,
+                                   &adev->virt.mm_table.gpu_addr,
+                                   (void *)&adev->virt.mm_table.cpu_addr);
+       if (r) {
+               DRM_ERROR("failed to alloc mm table and error = %d.\n", r);
+               return r;
+       }
+
+       memset((void *)adev->virt.mm_table.cpu_addr, 0, PAGE_SIZE);
+       DRM_INFO("MM table gpu addr = 0x%llx, cpu addr = %p.\n",
+                adev->virt.mm_table.gpu_addr,
+                adev->virt.mm_table.cpu_addr);
+       return 0;
+}
+
+/**
+ * amdgpu_virt_free_mm_table() - free mm table memory
+ * @amdgpu:    amdgpu device.
+ * Free MM table memory
+ */
+void amdgpu_virt_free_mm_table(struct amdgpu_device *adev)
+{
+       if (!amdgpu_sriov_vf(adev) || !adev->virt.mm_table.gpu_addr)
+               return;
+
+       amdgpu_bo_free_kernel(&adev->virt.mm_table.bo,
+                             &adev->virt.mm_table.gpu_addr,
+                             (void *)&adev->virt.mm_table.cpu_addr);
+       adev->virt.mm_table.gpu_addr = 0;
+}
index 1ee0a190b33b1dd4d2f236f507621352f7d2bc08..a8ed162cc0bc83ed8a86a623c8a45bd476f4f4f2 100644 (file)
@@ -98,5 +98,7 @@ int amdgpu_virt_request_full_gpu(struct amdgpu_device *adev, bool init);
 int amdgpu_virt_release_full_gpu(struct amdgpu_device *adev, bool init);
 int amdgpu_virt_reset_gpu(struct amdgpu_device *adev);
 int amdgpu_sriov_gpu_reset(struct amdgpu_device *adev, bool voluntary);
+int amdgpu_virt_alloc_mm_table(struct amdgpu_device *adev);
+void amdgpu_virt_free_mm_table(struct amdgpu_device *adev);
 
 #endif
index 7ed5302b511aa4b6b3eacf21ef13f25ba77d794c..07ff3b1514f129edc23875c1f42053f7ef1aaa72 100644 (file)
@@ -406,6 +406,8 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
                      struct amdgpu_job *job)
 {
        struct amdgpu_device *adev = ring->adev;
+       unsigned vmhub = ring->funcs->vmhub;
+       struct amdgpu_vm_id_manager *id_mgr = &adev->vm_manager.id_mgr[vmhub];
        uint64_t fence_context = adev->fence_context + ring->idx;
        struct dma_fence *updates = sync->last_vm_update;
        struct amdgpu_vm_id *id, *idle;
@@ -413,16 +415,15 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
        unsigned i;
        int r = 0;
 
-       fences = kmalloc_array(sizeof(void *), adev->vm_manager.num_ids,
-                              GFP_KERNEL);
+       fences = kmalloc_array(sizeof(void *), id_mgr->num_ids, GFP_KERNEL);
        if (!fences)
                return -ENOMEM;
 
-       mutex_lock(&adev->vm_manager.lock);
+       mutex_lock(&id_mgr->lock);
 
        /* Check if we have an idle VMID */
        i = 0;
-       list_for_each_entry(idle, &adev->vm_manager.ids_lru, list) {
+       list_for_each_entry(idle, &id_mgr->ids_lru, list) {
                fences[i] = amdgpu_sync_peek_fence(&idle->active, ring);
                if (!fences[i])
                        break;
@@ -430,7 +431,7 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
        }
 
        /* If we can't find a idle VMID to use, wait till one becomes available */
-       if (&idle->list == &adev->vm_manager.ids_lru) {
+       if (&idle->list == &id_mgr->ids_lru) {
                u64 fence_context = adev->vm_manager.fence_context + ring->idx;
                unsigned seqno = ++adev->vm_manager.seqno[ring->idx];
                struct dma_fence_array *array;
@@ -455,25 +456,19 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
                if (r)
                        goto error;
 
-               mutex_unlock(&adev->vm_manager.lock);
+               mutex_unlock(&id_mgr->lock);
                return 0;
 
        }
        kfree(fences);
 
-       job->vm_needs_flush = true;
+       job->vm_needs_flush = false;
        /* Check if we can use a VMID already assigned to this VM */
-       i = ring->idx;
-       do {
+       list_for_each_entry_reverse(id, &id_mgr->ids_lru, list) {
                struct dma_fence *flushed;
-
-               id = vm->ids[i++];
-               if (i == AMDGPU_MAX_RINGS)
-                       i = 0;
+               bool needs_flush = false;
 
                /* Check all the prerequisites to using this VMID */
-               if (!id)
-                       continue;
                if (amdgpu_vm_had_gpu_reset(adev, id))
                        continue;
 
@@ -483,16 +478,17 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
                if (job->vm_pd_addr != id->pd_gpu_addr)
                        continue;
 
-               if (!id->last_flush)
-                       continue;
-
-               if (id->last_flush->context != fence_context &&
-                   !dma_fence_is_signaled(id->last_flush))
-                       continue;
+               if (!id->last_flush ||
+                   (id->last_flush->context != fence_context &&
+                    !dma_fence_is_signaled(id->last_flush)))
+                       needs_flush = true;
 
                flushed  = id->flushed_updates;
-               if (updates &&
-                   (!flushed || dma_fence_is_later(updates, flushed)))
+               if (updates && (!flushed || dma_fence_is_later(updates, flushed)))
+                       needs_flush = true;
+
+               /* Concurrent flushes are only possible starting with Vega10 */
+               if (adev->asic_type < CHIP_VEGA10 && needs_flush)
                        continue;
 
                /* Good we can use this VMID. Remember this submission as
@@ -502,17 +498,17 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
                if (r)
                        goto error;
 
-               list_move_tail(&id->list, &adev->vm_manager.ids_lru);
-               vm->ids[ring->idx] = id;
-
-               job->vm_id = id - adev->vm_manager.ids;
-               job->vm_needs_flush = false;
-               trace_amdgpu_vm_grab_id(vm, ring->idx, job);
+               if (updates && (!flushed || dma_fence_is_later(updates, flushed))) {
+                       dma_fence_put(id->flushed_updates);
+                       id->flushed_updates = dma_fence_get(updates);
+               }
 
-               mutex_unlock(&adev->vm_manager.lock);
-               return 0;
+               if (needs_flush)
+                       goto needs_flush;
+               else
+                       goto no_flush_needed;
 
-       } while (i != ring->idx);
+       };
 
        /* Still no ID to use? Then use the idle one found earlier */
        id = idle;
@@ -522,23 +518,25 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
        if (r)
                goto error;
 
-       dma_fence_put(id->last_flush);
-       id->last_flush = NULL;
-
+       id->pd_gpu_addr = job->vm_pd_addr;
        dma_fence_put(id->flushed_updates);
        id->flushed_updates = dma_fence_get(updates);
-
-       id->pd_gpu_addr = job->vm_pd_addr;
        id->current_gpu_reset_count = atomic_read(&adev->gpu_reset_counter);
-       list_move_tail(&id->list, &adev->vm_manager.ids_lru);
        atomic64_set(&id->owner, vm->client_id);
-       vm->ids[ring->idx] = id;
 
-       job->vm_id = id - adev->vm_manager.ids;
-       trace_amdgpu_vm_grab_id(vm, ring->idx, job);
+needs_flush:
+       job->vm_needs_flush = true;
+       dma_fence_put(id->last_flush);
+       id->last_flush = NULL;
+
+no_flush_needed:
+       list_move_tail(&id->list, &id_mgr->ids_lru);
+
+       job->vm_id = id - id_mgr->ids;
+       trace_amdgpu_vm_grab_id(vm, ring, job);
 
 error:
-       mutex_unlock(&adev->vm_manager.lock);
+       mutex_unlock(&id_mgr->lock);
        return r;
 }
 
@@ -590,7 +588,9 @@ static u64 amdgpu_vm_adjust_mc_addr(struct amdgpu_device *adev, u64 mc_addr)
 int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job)
 {
        struct amdgpu_device *adev = ring->adev;
-       struct amdgpu_vm_id *id = &adev->vm_manager.ids[job->vm_id];
+       unsigned vmhub = ring->funcs->vmhub;
+       struct amdgpu_vm_id_manager *id_mgr = &adev->vm_manager.id_mgr[vmhub];
+       struct amdgpu_vm_id *id = &id_mgr->ids[job->vm_id];
        bool gds_switch_needed = ring->funcs->emit_gds_switch && (
                id->gds_base != job->gds_base ||
                id->gds_size != job->gds_size ||
@@ -614,24 +614,24 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job)
        if (ring->funcs->init_cond_exec)
                patch_offset = amdgpu_ring_init_cond_exec(ring);
 
-       if (ring->funcs->emit_pipeline_sync)
+       if (ring->funcs->emit_pipeline_sync && !job->need_pipeline_sync)
                amdgpu_ring_emit_pipeline_sync(ring);
 
        if (ring->funcs->emit_vm_flush && vm_flush_needed) {
                u64 pd_addr = amdgpu_vm_adjust_mc_addr(adev, job->vm_pd_addr);
                struct dma_fence *fence;
 
-               trace_amdgpu_vm_flush(pd_addr, ring->idx, job->vm_id);
+               trace_amdgpu_vm_flush(ring, job->vm_id, pd_addr);
                amdgpu_ring_emit_vm_flush(ring, job->vm_id, pd_addr);
 
                r = amdgpu_fence_emit(ring, &fence);
                if (r)
                        return r;
 
-               mutex_lock(&adev->vm_manager.lock);
+               mutex_lock(&id_mgr->lock);
                dma_fence_put(id->last_flush);
                id->last_flush = fence;
-               mutex_unlock(&adev->vm_manager.lock);
+               mutex_unlock(&id_mgr->lock);
        }
 
        if (gds_switch_needed) {
@@ -666,9 +666,11 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job)
  *
  * Reset saved GDW, GWS and OA to force switch on next flush.
  */
-void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vm_id)
+void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vmhub,
+                       unsigned vmid)
 {
-       struct amdgpu_vm_id *id = &adev->vm_manager.ids[vm_id];
+       struct amdgpu_vm_id_manager *id_mgr = &adev->vm_manager.id_mgr[vmhub];
+       struct amdgpu_vm_id *id = &id_mgr->ids[vmid];
 
        id->gds_base = 0;
        id->gds_size = 0;
@@ -1336,6 +1338,12 @@ static int amdgpu_vm_bo_split_mapping(struct amdgpu_device *adev,
        flags &= ~AMDGPU_PTE_MTYPE_MASK;
        flags |= (mapping->flags & AMDGPU_PTE_MTYPE_MASK);
 
+       if ((mapping->flags & AMDGPU_PTE_PRT) &&
+           (adev->asic_type >= CHIP_VEGA10)) {
+               flags |= AMDGPU_PTE_PRT;
+               flags &= ~AMDGPU_PTE_VALID;
+       }
+
        trace_amdgpu_vm_bo_update(mapping);
 
        pfn = mapping->offset >> PAGE_SHIFT;
@@ -1629,8 +1637,9 @@ int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
                        struct amdgpu_bo_va_mapping, list);
                list_del(&mapping->list);
 
-               r = amdgpu_vm_bo_split_mapping(adev, NULL, 0, NULL, vm, mapping,
-                                              0, 0, &f);
+               r = amdgpu_vm_bo_update_mapping(adev, NULL, 0, NULL, vm,
+                                               mapping->start, mapping->last,
+                                               0, 0, &f);
                amdgpu_vm_free_mapping(adev, vm, mapping, f);
                if (r) {
                        dma_fence_put(f);
@@ -2117,10 +2126,8 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm)
        unsigned ring_instance;
        struct amdgpu_ring *ring;
        struct amd_sched_rq *rq;
-       int i, r;
+       int r;
 
-       for (i = 0; i < AMDGPU_MAX_RINGS; ++i)
-               vm->ids[i] = NULL;
        vm->va = RB_ROOT;
        vm->client_id = atomic64_inc_return(&adev->vm_manager.client_counter);
        spin_lock_init(&vm->status_lock);
@@ -2241,16 +2248,21 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm)
  */
 void amdgpu_vm_manager_init(struct amdgpu_device *adev)
 {
-       unsigned i;
+       unsigned i, j;
+
+       for (i = 0; i < AMDGPU_MAX_VMHUBS; ++i) {
+               struct amdgpu_vm_id_manager *id_mgr =
+                       &adev->vm_manager.id_mgr[i];
 
-       INIT_LIST_HEAD(&adev->vm_manager.ids_lru);
+               mutex_init(&id_mgr->lock);
+               INIT_LIST_HEAD(&id_mgr->ids_lru);
 
-       /* skip over VMID 0, since it is the system VM */
-       for (i = 1; i < adev->vm_manager.num_ids; ++i) {
-               amdgpu_vm_reset_id(adev, i);
-               amdgpu_sync_create(&adev->vm_manager.ids[i].active);
-               list_add_tail(&adev->vm_manager.ids[i].list,
-                             &adev->vm_manager.ids_lru);
+               /* skip over VMID 0, since it is the system VM */
+               for (j = 1; j < id_mgr->num_ids; ++j) {
+                       amdgpu_vm_reset_id(adev, i, j);
+                       amdgpu_sync_create(&id_mgr->ids[i].active);
+                       list_add_tail(&id_mgr->ids[j].list, &id_mgr->ids_lru);
+               }
        }
 
        adev->vm_manager.fence_context =
@@ -2258,6 +2270,7 @@ void amdgpu_vm_manager_init(struct amdgpu_device *adev)
        for (i = 0; i < AMDGPU_MAX_RINGS; ++i)
                adev->vm_manager.seqno[i] = 0;
 
+
        atomic_set(&adev->vm_manager.vm_pte_next_ring, 0);
        atomic64_set(&adev->vm_manager.client_counter, 0);
        spin_lock_init(&adev->vm_manager.prt_lock);
@@ -2273,13 +2286,19 @@ void amdgpu_vm_manager_init(struct amdgpu_device *adev)
  */
 void amdgpu_vm_manager_fini(struct amdgpu_device *adev)
 {
-       unsigned i;
+       unsigned i, j;
 
-       for (i = 0; i < AMDGPU_NUM_VM; ++i) {
-               struct amdgpu_vm_id *id = &adev->vm_manager.ids[i];
+       for (i = 0; i < AMDGPU_MAX_VMHUBS; ++i) {
+               struct amdgpu_vm_id_manager *id_mgr =
+                       &adev->vm_manager.id_mgr[i];
 
-               amdgpu_sync_free(&adev->vm_manager.ids[i].active);
-               dma_fence_put(id->flushed_updates);
-               dma_fence_put(id->last_flush);
+               mutex_destroy(&id_mgr->lock);
+               for (j = 0; j < AMDGPU_NUM_VM; ++j) {
+                       struct amdgpu_vm_id *id = &id_mgr->ids[j];
+
+                       amdgpu_sync_free(&id->active);
+                       dma_fence_put(id->flushed_updates);
+                       dma_fence_put(id->last_flush);
+               }
        }
 }
index d9e57290dc718cf24b8802829a1f206e9f9acb32..d97e28b4bdc41cbb52e70647685b58db4886514a 100644 (file)
@@ -65,7 +65,8 @@ struct amdgpu_bo_list_entry;
 
 #define AMDGPU_PTE_FRAG(x)     ((x & 0x1fULL) << 7)
 
-#define AMDGPU_PTE_PRT         (1ULL << 63)
+/* TILED for VEGA10, reserved for older ASICs  */
+#define AMDGPU_PTE_PRT         (1ULL << 51)
 
 /* VEGA10 only */
 #define AMDGPU_PTE_MTYPE(a)    ((uint64_t)a << 57)
@@ -114,9 +115,6 @@ struct amdgpu_vm {
        struct dma_fence        *last_dir_update;
        uint64_t                last_eviction_counter;
 
-       /* for id and flush management per ring */
-       struct amdgpu_vm_id     *ids[AMDGPU_MAX_RINGS];
-
        /* protecting freed */
        spinlock_t              freed_lock;
 
@@ -149,12 +147,16 @@ struct amdgpu_vm_id {
        uint32_t                oa_size;
 };
 
+struct amdgpu_vm_id_manager {
+       struct mutex            lock;
+       unsigned                num_ids;
+       struct list_head        ids_lru;
+       struct amdgpu_vm_id     ids[AMDGPU_NUM_VM];
+};
+
 struct amdgpu_vm_manager {
        /* Handling of VMIDs */
-       struct mutex                            lock;
-       unsigned                                num_ids;
-       struct list_head                        ids_lru;
-       struct amdgpu_vm_id                     ids[AMDGPU_NUM_VM];
+       struct amdgpu_vm_id_manager             id_mgr[AMDGPU_MAX_VMHUBS];
 
        /* Handling of VM fences */
        u64                                     fence_context;
@@ -200,7 +202,8 @@ int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring,
                      struct amdgpu_sync *sync, struct dma_fence *fence,
                      struct amdgpu_job *job);
 int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job);
-void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vm_id);
+void amdgpu_vm_reset_id(struct amdgpu_device *adev, unsigned vmhub,
+                       unsigned vmid);
 int amdgpu_vm_update_directories(struct amdgpu_device *adev,
                                 struct amdgpu_vm *vm);
 int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
index 11ccda83d767b0e416667c56e48cb72f1ecb9668..6dc1410b380f376982551dbebe06f4dd84edf3b2 100644 (file)
@@ -1267,30 +1267,33 @@ static int ci_dpm_set_fan_speed_percent(struct amdgpu_device *adev,
 
 static void ci_dpm_set_fan_control_mode(struct amdgpu_device *adev, u32 mode)
 {
-       if (mode) {
-               /* stop auto-manage */
+       switch (mode) {
+       case AMD_FAN_CTRL_NONE:
                if (adev->pm.dpm.fan.ucode_fan_control)
                        ci_fan_ctrl_stop_smc_fan_control(adev);
-               ci_fan_ctrl_set_static_mode(adev, mode);
-       } else {
-               /* restart auto-manage */
+               ci_dpm_set_fan_speed_percent(adev, 100);
+               break;
+       case AMD_FAN_CTRL_MANUAL:
+               if (adev->pm.dpm.fan.ucode_fan_control)
+                       ci_fan_ctrl_stop_smc_fan_control(adev);
+               break;
+       case AMD_FAN_CTRL_AUTO:
                if (adev->pm.dpm.fan.ucode_fan_control)
                        ci_thermal_start_smc_fan_control(adev);
-               else
-                       ci_fan_ctrl_set_default_mode(adev);
+               break;
+       default:
+               break;
        }
 }
 
 static u32 ci_dpm_get_fan_control_mode(struct amdgpu_device *adev)
 {
        struct ci_power_info *pi = ci_get_pi(adev);
-       u32 tmp;
 
        if (pi->fan_is_controlled_by_smc)
-               return 0;
-
-       tmp = RREG32_SMC(ixCG_FDO_CTRL2) & CG_FDO_CTRL2__FDO_PWM_MODE_MASK;
-       return (tmp >> CG_FDO_CTRL2__FDO_PWM_MODE__SHIFT);
+               return AMD_FAN_CTRL_AUTO;
+       else
+               return AMD_FAN_CTRL_MANUAL;
 }
 
 #if 0
@@ -3036,6 +3039,7 @@ static int ci_populate_single_memory_level(struct amdgpu_device *adev,
                                                      memory_clock,
                                                      &memory_level->MinVddcPhases);
 
+       memory_level->EnabledForActivity = 1;
        memory_level->EnabledForThrottle = 1;
        memory_level->UpH = 0;
        memory_level->DownH = 100;
@@ -3468,8 +3472,6 @@ static int ci_populate_all_memory_levels(struct amdgpu_device *adev)
                        return ret;
        }
 
-       pi->smc_state_table.MemoryLevel[0].EnabledForActivity = 1;
-
        if ((dpm_table->mclk_table.count >= 2) &&
            ((adev->pdev->device == 0x67B0) || (adev->pdev->device == 0x67B1))) {
                pi->smc_state_table.MemoryLevel[1].MinVddc =
index ba98d35340a3025e863d3b7d871ddcd179a66703..0cdeb6a2e4a0166d8f33a542e950e7c87abc11fa 100644 (file)
@@ -2230,7 +2230,7 @@ static int dce_v10_0_crtc_do_set_base(struct drm_crtc *crtc,
        if (!atomic && fb && fb != crtc->primary->fb) {
                amdgpu_fb = to_amdgpu_framebuffer(fb);
                abo = gem_to_amdgpu_bo(amdgpu_fb->obj);
-               r = amdgpu_bo_reserve(abo, false);
+               r = amdgpu_bo_reserve(abo, true);
                if (unlikely(r != 0))
                        return r;
                amdgpu_bo_unpin(abo);
@@ -2589,7 +2589,7 @@ static int dce_v10_0_crtc_cursor_set2(struct drm_crtc *crtc,
 unpin:
        if (amdgpu_crtc->cursor_bo) {
                struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
-               ret = amdgpu_bo_reserve(aobj, false);
+               ret = amdgpu_bo_reserve(aobj, true);
                if (likely(ret == 0)) {
                        amdgpu_bo_unpin(aobj);
                        amdgpu_bo_unreserve(aobj);
@@ -2720,7 +2720,7 @@ static void dce_v10_0_crtc_disable(struct drm_crtc *crtc)
 
                amdgpu_fb = to_amdgpu_framebuffer(crtc->primary->fb);
                abo = gem_to_amdgpu_bo(amdgpu_fb->obj);
-               r = amdgpu_bo_reserve(abo, false);
+               r = amdgpu_bo_reserve(abo, true);
                if (unlikely(r))
                        DRM_ERROR("failed to reserve abo before unpin\n");
                else {
index e59bc42df18c4209f059d7201e6778e6478b7a78..773654a19749fa7594250c6683d688e50bb12172 100644 (file)
@@ -2214,7 +2214,7 @@ static int dce_v11_0_crtc_do_set_base(struct drm_crtc *crtc,
        if (!atomic && fb && fb != crtc->primary->fb) {
                amdgpu_fb = to_amdgpu_framebuffer(fb);
                abo = gem_to_amdgpu_bo(amdgpu_fb->obj);
-               r = amdgpu_bo_reserve(abo, false);
+               r = amdgpu_bo_reserve(abo, true);
                if (unlikely(r != 0))
                        return r;
                amdgpu_bo_unpin(abo);
@@ -2609,7 +2609,7 @@ static int dce_v11_0_crtc_cursor_set2(struct drm_crtc *crtc,
 unpin:
        if (amdgpu_crtc->cursor_bo) {
                struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
-               ret = amdgpu_bo_reserve(aobj, false);
+               ret = amdgpu_bo_reserve(aobj, true);
                if (likely(ret == 0)) {
                        amdgpu_bo_unpin(aobj);
                        amdgpu_bo_unreserve(aobj);
@@ -2740,7 +2740,7 @@ static void dce_v11_0_crtc_disable(struct drm_crtc *crtc)
 
                amdgpu_fb = to_amdgpu_framebuffer(crtc->primary->fb);
                abo = gem_to_amdgpu_bo(amdgpu_fb->obj);
-               r = amdgpu_bo_reserve(abo, false);
+               r = amdgpu_bo_reserve(abo, true);
                if (unlikely(r))
                        DRM_ERROR("failed to reserve abo before unpin\n");
                else {
index 307269bda4fa7e66f3c70505a50a21a428e0dc04..1f3552967ba374c2e5677a742b70e2040f867d65 100644 (file)
@@ -979,7 +979,7 @@ static void dce_v6_0_program_watermarks(struct amdgpu_device *adev,
        u32 priority_a_mark = 0, priority_b_mark = 0;
        u32 priority_a_cnt = PRIORITY_OFF;
        u32 priority_b_cnt = PRIORITY_OFF;
-       u32 tmp, arb_control3;
+       u32 tmp, arb_control3, lb_vblank_lead_lines = 0;
        fixed20_12 a, b, c;
 
        if (amdgpu_crtc->base.enabled && num_heads && mode) {
@@ -1091,6 +1091,8 @@ static void dce_v6_0_program_watermarks(struct amdgpu_device *adev,
                c.full = dfixed_div(c, a);
                priority_b_mark = dfixed_trunc(c);
                priority_b_cnt |= priority_b_mark & PRIORITY_MARK_MASK;
+
+               lb_vblank_lead_lines = DIV_ROUND_UP(lb_size, mode->crtc_hdisplay);
        }
 
        /* select wm A */
@@ -1120,6 +1122,9 @@ static void dce_v6_0_program_watermarks(struct amdgpu_device *adev,
        /* save values for DPM */
        amdgpu_crtc->line_time = line_time;
        amdgpu_crtc->wm_high = latency_watermark_a;
+
+       /* Save number of lines the linebuffer leads before the scanout */
+       amdgpu_crtc->lb_vblank_lead_lines = lb_vblank_lead_lines;
 }
 
 /* watermark setup */
@@ -1640,7 +1645,7 @@ static int dce_v6_0_crtc_do_set_base(struct drm_crtc *crtc,
        if (!atomic && fb && fb != crtc->primary->fb) {
                amdgpu_fb = to_amdgpu_framebuffer(fb);
                abo = gem_to_amdgpu_bo(amdgpu_fb->obj);
-               r = amdgpu_bo_reserve(abo, false);
+               r = amdgpu_bo_reserve(abo, true);
                if (unlikely(r != 0))
                        return r;
                amdgpu_bo_unpin(abo);
@@ -1957,7 +1962,7 @@ static int dce_v6_0_crtc_cursor_set2(struct drm_crtc *crtc,
 unpin:
        if (amdgpu_crtc->cursor_bo) {
                struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
-               ret = amdgpu_bo_reserve(aobj, false);
+               ret = amdgpu_bo_reserve(aobj, true);
                if (likely(ret == 0)) {
                        amdgpu_bo_unpin(aobj);
                        amdgpu_bo_unreserve(aobj);
@@ -2083,7 +2088,7 @@ static void dce_v6_0_crtc_disable(struct drm_crtc *crtc)
 
                amdgpu_fb = to_amdgpu_framebuffer(crtc->primary->fb);
                abo = gem_to_amdgpu_bo(amdgpu_fb->obj);
-               r = amdgpu_bo_reserve(abo, false);
+               r = amdgpu_bo_reserve(abo, true);
                if (unlikely(r))
                        DRM_ERROR("failed to reserve abo before unpin\n");
                else {
index 6df7a28e8aaccbd3e47225148252dd3c427744d4..3c558c170e5e685ad58aafa8dc6df301e879f264 100644 (file)
@@ -2089,7 +2089,7 @@ static int dce_v8_0_crtc_do_set_base(struct drm_crtc *crtc,
        if (!atomic && fb && fb != crtc->primary->fb) {
                amdgpu_fb = to_amdgpu_framebuffer(fb);
                abo = gem_to_amdgpu_bo(amdgpu_fb->obj);
-               r = amdgpu_bo_reserve(abo, false);
+               r = amdgpu_bo_reserve(abo, true);
                if (unlikely(r != 0))
                        return r;
                amdgpu_bo_unpin(abo);
@@ -2440,7 +2440,7 @@ static int dce_v8_0_crtc_cursor_set2(struct drm_crtc *crtc,
 unpin:
        if (amdgpu_crtc->cursor_bo) {
                struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
-               ret = amdgpu_bo_reserve(aobj, false);
+               ret = amdgpu_bo_reserve(aobj, true);
                if (likely(ret == 0)) {
                        amdgpu_bo_unpin(aobj);
                        amdgpu_bo_unreserve(aobj);
@@ -2571,7 +2571,7 @@ static void dce_v8_0_crtc_disable(struct drm_crtc *crtc)
 
                amdgpu_fb = to_amdgpu_framebuffer(crtc->primary->fb);
                abo = gem_to_amdgpu_bo(amdgpu_fb->obj);
-               r = amdgpu_bo_reserve(abo, false);
+               r = amdgpu_bo_reserve(abo, true);
                if (unlikely(r))
                        DRM_ERROR("failed to reserve abo before unpin\n");
                else {
index 81a24b6b484625bfc76916be44e6bd4e9ba53dcf..f1b479b6ac983da35b8e341cf98928bc35dcd700 100644 (file)
@@ -248,7 +248,7 @@ static void dce_virtual_crtc_disable(struct drm_crtc *crtc)
 
                amdgpu_fb = to_amdgpu_framebuffer(crtc->primary->fb);
                abo = gem_to_amdgpu_bo(amdgpu_fb->obj);
-               r = amdgpu_bo_reserve(abo, false);
+               r = amdgpu_bo_reserve(abo, true);
                if (unlikely(r))
                        DRM_ERROR("failed to reserve abo before unpin\n");
                else {
index 4c4874fdf59f72aa15a29dd3a51c25e94390d104..a125f9d44577ed4bb86d01516c7594977def46a7 100644 (file)
@@ -1579,7 +1579,7 @@ static void gfx_v6_0_setup_spi(struct amdgpu_device *adev)
 
 static void gfx_v6_0_config_init(struct amdgpu_device *adev)
 {
-       adev->gfx.config.double_offchip_lds_buf = 1;
+       adev->gfx.config.double_offchip_lds_buf = 0;
 }
 
 static void gfx_v6_0_gpu_init(struct amdgpu_device *adev)
@@ -2437,7 +2437,7 @@ static void gfx_v6_0_rlc_fini(struct amdgpu_device *adev)
        int r;
 
        if (adev->gfx.rlc.save_restore_obj) {
-               r = amdgpu_bo_reserve(adev->gfx.rlc.save_restore_obj, false);
+               r = amdgpu_bo_reserve(adev->gfx.rlc.save_restore_obj, true);
                if (unlikely(r != 0))
                        dev_warn(adev->dev, "(%d) reserve RLC sr bo failed\n", r);
                amdgpu_bo_unpin(adev->gfx.rlc.save_restore_obj);
@@ -2448,7 +2448,7 @@ static void gfx_v6_0_rlc_fini(struct amdgpu_device *adev)
        }
 
        if (adev->gfx.rlc.clear_state_obj) {
-               r = amdgpu_bo_reserve(adev->gfx.rlc.clear_state_obj, false);
+               r = amdgpu_bo_reserve(adev->gfx.rlc.clear_state_obj, true);
                if (unlikely(r != 0))
                        dev_warn(adev->dev, "(%d) reserve RLC c bo failed\n", r);
                amdgpu_bo_unpin(adev->gfx.rlc.clear_state_obj);
@@ -2459,7 +2459,7 @@ static void gfx_v6_0_rlc_fini(struct amdgpu_device *adev)
        }
 
        if (adev->gfx.rlc.cp_table_obj) {
-               r = amdgpu_bo_reserve(adev->gfx.rlc.cp_table_obj, false);
+               r = amdgpu_bo_reserve(adev->gfx.rlc.cp_table_obj, true);
                if (unlikely(r != 0))
                        dev_warn(adev->dev, "(%d) reserve RLC cp table bo failed\n", r);
                amdgpu_bo_unpin(adev->gfx.rlc.cp_table_obj);
@@ -3292,7 +3292,7 @@ static int gfx_v6_0_sw_init(void *handle)
                ring->me = 1;
                ring->pipe = i;
                ring->queue = i;
-               sprintf(ring->name, "comp %d.%d.%d", ring->me, ring->pipe, ring->queue);
+               sprintf(ring->name, "comp_%d.%d.%d", ring->me, ring->pipe, ring->queue);
                irq_type = AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP + ring->pipe;
                r = amdgpu_ring_init(adev, ring, 1024,
                                     &adev->gfx.eop_irq, irq_type);
index 8a8bc2fe6f2e4c81265219bda0f3928f412e8e7c..ee2f2139e2eba62b31173052c7b809c152489585 100644 (file)
@@ -1935,7 +1935,7 @@ static void gfx_v7_0_gpu_init(struct amdgpu_device *adev)
                                   INDEX_STRIDE, 3);
 
        mutex_lock(&adev->srbm_mutex);
-       for (i = 0; i < adev->vm_manager.num_ids; i++) {
+       for (i = 0; i < adev->vm_manager.id_mgr[0].num_ids; i++) {
                if (i == 0)
                        sh_mem_base = 0;
                else
@@ -2792,7 +2792,7 @@ static void gfx_v7_0_cp_compute_fini(struct amdgpu_device *adev)
                struct amdgpu_ring *ring = &adev->gfx.compute_ring[i];
 
                if (ring->mqd_obj) {
-                       r = amdgpu_bo_reserve(ring->mqd_obj, false);
+                       r = amdgpu_bo_reserve(ring->mqd_obj, true);
                        if (unlikely(r != 0))
                                dev_warn(adev->dev, "(%d) reserve MQD bo failed\n", r);
 
@@ -2810,7 +2810,7 @@ static void gfx_v7_0_mec_fini(struct amdgpu_device *adev)
        int r;
 
        if (adev->gfx.mec.hpd_eop_obj) {
-               r = amdgpu_bo_reserve(adev->gfx.mec.hpd_eop_obj, false);
+               r = amdgpu_bo_reserve(adev->gfx.mec.hpd_eop_obj, true);
                if (unlikely(r != 0))
                        dev_warn(adev->dev, "(%d) reserve HPD EOP bo failed\n", r);
                amdgpu_bo_unpin(adev->gfx.mec.hpd_eop_obj);
@@ -3359,7 +3359,7 @@ static void gfx_v7_0_rlc_fini(struct amdgpu_device *adev)
 
        /* save restore block */
        if (adev->gfx.rlc.save_restore_obj) {
-               r = amdgpu_bo_reserve(adev->gfx.rlc.save_restore_obj, false);
+               r = amdgpu_bo_reserve(adev->gfx.rlc.save_restore_obj, true);
                if (unlikely(r != 0))
                        dev_warn(adev->dev, "(%d) reserve RLC sr bo failed\n", r);
                amdgpu_bo_unpin(adev->gfx.rlc.save_restore_obj);
@@ -3371,7 +3371,7 @@ static void gfx_v7_0_rlc_fini(struct amdgpu_device *adev)
 
        /* clear state block */
        if (adev->gfx.rlc.clear_state_obj) {
-               r = amdgpu_bo_reserve(adev->gfx.rlc.clear_state_obj, false);
+               r = amdgpu_bo_reserve(adev->gfx.rlc.clear_state_obj, true);
                if (unlikely(r != 0))
                        dev_warn(adev->dev, "(%d) reserve RLC c bo failed\n", r);
                amdgpu_bo_unpin(adev->gfx.rlc.clear_state_obj);
@@ -3383,7 +3383,7 @@ static void gfx_v7_0_rlc_fini(struct amdgpu_device *adev)
 
        /* clear state block */
        if (adev->gfx.rlc.cp_table_obj) {
-               r = amdgpu_bo_reserve(adev->gfx.rlc.cp_table_obj, false);
+               r = amdgpu_bo_reserve(adev->gfx.rlc.cp_table_obj, true);
                if (unlikely(r != 0))
                        dev_warn(adev->dev, "(%d) reserve RLC cp table bo failed\n", r);
                amdgpu_bo_unpin(adev->gfx.rlc.cp_table_obj);
index dad8a4cd1b375c9ae2d8d1ce80bc84f48fbdf293..758d636a6f52b37556199498784285a332982c30 100644 (file)
@@ -1239,7 +1239,7 @@ static void gfx_v8_0_rlc_fini(struct amdgpu_device *adev)
 
        /* clear state block */
        if (adev->gfx.rlc.clear_state_obj) {
-               r = amdgpu_bo_reserve(adev->gfx.rlc.clear_state_obj, false);
+               r = amdgpu_bo_reserve(adev->gfx.rlc.clear_state_obj, true);
                if (unlikely(r != 0))
                        dev_warn(adev->dev, "(%d) reserve RLC cbs bo failed\n", r);
                amdgpu_bo_unpin(adev->gfx.rlc.clear_state_obj);
@@ -1250,7 +1250,7 @@ static void gfx_v8_0_rlc_fini(struct amdgpu_device *adev)
 
        /* jump table block */
        if (adev->gfx.rlc.cp_table_obj) {
-               r = amdgpu_bo_reserve(adev->gfx.rlc.cp_table_obj, false);
+               r = amdgpu_bo_reserve(adev->gfx.rlc.cp_table_obj, true);
                if (unlikely(r != 0))
                        dev_warn(adev->dev, "(%d) reserve RLC cp table bo failed\n", r);
                amdgpu_bo_unpin(adev->gfx.rlc.cp_table_obj);
@@ -1363,7 +1363,7 @@ static void gfx_v8_0_mec_fini(struct amdgpu_device *adev)
        int r;
 
        if (adev->gfx.mec.hpd_eop_obj) {
-               r = amdgpu_bo_reserve(adev->gfx.mec.hpd_eop_obj, false);
+               r = amdgpu_bo_reserve(adev->gfx.mec.hpd_eop_obj, true);
                if (unlikely(r != 0))
                        dev_warn(adev->dev, "(%d) reserve HPD EOP bo failed\n", r);
                amdgpu_bo_unpin(adev->gfx.mec.hpd_eop_obj);
@@ -1490,7 +1490,7 @@ static int gfx_v8_0_kiq_init(struct amdgpu_device *adev)
 
        memset(hpd, 0, MEC_HPD_SIZE);
 
-       r = amdgpu_bo_reserve(kiq->eop_obj, false);
+       r = amdgpu_bo_reserve(kiq->eop_obj, true);
        if (unlikely(r != 0))
                dev_warn(adev->dev, "(%d) reserve kiq eop bo failed\n", r);
        amdgpu_bo_kunmap(kiq->eop_obj);
@@ -1932,6 +1932,7 @@ static int gfx_v8_0_gpu_early_init(struct amdgpu_device *adev)
                case 0xca:
                case 0xce:
                case 0x88:
+               case 0xe6:
                        /* B6 */
                        adev->gfx.config.max_cu_per_sh = 6;
                        break;
@@ -1964,17 +1965,28 @@ static int gfx_v8_0_gpu_early_init(struct amdgpu_device *adev)
                adev->gfx.config.max_backends_per_se = 1;
 
                switch (adev->pdev->revision) {
+               case 0x80:
+               case 0x81:
                case 0xc0:
                case 0xc1:
                case 0xc2:
                case 0xc4:
                case 0xc8:
                case 0xc9:
+               case 0xd6:
+               case 0xda:
+               case 0xe9:
+               case 0xea:
                        adev->gfx.config.max_cu_per_sh = 3;
                        break;
+               case 0x83:
                case 0xd0:
                case 0xd1:
                case 0xd2:
+               case 0xd4:
+               case 0xdb:
+               case 0xe1:
+               case 0xe2:
                default:
                        adev->gfx.config.max_cu_per_sh = 2;
                        break;
@@ -3890,7 +3902,7 @@ static void gfx_v8_0_gpu_init(struct amdgpu_device *adev)
        sh_static_mem_cfg = REG_SET_FIELD(sh_static_mem_cfg, SH_STATIC_MEM_CONFIG,
                                   INDEX_STRIDE, 3);
        mutex_lock(&adev->srbm_mutex);
-       for (i = 0; i < adev->vm_manager.num_ids; i++) {
+       for (i = 0; i < adev->vm_manager.id_mgr[0].num_ids; i++) {
                vi_srbm_select(adev, 0, 0, 0, i);
                /* CP and shaders */
                if (i == 0) {
index a447b70841c9cd9b6aa89180bec0f3ae6f210910..0c16b7563b7317e2b63aef0a1800945f72430091 100644 (file)
@@ -39,7 +39,6 @@
 
 #define GFX9_NUM_GFX_RINGS     1
 #define GFX9_NUM_COMPUTE_RINGS 8
-#define GFX9_NUM_SE            4
 #define RLCG_UCODE_LOADING_START_ADDRESS 0x2000
 
 MODULE_FIRMWARE("amdgpu/vega10_ce.bin");
@@ -453,7 +452,7 @@ static void gfx_v9_0_mec_fini(struct amdgpu_device *adev)
        int r;
 
        if (adev->gfx.mec.hpd_eop_obj) {
-               r = amdgpu_bo_reserve(adev->gfx.mec.hpd_eop_obj, false);
+               r = amdgpu_bo_reserve(adev->gfx.mec.hpd_eop_obj, true);
                if (unlikely(r != 0))
                        dev_warn(adev->dev, "(%d) reserve HPD EOP bo failed\n", r);
                amdgpu_bo_unpin(adev->gfx.mec.hpd_eop_obj);
@@ -463,7 +462,7 @@ static void gfx_v9_0_mec_fini(struct amdgpu_device *adev)
                adev->gfx.mec.hpd_eop_obj = NULL;
        }
        if (adev->gfx.mec.mec_fw_obj) {
-               r = amdgpu_bo_reserve(adev->gfx.mec.mec_fw_obj, false);
+               r = amdgpu_bo_reserve(adev->gfx.mec.mec_fw_obj, true);
                if (unlikely(r != 0))
                        dev_warn(adev->dev, "(%d) reserve mec firmware bo failed\n", r);
                amdgpu_bo_unpin(adev->gfx.mec.mec_fw_obj);
@@ -599,7 +598,7 @@ static int gfx_v9_0_kiq_init(struct amdgpu_device *adev)
 
        memset(hpd, 0, MEC_HPD_SIZE);
 
-       r = amdgpu_bo_reserve(kiq->eop_obj, false);
+       r = amdgpu_bo_reserve(kiq->eop_obj, true);
        if (unlikely(r != 0))
                dev_warn(adev->dev, "(%d) reserve kiq eop bo failed\n", r);
        amdgpu_bo_kunmap(kiq->eop_obj);
@@ -631,7 +630,6 @@ static int gfx_v9_0_kiq_init_ring(struct amdgpu_device *adev,
                ring->pipe = 1;
        }
 
-       irq->data = ring;
        ring->queue = 0;
        ring->eop_gpu_addr = kiq->eop_gpu_addr;
        sprintf(ring->name, "kiq %d.%d.%d", ring->me, ring->pipe, ring->queue);
@@ -647,7 +645,6 @@ static void gfx_v9_0_kiq_free_ring(struct amdgpu_ring *ring,
 {
        amdgpu_wb_free(ring->adev, ring->adev->virt.reg_val_offs);
        amdgpu_ring_fini(ring);
-       irq->data = NULL;
 }
 
 /* create MQD for each compute queue */
@@ -705,19 +702,19 @@ static void gfx_v9_0_compute_mqd_sw_fini(struct amdgpu_device *adev)
 
 static uint32_t wave_read_ind(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t address)
 {
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_IND_INDEX),
+       WREG32_SOC15(GC, 0, mmSQ_IND_INDEX,
                (wave << SQ_IND_INDEX__WAVE_ID__SHIFT) |
                (simd << SQ_IND_INDEX__SIMD_ID__SHIFT) |
                (address << SQ_IND_INDEX__INDEX__SHIFT) |
                (SQ_IND_INDEX__FORCE_READ_MASK));
-       return RREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_IND_DATA));
+       return RREG32_SOC15(GC, 0, mmSQ_IND_DATA);
 }
 
 static void wave_read_regs(struct amdgpu_device *adev, uint32_t simd,
                           uint32_t wave, uint32_t thread,
                           uint32_t regno, uint32_t num, uint32_t *out)
 {
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_IND_INDEX),
+       WREG32_SOC15(GC, 0, mmSQ_IND_INDEX,
                (wave << SQ_IND_INDEX__WAVE_ID__SHIFT) |
                (simd << SQ_IND_INDEX__SIMD_ID__SHIFT) |
                (regno << SQ_IND_INDEX__INDEX__SHIFT) |
@@ -725,7 +722,7 @@ static void wave_read_regs(struct amdgpu_device *adev, uint32_t simd,
                (SQ_IND_INDEX__FORCE_READ_MASK) |
                (SQ_IND_INDEX__AUTO_INCR_MASK));
        while (num--)
-               *(out++) = RREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_IND_DATA));
+               *(out++) = RREG32_SOC15(GC, 0, mmSQ_IND_DATA);
 }
 
 static void gfx_v9_0_read_wave_data(struct amdgpu_device *adev, uint32_t simd, uint32_t wave, uint32_t *dst, int *no_fields)
@@ -774,7 +771,6 @@ static void gfx_v9_0_gpu_early_init(struct amdgpu_device *adev)
        switch (adev->asic_type) {
        case CHIP_VEGA10:
                adev->gfx.config.max_shader_engines = 4;
-               adev->gfx.config.max_tile_pipes = 8; //??
                adev->gfx.config.max_cu_per_sh = 16;
                adev->gfx.config.max_sh_per_se = 1;
                adev->gfx.config.max_backends_per_se = 4;
@@ -787,6 +783,8 @@ static void gfx_v9_0_gpu_early_init(struct amdgpu_device *adev)
                adev->gfx.config.sc_prim_fifo_size_backend = 0x100;
                adev->gfx.config.sc_hiz_tile_fifo_size = 0x30;
                adev->gfx.config.sc_earlyz_tile_fifo_size = 0x4C0;
+               adev->gfx.config.gs_vgt_table_depth = 32;
+               adev->gfx.config.gs_prim_buffer_depth = 1792;
                gb_addr_config = VEGA10_GB_ADDR_CONFIG_GOLDEN;
                break;
        default:
@@ -801,6 +799,10 @@ static void gfx_v9_0_gpu_early_init(struct amdgpu_device *adev)
                                        adev->gfx.config.gb_addr_config,
                                        GB_ADDR_CONFIG,
                                        NUM_PIPES);
+
+       adev->gfx.config.max_tile_pipes =
+               adev->gfx.config.gb_addr_config_fields.num_pipes;
+
        adev->gfx.config.gb_addr_config_fields.num_banks = 1 <<
                        REG_GET_FIELD(
                                        adev->gfx.config.gb_addr_config,
@@ -841,7 +843,7 @@ static int gfx_v9_0_ngg_create_buf(struct amdgpu_device *adev,
        }
        size_se = size_se ? size_se : default_size_se;
 
-       ngg_buf->size = size_se * GFX9_NUM_SE;
+       ngg_buf->size = size_se * adev->gfx.config.max_shader_engines;
        r = amdgpu_bo_create_kernel(adev, ngg_buf->size,
                                    PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM,
                                    &ngg_buf->bo,
@@ -888,7 +890,7 @@ static int gfx_v9_0_ngg_init(struct amdgpu_device *adev)
        adev->gfx.ngg.gds_reserve_addr += adev->gds.mem.gfx_partition_size;
 
        /* Primitive Buffer */
-       r = gfx_v9_0_ngg_create_buf(adev, &adev->gfx.ngg.buf[PRIM],
+       r = gfx_v9_0_ngg_create_buf(adev, &adev->gfx.ngg.buf[NGG_PRIM],
                                    amdgpu_prim_buf_per_se,
                                    64 * 1024);
        if (r) {
@@ -897,7 +899,7 @@ static int gfx_v9_0_ngg_init(struct amdgpu_device *adev)
        }
 
        /* Position Buffer */
-       r = gfx_v9_0_ngg_create_buf(adev, &adev->gfx.ngg.buf[POS],
+       r = gfx_v9_0_ngg_create_buf(adev, &adev->gfx.ngg.buf[NGG_POS],
                                    amdgpu_pos_buf_per_se,
                                    256 * 1024);
        if (r) {
@@ -906,7 +908,7 @@ static int gfx_v9_0_ngg_init(struct amdgpu_device *adev)
        }
 
        /* Control Sideband */
-       r = gfx_v9_0_ngg_create_buf(adev, &adev->gfx.ngg.buf[CNTL],
+       r = gfx_v9_0_ngg_create_buf(adev, &adev->gfx.ngg.buf[NGG_CNTL],
                                    amdgpu_cntl_sb_buf_per_se,
                                    256);
        if (r) {
@@ -918,7 +920,7 @@ static int gfx_v9_0_ngg_init(struct amdgpu_device *adev)
        if (amdgpu_param_buf_per_se <= 0)
                goto out;
 
-       r = gfx_v9_0_ngg_create_buf(adev, &adev->gfx.ngg.buf[PARAM],
+       r = gfx_v9_0_ngg_create_buf(adev, &adev->gfx.ngg.buf[NGG_PARAM],
                                    amdgpu_param_buf_per_se,
                                    512 * 1024);
        if (r) {
@@ -947,47 +949,47 @@ static int gfx_v9_0_ngg_en(struct amdgpu_device *adev)
 
        /* Program buffer size */
        data = 0;
-       size = adev->gfx.ngg.buf[PRIM].size / 256;
+       size = adev->gfx.ngg.buf[NGG_PRIM].size / 256;
        data = REG_SET_FIELD(data, WD_BUF_RESOURCE_1, INDEX_BUF_SIZE, size);
 
-       size = adev->gfx.ngg.buf[POS].size / 256;
+       size = adev->gfx.ngg.buf[NGG_POS].size / 256;
        data = REG_SET_FIELD(data, WD_BUF_RESOURCE_1, POS_BUF_SIZE, size);
 
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmWD_BUF_RESOURCE_1), data);
+       WREG32_SOC15(GC, 0, mmWD_BUF_RESOURCE_1, data);
 
        data = 0;
-       size = adev->gfx.ngg.buf[CNTL].size / 256;
+       size = adev->gfx.ngg.buf[NGG_CNTL].size / 256;
        data = REG_SET_FIELD(data, WD_BUF_RESOURCE_2, CNTL_SB_BUF_SIZE, size);
 
-       size = adev->gfx.ngg.buf[PARAM].size / 1024;
+       size = adev->gfx.ngg.buf[NGG_PARAM].size / 1024;
        data = REG_SET_FIELD(data, WD_BUF_RESOURCE_2, PARAM_BUF_SIZE, size);
 
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmWD_BUF_RESOURCE_2), data);
+       WREG32_SOC15(GC, 0, mmWD_BUF_RESOURCE_2, data);
 
        /* Program buffer base address */
-       base = lower_32_bits(adev->gfx.ngg.buf[PRIM].gpu_addr);
+       base = lower_32_bits(adev->gfx.ngg.buf[NGG_PRIM].gpu_addr);
        data = REG_SET_FIELD(0, WD_INDEX_BUF_BASE, BASE, base);
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmWD_INDEX_BUF_BASE), data);
+       WREG32_SOC15(GC, 0, mmWD_INDEX_BUF_BASE, data);
 
-       base = upper_32_bits(adev->gfx.ngg.buf[PRIM].gpu_addr);
+       base = upper_32_bits(adev->gfx.ngg.buf[NGG_PRIM].gpu_addr);
        data = REG_SET_FIELD(0, WD_INDEX_BUF_BASE_HI, BASE_HI, base);
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmWD_INDEX_BUF_BASE_HI), data);
+       WREG32_SOC15(GC, 0, mmWD_INDEX_BUF_BASE_HI, data);
 
-       base = lower_32_bits(adev->gfx.ngg.buf[POS].gpu_addr);
+       base = lower_32_bits(adev->gfx.ngg.buf[NGG_POS].gpu_addr);
        data = REG_SET_FIELD(0, WD_POS_BUF_BASE, BASE, base);
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmWD_POS_BUF_BASE), data);
+       WREG32_SOC15(GC, 0, mmWD_POS_BUF_BASE, data);
 
-       base = upper_32_bits(adev->gfx.ngg.buf[POS].gpu_addr);
+       base = upper_32_bits(adev->gfx.ngg.buf[NGG_POS].gpu_addr);
        data = REG_SET_FIELD(0, WD_POS_BUF_BASE_HI, BASE_HI, base);
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmWD_POS_BUF_BASE_HI), data);
+       WREG32_SOC15(GC, 0, mmWD_POS_BUF_BASE_HI, data);
 
-       base = lower_32_bits(adev->gfx.ngg.buf[CNTL].gpu_addr);
+       base = lower_32_bits(adev->gfx.ngg.buf[NGG_CNTL].gpu_addr);
        data = REG_SET_FIELD(0, WD_CNTL_SB_BUF_BASE, BASE, base);
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmWD_CNTL_SB_BUF_BASE), data);
+       WREG32_SOC15(GC, 0, mmWD_CNTL_SB_BUF_BASE, data);
 
-       base = upper_32_bits(adev->gfx.ngg.buf[CNTL].gpu_addr);
+       base = upper_32_bits(adev->gfx.ngg.buf[NGG_CNTL].gpu_addr);
        data = REG_SET_FIELD(0, WD_CNTL_SB_BUF_BASE_HI, BASE_HI, base);
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmWD_CNTL_SB_BUF_BASE_HI), data);
+       WREG32_SOC15(GC, 0, mmWD_CNTL_SB_BUF_BASE_HI, data);
 
        /* Clear GDS reserved memory */
        r = amdgpu_ring_alloc(ring, 17);
@@ -1096,7 +1098,7 @@ static int gfx_v9_0_sw_init(void *handle)
                ring->pipe = i / 8;
                ring->queue = i % 8;
                ring->eop_gpu_addr = adev->gfx.mec.hpd_eop_gpu_addr + (i * MEC_HPD_SIZE);
-               sprintf(ring->name, "comp %d.%d.%d", ring->me, ring->pipe, ring->queue);
+               sprintf(ring->name, "comp_%d.%d.%d", ring->me, ring->pipe, ring->queue);
                irq_type = AMDGPU_CP_IRQ_COMPUTE_MEC1_PIPE0_EOP + ring->pipe;
                /* type-2 packets are deprecated on MEC, use type-3 instead */
                r = amdgpu_ring_init(adev, ring, 1024,
@@ -1203,7 +1205,7 @@ static void gfx_v9_0_select_se_sh(struct amdgpu_device *adev, u32 se_num, u32 sh
                data = REG_SET_FIELD(data, GRBM_GFX_INDEX, SH_INDEX, sh_num);
                data = REG_SET_FIELD(data, GRBM_GFX_INDEX, SE_INDEX, se_num);
        }
-       WREG32( SOC15_REG_OFFSET(GC, 0, mmGRBM_GFX_INDEX), data);
+       WREG32_SOC15(GC, 0, mmGRBM_GFX_INDEX, data);
 }
 
 static u32 gfx_v9_0_create_bitmask(u32 bit_width)
@@ -1215,8 +1217,8 @@ static u32 gfx_v9_0_get_rb_active_bitmap(struct amdgpu_device *adev)
 {
        u32 data, mask;
 
-       data = RREG32(SOC15_REG_OFFSET(GC, 0, mmCC_RB_BACKEND_DISABLE));
-       data |= RREG32(SOC15_REG_OFFSET(GC, 0, mmGC_USER_RB_BACKEND_DISABLE));
+       data = RREG32_SOC15(GC, 0, mmCC_RB_BACKEND_DISABLE);
+       data |= RREG32_SOC15(GC, 0, mmGC_USER_RB_BACKEND_DISABLE);
 
        data &= CC_RB_BACKEND_DISABLE__BACKEND_DISABLE_MASK;
        data >>= GC_USER_RB_BACKEND_DISABLE__BACKEND_DISABLE__SHIFT;
@@ -1276,8 +1278,8 @@ static void gfx_v9_0_init_compute_vmid(struct amdgpu_device *adev)
        for (i = FIRST_COMPUTE_VMID; i < LAST_COMPUTE_VMID; i++) {
                soc15_grbm_select(adev, 0, 0, 0, i);
                /* CP and shaders */
-               WREG32(SOC15_REG_OFFSET(GC, 0, mmSH_MEM_CONFIG), sh_mem_config);
-               WREG32(SOC15_REG_OFFSET(GC, 0, mmSH_MEM_BASES), sh_mem_bases);
+               WREG32_SOC15(GC, 0, mmSH_MEM_CONFIG, sh_mem_config);
+               WREG32_SOC15(GC, 0, mmSH_MEM_BASES, sh_mem_bases);
        }
        soc15_grbm_select(adev, 0, 0, 0, 0);
        mutex_unlock(&adev->srbm_mutex);
@@ -1304,8 +1306,8 @@ static void gfx_v9_0_gpu_init(struct amdgpu_device *adev)
                tmp = 0;
                tmp = REG_SET_FIELD(tmp, SH_MEM_CONFIG, ALIGNMENT_MODE,
                                    SH_MEM_ALIGNMENT_MODE_UNALIGNED);
-               WREG32(SOC15_REG_OFFSET(GC, 0, mmSH_MEM_CONFIG), tmp);
-               WREG32(SOC15_REG_OFFSET(GC, 0, mmSH_MEM_BASES), 0);
+               WREG32_SOC15(GC, 0, mmSH_MEM_CONFIG, tmp);
+               WREG32_SOC15(GC, 0, mmSH_MEM_BASES, 0);
        }
        soc15_grbm_select(adev, 0, 0, 0, 0);
 
@@ -1320,7 +1322,7 @@ static void gfx_v9_0_gpu_init(struct amdgpu_device *adev)
         */
        gfx_v9_0_select_se_sh(adev, 0xffffffff, 0xffffffff, 0xffffffff);
 
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmPA_SC_FIFO_SIZE),
+       WREG32_SOC15(GC, 0, mmPA_SC_FIFO_SIZE,
                   (adev->gfx.config.sc_prim_fifo_size_frontend <<
                        PA_SC_FIFO_SIZE__SC_FRONTEND_PRIM_FIFO_SIZE__SHIFT) |
                   (adev->gfx.config.sc_prim_fifo_size_backend <<
@@ -1343,7 +1345,7 @@ static void gfx_v9_0_wait_for_rlc_serdes(struct amdgpu_device *adev)
                for (j = 0; j < adev->gfx.config.max_sh_per_se; j++) {
                        gfx_v9_0_select_se_sh(adev, i, j, 0xffffffff);
                        for (k = 0; k < adev->usec_timeout; k++) {
-                               if (RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_SERDES_CU_MASTER_BUSY)) == 0)
+                               if (RREG32_SOC15(GC, 0, mmRLC_SERDES_CU_MASTER_BUSY) == 0)
                                        break;
                                udelay(1);
                        }
@@ -1357,7 +1359,7 @@ static void gfx_v9_0_wait_for_rlc_serdes(struct amdgpu_device *adev)
                RLC_SERDES_NONCU_MASTER_BUSY__TC0_MASTER_BUSY_MASK |
                RLC_SERDES_NONCU_MASTER_BUSY__TC1_MASTER_BUSY_MASK;
        for (k = 0; k < adev->usec_timeout; k++) {
-               if ((RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_SERDES_NONCU_MASTER_BUSY)) & mask) == 0)
+               if ((RREG32_SOC15(GC, 0, mmRLC_SERDES_NONCU_MASTER_BUSY) & mask) == 0)
                        break;
                udelay(1);
        }
@@ -1366,7 +1368,7 @@ static void gfx_v9_0_wait_for_rlc_serdes(struct amdgpu_device *adev)
 static void gfx_v9_0_enable_gui_idle_interrupt(struct amdgpu_device *adev,
                                               bool enable)
 {
-       u32 tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_INT_CNTL_RING0));
+       u32 tmp = RREG32_SOC15(GC, 0, mmCP_INT_CNTL_RING0);
 
        if (enable)
                return;
@@ -1376,15 +1378,15 @@ static void gfx_v9_0_enable_gui_idle_interrupt(struct amdgpu_device *adev,
        tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CMP_BUSY_INT_ENABLE, enable ? 1 : 0);
        tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, GFX_IDLE_INT_ENABLE, enable ? 1 : 0);
 
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_INT_CNTL_RING0), tmp);
+       WREG32_SOC15(GC, 0, mmCP_INT_CNTL_RING0, tmp);
 }
 
 void gfx_v9_0_rlc_stop(struct amdgpu_device *adev)
 {
-       u32 tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CNTL));
+       u32 tmp = RREG32_SOC15(GC, 0, mmRLC_CNTL);
 
        tmp = REG_SET_FIELD(tmp, RLC_CNTL, RLC_ENABLE_F32, 0);
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CNTL), tmp);
+       WREG32_SOC15(GC, 0, mmRLC_CNTL, tmp);
 
        gfx_v9_0_enable_gui_idle_interrupt(adev, false);
 
@@ -1415,17 +1417,17 @@ static void gfx_v9_0_rlc_start(struct amdgpu_device *adev)
 
 #ifdef AMDGPU_RLC_DEBUG_RETRY
        /* RLC_GPM_GENERAL_6 : RLC Ucode version */
-       rlc_ucode_ver = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_GPM_GENERAL_6));
+       rlc_ucode_ver = RREG32_SOC15(GC, 0, mmRLC_GPM_GENERAL_6);
        if(rlc_ucode_ver == 0x108) {
                DRM_INFO("Using rlc debug ucode. mmRLC_GPM_GENERAL_6 ==0x08%x / fw_ver == %i \n",
                                rlc_ucode_ver, adev->gfx.rlc_fw_version);
                /* RLC_GPM_TIMER_INT_3 : Timer interval in RefCLK cycles,
                 * default is 0x9C4 to create a 100us interval */
-               WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_GPM_TIMER_INT_3), 0x9C4);
+               WREG32_SOC15(GC, 0, mmRLC_GPM_TIMER_INT_3, 0x9C4);
                /* RLC_GPM_GENERAL_12 : Minimum gap between wptr and rptr
                 * to disable the page fault retry interrupts, default is 
                 * 0x100 (256) */
-               WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_GPM_GENERAL_12), 0x100);
+               WREG32_SOC15(GC, 0, mmRLC_GPM_GENERAL_12, 0x100);
        }
 #endif
 }
@@ -1446,11 +1448,11 @@ static int gfx_v9_0_rlc_load_microcode(struct amdgpu_device *adev)
                           le32_to_cpu(hdr->header.ucode_array_offset_bytes));
        fw_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
 
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_GPM_UCODE_ADDR),
+       WREG32_SOC15(GC, 0, mmRLC_GPM_UCODE_ADDR,
                        RLCG_UCODE_LOADING_START_ADDRESS);
        for (i = 0; i < fw_size; i++)
-               WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_GPM_UCODE_DATA), le32_to_cpup(fw_data++));
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_GPM_UCODE_ADDR), adev->gfx.rlc_fw_version);
+               WREG32_SOC15(GC, 0, mmRLC_GPM_UCODE_DATA, le32_to_cpup(fw_data++));
+       WREG32_SOC15(GC, 0, mmRLC_GPM_UCODE_ADDR, adev->gfx.rlc_fw_version);
 
        return 0;
 }
@@ -1465,10 +1467,10 @@ static int gfx_v9_0_rlc_resume(struct amdgpu_device *adev)
        gfx_v9_0_rlc_stop(adev);
 
        /* disable CG */
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGCG_CGLS_CTRL), 0);
+       WREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL, 0);
 
        /* disable PG */
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_PG_CNTL), 0);
+       WREG32_SOC15(GC, 0, mmRLC_PG_CNTL, 0);
 
        gfx_v9_0_rlc_reset(adev);
 
@@ -1487,7 +1489,7 @@ static int gfx_v9_0_rlc_resume(struct amdgpu_device *adev)
 static void gfx_v9_0_cp_gfx_enable(struct amdgpu_device *adev, bool enable)
 {
        int i;
-       u32 tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_ME_CNTL));
+       u32 tmp = RREG32_SOC15(GC, 0, mmCP_ME_CNTL);
 
        tmp = REG_SET_FIELD(tmp, CP_ME_CNTL, ME_HALT, enable ? 0 : 1);
        tmp = REG_SET_FIELD(tmp, CP_ME_CNTL, PFP_HALT, enable ? 0 : 1);
@@ -1496,7 +1498,7 @@ static void gfx_v9_0_cp_gfx_enable(struct amdgpu_device *adev, bool enable)
                for (i = 0; i < adev->gfx.num_gfx_rings; i++)
                        adev->gfx.gfx_ring[i].ready = false;
        }
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_ME_CNTL), tmp);
+       WREG32_SOC15(GC, 0, mmCP_ME_CNTL, tmp);
        udelay(50);
 }
 
@@ -1529,30 +1531,30 @@ static int gfx_v9_0_cp_gfx_load_microcode(struct amdgpu_device *adev)
                (adev->gfx.pfp_fw->data +
                 le32_to_cpu(pfp_hdr->header.ucode_array_offset_bytes));
        fw_size = le32_to_cpu(pfp_hdr->header.ucode_size_bytes) / 4;
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_PFP_UCODE_ADDR), 0);
+       WREG32_SOC15(GC, 0, mmCP_PFP_UCODE_ADDR, 0);
        for (i = 0; i < fw_size; i++)
-               WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_PFP_UCODE_DATA), le32_to_cpup(fw_data++));
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_PFP_UCODE_ADDR), adev->gfx.pfp_fw_version);
+               WREG32_SOC15(GC, 0, mmCP_PFP_UCODE_DATA, le32_to_cpup(fw_data++));
+       WREG32_SOC15(GC, 0, mmCP_PFP_UCODE_ADDR, adev->gfx.pfp_fw_version);
 
        /* CE */
        fw_data = (const __le32 *)
                (adev->gfx.ce_fw->data +
                 le32_to_cpu(ce_hdr->header.ucode_array_offset_bytes));
        fw_size = le32_to_cpu(ce_hdr->header.ucode_size_bytes) / 4;
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_CE_UCODE_ADDR), 0);
+       WREG32_SOC15(GC, 0, mmCP_CE_UCODE_ADDR, 0);
        for (i = 0; i < fw_size; i++)
-               WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_CE_UCODE_DATA), le32_to_cpup(fw_data++));
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_CE_UCODE_ADDR), adev->gfx.ce_fw_version);
+               WREG32_SOC15(GC, 0, mmCP_CE_UCODE_DATA, le32_to_cpup(fw_data++));
+       WREG32_SOC15(GC, 0, mmCP_CE_UCODE_ADDR, adev->gfx.ce_fw_version);
 
        /* ME */
        fw_data = (const __le32 *)
                (adev->gfx.me_fw->data +
                 le32_to_cpu(me_hdr->header.ucode_array_offset_bytes));
        fw_size = le32_to_cpu(me_hdr->header.ucode_size_bytes) / 4;
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_ME_RAM_WADDR), 0);
+       WREG32_SOC15(GC, 0, mmCP_ME_RAM_WADDR, 0);
        for (i = 0; i < fw_size; i++)
-               WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_ME_RAM_DATA), le32_to_cpup(fw_data++));
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_ME_RAM_WADDR), adev->gfx.me_fw_version);
+               WREG32_SOC15(GC, 0, mmCP_ME_RAM_DATA, le32_to_cpup(fw_data++));
+       WREG32_SOC15(GC, 0, mmCP_ME_RAM_WADDR, adev->gfx.me_fw_version);
 
        return 0;
 }
@@ -1594,8 +1596,8 @@ static int gfx_v9_0_cp_gfx_start(struct amdgpu_device *adev)
        int r, i;
 
        /* init the CP */
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MAX_CONTEXT), adev->gfx.config.max_hw_contexts - 1);
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_DEVICE_ID), 1);
+       WREG32_SOC15(GC, 0, mmCP_MAX_CONTEXT, adev->gfx.config.max_hw_contexts - 1);
+       WREG32_SOC15(GC, 0, mmCP_DEVICE_ID, 1);
 
        gfx_v9_0_cp_gfx_enable(adev, true);
 
@@ -1650,10 +1652,10 @@ static int gfx_v9_0_cp_gfx_resume(struct amdgpu_device *adev)
        u64 rb_addr, rptr_addr, wptr_gpu_addr;
 
        /* Set the write pointer delay */
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB_WPTR_DELAY), 0);
+       WREG32_SOC15(GC, 0, mmCP_RB_WPTR_DELAY, 0);
 
        /* set the RB to use vmid 0 */
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB_VMID), 0);
+       WREG32_SOC15(GC, 0, mmCP_RB_VMID, 0);
 
        /* Set ring buffer size */
        ring = &adev->gfx.gfx_ring[0];
@@ -1663,30 +1665,30 @@ static int gfx_v9_0_cp_gfx_resume(struct amdgpu_device *adev)
 #ifdef __BIG_ENDIAN
        tmp = REG_SET_FIELD(tmp, CP_RB0_CNTL, BUF_SWAP, 1);
 #endif
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB0_CNTL), tmp);
+       WREG32_SOC15(GC, 0, mmCP_RB0_CNTL, tmp);
 
        /* Initialize the ring buffer's write pointers */
        ring->wptr = 0;
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB0_WPTR), lower_32_bits(ring->wptr));
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB0_WPTR_HI), upper_32_bits(ring->wptr));
+       WREG32_SOC15(GC, 0, mmCP_RB0_WPTR, lower_32_bits(ring->wptr));
+       WREG32_SOC15(GC, 0, mmCP_RB0_WPTR_HI, upper_32_bits(ring->wptr));
 
        /* set the wb address wether it's enabled or not */
        rptr_addr = adev->wb.gpu_addr + (ring->rptr_offs * 4);
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB0_RPTR_ADDR), lower_32_bits(rptr_addr));
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB0_RPTR_ADDR_HI), upper_32_bits(rptr_addr) & CP_RB_RPTR_ADDR_HI__RB_RPTR_ADDR_HI_MASK);
+       WREG32_SOC15(GC, 0, mmCP_RB0_RPTR_ADDR, lower_32_bits(rptr_addr));
+       WREG32_SOC15(GC, 0, mmCP_RB0_RPTR_ADDR_HI, upper_32_bits(rptr_addr) & CP_RB_RPTR_ADDR_HI__RB_RPTR_ADDR_HI_MASK);
 
        wptr_gpu_addr = adev->wb.gpu_addr + (ring->wptr_offs * 4);
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB_WPTR_POLL_ADDR_LO), lower_32_bits(wptr_gpu_addr));
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB_WPTR_POLL_ADDR_HI), upper_32_bits(wptr_gpu_addr));
+       WREG32_SOC15(GC, 0, mmCP_RB_WPTR_POLL_ADDR_LO, lower_32_bits(wptr_gpu_addr));
+       WREG32_SOC15(GC, 0, mmCP_RB_WPTR_POLL_ADDR_HI, upper_32_bits(wptr_gpu_addr));
 
        mdelay(1);
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB0_CNTL), tmp);
+       WREG32_SOC15(GC, 0, mmCP_RB0_CNTL, tmp);
 
        rb_addr = ring->gpu_addr >> 8;
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB0_BASE), rb_addr);
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB0_BASE_HI), upper_32_bits(rb_addr));
+       WREG32_SOC15(GC, 0, mmCP_RB0_BASE, rb_addr);
+       WREG32_SOC15(GC, 0, mmCP_RB0_BASE_HI, upper_32_bits(rb_addr));
 
-       tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB_DOORBELL_CONTROL));
+       tmp = RREG32_SOC15(GC, 0, mmCP_RB_DOORBELL_CONTROL);
        if (ring->use_doorbell) {
                tmp = REG_SET_FIELD(tmp, CP_RB_DOORBELL_CONTROL,
                                    DOORBELL_OFFSET, ring->doorbell_index);
@@ -1695,13 +1697,13 @@ static int gfx_v9_0_cp_gfx_resume(struct amdgpu_device *adev)
        } else {
                tmp = REG_SET_FIELD(tmp, CP_RB_DOORBELL_CONTROL, DOORBELL_EN, 0);
        }
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB_DOORBELL_CONTROL), tmp);
+       WREG32_SOC15(GC, 0, mmCP_RB_DOORBELL_CONTROL, tmp);
 
        tmp = REG_SET_FIELD(0, CP_RB_DOORBELL_RANGE_LOWER,
                        DOORBELL_RANGE_LOWER, ring->doorbell_index);
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB_DOORBELL_RANGE_LOWER), tmp);
+       WREG32_SOC15(GC, 0, mmCP_RB_DOORBELL_RANGE_LOWER, tmp);
 
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB_DOORBELL_RANGE_UPPER),
+       WREG32_SOC15(GC, 0, mmCP_RB_DOORBELL_RANGE_UPPER,
                       CP_RB_DOORBELL_RANGE_UPPER__DOORBELL_RANGE_UPPER_MASK);
 
 
@@ -1717,9 +1719,9 @@ static void gfx_v9_0_cp_compute_enable(struct amdgpu_device *adev, bool enable)
        int i;
 
        if (enable) {
-               WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MEC_CNTL), 0);
+               WREG32_SOC15(GC, 0, mmCP_MEC_CNTL, 0);
        } else {
-               WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MEC_CNTL),
+               WREG32_SOC15(GC, 0, mmCP_MEC_CNTL,
                        (CP_MEC_CNTL__MEC_ME1_HALT_MASK | CP_MEC_CNTL__MEC_ME2_HALT_MASK));
                for (i = 0; i < adev->gfx.num_compute_rings; i++)
                        adev->gfx.compute_ring[i].ready = false;
@@ -1756,21 +1758,21 @@ static int gfx_v9_0_cp_compute_load_microcode(struct amdgpu_device *adev)
        tmp = 0;
        tmp = REG_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, VMID, 0);
        tmp = REG_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, CACHE_POLICY, 0);
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_CPC_IC_BASE_CNTL), tmp);
+       WREG32_SOC15(GC, 0, mmCP_CPC_IC_BASE_CNTL, tmp);
 
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_CPC_IC_BASE_LO),
+       WREG32_SOC15(GC, 0, mmCP_CPC_IC_BASE_LO,
                adev->gfx.mec.mec_fw_gpu_addr & 0xFFFFF000);
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_CPC_IC_BASE_HI),
+       WREG32_SOC15(GC, 0, mmCP_CPC_IC_BASE_HI,
                upper_32_bits(adev->gfx.mec.mec_fw_gpu_addr));
  
        /* MEC1 */
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MEC_ME1_UCODE_ADDR),
+       WREG32_SOC15(GC, 0, mmCP_MEC_ME1_UCODE_ADDR,
                         mec_hdr->jt_offset);
        for (i = 0; i < mec_hdr->jt_size; i++)
-               WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MEC_ME1_UCODE_DATA),
+               WREG32_SOC15(GC, 0, mmCP_MEC_ME1_UCODE_DATA,
                        le32_to_cpup(fw_data + mec_hdr->jt_offset + i));
 
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MEC_ME1_UCODE_ADDR),
+       WREG32_SOC15(GC, 0, mmCP_MEC_ME1_UCODE_ADDR,
                        adev->gfx.mec_fw_version);
        /* Todo : Loading MEC2 firmware is only necessary if MEC2 should run different microcode than MEC1. */
 
@@ -1785,7 +1787,7 @@ static void gfx_v9_0_cp_compute_fini(struct amdgpu_device *adev)
                struct amdgpu_ring *ring = &adev->gfx.compute_ring[i];
 
                if (ring->mqd_obj) {
-                       r = amdgpu_bo_reserve(ring->mqd_obj, false);
+                       r = amdgpu_bo_reserve(ring->mqd_obj, true);
                        if (unlikely(r != 0))
                                dev_warn(adev->dev, "(%d) reserve MQD bo failed\n", r);
 
@@ -1823,12 +1825,12 @@ static void gfx_v9_0_kiq_setting(struct amdgpu_ring *ring)
        struct amdgpu_device *adev = ring->adev;
 
        /* tell RLC which is KIQ queue */
-       tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CP_SCHEDULERS));
+       tmp = RREG32_SOC15(GC, 0, mmRLC_CP_SCHEDULERS);
        tmp &= 0xffffff00;
        tmp |= (ring->me << 5) | (ring->pipe << 3) | (ring->queue);
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CP_SCHEDULERS), tmp);
+       WREG32_SOC15(GC, 0, mmRLC_CP_SCHEDULERS, tmp);
        tmp |= 0x80;
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CP_SCHEDULERS), tmp);
+       WREG32_SOC15(GC, 0, mmRLC_CP_SCHEDULERS, tmp);
 }
 
 static void gfx_v9_0_kiq_enable(struct amdgpu_ring *ring)
@@ -1898,14 +1900,14 @@ static int gfx_v9_0_mqd_init(struct amdgpu_ring *ring)
        mqd->cp_hqd_eop_base_addr_hi = upper_32_bits(eop_base_addr);
 
        /* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */
-       tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_EOP_CONTROL));
+       tmp = RREG32_SOC15(GC, 0, mmCP_HQD_EOP_CONTROL);
        tmp = REG_SET_FIELD(tmp, CP_HQD_EOP_CONTROL, EOP_SIZE,
                        (order_base_2(MEC_HPD_SIZE / 4) - 1));
 
        mqd->cp_hqd_eop_control = tmp;
 
        /* enable doorbell? */
-       tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL));
+       tmp = RREG32_SOC15(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL);
 
        if (ring->use_doorbell) {
                tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
@@ -1935,7 +1937,7 @@ static int gfx_v9_0_mqd_init(struct amdgpu_ring *ring)
        mqd->cp_mqd_base_addr_hi = upper_32_bits(ring->mqd_gpu_addr);
 
        /* set MQD vmid to 0 */
-       tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MQD_CONTROL));
+       tmp = RREG32_SOC15(GC, 0, mmCP_MQD_CONTROL);
        tmp = REG_SET_FIELD(tmp, CP_MQD_CONTROL, VMID, 0);
        mqd->cp_mqd_control = tmp;
 
@@ -1945,7 +1947,7 @@ static int gfx_v9_0_mqd_init(struct amdgpu_ring *ring)
        mqd->cp_hqd_pq_base_hi = upper_32_bits(hqd_gpu_addr);
 
        /* set up the HQD, this is similar to CP_RB0_CNTL */
-       tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_CONTROL));
+       tmp = RREG32_SOC15(GC, 0, mmCP_HQD_PQ_CONTROL);
        tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, QUEUE_SIZE,
                            (order_base_2(ring->ring_size / 4) - 1));
        tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, RPTR_BLOCK_SIZE,
@@ -1973,7 +1975,7 @@ static int gfx_v9_0_mqd_init(struct amdgpu_ring *ring)
        tmp = 0;
        /* enable the doorbell if requested */
        if (ring->use_doorbell) {
-               tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL));
+               tmp = RREG32_SOC15(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL);
                tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
                                DOORBELL_OFFSET, ring->doorbell_index);
 
@@ -1989,15 +1991,20 @@ static int gfx_v9_0_mqd_init(struct amdgpu_ring *ring)
 
        /* reset read and write pointers, similar to CP_RB0_WPTR/_RPTR */
        ring->wptr = 0;
-       mqd->cp_hqd_pq_rptr = RREG32(mmCP_HQD_PQ_RPTR);
+       mqd->cp_hqd_pq_rptr = RREG32_SOC15(GC, 0, mmCP_HQD_PQ_RPTR);
 
        /* set the vmid for the queue */
        mqd->cp_hqd_vmid = 0;
 
-       tmp = RREG32(mmCP_HQD_PERSISTENT_STATE);
+       tmp = RREG32_SOC15(GC, 0, mmCP_HQD_PERSISTENT_STATE);
        tmp = REG_SET_FIELD(tmp, CP_HQD_PERSISTENT_STATE, PRELOAD_SIZE, 0x53);
        mqd->cp_hqd_persistent_state = tmp;
 
+       /* set MIN_IB_AVAIL_SIZE */
+       tmp = RREG32_SOC15(GC, 0, mmCP_HQD_IB_CONTROL);
+       tmp = REG_SET_FIELD(tmp, CP_HQD_IB_CONTROL, MIN_IB_AVAIL_SIZE, 3);
+       mqd->cp_hqd_ib_control = tmp;
+
        /* activate the queue */
        mqd->cp_hqd_active = 1;
 
@@ -2013,94 +2020,94 @@ static int gfx_v9_0_kiq_init_register(struct amdgpu_ring *ring)
        /* disable wptr polling */
        WREG32_FIELD15(GC, 0, CP_PQ_WPTR_POLL_CNTL, EN, 0);
 
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_EOP_BASE_ADDR),
+       WREG32_SOC15(GC, 0, mmCP_HQD_EOP_BASE_ADDR,
               mqd->cp_hqd_eop_base_addr_lo);
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_EOP_BASE_ADDR_HI),
+       WREG32_SOC15(GC, 0, mmCP_HQD_EOP_BASE_ADDR_HI,
               mqd->cp_hqd_eop_base_addr_hi);
 
        /* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_EOP_CONTROL),
+       WREG32_SOC15(GC, 0, mmCP_HQD_EOP_CONTROL,
               mqd->cp_hqd_eop_control);
 
        /* enable doorbell? */
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL),
+       WREG32_SOC15(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL,
               mqd->cp_hqd_pq_doorbell_control);
 
        /* disable the queue if it's active */
-       if (RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_ACTIVE)) & 1) {
-               WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_DEQUEUE_REQUEST), 1);
+       if (RREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE) & 1) {
+               WREG32_SOC15(GC, 0, mmCP_HQD_DEQUEUE_REQUEST, 1);
                for (j = 0; j < adev->usec_timeout; j++) {
-                       if (!(RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_ACTIVE)) & 1))
+                       if (!(RREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE) & 1))
                                break;
                        udelay(1);
                }
-               WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_DEQUEUE_REQUEST),
+               WREG32_SOC15(GC, 0, mmCP_HQD_DEQUEUE_REQUEST,
                       mqd->cp_hqd_dequeue_request);
-               WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_RPTR),
+               WREG32_SOC15(GC, 0, mmCP_HQD_PQ_RPTR,
                       mqd->cp_hqd_pq_rptr);
-               WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_LO),
+               WREG32_SOC15(GC, 0, mmCP_HQD_PQ_WPTR_LO,
                       mqd->cp_hqd_pq_wptr_lo);
-               WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_HI),
+               WREG32_SOC15(GC, 0, mmCP_HQD_PQ_WPTR_HI,
                       mqd->cp_hqd_pq_wptr_hi);
        }
 
        /* set the pointer to the MQD */
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MQD_BASE_ADDR),
+       WREG32_SOC15(GC, 0, mmCP_MQD_BASE_ADDR,
               mqd->cp_mqd_base_addr_lo);
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MQD_BASE_ADDR_HI),
+       WREG32_SOC15(GC, 0, mmCP_MQD_BASE_ADDR_HI,
               mqd->cp_mqd_base_addr_hi);
 
        /* set MQD vmid to 0 */
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MQD_CONTROL),
+       WREG32_SOC15(GC, 0, mmCP_MQD_CONTROL,
               mqd->cp_mqd_control);
 
        /* set the pointer to the HQD, this is similar CP_RB0_BASE/_HI */
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_BASE),
+       WREG32_SOC15(GC, 0, mmCP_HQD_PQ_BASE,
               mqd->cp_hqd_pq_base_lo);
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_BASE_HI),
+       WREG32_SOC15(GC, 0, mmCP_HQD_PQ_BASE_HI,
               mqd->cp_hqd_pq_base_hi);
 
        /* set up the HQD, this is similar to CP_RB0_CNTL */
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_CONTROL),
+       WREG32_SOC15(GC, 0, mmCP_HQD_PQ_CONTROL,
               mqd->cp_hqd_pq_control);
 
        /* set the wb address whether it's enabled or not */
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_RPTR_REPORT_ADDR),
+       WREG32_SOC15(GC, 0, mmCP_HQD_PQ_RPTR_REPORT_ADDR,
                                mqd->cp_hqd_pq_rptr_report_addr_lo);
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_RPTR_REPORT_ADDR_HI),
+       WREG32_SOC15(GC, 0, mmCP_HQD_PQ_RPTR_REPORT_ADDR_HI,
                                mqd->cp_hqd_pq_rptr_report_addr_hi);
 
        /* only used if CP_PQ_WPTR_POLL_CNTL.CP_PQ_WPTR_POLL_CNTL__EN_MASK=1 */
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_POLL_ADDR),
+       WREG32_SOC15(GC, 0, mmCP_HQD_PQ_WPTR_POLL_ADDR,
               mqd->cp_hqd_pq_wptr_poll_addr_lo);
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI),
+       WREG32_SOC15(GC, 0, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI,
               mqd->cp_hqd_pq_wptr_poll_addr_hi);
 
        /* enable the doorbell if requested */
        if (ring->use_doorbell) {
-               WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MEC_DOORBELL_RANGE_LOWER),
+               WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_LOWER,
                                        (AMDGPU_DOORBELL64_KIQ *2) << 2);
-               WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MEC_DOORBELL_RANGE_UPPER),
+               WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_UPPER,
                                        (AMDGPU_DOORBELL64_USERQUEUE_END * 2) << 2);
        }
 
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL),
+       WREG32_SOC15(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL,
               mqd->cp_hqd_pq_doorbell_control);
 
        /* reset read and write pointers, similar to CP_RB0_WPTR/_RPTR */
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_LO),
+       WREG32_SOC15(GC, 0, mmCP_HQD_PQ_WPTR_LO,
               mqd->cp_hqd_pq_wptr_lo);
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_HI),
+       WREG32_SOC15(GC, 0, mmCP_HQD_PQ_WPTR_HI,
               mqd->cp_hqd_pq_wptr_hi);
 
        /* set the vmid for the queue */
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_VMID), mqd->cp_hqd_vmid);
+       WREG32_SOC15(GC, 0, mmCP_HQD_VMID, mqd->cp_hqd_vmid);
 
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PERSISTENT_STATE),
+       WREG32_SOC15(GC, 0, mmCP_HQD_PERSISTENT_STATE,
               mqd->cp_hqd_persistent_state);
 
        /* activate the queue */
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_ACTIVE),
+       WREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE,
               mqd->cp_hqd_active);
 
        if (ring->use_doorbell)
@@ -2323,7 +2330,7 @@ static bool gfx_v9_0_is_idle(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       if (REG_GET_FIELD(RREG32(SOC15_REG_OFFSET(GC, 0, mmGRBM_STATUS)), 
+       if (REG_GET_FIELD(RREG32_SOC15(GC, 0, mmGRBM_STATUS),
                                GRBM_STATUS, GUI_ACTIVE))
                return false;
        else
@@ -2338,7 +2345,7 @@ static int gfx_v9_0_wait_for_idle(void *handle)
 
        for (i = 0; i < adev->usec_timeout; i++) {
                /* read MC_STATUS */
-               tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmGRBM_STATUS)) & 
+               tmp = RREG32_SOC15(GC, 0, mmGRBM_STATUS) &
                        GRBM_STATUS__GUI_ACTIVE_MASK;
 
                if (!REG_GET_FIELD(tmp, GRBM_STATUS, GUI_ACTIVE))
@@ -2355,7 +2362,7 @@ static int gfx_v9_0_soft_reset(void *handle)
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
        /* GRBM_STATUS */
-       tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmGRBM_STATUS));
+       tmp = RREG32_SOC15(GC, 0, mmGRBM_STATUS);
        if (tmp & (GRBM_STATUS__PA_BUSY_MASK | GRBM_STATUS__SC_BUSY_MASK |
                   GRBM_STATUS__BCI_BUSY_MASK | GRBM_STATUS__SX_BUSY_MASK |
                   GRBM_STATUS__TA_BUSY_MASK | GRBM_STATUS__VGT_BUSY_MASK |
@@ -2374,7 +2381,7 @@ static int gfx_v9_0_soft_reset(void *handle)
        }
 
        /* GRBM_STATUS2 */
-       tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmGRBM_STATUS2));
+       tmp = RREG32_SOC15(GC, 0, mmGRBM_STATUS2);
        if (REG_GET_FIELD(tmp, GRBM_STATUS2, RLC_BUSY))
                grbm_soft_reset = REG_SET_FIELD(grbm_soft_reset,
                                                GRBM_SOFT_RESET, SOFT_RESET_RLC, 1);
@@ -2391,17 +2398,17 @@ static int gfx_v9_0_soft_reset(void *handle)
                gfx_v9_0_cp_compute_enable(adev, false);
 
                if (grbm_soft_reset) {
-                       tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmGRBM_SOFT_RESET));
+                       tmp = RREG32_SOC15(GC, 0, mmGRBM_SOFT_RESET);
                        tmp |= grbm_soft_reset;
                        dev_info(adev->dev, "GRBM_SOFT_RESET=0x%08X\n", tmp);
-                       WREG32(SOC15_REG_OFFSET(GC, 0, mmGRBM_SOFT_RESET), tmp);
-                       tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmGRBM_SOFT_RESET));
+                       WREG32_SOC15(GC, 0, mmGRBM_SOFT_RESET, tmp);
+                       tmp = RREG32_SOC15(GC, 0, mmGRBM_SOFT_RESET);
 
                        udelay(50);
 
                        tmp &= ~grbm_soft_reset;
-                       WREG32(SOC15_REG_OFFSET(GC, 0, mmGRBM_SOFT_RESET), tmp);
-                       tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmGRBM_SOFT_RESET));
+                       WREG32_SOC15(GC, 0, mmGRBM_SOFT_RESET, tmp);
+                       tmp = RREG32_SOC15(GC, 0, mmGRBM_SOFT_RESET);
                }
 
                /* Wait a little for things to settle down */
@@ -2415,9 +2422,9 @@ static uint64_t gfx_v9_0_get_gpu_clock_counter(struct amdgpu_device *adev)
        uint64_t clock;
 
        mutex_lock(&adev->gfx.gpu_clock_mutex);
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CAPTURE_GPU_CLOCK_COUNT), 1);
-       clock = (uint64_t)RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_GPU_CLOCK_COUNT_LSB)) |
-               ((uint64_t)RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_GPU_CLOCK_COUNT_MSB)) << 32ULL);
+       WREG32_SOC15(GC, 0, mmRLC_CAPTURE_GPU_CLOCK_COUNT, 1);
+       clock = (uint64_t)RREG32_SOC15(GC, 0, mmRLC_GPU_CLOCK_COUNT_LSB) |
+               ((uint64_t)RREG32_SOC15(GC, 0, mmRLC_GPU_CLOCK_COUNT_MSB) << 32ULL);
        mutex_unlock(&adev->gfx.gpu_clock_mutex);
        return clock;
 }
@@ -2497,7 +2504,7 @@ static void gfx_v9_0_enter_rlc_safe_mode(struct amdgpu_device *adev)
                return;
 
        /* if RLC is not enabled, do nothing */
-       rlc_setting = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CNTL));
+       rlc_setting = RREG32_SOC15(GC, 0, mmRLC_CNTL);
        if (!(rlc_setting & RLC_CNTL__RLC_ENABLE_F32_MASK))
                return;
 
@@ -2506,7 +2513,7 @@ static void gfx_v9_0_enter_rlc_safe_mode(struct amdgpu_device *adev)
             AMD_CG_SUPPORT_GFX_3D_CGCG)) {
                data = RLC_SAFE_MODE__CMD_MASK;
                data |= (1 << RLC_SAFE_MODE__MESSAGE__SHIFT);
-               WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_SAFE_MODE), data);
+               WREG32_SOC15(GC, 0, mmRLC_SAFE_MODE, data);
 
                /* wait for RLC_SAFE_MODE */
                for (i = 0; i < adev->usec_timeout; i++) {
@@ -2526,7 +2533,7 @@ static void gfx_v9_0_exit_rlc_safe_mode(struct amdgpu_device *adev)
                return;
 
        /* if RLC is not enabled, do nothing */
-       rlc_setting = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CNTL));
+       rlc_setting = RREG32_SOC15(GC, 0, mmRLC_CNTL);
        if (!(rlc_setting & RLC_CNTL__RLC_ENABLE_F32_MASK))
                return;
 
@@ -2537,7 +2544,7 @@ static void gfx_v9_0_exit_rlc_safe_mode(struct amdgpu_device *adev)
                 * mode.
                 */
                data = RLC_SAFE_MODE__CMD_MASK;
-               WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_SAFE_MODE), data);
+               WREG32_SOC15(GC, 0, mmRLC_SAFE_MODE, data);
                adev->gfx.rlc.in_safe_mode = false;
        }
 }
@@ -2550,7 +2557,7 @@ static void gfx_v9_0_update_medium_grain_clock_gating(struct amdgpu_device *adev
        /* It is disabled by HW by default */
        if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_MGCG)) {
                /* 1 - RLC_CGTT_MGCG_OVERRIDE */
-               def = data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE));
+               def = data = RREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE);
                data &= ~(RLC_CGTT_MGCG_OVERRIDE__CPF_CGTT_SCLK_OVERRIDE_MASK |
                          RLC_CGTT_MGCG_OVERRIDE__GRBM_CGTT_SCLK_OVERRIDE_MASK |
                          RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGCG_OVERRIDE_MASK |
@@ -2560,48 +2567,48 @@ static void gfx_v9_0_update_medium_grain_clock_gating(struct amdgpu_device *adev
                data |= RLC_CGTT_MGCG_OVERRIDE__RLC_CGTT_SCLK_OVERRIDE_MASK;
 
                if (def != data)
-                       WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE), data);
+                       WREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE, data);
 
                /* MGLS is a global flag to control all MGLS in GFX */
                if (adev->cg_flags & AMD_CG_SUPPORT_GFX_MGLS) {
                        /* 2 - RLC memory Light sleep */
                        if (adev->cg_flags & AMD_CG_SUPPORT_GFX_RLC_LS) {
-                               def = data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_MEM_SLP_CNTL));
+                               def = data = RREG32_SOC15(GC, 0, mmRLC_MEM_SLP_CNTL);
                                data |= RLC_MEM_SLP_CNTL__RLC_MEM_LS_EN_MASK;
                                if (def != data)
-                                       WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_MEM_SLP_CNTL), data);
+                                       WREG32_SOC15(GC, 0, mmRLC_MEM_SLP_CNTL, data);
                        }
                        /* 3 - CP memory Light sleep */
                        if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CP_LS) {
-                               def = data = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MEM_SLP_CNTL));
+                               def = data = RREG32_SOC15(GC, 0, mmCP_MEM_SLP_CNTL);
                                data |= CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK;
                                if (def != data)
-                                       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MEM_SLP_CNTL), data);
+                                       WREG32_SOC15(GC, 0, mmCP_MEM_SLP_CNTL, data);
                        }
                }
        } else {
                /* 1 - MGCG_OVERRIDE */
-               def = data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE));
+               def = data = RREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE);
                data |= (RLC_CGTT_MGCG_OVERRIDE__CPF_CGTT_SCLK_OVERRIDE_MASK |
                         RLC_CGTT_MGCG_OVERRIDE__RLC_CGTT_SCLK_OVERRIDE_MASK |
                         RLC_CGTT_MGCG_OVERRIDE__GRBM_CGTT_SCLK_OVERRIDE_MASK |
                         RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGCG_OVERRIDE_MASK |
                         RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGLS_OVERRIDE_MASK);
                if (def != data)
-                       WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE), data);
+                       WREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE, data);
 
                /* 2 - disable MGLS in RLC */
-               data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_MEM_SLP_CNTL));
+               data = RREG32_SOC15(GC, 0, mmRLC_MEM_SLP_CNTL);
                if (data & RLC_MEM_SLP_CNTL__RLC_MEM_LS_EN_MASK) {
                        data &= ~RLC_MEM_SLP_CNTL__RLC_MEM_LS_EN_MASK;
-                       WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_MEM_SLP_CNTL), data);
+                       WREG32_SOC15(GC, 0, mmRLC_MEM_SLP_CNTL, data);
                }
 
                /* 3 - disable MGLS in CP */
-               data = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MEM_SLP_CNTL));
+               data = RREG32_SOC15(GC, 0, mmCP_MEM_SLP_CNTL);
                if (data & CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK) {
                        data &= ~CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK;
-                       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MEM_SLP_CNTL), data);
+                       WREG32_SOC15(GC, 0, mmCP_MEM_SLP_CNTL, data);
                }
        }
 }
@@ -2616,37 +2623,37 @@ static void gfx_v9_0_update_3d_clock_gating(struct amdgpu_device *adev,
        /* Enable 3D CGCG/CGLS */
        if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_3D_CGCG)) {
                /* write cmd to clear cgcg/cgls ov */
-               def = data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE));
+               def = data = RREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE);
                /* unset CGCG override */
                data &= ~RLC_CGTT_MGCG_OVERRIDE__GFXIP_GFX3D_CG_OVERRIDE_MASK;
                /* update CGCG and CGLS override bits */
                if (def != data)
-                       WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE), data);
+                       WREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE, data);
                /* enable 3Dcgcg FSM(0x0020003f) */
-               def = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D));
+               def = RREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D);
                data = (0x2000 << RLC_CGCG_CGLS_CTRL_3D__CGCG_GFX_IDLE_THRESHOLD__SHIFT) |
                        RLC_CGCG_CGLS_CTRL_3D__CGCG_EN_MASK;
                if (adev->cg_flags & AMD_CG_SUPPORT_GFX_3D_CGLS)
                        data |= (0x000F << RLC_CGCG_CGLS_CTRL_3D__CGLS_REP_COMPANSAT_DELAY__SHIFT) |
                                RLC_CGCG_CGLS_CTRL_3D__CGLS_EN_MASK;
                if (def != data)
-                       WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D), data);
+                       WREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D, data);
 
                /* set IDLE_POLL_COUNT(0x00900100) */
-               def = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB_WPTR_POLL_CNTL));
+               def = RREG32_SOC15(GC, 0, mmCP_RB_WPTR_POLL_CNTL);
                data = (0x0100 << CP_RB_WPTR_POLL_CNTL__POLL_FREQUENCY__SHIFT) |
                        (0x0090 << CP_RB_WPTR_POLL_CNTL__IDLE_POLL_COUNT__SHIFT);
                if (def != data)
-                       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB_WPTR_POLL_CNTL), data);
+                       WREG32_SOC15(GC, 0, mmCP_RB_WPTR_POLL_CNTL, data);
        } else {
                /* Disable CGCG/CGLS */
-               def = data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D));
+               def = data = RREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D);
                /* disable cgcg, cgls should be disabled */
                data &= ~(RLC_CGCG_CGLS_CTRL_3D__CGCG_EN_MASK |
                          RLC_CGCG_CGLS_CTRL_3D__CGLS_EN_MASK);
                /* disable cgcg and cgls in FSM */
                if (def != data)
-                       WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D), data);
+                       WREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D, data);
        }
 
        adev->gfx.rlc.funcs->exit_safe_mode(adev);
@@ -2660,7 +2667,7 @@ static void gfx_v9_0_update_coarse_grain_clock_gating(struct amdgpu_device *adev
        adev->gfx.rlc.funcs->enter_safe_mode(adev);
 
        if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGCG)) {
-               def = data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE));
+               def = data = RREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE);
                /* unset CGCG override */
                data &= ~RLC_CGTT_MGCG_OVERRIDE__GFXIP_CGCG_OVERRIDE_MASK;
                if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGLS)
@@ -2669,31 +2676,31 @@ static void gfx_v9_0_update_coarse_grain_clock_gating(struct amdgpu_device *adev
                        data |= RLC_CGTT_MGCG_OVERRIDE__GFXIP_CGLS_OVERRIDE_MASK;
                /* update CGCG and CGLS override bits */
                if (def != data)
-                       WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE), data);
+                       WREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE, data);
 
                /* enable cgcg FSM(0x0020003F) */
-               def = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGCG_CGLS_CTRL));
+               def = RREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL);
                data = (0x2000 << RLC_CGCG_CGLS_CTRL__CGCG_GFX_IDLE_THRESHOLD__SHIFT) |
                        RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK;
                if (adev->cg_flags & AMD_CG_SUPPORT_GFX_CGLS)
                        data |= (0x000F << RLC_CGCG_CGLS_CTRL__CGLS_REP_COMPANSAT_DELAY__SHIFT) |
                                RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK;
                if (def != data)
-                       WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGCG_CGLS_CTRL), data);
+                       WREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL, data);
 
                /* set IDLE_POLL_COUNT(0x00900100) */
-               def = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB_WPTR_POLL_CNTL));
+               def = RREG32_SOC15(GC, 0, mmCP_RB_WPTR_POLL_CNTL);
                data = (0x0100 << CP_RB_WPTR_POLL_CNTL__POLL_FREQUENCY__SHIFT) |
                        (0x0090 << CP_RB_WPTR_POLL_CNTL__IDLE_POLL_COUNT__SHIFT);
                if (def != data)
-                       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB_WPTR_POLL_CNTL), data);
+                       WREG32_SOC15(GC, 0, mmCP_RB_WPTR_POLL_CNTL, data);
        } else {
-               def = data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGCG_CGLS_CTRL));
+               def = data = RREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL);
                /* reset CGCG/CGLS bits */
                data &= ~(RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK | RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK);
                /* disable cgcg and cgls in FSM */
                if (def != data)
-                       WREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGCG_CGLS_CTRL), data);
+                       WREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL, data);
        }
 
        adev->gfx.rlc.funcs->exit_safe_mode(adev);
@@ -2740,6 +2747,9 @@ static int gfx_v9_0_set_clockgating_state(void *handle,
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
+       if (amdgpu_sriov_vf(adev))
+               return 0;
+
        switch (adev->asic_type) {
        case CHIP_VEGA10:
                gfx_v9_0_update_gfx_clock_gating(adev,
@@ -2760,12 +2770,12 @@ static void gfx_v9_0_get_clockgating_state(void *handle, u32 *flags)
                *flags = 0;
 
        /* AMD_CG_SUPPORT_GFX_MGCG */
-       data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE));
+       data = RREG32_SOC15(GC, 0, mmRLC_CGTT_MGCG_OVERRIDE);
        if (!(data & RLC_CGTT_MGCG_OVERRIDE__GFXIP_MGCG_OVERRIDE_MASK))
                *flags |= AMD_CG_SUPPORT_GFX_MGCG;
 
        /* AMD_CG_SUPPORT_GFX_CGCG */
-       data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGCG_CGLS_CTRL));
+       data = RREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL);
        if (data & RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK)
                *flags |= AMD_CG_SUPPORT_GFX_CGCG;
 
@@ -2774,17 +2784,17 @@ static void gfx_v9_0_get_clockgating_state(void *handle, u32 *flags)
                *flags |= AMD_CG_SUPPORT_GFX_CGLS;
 
        /* AMD_CG_SUPPORT_GFX_RLC_LS */
-       data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_MEM_SLP_CNTL));
+       data = RREG32_SOC15(GC, 0, mmRLC_MEM_SLP_CNTL);
        if (data & RLC_MEM_SLP_CNTL__RLC_MEM_LS_EN_MASK)
                *flags |= AMD_CG_SUPPORT_GFX_RLC_LS | AMD_CG_SUPPORT_GFX_MGLS;
 
        /* AMD_CG_SUPPORT_GFX_CP_LS */
-       data = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MEM_SLP_CNTL));
+       data = RREG32_SOC15(GC, 0, mmCP_MEM_SLP_CNTL);
        if (data & CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK)
                *flags |= AMD_CG_SUPPORT_GFX_CP_LS | AMD_CG_SUPPORT_GFX_MGLS;
 
        /* AMD_CG_SUPPORT_GFX_3D_CGCG */
-       data = RREG32(SOC15_REG_OFFSET(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D));
+       data = RREG32_SOC15(GC, 0, mmRLC_CGCG_CGLS_CTRL_3D);
        if (data & RLC_CGCG_CGLS_CTRL_3D__CGCG_EN_MASK)
                *flags |= AMD_CG_SUPPORT_GFX_3D_CGCG;
 
@@ -2807,8 +2817,8 @@ static u64 gfx_v9_0_ring_get_wptr_gfx(struct amdgpu_ring *ring)
        if (ring->use_doorbell) {
                wptr = atomic64_read((atomic64_t *)&adev->wb.wb[ring->wptr_offs]);
        } else {
-               wptr = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB0_WPTR));
-               wptr += (u64)RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB0_WPTR_HI)) << 32;
+               wptr = RREG32_SOC15(GC, 0, mmCP_RB0_WPTR);
+               wptr += (u64)RREG32_SOC15(GC, 0, mmCP_RB0_WPTR_HI) << 32;
        }
 
        return wptr;
@@ -2823,8 +2833,8 @@ static void gfx_v9_0_ring_set_wptr_gfx(struct amdgpu_ring *ring)
                atomic64_set((atomic64_t*)&adev->wb.wb[ring->wptr_offs], ring->wptr);
                WDOORBELL64(ring->doorbell_index, ring->wptr);
        } else {
-               WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB0_WPTR), lower_32_bits(ring->wptr));
-               WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_RB0_WPTR_HI), upper_32_bits(ring->wptr));
+               WREG32_SOC15(GC, 0, mmCP_RB0_WPTR, lower_32_bits(ring->wptr));
+               WREG32_SOC15(GC, 0, mmCP_RB0_WPTR_HI, upper_32_bits(ring->wptr));
        }
 }
 
@@ -2956,35 +2966,29 @@ static void gfx_v9_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring)
 static void gfx_v9_0_ring_emit_vm_flush(struct amdgpu_ring *ring,
                                        unsigned vm_id, uint64_t pd_addr)
 {
+       struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->funcs->vmhub];
        int usepfp = (ring->funcs->type == AMDGPU_RING_TYPE_GFX);
        uint32_t req = ring->adev->gart.gart_funcs->get_invalidate_req(vm_id);
-       unsigned eng = ring->idx;
-       unsigned i;
+       unsigned eng = ring->vm_inv_eng;
 
        pd_addr = pd_addr | 0x1; /* valid bit */
        /* now only use physical base address of PDE and valid */
        BUG_ON(pd_addr & 0xFFFF00000000003EULL);
 
-       for (i = 0; i < AMDGPU_MAX_VMHUBS; ++i) {
-               struct amdgpu_vmhub *hub = &ring->adev->vmhub[i];
-
-               gfx_v9_0_write_data_to_reg(ring, usepfp, true,
-                                          hub->ctx0_ptb_addr_lo32
-                                          + (2 * vm_id),
-                                          lower_32_bits(pd_addr));
+       gfx_v9_0_write_data_to_reg(ring, usepfp, true,
+                                  hub->ctx0_ptb_addr_lo32 + (2 * vm_id),
+                                  lower_32_bits(pd_addr));
 
-               gfx_v9_0_write_data_to_reg(ring, usepfp, true,
-                                          hub->ctx0_ptb_addr_hi32
-                                          + (2 * vm_id),
-                                          upper_32_bits(pd_addr));
+       gfx_v9_0_write_data_to_reg(ring, usepfp, true,
+                                  hub->ctx0_ptb_addr_hi32 + (2 * vm_id),
+                                  upper_32_bits(pd_addr));
 
-               gfx_v9_0_write_data_to_reg(ring, usepfp, true,
-                                          hub->vm_inv_eng0_req + eng, req);
+       gfx_v9_0_write_data_to_reg(ring, usepfp, true,
+                                  hub->vm_inv_eng0_req + eng, req);
 
-               /* wait for the invalidate to complete */
-               gfx_v9_0_wait_reg_mem(ring, 0, 0, 0, hub->vm_inv_eng0_ack +
-                                     eng, 0, 1 << vm_id, 1 << vm_id, 0x20);
-       }
+       /* wait for the invalidate to complete */
+       gfx_v9_0_wait_reg_mem(ring, 0, 0, 0, hub->vm_inv_eng0_ack +
+                             eng, 0, 1 << vm_id, 1 << vm_id, 0x20);
 
        /* compute doesn't have PFP */
        if (usepfp) {
@@ -3373,9 +3377,7 @@ static int gfx_v9_0_kiq_set_interrupt_state(struct amdgpu_device *adev,
                                            enum amdgpu_interrupt_state state)
 {
        uint32_t tmp, target;
-       struct amdgpu_ring *ring = (struct amdgpu_ring *)src->data;
-
-       BUG_ON(!ring || (ring->funcs->type != AMDGPU_RING_TYPE_KIQ));
+       struct amdgpu_ring *ring = &(adev->gfx.kiq.ring);
 
        if (ring->me == 1)
                target = SOC15_REG_OFFSET(GC, 0, mmCP_ME1_PIPE0_INT_CNTL);
@@ -3386,20 +3388,20 @@ static int gfx_v9_0_kiq_set_interrupt_state(struct amdgpu_device *adev,
        switch (type) {
        case AMDGPU_CP_KIQ_IRQ_DRIVER0:
                if (state == AMDGPU_IRQ_STATE_DISABLE) {
-                       tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCPC_INT_CNTL));
+                       tmp = RREG32_SOC15(GC, 0, mmCPC_INT_CNTL);
                        tmp = REG_SET_FIELD(tmp, CPC_INT_CNTL,
                                                 GENERIC2_INT_ENABLE, 0);
-                       WREG32(SOC15_REG_OFFSET(GC, 0, mmCPC_INT_CNTL), tmp);
+                       WREG32_SOC15(GC, 0, mmCPC_INT_CNTL, tmp);
 
                        tmp = RREG32(target);
                        tmp = REG_SET_FIELD(tmp, CP_ME2_PIPE0_INT_CNTL,
                                                 GENERIC2_INT_ENABLE, 0);
                        WREG32(target, tmp);
                } else {
-                       tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCPC_INT_CNTL));
+                       tmp = RREG32_SOC15(GC, 0, mmCPC_INT_CNTL);
                        tmp = REG_SET_FIELD(tmp, CPC_INT_CNTL,
                                                 GENERIC2_INT_ENABLE, 1);
-                       WREG32(SOC15_REG_OFFSET(GC, 0, mmCPC_INT_CNTL), tmp);
+                       WREG32_SOC15(GC, 0, mmCPC_INT_CNTL, tmp);
 
                        tmp = RREG32(target);
                        tmp = REG_SET_FIELD(tmp, CP_ME2_PIPE0_INT_CNTL,
@@ -3419,9 +3421,7 @@ static int gfx_v9_0_kiq_irq(struct amdgpu_device *adev,
                            struct amdgpu_iv_entry *entry)
 {
        u8 me_id, pipe_id, queue_id;
-       struct amdgpu_ring *ring = (struct amdgpu_ring *)source->data;
-
-       BUG_ON(!ring || (ring->funcs->type != AMDGPU_RING_TYPE_KIQ));
+       struct amdgpu_ring *ring = &(adev->gfx.kiq.ring);
 
        me_id = (entry->ring_id & 0x0c) >> 2;
        pipe_id = (entry->ring_id & 0x03) >> 0;
@@ -3456,13 +3456,14 @@ static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_gfx = {
        .align_mask = 0xff,
        .nop = PACKET3(PACKET3_NOP, 0x3FFF),
        .support_64bit_ptrs = true,
+       .vmhub = AMDGPU_GFXHUB,
        .get_rptr = gfx_v9_0_ring_get_rptr_gfx,
        .get_wptr = gfx_v9_0_ring_get_wptr_gfx,
        .set_wptr = gfx_v9_0_ring_set_wptr_gfx,
        .emit_frame_size = /* totally 242 maximum if 16 IBs */
                5 +  /* COND_EXEC */
                7 +  /* PIPELINE_SYNC */
-               46 + /* VM_FLUSH */
+               24 + /* VM_FLUSH */
                8 +  /* FENCE for VM_FLUSH */
                20 + /* GDS switch */
                4 + /* double SWITCH_BUFFER,
@@ -3500,6 +3501,7 @@ static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_compute = {
        .align_mask = 0xff,
        .nop = PACKET3(PACKET3_NOP, 0x3FFF),
        .support_64bit_ptrs = true,
+       .vmhub = AMDGPU_GFXHUB,
        .get_rptr = gfx_v9_0_ring_get_rptr_compute,
        .get_wptr = gfx_v9_0_ring_get_wptr_compute,
        .set_wptr = gfx_v9_0_ring_set_wptr_compute,
@@ -3508,7 +3510,7 @@ static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_compute = {
                7 + /* gfx_v9_0_ring_emit_hdp_flush */
                5 + /* gfx_v9_0_ring_emit_hdp_invalidate */
                7 + /* gfx_v9_0_ring_emit_pipeline_sync */
-               64 + /* gfx_v9_0_ring_emit_vm_flush */
+               24 + /* gfx_v9_0_ring_emit_vm_flush */
                8 + 8 + 8, /* gfx_v9_0_ring_emit_fence x3 for user fence, vm fence */
        .emit_ib_size = 4, /* gfx_v9_0_ring_emit_ib_compute */
        .emit_ib = gfx_v9_0_ring_emit_ib_compute,
@@ -3529,6 +3531,7 @@ static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_kiq = {
        .align_mask = 0xff,
        .nop = PACKET3(PACKET3_NOP, 0x3FFF),
        .support_64bit_ptrs = true,
+       .vmhub = AMDGPU_GFXHUB,
        .get_rptr = gfx_v9_0_ring_get_rptr_compute,
        .get_wptr = gfx_v9_0_ring_get_wptr_compute,
        .set_wptr = gfx_v9_0_ring_set_wptr_compute,
@@ -3537,7 +3540,7 @@ static const struct amdgpu_ring_funcs gfx_v9_0_ring_funcs_kiq = {
                7 + /* gfx_v9_0_ring_emit_hdp_flush */
                5 + /* gfx_v9_0_ring_emit_hdp_invalidate */
                7 + /* gfx_v9_0_ring_emit_pipeline_sync */
-               64 + /* gfx_v9_0_ring_emit_vm_flush */
+               24 + /* gfx_v9_0_ring_emit_vm_flush */
                8 + 8 + 8, /* gfx_v9_0_ring_emit_fence_kiq x3 for user fence, vm fence */
        .emit_ib_size = 4, /* gfx_v9_0_ring_emit_ib_compute */
        .emit_ib = gfx_v9_0_ring_emit_ib_compute,
@@ -3612,7 +3615,7 @@ static void gfx_v9_0_set_rlc_funcs(struct amdgpu_device *adev)
 static void gfx_v9_0_set_gds_init(struct amdgpu_device *adev)
 {
        /* init asci gds info */
-       adev->gds.mem.total_size = RREG32(SOC15_REG_OFFSET(GC, 0, mmGDS_VMID0_SIZE));
+       adev->gds.mem.total_size = RREG32_SOC15(GC, 0, mmGDS_VMID0_SIZE);
        adev->gds.gws.total_size = 64;
        adev->gds.oa.total_size = 16;
 
@@ -3641,8 +3644,8 @@ static u32 gfx_v9_0_get_cu_active_bitmap(struct amdgpu_device *adev)
 {
        u32 data, mask;
 
-       data = RREG32(SOC15_REG_OFFSET(GC, 0, mmCC_GC_SHADER_ARRAY_CONFIG));
-       data |= RREG32(SOC15_REG_OFFSET(GC, 0, mmGC_USER_SHADER_ARRAY_CONFIG));
+       data = RREG32_SOC15(GC, 0, mmCC_GC_SHADER_ARRAY_CONFIG);
+       data |= RREG32_SOC15(GC, 0, mmGC_USER_SHADER_ARRAY_CONFIG);
 
        data &= CC_GC_SHADER_ARRAY_CONFIG__INACTIVE_CUS_MASK;
        data >>= CC_GC_SHADER_ARRAY_CONFIG__INACTIVE_CUS__SHIFT;
@@ -3763,25 +3766,25 @@ static int gfx_v9_0_init_queue(struct amdgpu_ring *ring)
        eop_gpu_addr = adev->gfx.mec.hpd_eop_gpu_addr + (ring->queue * MEC_HPD_SIZE);
        eop_gpu_addr >>= 8;
 
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_EOP_BASE_ADDR), lower_32_bits(eop_gpu_addr));
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_EOP_BASE_ADDR_HI), upper_32_bits(eop_gpu_addr));
+       WREG32_SOC15(GC, 0, mmCP_HQD_EOP_BASE_ADDR, lower_32_bits(eop_gpu_addr));
+       WREG32_SOC15(GC, 0, mmCP_HQD_EOP_BASE_ADDR_HI, upper_32_bits(eop_gpu_addr));
        mqd->cp_hqd_eop_base_addr_lo = lower_32_bits(eop_gpu_addr);
        mqd->cp_hqd_eop_base_addr_hi = upper_32_bits(eop_gpu_addr);
 
        /* set the EOP size, register value is 2^(EOP_SIZE+1) dwords */
-       tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_EOP_CONTROL));
+       tmp = RREG32_SOC15(GC, 0, mmCP_HQD_EOP_CONTROL);
        tmp = REG_SET_FIELD(tmp, CP_HQD_EOP_CONTROL, EOP_SIZE,
                                    (order_base_2(MEC_HPD_SIZE / 4) - 1));
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_EOP_CONTROL), tmp);
+       WREG32_SOC15(GC, 0, mmCP_HQD_EOP_CONTROL, tmp);
 
        /* enable doorbell? */
-       tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL));
+       tmp = RREG32_SOC15(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL);
        if (use_doorbell)
                tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, DOORBELL_EN, 1);
        else
                tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, DOORBELL_EN, 0);
 
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL), tmp);
+       WREG32_SOC15(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL, tmp);
        mqd->cp_hqd_pq_doorbell_control = tmp;
 
        /* disable the queue if it's active */
@@ -3790,40 +3793,40 @@ static int gfx_v9_0_init_queue(struct amdgpu_ring *ring)
        mqd->cp_hqd_pq_rptr = 0;
        mqd->cp_hqd_pq_wptr_lo = 0;
        mqd->cp_hqd_pq_wptr_hi = 0;
-       if (RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_ACTIVE)) & 1) {
-               WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_DEQUEUE_REQUEST), 1);
+       if (RREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE) & 1) {
+               WREG32_SOC15(GC, 0, mmCP_HQD_DEQUEUE_REQUEST, 1);
                for (j = 0; j < adev->usec_timeout; j++) {
-                       if (!(RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_ACTIVE)) & 1))
+                       if (!(RREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE) & 1))
                                break;
                        udelay(1);
                }
-               WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_DEQUEUE_REQUEST), mqd->cp_hqd_dequeue_request);
-               WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_RPTR), mqd->cp_hqd_pq_rptr);
-               WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_LO), mqd->cp_hqd_pq_wptr_lo);
-               WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_HI), mqd->cp_hqd_pq_wptr_hi);
+               WREG32_SOC15(GC, 0, mmCP_HQD_DEQUEUE_REQUEST, mqd->cp_hqd_dequeue_request);
+               WREG32_SOC15(GC, 0, mmCP_HQD_PQ_RPTR, mqd->cp_hqd_pq_rptr);
+               WREG32_SOC15(GC, 0, mmCP_HQD_PQ_WPTR_LO, mqd->cp_hqd_pq_wptr_lo);
+               WREG32_SOC15(GC, 0, mmCP_HQD_PQ_WPTR_HI, mqd->cp_hqd_pq_wptr_hi);
        }
 
        /* set the pointer to the MQD */
        mqd->cp_mqd_base_addr_lo = mqd_gpu_addr & 0xfffffffc;
        mqd->cp_mqd_base_addr_hi = upper_32_bits(mqd_gpu_addr);
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MQD_BASE_ADDR), mqd->cp_mqd_base_addr_lo);
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MQD_BASE_ADDR_HI), mqd->cp_mqd_base_addr_hi);
+       WREG32_SOC15(GC, 0, mmCP_MQD_BASE_ADDR, mqd->cp_mqd_base_addr_lo);
+       WREG32_SOC15(GC, 0, mmCP_MQD_BASE_ADDR_HI, mqd->cp_mqd_base_addr_hi);
 
        /* set MQD vmid to 0 */
-       tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MQD_CONTROL));
+       tmp = RREG32_SOC15(GC, 0, mmCP_MQD_CONTROL);
        tmp = REG_SET_FIELD(tmp, CP_MQD_CONTROL, VMID, 0);
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MQD_CONTROL), tmp);
+       WREG32_SOC15(GC, 0, mmCP_MQD_CONTROL, tmp);
        mqd->cp_mqd_control = tmp;
 
        /* set the pointer to the HQD, this is similar CP_RB0_BASE/_HI */
        hqd_gpu_addr = ring->gpu_addr >> 8;
        mqd->cp_hqd_pq_base_lo = hqd_gpu_addr;
        mqd->cp_hqd_pq_base_hi = upper_32_bits(hqd_gpu_addr);
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_BASE), mqd->cp_hqd_pq_base_lo);
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_BASE_HI), mqd->cp_hqd_pq_base_hi);
+       WREG32_SOC15(GC, 0, mmCP_HQD_PQ_BASE, mqd->cp_hqd_pq_base_lo);
+       WREG32_SOC15(GC, 0, mmCP_HQD_PQ_BASE_HI, mqd->cp_hqd_pq_base_hi);
 
        /* set up the HQD, this is similar to CP_RB0_CNTL */
-       tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_CONTROL));
+       tmp = RREG32_SOC15(GC, 0, mmCP_HQD_PQ_CONTROL);
        tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, QUEUE_SIZE,
                (order_base_2(ring->ring_size / 4) - 1));
        tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, RPTR_BLOCK_SIZE,
@@ -3835,7 +3838,7 @@ static int gfx_v9_0_init_queue(struct amdgpu_ring *ring)
        tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, ROQ_PQ_IB_FLIP, 0);
        tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, PRIV_STATE, 1);
        tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_CONTROL, KMD_QUEUE, 1);
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_CONTROL), tmp);
+       WREG32_SOC15(GC, 0, mmCP_HQD_PQ_CONTROL, tmp);
        mqd->cp_hqd_pq_control = tmp;
 
        /* set the wb address wether it's enabled or not */
@@ -3843,27 +3846,27 @@ static int gfx_v9_0_init_queue(struct amdgpu_ring *ring)
        mqd->cp_hqd_pq_rptr_report_addr_lo = wb_gpu_addr & 0xfffffffc;
        mqd->cp_hqd_pq_rptr_report_addr_hi =
        upper_32_bits(wb_gpu_addr) & 0xffff;
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_RPTR_REPORT_ADDR),
+       WREG32_SOC15(GC, 0, mmCP_HQD_PQ_RPTR_REPORT_ADDR,
                mqd->cp_hqd_pq_rptr_report_addr_lo);
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_RPTR_REPORT_ADDR_HI),
+       WREG32_SOC15(GC, 0, mmCP_HQD_PQ_RPTR_REPORT_ADDR_HI,
                mqd->cp_hqd_pq_rptr_report_addr_hi);
 
        /* only used if CP_PQ_WPTR_POLL_CNTL.CP_PQ_WPTR_POLL_CNTL__EN_MASK=1 */
        wb_gpu_addr = adev->wb.gpu_addr + (ring->wptr_offs * 4);
        mqd->cp_hqd_pq_wptr_poll_addr_lo = wb_gpu_addr & 0xfffffffc;
        mqd->cp_hqd_pq_wptr_poll_addr_hi = upper_32_bits(wb_gpu_addr) & 0xffff;
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_POLL_ADDR),
+       WREG32_SOC15(GC, 0, mmCP_HQD_PQ_WPTR_POLL_ADDR,
                mqd->cp_hqd_pq_wptr_poll_addr_lo);
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI),
+       WREG32_SOC15(GC, 0, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI,
                mqd->cp_hqd_pq_wptr_poll_addr_hi);
 
        /* enable the doorbell if requested */
        if (use_doorbell) {
-               WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MEC_DOORBELL_RANGE_LOWER),
+               WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_LOWER,
                        (AMDGPU_DOORBELL64_KIQ * 2) << 2);
-               WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_MEC_DOORBELL_RANGE_UPPER),
+               WREG32_SOC15(GC, 0, mmCP_MEC_DOORBELL_RANGE_UPPER,
                        (AMDGPU_DOORBELL64_MEC_RING7 * 2) << 2);
-               tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL));
+               tmp = RREG32_SOC15(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL);
                tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL,
                        DOORBELL_OFFSET, ring->doorbell_index);
                tmp = REG_SET_FIELD(tmp, CP_HQD_PQ_DOORBELL_CONTROL, DOORBELL_EN, 1);
@@ -3874,25 +3877,25 @@ static int gfx_v9_0_init_queue(struct amdgpu_ring *ring)
        } else {
                mqd->cp_hqd_pq_doorbell_control = 0;
        }
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL),
+       WREG32_SOC15(GC, 0, mmCP_HQD_PQ_DOORBELL_CONTROL,
                mqd->cp_hqd_pq_doorbell_control);
 
        /* reset read and write pointers, similar to CP_RB0_WPTR/_RPTR */
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_LO), mqd->cp_hqd_pq_wptr_lo);
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PQ_WPTR_HI), mqd->cp_hqd_pq_wptr_hi);
+       WREG32_SOC15(GC, 0, mmCP_HQD_PQ_WPTR_LO, mqd->cp_hqd_pq_wptr_lo);
+       WREG32_SOC15(GC, 0, mmCP_HQD_PQ_WPTR_HI, mqd->cp_hqd_pq_wptr_hi);
 
        /* set the vmid for the queue */
        mqd->cp_hqd_vmid = 0;
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_VMID), mqd->cp_hqd_vmid);
+       WREG32_SOC15(GC, 0, mmCP_HQD_VMID, mqd->cp_hqd_vmid);
 
-       tmp = RREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PERSISTENT_STATE));
+       tmp = RREG32_SOC15(GC, 0, mmCP_HQD_PERSISTENT_STATE);
        tmp = REG_SET_FIELD(tmp, CP_HQD_PERSISTENT_STATE, PRELOAD_SIZE, 0x53);
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_PERSISTENT_STATE), tmp);
+       WREG32_SOC15(GC, 0, mmCP_HQD_PERSISTENT_STATE, tmp);
        mqd->cp_hqd_persistent_state = tmp;
 
        /* activate the queue */
        mqd->cp_hqd_active = 1;
-       WREG32(SOC15_REG_OFFSET(GC, 0, mmCP_HQD_ACTIVE), mqd->cp_hqd_active);
+       WREG32_SOC15(GC, 0, mmCP_HQD_ACTIVE, mqd->cp_hqd_active);
 
        soc15_grbm_select(adev, 0, 0, 0, 0);
        mutex_unlock(&adev->srbm_mutex);
index 631aef38126d76d452cf7c9b6f2918e42b152827..a572979f186cdaeba52701fb8183850e16581143 100644 (file)
@@ -346,7 +346,8 @@ static int gmc_v6_0_mc_init(struct amdgpu_device *adev)
         * size equal to the 1024 or vram, whichever is larger.
         */
        if (amdgpu_gart_size == -1)
-               adev->mc.gtt_size = max((1024ULL << 20), adev->mc.mc_vram_size);
+               adev->mc.gtt_size = max((AMDGPU_DEFAULT_GTT_SIZE_MB << 20),
+                                       adev->mc.mc_vram_size);
        else
                adev->mc.gtt_size = (uint64_t)amdgpu_gart_size << 20;
 
@@ -621,7 +622,7 @@ static int gmc_v6_0_vm_init(struct amdgpu_device *adev)
         * amdgpu graphics/compute will use VMIDs 1-7
         * amdkfd will use VMIDs 8-15
         */
-       adev->vm_manager.num_ids = AMDGPU_NUM_OF_VMIDS;
+       adev->vm_manager.id_mgr[0].num_ids = AMDGPU_NUM_OF_VMIDS;
        adev->vm_manager.num_level = 1;
        amdgpu_vm_manager_init(adev);
 
index 92abe12d92bbc0e8c201a96bf7dc79bf2acb4b13..a9083a16a250920c64605bc447ca19c8b3014f3a 100644 (file)
@@ -395,7 +395,8 @@ static int gmc_v7_0_mc_init(struct amdgpu_device *adev)
         * size equal to the 1024 or vram, whichever is larger.
         */
        if (amdgpu_gart_size == -1)
-               adev->mc.gtt_size = max((1024ULL << 20), adev->mc.mc_vram_size);
+               adev->mc.gtt_size = max((AMDGPU_DEFAULT_GTT_SIZE_MB << 20),
+                                       adev->mc.mc_vram_size);
        else
                adev->mc.gtt_size = (uint64_t)amdgpu_gart_size << 20;
 
@@ -746,7 +747,7 @@ static int gmc_v7_0_vm_init(struct amdgpu_device *adev)
         * amdgpu graphics/compute will use VMIDs 1-7
         * amdkfd will use VMIDs 8-15
         */
-       adev->vm_manager.num_ids = AMDGPU_NUM_OF_VMIDS;
+       adev->vm_manager.id_mgr[0].num_ids = AMDGPU_NUM_OF_VMIDS;
        adev->vm_manager.num_level = 1;
        amdgpu_vm_manager_init(adev);
 
index f2ccefc66fd471635f0d56eac2f8d6187194698b..4ac99784160a3ed9fbb59c5bf53a8d1b0a6ec1b4 100644 (file)
@@ -557,7 +557,8 @@ static int gmc_v8_0_mc_init(struct amdgpu_device *adev)
         * size equal to the 1024 or vram, whichever is larger.
         */
        if (amdgpu_gart_size == -1)
-               adev->mc.gtt_size = max((1024ULL << 20), adev->mc.mc_vram_size);
+               adev->mc.gtt_size = max((AMDGPU_DEFAULT_GTT_SIZE_MB << 20),
+                                       adev->mc.mc_vram_size);
        else
                adev->mc.gtt_size = (uint64_t)amdgpu_gart_size << 20;
 
@@ -949,7 +950,7 @@ static int gmc_v8_0_vm_init(struct amdgpu_device *adev)
         * amdgpu graphics/compute will use VMIDs 1-7
         * amdkfd will use VMIDs 8-15
         */
-       adev->vm_manager.num_ids = AMDGPU_NUM_OF_VMIDS;
+       adev->vm_manager.id_mgr[0].num_ids = AMDGPU_NUM_OF_VMIDS;
        adev->vm_manager.num_level = 1;
        amdgpu_vm_manager_init(adev);
 
index 3b045e0b114e758aa32b78577b622001c13d5073..dc1e1c1d6b2430cb9957047a454cde87bf439561 100644 (file)
@@ -386,6 +386,23 @@ static int gmc_v9_0_early_init(void *handle)
 static int gmc_v9_0_late_init(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+       unsigned vm_inv_eng[AMDGPU_MAX_VMHUBS] = { 3, 3 };
+       unsigned i;
+
+       for(i = 0; i < adev->num_rings; ++i) {
+               struct amdgpu_ring *ring = adev->rings[i];
+               unsigned vmhub = ring->funcs->vmhub;
+
+               ring->vm_inv_eng = vm_inv_eng[vmhub]++;
+               dev_info(adev->dev, "ring %u(%s) uses VM inv eng %u on hub %u\n",
+                        ring->idx, ring->name, ring->vm_inv_eng,
+                        ring->funcs->vmhub);
+       }
+
+       /* Engine 17 is used for GART flushes */
+       for(i = 0; i < AMDGPU_MAX_VMHUBS; ++i)
+               BUG_ON(vm_inv_eng[i] > 17);
+
        return amdgpu_irq_get(adev, &adev->mc.vm_fault, 0);
 }
 
@@ -469,7 +486,8 @@ static int gmc_v9_0_mc_init(struct amdgpu_device *adev)
         * size equal to the 1024 or vram, whichever is larger.
         */
        if (amdgpu_gart_size == -1)
-               adev->mc.gtt_size = max((1024ULL << 20), adev->mc.mc_vram_size);
+               adev->mc.gtt_size = max((AMDGPU_DEFAULT_GTT_SIZE_MB << 20),
+                                       adev->mc.mc_vram_size);
        else
                adev->mc.gtt_size = (uint64_t)amdgpu_gart_size << 20;
 
@@ -519,7 +537,8 @@ static int gmc_v9_0_vm_init(struct amdgpu_device *adev)
         * amdgpu graphics/compute will use VMIDs 1-7
         * amdkfd will use VMIDs 8-15
         */
-       adev->vm_manager.num_ids = AMDGPU_NUM_OF_VMIDS;
+       adev->vm_manager.id_mgr[AMDGPU_GFXHUB].num_ids = AMDGPU_NUM_OF_VMIDS;
+       adev->vm_manager.id_mgr[AMDGPU_MMHUB].num_ids = AMDGPU_NUM_OF_VMIDS;
 
        /* TODO: fix num_level for APU when updating vm size and block size */
        if (adev->flags & AMD_IS_APU)
index 62684510ddcdb579629ab707b2f098cc788810f1..dbfe48d1207ab6a492314c94f0fab079bf6447b6 100644 (file)
@@ -511,6 +511,9 @@ static int mmhub_v1_0_set_clockgating_state(void *handle,
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
+       if (amdgpu_sriov_vf(adev))
+               return 0;
+
        switch (adev->asic_type) {
        case CHIP_VEGA10:
                mmhub_v1_0_update_medium_grain_clock_gating(adev,
index 5f0fc8bf16a92afc8d86b9d66a610b70631f5365..8af0bddf85e4b06e89a7200a8592d10c916360ba 100644 (file)
@@ -84,4 +84,61 @@ struct mmsch_v1_0_cmd_indirect_write {
        uint32_t reg_value;
 };
 
+static inline void mmsch_v1_0_insert_direct_wt(struct mmsch_v1_0_cmd_direct_write *direct_wt,
+                                              uint32_t *init_table,
+                                              uint32_t reg_offset,
+                                              uint32_t value)
+{
+       direct_wt->cmd_header.reg_offset = reg_offset;
+       direct_wt->reg_value = value;
+       memcpy((void *)init_table, direct_wt, sizeof(struct mmsch_v1_0_cmd_direct_write));
+}
+
+static inline void mmsch_v1_0_insert_direct_rd_mod_wt(struct mmsch_v1_0_cmd_direct_read_modify_write *direct_rd_mod_wt,
+                                                     uint32_t *init_table,
+                                                     uint32_t reg_offset,
+                                                     uint32_t mask, uint32_t data)
+{
+       direct_rd_mod_wt->cmd_header.reg_offset = reg_offset;
+       direct_rd_mod_wt->mask_value = mask;
+       direct_rd_mod_wt->write_data = data;
+       memcpy((void *)init_table, direct_rd_mod_wt,
+              sizeof(struct mmsch_v1_0_cmd_direct_read_modify_write));
+}
+
+static inline void mmsch_v1_0_insert_direct_poll(struct mmsch_v1_0_cmd_direct_polling *direct_poll,
+                                                uint32_t *init_table,
+                                                uint32_t reg_offset,
+                                                uint32_t mask, uint32_t wait)
+{
+       direct_poll->cmd_header.reg_offset = reg_offset;
+       direct_poll->mask_value = mask;
+       direct_poll->wait_value = wait;
+       memcpy((void *)init_table, direct_poll, sizeof(struct mmsch_v1_0_cmd_direct_polling));
+}
+
+#define MMSCH_V1_0_INSERT_DIRECT_RD_MOD_WT(reg, mask, data) { \
+       mmsch_v1_0_insert_direct_rd_mod_wt(&direct_rd_mod_wt, \
+                                          init_table, (reg), \
+                                          (mask), (data)); \
+       init_table += sizeof(struct mmsch_v1_0_cmd_direct_read_modify_write)/4; \
+       table_size += sizeof(struct mmsch_v1_0_cmd_direct_read_modify_write)/4; \
+}
+
+#define MMSCH_V1_0_INSERT_DIRECT_WT(reg, value) { \
+       mmsch_v1_0_insert_direct_wt(&direct_wt, \
+                                   init_table, (reg), \
+                                   (value)); \
+       init_table += sizeof(struct mmsch_v1_0_cmd_direct_write)/4; \
+       table_size += sizeof(struct mmsch_v1_0_cmd_direct_write)/4; \
+}
+
+#define MMSCH_V1_0_INSERT_DIRECT_POLL(reg, mask, wait) { \
+       mmsch_v1_0_insert_direct_poll(&direct_poll, \
+                                     init_table, (reg), \
+                                     (mask), (wait)); \
+       init_table += sizeof(struct mmsch_v1_0_cmd_direct_polling)/4; \
+       table_size += sizeof(struct mmsch_v1_0_cmd_direct_polling)/4; \
+}
+
 #endif
index 70a3dd13cb02db3170e9f8a50ada744e8753b3c3..7bdc51b02326118938884d6d33ef036456822563 100644 (file)
@@ -368,9 +368,12 @@ static int xgpu_vi_mailbox_rcv_msg(struct amdgpu_device *adev,
        u32 reg;
        u32 mask = REG_FIELD_MASK(MAILBOX_CONTROL, RCV_MSG_VALID);
 
-       reg = RREG32_NO_KIQ(mmMAILBOX_CONTROL);
-       if (!(reg & mask))
-               return -ENOENT;
+       /* workaround: host driver doesn't set VALID for CMPL now */
+       if (event != IDH_FLR_NOTIFICATION_CMPL) {
+               reg = RREG32_NO_KIQ(mmMAILBOX_CONTROL);
+               if (!(reg & mask))
+                       return -ENOENT;
+       }
 
        reg = RREG32_NO_KIQ(mmMAILBOX_MSGBUF_RCV_DW0);
        if (reg != event)
index c3588d1c7cb0f164174598637cec00e238a20682..60a6407ba267b6793286bda01102f9228e60bd76 100644 (file)
@@ -166,11 +166,8 @@ int psp_v3_1_bootloader_load_sysdrv(struct psp_context *psp)
 {
        int ret;
        uint32_t psp_gfxdrv_command_reg = 0;
-       struct amdgpu_bo *psp_sysdrv;
-       void *psp_sysdrv_virt = NULL;
-       uint64_t psp_sysdrv_mem;
        struct amdgpu_device *adev = psp->adev;
-       uint32_t size, sol_reg;
+       uint32_t sol_reg;
 
        /* Check sOS sign of life register to confirm sys driver and sOS
         * are already been loaded.
@@ -185,27 +182,14 @@ int psp_v3_1_bootloader_load_sysdrv(struct psp_context *psp)
        if (ret)
                return ret;
 
-       /*
-        * Create a 1 meg GART memory to store the psp sys driver
-        * binary with a 1 meg aligned address
-        */
-       size = (psp->sys_bin_size + (PSP_BOOTLOADER_1_MEG_ALIGNMENT - 1)) &
-               (~(PSP_BOOTLOADER_1_MEG_ALIGNMENT - 1));
-
-       ret = amdgpu_bo_create_kernel(adev, size, PSP_BOOTLOADER_1_MEG_ALIGNMENT,
-                                     AMDGPU_GEM_DOMAIN_GTT,
-                                     &psp_sysdrv,
-                                     &psp_sysdrv_mem,
-                                     &psp_sysdrv_virt);
-       if (ret)
-               return ret;
+       memset(psp->fw_pri_buf, 0, PSP_1_MEG);
 
        /* Copy PSP System Driver binary to memory */
-       memcpy(psp_sysdrv_virt, psp->sys_start_addr, psp->sys_bin_size);
+       memcpy(psp->fw_pri_buf, psp->sys_start_addr, psp->sys_bin_size);
 
        /* Provide the sys driver to bootrom */
        WREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_36),
-              (uint32_t)(psp_sysdrv_mem >> 20));
+              (uint32_t)(psp->fw_pri_mc_addr >> 20));
        psp_gfxdrv_command_reg = 1 << 16;
        WREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35),
               psp_gfxdrv_command_reg);
@@ -216,8 +200,6 @@ int psp_v3_1_bootloader_load_sysdrv(struct psp_context *psp)
        ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35),
                           0x80000000, 0x80000000, false);
 
-       amdgpu_bo_free_kernel(&psp_sysdrv, &psp_sysdrv_mem, &psp_sysdrv_virt);
-
        return ret;
 }
 
@@ -225,11 +207,8 @@ int psp_v3_1_bootloader_load_sos(struct psp_context *psp)
 {
        int ret;
        unsigned int psp_gfxdrv_command_reg = 0;
-       struct amdgpu_bo *psp_sos;
-       void *psp_sos_virt = NULL;
-       uint64_t psp_sos_mem;
        struct amdgpu_device *adev = psp->adev;
-       uint32_t size, sol_reg;
+       uint32_t sol_reg;
 
        /* Check sOS sign of life register to confirm sys driver and sOS
         * are already been loaded.
@@ -244,23 +223,14 @@ int psp_v3_1_bootloader_load_sos(struct psp_context *psp)
        if (ret)
                return ret;
 
-       size = (psp->sos_bin_size + (PSP_BOOTLOADER_1_MEG_ALIGNMENT - 1)) &
-               (~((uint64_t)PSP_BOOTLOADER_1_MEG_ALIGNMENT - 1));
-
-       ret = amdgpu_bo_create_kernel(adev, size, PSP_BOOTLOADER_1_MEG_ALIGNMENT,
-                                     AMDGPU_GEM_DOMAIN_GTT,
-                                     &psp_sos,
-                                     &psp_sos_mem,
-                                     &psp_sos_virt);
-       if (ret)
-               return ret;
+       memset(psp->fw_pri_buf, 0, PSP_1_MEG);
 
        /* Copy Secure OS binary to PSP memory */
-       memcpy(psp_sos_virt, psp->sos_start_addr, psp->sos_bin_size);
+       memcpy(psp->fw_pri_buf, psp->sos_start_addr, psp->sos_bin_size);
 
        /* Provide the PSP secure OS to bootrom */
        WREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_36),
-              (uint32_t)(psp_sos_mem >> 20));
+              (uint32_t)(psp->fw_pri_mc_addr >> 20));
        psp_gfxdrv_command_reg = 2 << 16;
        WREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_35),
               psp_gfxdrv_command_reg);
@@ -273,8 +243,6 @@ int psp_v3_1_bootloader_load_sos(struct psp_context *psp)
                           0, true);
 #endif
 
-       amdgpu_bo_free_kernel(&psp_sos, &psp_sos_mem, &psp_sos_virt);
-
        return ret;
 }
 
@@ -300,7 +268,6 @@ int psp_v3_1_prep_cmd_buf(struct amdgpu_firmware_info *ucode, struct psp_gfx_cmd
 int psp_v3_1_ring_init(struct psp_context *psp, enum psp_ring_type ring_type)
 {
        int ret = 0;
-       unsigned int psp_ring_reg = 0;
        struct psp_ring *ring;
        struct amdgpu_device *adev = psp->adev;
 
@@ -320,6 +287,16 @@ int psp_v3_1_ring_init(struct psp_context *psp, enum psp_ring_type ring_type)
                return ret;
        }
 
+       return 0;
+}
+
+int psp_v3_1_ring_create(struct psp_context *psp, enum psp_ring_type ring_type)
+{
+       int ret = 0;
+       unsigned int psp_ring_reg = 0;
+       struct psp_ring *ring = &psp->km_ring;
+       struct amdgpu_device *adev = psp->adev;
+
        /* Write low address of the ring to C2PMSG_69 */
        psp_ring_reg = lower_32_bits(ring->ring_mem_mc_addr);
        WREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_69), psp_ring_reg);
@@ -344,6 +321,33 @@ int psp_v3_1_ring_init(struct psp_context *psp, enum psp_ring_type ring_type)
        return ret;
 }
 
+int psp_v3_1_ring_destroy(struct psp_context *psp, enum psp_ring_type ring_type)
+{
+       int ret = 0;
+       struct psp_ring *ring;
+       unsigned int psp_ring_reg = 0;
+       struct amdgpu_device *adev = psp->adev;
+
+       ring = &psp->km_ring;
+
+       /* Write the ring destroy command to C2PMSG_64 */
+       psp_ring_reg = 3 << 16;
+       WREG32(SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64), psp_ring_reg);
+
+       /* there might be handshake issue with hardware which needs delay */
+       mdelay(20);
+
+       /* Wait for response flag (bit 31) in C2PMSG_64 */
+       ret = psp_wait_for(psp, SOC15_REG_OFFSET(MP0, 0, mmMP0_SMN_C2PMSG_64),
+                          0x80000000, 0x80000000, false);
+
+       if (ring->ring_mem)
+               amdgpu_bo_free_kernel(&adev->firmware.rbuf,
+                                     &ring->ring_mem_mc_addr,
+                                     (void **)&ring->ring_mem);
+       return ret;
+}
+
 int psp_v3_1_cmd_submit(struct psp_context *psp,
                        struct amdgpu_firmware_info *ucode,
                        uint64_t cmd_buf_mc_addr, uint64_t fence_mc_addr,
index e82eff741a085f67332d9651730d4a641d1aebb9..9dcd0b25c4c60c635c508e609ca588c748bbba65 100644 (file)
@@ -39,6 +39,10 @@ extern int psp_v3_1_prep_cmd_buf(struct amdgpu_firmware_info *ucode,
                                 struct psp_gfx_cmd_resp *cmd);
 extern int psp_v3_1_ring_init(struct psp_context *psp,
                              enum psp_ring_type ring_type);
+extern int psp_v3_1_ring_create(struct psp_context *psp,
+                               enum psp_ring_type ring_type);
+extern int psp_v3_1_ring_destroy(struct psp_context *psp,
+                               enum psp_ring_type ring_type);
 extern int psp_v3_1_cmd_submit(struct psp_context *psp,
                               struct amdgpu_firmware_info *ucode,
                               uint64_t cmd_buf_mc_addr, uint64_t fence_mc_addr,
index 21f38d8823353cae261e72c1b8d73289c67ad552..ecc70a730a54702523e49cd01a213beb0e61116d 100644 (file)
@@ -48,8 +48,7 @@ static void sdma_v4_0_set_buffer_funcs(struct amdgpu_device *adev);
 static void sdma_v4_0_set_vm_pte_funcs(struct amdgpu_device *adev);
 static void sdma_v4_0_set_irq_funcs(struct amdgpu_device *adev);
 
-static const u32 golden_settings_sdma_4[] =
-{
+static const u32 golden_settings_sdma_4[] = {
        SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_CHICKEN_BITS), 0xfe931f07, 0x02831f07,
        SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_CLK_CTRL), 0xff000ff0, 0x3f000100,
        SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_GFX_IB_CNTL), 0x800f0100, 0x00000100,
@@ -76,8 +75,7 @@ static const u32 golden_settings_sdma_4[] =
        SOC15_REG_OFFSET(SDMA1, 0, mmSDMA1_UTCL1_PAGE), 0x000003ff, 0x000003c0
 };
 
-static const u32 golden_settings_sdma_vg10[] =
-{
+static const u32 golden_settings_sdma_vg10[] = {
        SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG), 0x0018773f, 0x00104002,
        SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG_READ), 0x0018773f, 0x00104002,
        SOC15_REG_OFFSET(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG), 0x0018773f, 0x00104002,
@@ -87,16 +85,17 @@ static const u32 golden_settings_sdma_vg10[] =
 static u32 sdma_v4_0_get_reg_offset(u32 instance, u32 internal_offset)
 {
        u32 base = 0;
+
        switch (instance) {
-               case 0:
-                       base = SDMA0_BASE.instance[0].segment[0];
-                       break;
-               case 1:
-                       base = SDMA1_BASE.instance[0].segment[0];
-                       break;
-               default:
-                       BUG();
-                       break;
+       case 0:
+               base = SDMA0_BASE.instance[0].segment[0];
+               break;
+       case 1:
+               base = SDMA1_BASE.instance[0].segment[0];
+               break;
+       default:
+               BUG();
+               break;
        }
 
        return base + internal_offset;
@@ -159,7 +158,8 @@ static int sdma_v4_0_init_microcode(struct amdgpu_device *adev)
        case CHIP_VEGA10:
                chip_name = "vega10";
                break;
-       default: BUG();
+       default:
+               BUG();
        }
 
        for (i = 0; i < adev->sdma.num_instances; i++) {
@@ -179,7 +179,7 @@ static int sdma_v4_0_init_microcode(struct amdgpu_device *adev)
                if (adev->sdma.instance[i].feature_version >= 20)
                        adev->sdma.instance[i].burst_nop = true;
                DRM_DEBUG("psp_load == '%s'\n",
-                               adev->firmware.load_type == AMDGPU_FW_LOAD_PSP? "true": "false");
+                               adev->firmware.load_type == AMDGPU_FW_LOAD_PSP ? "true" : "false");
 
                if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
                        info = &adev->firmware.ucode[AMDGPU_UCODE_ID_SDMA0 + i];
@@ -192,9 +192,7 @@ static int sdma_v4_0_init_microcode(struct amdgpu_device *adev)
        }
 out:
        if (err) {
-               printk(KERN_ERR
-                      "sdma_v4_0: Failed to load firmware \"%s\"\n",
-                      fw_name);
+               DRM_ERROR("sdma_v4_0: Failed to load firmware \"%s\"\n", fw_name);
                for (i = 0; i < adev->sdma.num_instances; i++) {
                        release_firmware(adev->sdma.instance[i].fw);
                        adev->sdma.instance[i].fw = NULL;
@@ -212,10 +210,10 @@ out:
  */
 static uint64_t sdma_v4_0_ring_get_rptr(struct amdgpu_ring *ring)
 {
-       u64rptr;
+       u64 *rptr;
 
        /* XXX check if swapping is necessary on BE */
-       rptr =((u64*)&ring->adev->wb.wb[ring->rptr_offs]);
+       rptr = ((u64 *)&ring->adev->wb.wb[ring->rptr_offs]);
 
        DRM_DEBUG("rptr before shift == 0x%016llx\n", *rptr);
        return ((*rptr) >> 2);
@@ -231,19 +229,20 @@ static uint64_t sdma_v4_0_ring_get_rptr(struct amdgpu_ring *ring)
 static uint64_t sdma_v4_0_ring_get_wptr(struct amdgpu_ring *ring)
 {
        struct amdgpu_device *adev = ring->adev;
-       u64wptr = NULL;
-       uint64_t local_wptr=0;
+       u64 *wptr = NULL;
+       uint64_t local_wptr = 0;
 
        if (ring->use_doorbell) {
                /* XXX check if swapping is necessary on BE */
-               wptr = ((u64*)&adev->wb.wb[ring->wptr_offs]);
+               wptr = ((u64 *)&adev->wb.wb[ring->wptr_offs]);
                DRM_DEBUG("wptr/doorbell before shift == 0x%016llx\n", *wptr);
                *wptr = (*wptr) >> 2;
                DRM_DEBUG("wptr/doorbell after shift == 0x%016llx\n", *wptr);
        } else {
                u32 lowbit, highbit;
                int me = (ring == &adev->sdma.instance[0].ring) ? 0 : 1;
-               wptr=&local_wptr;
+
+               wptr = &local_wptr;
                lowbit = RREG32(sdma_v4_0_get_reg_offset(me, mmSDMA0_GFX_RB_WPTR)) >> 2;
                highbit = RREG32(sdma_v4_0_get_reg_offset(me, mmSDMA0_GFX_RB_WPTR_HI)) >> 2;
 
@@ -285,12 +284,13 @@ static void sdma_v4_0_ring_set_wptr(struct amdgpu_ring *ring)
                WDOORBELL64(ring->doorbell_index, ring->wptr << 2);
        } else {
                int me = (ring == &ring->adev->sdma.instance[0].ring) ? 0 : 1;
+
                DRM_DEBUG("Not using doorbell -- "
                                "mmSDMA%i_GFX_RB_WPTR == 0x%08x "
-                               "mmSDMA%i_GFX_RB_WPTR_HI == 0x%08x \n",
-                               me,
+                               "mmSDMA%i_GFX_RB_WPTR_HI == 0x%08x\n",
                                me,
                                lower_32_bits(ring->wptr << 2),
+                               me,
                                upper_32_bits(ring->wptr << 2));
                WREG32(sdma_v4_0_get_reg_offset(me, mmSDMA0_GFX_RB_WPTR), lower_32_bits(ring->wptr << 2));
                WREG32(sdma_v4_0_get_reg_offset(me, mmSDMA0_GFX_RB_WPTR_HI), upper_32_bits(ring->wptr << 2));
@@ -319,22 +319,22 @@ static void sdma_v4_0_ring_insert_nop(struct amdgpu_ring *ring, uint32_t count)
  * Schedule an IB in the DMA ring (VEGA10).
  */
 static void sdma_v4_0_ring_emit_ib(struct amdgpu_ring *ring,
-                                   struct amdgpu_ib *ib,
-                                   unsigned vm_id, bool ctx_switch)
+                                       struct amdgpu_ib *ib,
+                                       unsigned vm_id, bool ctx_switch)
 {
-        u32 vmid = vm_id & 0xf;
+       u32 vmid = vm_id & 0xf;
 
-        /* IB packet must end on a 8 DW boundary */
-        sdma_v4_0_ring_insert_nop(ring, (10 - (lower_32_bits(ring->wptr) & 7)) % 8);
+       /* IB packet must end on a 8 DW boundary */
+       sdma_v4_0_ring_insert_nop(ring, (10 - (lower_32_bits(ring->wptr) & 7)) % 8);
 
-        amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_INDIRECT) |
-                          SDMA_PKT_INDIRECT_HEADER_VMID(vmid));
-        /* base must be 32 byte aligned */
-        amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr) & 0xffffffe0);
-        amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr));
-        amdgpu_ring_write(ring, ib->length_dw);
-        amdgpu_ring_write(ring, 0);
-        amdgpu_ring_write(ring, 0);
+       amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_INDIRECT) |
+                         SDMA_PKT_INDIRECT_HEADER_VMID(vmid));
+       /* base must be 32 byte aligned */
+       amdgpu_ring_write(ring, lower_32_bits(ib->gpu_addr) & 0xffffffe0);
+       amdgpu_ring_write(ring, upper_32_bits(ib->gpu_addr));
+       amdgpu_ring_write(ring, ib->length_dw);
+       amdgpu_ring_write(ring, 0);
+       amdgpu_ring_write(ring, 0);
 
 }
 
@@ -523,7 +523,7 @@ static int sdma_v4_0_gfx_resume(struct amdgpu_device *adev)
        u32 doorbell;
        u32 doorbell_offset;
        u32 temp;
-       int i,r;
+       int i, r;
 
        for (i = 0; i < adev->sdma.num_instances; i++) {
                ring = &adev->sdma.instance[i].ring;
@@ -572,7 +572,7 @@ static int sdma_v4_0_gfx_resume(struct amdgpu_device *adev)
                doorbell = RREG32(sdma_v4_0_get_reg_offset(i, mmSDMA0_GFX_DOORBELL));
                doorbell_offset = RREG32(sdma_v4_0_get_reg_offset(i, mmSDMA0_GFX_DOORBELL_OFFSET));
 
-               if (ring->use_doorbell){
+               if (ring->use_doorbell) {
                        doorbell = REG_SET_FIELD(doorbell, SDMA0_GFX_DOORBELL, ENABLE, 1);
                        doorbell_offset = REG_SET_FIELD(doorbell_offset, SDMA0_GFX_DOORBELL_OFFSET,
                                        OFFSET, ring->doorbell_index);
@@ -694,9 +694,7 @@ static int sdma_v4_0_load_microcode(struct amdgpu_device *adev)
 
 
                for (j = 0; j < fw_size; j++)
-               {
                        WREG32(sdma_v4_0_get_reg_offset(i, mmSDMA0_UCODE_DATA), le32_to_cpup(fw_data++));
-               }
 
                WREG32(sdma_v4_0_get_reg_offset(i, mmSDMA0_UCODE_ADDR), adev->sdma.instance[i].fw_version);
        }
@@ -744,10 +742,8 @@ static int sdma_v4_0_start(struct amdgpu_device *adev)
        if (r)
                return r;
        r = sdma_v4_0_rlc_resume(adev);
-       if (r)
-               return r;
 
-       return 0;
+       return r;
 }
 
 /**
@@ -797,9 +793,8 @@ static int sdma_v4_0_ring_test_ring(struct amdgpu_ring *ring)
 
        for (i = 0; i < adev->usec_timeout; i++) {
                tmp = le32_to_cpu(adev->wb.wb[index]);
-               if (tmp == 0xDEADBEEF) {
+               if (tmp == 0xDEADBEEF)
                        break;
-               }
                DRM_UDELAY(1);
        }
 
@@ -864,29 +859,29 @@ static int sdma_v4_0_ring_test_ib(struct amdgpu_ring *ring, long timeout)
        if (r)
                goto err1;
 
-        r = dma_fence_wait_timeout(f, false, timeout);
-        if (r == 0) {
-                DRM_ERROR("amdgpu: IB test timed out\n");
-                r = -ETIMEDOUT;
-                goto err1;
-        } else if (r < 0) {
-                DRM_ERROR("amdgpu: fence wait failed (%ld).\n", r);
-                goto err1;
-        }
-        tmp = le32_to_cpu(adev->wb.wb[index]);
-        if (tmp == 0xDEADBEEF) {
-                DRM_INFO("ib test on ring %d succeeded\n", ring->idx);
-                r = 0;
-        } else {
-                DRM_ERROR("amdgpu: ib test failed (0x%08X)\n", tmp);
-                r = -EINVAL;
-        }
+       r = dma_fence_wait_timeout(f, false, timeout);
+       if (r == 0) {
+               DRM_ERROR("amdgpu: IB test timed out\n");
+               r = -ETIMEDOUT;
+               goto err1;
+       } else if (r < 0) {
+               DRM_ERROR("amdgpu: fence wait failed (%ld).\n", r);
+               goto err1;
+       }
+       tmp = le32_to_cpu(adev->wb.wb[index]);
+       if (tmp == 0xDEADBEEF) {
+               DRM_INFO("ib test on ring %d succeeded\n", ring->idx);
+               r = 0;
+       } else {
+               DRM_ERROR("amdgpu: ib test failed (0x%08X)\n", tmp);
+               r = -EINVAL;
+       }
 err1:
-        amdgpu_ib_free(adev, &ib, NULL);
-        dma_fence_put(f);
+       amdgpu_ib_free(adev, &ib, NULL);
+       dma_fence_put(f);
 err0:
-        amdgpu_wb_free(adev, index);
-        return r;
+       amdgpu_wb_free(adev, index);
+       return r;
 }
 
 
@@ -1039,44 +1034,40 @@ static void sdma_v4_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring)
 static void sdma_v4_0_ring_emit_vm_flush(struct amdgpu_ring *ring,
                                         unsigned vm_id, uint64_t pd_addr)
 {
+       struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->funcs->vmhub];
        uint32_t req = ring->adev->gart.gart_funcs->get_invalidate_req(vm_id);
-       unsigned eng = ring->idx;
-       unsigned i;
+       unsigned eng = ring->vm_inv_eng;
 
        pd_addr = pd_addr | 0x1; /* valid bit */
        /* now only use physical base address of PDE and valid */
        BUG_ON(pd_addr & 0xFFFF00000000003EULL);
 
-       for (i = 0; i < AMDGPU_MAX_VMHUBS; ++i) {
-               struct amdgpu_vmhub *hub = &ring->adev->vmhub[i];
-
-               amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_SRBM_WRITE) |
-                                 SDMA_PKT_SRBM_WRITE_HEADER_BYTE_EN(0xf));
-               amdgpu_ring_write(ring, hub->ctx0_ptb_addr_lo32 + vm_id * 2);
-               amdgpu_ring_write(ring, lower_32_bits(pd_addr));
-
-               amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_SRBM_WRITE) |
-                                 SDMA_PKT_SRBM_WRITE_HEADER_BYTE_EN(0xf));
-               amdgpu_ring_write(ring, hub->ctx0_ptb_addr_hi32 + vm_id * 2);
-               amdgpu_ring_write(ring, upper_32_bits(pd_addr));
-
-               /* flush TLB */
-               amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_SRBM_WRITE) |
-                                 SDMA_PKT_SRBM_WRITE_HEADER_BYTE_EN(0xf));
-               amdgpu_ring_write(ring, hub->vm_inv_eng0_req + eng);
-               amdgpu_ring_write(ring, req);
-
-               /* wait for flush */
-               amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_POLL_REGMEM) |
-                                 SDMA_PKT_POLL_REGMEM_HEADER_HDP_FLUSH(0) |
-                                 SDMA_PKT_POLL_REGMEM_HEADER_FUNC(3)); /* equal */
-               amdgpu_ring_write(ring, (hub->vm_inv_eng0_ack + eng) << 2);
-               amdgpu_ring_write(ring, 0);
-               amdgpu_ring_write(ring, 1 << vm_id); /* reference */
-               amdgpu_ring_write(ring, 1 << vm_id); /* mask */
-               amdgpu_ring_write(ring, SDMA_PKT_POLL_REGMEM_DW5_RETRY_COUNT(0xfff) |
-                                 SDMA_PKT_POLL_REGMEM_DW5_INTERVAL(10));
-       }
+       amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_SRBM_WRITE) |
+                         SDMA_PKT_SRBM_WRITE_HEADER_BYTE_EN(0xf));
+       amdgpu_ring_write(ring, hub->ctx0_ptb_addr_lo32 + vm_id * 2);
+       amdgpu_ring_write(ring, lower_32_bits(pd_addr));
+
+       amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_SRBM_WRITE) |
+                         SDMA_PKT_SRBM_WRITE_HEADER_BYTE_EN(0xf));
+       amdgpu_ring_write(ring, hub->ctx0_ptb_addr_hi32 + vm_id * 2);
+       amdgpu_ring_write(ring, upper_32_bits(pd_addr));
+
+       /* flush TLB */
+       amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_SRBM_WRITE) |
+                         SDMA_PKT_SRBM_WRITE_HEADER_BYTE_EN(0xf));
+       amdgpu_ring_write(ring, hub->vm_inv_eng0_req + eng);
+       amdgpu_ring_write(ring, req);
+
+       /* wait for flush */
+       amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_POLL_REGMEM) |
+                         SDMA_PKT_POLL_REGMEM_HEADER_HDP_FLUSH(0) |
+                         SDMA_PKT_POLL_REGMEM_HEADER_FUNC(3)); /* equal */
+       amdgpu_ring_write(ring, (hub->vm_inv_eng0_ack + eng) << 2);
+       amdgpu_ring_write(ring, 0);
+       amdgpu_ring_write(ring, 1 << vm_id); /* reference */
+       amdgpu_ring_write(ring, 1 << vm_id); /* mask */
+       amdgpu_ring_write(ring, SDMA_PKT_POLL_REGMEM_DW5_RETRY_COUNT(0xfff) |
+                         SDMA_PKT_POLL_REGMEM_DW5_INTERVAL(10));
 }
 
 static int sdma_v4_0_early_init(void *handle)
@@ -1162,8 +1153,6 @@ static int sdma_v4_0_hw_init(void *handle)
        sdma_v4_0_init_golden_registers(adev);
 
        r = sdma_v4_0_start(adev);
-       if (r)
-               return r;
 
        return r;
 }
@@ -1199,10 +1188,12 @@ static bool sdma_v4_0_is_idle(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
        u32 i;
+
        for (i = 0; i < adev->sdma.num_instances; i++) {
                u32 tmp = RREG32(sdma_v4_0_get_reg_offset(i, mmSDMA0_STATUS_REG));
+
                if (!(tmp & SDMA0_STATUS_REG__IDLE_MASK))
-                        return false;
+                       return false;
        }
 
        return true;
@@ -1211,8 +1202,9 @@ static bool sdma_v4_0_is_idle(void *handle)
 static int sdma_v4_0_wait_for_idle(void *handle)
 {
        unsigned i;
-       u32 sdma0,sdma1;
+       u32 sdma0, sdma1;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+
        for (i = 0; i < adev->usec_timeout; i++) {
                sdma0 = RREG32(sdma_v4_0_get_reg_offset(0, mmSDMA0_STATUS_REG));
                sdma1 = RREG32(sdma_v4_0_get_reg_offset(1, mmSDMA0_STATUS_REG));
@@ -1240,7 +1232,7 @@ static int sdma_v4_0_set_trap_irq_state(struct amdgpu_device *adev,
 
        u32 reg_offset = (type == AMDGPU_SDMA_IRQ_TRAP0) ?
                sdma_v4_0_get_reg_offset(0, mmSDMA0_CNTL) :
-               sdma_v4_0_get_reg_offset(1, mmSDMA0_CNTL);
+               sdma_v4_0_get_reg_offset(1, mmSDMA0_CNTL);
 
        sdma_cntl = RREG32(reg_offset);
        sdma_cntl = REG_SET_FIELD(sdma_cntl, SDMA0_CNTL, TRAP_ENABLE,
@@ -1332,7 +1324,7 @@ static void sdma_v4_0_update_medium_grain_clock_gating(
                                  SDMA1_CLK_CTRL__SOFT_OVERRIDE2_MASK |
                                  SDMA1_CLK_CTRL__SOFT_OVERRIDE1_MASK |
                                  SDMA1_CLK_CTRL__SOFT_OVERRIDE0_MASK);
-                       if(def != data)
+                       if (def != data)
                                WREG32(SOC15_REG_OFFSET(SDMA1, 0, mmSDMA1_CLK_CTRL), data);
                }
        } else {
@@ -1382,17 +1374,17 @@ static void sdma_v4_0_update_medium_grain_light_sleep(
 
                /* 1-not override: enable sdma1 mem light sleep */
                if (adev->asic_type == CHIP_VEGA10) {
-                        def = data = RREG32(SOC15_REG_OFFSET(SDMA1, 0, mmSDMA1_POWER_CNTL));
-                        data |= SDMA1_POWER_CNTL__MEM_POWER_OVERRIDE_MASK;
-                        if (def != data)
-                                WREG32(SOC15_REG_OFFSET(SDMA1, 0, mmSDMA1_POWER_CNTL), data);
+                       def = data = RREG32(SOC15_REG_OFFSET(SDMA1, 0, mmSDMA1_POWER_CNTL));
+                       data |= SDMA1_POWER_CNTL__MEM_POWER_OVERRIDE_MASK;
+                       if (def != data)
+                               WREG32(SOC15_REG_OFFSET(SDMA1, 0, mmSDMA1_POWER_CNTL), data);
                }
        } else {
                /* 0-override:disable sdma0 mem light sleep */
                def = data = RREG32(SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_POWER_CNTL));
                data &= ~SDMA0_POWER_CNTL__MEM_POWER_OVERRIDE_MASK;
                if (def != data)
-                      WREG32(SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_POWER_CNTL), data);
+                       WREG32(SOC15_REG_OFFSET(SDMA0, 0, mmSDMA0_POWER_CNTL), data);
 
                /* 0-override:disable sdma1 mem light sleep */
                if (adev->asic_type == CHIP_VEGA10) {
@@ -1473,6 +1465,7 @@ static const struct amdgpu_ring_funcs sdma_v4_0_ring_funcs = {
        .align_mask = 0xf,
        .nop = SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP),
        .support_64bit_ptrs = true,
+       .vmhub = AMDGPU_MMHUB,
        .get_rptr = sdma_v4_0_ring_get_rptr,
        .get_wptr = sdma_v4_0_ring_get_wptr,
        .set_wptr = sdma_v4_0_ring_set_wptr,
@@ -1480,7 +1473,7 @@ static const struct amdgpu_ring_funcs sdma_v4_0_ring_funcs = {
                6 + /* sdma_v4_0_ring_emit_hdp_flush */
                3 + /* sdma_v4_0_ring_emit_hdp_invalidate */
                6 + /* sdma_v4_0_ring_emit_pipeline_sync */
-               36 + /* sdma_v4_0_ring_emit_vm_flush */
+               18 + /* sdma_v4_0_ring_emit_vm_flush */
                10 + 10 + 10, /* sdma_v4_0_ring_emit_fence x3 for user fence, vm fence */
        .emit_ib_size = 7 + 6, /* sdma_v4_0_ring_emit_ib */
        .emit_ib = sdma_v4_0_ring_emit_ib,
@@ -1606,8 +1599,7 @@ static void sdma_v4_0_set_vm_pte_funcs(struct amdgpu_device *adev)
        }
 }
 
-const struct amdgpu_ip_block_version sdma_v4_0_ip_block =
-{
+const struct amdgpu_ip_block_version sdma_v4_0_ip_block = {
        .type = AMD_IP_BLOCK_TYPE_SDMA,
        .major = 4,
        .minor = 0,
index 385de8617075383d4cc28726293f77a5649809a9..6b55d451ae7f94cd1c3342bc87f1cb37edac76e8 100644 (file)
@@ -25,7 +25,7 @@
 #include <linux/module.h>
 #include "drmP.h"
 #include "amdgpu.h"
-#include "amdgpu_atombios.h"
+#include "amdgpu_atomfirmware.h"
 #include "amdgpu_ih.h"
 #include "amdgpu_uvd.h"
 #include "amdgpu_vce.h"
@@ -405,11 +405,11 @@ static void soc15_gpu_pci_config_reset(struct amdgpu_device *adev)
 
 static int soc15_asic_reset(struct amdgpu_device *adev)
 {
-       amdgpu_atombios_scratch_regs_engine_hung(adev, true);
+       amdgpu_atomfirmware_scratch_regs_engine_hung(adev, true);
 
        soc15_gpu_pci_config_reset(adev);
 
-       amdgpu_atombios_scratch_regs_engine_hung(adev, false);
+       amdgpu_atomfirmware_scratch_regs_engine_hung(adev, false);
 
        return 0;
 }
@@ -505,8 +505,7 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
                        amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
                amdgpu_ip_block_add(adev, &gfx_v9_0_ip_block);
                amdgpu_ip_block_add(adev, &sdma_v4_0_ip_block);
-               if (!amdgpu_sriov_vf(adev))
-                       amdgpu_ip_block_add(adev, &uvd_v7_0_ip_block);
+               amdgpu_ip_block_add(adev, &uvd_v7_0_ip_block);
                amdgpu_ip_block_add(adev, &vce_v4_0_ip_block);
                break;
        default:
index 2b96c806baa12a673bd2b9d4332d0fdfe5a4dc6c..e8df6d820dbe62922a11616ea43a68cd5e7a060d 100644 (file)
@@ -45,13 +45,31 @@ struct nbio_pcie_index_data {
        u32 index_offset;
        u32 data_offset;
 };
-// Register Access Macro
+
+/* Register Access Macros */
 #define SOC15_REG_OFFSET(ip, inst, reg)       (0 == reg##_BASE_IDX ? ip##_BASE__INST##inst##_SEG0 + reg : \
                                                 (1 == reg##_BASE_IDX ? ip##_BASE__INST##inst##_SEG1 + reg : \
                                                     (2 == reg##_BASE_IDX ? ip##_BASE__INST##inst##_SEG2 + reg : \
                                                         (3 == reg##_BASE_IDX ? ip##_BASE__INST##inst##_SEG3 + reg : \
                                                             (ip##_BASE__INST##inst##_SEG4 + reg)))))
 
+#define WREG32_FIELD15(ip, idx, reg, field, val)       \
+       WREG32(SOC15_REG_OFFSET(ip, idx, mm##reg), (RREG32(SOC15_REG_OFFSET(ip, idx, mm##reg)) & ~REG_FIELD_MASK(reg, field)) | (val) << REG_FIELD_SHIFT(reg, field))
+
+#define RREG32_SOC15(ip, inst, reg) \
+       RREG32( (0 == reg##_BASE_IDX ? ip##_BASE__INST##inst##_SEG0 + reg : \
+               (1 == reg##_BASE_IDX ? ip##_BASE__INST##inst##_SEG1 + reg : \
+               (2 == reg##_BASE_IDX ? ip##_BASE__INST##inst##_SEG2 + reg : \
+               (3 == reg##_BASE_IDX ? ip##_BASE__INST##inst##_SEG3 + reg : \
+               (ip##_BASE__INST##inst##_SEG4 + reg))))))
+
+#define WREG32_SOC15(ip, inst, reg, value) \
+       WREG32( (0 == reg##_BASE_IDX ? ip##_BASE__INST##inst##_SEG0 + reg : \
+               (1 == reg##_BASE_IDX ? ip##_BASE__INST##inst##_SEG1 + reg : \
+               (2 == reg##_BASE_IDX ? ip##_BASE__INST##inst##_SEG2 + reg : \
+               (3 == reg##_BASE_IDX ? ip##_BASE__INST##inst##_SEG3 + reg : \
+               (ip##_BASE__INST##inst##_SEG4 + reg))))), value)
+
 #endif
 
 
index 9bcf014692820f1e6c78f507f1a8661fa2271bee..eca8f6e01e97dbf871de603500a7037315711f31 100644 (file)
 #include "amdgpu_uvd.h"
 #include "soc15d.h"
 #include "soc15_common.h"
+#include "mmsch_v1_0.h"
 
 #include "vega10/soc15ip.h"
 #include "vega10/UVD/uvd_7_0_offset.h"
 #include "vega10/UVD/uvd_7_0_sh_mask.h"
+#include "vega10/VCE/vce_4_0_offset.h"
+#include "vega10/VCE/vce_4_0_default.h"
+#include "vega10/VCE/vce_4_0_sh_mask.h"
 #include "vega10/NBIF/nbif_6_1_offset.h"
 #include "vega10/HDP/hdp_4_0_offset.h"
 #include "vega10/MMHUB/mmhub_1_0_offset.h"
@@ -41,6 +45,7 @@ static void uvd_v7_0_set_enc_ring_funcs(struct amdgpu_device *adev);
 static void uvd_v7_0_set_irq_funcs(struct amdgpu_device *adev);
 static int uvd_v7_0_start(struct amdgpu_device *adev);
 static void uvd_v7_0_stop(struct amdgpu_device *adev);
+static int uvd_v7_0_sriov_start(struct amdgpu_device *adev);
 
 /**
  * uvd_v7_0_ring_get_rptr - get read pointer
@@ -98,6 +103,9 @@ static uint64_t uvd_v7_0_enc_ring_get_wptr(struct amdgpu_ring *ring)
 {
        struct amdgpu_device *adev = ring->adev;
 
+       if (ring->use_doorbell)
+               return adev->wb.wb[ring->wptr_offs];
+
        if (ring == &adev->uvd.ring_enc[0])
                return RREG32(SOC15_REG_OFFSET(UVD, 0, mmUVD_RB_WPTR));
        else
@@ -129,6 +137,13 @@ static void uvd_v7_0_enc_ring_set_wptr(struct amdgpu_ring *ring)
 {
        struct amdgpu_device *adev = ring->adev;
 
+       if (ring->use_doorbell) {
+               /* XXX check if swapping is necessary on BE */
+               adev->wb.wb[ring->wptr_offs] = lower_32_bits(ring->wptr);
+               WDOORBELL32(ring->doorbell_index, lower_32_bits(ring->wptr));
+               return;
+       }
+
        if (ring == &adev->uvd.ring_enc[0])
                WREG32(SOC15_REG_OFFSET(UVD, 0, mmUVD_RB_WPTR),
                        lower_32_bits(ring->wptr));
@@ -353,7 +368,10 @@ static int uvd_v7_0_early_init(void *handle)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       adev->uvd.num_enc_rings = 2;
+       if (amdgpu_sriov_vf(adev))
+               adev->uvd.num_enc_rings = 1;
+       else
+               adev->uvd.num_enc_rings = 2;
        uvd_v7_0_set_ring_funcs(adev);
        uvd_v7_0_set_enc_ring_funcs(adev);
        uvd_v7_0_set_irq_funcs(adev);
@@ -406,21 +424,31 @@ static int uvd_v7_0_sw_init(void *handle)
        r = amdgpu_uvd_resume(adev);
        if (r)
                return r;
+       if (!amdgpu_sriov_vf(adev)) {
+               ring = &adev->uvd.ring;
+               sprintf(ring->name, "uvd");
+               r = amdgpu_ring_init(adev, ring, 512, &adev->uvd.irq, 0);
+               if (r)
+                       return r;
+       }
 
-       ring = &adev->uvd.ring;
-       sprintf(ring->name, "uvd");
-       r = amdgpu_ring_init(adev, ring, 512, &adev->uvd.irq, 0);
-       if (r)
-               return r;
 
        for (i = 0; i < adev->uvd.num_enc_rings; ++i) {
                ring = &adev->uvd.ring_enc[i];
                sprintf(ring->name, "uvd_enc%d", i);
+               if (amdgpu_sriov_vf(adev)) {
+                       ring->use_doorbell = true;
+                       ring->doorbell_index = AMDGPU_DOORBELL64_UVD_RING0_1 * 2;
+               }
                r = amdgpu_ring_init(adev, ring, 512, &adev->uvd.irq, 0);
                if (r)
                        return r;
        }
 
+       r = amdgpu_virt_alloc_mm_table(adev);
+       if (r)
+               return r;
+
        return r;
 }
 
@@ -429,6 +457,8 @@ static int uvd_v7_0_sw_fini(void *handle)
        int i, r;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
+       amdgpu_virt_free_mm_table(adev);
+
        r = amdgpu_uvd_suspend(adev);
        if (r)
                return r;
@@ -455,48 +485,53 @@ static int uvd_v7_0_hw_init(void *handle)
        uint32_t tmp;
        int i, r;
 
-       r = uvd_v7_0_start(adev);
+       if (amdgpu_sriov_vf(adev))
+               r = uvd_v7_0_sriov_start(adev);
+       else
+               r = uvd_v7_0_start(adev);
        if (r)
                goto done;
 
-       ring->ready = true;
-       r = amdgpu_ring_test_ring(ring);
-       if (r) {
-               ring->ready = false;
-               goto done;
-       }
+       if (!amdgpu_sriov_vf(adev)) {
+               ring->ready = true;
+               r = amdgpu_ring_test_ring(ring);
+               if (r) {
+                       ring->ready = false;
+                       goto done;
+               }
 
-       r = amdgpu_ring_alloc(ring, 10);
-       if (r) {
-               DRM_ERROR("amdgpu: ring failed to lock UVD ring (%d).\n", r);
-               goto done;
-       }
+               r = amdgpu_ring_alloc(ring, 10);
+               if (r) {
+                       DRM_ERROR("amdgpu: ring failed to lock UVD ring (%d).\n", r);
+                       goto done;
+               }
 
-       tmp = PACKET0(SOC15_REG_OFFSET(UVD, 0,
-               mmUVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL), 0);
-       amdgpu_ring_write(ring, tmp);
-       amdgpu_ring_write(ring, 0xFFFFF);
+               tmp = PACKET0(SOC15_REG_OFFSET(UVD, 0,
+                       mmUVD_SEMA_WAIT_FAULT_TIMEOUT_CNTL), 0);
+               amdgpu_ring_write(ring, tmp);
+               amdgpu_ring_write(ring, 0xFFFFF);
 
-       tmp = PACKET0(SOC15_REG_OFFSET(UVD, 0,
-               mmUVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL), 0);
-       amdgpu_ring_write(ring, tmp);
-       amdgpu_ring_write(ring, 0xFFFFF);
+               tmp = PACKET0(SOC15_REG_OFFSET(UVD, 0,
+                       mmUVD_SEMA_WAIT_INCOMPLETE_TIMEOUT_CNTL), 0);
+               amdgpu_ring_write(ring, tmp);
+               amdgpu_ring_write(ring, 0xFFFFF);
 
-       tmp = PACKET0(SOC15_REG_OFFSET(UVD, 0,
-               mmUVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL), 0);
-       amdgpu_ring_write(ring, tmp);
-       amdgpu_ring_write(ring, 0xFFFFF);
+               tmp = PACKET0(SOC15_REG_OFFSET(UVD, 0,
+                       mmUVD_SEMA_SIGNAL_INCOMPLETE_TIMEOUT_CNTL), 0);
+               amdgpu_ring_write(ring, tmp);
+               amdgpu_ring_write(ring, 0xFFFFF);
 
-       /* Clear timeout status bits */
-       amdgpu_ring_write(ring, PACKET0(SOC15_REG_OFFSET(UVD, 0,
-               mmUVD_SEMA_TIMEOUT_STATUS), 0));
-       amdgpu_ring_write(ring, 0x8);
+               /* Clear timeout status bits */
+               amdgpu_ring_write(ring, PACKET0(SOC15_REG_OFFSET(UVD, 0,
+                       mmUVD_SEMA_TIMEOUT_STATUS), 0));
+               amdgpu_ring_write(ring, 0x8);
 
-       amdgpu_ring_write(ring, PACKET0(SOC15_REG_OFFSET(UVD, 0,
-               mmUVD_SEMA_CNTL), 0));
-       amdgpu_ring_write(ring, 3);
+               amdgpu_ring_write(ring, PACKET0(SOC15_REG_OFFSET(UVD, 0,
+                       mmUVD_SEMA_CNTL), 0));
+               amdgpu_ring_write(ring, 3);
 
-       amdgpu_ring_commit(ring);
+               amdgpu_ring_commit(ring);
+       }
 
        for (i = 0; i < adev->uvd.num_enc_rings; ++i) {
                ring = &adev->uvd.ring_enc[i];
@@ -618,6 +653,241 @@ static void uvd_v7_0_mc_resume(struct amdgpu_device *adev)
        WREG32(SOC15_REG_OFFSET(UVD, 0, mmUVD_GP_SCRATCH4), adev->uvd.max_handles);
 }
 
+static int uvd_v7_0_mmsch_start(struct amdgpu_device *adev,
+                               struct amdgpu_mm_table *table)
+{
+       uint32_t data = 0, loop;
+       uint64_t addr = table->gpu_addr;
+       struct mmsch_v1_0_init_header *header = (struct mmsch_v1_0_init_header *)table->cpu_addr;
+       uint32_t size;
+
+       size = header->header_size + header->vce_table_size + header->uvd_table_size;
+
+       /* 1, write to vce_mmsch_vf_ctx_addr_lo/hi register with GPU mc addr of memory descriptor location */
+       WREG32(SOC15_REG_OFFSET(VCE, 0, mmVCE_MMSCH_VF_CTX_ADDR_LO), lower_32_bits(addr));
+       WREG32(SOC15_REG_OFFSET(VCE, 0, mmVCE_MMSCH_VF_CTX_ADDR_HI), upper_32_bits(addr));
+
+       /* 2, update vmid of descriptor */
+       data = RREG32(SOC15_REG_OFFSET(VCE, 0, mmVCE_MMSCH_VF_VMID));
+       data &= ~VCE_MMSCH_VF_VMID__VF_CTX_VMID_MASK;
+       data |= (0 << VCE_MMSCH_VF_VMID__VF_CTX_VMID__SHIFT); /* use domain0 for MM scheduler */
+       WREG32(SOC15_REG_OFFSET(VCE, 0, mmVCE_MMSCH_VF_VMID), data);
+
+       /* 3, notify mmsch about the size of this descriptor */
+       WREG32(SOC15_REG_OFFSET(VCE, 0, mmVCE_MMSCH_VF_CTX_SIZE), size);
+
+       /* 4, set resp to zero */
+       WREG32(SOC15_REG_OFFSET(VCE, 0, mmVCE_MMSCH_VF_MAILBOX_RESP), 0);
+
+       /* 5, kick off the initialization and wait until VCE_MMSCH_VF_MAILBOX_RESP becomes non-zero */
+       WREG32(SOC15_REG_OFFSET(VCE, 0, mmVCE_MMSCH_VF_MAILBOX_HOST), 0x10000001);
+
+       data = RREG32(SOC15_REG_OFFSET(VCE, 0, mmVCE_MMSCH_VF_MAILBOX_RESP));
+       loop = 1000;
+       while ((data & 0x10000002) != 0x10000002) {
+               udelay(10);
+               data = RREG32(SOC15_REG_OFFSET(VCE, 0, mmVCE_MMSCH_VF_MAILBOX_RESP));
+               loop--;
+               if (!loop)
+                       break;
+       }
+
+       if (!loop) {
+               dev_err(adev->dev, "failed to init MMSCH, mmVCE_MMSCH_VF_MAILBOX_RESP = %x\n", data);
+               return -EBUSY;
+       }
+
+       return 0;
+}
+
+static int uvd_v7_0_sriov_start(struct amdgpu_device *adev)
+{
+       struct amdgpu_ring *ring;
+       uint32_t offset, size, tmp;
+       uint32_t table_size = 0;
+       struct mmsch_v1_0_cmd_direct_write direct_wt = { {0} };
+       struct mmsch_v1_0_cmd_direct_read_modify_write direct_rd_mod_wt = { {0} };
+       struct mmsch_v1_0_cmd_direct_polling direct_poll = { {0} };
+       struct mmsch_v1_0_cmd_end end = { {0} };
+       uint32_t *init_table = adev->virt.mm_table.cpu_addr;
+       struct mmsch_v1_0_init_header *header = (struct mmsch_v1_0_init_header *)init_table;
+
+       direct_wt.cmd_header.command_type = MMSCH_COMMAND__DIRECT_REG_WRITE;
+       direct_rd_mod_wt.cmd_header.command_type = MMSCH_COMMAND__DIRECT_REG_READ_MODIFY_WRITE;
+       direct_poll.cmd_header.command_type = MMSCH_COMMAND__DIRECT_REG_POLLING;
+       end.cmd_header.command_type = MMSCH_COMMAND__END;
+
+       if (header->uvd_table_offset == 0 && header->uvd_table_size == 0) {
+               header->version = MMSCH_VERSION;
+               header->header_size = sizeof(struct mmsch_v1_0_init_header) >> 2;
+
+               if (header->vce_table_offset == 0 && header->vce_table_size == 0)
+                       header->uvd_table_offset = header->header_size;
+               else
+                       header->uvd_table_offset = header->vce_table_size + header->vce_table_offset;
+
+               init_table += header->uvd_table_offset;
+
+               ring = &adev->uvd.ring;
+               size = AMDGPU_GPU_PAGE_ALIGN(adev->uvd.fw->size + 4);
+
+               /* disable clock gating */
+               MMSCH_V1_0_INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_POWER_STATUS),
+                                                  ~UVD_POWER_STATUS__UVD_PG_MODE_MASK, 0);
+               MMSCH_V1_0_INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_STATUS),
+                                                  0xFFFFFFFF, 0x00000004);
+               /* mc resume*/
+               if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
+                       MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW),
+                                                   lower_32_bits(adev->firmware.ucode[AMDGPU_UCODE_ID_UVD].mc_addr));
+                       MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH),
+                                                   upper_32_bits(adev->firmware.ucode[AMDGPU_UCODE_ID_UVD].mc_addr));
+                       offset = 0;
+               } else {
+                       MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_LOW),
+                                                   lower_32_bits(adev->uvd.gpu_addr));
+                       MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_VCPU_CACHE_64BIT_BAR_HIGH),
+                                                   upper_32_bits(adev->uvd.gpu_addr));
+                       offset = size;
+               }
+
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_VCPU_CACHE_OFFSET0),
+                                           AMDGPU_UVD_FIRMWARE_OFFSET >> 3);
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_VCPU_CACHE_SIZE0), size);
+
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_VCPU_CACHE1_64BIT_BAR_LOW),
+                                           lower_32_bits(adev->uvd.gpu_addr + offset));
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_VCPU_CACHE1_64BIT_BAR_HIGH),
+                                           upper_32_bits(adev->uvd.gpu_addr + offset));
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_VCPU_CACHE_OFFSET1), (1 << 21));
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_VCPU_CACHE_SIZE1), AMDGPU_UVD_HEAP_SIZE);
+
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_VCPU_CACHE2_64BIT_BAR_LOW),
+                                           lower_32_bits(adev->uvd.gpu_addr + offset + AMDGPU_UVD_HEAP_SIZE));
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_VCPU_CACHE2_64BIT_BAR_HIGH),
+                                           upper_32_bits(adev->uvd.gpu_addr + offset + AMDGPU_UVD_HEAP_SIZE));
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_VCPU_CACHE_OFFSET2), (2 << 21));
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_VCPU_CACHE_SIZE2),
+                                           AMDGPU_UVD_STACK_SIZE + (AMDGPU_UVD_SESSION_SIZE * 40));
+
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_UDEC_ADDR_CONFIG),
+                                           adev->gfx.config.gb_addr_config);
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_UDEC_DB_ADDR_CONFIG),
+                                           adev->gfx.config.gb_addr_config);
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_UDEC_DBW_ADDR_CONFIG),
+                                           adev->gfx.config.gb_addr_config);
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_GP_SCRATCH4), adev->uvd.max_handles);
+               /* mc resume end*/
+
+               /* disable clock gating */
+               MMSCH_V1_0_INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_CGC_CTRL),
+                                                  ~UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK, 0);
+
+               /* disable interupt */
+               MMSCH_V1_0_INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_MASTINT_EN),
+                                                  ~UVD_MASTINT_EN__VCPU_EN_MASK, 0);
+
+               /* stall UMC and register bus before resetting VCPU */
+               MMSCH_V1_0_INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_CTRL2),
+                                                  ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK,
+                                                  UVD_LMI_CTRL2__STALL_ARB_UMC_MASK);
+
+               /* put LMI, VCPU, RBC etc... into reset */
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_SOFT_RESET),
+                                           (uint32_t)(UVD_SOFT_RESET__LMI_SOFT_RESET_MASK |
+                                                      UVD_SOFT_RESET__VCPU_SOFT_RESET_MASK |
+                                                      UVD_SOFT_RESET__LBSI_SOFT_RESET_MASK |
+                                                      UVD_SOFT_RESET__RBC_SOFT_RESET_MASK |
+                                                      UVD_SOFT_RESET__CSM_SOFT_RESET_MASK |
+                                                      UVD_SOFT_RESET__CXW_SOFT_RESET_MASK |
+                                                      UVD_SOFT_RESET__TAP_SOFT_RESET_MASK |
+                                                      UVD_SOFT_RESET__LMI_UMC_SOFT_RESET_MASK));
+
+               /* initialize UVD memory controller */
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_CTRL),
+                                           (uint32_t)((0x40 << UVD_LMI_CTRL__WRITE_CLEAN_TIMER__SHIFT) |
+                                                      UVD_LMI_CTRL__WRITE_CLEAN_TIMER_EN_MASK |
+                                                      UVD_LMI_CTRL__DATA_COHERENCY_EN_MASK |
+                                                      UVD_LMI_CTRL__VCPU_DATA_COHERENCY_EN_MASK |
+                                                      UVD_LMI_CTRL__REQ_MODE_MASK |
+                                                      0x00100000L));
+
+               /* disable byte swapping */
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_SWAP_CNTL), 0);
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_MP_SWAP_CNTL), 0);
+
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_MPC_SET_MUXA0), 0x40c2040);
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_MPC_SET_MUXA1), 0x0);
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_MPC_SET_MUXB0), 0x40c2040);
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_MPC_SET_MUXB1), 0x0);
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_MPC_SET_ALU), 0);
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_MPC_SET_MUX), 0x88);
+
+               /* take all subblocks out of reset, except VCPU */
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_SOFT_RESET),
+                                           UVD_SOFT_RESET__VCPU_SOFT_RESET_MASK);
+
+               /* enable VCPU clock */
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_VCPU_CNTL),
+                                           UVD_VCPU_CNTL__CLK_EN_MASK);
+
+               /* enable UMC */
+               MMSCH_V1_0_INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_CTRL2),
+                                                  ~UVD_LMI_CTRL2__STALL_ARB_UMC_MASK, 0);
+
+               /* boot up the VCPU */
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_SOFT_RESET), 0);
+
+               MMSCH_V1_0_INSERT_DIRECT_POLL(SOC15_REG_OFFSET(UVD, 0, mmUVD_STATUS), 0x02, 0x02);
+
+               /* enable master interrupt */
+               MMSCH_V1_0_INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_MASTINT_EN),
+                                                  ~(UVD_MASTINT_EN__VCPU_EN_MASK|UVD_MASTINT_EN__SYS_EN_MASK),
+                                                  (UVD_MASTINT_EN__VCPU_EN_MASK|UVD_MASTINT_EN__SYS_EN_MASK));
+
+               /* clear the bit 4 of UVD_STATUS */
+               MMSCH_V1_0_INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_STATUS),
+                                                  ~(2 << UVD_STATUS__VCPU_REPORT__SHIFT), 0);
+
+               /* force RBC into idle state */
+               size = order_base_2(ring->ring_size);
+               tmp = REG_SET_FIELD(0, UVD_RBC_RB_CNTL, RB_BUFSZ, size);
+               tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_BLKSZ, 1);
+               tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_NO_FETCH, 1);
+               tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_WPTR_POLL_EN, 0);
+               tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_NO_UPDATE, 1);
+               tmp = REG_SET_FIELD(tmp, UVD_RBC_RB_CNTL, RB_RPTR_WR_EN, 1);
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_RBC_RB_CNTL), tmp);
+
+               /* set the write pointer delay */
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_RBC_RB_WPTR_CNTL), 0);
+
+               /* set the wb address */
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_RBC_RB_RPTR_ADDR),
+                                           (upper_32_bits(ring->gpu_addr) >> 2));
+
+               /* programm the RB_BASE for ring buffer */
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_RBC_RB_64BIT_BAR_LOW),
+                                           lower_32_bits(ring->gpu_addr));
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_LMI_RBC_RB_64BIT_BAR_HIGH),
+                                           upper_32_bits(ring->gpu_addr));
+
+               ring->wptr = 0;
+               ring = &adev->uvd.ring_enc[0];
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_RB_BASE_LO), ring->gpu_addr);
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_RB_BASE_HI), upper_32_bits(ring->gpu_addr));
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(UVD, 0, mmUVD_RB_SIZE), ring->ring_size / 4);
+
+               /* add end packet */
+               memcpy((void *)init_table, &end, sizeof(struct mmsch_v1_0_cmd_end));
+               table_size += sizeof(struct mmsch_v1_0_cmd_end) / 4;
+               header->uvd_table_size = table_size;
+
+               return uvd_v7_0_mmsch_start(adev, &adev->virt.mm_table);
+       }
+       return -EINVAL; /* already initializaed ? */
+}
+
 /**
  * uvd_v7_0_start - start UVD block
  *
@@ -1034,42 +1304,38 @@ static void uvd_v7_0_vm_reg_wait(struct amdgpu_ring *ring,
 static void uvd_v7_0_ring_emit_vm_flush(struct amdgpu_ring *ring,
                                        unsigned vm_id, uint64_t pd_addr)
 {
+       struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->funcs->vmhub];
        uint32_t req = ring->adev->gart.gart_funcs->get_invalidate_req(vm_id);
        uint32_t data0, data1, mask;
-       unsigned eng = ring->idx;
-       unsigned i;
+       unsigned eng = ring->vm_inv_eng;
 
        pd_addr = pd_addr | 0x1; /* valid bit */
        /* now only use physical base address of PDE and valid */
        BUG_ON(pd_addr & 0xFFFF00000000003EULL);
 
-       for (i = 0; i < AMDGPU_MAX_VMHUBS; ++i) {
-               struct amdgpu_vmhub *hub = &ring->adev->vmhub[i];
-
-               data0 = (hub->ctx0_ptb_addr_hi32 + vm_id * 2) << 2;
-               data1 = upper_32_bits(pd_addr);
-               uvd_v7_0_vm_reg_write(ring, data0, data1);
-
-               data0 = (hub->ctx0_ptb_addr_lo32 + vm_id * 2) << 2;
-               data1 = lower_32_bits(pd_addr);
-               uvd_v7_0_vm_reg_write(ring, data0, data1);
-
-               data0 = (hub->ctx0_ptb_addr_lo32 + vm_id * 2) << 2;
-               data1 = lower_32_bits(pd_addr);
-               mask = 0xffffffff;
-               uvd_v7_0_vm_reg_wait(ring, data0, data1, mask);
-
-               /* flush TLB */
-               data0 = (hub->vm_inv_eng0_req + eng) << 2;
-               data1 = req;
-               uvd_v7_0_vm_reg_write(ring, data0, data1);
-
-               /* wait for flush */
-               data0 = (hub->vm_inv_eng0_ack + eng) << 2;
-               data1 = 1 << vm_id;
-               mask =  1 << vm_id;
-               uvd_v7_0_vm_reg_wait(ring, data0, data1, mask);
-       }
+       data0 = (hub->ctx0_ptb_addr_hi32 + vm_id * 2) << 2;
+       data1 = upper_32_bits(pd_addr);
+       uvd_v7_0_vm_reg_write(ring, data0, data1);
+
+       data0 = (hub->ctx0_ptb_addr_lo32 + vm_id * 2) << 2;
+       data1 = lower_32_bits(pd_addr);
+       uvd_v7_0_vm_reg_write(ring, data0, data1);
+
+       data0 = (hub->ctx0_ptb_addr_lo32 + vm_id * 2) << 2;
+       data1 = lower_32_bits(pd_addr);
+       mask = 0xffffffff;
+       uvd_v7_0_vm_reg_wait(ring, data0, data1, mask);
+
+       /* flush TLB */
+       data0 = (hub->vm_inv_eng0_req + eng) << 2;
+       data1 = req;
+       uvd_v7_0_vm_reg_write(ring, data0, data1);
+
+       /* wait for flush */
+       data0 = (hub->vm_inv_eng0_ack + eng) << 2;
+       data1 = 1 << vm_id;
+       mask =  1 << vm_id;
+       uvd_v7_0_vm_reg_wait(ring, data0, data1, mask);
 }
 
 static void uvd_v7_0_enc_ring_insert_end(struct amdgpu_ring *ring)
@@ -1080,44 +1346,37 @@ static void uvd_v7_0_enc_ring_insert_end(struct amdgpu_ring *ring)
 static void uvd_v7_0_enc_ring_emit_vm_flush(struct amdgpu_ring *ring,
                         unsigned int vm_id, uint64_t pd_addr)
 {
+       struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->funcs->vmhub];
        uint32_t req = ring->adev->gart.gart_funcs->get_invalidate_req(vm_id);
-       unsigned eng = ring->idx;
-       unsigned i;
+       unsigned eng = ring->vm_inv_eng;
 
        pd_addr = pd_addr | 0x1; /* valid bit */
        /* now only use physical base address of PDE and valid */
        BUG_ON(pd_addr & 0xFFFF00000000003EULL);
 
-       for (i = 0; i < AMDGPU_MAX_VMHUBS; ++i) {
-               struct amdgpu_vmhub *hub = &ring->adev->vmhub[i];
-
-               amdgpu_ring_write(ring, HEVC_ENC_CMD_REG_WRITE);
-               amdgpu_ring_write(ring,
-                       (hub->ctx0_ptb_addr_hi32 + vm_id * 2) << 2);
-               amdgpu_ring_write(ring, upper_32_bits(pd_addr));
-
-               amdgpu_ring_write(ring, HEVC_ENC_CMD_REG_WRITE);
-               amdgpu_ring_write(ring,
-                       (hub->ctx0_ptb_addr_lo32 + vm_id * 2) << 2);
-               amdgpu_ring_write(ring, lower_32_bits(pd_addr));
-
-               amdgpu_ring_write(ring, HEVC_ENC_CMD_REG_WAIT);
-               amdgpu_ring_write(ring,
-                       (hub->ctx0_ptb_addr_lo32 + vm_id * 2) << 2);
-               amdgpu_ring_write(ring, 0xffffffff);
-               amdgpu_ring_write(ring, lower_32_bits(pd_addr));
-
-               /* flush TLB */
-               amdgpu_ring_write(ring, HEVC_ENC_CMD_REG_WRITE);
-               amdgpu_ring_write(ring, (hub->vm_inv_eng0_req + eng) << 2);
-               amdgpu_ring_write(ring, req);
-
-               /* wait for flush */
-               amdgpu_ring_write(ring, HEVC_ENC_CMD_REG_WAIT);
-               amdgpu_ring_write(ring, (hub->vm_inv_eng0_ack + eng) << 2);
-               amdgpu_ring_write(ring, 1 << vm_id);
-               amdgpu_ring_write(ring, 1 << vm_id);
-       }
+       amdgpu_ring_write(ring, HEVC_ENC_CMD_REG_WRITE);
+       amdgpu_ring_write(ring, (hub->ctx0_ptb_addr_hi32 + vm_id * 2) << 2);
+       amdgpu_ring_write(ring, upper_32_bits(pd_addr));
+
+       amdgpu_ring_write(ring, HEVC_ENC_CMD_REG_WRITE);
+       amdgpu_ring_write(ring, (hub->ctx0_ptb_addr_lo32 + vm_id * 2) << 2);
+       amdgpu_ring_write(ring, lower_32_bits(pd_addr));
+
+       amdgpu_ring_write(ring, HEVC_ENC_CMD_REG_WAIT);
+       amdgpu_ring_write(ring, (hub->ctx0_ptb_addr_lo32 + vm_id * 2) << 2);
+       amdgpu_ring_write(ring, 0xffffffff);
+       amdgpu_ring_write(ring, lower_32_bits(pd_addr));
+
+       /* flush TLB */
+       amdgpu_ring_write(ring, HEVC_ENC_CMD_REG_WRITE);
+       amdgpu_ring_write(ring, (hub->vm_inv_eng0_req + eng) << 2);
+       amdgpu_ring_write(ring, req);
+
+       /* wait for flush */
+       amdgpu_ring_write(ring, HEVC_ENC_CMD_REG_WAIT);
+       amdgpu_ring_write(ring, (hub->vm_inv_eng0_ack + eng) << 2);
+       amdgpu_ring_write(ring, 1 << vm_id);
+       amdgpu_ring_write(ring, 1 << vm_id);
 }
 
 #if 0
@@ -1240,7 +1499,8 @@ static int uvd_v7_0_process_interrupt(struct amdgpu_device *adev,
                amdgpu_fence_process(&adev->uvd.ring_enc[0]);
                break;
        case 120:
-               amdgpu_fence_process(&adev->uvd.ring_enc[1]);
+               if (!amdgpu_sriov_vf(adev))
+                       amdgpu_fence_process(&adev->uvd.ring_enc[1]);
                break;
        default:
                DRM_ERROR("Unhandled interrupt: %d %d\n",
@@ -1448,13 +1708,14 @@ static const struct amdgpu_ring_funcs uvd_v7_0_ring_vm_funcs = {
        .align_mask = 0xf,
        .nop = PACKET0(SOC15_REG_OFFSET(UVD, 0, mmUVD_NO_OP), 0),
        .support_64bit_ptrs = false,
+       .vmhub = AMDGPU_MMHUB,
        .get_rptr = uvd_v7_0_ring_get_rptr,
        .get_wptr = uvd_v7_0_ring_get_wptr,
        .set_wptr = uvd_v7_0_ring_set_wptr,
        .emit_frame_size =
                2 + /* uvd_v7_0_ring_emit_hdp_flush */
                2 + /* uvd_v7_0_ring_emit_hdp_invalidate */
-               34 * AMDGPU_MAX_VMHUBS + /* uvd_v7_0_ring_emit_vm_flush */
+               34 + /* uvd_v7_0_ring_emit_vm_flush */
                14 + 14, /* uvd_v7_0_ring_emit_fence x2 vm fence */
        .emit_ib_size = 8, /* uvd_v7_0_ring_emit_ib */
        .emit_ib = uvd_v7_0_ring_emit_ib,
@@ -1475,11 +1736,12 @@ static const struct amdgpu_ring_funcs uvd_v7_0_enc_ring_vm_funcs = {
        .align_mask = 0x3f,
        .nop = HEVC_ENC_CMD_NO_OP,
        .support_64bit_ptrs = false,
+       .vmhub = AMDGPU_MMHUB,
        .get_rptr = uvd_v7_0_enc_ring_get_rptr,
        .get_wptr = uvd_v7_0_enc_ring_get_wptr,
        .set_wptr = uvd_v7_0_enc_ring_set_wptr,
        .emit_frame_size =
-               17 * AMDGPU_MAX_VMHUBS + /* uvd_v7_0_enc_ring_emit_vm_flush */
+               17 + /* uvd_v7_0_enc_ring_emit_vm_flush */
                5 + 5 + /* uvd_v7_0_enc_ring_emit_fence x2 vm fence */
                1, /* uvd_v7_0_enc_ring_insert_end */
        .emit_ib_size = 5, /* uvd_v7_0_enc_ring_emit_ib */
index edde5fe938d6b5876927b55e9b77c4c58eeabba4..139f964196b42ba65f6e5e8c0b51fa1c2e9ae37c 100644 (file)
@@ -49,63 +49,6 @@ static void vce_v4_0_mc_resume(struct amdgpu_device *adev);
 static void vce_v4_0_set_ring_funcs(struct amdgpu_device *adev);
 static void vce_v4_0_set_irq_funcs(struct amdgpu_device *adev);
 
-static inline void mmsch_insert_direct_wt(struct mmsch_v1_0_cmd_direct_write *direct_wt,
-                                         uint32_t *init_table,
-                                         uint32_t reg_offset,
-                                         uint32_t value)
-{
-       direct_wt->cmd_header.reg_offset = reg_offset;
-       direct_wt->reg_value = value;
-       memcpy((void *)init_table, direct_wt, sizeof(struct mmsch_v1_0_cmd_direct_write));
-}
-
-static inline void mmsch_insert_direct_rd_mod_wt(struct mmsch_v1_0_cmd_direct_read_modify_write *direct_rd_mod_wt,
-                                                uint32_t *init_table,
-                                                uint32_t reg_offset,
-                                                uint32_t mask, uint32_t data)
-{
-       direct_rd_mod_wt->cmd_header.reg_offset = reg_offset;
-       direct_rd_mod_wt->mask_value = mask;
-       direct_rd_mod_wt->write_data = data;
-       memcpy((void *)init_table, direct_rd_mod_wt,
-              sizeof(struct mmsch_v1_0_cmd_direct_read_modify_write));
-}
-
-static inline void mmsch_insert_direct_poll(struct mmsch_v1_0_cmd_direct_polling *direct_poll,
-                                           uint32_t *init_table,
-                                           uint32_t reg_offset,
-                                           uint32_t mask, uint32_t wait)
-{
-       direct_poll->cmd_header.reg_offset = reg_offset;
-       direct_poll->mask_value = mask;
-       direct_poll->wait_value = wait;
-       memcpy((void *)init_table, direct_poll, sizeof(struct mmsch_v1_0_cmd_direct_polling));
-}
-
-#define INSERT_DIRECT_RD_MOD_WT(reg, mask, data) { \
-       mmsch_insert_direct_rd_mod_wt(&direct_rd_mod_wt, \
-                                     init_table, (reg), \
-                                     (mask), (data)); \
-       init_table += sizeof(struct mmsch_v1_0_cmd_direct_read_modify_write)/4; \
-       table_size += sizeof(struct mmsch_v1_0_cmd_direct_read_modify_write)/4; \
-}
-
-#define INSERT_DIRECT_WT(reg, value) { \
-       mmsch_insert_direct_wt(&direct_wt, \
-                              init_table, (reg), \
-                              (value)); \
-       init_table += sizeof(struct mmsch_v1_0_cmd_direct_write)/4; \
-       table_size += sizeof(struct mmsch_v1_0_cmd_direct_write)/4; \
-}
-
-#define INSERT_DIRECT_POLL(reg, mask, wait) { \
-       mmsch_insert_direct_poll(&direct_poll, \
-                                init_table, (reg), \
-                                (mask), (wait)); \
-       init_table += sizeof(struct mmsch_v1_0_cmd_direct_polling)/4; \
-       table_size += sizeof(struct mmsch_v1_0_cmd_direct_polling)/4; \
-}
-
 /**
  * vce_v4_0_ring_get_rptr - get read pointer
  *
@@ -280,60 +223,73 @@ static int vce_v4_0_sriov_start(struct amdgpu_device *adev)
                init_table += header->vce_table_offset;
 
                ring = &adev->vce.ring[0];
-               INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_RB_RPTR), ring->wptr);
-               INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_RB_WPTR), ring->wptr);
-               INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_RB_BASE_LO), lower_32_bits(ring->gpu_addr));
-               INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_RB_BASE_HI), upper_32_bits(ring->gpu_addr));
-               INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_RB_SIZE), ring->ring_size / 4);
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_RB_BASE_LO),
+                                           lower_32_bits(ring->gpu_addr));
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_RB_BASE_HI),
+                                           upper_32_bits(ring->gpu_addr));
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_RB_SIZE),
+                                           ring->ring_size / 4);
 
                /* BEGING OF MC_RESUME */
-               INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_CLOCK_GATING_A), ~(1 << 16), 0);
-               INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_UENC_CLOCK_GATING), ~0xFF9FF000, 0x1FF000);
-               INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_UENC_REG_CLOCK_GATING), ~0x3F, 0x3F);
-               INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_CLOCK_GATING_B), 0x1FF);
-
-               INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_CTRL), 0x398000);
-               INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_CACHE_CTRL), ~0x1, 0);
-               INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_SWAP_CNTL), 0);
-               INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_SWAP_CNTL1), 0);
-               INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VM_CTRL), 0);
-
-               INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VCPU_CACHE_40BIT_BAR0), adev->vce.gpu_addr >> 8);
-               INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VCPU_CACHE_40BIT_BAR1), adev->vce.gpu_addr >> 8);
-               INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VCPU_CACHE_40BIT_BAR2), adev->vce.gpu_addr >> 8);
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_CTRL), 0x398000);
+               MMSCH_V1_0_INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_CACHE_CTRL), ~0x1, 0);
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_SWAP_CNTL), 0);
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_SWAP_CNTL1), 0);
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VM_CTRL), 0);
+
+               if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
+                   MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VCPU_CACHE_40BIT_BAR0),
+                                               adev->firmware.ucode[AMDGPU_UCODE_ID_VCE].mc_addr >> 8);
+                   MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VCPU_CACHE_40BIT_BAR1),
+                                               adev->firmware.ucode[AMDGPU_UCODE_ID_VCE].mc_addr >> 8);
+                   MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VCPU_CACHE_40BIT_BAR2),
+                                               adev->firmware.ucode[AMDGPU_UCODE_ID_VCE].mc_addr >> 8);
+               } else {
+                   MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VCPU_CACHE_40BIT_BAR0),
+                                               adev->vce.gpu_addr >> 8);
+                   MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VCPU_CACHE_40BIT_BAR1),
+                                               adev->vce.gpu_addr >> 8);
+                   MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_VCPU_CACHE_40BIT_BAR2),
+                                               adev->vce.gpu_addr >> 8);
+               }
 
                offset = AMDGPU_VCE_FIRMWARE_OFFSET;
                size = VCE_V4_0_FW_SIZE;
-               INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_VCPU_CACHE_OFFSET0), offset & 0x7FFFFFFF);
-               INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_VCPU_CACHE_SIZE0), size);
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_VCPU_CACHE_OFFSET0),
+                                           offset & 0x7FFFFFFF);
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_VCPU_CACHE_SIZE0), size);
 
                offset += size;
                size = VCE_V4_0_STACK_SIZE;
-               INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_VCPU_CACHE_OFFSET1), offset & 0x7FFFFFFF);
-               INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_VCPU_CACHE_SIZE1), size);
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_VCPU_CACHE_OFFSET1),
+                                           offset & 0x7FFFFFFF);
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_VCPU_CACHE_SIZE1), size);
 
                offset += size;
                size = VCE_V4_0_DATA_SIZE;
-               INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_VCPU_CACHE_OFFSET2), offset & 0x7FFFFFFF);
-               INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_VCPU_CACHE_SIZE2), size);
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_VCPU_CACHE_OFFSET2),
+                                           offset & 0x7FFFFFFF);
+               MMSCH_V1_0_INSERT_DIRECT_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_VCPU_CACHE_SIZE2), size);
 
-               INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_CTRL2), ~0x100, 0);
-               INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_SYS_INT_EN),
-                               0xffffffff, VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK);
+               MMSCH_V1_0_INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_LMI_CTRL2), ~0x100, 0);
+               MMSCH_V1_0_INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_SYS_INT_EN),
+                                                  0xffffffff, VCE_SYS_INT_EN__VCE_SYS_INT_TRAP_INTERRUPT_EN_MASK);
 
                /* end of MC_RESUME */
-               INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_VCPU_CNTL),
-                               ~0x200001, VCE_VCPU_CNTL__CLK_EN_MASK);
-               INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_SOFT_RESET),
-                               ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK, 0);
+               MMSCH_V1_0_INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_STATUS),
+                                                  VCE_STATUS__JOB_BUSY_MASK, ~VCE_STATUS__JOB_BUSY_MASK);
+               MMSCH_V1_0_INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_VCPU_CNTL),
+                                                  ~0x200001, VCE_VCPU_CNTL__CLK_EN_MASK);
+               MMSCH_V1_0_INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_SOFT_RESET),
+                                                  ~VCE_SOFT_RESET__ECPU_SOFT_RESET_MASK, 0);
 
-               INSERT_DIRECT_POLL(SOC15_REG_OFFSET(VCE, 0, mmVCE_STATUS),
-                               VCE_STATUS_VCPU_REPORT_FW_LOADED_MASK,
-                               VCE_STATUS_VCPU_REPORT_FW_LOADED_MASK);
+               MMSCH_V1_0_INSERT_DIRECT_POLL(SOC15_REG_OFFSET(VCE, 0, mmVCE_STATUS),
+                                             VCE_STATUS_VCPU_REPORT_FW_LOADED_MASK,
+                                             VCE_STATUS_VCPU_REPORT_FW_LOADED_MASK);
 
                /* clear BUSY flag */
-               INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_STATUS),
-                               ~VCE_STATUS__JOB_BUSY_MASK, 0);
+               MMSCH_V1_0_INSERT_DIRECT_RD_MOD_WT(SOC15_REG_OFFSET(VCE, 0, mmVCE_STATUS),
+                                                  ~VCE_STATUS__JOB_BUSY_MASK, 0);
 
                /* add end packet */
                memcpy((void *)init_table, &end, sizeof(struct mmsch_v1_0_cmd_end));
@@ -494,20 +450,9 @@ static int vce_v4_0_sw_init(void *handle)
                        return r;
        }
 
-       if (amdgpu_sriov_vf(adev)) {
-               r = amdgpu_bo_create_kernel(adev, PAGE_SIZE, PAGE_SIZE,
-                                           AMDGPU_GEM_DOMAIN_VRAM,
-                                           &adev->virt.mm_table.bo,
-                                           &adev->virt.mm_table.gpu_addr,
-                                           (void *)&adev->virt.mm_table.cpu_addr);
-               if (!r) {
-                       memset((void *)adev->virt.mm_table.cpu_addr, 0, PAGE_SIZE);
-                       printk("mm table gpu addr = 0x%llx, cpu addr = %p. \n",
-                              adev->virt.mm_table.gpu_addr,
-                              adev->virt.mm_table.cpu_addr);
-               }
+       r = amdgpu_virt_alloc_mm_table(adev);
+       if (r)
                return r;
-       }
 
        return r;
 }
@@ -518,10 +463,7 @@ static int vce_v4_0_sw_fini(void *handle)
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
        /* free MM table */
-       if (amdgpu_sriov_vf(adev))
-               amdgpu_bo_free_kernel(&adev->virt.mm_table.bo,
-                                     &adev->virt.mm_table.gpu_addr,
-                                     (void *)&adev->virt.mm_table.cpu_addr);
+       amdgpu_virt_free_mm_table(adev);
 
        r = amdgpu_vce_suspend(adev);
        if (r)
@@ -973,44 +915,37 @@ static void vce_v4_0_ring_insert_end(struct amdgpu_ring *ring)
 static void vce_v4_0_emit_vm_flush(struct amdgpu_ring *ring,
                         unsigned int vm_id, uint64_t pd_addr)
 {
+       struct amdgpu_vmhub *hub = &ring->adev->vmhub[ring->funcs->vmhub];
        uint32_t req = ring->adev->gart.gart_funcs->get_invalidate_req(vm_id);
-       unsigned eng = ring->idx;
-       unsigned i;
+       unsigned eng = ring->vm_inv_eng;
 
        pd_addr = pd_addr | 0x1; /* valid bit */
        /* now only use physical base address of PDE and valid */
        BUG_ON(pd_addr & 0xFFFF00000000003EULL);
 
-       for (i = 0; i < AMDGPU_MAX_VMHUBS; ++i) {
-               struct amdgpu_vmhub *hub = &ring->adev->vmhub[i];
-
-               amdgpu_ring_write(ring, VCE_CMD_REG_WRITE);
-               amdgpu_ring_write(ring,
-                       (hub->ctx0_ptb_addr_hi32 + vm_id * 2) << 2);
-               amdgpu_ring_write(ring, upper_32_bits(pd_addr));
-
-               amdgpu_ring_write(ring, VCE_CMD_REG_WRITE);
-               amdgpu_ring_write(ring,
-                       (hub->ctx0_ptb_addr_lo32 + vm_id * 2) << 2);
-               amdgpu_ring_write(ring, lower_32_bits(pd_addr));
-
-               amdgpu_ring_write(ring, VCE_CMD_REG_WAIT);
-               amdgpu_ring_write(ring,
-                       (hub->ctx0_ptb_addr_lo32 + vm_id * 2) << 2);
-               amdgpu_ring_write(ring, 0xffffffff);
-               amdgpu_ring_write(ring, lower_32_bits(pd_addr));
-
-               /* flush TLB */
-               amdgpu_ring_write(ring, VCE_CMD_REG_WRITE);
-               amdgpu_ring_write(ring, (hub->vm_inv_eng0_req + eng) << 2);
-               amdgpu_ring_write(ring, req);
-
-               /* wait for flush */
-               amdgpu_ring_write(ring, VCE_CMD_REG_WAIT);
-               amdgpu_ring_write(ring, (hub->vm_inv_eng0_ack + eng) << 2);
-               amdgpu_ring_write(ring, 1 << vm_id);
-               amdgpu_ring_write(ring, 1 << vm_id);
-       }
+       amdgpu_ring_write(ring, VCE_CMD_REG_WRITE);
+       amdgpu_ring_write(ring, (hub->ctx0_ptb_addr_hi32 + vm_id * 2) << 2);
+       amdgpu_ring_write(ring, upper_32_bits(pd_addr));
+
+       amdgpu_ring_write(ring, VCE_CMD_REG_WRITE);
+       amdgpu_ring_write(ring, (hub->ctx0_ptb_addr_lo32 + vm_id * 2) << 2);
+       amdgpu_ring_write(ring, lower_32_bits(pd_addr));
+
+       amdgpu_ring_write(ring, VCE_CMD_REG_WAIT);
+       amdgpu_ring_write(ring, (hub->ctx0_ptb_addr_lo32 + vm_id * 2) << 2);
+       amdgpu_ring_write(ring, 0xffffffff);
+       amdgpu_ring_write(ring, lower_32_bits(pd_addr));
+
+       /* flush TLB */
+       amdgpu_ring_write(ring, VCE_CMD_REG_WRITE);
+       amdgpu_ring_write(ring, (hub->vm_inv_eng0_req + eng) << 2);
+       amdgpu_ring_write(ring, req);
+
+       /* wait for flush */
+       amdgpu_ring_write(ring, VCE_CMD_REG_WAIT);
+       amdgpu_ring_write(ring, (hub->vm_inv_eng0_ack + eng) << 2);
+       amdgpu_ring_write(ring, 1 << vm_id);
+       amdgpu_ring_write(ring, 1 << vm_id);
 }
 
 static int vce_v4_0_set_interrupt_state(struct amdgpu_device *adev,
@@ -1078,12 +1013,13 @@ static const struct amdgpu_ring_funcs vce_v4_0_ring_vm_funcs = {
        .align_mask = 0x3f,
        .nop = VCE_CMD_NO_OP,
        .support_64bit_ptrs = false,
+       .vmhub = AMDGPU_MMHUB,
        .get_rptr = vce_v4_0_ring_get_rptr,
        .get_wptr = vce_v4_0_ring_get_wptr,
        .set_wptr = vce_v4_0_ring_set_wptr,
        .parse_cs = amdgpu_vce_ring_parse_cs_vm,
        .emit_frame_size =
-               17 * AMDGPU_MAX_VMHUBS + /* vce_v4_0_emit_vm_flush */
+               17 + /* vce_v4_0_emit_vm_flush */
                5 + 5 + /* amdgpu_vce_ring_emit_fence x2 vm fence */
                1, /* vce_v4_0_ring_insert_end */
        .emit_ib_size = 5, /* vce_v4_0_ring_emit_ib */
index 2ccf44e580de4a521a805bd57f527377abe0ac4d..1d1ac1ef94f7a4e48f1d46485ca28a07ec7d78b9 100644 (file)
@@ -138,6 +138,12 @@ struct amd_pp_profile {
        uint8_t down_hyst;
 };
 
+enum amd_fan_ctrl_mode {
+       AMD_FAN_CTRL_NONE = 0,
+       AMD_FAN_CTRL_MANUAL = 1,
+       AMD_FAN_CTRL_AUTO = 2,
+};
+
 /* CG flags */
 #define AMD_CG_SUPPORT_GFX_MGCG                        (1 << 0)
 #define AMD_CG_SUPPORT_GFX_MGLS                        (1 << 1)
index 17b9d41f3e879b45dc7cc69313d5e1cd6e421e8c..0a94f749e3c0a24f5d9b98256f19336d73704a09 100644 (file)
@@ -53,20 +53,6 @@ enum cgs_ind_reg {
        CGS_IND_REG__AUDIO_ENDPT
 };
 
-/**
- * enum cgs_clock - Clocks controlled by the SMU
- */
-enum cgs_clock {
-       CGS_CLOCK__SCLK,
-       CGS_CLOCK__MCLK,
-       CGS_CLOCK__VCLK,
-       CGS_CLOCK__DCLK,
-       CGS_CLOCK__ECLK,
-       CGS_CLOCK__ACLK,
-       CGS_CLOCK__ICLK,
-       /* ... */
-};
-
 /**
  * enum cgs_engine - Engines that can be statically power-gated
  */
@@ -81,15 +67,6 @@ enum cgs_engine {
        /* ... */
 };
 
-/**
- * enum cgs_voltage_planes - Voltage planes for external camera HW
- */
-enum cgs_voltage_planes {
-       CGS_VOLTAGE_PLANE__SENSOR0,
-       CGS_VOLTAGE_PLANE__SENSOR1,
-       /* ... */
-};
-
 /*
  * enum cgs_ucode_id - Firmware types for different IPs
  */
@@ -146,17 +123,6 @@ enum cgs_resource_type {
        CGS_RESOURCE_TYPE_ROM,
 };
 
-/**
- * struct cgs_clock_limits - Clock limits
- *
- * Clocks are specified in 10KHz units.
- */
-struct cgs_clock_limits {
-       unsigned min;           /**< Minimum supported frequency */
-       unsigned max;           /**< Maxumim supported frequency */
-       unsigned sustainable;   /**< Thermally sustainable frequency */
-};
-
 /**
  * struct cgs_firmware_info - Firmware information
  */
@@ -220,54 +186,6 @@ struct cgs_acpi_method_info {
        uint32_t padding[9];
 };
 
-/**
- * cgs_gpu_mem_info() - Return information about memory heaps
- * @cgs_device: opaque device handle
- * @type:      memory type
- * @mc_start:  Start MC address of the heap (output)
- * @mc_size:   MC address space size (output)
- * @mem_size:  maximum amount of memory available for allocation (output)
- *
- * This function returns information about memory heaps. The type
- * parameter is used to select the memory heap. The mc_start and
- * mc_size for GART heaps may be bigger than the memory available for
- * allocation.
- *
- * mc_start and mc_size are undefined for non-contiguous FB memory
- * types, since buffers allocated with these types may or may not be
- * GART mapped.
- *
- * Return:  0 on success, -errno otherwise
- */
-typedef int (*cgs_gpu_mem_info_t)(struct cgs_device *cgs_device, enum cgs_gpu_mem_type type,
-                                 uint64_t *mc_start, uint64_t *mc_size,
-                                 uint64_t *mem_size);
-
-/**
- * cgs_gmap_kmem() - map kernel memory to GART aperture
- * @cgs_device:        opaque device handle
- * @kmem:      pointer to kernel memory
- * @size:      size to map
- * @min_offset: minimum offset from start of GART aperture
- * @max_offset: maximum offset from start of GART aperture
- * @kmem_handle: kernel memory handle (output)
- * @mcaddr:    MC address (output)
- *
- * Return:  0 on success, -errno otherwise
- */
-typedef int (*cgs_gmap_kmem_t)(struct cgs_device *cgs_device, void *kmem, uint64_t size,
-                              uint64_t min_offset, uint64_t max_offset,
-                              cgs_handle_t *kmem_handle, uint64_t *mcaddr);
-
-/**
- * cgs_gunmap_kmem() - unmap kernel memory
- * @cgs_device:        opaque device handle
- * @kmem_handle: kernel memory handle returned by gmap_kmem
- *
- * Return:  0 on success, -errno otherwise
- */
-typedef int (*cgs_gunmap_kmem_t)(struct cgs_device *cgs_device, cgs_handle_t kmem_handle);
-
 /**
  * cgs_alloc_gpu_mem() - Allocate GPU memory
  * @cgs_device:        opaque device handle
@@ -391,62 +309,6 @@ typedef uint32_t (*cgs_read_ind_register_t)(struct cgs_device *cgs_device, enum
 typedef void (*cgs_write_ind_register_t)(struct cgs_device *cgs_device, enum cgs_ind_reg space,
                                         unsigned index, uint32_t value);
 
-/**
- * cgs_read_pci_config_byte() - Read byte from PCI configuration space
- * @cgs_device:        opaque device handle
- * @addr:      address
- *
- * Return:  Value read
- */
-typedef uint8_t (*cgs_read_pci_config_byte_t)(struct cgs_device *cgs_device, unsigned addr);
-
-/**
- * cgs_read_pci_config_word() - Read word from PCI configuration space
- * @cgs_device:        opaque device handle
- * @addr:      address, must be word-aligned
- *
- * Return:  Value read
- */
-typedef uint16_t (*cgs_read_pci_config_word_t)(struct cgs_device *cgs_device, unsigned addr);
-
-/**
- * cgs_read_pci_config_dword() - Read dword from PCI configuration space
- * @cgs_device:        opaque device handle
- * @addr:      address, must be dword-aligned
- *
- * Return:  Value read
- */
-typedef uint32_t (*cgs_read_pci_config_dword_t)(struct cgs_device *cgs_device,
-                                               unsigned addr);
-
-/**
- * cgs_write_pci_config_byte() - Write byte to PCI configuration space
- * @cgs_device:        opaque device handle
- * @addr:      address
- * @value:     value to write
- */
-typedef void (*cgs_write_pci_config_byte_t)(struct cgs_device *cgs_device, unsigned addr,
-                                           uint8_t value);
-
-/**
- * cgs_write_pci_config_word() - Write byte to PCI configuration space
- * @cgs_device:        opaque device handle
- * @addr:      address, must be word-aligned
- * @value:     value to write
- */
-typedef void (*cgs_write_pci_config_word_t)(struct cgs_device *cgs_device, unsigned addr,
-                                           uint16_t value);
-
-/**
- * cgs_write_pci_config_dword() - Write byte to PCI configuration space
- * @cgs_device:        opaque device handle
- * @addr:      address, must be dword-aligned
- * @value:     value to write
- */
-typedef void (*cgs_write_pci_config_dword_t)(struct cgs_device *cgs_device, unsigned addr,
-                                            uint32_t value);
-
-
 /**
  * cgs_get_pci_resource() - provide access to a device resource (PCI BAR)
  * @cgs_device:        opaque device handle
@@ -500,87 +362,6 @@ typedef int (*cgs_atom_get_cmd_table_revs_t)(struct cgs_device *cgs_device, unsi
 typedef int (*cgs_atom_exec_cmd_table_t)(struct cgs_device *cgs_device,
                                         unsigned table, void *args);
 
-/**
- * cgs_create_pm_request() - Create a power management request
- * @cgs_device:        opaque device handle
- * @request:   handle of created PM request (output)
- *
- * Return:  0 on success, -errno otherwise
- */
-typedef int (*cgs_create_pm_request_t)(struct cgs_device *cgs_device, cgs_handle_t *request);
-
-/**
- * cgs_destroy_pm_request() - Destroy a power management request
- * @cgs_device:        opaque device handle
- * @request:   handle of created PM request
- *
- * Return:  0 on success, -errno otherwise
- */
-typedef int (*cgs_destroy_pm_request_t)(struct cgs_device *cgs_device, cgs_handle_t request);
-
-/**
- * cgs_set_pm_request() - Activate or deactiveate a PM request
- * @cgs_device:        opaque device handle
- * @request:   PM request handle
- * @active:    0 = deactivate, non-0 = activate
- *
- * While a PM request is active, its minimum clock requests are taken
- * into account as the requested engines are powered up. When the
- * request is inactive, the engines may be powered down and clocks may
- * be lower, depending on other PM requests by other driver
- * components.
- *
- * Return:  0 on success, -errno otherwise
- */
-typedef int (*cgs_set_pm_request_t)(struct cgs_device *cgs_device, cgs_handle_t request,
-                                   int active);
-
-/**
- * cgs_pm_request_clock() - Request a minimum frequency for a specific clock
- * @cgs_device:        opaque device handle
- * @request:   PM request handle
- * @clock:     which clock?
- * @freq:      requested min. frequency in 10KHz units (0 to clear request)
- *
- * Return:  0 on success, -errno otherwise
- */
-typedef int (*cgs_pm_request_clock_t)(struct cgs_device *cgs_device, cgs_handle_t request,
-                                     enum cgs_clock clock, unsigned freq);
-
-/**
- * cgs_pm_request_engine() - Request an engine to be powered up
- * @cgs_device:        opaque device handle
- * @request:   PM request handle
- * @engine:    which engine?
- * @powered:   0 = powered down, non-0 = powered up
- *
- * Return:  0 on success, -errno otherwise
- */
-typedef int (*cgs_pm_request_engine_t)(struct cgs_device *cgs_device, cgs_handle_t request,
-                                      enum cgs_engine engine, int powered);
-
-/**
- * cgs_pm_query_clock_limits() - Query clock frequency limits
- * @cgs_device:        opaque device handle
- * @clock:     which clock?
- * @limits:    clock limits
- *
- * Return:  0 on success, -errno otherwise
- */
-typedef int (*cgs_pm_query_clock_limits_t)(struct cgs_device *cgs_device,
-                                          enum cgs_clock clock,
-                                          struct cgs_clock_limits *limits);
-
-/**
- * cgs_set_camera_voltages() - Apply specific voltages to PMIC voltage planes
- * @cgs_device:        opaque device handle
- * @mask:      bitmask of voltages to change (1<<CGS_VOLTAGE_PLANE__xyz|...)
- * @voltages:  pointer to array of voltage values in 1mV units
- *
- * Return: 0 on success, -errno otherwise
- */
-typedef int (*cgs_set_camera_voltages_t)(struct cgs_device *cgs_device, uint32_t mask,
-                                        const uint32_t *voltages);
 /**
  * cgs_get_firmware_info - Get the firmware information from core driver
  * @cgs_device: opaque device handle
@@ -627,9 +408,6 @@ typedef int (*cgs_enter_safe_mode)(struct cgs_device *cgs_device, bool en);
 
 struct cgs_ops {
        /* memory management calls (similar to KFD interface) */
-       cgs_gpu_mem_info_t gpu_mem_info;
-       cgs_gmap_kmem_t gmap_kmem;
-       cgs_gunmap_kmem_t gunmap_kmem;
        cgs_alloc_gpu_mem_t alloc_gpu_mem;
        cgs_free_gpu_mem_t free_gpu_mem;
        cgs_gmap_gpu_mem_t gmap_gpu_mem;
@@ -641,27 +419,12 @@ struct cgs_ops {
        cgs_write_register_t write_register;
        cgs_read_ind_register_t read_ind_register;
        cgs_write_ind_register_t write_ind_register;
-       /* PCI configuration space access */
-       cgs_read_pci_config_byte_t read_pci_config_byte;
-       cgs_read_pci_config_word_t read_pci_config_word;
-       cgs_read_pci_config_dword_t read_pci_config_dword;
-       cgs_write_pci_config_byte_t write_pci_config_byte;
-       cgs_write_pci_config_word_t write_pci_config_word;
-       cgs_write_pci_config_dword_t write_pci_config_dword;
        /* PCI resources */
        cgs_get_pci_resource_t get_pci_resource;
        /* ATOM BIOS */
        cgs_atom_get_data_table_t atom_get_data_table;
        cgs_atom_get_cmd_table_revs_t atom_get_cmd_table_revs;
        cgs_atom_exec_cmd_table_t atom_exec_cmd_table;
-       /* Power management */
-       cgs_create_pm_request_t create_pm_request;
-       cgs_destroy_pm_request_t destroy_pm_request;
-       cgs_set_pm_request_t set_pm_request;
-       cgs_pm_request_clock_t pm_request_clock;
-       cgs_pm_request_engine_t pm_request_engine;
-       cgs_pm_query_clock_limits_t pm_query_clock_limits;
-       cgs_set_camera_voltages_t set_camera_voltages;
        /* Firmware Info */
        cgs_get_firmware_info get_firmware_info;
        cgs_rel_firmware rel_firmware;
@@ -696,12 +459,6 @@ struct cgs_device
 #define CGS_OS_CALL(func,dev,...) \
        (((struct cgs_device *)dev)->os_ops->func(dev, ##__VA_ARGS__))
 
-#define cgs_gpu_mem_info(dev,type,mc_start,mc_size,mem_size)           \
-       CGS_CALL(gpu_mem_info,dev,type,mc_start,mc_size,mem_size)
-#define cgs_gmap_kmem(dev,kmem,size,min_off,max_off,kmem_handle,mcaddr)        \
-       CGS_CALL(gmap_kmem,dev,kmem,size,min_off,max_off,kmem_handle,mcaddr)
-#define cgs_gunmap_kmem(dev,kmem_handle)       \
-       CGS_CALL(gunmap_kmem,dev,keme_handle)
 #define cgs_alloc_gpu_mem(dev,type,size,align,min_off,max_off,handle)  \
        CGS_CALL(alloc_gpu_mem,dev,type,size,align,min_off,max_off,handle)
 #define cgs_free_gpu_mem(dev,handle)           \
@@ -724,19 +481,6 @@ struct cgs_device
 #define cgs_write_ind_register(dev,space,index,value)          \
        CGS_CALL(write_ind_register,dev,space,index,value)
 
-#define cgs_read_pci_config_byte(dev,addr)     \
-       CGS_CALL(read_pci_config_byte,dev,addr)
-#define cgs_read_pci_config_word(dev,addr)     \
-       CGS_CALL(read_pci_config_word,dev,addr)
-#define cgs_read_pci_config_dword(dev,addr)            \
-       CGS_CALL(read_pci_config_dword,dev,addr)
-#define cgs_write_pci_config_byte(dev,addr,value)      \
-       CGS_CALL(write_pci_config_byte,dev,addr,value)
-#define cgs_write_pci_config_word(dev,addr,value)      \
-       CGS_CALL(write_pci_config_word,dev,addr,value)
-#define cgs_write_pci_config_dword(dev,addr,value)     \
-       CGS_CALL(write_pci_config_dword,dev,addr,value)
-
 #define cgs_atom_get_data_table(dev,table,size,frev,crev)      \
        CGS_CALL(atom_get_data_table,dev,table,size,frev,crev)
 #define cgs_atom_get_cmd_table_revs(dev,table,frev,crev)       \
@@ -744,20 +488,6 @@ struct cgs_device
 #define cgs_atom_exec_cmd_table(dev,table,args)                \
        CGS_CALL(atom_exec_cmd_table,dev,table,args)
 
-#define cgs_create_pm_request(dev,request)     \
-       CGS_CALL(create_pm_request,dev,request)
-#define cgs_destroy_pm_request(dev,request)            \
-       CGS_CALL(destroy_pm_request,dev,request)
-#define cgs_set_pm_request(dev,request,active)         \
-       CGS_CALL(set_pm_request,dev,request,active)
-#define cgs_pm_request_clock(dev,request,clock,freq)           \
-       CGS_CALL(pm_request_clock,dev,request,clock,freq)
-#define cgs_pm_request_engine(dev,request,engine,powered)      \
-       CGS_CALL(pm_request_engine,dev,request,engine,powered)
-#define cgs_pm_query_clock_limits(dev,clock,limits)            \
-       CGS_CALL(pm_query_clock_limits,dev,clock,limits)
-#define cgs_set_camera_voltages(dev,mask,voltages)     \
-       CGS_CALL(set_camera_voltages,dev,mask,voltages)
 #define cgs_get_firmware_info(dev, type, info) \
        CGS_CALL(get_firmware_info, dev, type, info)
 #define cgs_rel_firmware(dev, type)    \
index 9da5b0bb66d874bb72412544d5f4410e02a3e0d3..f73e80c4bf3374b136a816f4c4dc72ccca05e62d 100644 (file)
@@ -251,7 +251,9 @@ static int pp_suspend(void *handle)
 
        ret = pp_check(pp_handle);
 
-       if (ret != 0)
+       if (ret == PP_DPM_DISABLED)
+               return 0;
+       else if (ret != 0)
                return ret;
 
        eventmgr = pp_handle->eventmgr;
index 9ef2d90e28869f7a6058eb7a1f9771241bb7fc9d..b82c43af59ab38fd5b9d4c73eaa2b4db7049480f 100644 (file)
@@ -219,7 +219,7 @@ const pem_event_action notify_smu_suspend_tasks[] = {
 };
 
 const pem_event_action disable_smc_firmware_ctf_tasks[] = {
-       /* PEM_Task_DisableSMCFirmwareCTF,*/
+       pem_task_disable_smc_firmware_ctf,
        NULL
 };
 
index e04216ec7ee15b51043045064455598696655d45..8c4ebaae1e0cadf1bf037727789b22bcc3ce185b 100644 (file)
@@ -173,6 +173,11 @@ int pem_task_stop_asic_block_usage(struct pp_eventmgr *eventmgr, struct pem_even
        return 0;
 }
 
+int pem_task_disable_smc_firmware_ctf(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
+{
+       return phm_disable_smc_firmware_ctf(eventmgr->hwmgr);
+}
+
 int pem_task_setup_asic(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data)
 {
        return phm_setup_asic(eventmgr->hwmgr);
index 6c6297e3b5984732c1561febce9ce346c0c83838..37e7ca5a58e0a21b669f83855d61ae70b0df6034 100644 (file)
@@ -84,5 +84,6 @@ int pem_task_update_allowed_performance_levels(struct pp_eventmgr *eventmgr, str
 /*thermal */
 int pem_task_initialize_thermal_controller(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
 int pem_task_uninitialize_thermal_controller(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
+int pem_task_disable_smc_firmware_ctf(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data);
 
 #endif /* _EVENT_TASKS_H_ */
index 23bba2c8b18e60d9a66c17f746cd54beb5ca18e4..fcc722ea76490a3d788c1a2b577423dd01033392 100644 (file)
@@ -501,3 +501,13 @@ int phm_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_clock_i
 
        return hwmgr->hwmgr_func->get_max_high_clocks(hwmgr, clocks);
 }
+
+int phm_disable_smc_firmware_ctf(struct pp_hwmgr *hwmgr)
+{
+       PHM_FUNC_CHECK(hwmgr);
+
+       if (hwmgr->hwmgr_func->disable_smc_firmware_ctf == NULL)
+               return -EINVAL;
+
+       return hwmgr->hwmgr_func->disable_smc_firmware_ctf(hwmgr);
+}
index b71525f838e6db8fbf611aba60d8219e03b89dfe..56023114ad6fb495a660b45d1b6204f166c6dccb 100644 (file)
@@ -314,52 +314,45 @@ int pp_atomfwctrl_get_avfs_information(struct pp_hwmgr *hwmgr,
                        le32_to_cpu(profile->gb_vdroop_table_ckson_a2);
        param->ulGbFuseTableCksoffM1 =
                        le32_to_cpu(profile->avfsgb_fuse_table_cksoff_m1);
-       param->usGbFuseTableCksoffM2 =
+       param->ulGbFuseTableCksoffM2 =
                        le16_to_cpu(profile->avfsgb_fuse_table_cksoff_m2);
        param->ulGbFuseTableCksoffB =
                        le32_to_cpu(profile->avfsgb_fuse_table_cksoff_b);
        param->ulGbFuseTableCksonM1 =
                        le32_to_cpu(profile->avfsgb_fuse_table_ckson_m1);
-       param->usGbFuseTableCksonM2 =
+       param->ulGbFuseTableCksonM2 =
                        le16_to_cpu(profile->avfsgb_fuse_table_ckson_m2);
        param->ulGbFuseTableCksonB =
                        le32_to_cpu(profile->avfsgb_fuse_table_ckson_b);
-       param->usMaxVoltage025mv =
-                       le16_to_cpu(profile->max_voltage_0_25mv);
-       param->ucEnableGbVdroopTableCksoff =
-                       profile->enable_gb_vdroop_table_cksoff;
+
        param->ucEnableGbVdroopTableCkson =
                        profile->enable_gb_vdroop_table_ckson;
-       param->ucEnableGbFuseTableCksoff =
-                       profile->enable_gb_fuse_table_cksoff;
        param->ucEnableGbFuseTableCkson =
                        profile->enable_gb_fuse_table_ckson;
        param->usPsmAgeComfactor =
                        le16_to_cpu(profile->psm_age_comfactor);
-       param->ucEnableApplyAvfsCksoffVoltage =
-                       profile->enable_apply_avfs_cksoff_voltage;
 
        param->ulDispclk2GfxclkM1 =
                        le32_to_cpu(profile->dispclk2gfxclk_a);
-       param->usDispclk2GfxclkM2 =
+       param->ulDispclk2GfxclkM2 =
                        le16_to_cpu(profile->dispclk2gfxclk_b);
        param->ulDispclk2GfxclkB =
                        le32_to_cpu(profile->dispclk2gfxclk_c);
        param->ulDcefclk2GfxclkM1 =
                        le32_to_cpu(profile->dcefclk2gfxclk_a);
-       param->usDcefclk2GfxclkM2 =
+       param->ulDcefclk2GfxclkM2 =
                        le16_to_cpu(profile->dcefclk2gfxclk_b);
        param->ulDcefclk2GfxclkB =
                        le32_to_cpu(profile->dcefclk2gfxclk_c);
        param->ulPixelclk2GfxclkM1 =
                        le32_to_cpu(profile->pixclk2gfxclk_a);
-       param->usPixelclk2GfxclkM2 =
+       param->ulPixelclk2GfxclkM2 =
                        le16_to_cpu(profile->pixclk2gfxclk_b);
        param->ulPixelclk2GfxclkB =
                        le32_to_cpu(profile->pixclk2gfxclk_c);
        param->ulPhyclk2GfxclkM1 =
                        le32_to_cpu(profile->phyclk2gfxclk_a);
-       param->usPhyclk2GfxclkM2 =
+       param->ulPhyclk2GfxclkM2 =
                        le16_to_cpu(profile->phyclk2gfxclk_b);
        param->ulPhyclk2GfxclkB =
                        le32_to_cpu(profile->phyclk2gfxclk_c);
@@ -394,3 +387,31 @@ int pp_atomfwctrl_get_gpio_information(struct pp_hwmgr *hwmgr,
 
        return 0;
 }
+
+int pp_atomfwctrl_get_vbios_bootup_values(struct pp_hwmgr *hwmgr,
+                       struct pp_atomfwctrl_bios_boot_up_values *boot_values)
+{
+       struct atom_firmware_info_v3_1 *info = NULL;
+       uint16_t ix;
+
+       ix = GetIndexIntoMasterDataTable(firmwareinfo);
+       info = (struct atom_firmware_info_v3_1 *)
+               cgs_atom_get_data_table(hwmgr->device,
+                               ix, NULL, NULL, NULL);
+
+       if (!info) {
+               pr_info("Error retrieving BIOS firmwareinfo!");
+               return -EINVAL;
+       }
+
+       boot_values->ulRevision = info->firmware_revision;
+       boot_values->ulGfxClk   = info->bootup_sclk_in10khz;
+       boot_values->ulUClk     = info->bootup_mclk_in10khz;
+       boot_values->ulSocClk   = 0;
+       boot_values->usVddc     = info->bootup_vddc_mv;
+       boot_values->usVddci    = info->bootup_vddci_mv;
+       boot_values->usMvddc    = info->bootup_mvddc_mv;
+       boot_values->usVddGfx   = info->bootup_vddgfx_mv;
+
+       return 0;
+}
\ No newline at end of file
index 7efe9b96cb337eaba840532f8d908fe67e8febc7..43a6711e3c0648eb93a702d4ae96d3f5310d91e5 100644 (file)
@@ -69,7 +69,7 @@ struct pp_atomfwctrl_clock_dividers_soc15 {
 struct pp_atomfwctrl_avfs_parameters {
        uint32_t   ulMaxVddc;
        uint32_t   ulMinVddc;
-       uint8_t    ucMaxVidStep;
+
        uint32_t   ulMeanNsigmaAcontant0;
        uint32_t   ulMeanNsigmaAcontant1;
        uint32_t   ulMeanNsigmaAcontant2;
@@ -82,30 +82,30 @@ struct pp_atomfwctrl_avfs_parameters {
        uint32_t   ulGbVdroopTableCksonA0;
        uint32_t   ulGbVdroopTableCksonA1;
        uint32_t   ulGbVdroopTableCksonA2;
+
        uint32_t   ulGbFuseTableCksoffM1;
-       uint16_t   usGbFuseTableCksoffM2;
-       uint32_t   ulGbFuseTableCksoffB;\
+       uint32_t   ulGbFuseTableCksoffM2;
+       uint32_t   ulGbFuseTableCksoffB;
+
        uint32_t   ulGbFuseTableCksonM1;
-       uint16_t   usGbFuseTableCksonM2;
+       uint32_t   ulGbFuseTableCksonM2;
        uint32_t   ulGbFuseTableCksonB;
-       uint16_t   usMaxVoltage025mv;
-       uint8_t    ucEnableGbVdroopTableCksoff;
+
        uint8_t    ucEnableGbVdroopTableCkson;
-       uint8_t    ucEnableGbFuseTableCksoff;
        uint8_t    ucEnableGbFuseTableCkson;
        uint16_t   usPsmAgeComfactor;
-       uint8_t    ucEnableApplyAvfsCksoffVoltage;
+
        uint32_t   ulDispclk2GfxclkM1;
-       uint16_t   usDispclk2GfxclkM2;
+       uint32_t   ulDispclk2GfxclkM2;
        uint32_t   ulDispclk2GfxclkB;
        uint32_t   ulDcefclk2GfxclkM1;
-       uint16_t   usDcefclk2GfxclkM2;
+       uint32_t   ulDcefclk2GfxclkM2;
        uint32_t   ulDcefclk2GfxclkB;
        uint32_t   ulPixelclk2GfxclkM1;
-       uint16_t   usPixelclk2GfxclkM2;
+       uint32_t   ulPixelclk2GfxclkM2;
        uint32_t   ulPixelclk2GfxclkB;
        uint32_t   ulPhyclk2GfxclkM1;
-       uint16_t   usPhyclk2GfxclkM2;
+       uint32_t   ulPhyclk2GfxclkM2;
        uint32_t   ulPhyclk2GfxclkB;
 };
 
@@ -119,6 +119,18 @@ struct pp_atomfwctrl_gpio_parameters {
        uint8_t   ucFwCtfGpio;
        uint8_t   ucFwCtfPolarity;
 };
+
+struct pp_atomfwctrl_bios_boot_up_values {
+       uint32_t   ulRevision;
+       uint32_t   ulGfxClk;
+       uint32_t   ulUClk;
+       uint32_t   ulSocClk;
+       uint16_t   usVddc;
+       uint16_t   usVddci;
+       uint16_t   usMvddc;
+       uint16_t   usVddGfx;
+};
+
 int pp_atomfwctrl_get_gpu_pll_dividers_vega10(struct pp_hwmgr *hwmgr,
                uint32_t clock_type, uint32_t clock_value,
                struct pp_atomfwctrl_clock_dividers_soc15 *dividers);
@@ -136,5 +148,8 @@ int pp_atomfwctrl_get_avfs_information(struct pp_hwmgr *hwmgr,
 int pp_atomfwctrl_get_gpio_information(struct pp_hwmgr *hwmgr,
                struct pp_atomfwctrl_gpio_parameters *param);
 
+int pp_atomfwctrl_get_vbios_bootup_values(struct pp_hwmgr *hwmgr,
+                       struct pp_atomfwctrl_bios_boot_up_values *boot_values);
+
 #endif
 
index 8f663ab56a802bfea2db78338a9b19286e623e52..a74a3db3056c9c4a991e2b4525eb09de8a234a0a 100644 (file)
@@ -4334,26 +4334,31 @@ static int smu7_print_clock_levels(struct pp_hwmgr *hwmgr,
 
 static int smu7_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
 {
-       if (mode) {
-               /* stop auto-manage */
-               if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
-                               PHM_PlatformCaps_MicrocodeFanControl))
-                       smu7_fan_ctrl_stop_smc_fan_control(hwmgr);
-               smu7_fan_ctrl_set_static_mode(hwmgr, mode);
-       } else
-               /* restart auto-manage */
-               smu7_fan_ctrl_reset_fan_speed_to_default(hwmgr);
+       int result = 0;
 
-       return 0;
+       switch (mode) {
+       case AMD_FAN_CTRL_NONE:
+               result = smu7_fan_ctrl_set_fan_speed_percent(hwmgr, 100);
+               break;
+       case AMD_FAN_CTRL_MANUAL:
+               if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+                       PHM_PlatformCaps_MicrocodeFanControl))
+                       result = smu7_fan_ctrl_stop_smc_fan_control(hwmgr);
+               break;
+       case AMD_FAN_CTRL_AUTO:
+               result = smu7_fan_ctrl_set_static_mode(hwmgr, mode);
+               if (!result)
+                       result = smu7_fan_ctrl_start_smc_fan_control(hwmgr);
+               break;
+       default:
+               break;
+       }
+       return result;
 }
 
 static int smu7_get_fan_control_mode(struct pp_hwmgr *hwmgr)
 {
-       if (hwmgr->fan_ctrl_is_in_default_mode)
-               return hwmgr->fan_ctrl_default_mode;
-       else
-               return PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
-                               CG_FDO_CTRL2, FDO_PWM_MODE);
+       return hwmgr->fan_ctrl_enabled ? AMD_FAN_CTRL_AUTO : AMD_FAN_CTRL_MANUAL;
 }
 
 static int smu7_get_sclk_od(struct pp_hwmgr *hwmgr)
@@ -4522,32 +4527,6 @@ static int smu7_get_clock_by_type(struct pp_hwmgr *hwmgr, enum amd_pp_clock_type
        return 0;
 }
 
-static int smu7_request_firmware(struct pp_hwmgr *hwmgr)
-{
-       int ret;
-       struct cgs_firmware_info info = {0};
-
-       ret = cgs_get_firmware_info(hwmgr->device,
-                                   smu7_convert_fw_type_to_cgs(UCODE_ID_SMU),
-                                   &info);
-       if (ret || !info.kptr)
-               return -EINVAL;
-
-       return 0;
-}
-
-static int smu7_release_firmware(struct pp_hwmgr *hwmgr)
-{
-       int ret;
-
-       ret = cgs_rel_firmware(hwmgr->device,
-                              smu7_convert_fw_type_to_cgs(UCODE_ID_SMU));
-       if (ret)
-               return -EINVAL;
-
-       return 0;
-}
-
 static void smu7_find_min_clock_masks(struct pp_hwmgr *hwmgr,
                uint32_t *sclk_mask, uint32_t *mclk_mask,
                uint32_t min_sclk, uint32_t min_mclk)
@@ -4691,10 +4670,9 @@ static const struct pp_hwmgr_func smu7_hwmgr_funcs = {
        .get_clock_by_type = smu7_get_clock_by_type,
        .read_sensor = smu7_read_sensor,
        .dynamic_state_management_disable = smu7_disable_dpm_tasks,
-       .request_firmware = smu7_request_firmware,
-       .release_firmware = smu7_release_firmware,
        .set_power_profile_state = smu7_set_power_profile_state,
        .avfs_control = smu7_avfs_control,
+       .disable_smc_firmware_ctf = smu7_thermal_disable_alert,
 };
 
 uint8_t smu7_get_sleep_divider_id_from_clock(uint32_t clock,
index 436ca5ce82480d3957ff632f9976f13ab40bbdae..baddb569a8b8283881f8dc8f6d5d87e00927c8b2 100644 (file)
@@ -112,10 +112,9 @@ int smu7_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed)
 */
 int smu7_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
 {
-
        if (hwmgr->fan_ctrl_is_in_default_mode) {
                hwmgr->fan_ctrl_default_mode =
-                               PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device,     CGS_IND_REG__SMC,
+                               PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
                                                CG_FDO_CTRL2, FDO_PWM_MODE);
                hwmgr->tmin =
                                PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
@@ -149,7 +148,7 @@ int smu7_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr)
        return 0;
 }
 
-static int smu7_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr)
+int smu7_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr)
 {
        int result;
 
@@ -179,6 +178,7 @@ static int smu7_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr)
                                PPSMC_MSG_SetFanTemperatureTarget,
                                hwmgr->thermal_controller.
                                advanceFanControlParameters.ucTargetTemperature);
+       hwmgr->fan_ctrl_enabled = true;
 
        return result;
 }
@@ -186,6 +186,7 @@ static int smu7_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr)
 
 int smu7_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr)
 {
+       hwmgr->fan_ctrl_enabled = false;
        return smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_StopFanControl);
 }
 
@@ -280,7 +281,7 @@ int smu7_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed)
        PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC,
                                CG_TACH_STATUS, TACH_PERIOD, tach_period);
 
-       return smu7_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC);
+       return smu7_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC_RPM);
 }
 
 /**
index 2ed774db42c7b922f2b8ac77921a7bdb4b91ef7f..ba71b608fa752d5ac7b6ba4dd3d2b4fd7ce7cee9 100644 (file)
@@ -54,6 +54,6 @@ extern int smu7_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *spe
 extern int smu7_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr);
 extern int smu7_thermal_enable_alert(struct pp_hwmgr *hwmgr);
 extern int smu7_thermal_disable_alert(struct pp_hwmgr *hwmgr);
-
+extern int smu7_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr);
 #endif
 
index 83949550edac5e4ac481eb8432cc650b1cd6508f..ad30f5d3a10d5ea2a0118203ff66110a11b0583a 100644 (file)
@@ -111,6 +111,8 @@ static void vega10_set_default_registry_data(struct pp_hwmgr *hwmgr)
                        hwmgr->feature_mask & PP_SOCCLK_DPM_MASK ? false : true;
        data->registry_data.mclk_dpm_key_disabled =
                        hwmgr->feature_mask & PP_MCLK_DPM_MASK ? false : true;
+       data->registry_data.pcie_dpm_key_disabled =
+                       hwmgr->feature_mask & PP_PCIE_DPM_MASK ? false : true;
 
        data->registry_data.dcefclk_dpm_key_disabled =
                        hwmgr->feature_mask & PP_DCEFCLK_DPM_MASK ? false : true;
@@ -121,7 +123,9 @@ static void vega10_set_default_registry_data(struct pp_hwmgr *hwmgr)
                data->registry_data.enable_tdc_limit_feature = 1;
        }
 
-       data->registry_data.pcie_dpm_key_disabled = 1;
+       data->registry_data.clock_stretcher_support =
+                       hwmgr->feature_mask & PP_CLOCK_STRETCH_MASK ? false : true;
+
        data->registry_data.disable_water_mark = 0;
 
        data->registry_data.fan_control_support = 1;
@@ -1133,7 +1137,7 @@ static void vega10_setup_default_single_dpm_table(struct pp_hwmgr *hwmgr,
        int i;
 
        for (i = 0; i < dep_table->count; i++) {
-               if (i == 0 || dpm_table->dpm_levels[dpm_table->count - 1].value !=
+               if (i == 0 || dpm_table->dpm_levels[dpm_table->count - 1].value <=
                                dep_table->entries[i].clk) {
                        dpm_table->dpm_levels[dpm_table->count].value =
                                        dep_table->entries[i].clk;
@@ -1178,29 +1182,9 @@ static int vega10_setup_default_pcie_table(struct pp_hwmgr *hwmgr)
                else
                        pcie_table->lclk[i] =
                                        bios_pcie_table->entries[i].pcie_sclk;
-
-               pcie_table->count++;
        }
 
-       if (data->registry_data.pcieSpeedOverride)
-               pcie_table->pcie_gen[i] = data->registry_data.pcieSpeedOverride;
-       else
-               pcie_table->pcie_gen[i] =
-                       bios_pcie_table->entries[bios_pcie_table->count - 1].gen_speed;
-
-       if (data->registry_data.pcieLaneOverride)
-               pcie_table->pcie_lane[i] = data->registry_data.pcieLaneOverride;
-       else
-               pcie_table->pcie_lane[i] =
-                       bios_pcie_table->entries[bios_pcie_table->count - 1].lane_width;
-
-       if (data->registry_data.pcieClockOverride)
-               pcie_table->lclk[i] = data->registry_data.pcieClockOverride;
-       else
-               pcie_table->lclk[i] =
-                       bios_pcie_table->entries[bios_pcie_table->count - 1].pcie_sclk;
-
-       pcie_table->count++;
+       pcie_table->count = NUM_LINK_LEVELS;
 
        return 0;
 }
@@ -1290,7 +1274,7 @@ static int vega10_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)
        dpm_table = &(data->dpm_table.eclk_table);
        for (i = 0; i < dep_mm_table->count; i++) {
                if (i == 0 || dpm_table->dpm_levels
-                               [dpm_table->count - 1].value !=
+                               [dpm_table->count - 1].value <=
                                                dep_mm_table->entries[i].eclk) {
                        dpm_table->dpm_levels[dpm_table->count].value =
                                        dep_mm_table->entries[i].eclk;
@@ -1306,7 +1290,7 @@ static int vega10_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)
        dpm_table = &(data->dpm_table.vclk_table);
        for (i = 0; i < dep_mm_table->count; i++) {
                if (i == 0 || dpm_table->dpm_levels
-                               [dpm_table->count - 1].value !=
+                               [dpm_table->count - 1].value <=
                                                dep_mm_table->entries[i].vclk) {
                        dpm_table->dpm_levels[dpm_table->count].value =
                                        dep_mm_table->entries[i].vclk;
@@ -1320,7 +1304,7 @@ static int vega10_setup_default_dpm_tables(struct pp_hwmgr *hwmgr)
        dpm_table = &(data->dpm_table.dclk_table);
        for (i = 0; i < dep_mm_table->count; i++) {
                if (i == 0 || dpm_table->dpm_levels
-                               [dpm_table->count - 1].value !=
+                               [dpm_table->count - 1].value <=
                                                dep_mm_table->entries[i].dclk) {
                        dpm_table->dpm_levels[dpm_table->count].value =
                                        dep_mm_table->entries[i].dclk;
@@ -1432,9 +1416,7 @@ static int vega10_populate_ulv_state(struct pp_hwmgr *hwmgr)
                        (struct phm_ppt_v2_information *)(hwmgr->pptable);
 
        data->smc_state_table.pp_table.UlvOffsetVid =
-                       (uint8_t)(table_info->us_ulv_voltage_offset *
-                                       VOLTAGE_VID_OFFSET_SCALE2 /
-                                       VOLTAGE_VID_OFFSET_SCALE1);
+                       (uint8_t)table_info->us_ulv_voltage_offset;
 
        data->smc_state_table.pp_table.UlvSmnclkDid =
                        (uint8_t)(table_info->us_ulv_smnclk_did);
@@ -1553,7 +1535,11 @@ static int vega10_populate_single_gfx_level(struct pp_hwmgr *hwmgr,
        current_gfxclk_level->FbMult =
                        cpu_to_le32(dividers.ulPll_fb_mult);
        /* Spread FB Multiplier bit: bit 0:8 int, bit 31:16 frac */
-       current_gfxclk_level->SsOn = dividers.ucPll_ss_enable;
+       if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+                               PHM_PlatformCaps_EngineSpreadSpectrumSupport))
+               current_gfxclk_level->SsOn = dividers.ucPll_ss_enable;
+       else
+               current_gfxclk_level->SsOn = 0;
        current_gfxclk_level->SsFbMult =
                        cpu_to_le32(dividers.ulPll_ss_fbsmult);
        current_gfxclk_level->SsSlewFrac =
@@ -2044,10 +2030,10 @@ static int vega10_populate_clock_stretcher_table(struct pp_hwmgr *hwmgr)
                        table_info->vdd_dep_on_sclk;
        uint32_t i;
 
-       for (i = 0; dep_table->count; i++) {
+       for (i = 0; i < dep_table->count; i++) {
                pp_table->CksEnable[i] = dep_table->entries[i].cks_enable;
-               pp_table->CksVidOffset[i] = convert_to_vid(
-                               dep_table->entries[i].cks_voffset);
+               pp_table->CksVidOffset[i] = (uint8_t)(dep_table->entries[i].cks_voffset
+                               * VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1);
        }
 
        return 0;
@@ -2073,66 +2059,70 @@ static int vega10_populate_avfs_parameters(struct pp_hwmgr *hwmgr)
                result = pp_atomfwctrl_get_avfs_information(hwmgr, &avfs_params);
                if (!result) {
                        pp_table->MinVoltageVid = (uint8_t)
-                                       convert_to_vid((uint16_t)(avfs_params.ulMaxVddc));
-                       pp_table->MaxVoltageVid = (uint8_t)
                                        convert_to_vid((uint16_t)(avfs_params.ulMinVddc));
-                       pp_table->BtcGbVdroopTableCksOn.a0 =
-                                       cpu_to_le32(avfs_params.ulGbVdroopTableCksonA0);
-                       pp_table->BtcGbVdroopTableCksOn.a1 =
-                                       cpu_to_le32(avfs_params.ulGbVdroopTableCksonA1);
-                       pp_table->BtcGbVdroopTableCksOn.a2 =
-                                       cpu_to_le32(avfs_params.ulGbVdroopTableCksonA2);
+                       pp_table->MaxVoltageVid = (uint8_t)
+                                       convert_to_vid((uint16_t)(avfs_params.ulMaxVddc));
+
+                       pp_table->AConstant[0] = cpu_to_le32(avfs_params.ulMeanNsigmaAcontant0);
+                       pp_table->AConstant[1] = cpu_to_le32(avfs_params.ulMeanNsigmaAcontant1);
+                       pp_table->AConstant[2] = cpu_to_le32(avfs_params.ulMeanNsigmaAcontant2);
+                       pp_table->DC_tol_sigma = cpu_to_le16(avfs_params.usMeanNsigmaDcTolSigma);
+                       pp_table->Platform_mean = cpu_to_le16(avfs_params.usMeanNsigmaPlatformMean);
+                       pp_table->Platform_sigma = cpu_to_le16(avfs_params.usMeanNsigmaDcTolSigma);
+                       pp_table->PSM_Age_CompFactor = cpu_to_le16(avfs_params.usPsmAgeComfactor);
 
                        pp_table->BtcGbVdroopTableCksOff.a0 =
                                        cpu_to_le32(avfs_params.ulGbVdroopTableCksoffA0);
+                       pp_table->BtcGbVdroopTableCksOff.a0_shift = 20;
                        pp_table->BtcGbVdroopTableCksOff.a1 =
                                        cpu_to_le32(avfs_params.ulGbVdroopTableCksoffA1);
+                       pp_table->BtcGbVdroopTableCksOff.a1_shift = 20;
                        pp_table->BtcGbVdroopTableCksOff.a2 =
                                        cpu_to_le32(avfs_params.ulGbVdroopTableCksoffA2);
+                       pp_table->BtcGbVdroopTableCksOff.a2_shift = 20;
+
+                       pp_table->OverrideBtcGbCksOn = avfs_params.ucEnableGbVdroopTableCkson;
+                       pp_table->BtcGbVdroopTableCksOn.a0 =
+                                       cpu_to_le32(avfs_params.ulGbVdroopTableCksonA0);
+                       pp_table->BtcGbVdroopTableCksOn.a0_shift = 20;
+                       pp_table->BtcGbVdroopTableCksOn.a1 =
+                                       cpu_to_le32(avfs_params.ulGbVdroopTableCksonA1);
+                       pp_table->BtcGbVdroopTableCksOn.a1_shift = 20;
+                       pp_table->BtcGbVdroopTableCksOn.a2 =
+                                       cpu_to_le32(avfs_params.ulGbVdroopTableCksonA2);
+                       pp_table->BtcGbVdroopTableCksOn.a2_shift = 20;
 
                        pp_table->AvfsGbCksOn.m1 =
                                        cpu_to_le32(avfs_params.ulGbFuseTableCksonM1);
                        pp_table->AvfsGbCksOn.m2 =
-                                       cpu_to_le16(avfs_params.usGbFuseTableCksonM2);
+                                       cpu_to_le16(avfs_params.ulGbFuseTableCksonM2);
                        pp_table->AvfsGbCksOn.b =
                                        cpu_to_le32(avfs_params.ulGbFuseTableCksonB);
                        pp_table->AvfsGbCksOn.m1_shift = 24;
                        pp_table->AvfsGbCksOn.m2_shift = 12;
+                       pp_table->AvfsGbCksOn.b_shift = 0;
 
+                       pp_table->OverrideAvfsGbCksOn =
+                                       avfs_params.ucEnableGbFuseTableCkson;
                        pp_table->AvfsGbCksOff.m1 =
                                        cpu_to_le32(avfs_params.ulGbFuseTableCksoffM1);
                        pp_table->AvfsGbCksOff.m2 =
-                                       cpu_to_le16(avfs_params.usGbFuseTableCksoffM2);
+                                       cpu_to_le16(avfs_params.ulGbFuseTableCksoffM2);
                        pp_table->AvfsGbCksOff.b =
                                        cpu_to_le32(avfs_params.ulGbFuseTableCksoffB);
                        pp_table->AvfsGbCksOff.m1_shift = 24;
                        pp_table->AvfsGbCksOff.m2_shift = 12;
-
-                       pp_table->AConstant[0] =
-                                       cpu_to_le32(avfs_params.ulMeanNsigmaAcontant0);
-                       pp_table->AConstant[1] =
-                                       cpu_to_le32(avfs_params.ulMeanNsigmaAcontant1);
-                       pp_table->AConstant[2] =
-                                       cpu_to_le32(avfs_params.ulMeanNsigmaAcontant2);
-                       pp_table->DC_tol_sigma =
-                                       cpu_to_le16(avfs_params.usMeanNsigmaDcTolSigma);
-                       pp_table->Platform_mean =
-                                       cpu_to_le16(avfs_params.usMeanNsigmaPlatformMean);
-                       pp_table->PSM_Age_CompFactor =
-                                       cpu_to_le16(avfs_params.usPsmAgeComfactor);
-                       pp_table->Platform_sigma =
-                                       cpu_to_le16(avfs_params.usMeanNsigmaDcTolSigma);
-
-                       for (i = 0; i < dep_table->count; i++)
-                               pp_table->StaticVoltageOffsetVid[i] = (uint8_t)
-                                               (dep_table->entries[i].sclk_offset *
+                       pp_table->AvfsGbCksOff.b_shift = 0;
+
+                       for (i = 0; i < dep_table->count; i++) {
+                               if (dep_table->entries[i].sclk_offset == 0)
+                                       pp_table->StaticVoltageOffsetVid[i] = 248;
+                               else
+                                       pp_table->StaticVoltageOffsetVid[i] =
+                                               (uint8_t)(dep_table->entries[i].sclk_offset *
                                                                VOLTAGE_VID_OFFSET_SCALE2 /
                                                                VOLTAGE_VID_OFFSET_SCALE1);
-
-                       pp_table->OverrideBtcGbCksOn =
-                                       avfs_params.ucEnableGbVdroopTableCkson;
-                       pp_table->OverrideAvfsGbCksOn =
-                                       avfs_params.ucEnableGbFuseTableCkson;
+                       }
 
                        if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
                                        data->disp_clk_quad_eqn_a) &&
@@ -2141,20 +2131,21 @@ static int vega10_populate_avfs_parameters(struct pp_hwmgr *hwmgr)
                                pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m1 =
                                                (int32_t)data->disp_clk_quad_eqn_a;
                                pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m2 =
-                                               (int16_t)data->disp_clk_quad_eqn_b;
+                                               (int32_t)data->disp_clk_quad_eqn_b;
                                pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].b =
                                                (int32_t)data->disp_clk_quad_eqn_c;
                        } else {
                                pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m1 =
                                                (int32_t)avfs_params.ulDispclk2GfxclkM1;
                                pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m2 =
-                                               (int16_t)avfs_params.usDispclk2GfxclkM2;
+                                               (int32_t)avfs_params.ulDispclk2GfxclkM2;
                                pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].b =
                                                (int32_t)avfs_params.ulDispclk2GfxclkB;
                        }
 
                        pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m1_shift = 24;
                        pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].m2_shift = 12;
+                       pp_table->DisplayClock2Gfxclk[DSPCLK_DISPCLK].b_shift = 12;
 
                        if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
                                        data->dcef_clk_quad_eqn_a) &&
@@ -2163,20 +2154,21 @@ static int vega10_populate_avfs_parameters(struct pp_hwmgr *hwmgr)
                                pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m1 =
                                                (int32_t)data->dcef_clk_quad_eqn_a;
                                pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m2 =
-                                               (int16_t)data->dcef_clk_quad_eqn_b;
+                                               (int32_t)data->dcef_clk_quad_eqn_b;
                                pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].b =
                                                (int32_t)data->dcef_clk_quad_eqn_c;
                        } else {
                                pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m1 =
                                                (int32_t)avfs_params.ulDcefclk2GfxclkM1;
                                pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m2 =
-                                               (int16_t)avfs_params.usDcefclk2GfxclkM2;
+                                               (int32_t)avfs_params.ulDcefclk2GfxclkM2;
                                pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].b =
                                                (int32_t)avfs_params.ulDcefclk2GfxclkB;
                        }
 
                        pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m1_shift = 24;
                        pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].m2_shift = 12;
+                       pp_table->DisplayClock2Gfxclk[DSPCLK_DCEFCLK].b_shift = 12;
 
                        if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
                                        data->pixel_clk_quad_eqn_a) &&
@@ -2185,21 +2177,21 @@ static int vega10_populate_avfs_parameters(struct pp_hwmgr *hwmgr)
                                pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m1 =
                                                (int32_t)data->pixel_clk_quad_eqn_a;
                                pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m2 =
-                                               (int16_t)data->pixel_clk_quad_eqn_b;
+                                               (int32_t)data->pixel_clk_quad_eqn_b;
                                pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].b =
                                                (int32_t)data->pixel_clk_quad_eqn_c;
                        } else {
                                pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m1 =
                                                (int32_t)avfs_params.ulPixelclk2GfxclkM1;
                                pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m2 =
-                                               (int16_t)avfs_params.usPixelclk2GfxclkM2;
+                                               (int32_t)avfs_params.ulPixelclk2GfxclkM2;
                                pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].b =
                                                (int32_t)avfs_params.ulPixelclk2GfxclkB;
                        }
 
                        pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m1_shift = 24;
                        pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].m2_shift = 12;
-
+                       pp_table->DisplayClock2Gfxclk[DSPCLK_PIXCLK].b_shift = 12;
                        if ((PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
                                        data->phy_clk_quad_eqn_a) &&
                                (PPREGKEY_VEGA10QUADRATICEQUATION_DFLT !=
@@ -2207,20 +2199,21 @@ static int vega10_populate_avfs_parameters(struct pp_hwmgr *hwmgr)
                                pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m1 =
                                                (int32_t)data->phy_clk_quad_eqn_a;
                                pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m2 =
-                                               (int16_t)data->phy_clk_quad_eqn_b;
+                                               (int32_t)data->phy_clk_quad_eqn_b;
                                pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].b =
                                                (int32_t)data->phy_clk_quad_eqn_c;
                        } else {
                                pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m1 =
                                                (int32_t)avfs_params.ulPhyclk2GfxclkM1;
                                pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m2 =
-                                               (int16_t)avfs_params.usPhyclk2GfxclkM2;
+                                               (int32_t)avfs_params.ulPhyclk2GfxclkM2;
                                pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].b =
                                                (int32_t)avfs_params.ulPhyclk2GfxclkB;
                        }
 
                        pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m1_shift = 24;
                        pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].m2_shift = 12;
+                       pp_table->DisplayClock2Gfxclk[DSPCLK_PHYCLK].b_shift = 12;
                } else {
                        data->smu_features[GNLD_AVFS].supported = false;
                }
@@ -2309,6 +2302,7 @@ static int vega10_init_smc_table(struct pp_hwmgr *hwmgr)
                        (struct phm_ppt_v2_information *)(hwmgr->pptable);
        PPTable_t *pp_table = &(data->smc_state_table.pp_table);
        struct pp_atomfwctrl_voltage_table voltage_table;
+       struct pp_atomfwctrl_bios_boot_up_values boot_up_values;
 
        result = vega10_setup_default_dpm_tables(hwmgr);
        PP_ASSERT_WITH_CODE(!result,
@@ -2331,6 +2325,7 @@ static int vega10_init_smc_table(struct pp_hwmgr *hwmgr)
                        (uint8_t)(table_info->uc_vce_dpm_voltage_mode);
        pp_table->Mp0DpmVoltageMode =
                        (uint8_t)(table_info->uc_mp0_dpm_voltage_mode);
+
        pp_table->DisplayDpmVoltageMode =
                        (uint8_t)(table_info->uc_dcef_dpm_voltage_mode);
 
@@ -2372,14 +2367,31 @@ static int vega10_init_smc_table(struct pp_hwmgr *hwmgr)
                        "Failed to initialize UVD Level!",
                        return result);
 
-       if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
-                       PHM_PlatformCaps_ClockStretcher)) {
+       if (data->registry_data.clock_stretcher_support) {
                result = vega10_populate_clock_stretcher_table(hwmgr);
                PP_ASSERT_WITH_CODE(!result,
                                "Failed to populate Clock Stretcher Table!",
                                return result);
        }
 
+       result = pp_atomfwctrl_get_vbios_bootup_values(hwmgr, &boot_up_values);
+       if (!result) {
+               data->vbios_boot_state.vddc     = boot_up_values.usVddc;
+               data->vbios_boot_state.vddci    = boot_up_values.usVddci;
+               data->vbios_boot_state.mvddc    = boot_up_values.usMvddc;
+               data->vbios_boot_state.gfx_clock = boot_up_values.ulGfxClk;
+               data->vbios_boot_state.mem_clock = boot_up_values.ulUClk;
+               data->vbios_boot_state.soc_clock = boot_up_values.ulSocClk;
+               if (0 != boot_up_values.usVddc) {
+                       smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+                                               PPSMC_MSG_SetFloorSocVoltage,
+                                               (boot_up_values.usVddc * 4));
+                       data->vbios_boot_state.bsoc_vddc_lock = true;
+               } else {
+                       data->vbios_boot_state.bsoc_vddc_lock = false;
+               }
+       }
+
        result = vega10_populate_avfs_parameters(hwmgr);
        PP_ASSERT_WITH_CODE(!result,
                        "Failed to initialize AVFS Parameters!",
@@ -2404,35 +2416,9 @@ static int vega10_init_smc_table(struct pp_hwmgr *hwmgr)
        PP_ASSERT_WITH_CODE(!result,
                        "Failed to upload PPtable!", return result);
 
-       if (data->smu_features[GNLD_AVFS].supported) {
-               uint32_t features_enabled;
-               result = vega10_get_smc_features(hwmgr->smumgr, &features_enabled);
-               PP_ASSERT_WITH_CODE(!result,
-                               "Failed to Retrieve Enabled Features!",
-                               return result);
-               if (!(features_enabled & (1 << FEATURE_AVFS_BIT))) {
-                       result = vega10_perform_btc(hwmgr->smumgr);
-                       PP_ASSERT_WITH_CODE(!result,
-                                       "Failed to Perform BTC!",
-                                       return result);
-                       result = vega10_avfs_enable(hwmgr, true);
-                       PP_ASSERT_WITH_CODE(!result,
-                                       "Attempt to enable AVFS feature Failed!",
-                                       return result);
-                       result = vega10_save_vft_table(hwmgr->smumgr,
-                                       (uint8_t *)&(data->smc_state_table.avfs_table));
-                       PP_ASSERT_WITH_CODE(!result,
-                                       "Attempt to save VFT table Failed!",
+       result = vega10_avfs_enable(hwmgr, true);
+       PP_ASSERT_WITH_CODE(!result, "Attempt to enable AVFS feature Failed!",
                                        return result);
-               } else {
-                       data->smu_features[GNLD_AVFS].enabled = true;
-                       result = vega10_restore_vft_table(hwmgr->smumgr,
-                                       (uint8_t *)&(data->smc_state_table.avfs_table));
-                       PP_ASSERT_WITH_CODE(!result,
-                                       "Attempt to restore VFT table Failed!",
-                                       return result;);
-               }
-       }
 
        return 0;
 }
@@ -2457,6 +2443,26 @@ static int vega10_enable_thermal_protection(struct pp_hwmgr *hwmgr)
        return 0;
 }
 
+static int vega10_disable_thermal_protection(struct pp_hwmgr *hwmgr)
+{
+       struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
+
+       if (data->smu_features[GNLD_THERMAL].supported) {
+               if (!data->smu_features[GNLD_THERMAL].enabled)
+                       pr_info("THERMAL Feature Already disabled!");
+
+               PP_ASSERT_WITH_CODE(
+                               !vega10_enable_smc_features(hwmgr->smumgr,
+                               false,
+                               data->smu_features[GNLD_THERMAL].smu_feature_bitmap),
+                               "disable THERMAL Feature Failed!",
+                               return -1);
+               data->smu_features[GNLD_THERMAL].enabled = false;
+       }
+
+       return 0;
+}
+
 static int vega10_enable_vrhot_feature(struct pp_hwmgr *hwmgr)
 {
        struct vega10_hwmgr *data =
@@ -2535,6 +2541,37 @@ static int vega10_enable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr)
        return 0;
 }
 
+static int vega10_stop_dpm(struct pp_hwmgr *hwmgr, uint32_t bitmap)
+{
+       struct vega10_hwmgr *data =
+                       (struct vega10_hwmgr *)(hwmgr->backend);
+       uint32_t i, feature_mask = 0;
+
+
+       if(data->smu_features[GNLD_LED_DISPLAY].supported == true){
+               PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
+                               true, data->smu_features[GNLD_LED_DISPLAY].smu_feature_bitmap),
+               "Attempt to Enable LED DPM feature Failed!", return -EINVAL);
+               data->smu_features[GNLD_LED_DISPLAY].enabled = true;
+       }
+
+       for (i = 0; i < GNLD_DPM_MAX; i++) {
+               if (data->smu_features[i].smu_feature_bitmap & bitmap) {
+                       if (data->smu_features[i].supported) {
+                               if (data->smu_features[i].enabled) {
+                                       feature_mask |= data->smu_features[i].
+                                                       smu_feature_bitmap;
+                                       data->smu_features[i].enabled = false;
+                               }
+                       }
+               }
+       }
+
+       vega10_enable_smc_features(hwmgr->smumgr, false, feature_mask);
+
+       return 0;
+}
+
 /**
  * @brief Tell SMC to enabled the supported DPMs.
  *
@@ -2576,6 +2613,12 @@ static int vega10_start_dpm(struct pp_hwmgr *hwmgr, uint32_t bitmap)
                data->smu_features[GNLD_LED_DISPLAY].enabled = true;
        }
 
+       if (data->vbios_boot_state.bsoc_vddc_lock) {
+               smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+                                               PPSMC_MSG_SetFloorSocVoltage, 0);
+               data->vbios_boot_state.bsoc_vddc_lock = false;
+       }
+
        if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
                        PHM_PlatformCaps_Falcon_QuickTransition)) {
                if (data->smu_features[GNLD_ACDC].supported) {
@@ -2602,8 +2645,6 @@ static int vega10_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
                        "Failed to configure telemetry!",
                        return tmp_result);
 
-       vega10_set_tools_address(hwmgr->smumgr);
-
        smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
                        PPSMC_MSG_NumOfDisplays, 0);
 
@@ -3880,32 +3921,36 @@ static int vega10_dpm_force_dpm_level(struct pp_hwmgr *hwmgr,
 
 static int vega10_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode)
 {
-       if (mode) {
-               /* stop auto-manage */
-               if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
-                               PHM_PlatformCaps_MicrocodeFanControl))
-                       vega10_fan_ctrl_stop_smc_fan_control(hwmgr);
-               vega10_fan_ctrl_set_static_mode(hwmgr, mode);
-       } else
-               /* restart auto-manage */
-               vega10_fan_ctrl_reset_fan_speed_to_default(hwmgr);
+       int result = 0;
 
-       return 0;
+       switch (mode) {
+       case AMD_FAN_CTRL_NONE:
+               result = vega10_fan_ctrl_set_fan_speed_percent(hwmgr, 100);
+               break;
+       case AMD_FAN_CTRL_MANUAL:
+               if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+                       PHM_PlatformCaps_MicrocodeFanControl))
+                       result = vega10_fan_ctrl_stop_smc_fan_control(hwmgr);
+               break;
+       case AMD_FAN_CTRL_AUTO:
+               result = vega10_fan_ctrl_set_static_mode(hwmgr, mode);
+               if (!result)
+                       result = vega10_fan_ctrl_start_smc_fan_control(hwmgr);
+               break;
+       default:
+               break;
+       }
+       return result;
 }
 
 static int vega10_get_fan_control_mode(struct pp_hwmgr *hwmgr)
 {
-       uint32_t reg;
+       struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
 
-       if (hwmgr->fan_ctrl_is_in_default_mode) {
-               return hwmgr->fan_ctrl_default_mode;
-       } else {
-               reg = soc15_get_register_offset(THM_HWID, 0,
-                       mmCG_FDO_CTRL2_BASE_IDX, mmCG_FDO_CTRL2);
-               return (cgs_read_register(hwmgr->device, reg) &
-                               CG_FDO_CTRL2__FDO_PWM_MODE_MASK) >>
-                               CG_FDO_CTRL2__FDO_PWM_MODE__SHIFT;
-       }
+       if (data->smu_features[GNLD_FAN_CONTROL].enabled == false)
+               return AMD_FAN_CTRL_MANUAL;
+       else
+               return AMD_FAN_CTRL_AUTO;
 }
 
 static int vega10_get_dal_power_level(struct pp_hwmgr *hwmgr,
@@ -4148,55 +4193,56 @@ static int vega10_force_clock_level(struct pp_hwmgr *hwmgr,
 
        switch (type) {
        case PP_SCLK:
-               if (data->registry_data.sclk_dpm_key_disabled)
-                       break;
-
                for (i = 0; i < 32; i++) {
                        if (mask & (1 << i))
                                break;
                }
+               data->smc_state_table.gfx_boot_level = i;
 
-               PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc_with_parameter(
-                               hwmgr->smumgr,
-                               PPSMC_MSG_SetSoftMinGfxclkByIndex,
-                               i),
-                               "Failed to set soft min sclk index!",
-                               return -1);
+               for (i = 31; i >= 0; i--) {
+                       if (mask & (1 << i))
+                               break;
+               }
+               data->smc_state_table.gfx_max_level = i;
+
+               PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr),
+                       "Failed to upload boot level to lowest!",
+                       return -EINVAL);
+
+               PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr),
+                       "Failed to upload dpm max level to highest!",
+                       return -EINVAL);
                break;
 
        case PP_MCLK:
-               if (data->registry_data.mclk_dpm_key_disabled)
-                       break;
-
                for (i = 0; i < 32; i++) {
                        if (mask & (1 << i))
                                break;
                }
 
-               PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc_with_parameter(
-                               hwmgr->smumgr,
-                               PPSMC_MSG_SetSoftMinUclkByIndex,
-                               i),
-                               "Failed to set soft min mclk index!",
-                               return -1);
-               break;
-
-       case PP_PCIE:
-               if (data->registry_data.pcie_dpm_key_disabled)
-                       break;
-
                for (i = 0; i < 32; i++) {
                        if (mask & (1 << i))
                                break;
                }
+               data->smc_state_table.mem_boot_level = i;
+
+               for (i = 31; i >= 0; i--) {
+                       if (mask & (1 << i))
+                               break;
+               }
+               data->smc_state_table.mem_max_level = i;
+
+               PP_ASSERT_WITH_CODE(!vega10_upload_dpm_bootup_level(hwmgr),
+                       "Failed to upload boot level to lowest!",
+                       return -EINVAL);
+
+               PP_ASSERT_WITH_CODE(!vega10_upload_dpm_max_level(hwmgr),
+                       "Failed to upload dpm max level to highest!",
+                       return -EINVAL);
 
-               PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc_with_parameter(
-                               hwmgr->smumgr,
-                               PPSMC_MSG_SetMinLinkDpmByIndex,
-                               i),
-                               "Failed to set min pcie index!",
-                               return -1);
                break;
+
+       case PP_PCIE:
        default:
                break;
        }
@@ -4395,11 +4441,55 @@ vega10_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmg
        return is_update_required;
 }
 
+static int vega10_disable_dpm_tasks(struct pp_hwmgr *hwmgr)
+{
+       int tmp_result, result = 0;
+
+       tmp_result = (vega10_is_dpm_running(hwmgr)) ? 0 : -1;
+       PP_ASSERT_WITH_CODE(tmp_result == 0,
+                       "DPM is not running right now, no need to disable DPM!",
+                       return 0);
+
+       if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+                       PHM_PlatformCaps_ThermalController))
+               vega10_disable_thermal_protection(hwmgr);
+
+       tmp_result = vega10_disable_power_containment(hwmgr);
+       PP_ASSERT_WITH_CODE((tmp_result == 0),
+                       "Failed to disable power containment!", result = tmp_result);
+
+       tmp_result = vega10_avfs_enable(hwmgr, false);
+       PP_ASSERT_WITH_CODE((tmp_result == 0),
+                       "Failed to disable AVFS!", result = tmp_result);
+
+       tmp_result = vega10_stop_dpm(hwmgr, SMC_DPM_FEATURES);
+       PP_ASSERT_WITH_CODE((tmp_result == 0),
+                       "Failed to stop DPM!", result = tmp_result);
+
+       return result;
+}
+
+static int vega10_power_off_asic(struct pp_hwmgr *hwmgr)
+{
+       struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
+       int result;
+
+       result = vega10_disable_dpm_tasks(hwmgr);
+       PP_ASSERT_WITH_CODE((0 == result),
+                       "[disable_dpm_tasks] Failed to disable DPM!",
+                       );
+       data->water_marks_bitmap &= ~(WaterMarksLoaded);
+
+       return result;
+}
+
+
 static const struct pp_hwmgr_func vega10_hwmgr_funcs = {
        .backend_init = vega10_hwmgr_backend_init,
        .backend_fini = vega10_hwmgr_backend_fini,
        .asic_setup = vega10_setup_asic_task,
        .dynamic_state_management_enable = vega10_enable_dpm_tasks,
+       .dynamic_state_management_disable = vega10_disable_dpm_tasks,
        .get_num_of_pp_table_entries =
                        vega10_get_number_of_powerplay_table_entries,
        .get_power_state_size = vega10_get_power_state_size,
@@ -4439,6 +4529,8 @@ static const struct pp_hwmgr_func vega10_hwmgr_funcs = {
        .check_states_equal = vega10_check_states_equal,
        .check_smc_update_required_for_display_configuration =
                        vega10_check_smc_update_required_for_display_configuration,
+       .power_off_asic = vega10_power_off_asic,
+       .disable_smc_firmware_ctf = vega10_thermal_disable_alert,
 };
 
 int vega10_hwmgr_init(struct pp_hwmgr *hwmgr)
index 83c67b9262ffb6dc96f08e93411c0f6b84bef035..1912e086c0cf9abd5a174e71f59074fd70fa615c 100644 (file)
@@ -177,8 +177,11 @@ struct vega10_dpmlevel_enable_mask {
 };
 
 struct vega10_vbios_boot_state {
+       bool        bsoc_vddc_lock;
        uint16_t    vddc;
        uint16_t    vddci;
+       uint16_t    mvddc;
+       uint16_t    vdd_gfx;
        uint32_t    gfx_clock;
        uint32_t    mem_clock;
        uint32_t    soc_clock;
index f1e244cd2370bee568db2b889a0b0030aad7576a..3f72268e99bb812d780ba1b9b4f52b2211ee3445 100644 (file)
@@ -48,8 +48,8 @@ void vega10_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr)
        table->Tliquid1Limit = cpu_to_le16(tdp_table->usTemperatureLimitLiquid1);
        table->Tliquid2Limit = cpu_to_le16(tdp_table->usTemperatureLimitLiquid2);
        table->TplxLimit = cpu_to_le16(tdp_table->usTemperatureLimitPlx);
-       table->LoadLineResistance = cpu_to_le16(
-                       hwmgr->platform_descriptor.LoadLineSlope);
+       table->LoadLineResistance =
+                       hwmgr->platform_descriptor.LoadLineSlope * 256;
        table->FitLimit = 0; /* Not used for Vega10 */
 
        table->Liquid1_I2C_address = tdp_table->ucLiquid1_I2C_address;
@@ -113,6 +113,29 @@ int vega10_enable_power_containment(struct pp_hwmgr *hwmgr)
        return result;
 }
 
+int vega10_disable_power_containment(struct pp_hwmgr *hwmgr)
+{
+       struct vega10_hwmgr *data =
+                       (struct vega10_hwmgr *)(hwmgr->backend);
+
+       if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps,
+                       PHM_PlatformCaps_PowerContainment)) {
+               if (data->smu_features[GNLD_PPT].supported)
+                       PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
+                                       false, data->smu_features[GNLD_PPT].smu_feature_bitmap),
+                                       "Attempt to disable PPT feature Failed!",
+                                       data->smu_features[GNLD_PPT].supported = false);
+
+               if (data->smu_features[GNLD_TDC].supported)
+                       PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
+                                       false, data->smu_features[GNLD_TDC].smu_feature_bitmap),
+                                       "Attempt to disable PPT feature Failed!",
+                                       data->smu_features[GNLD_TDC].supported = false);
+       }
+
+       return 0;
+}
+
 static int vega10_set_overdrive_target_percentage(struct pp_hwmgr *hwmgr,
                uint32_t adjust_percent)
 {
index d9662bf4a4b4f9d9bed26f204d504667df90f5e7..9ecaa27c0bb547e1c72707c4a562f19123b7ff76 100644 (file)
@@ -60,6 +60,7 @@ int vega10_enable_smc_cac(struct pp_hwmgr *hwmgr);
 int vega10_enable_power_containment(struct pp_hwmgr *hwmgr);
 int vega10_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n);
 int vega10_power_control_set_level(struct pp_hwmgr *hwmgr);
+int vega10_disable_power_containment(struct pp_hwmgr *hwmgr);
 
 #endif  /* _VEGA10_POWERTUNE_H_ */
 
index 8b55ae01132d6ffdc4c3a7c63779e7f97124a8ea..00e95511e19af1df99780646300288f5d6c2b7ed 100644 (file)
@@ -407,7 +407,7 @@ static int get_tdp_table(
                tdp_table->ucPlx_I2C_address = power_tune_table->ucPlx_I2C_address;
                tdp_table->ucPlx_I2C_Line = power_tune_table->ucPlx_I2C_LineSCL;
                tdp_table->ucPlx_I2C_LineSDA = power_tune_table->ucPlx_I2C_LineSDA;
-               hwmgr->platform_descriptor.LoadLineSlope = power_tune_table->usLoadLineResistance;
+               hwmgr->platform_descriptor.LoadLineSlope = le16_to_cpu(power_tune_table->usLoadLineResistance);
        } else {
                power_tune_table_v2 = (ATOM_Vega10_PowerTune_Table_V2 *)table;
                tdp_table->usMaximumPowerDeliveryLimit = le16_to_cpu(power_tune_table_v2->usSocketPowerLimit);
@@ -453,7 +453,7 @@ static int get_tdp_table(
                tdp_table->ucPlx_I2C_LineSDA = sda;
 
                hwmgr->platform_descriptor.LoadLineSlope =
-                                       power_tune_table_v2->usLoadLineResistance;
+                                       le16_to_cpu(power_tune_table_v2->usLoadLineResistance);
        }
 
        *info_tdp_table = tdp_table;
index f4d77b62e1ba8653e7508387d6465f37f03451ed..d5f53d04fa08c30a4053aa9fd07b04c795177e4e 100644 (file)
@@ -381,14 +381,10 @@ int vega10_thermal_get_temperature(struct pp_hwmgr *hwmgr)
 
        temp = cgs_read_register(hwmgr->device, reg);
 
-       temp = (temp & CG_MULT_THERMAL_STATUS__CTF_TEMP_MASK) >>
-                       CG_MULT_THERMAL_STATUS__CTF_TEMP__SHIFT;
+       temp = (temp & CG_MULT_THERMAL_STATUS__ASIC_MAX_TEMP_MASK) >>
+                       CG_MULT_THERMAL_STATUS__ASIC_MAX_TEMP__SHIFT;
 
-       /* Bit 9 means the reading is lower than the lowest usable value. */
-       if (temp & 0x200)
-               temp = VEGA10_THERMAL_MAXIMUM_TEMP_READING;
-       else
-               temp = temp & 0x1ff;
+       temp = temp & 0x1ff;
 
        temp *= PP_TEMPERATURE_UNITS_PER_CENTIGRADES;
 
@@ -424,23 +420,28 @@ static int vega10_thermal_set_temperature_range(struct pp_hwmgr *hwmgr,
                        mmTHM_THERMAL_INT_CTRL_BASE_IDX, mmTHM_THERMAL_INT_CTRL);
 
        val = cgs_read_register(hwmgr->device, reg);
-       val &= ~(THM_THERMAL_INT_CTRL__DIG_THERM_INTH_MASK);
-       val |= (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES) <<
-                       THM_THERMAL_INT_CTRL__DIG_THERM_INTH__SHIFT;
-       val &= ~(THM_THERMAL_INT_CTRL__DIG_THERM_INTL_MASK);
-       val |= (low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES) <<
-                       THM_THERMAL_INT_CTRL__DIG_THERM_INTL__SHIFT;
+
+       val &= (~THM_THERMAL_INT_CTRL__MAX_IH_CREDIT_MASK);
+       val |=  (5 << THM_THERMAL_INT_CTRL__MAX_IH_CREDIT__SHIFT);
+
+       val &= (~THM_THERMAL_INT_CTRL__THERM_IH_HW_ENA_MASK);
+       val |= (1 << THM_THERMAL_INT_CTRL__THERM_IH_HW_ENA__SHIFT);
+
+       val &= (~THM_THERMAL_INT_CTRL__DIG_THERM_INTH_MASK);
+       val |= ((high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)
+                       << THM_THERMAL_INT_CTRL__DIG_THERM_INTH__SHIFT);
+
+       val &= (~THM_THERMAL_INT_CTRL__DIG_THERM_INTL_MASK);
+       val |= ((low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)
+                       << THM_THERMAL_INT_CTRL__DIG_THERM_INTL__SHIFT);
+
+       val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK);
+
        cgs_write_register(hwmgr->device, reg, val);
 
        reg = soc15_get_register_offset(THM_HWID, 0,
                        mmTHM_TCON_HTC_BASE_IDX, mmTHM_TCON_HTC);
 
-       val = cgs_read_register(hwmgr->device, reg);
-       val &= ~(THM_TCON_HTC__HTC_TMP_LMT_MASK);
-       val |= (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES) <<
-                       THM_TCON_HTC__HTC_TMP_LMT__SHIFT;
-       cgs_write_register(hwmgr->device, reg, val);
-
        return 0;
 }
 
@@ -482,18 +483,28 @@ static int vega10_thermal_initialize(struct pp_hwmgr *hwmgr)
 static int vega10_thermal_enable_alert(struct pp_hwmgr *hwmgr)
 {
        struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
+       uint32_t val = 0;
+       uint32_t reg;
 
        if (data->smu_features[GNLD_FW_CTF].supported) {
                if (data->smu_features[GNLD_FW_CTF].enabled)
                        printk("[Thermal_EnableAlert] FW CTF Already Enabled!\n");
+
+               PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
+                               true,
+                               data->smu_features[GNLD_FW_CTF].smu_feature_bitmap),
+                               "Attempt to Enable FW CTF feature Failed!",
+                               return -1);
+               data->smu_features[GNLD_FW_CTF].enabled = true;
        }
 
-       PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
-                       true,
-                       data->smu_features[GNLD_FW_CTF].smu_feature_bitmap),
-                       "Attempt to Enable FW CTF feature Failed!",
-                       return -1);
-       data->smu_features[GNLD_FW_CTF].enabled = true;
+       val |= (1 << THM_THERMAL_INT_ENA__THERM_INTH_CLR__SHIFT);
+       val |= (1 << THM_THERMAL_INT_ENA__THERM_INTL_CLR__SHIFT);
+       val |= (1 << THM_THERMAL_INT_ENA__THERM_TRIGGER_CLR__SHIFT);
+
+       reg = soc15_get_register_offset(THM_HWID, 0, mmTHM_THERMAL_INT_ENA_BASE_IDX, mmTHM_THERMAL_INT_ENA);
+       cgs_write_register(hwmgr->device, reg, val);
+
        return 0;
 }
 
@@ -501,21 +512,27 @@ static int vega10_thermal_enable_alert(struct pp_hwmgr *hwmgr)
 * Disable thermal alerts on the RV770 thermal controller.
 * @param    hwmgr The address of the hardware manager.
 */
-static int vega10_thermal_disable_alert(struct pp_hwmgr *hwmgr)
+int vega10_thermal_disable_alert(struct pp_hwmgr *hwmgr)
 {
        struct vega10_hwmgr *data = (struct vega10_hwmgr *)(hwmgr->backend);
+       uint32_t reg;
 
        if (data->smu_features[GNLD_FW_CTF].supported) {
                if (!data->smu_features[GNLD_FW_CTF].enabled)
                        printk("[Thermal_EnableAlert] FW CTF Already disabled!\n");
-       }
 
-       PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
+
+               PP_ASSERT_WITH_CODE(!vega10_enable_smc_features(hwmgr->smumgr,
                        false,
                        data->smu_features[GNLD_FW_CTF].smu_feature_bitmap),
                        "Attempt to disable FW CTF feature Failed!",
                        return -1);
-       data->smu_features[GNLD_FW_CTF].enabled = false;
+               data->smu_features[GNLD_FW_CTF].enabled = false;
+       }
+
+       reg = soc15_get_register_offset(THM_HWID, 0, mmTHM_THERMAL_INT_ENA_BASE_IDX, mmTHM_THERMAL_INT_ENA);
+       cgs_write_register(hwmgr->device, reg, 0);
+
        return 0;
 }
 
@@ -561,6 +578,11 @@ int tf_vega10_thermal_setup_fan_table(struct pp_hwmgr *hwmgr,
                        advanceFanControlParameters.ulMinFanSCLKAcousticLimit);
        table->FanTargetTemperature = hwmgr->thermal_controller.
                        advanceFanControlParameters.usTMax;
+
+       smum_send_msg_to_smc_with_parameter(hwmgr->smumgr,
+                               PPSMC_MSG_SetFanTemperatureTarget,
+                               (uint32_t)table->FanTargetTemperature);
+
        table->FanPwmMin = hwmgr->thermal_controller.
                        advanceFanControlParameters.usPWMMin * 255 / 100;
        table->FanTargetGfxclk = (uint16_t)(hwmgr->thermal_controller.
index 8036808ec42123d307b0a58455057e2f178196a0..776f3a2effc0a67c7355b712252f6fec4010aba4 100644 (file)
@@ -78,6 +78,8 @@ extern int vega10_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr,
                uint32_t *speed);
 extern int vega10_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr);
 extern uint32_t smu7_get_xclk(struct pp_hwmgr *hwmgr);
+extern int vega10_thermal_disable_alert(struct pp_hwmgr *hwmgr);
+int vega10_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr);
 
 #endif
 
index 5345b50761f4e6c1a76b2e9fa1a8483d00372d55..a1ebe1014492058e07658b512ec4ac3bc6db2c1a 100644 (file)
@@ -431,6 +431,6 @@ extern int phm_display_clock_voltage_request(struct pp_hwmgr *hwmgr,
                struct pp_display_clock_request *clock);
 
 extern int phm_get_max_high_clocks(struct pp_hwmgr *hwmgr, struct amd_pp_simple_clock_info *clocks);
-
+extern int phm_disable_smc_firmware_ctf(struct pp_hwmgr *hwmgr);
 #endif /* _HARDWARE_MANAGER_H_ */
 
index 320225dd3328af69af146c2fc3c68a88135712c5..805b9df452a3dc828e138e01169b77e11c43297c 100644 (file)
@@ -368,11 +368,10 @@ struct pp_hwmgr_func {
        int (*get_mclk_od)(struct pp_hwmgr *hwmgr);
        int (*set_mclk_od)(struct pp_hwmgr *hwmgr, uint32_t value);
        int (*read_sensor)(struct pp_hwmgr *hwmgr, int idx, void *value, int *size);
-       int (*request_firmware)(struct pp_hwmgr *hwmgr);
-       int (*release_firmware)(struct pp_hwmgr *hwmgr);
        int (*set_power_profile_state)(struct pp_hwmgr *hwmgr,
                        struct amd_pp_profile *request);
        int (*avfs_control)(struct pp_hwmgr *hwmgr, bool enable);
+       int (*disable_smc_firmware_ctf)(struct pp_hwmgr *hwmgr);
 };
 
 struct pp_table_func {
@@ -765,6 +764,7 @@ struct pp_hwmgr {
        struct pp_thermal_controller_info thermal_controller;
        bool fan_ctrl_is_in_default_mode;
        uint32_t fan_ctrl_default_mode;
+       bool fan_ctrl_enabled;
        uint32_t tmin;
        struct phm_microcode_version_info microcode_version_info;
        uint32_t ps_size;
index 2037910adcb1208c6207966e556656541050bec8..d43f98a910b08e2475f48f0bea2f0c28c5923133 100644 (file)
@@ -30,7 +30,7 @@
  * SMU TEAM: Always increment the interface version if
  * any structure is changed in this file
  */
-#define SMU9_DRIVER_IF_VERSION 0xB
+#define SMU9_DRIVER_IF_VERSION 0xD
 
 #define PPTABLE_V10_SMU_VERSION 1
 
@@ -302,7 +302,17 @@ typedef struct {
 
   uint32_t     DpmLevelPowerDelta;
 
-  uint32_t     Reserved[19];
+  uint8_t      EnableBoostState;
+  uint8_t      AConstant_Shift;
+  uint8_t      DC_tol_sigma_Shift;
+  uint8_t      PSM_Age_CompFactor_Shift;
+
+  uint16_t     BoostStartTemperature;
+  uint16_t     BoostStopTemperature;
+
+  PllSetting_t GfxBoostState;
+
+  uint32_t     Reserved[14];
 
   /* Padding - ignore */
   uint32_t     MmHubPadding[7]; /* SMU internal use */
@@ -464,4 +474,8 @@ typedef struct {
 #define DB_PCC_SHIFT 26
 #define DB_EDC_SHIFT 27
 
+#define REMOVE_FMAX_MARGIN_BIT     0x0
+#define REMOVE_DCTOL_MARGIN_BIT    0x1
+#define REMOVE_PLATFORM_MARGIN_BIT 0x2
+
 #endif
index 90beef35bba2a3fed940a28771ea9cb0a2e390db..254974d3d371ccb5f7a44393dd3b3463e3e73540 100644 (file)
@@ -122,7 +122,10 @@ typedef uint16_t PPSMC_Result;
 #define PPSMC_MSG_SetFanMinPwm                   0x52
 #define PPSMC_MSG_ConfigureGfxDidt               0x55
 #define PPSMC_MSG_NumOfDisplays                  0x56
-#define PPSMC_Message_Count                      0x57
+#define PPSMC_MSG_ReadSerialNumTop32             0x58
+#define PPSMC_MSG_ReadSerialNumBottom32          0x59
+#define PPSMC_Message_Count                      0x5A
+
 
 typedef int PPSMC_Msg;
 
index 2685f02ab551eb84f542c0f9475e57062add5fd2..115f0e4b16032d89aa48b43f18d72905036bc59b 100644 (file)
@@ -74,18 +74,18 @@ static bool vega10_is_smc_ram_running(struct pp_smumgr *smumgr)
        return false;
 }
 
-/**
-* Check if SMC has responded to previous message.
-*
-* @param    smumgr  the address of the powerplay hardware manager.
-* @return   TRUE    SMC has responded, FALSE otherwise.
-*/
+/*
+ * Check if SMC has responded to previous message.
+ *
+ * @param    smumgr  the address of the powerplay hardware manager.
+ * @return   TRUE    SMC has responded, FALSE otherwise.
+ */
 static uint32_t vega10_wait_for_response(struct pp_smumgr *smumgr)
 {
        uint32_t reg;
 
        if (!vega10_is_smc_ram_running(smumgr))
-               return -1;
+               return -EINVAL;
 
        reg = soc15_get_register_offset(MP1_HWID, 0,
                        mmMP1_SMN_C2PMSG_90_BASE_IDX, mmMP1_SMN_C2PMSG_90);
@@ -96,20 +96,19 @@ static uint32_t vega10_wait_for_response(struct pp_smumgr *smumgr)
        return cgs_read_register(smumgr->device, reg);
 }
 
-/**
-* Send a message to the SMC, and do not wait for its response.
-*
-* @param    smumgr  the address of the powerplay hardware manager.
-* @param    msg the message to send.
-* @return   Always return 0.
-*/
+/*
+ * Send a message to the SMC, and do not wait for its response.
+ * @param    smumgr  the address of the powerplay hardware manager.
+ * @param    msg the message to send.
+ * @return   Always return 0.
+ */
 int vega10_send_msg_to_smc_without_waiting(struct pp_smumgr *smumgr,
                uint16_t msg)
 {
        uint32_t reg;
 
        if (!vega10_is_smc_ram_running(smumgr))
-               return -1;
+               return -EINVAL;
 
        reg = soc15_get_register_offset(MP1_HWID, 0,
                        mmMP1_SMN_C2PMSG_66_BASE_IDX, mmMP1_SMN_C2PMSG_66);
@@ -118,19 +117,18 @@ int vega10_send_msg_to_smc_without_waiting(struct pp_smumgr *smumgr,
        return 0;
 }
 
-/**
-* Send a message to the SMC, and wait for its response.
-*
-* @param    smumgr  the address of the powerplay hardware manager.
-* @param    msg the message to send.
-* @return   The response that came from the SMC.
-*/
+/*
+ * Send a message to the SMC, and wait for its response.
+ * @param    smumgr  the address of the powerplay hardware manager.
+ * @param    msg the message to send.
+ * @return   Always return 0.
+ */
 int vega10_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg)
 {
        uint32_t reg;
 
        if (!vega10_is_smc_ram_running(smumgr))
-               return -1;
+               return -EINVAL;
 
        vega10_wait_for_response(smumgr);
 
@@ -140,19 +138,18 @@ int vega10_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg)
 
        vega10_send_msg_to_smc_without_waiting(smumgr, msg);
 
-       PP_ASSERT_WITH_CODE(vega10_wait_for_response(smumgr) == 1,
-                       "Failed to send Message.",
-                       return -1);
+       if (vega10_wait_for_response(smumgr) != 1)
+               pr_err("Failed to send message: 0x%x\n", msg);
 
        return 0;
 }
 
-/**
+/*
  * Send a message to the SMC with parameter
  * @param    smumgr:  the address of the powerplay hardware manager.
  * @param    msg: the message to send.
  * @param    parameter: the parameter to send
- * @return   The response that came from the SMC.
+ * @return   Always return 0.
  */
 int vega10_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr,
                uint16_t msg, uint32_t parameter)
@@ -160,7 +157,7 @@ int vega10_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr,
        uint32_t reg;
 
        if (!vega10_is_smc_ram_running(smumgr))
-               return -1;
+               return -EINVAL;
 
        vega10_wait_for_response(smumgr);
 
@@ -174,22 +171,20 @@ int vega10_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr,
 
        vega10_send_msg_to_smc_without_waiting(smumgr, msg);
 
-       PP_ASSERT_WITH_CODE(vega10_wait_for_response(smumgr) == 1,
-                       "Failed to send Message.",
-                       return -1);
+       if (vega10_wait_for_response(smumgr) != 1)
+               pr_err("Failed to send message: 0x%x\n", msg);
 
        return 0;
 }
 
 
-/**
-* Send a message to the SMC with parameter, do not wait for response
-*
-* @param    smumgr:  the address of the powerplay hardware manager.
-* @param    msg: the message to send.
-* @param    parameter: the parameter to send
-* @return   The response that came from the SMC.
-*/
+/*
+ * Send a message to the SMC with parameter, do not wait for response
+ * @param    smumgr:  the address of the powerplay hardware manager.
+ * @param    msg: the message to send.
+ * @param    parameter: the parameter to send
+ * @return   The response that came from the SMC.
+ */
 int vega10_send_msg_to_smc_with_parameter_without_waiting(
                struct pp_smumgr *smumgr, uint16_t msg, uint32_t parameter)
 {
@@ -202,13 +197,12 @@ int vega10_send_msg_to_smc_with_parameter_without_waiting(
        return vega10_send_msg_to_smc_without_waiting(smumgr, msg);
 }
 
-/**
-* Retrieve an argument from SMC.
-*
-* @param    smumgr  the address of the powerplay hardware manager.
-* @param    arg     pointer to store the argument from SMC.
-* @return   Always return 0.
-*/
+/*
+ * Retrieve an argument from SMC.
+ * @param    smumgr  the address of the powerplay hardware manager.
+ * @param    arg     pointer to store the argument from SMC.
+ * @return   Always return 0.
+ */
 int vega10_read_arg_from_smc(struct pp_smumgr *smumgr, uint32_t *arg)
 {
        uint32_t reg;
@@ -221,11 +215,11 @@ int vega10_read_arg_from_smc(struct pp_smumgr *smumgr, uint32_t *arg)
        return 0;
 }
 
-/**
-* Copy table from SMC into driver FB
-* @param   smumgr    the address of the SMC manager
-* @param   table_id    the driver's table ID to copy from
-*/
+/*
+ * Copy table from SMC into driver FB
+ * @param   smumgr    the address of the SMC manager
+ * @param   table_id    the driver's table ID to copy from
+ */
 int vega10_copy_table_from_smc(struct pp_smumgr *smumgr,
                uint8_t *table, int16_t table_id)
 {
@@ -233,25 +227,25 @@ int vega10_copy_table_from_smc(struct pp_smumgr *smumgr,
                        (struct vega10_smumgr *)(smumgr->backend);
 
        PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
-                       "Invalid SMU Table ID!", return -1;);
+                       "Invalid SMU Table ID!", return -EINVAL);
        PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
-                       "Invalid SMU Table version!", return -1;);
+                       "Invalid SMU Table version!", return -EINVAL);
        PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
-                       "Invalid SMU Table Length!", return -1;);
+                       "Invalid SMU Table Length!", return -EINVAL);
        PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(smumgr,
                        PPSMC_MSG_SetDriverDramAddrHigh,
                        priv->smu_tables.entry[table_id].table_addr_high) == 0,
-                       "[CopyTableFromSMC] Attempt to Set Dram Addr High Failed!", return -1;);
+                       "[CopyTableFromSMC] Attempt to Set Dram Addr High Failed!", return -EINVAL);
        PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(smumgr,
                        PPSMC_MSG_SetDriverDramAddrLow,
                        priv->smu_tables.entry[table_id].table_addr_low) == 0,
                        "[CopyTableFromSMC] Attempt to Set Dram Addr Low Failed!",
-                       return -1;);
+                       return -EINVAL);
        PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(smumgr,
                        PPSMC_MSG_TransferTableSmu2Dram,
                        priv->smu_tables.entry[table_id].table_id) == 0,
                        "[CopyTableFromSMC] Attempt to Transfer Table From SMU Failed!",
-                       return -1;);
+                       return -EINVAL);
 
        memcpy(table, priv->smu_tables.entry[table_id].table,
                        priv->smu_tables.entry[table_id].size);
@@ -259,11 +253,11 @@ int vega10_copy_table_from_smc(struct pp_smumgr *smumgr,
        return 0;
 }
 
-/**
-* Copy table from Driver FB into SMC
-* @param   smumgr    the address of the SMC manager
-* @param   table_id    the table to copy from
-*/
+/*
+ * Copy table from Driver FB into SMC
+ * @param   smumgr    the address of the SMC manager
+ * @param   table_id    the table to copy from
+ */
 int vega10_copy_table_to_smc(struct pp_smumgr *smumgr,
                uint8_t *table, int16_t table_id)
 {
@@ -271,11 +265,11 @@ int vega10_copy_table_to_smc(struct pp_smumgr *smumgr,
                        (struct vega10_smumgr *)(smumgr->backend);
 
        PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
-                       "Invalid SMU Table ID!", return -1;);
+                       "Invalid SMU Table ID!", return -EINVAL);
        PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
-                       "Invalid SMU Table version!", return -1;);
+                       "Invalid SMU Table version!", return -EINVAL);
        PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
-                       "Invalid SMU Table Length!", return -1;);
+                       "Invalid SMU Table Length!", return -EINVAL);
 
        memcpy(priv->smu_tables.entry[table_id].table, table,
                        priv->smu_tables.entry[table_id].size);
@@ -284,27 +278,18 @@ int vega10_copy_table_to_smc(struct pp_smumgr *smumgr,
                        PPSMC_MSG_SetDriverDramAddrHigh,
                        priv->smu_tables.entry[table_id].table_addr_high) == 0,
                        "[CopyTableToSMC] Attempt to Set Dram Addr High Failed!",
-                       return -1;);
+                       return -EINVAL;);
        PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(smumgr,
                        PPSMC_MSG_SetDriverDramAddrLow,
                        priv->smu_tables.entry[table_id].table_addr_low) == 0,
                        "[CopyTableToSMC] Attempt to Set Dram Addr Low Failed!",
-                       return -1;);
+                       return -EINVAL);
        PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(smumgr,
                        PPSMC_MSG_TransferTableDram2Smu,
                        priv->smu_tables.entry[table_id].table_id) == 0,
                        "[CopyTableToSMC] Attempt to Transfer Table To SMU Failed!",
-                       return -1;);
-
-       return 0;
-}
+                       return -EINVAL);
 
-int vega10_perform_btc(struct pp_smumgr *smumgr)
-{
-       PP_ASSERT_WITH_CODE(!vega10_send_msg_to_smc_with_parameter(
-                       smumgr, PPSMC_MSG_RunBtc, 0),
-                       "Attempt to run DC BTC Failed!",
-                       return -1);
        return 0;
 }
 
@@ -312,7 +297,7 @@ int vega10_save_vft_table(struct pp_smumgr *smumgr, uint8_t *avfs_table)
 {
        PP_ASSERT_WITH_CODE(avfs_table,
                        "No access to SMC AVFS Table",
-                       return -1);
+                       return -EINVAL);
 
        return vega10_copy_table_from_smc(smumgr, avfs_table, AVFSTABLE);
 }
@@ -321,7 +306,7 @@ int vega10_restore_vft_table(struct pp_smumgr *smumgr, uint8_t *avfs_table)
 {
        PP_ASSERT_WITH_CODE(avfs_table,
                        "No access to SMC AVFS Table",
-                       return -1);
+                       return -EINVAL);
 
        return vega10_copy_table_to_smc(smumgr, avfs_table, AVFSTABLE);
 }
@@ -339,13 +324,16 @@ int vega10_enable_smc_features(struct pp_smumgr *smumgr,
 int vega10_get_smc_features(struct pp_smumgr *smumgr,
                uint32_t *features_enabled)
 {
+       if (features_enabled == NULL)
+               return -EINVAL;
+
        if (!vega10_send_msg_to_smc(smumgr,
                        PPSMC_MSG_GetEnabledSmuFeatures)) {
-               if (!vega10_read_arg_from_smc(smumgr, features_enabled))
-                       return 0;
+               vega10_read_arg_from_smc(smumgr, features_enabled);
+               return 0;
        }
 
-       return -1;
+       return -EINVAL;
 }
 
 int vega10_set_tools_address(struct pp_smumgr *smumgr)
@@ -372,25 +360,20 @@ static int vega10_verify_smc_interface(struct pp_smumgr *smumgr)
        PP_ASSERT_WITH_CODE(!vega10_send_msg_to_smc(smumgr,
                        PPSMC_MSG_GetDriverIfVersion),
                        "Attempt to get SMC IF Version Number Failed!",
-                       return -1);
-       PP_ASSERT_WITH_CODE(!vega10_read_arg_from_smc(smumgr,
-                       &smc_driver_if_version),
-                       "Attempt to read SMC IF Version Number Failed!",
-                       return -1);
-
-       if (smc_driver_if_version != SMU9_DRIVER_IF_VERSION)
-               return -1;
+                       return -EINVAL);
+       vega10_read_arg_from_smc(smumgr, &smc_driver_if_version);
+
+       if (smc_driver_if_version != SMU9_DRIVER_IF_VERSION) {
+               pr_err("Your firmware(0x%x) doesn't match \
+                       SMU9_DRIVER_IF_VERSION(0x%x). \
+                       Please update your firmware!\n",
+                       smc_driver_if_version, SMU9_DRIVER_IF_VERSION);
+               return -EINVAL;
+       }
 
        return 0;
 }
 
-/**
-* Write a 32bit value to the SMC SRAM space.
-* ALL PARAMETERS ARE IN HOST BYTE ORDER.
-* @param    smumgr  the address of the powerplay hardware manager.
-* @param    smc_addr the address in the SMC RAM to access.
-* @param    value to write to the SMC SRAM.
-*/
 static int vega10_smu_init(struct pp_smumgr *smumgr)
 {
        struct vega10_smumgr *priv;
@@ -427,7 +410,7 @@ static int vega10_smu_init(struct pp_smumgr *smumgr)
                        kfree(smumgr->backend);
                        cgs_free_gpu_mem(smumgr->device,
                        (cgs_handle_t)handle);
-                       return -1);
+                       return -EINVAL);
 
        priv->smu_tables.entry[PPTABLE].version = 0x01;
        priv->smu_tables.entry[PPTABLE].size = sizeof(PPTable_t);
@@ -455,7 +438,7 @@ static int vega10_smu_init(struct pp_smumgr *smumgr)
                        (cgs_handle_t)priv->smu_tables.entry[PPTABLE].handle);
                        cgs_free_gpu_mem(smumgr->device,
                        (cgs_handle_t)handle);
-                       return -1);
+                       return -EINVAL);
 
        priv->smu_tables.entry[WMTABLE].version = 0x01;
        priv->smu_tables.entry[WMTABLE].size = sizeof(Watermarks_t);
@@ -485,7 +468,7 @@ static int vega10_smu_init(struct pp_smumgr *smumgr)
                        (cgs_handle_t)priv->smu_tables.entry[WMTABLE].handle);
                        cgs_free_gpu_mem(smumgr->device,
                        (cgs_handle_t)handle);
-                       return -1);
+                       return -EINVAL);
 
        priv->smu_tables.entry[AVFSTABLE].version = 0x01;
        priv->smu_tables.entry[AVFSTABLE].size = sizeof(AvfsTable_t);
@@ -497,7 +480,7 @@ static int vega10_smu_init(struct pp_smumgr *smumgr)
        priv->smu_tables.entry[AVFSTABLE].table = kaddr;
        priv->smu_tables.entry[AVFSTABLE].handle = handle;
 
-       tools_size = 0;
+       tools_size = 0x19000;
        if (tools_size) {
                smu_allocate_memory(smumgr->device,
                                tools_size,
@@ -517,9 +500,44 @@ static int vega10_smu_init(struct pp_smumgr *smumgr)
                                        smu_lower_32_bits(mc_addr);
                        priv->smu_tables.entry[TOOLSTABLE].table = kaddr;
                        priv->smu_tables.entry[TOOLSTABLE].handle = handle;
+                       vega10_set_tools_address(smumgr);
                }
        }
 
+       /* allocate space for AVFS Fuse table */
+       smu_allocate_memory(smumgr->device,
+                       sizeof(AvfsFuseOverride_t),
+                       CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB,
+                       PAGE_SIZE,
+                       &mc_addr,
+                       &kaddr,
+                       &handle);
+
+       PP_ASSERT_WITH_CODE(kaddr,
+                       "[vega10_smu_init] Out of memory for avfs fuse table.",
+                       kfree(smumgr->backend);
+                       cgs_free_gpu_mem(smumgr->device,
+                       (cgs_handle_t)priv->smu_tables.entry[PPTABLE].handle);
+                       cgs_free_gpu_mem(smumgr->device,
+                       (cgs_handle_t)priv->smu_tables.entry[WMTABLE].handle);
+                       cgs_free_gpu_mem(smumgr->device,
+                       (cgs_handle_t)priv->smu_tables.entry[AVFSTABLE].handle);
+                       cgs_free_gpu_mem(smumgr->device,
+                       (cgs_handle_t)priv->smu_tables.entry[TOOLSTABLE].handle);
+                       cgs_free_gpu_mem(smumgr->device,
+                       (cgs_handle_t)handle);
+                       return -EINVAL);
+
+       priv->smu_tables.entry[AVFSFUSETABLE].version = 0x01;
+       priv->smu_tables.entry[AVFSFUSETABLE].size = sizeof(AvfsFuseOverride_t);
+       priv->smu_tables.entry[AVFSFUSETABLE].table_id = TABLE_AVFS_FUSE_OVERRIDE;
+       priv->smu_tables.entry[AVFSFUSETABLE].table_addr_high =
+                       smu_upper_32_bits(mc_addr);
+       priv->smu_tables.entry[AVFSFUSETABLE].table_addr_low =
+                       smu_lower_32_bits(mc_addr);
+       priv->smu_tables.entry[AVFSFUSETABLE].table = kaddr;
+       priv->smu_tables.entry[AVFSFUSETABLE].handle = handle;
+
        return 0;
 }
 
@@ -538,6 +556,8 @@ static int vega10_smu_fini(struct pp_smumgr *smumgr)
                if (priv->smu_tables.entry[TOOLSTABLE].table)
                        cgs_free_gpu_mem(smumgr->device,
                                        (cgs_handle_t)priv->smu_tables.entry[TOOLSTABLE].handle);
+               cgs_free_gpu_mem(smumgr->device,
+                               (cgs_handle_t)priv->smu_tables.entry[AVFSFUSETABLE].handle);
                kfree(smumgr->backend);
                smumgr->backend = NULL;
        }
@@ -548,7 +568,7 @@ static int vega10_start_smu(struct pp_smumgr *smumgr)
 {
        PP_ASSERT_WITH_CODE(!vega10_verify_smc_interface(smumgr),
                        "Failed to verify SMC interface!",
-                       return -1);
+                       return -EINVAL);
        return 0;
 }
 
index ad050212426df09eb11a3b2caf6775d5fb3064df..821425c1e4e0ba7b4e3c0af9f269ee0eb9be1bc0 100644 (file)
@@ -30,6 +30,7 @@ enum smu_table_id {
        WMTABLE,
        AVFSTABLE,
        TOOLSTABLE,
+       AVFSFUSETABLE,
        MAX_SMU_TABLE,
 };
 
@@ -62,7 +63,6 @@ int vega10_get_smc_features(struct pp_smumgr *smumgr,
                uint32_t *features_enabled);
 int vega10_save_vft_table(struct pp_smumgr *smumgr, uint8_t *avfs_table);
 int vega10_restore_vft_table(struct pp_smumgr *smumgr, uint8_t *avfs_table);
-int vega10_perform_btc(struct pp_smumgr *smumgr);
 
 int vega10_set_tools_address(struct pp_smumgr *smumgr);
 
index acd882a188bc84f5694ce94b095a5d2160e89ae2..fea96a765cf14698eaa2b9e6f30ea7a707245ea7 100644 (file)
@@ -236,6 +236,23 @@ static void amd_sched_entity_clear_dep(struct dma_fence *f, struct dma_fence_cb
        dma_fence_put(f);
 }
 
+bool amd_sched_dependency_optimized(struct dma_fence* fence,
+                                   struct amd_sched_entity *entity)
+{
+       struct amd_gpu_scheduler *sched = entity->sched;
+       struct amd_sched_fence *s_fence;
+
+       if (!fence || dma_fence_is_signaled(fence))
+               return false;
+       if (fence->context == entity->fence_context)
+               return true;
+       s_fence = to_amd_sched_fence(fence);
+       if (s_fence && s_fence->sched == sched)
+               return true;
+
+       return false;
+}
+
 static bool amd_sched_entity_add_dependency_cb(struct amd_sched_entity *entity)
 {
        struct amd_gpu_scheduler *sched = entity->sched;
@@ -387,7 +404,9 @@ void amd_sched_hw_job_reset(struct amd_gpu_scheduler *sched)
 
        spin_lock(&sched->job_list_lock);
        list_for_each_entry_reverse(s_job, &sched->ring_mirror_list, node) {
-               if (dma_fence_remove_callback(s_job->s_fence->parent, &s_job->s_fence->cb)) {
+               if (s_job->s_fence->parent &&
+                   dma_fence_remove_callback(s_job->s_fence->parent,
+                                             &s_job->s_fence->cb)) {
                        dma_fence_put(s_job->s_fence->parent);
                        s_job->s_fence->parent = NULL;
                }
@@ -460,9 +479,9 @@ int amd_sched_job_init(struct amd_sched_job *job,
        job->sched = sched;
        job->s_entity = entity;
        job->s_fence = amd_sched_fence_create(entity, owner);
-       job->id = atomic64_inc_return(&sched->job_id_count);
        if (!job->s_fence)
                return -ENOMEM;
+       job->id = atomic64_inc_return(&sched->job_id_count);
 
        INIT_WORK(&job->finish_work, amd_sched_job_finish);
        INIT_LIST_HEAD(&job->node);
index 0255c7f8a6d8350604ef54bde3561a725edaa930..924d4a5899e140cb61766f2e4fde9223d36c9850 100644 (file)
@@ -158,4 +158,6 @@ int amd_sched_job_init(struct amd_sched_job *job,
                       void *owner);
 void amd_sched_hw_job_reset(struct amd_gpu_scheduler *sched);
 void amd_sched_job_recovery(struct amd_gpu_scheduler *sched);
+bool amd_sched_dependency_optimized(struct dma_fence* fence,
+                                   struct amd_sched_entity *entity);
 #endif
index fad3d44e4642733c00dc024734cfe2340715142b..2e55599816aa5dfda1252a4affd0cee81d2c2ef2 100644 (file)
@@ -80,6 +80,8 @@
 #define EDID_QUIRK_FORCE_12BPC                 (1 << 9)
 /* Force 6bpc */
 #define EDID_QUIRK_FORCE_6BPC                  (1 << 10)
+/* Force 10bpc */
+#define EDID_QUIRK_FORCE_10BPC                 (1 << 11)
 
 struct detailed_mode_closure {
        struct drm_connector *connector;
@@ -122,6 +124,9 @@ static const struct edid_quirk {
        { "FCM", 13600, EDID_QUIRK_PREFER_LARGE_75 |
          EDID_QUIRK_DETAILED_IN_CM },
 
+       /* LGD panel of HP zBook 17 G2, eDP 10 bpc, but reports unknown bpc */
+       { "LGD", 764, EDID_QUIRK_FORCE_10BPC },
+
        /* LG Philips LCD LP154W01-A5 */
        { "LPL", 0, EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE },
        { "LPL", 0x2a00, EDID_QUIRK_DETAILED_USE_MAXIMUM_SIZE },
@@ -4244,6 +4249,9 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid)
        if (quirks & EDID_QUIRK_FORCE_8BPC)
                connector->display_info.bpc = 8;
 
+       if (quirks & EDID_QUIRK_FORCE_10BPC)
+               connector->display_info.bpc = 10;
+
        if (quirks & EDID_QUIRK_FORCE_12BPC)
                connector->display_info.bpc = 12;
 
index a0ea3241c65117ad056a67c8d3be17af317d80c5..1f178b878e42f01ce667067098cba6b93a6a22e3 100644 (file)
@@ -2446,7 +2446,7 @@ EXPORT_SYMBOL(drm_fb_helper_hotplug_event);
 int __init drm_fb_helper_modinit(void)
 {
 #if defined(CONFIG_FRAMEBUFFER_CONSOLE_MODULE) && !defined(CONFIG_EXPERT)
-       const char *name = "fbcon";
+       const char name[] = "fbcon";
        struct module *fbcon;
 
        mutex_lock(&module_mutex);
index d019b5e311cc5502e2d273525ea4144f5d0a796d..2d955d7d7b6d83ecdfae58e5bf26084f28a98999 100644 (file)
@@ -161,8 +161,8 @@ void etnaviv_core_dump(struct etnaviv_gpu *gpu)
        file_size += sizeof(*iter.hdr) * n_obj;
 
        /* Allocate the file in vmalloc memory, it's likely to be big */
-       iter.start = __vmalloc(file_size, GFP_KERNEL | __GFP_HIGHMEM |
-                              __GFP_NOWARN | __GFP_NORETRY, PAGE_KERNEL);
+       iter.start = __vmalloc(file_size, GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY,
+                              PAGE_KERNEL);
        if (!iter.start) {
                dev_warn(gpu->dev, "failed to allocate devcoredump file\n");
                return;
index 3f4f424196b2f6a0e230ac95f078a312472e47af..3949b0990916c5ea50b3ae442735c47b6a7b110f 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <drm/drmP.h>
 #include <linux/shmem_fs.h>
+#include <asm/set_memory.h>
 #include "psb_drv.h"
 #include "blitter.h"
 
index 5ee93ff5560890822cc71271c8226476bf56776c..1f9b35afefeebc9f66ad6e018afe479f4b8b0df0 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/pm_runtime.h>
 #include <acpi/video.h>
 #include <linux/module.h>
+#include <asm/set_memory.h>
 
 static struct drm_driver driver;
 static int psb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
index e091809a9a9ecb227b1194cf81e06b5f5fd061ae..b00edd3b8800d2d327f7f5f14c537c61e63922bf 100644 (file)
@@ -87,3 +87,16 @@ config DRM_I915_LOW_LEVEL_TRACEPOINTS
           and also analyze the request dependency resolving timeline.
 
           If in doubt, say "N".
+
+config DRM_I915_DEBUG_VBLANK_EVADE
+       bool "Enable extra debug warnings for vblank evasion"
+       depends on DRM_I915
+       default n
+       help
+         Choose this option to turn on extra debug warnings for the
+         vblank evade mechanism. This gives a warning every time the
+         the deadline allotted for the vblank evade critical section
+         is exceeded, even if there isn't an actual risk of missing
+         the vblank.
+
+         If in doubt, say "N".
index 532a577ff7a14e8f56613f605bb515833f7cc615..b6ac3df18b582534b118ab44aae1dbfe9f75186e 100644 (file)
@@ -4789,7 +4789,7 @@ i915_gem_load_init(struct drm_i915_private *dev_priv)
        dev_priv->requests = KMEM_CACHE(drm_i915_gem_request,
                                        SLAB_HWCACHE_ALIGN |
                                        SLAB_RECLAIM_ACCOUNT |
-                                       SLAB_DESTROY_BY_RCU);
+                                       SLAB_TYPESAFE_BY_RCU);
        if (!dev_priv->requests)
                goto err_vmas;
 
index 8bab4aea63e60846262977196b2516821497bd21..2aa6b97fd22f28436b984a6ae9a537f36ada545a 100644 (file)
@@ -31,6 +31,8 @@
 #include <linux/seq_file.h>
 #include <linux/stop_machine.h>
 
+#include <asm/set_memory.h>
+
 #include <drm/drmP.h>
 #include <drm/i915_drm.h>
 
index a211c53c813f75d9e38274643bfc73031eeafa5a..129c58bb4805509ee708830458e766cfaa24237e 100644 (file)
@@ -521,7 +521,7 @@ static inline struct drm_i915_gem_request *
 __i915_gem_active_get_rcu(const struct i915_gem_active *active)
 {
        /* Performing a lockless retrieval of the active request is super
-        * tricky. SLAB_DESTROY_BY_RCU merely guarantees that the backing
+        * tricky. SLAB_TYPESAFE_BY_RCU merely guarantees that the backing
         * slab of request objects will not be freed whilst we hold the
         * RCU read lock. It does not guarantee that the request itself
         * will not be freed and then *reused*. Viz,
index f7d431427115a2f5e3c997afd2d628cd0c3ac2d0..8c87c717c7cda92c4256cf277828e594f96a0ad1 100644 (file)
@@ -198,12 +198,15 @@ void intel_pipe_update_end(struct intel_crtc *crtc, struct intel_flip_work *work
                          ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time),
                          crtc->debug.min_vbl, crtc->debug.max_vbl,
                          crtc->debug.scanline_start, scanline_end);
-       } else if (ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time) >
-                  VBLANK_EVASION_TIME_US)
+       }
+#ifdef CONFIG_DRM_I915_DEBUG_VBLANK_EVADE
+       else if (ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time) >
+                VBLANK_EVASION_TIME_US)
                DRM_WARN("Atomic update on pipe (%c) took %lld us, max time under evasion is %u us\n",
                         pipe_name(pipe),
                         ktime_us_delta(end_vbl_time, crtc->debug.start_vbl_time),
                         VBLANK_EVASION_TIME_US);
+#endif
 }
 
 static void
index 6a8258eacdcb614ff57ee933599aaf54b33d7ebd..9f24c5da3f8d3c62b32343e870564f73a740cfd2 100644 (file)
@@ -174,7 +174,7 @@ struct drm_i915_private *mock_gem_device(void)
        i915->requests = KMEM_CACHE(mock_request,
                                    SLAB_HWCACHE_ALIGN |
                                    SLAB_RECLAIM_ACCOUNT |
-                                   SLAB_DESTROY_BY_RCU);
+                                   SLAB_TYPESAFE_BY_RCU);
        if (!i915->requests)
                goto err_vmas;
 
index ca5397beb357d2a0635bbe385a19a99cc6989df8..2170534101cafda1e66ccdf0ee5262a62fdde7bf 100644 (file)
@@ -568,9 +568,7 @@ u_memcpya(uint64_t user, unsigned nmemb, unsigned size)
 
        size *= nmemb;
 
-       mem = kmalloc(size, GFP_KERNEL | __GFP_NOWARN);
-       if (!mem)
-               mem = vmalloc(size);
+       mem = kvmalloc(size, GFP_KERNEL);
        if (!mem)
                return ERR_PTR(-ENOMEM);
 
index 0e58537352fed2608fc915fc2a3201b6513f1f32..a7663249b3baf2df1c5c75d87d3b32109984ba97 100644 (file)
@@ -831,8 +831,7 @@ nv50_wndw_atomic_check_release(struct nv50_wndw *wndw,
 static int
 nv50_wndw_atomic_check_acquire(struct nv50_wndw *wndw,
                               struct nv50_wndw_atom *asyw,
-                              struct nv50_head_atom *asyh,
-                              u32 pflip_flags)
+                              struct nv50_head_atom *asyh)
 {
        struct nouveau_framebuffer *fb = nouveau_framebuffer(asyw->state.fb);
        struct nouveau_drm *drm = nouveau_drm(wndw->plane.dev);
@@ -848,7 +847,10 @@ nv50_wndw_atomic_check_acquire(struct nv50_wndw *wndw,
        asyw->image.h = fb->base.height;
        asyw->image.kind = (fb->nvbo->tile_flags & 0x0000ff00) >> 8;
 
-       asyw->interval = pflip_flags & DRM_MODE_PAGE_FLIP_ASYNC ? 0 : 1;
+       if (asyh->state.pageflip_flags & DRM_MODE_PAGE_FLIP_ASYNC)
+               asyw->interval = 0;
+       else
+               asyw->interval = 1;
 
        if (asyw->image.kind) {
                asyw->image.layout = 0;
@@ -887,7 +889,6 @@ nv50_wndw_atomic_check(struct drm_plane *plane, struct drm_plane_state *state)
        struct nv50_head_atom *harm = NULL, *asyh = NULL;
        bool varm = false, asyv = false, asym = false;
        int ret;
-       u32 pflip_flags = 0;
 
        NV_ATOMIC(drm, "%s atomic_check\n", plane->name);
        if (asyw->state.crtc) {
@@ -896,7 +897,6 @@ nv50_wndw_atomic_check(struct drm_plane *plane, struct drm_plane_state *state)
                        return PTR_ERR(asyh);
                asym = drm_atomic_crtc_needs_modeset(&asyh->state);
                asyv = asyh->state.active;
-               pflip_flags = asyh->state.pageflip_flags;
        }
 
        if (armw->state.crtc) {
@@ -912,12 +912,9 @@ nv50_wndw_atomic_check(struct drm_plane *plane, struct drm_plane_state *state)
                if (memcmp(&armw->point, &asyw->point, sizeof(asyw->point)))
                        asyw->set.point = true;
 
-               if (!varm || asym || armw->state.fb != asyw->state.fb) {
-                       ret = nv50_wndw_atomic_check_acquire(
-                                       wndw, asyw, asyh, pflip_flags);
-                       if (ret)
-                               return ret;
-               }
+               ret = nv50_wndw_atomic_check_acquire(wndw, asyw, asyh);
+               if (ret)
+                       return ret;
        } else
        if (varm) {
                nv50_wndw_atomic_check_release(wndw, asyw, harm);
@@ -1122,9 +1119,13 @@ static void
 nv50_curs_prepare(struct nv50_wndw *wndw, struct nv50_head_atom *asyh,
                  struct nv50_wndw_atom *asyw)
 {
-       asyh->curs.handle = nv50_disp(wndw->plane.dev)->mast.base.vram.handle;
-       asyh->curs.offset = asyw->image.offset;
-       asyh->set.curs = asyh->curs.visible;
+       u32 handle = nv50_disp(wndw->plane.dev)->mast.base.vram.handle;
+       u32 offset = asyw->image.offset;
+       if (asyh->curs.handle != handle || asyh->curs.offset != offset) {
+               asyh->curs.handle = handle;
+               asyh->curs.offset = offset;
+               asyh->set.curs = asyh->curs.visible;
+       }
 }
 
 static void
index 89d2e9da11c78aba5514acd1ec078b06475ae5f4..acd76fd4f6d85eab1fe6fea719a888f93725c575 100644 (file)
@@ -295,7 +295,7 @@ nvkm_object_ctor(const struct nvkm_object_func *func,
        INIT_LIST_HEAD(&object->head);
        INIT_LIST_HEAD(&object->tree);
        RB_CLEAR_NODE(&object->node);
-       WARN_ON(oclass->engine && !object->engine);
+       WARN_ON(IS_ERR(object->engine));
 }
 
 int
index c63975907c907da7afc433398d49c99137fca04d..4a9bd4f1cb931afdfaa71375f165f5dda79b53d7 100644 (file)
@@ -638,7 +638,6 @@ gf100_ram_ctor(const struct nvkm_ram_func *func, struct nvkm_fb *fb,
                        return ret;
        }
 
-       ram->ranks = (nvkm_rd32(device, 0x10f200) & 0x00000004) ? 2 : 1;
        return 0;
 }
 
index df949fa7d05d3a5dc188686c0c1eb10673514ff1..be691a7b972f38362009a39b5ff50d029531ba05 100644 (file)
@@ -146,7 +146,7 @@ nvkm_therm_update(struct nvkm_therm *therm, int mode)
                poll = false;
        }
 
-       if (list_empty(&therm->alarm.head) && poll)
+       if (poll)
                nvkm_timer_alarm(tmr, 1000000000ULL, &therm->alarm);
        spin_unlock_irqrestore(&therm->lock, flags);
 
index 91198d79393acb1c8c1a64715417bbfbceb07c26..e2feccec25f59a9717131f7eeb31b827415ff3c7 100644 (file)
@@ -83,7 +83,7 @@ nvkm_fan_update(struct nvkm_fan *fan, bool immediate, int target)
        spin_unlock_irqrestore(&fan->lock, flags);
 
        /* schedule next fan update, if not at target speed already */
-       if (list_empty(&fan->alarm.head) && target != duty) {
+       if (target != duty) {
                u16 bump_period = fan->bios.bump_period;
                u16 slow_down_period = fan->bios.slow_down_period;
                u64 delay;
index 59701b7a659752859fbca72171ba85454b0c673f..ff9fbe7950e5c6c9cef7336d2d88fc94bebe5771 100644 (file)
@@ -53,7 +53,7 @@ nvkm_fantog_update(struct nvkm_fantog *fan, int percent)
        duty = !nvkm_gpio_get(gpio, 0, DCB_GPIO_FAN, 0xff);
        nvkm_gpio_set(gpio, 0, DCB_GPIO_FAN, 0xff, duty);
 
-       if (list_empty(&fan->alarm.head) && percent != (duty * 100)) {
+       if (percent != (duty * 100)) {
                u64 next_change = (percent * fan->period_us) / 100;
                if (!duty)
                        next_change = fan->period_us - next_change;
index b9703c02d8ca7e6facca69c77bab9becf2a561f8..9a79e91fdfdc6dda7812455144044da8cc2d64f4 100644 (file)
@@ -185,7 +185,7 @@ alarm_timer_callback(struct nvkm_alarm *alarm)
        spin_unlock_irqrestore(&therm->sensor.alarm_program_lock, flags);
 
        /* schedule the next poll in one second */
-       if (therm->func->temp_get(therm) >= 0 && list_empty(&alarm->head))
+       if (therm->func->temp_get(therm) >= 0)
                nvkm_timer_alarm(tmr, 1000000000ULL, alarm);
 }
 
index 07dc82bfe346029aab3827f8d435769b433d1ced..f2a86eae0a0d624b31cb8ee9a65e6487705a6c1a 100644 (file)
@@ -36,23 +36,29 @@ nvkm_timer_alarm_trigger(struct nvkm_timer *tmr)
        unsigned long flags;
        LIST_HEAD(exec);
 
-       /* move any due alarms off the pending list */
+       /* Process pending alarms. */
        spin_lock_irqsave(&tmr->lock, flags);
        list_for_each_entry_safe(alarm, atemp, &tmr->alarms, head) {
-               if (alarm->timestamp <= nvkm_timer_read(tmr))
-                       list_move_tail(&alarm->head, &exec);
+               /* Have we hit the earliest alarm that hasn't gone off? */
+               if (alarm->timestamp > nvkm_timer_read(tmr)) {
+                       /* Schedule it.  If we didn't race, we're done. */
+                       tmr->func->alarm_init(tmr, alarm->timestamp);
+                       if (alarm->timestamp > nvkm_timer_read(tmr))
+                               break;
+               }
+
+               /* Move to completed list.  We'll drop the lock before
+                * executing the callback so it can reschedule itself.
+                */
+               list_move_tail(&alarm->head, &exec);
        }
 
-       /* reschedule interrupt for next alarm time */
-       if (!list_empty(&tmr->alarms)) {
-               alarm = list_first_entry(&tmr->alarms, typeof(*alarm), head);
-               tmr->func->alarm_init(tmr, alarm->timestamp);
-       } else {
+       /* Shut down interrupt if no more pending alarms. */
+       if (list_empty(&tmr->alarms))
                tmr->func->alarm_fini(tmr);
-       }
        spin_unlock_irqrestore(&tmr->lock, flags);
 
-       /* execute any pending alarm handlers */
+       /* Execute completed callbacks. */
        list_for_each_entry_safe(alarm, atemp, &exec, head) {
                list_del_init(&alarm->head);
                alarm->func(alarm);
@@ -65,24 +71,37 @@ nvkm_timer_alarm(struct nvkm_timer *tmr, u32 nsec, struct nvkm_alarm *alarm)
        struct nvkm_alarm *list;
        unsigned long flags;
 
-       alarm->timestamp = nvkm_timer_read(tmr) + nsec;
-
-       /* append new alarm to list, in soonest-alarm-first order */
+       /* Remove alarm from pending list.
+        *
+        * This both protects against the corruption of the list,
+        * and implements alarm rescheduling/cancellation.
+        */
        spin_lock_irqsave(&tmr->lock, flags);
-       if (!nsec) {
-               if (!list_empty(&alarm->head))
-                       list_del(&alarm->head);
-       } else {
+       list_del_init(&alarm->head);
+
+       if (nsec) {
+               /* Insert into pending list, ordered earliest to latest. */
+               alarm->timestamp = nvkm_timer_read(tmr) + nsec;
                list_for_each_entry(list, &tmr->alarms, head) {
                        if (list->timestamp > alarm->timestamp)
                                break;
                }
+
                list_add_tail(&alarm->head, &list->head);
+
+               /* Update HW if this is now the earliest alarm. */
+               list = list_first_entry(&tmr->alarms, typeof(*list), head);
+               if (list == alarm) {
+                       tmr->func->alarm_init(tmr, alarm->timestamp);
+                       /* This shouldn't happen if callers aren't stupid.
+                        *
+                        * Worst case scenario is that it'll take roughly
+                        * 4 seconds for the next alarm to trigger.
+                        */
+                       WARN_ON(alarm->timestamp <= nvkm_timer_read(tmr));
+               }
        }
        spin_unlock_irqrestore(&tmr->lock, flags);
-
-       /* process pending alarms */
-       nvkm_timer_alarm_trigger(tmr);
 }
 
 void
index 7b9ce87f061767ad25771074c3e88a34574b83a9..7f48249f41decea964d62790601b6be5d6d78f4c 100644 (file)
@@ -76,8 +76,8 @@ nv04_timer_intr(struct nvkm_timer *tmr)
        u32 stat = nvkm_rd32(device, NV04_PTIMER_INTR_0);
 
        if (stat & 0x00000001) {
-               nvkm_timer_alarm_trigger(tmr);
                nvkm_wr32(device, NV04_PTIMER_INTR_0, 0x00000001);
+               nvkm_timer_alarm_trigger(tmr);
                stat &= ~0x00000001;
        }
 
index 53710dd7d5dd55a020c813bc5b4c020c3ba55d23..ccebe0f8d2e1e3b4ec15d6170b788e2e8fc8b980 100644 (file)
@@ -9150,23 +9150,10 @@ static u32 dce8_latency_watermark(struct dce8_wm_params *wm)
        a.full = dfixed_const(available_bandwidth);
        b.full = dfixed_const(wm->num_heads);
        a.full = dfixed_div(a, b);
+       tmp = div_u64((u64) dmif_size * (u64) wm->disp_clk, mc_latency + 512);
+       tmp = min(dfixed_trunc(a), tmp);
 
-       b.full = dfixed_const(mc_latency + 512);
-       c.full = dfixed_const(wm->disp_clk);
-       b.full = dfixed_div(b, c);
-
-       c.full = dfixed_const(dmif_size);
-       b.full = dfixed_div(c, b);
-
-       tmp = min(dfixed_trunc(a), dfixed_trunc(b));
-
-       b.full = dfixed_const(1000);
-       c.full = dfixed_const(wm->disp_clk);
-       b.full = dfixed_div(c, b);
-       c.full = dfixed_const(wm->bytes_per_pixel);
-       b.full = dfixed_mul(b, c);
-
-       lb_fill_bw = min(tmp, dfixed_trunc(b));
+       lb_fill_bw = min(tmp, wm->disp_clk * wm->bytes_per_pixel / 1000);
 
        a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel);
        b.full = dfixed_const(1000);
@@ -9274,14 +9261,14 @@ static void dce8_program_watermarks(struct radeon_device *rdev,
 {
        struct drm_display_mode *mode = &radeon_crtc->base.mode;
        struct dce8_wm_params wm_low, wm_high;
-       u32 pixel_period;
+       u32 active_time;
        u32 line_time = 0;
        u32 latency_watermark_a = 0, latency_watermark_b = 0;
        u32 tmp, wm_mask;
 
        if (radeon_crtc->base.enabled && num_heads && mode) {
-               pixel_period = 1000000 / (u32)mode->clock;
-               line_time = min((u32)mode->crtc_htotal * pixel_period, (u32)65535);
+               active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock;
+               line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535);
 
                /* watermark for high clocks */
                if ((rdev->pm.pm_method == PM_METHOD_DPM) &&
@@ -9297,7 +9284,7 @@ static void dce8_program_watermarks(struct radeon_device *rdev,
 
                wm_high.disp_clk = mode->clock;
                wm_high.src_width = mode->crtc_hdisplay;
-               wm_high.active_time = mode->crtc_hdisplay * pixel_period;
+               wm_high.active_time = active_time;
                wm_high.blank_time = line_time - wm_high.active_time;
                wm_high.interlaced = false;
                if (mode->flags & DRM_MODE_FLAG_INTERLACE)
@@ -9337,7 +9324,7 @@ static void dce8_program_watermarks(struct radeon_device *rdev,
 
                wm_low.disp_clk = mode->clock;
                wm_low.src_width = mode->crtc_hdisplay;
-               wm_low.active_time = mode->crtc_hdisplay * pixel_period;
+               wm_low.active_time = active_time;
                wm_low.blank_time = line_time - wm_low.active_time;
                wm_low.interlaced = false;
                if (mode->flags & DRM_MODE_FLAG_INTERLACE)
index d1b1e0cc3c25b773f32ccc74c9401cf99b363c84..f130ec41ee4bbcad63516335dfaf17e24e782b60 100644 (file)
@@ -2188,13 +2188,7 @@ static u32 evergreen_latency_watermark(struct evergreen_wm_params *wm)
        b.full = dfixed_const(wm->num_heads);
        a.full = dfixed_div(a, b);
 
-       b.full = dfixed_const(1000);
-       c.full = dfixed_const(wm->disp_clk);
-       b.full = dfixed_div(c, b);
-       c.full = dfixed_const(wm->bytes_per_pixel);
-       b.full = dfixed_mul(b, c);
-
-       lb_fill_bw = min(dfixed_trunc(a), dfixed_trunc(b));
+       lb_fill_bw = min(dfixed_trunc(a), wm->disp_clk * wm->bytes_per_pixel / 1000);
 
        a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel);
        b.full = dfixed_const(1000);
@@ -2261,7 +2255,7 @@ static void evergreen_program_watermarks(struct radeon_device *rdev,
        struct drm_display_mode *mode = &radeon_crtc->base.mode;
        struct evergreen_wm_params wm_low, wm_high;
        u32 dram_channels;
-       u32 pixel_period;
+       u32 active_time;
        u32 line_time = 0;
        u32 latency_watermark_a = 0, latency_watermark_b = 0;
        u32 priority_a_mark = 0, priority_b_mark = 0;
@@ -2272,8 +2266,8 @@ static void evergreen_program_watermarks(struct radeon_device *rdev,
        fixed20_12 a, b, c;
 
        if (radeon_crtc->base.enabled && num_heads && mode) {
-               pixel_period = 1000000 / (u32)mode->clock;
-               line_time = min((u32)mode->crtc_htotal * pixel_period, (u32)65535);
+               active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock;
+               line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535);
                priority_a_cnt = 0;
                priority_b_cnt = 0;
                dram_channels = evergreen_get_number_of_dram_channels(rdev);
@@ -2291,7 +2285,7 @@ static void evergreen_program_watermarks(struct radeon_device *rdev,
 
                wm_high.disp_clk = mode->clock;
                wm_high.src_width = mode->crtc_hdisplay;
-               wm_high.active_time = mode->crtc_hdisplay * pixel_period;
+               wm_high.active_time = active_time;
                wm_high.blank_time = line_time - wm_high.active_time;
                wm_high.interlaced = false;
                if (mode->flags & DRM_MODE_FLAG_INTERLACE)
@@ -2318,7 +2312,7 @@ static void evergreen_program_watermarks(struct radeon_device *rdev,
 
                wm_low.disp_clk = mode->clock;
                wm_low.src_width = mode->crtc_hdisplay;
-               wm_low.active_time = mode->crtc_hdisplay * pixel_period;
+               wm_low.active_time = active_time;
                wm_low.blank_time = line_time - wm_low.active_time;
                wm_low.interlaced = false;
                if (mode->flags & DRM_MODE_FLAG_INTERLACE)
index 3eb0c4f9f7960d2fbcfbbd86de480f9fcc97f914..45e1d4e60759f55bbe4bb03faf629a442d7417f8 100644 (file)
@@ -203,6 +203,7 @@ static void r420_clock_resume(struct radeon_device *rdev)
 
 static void r420_cp_errata_init(struct radeon_device *rdev)
 {
+       int r;
        struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
 
        /* RV410 and R420 can lock up if CP DMA to host memory happens
@@ -212,7 +213,8 @@ static void r420_cp_errata_init(struct radeon_device *rdev)
         * of the CP init, apparently.
         */
        radeon_scratch_get(rdev, &rdev->config.r300.resync_scratch);
-       radeon_ring_lock(rdev, ring, 8);
+       r = radeon_ring_lock(rdev, ring, 8);
+       WARN_ON(r);
        radeon_ring_write(ring, PACKET0(R300_CP_RESYNC_ADDR, 1));
        radeon_ring_write(ring, rdev->config.r300.resync_scratch);
        radeon_ring_write(ring, 0xDEADBEEF);
@@ -221,12 +223,14 @@ static void r420_cp_errata_init(struct radeon_device *rdev)
 
 static void r420_cp_errata_fini(struct radeon_device *rdev)
 {
+       int r;
        struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
 
        /* Catch the RESYNC we dispatched all the way back,
         * at the very beginning of the CP init.
         */
-       radeon_ring_lock(rdev, ring, 8);
+       r = radeon_ring_lock(rdev, ring, 8);
+       WARN_ON(r);
        radeon_ring_write(ring, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
        radeon_ring_write(ring, R300_RB3D_DC_FINISH);
        radeon_ring_unlock_commit(rdev, ring, false);
index df6b58c085445f9b57640d52574421f11c371e8a..3ac671f6c8e1f05ff3dda913d915641540d15611 100644 (file)
@@ -117,11 +117,13 @@ static int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
                priority = (r->flags & RADEON_RELOC_PRIO_MASK) * 2
                           + !!r->write_domain;
 
-               /* the first reloc of an UVD job is the msg and that must be in
-                  VRAM, also but everything into VRAM on AGP cards and older
-                  IGP chips to avoid image corruptions */
+               /* The first reloc of an UVD job is the msg and that must be in
+                * VRAM, the second reloc is the DPB and for WMV that must be in
+                * VRAM as well. Also put everything into VRAM on AGP cards and older
+                * IGP chips to avoid image corruptions
+                */
                if (p->ring == R600_RING_TYPE_UVD_INDEX &&
-                   (i == 0 || pci_find_capability(p->rdev->ddev->pdev,
+                   (i <= 0 || pci_find_capability(p->rdev->ddev->pdev,
                                                   PCI_CAP_ID_AGP) ||
                     p->rdev->family == CHIP_RS780 ||
                     p->rdev->family == CHIP_RS880)) {
index c4777c8d0312a047790bcd309ac00fba2c8a02a4..0b3ec35515f3b940216df1d48fcd18b57a8779af 100644 (file)
@@ -27,6 +27,9 @@
  */
 #include <drm/drmP.h>
 #include <drm/radeon_drm.h>
+#ifdef CONFIG_X86
+#include <asm/set_memory.h>
+#endif
 #include "radeon.h"
 
 /*
index bec2ec056de43d30f27e0c9c218036f7d324372c..8b722297a05c7f5c3d958285664e3c37c398eb7a 100644 (file)
@@ -81,7 +81,7 @@ static void radeon_ttm_bo_destroy(struct ttm_buffer_object *tbo)
        list_del_init(&bo->list);
        mutex_unlock(&bo->rdev->gem.mutex);
        radeon_bo_clear_surface_reg(bo);
-       WARN_ON(!list_empty(&bo->va));
+       WARN_ON_ONCE(!list_empty(&bo->va));
        drm_gem_object_release(&bo->gem_base);
        kfree(bo);
 }
index 4fdc7bda7a7d5c85612b51c0630014e365d6a1e9..f5e9abfadb560879ad98e889987e031ac9f1379b 100644 (file)
@@ -298,7 +298,12 @@ static int radeon_test_create_and_emit_fence(struct radeon_device *rdev,
                        DRM_ERROR("Failed to lock ring A %d\n", ring->idx);
                        return r;
                }
-               radeon_fence_emit(rdev, fence, ring->idx);
+               r = radeon_fence_emit(rdev, fence, ring->idx);
+               if (r) {
+                       DRM_ERROR("Failed to emit fence\n");
+                       radeon_ring_unlock_undo(rdev, ring);
+                       return r;
+               }
                radeon_ring_unlock_commit(rdev, ring, false);
        }
        return 0;
index d34d1cf33895766c55a122adad041be62e42c70c..7431eb4a11b7f721fc8e44240c09742b02dc0446 100644 (file)
@@ -621,7 +621,7 @@ static int radeon_uvd_cs_reloc(struct radeon_cs_parser *p,
        }
 
        /* TODO: is this still necessary on NI+ ? */
-       if ((cmd == 0 || cmd == 0x3) &&
+       if ((cmd == 0 || cmd == 1 || cmd == 0x3) &&
            (start >> 28) != (p->rdev->uvd.gpu_addr >> 28)) {
                DRM_ERROR("msg/fb buffer %LX-%LX out of 256MB segment!\n",
                          start, end);
index 528e5a49a214202c31c190af813213eb6f609912..ceee87f029d9a3479d374c4fc305338377dee961 100644 (file)
@@ -2204,23 +2204,10 @@ static u32 dce6_latency_watermark(struct dce6_wm_params *wm)
        a.full = dfixed_const(available_bandwidth);
        b.full = dfixed_const(wm->num_heads);
        a.full = dfixed_div(a, b);
+       tmp = div_u64((u64) dmif_size * (u64) wm->disp_clk, mc_latency + 512);
+       tmp = min(dfixed_trunc(a), tmp);
 
-       b.full = dfixed_const(mc_latency + 512);
-       c.full = dfixed_const(wm->disp_clk);
-       b.full = dfixed_div(b, c);
-
-       c.full = dfixed_const(dmif_size);
-       b.full = dfixed_div(c, b);
-
-       tmp = min(dfixed_trunc(a), dfixed_trunc(b));
-
-       b.full = dfixed_const(1000);
-       c.full = dfixed_const(wm->disp_clk);
-       b.full = dfixed_div(c, b);
-       c.full = dfixed_const(wm->bytes_per_pixel);
-       b.full = dfixed_mul(b, c);
-
-       lb_fill_bw = min(tmp, dfixed_trunc(b));
+       lb_fill_bw = min(tmp, wm->disp_clk * wm->bytes_per_pixel / 1000);
 
        a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel);
        b.full = dfixed_const(1000);
@@ -2287,7 +2274,7 @@ static void dce6_program_watermarks(struct radeon_device *rdev,
        struct drm_display_mode *mode = &radeon_crtc->base.mode;
        struct dce6_wm_params wm_low, wm_high;
        u32 dram_channels;
-       u32 pixel_period;
+       u32 active_time;
        u32 line_time = 0;
        u32 latency_watermark_a = 0, latency_watermark_b = 0;
        u32 priority_a_mark = 0, priority_b_mark = 0;
@@ -2297,8 +2284,8 @@ static void dce6_program_watermarks(struct radeon_device *rdev,
        fixed20_12 a, b, c;
 
        if (radeon_crtc->base.enabled && num_heads && mode) {
-               pixel_period = 1000000 / (u32)mode->clock;
-               line_time = min((u32)mode->crtc_htotal * pixel_period, (u32)65535);
+               active_time = 1000000UL * (u32)mode->crtc_hdisplay / (u32)mode->clock;
+               line_time = min((u32) (1000000UL * (u32)mode->crtc_htotal / (u32)mode->clock), (u32)65535);
                priority_a_cnt = 0;
                priority_b_cnt = 0;
 
@@ -2320,7 +2307,7 @@ static void dce6_program_watermarks(struct radeon_device *rdev,
 
                wm_high.disp_clk = mode->clock;
                wm_high.src_width = mode->crtc_hdisplay;
-               wm_high.active_time = mode->crtc_hdisplay * pixel_period;
+               wm_high.active_time = active_time;
                wm_high.blank_time = line_time - wm_high.active_time;
                wm_high.interlaced = false;
                if (mode->flags & DRM_MODE_FLAG_INTERLACE)
@@ -2347,7 +2334,7 @@ static void dce6_program_watermarks(struct radeon_device *rdev,
 
                wm_low.disp_clk = mode->clock;
                wm_low.src_width = mode->crtc_hdisplay;
-               wm_low.active_time = mode->crtc_hdisplay * pixel_period;
+               wm_low.active_time = active_time;
                wm_low.blank_time = line_time - wm_low.active_time;
                wm_low.interlaced = false;
                if (mode->flags & DRM_MODE_FLAG_INTERLACE)
index e44626a2e6980bd390888119cb284e52214f644e..a6d7fcb99c0bd01228bfe5b47bd4c9c526b1a844 100644 (file)
@@ -1394,7 +1394,7 @@ EXPORT_SYMBOL(ttm_bo_evict_mm);
 int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type,
                        unsigned long p_size)
 {
-       int ret = -EINVAL;
+       int ret;
        struct ttm_mem_type_manager *man;
        unsigned i;
 
@@ -1412,7 +1412,6 @@ int ttm_bo_init_mm(struct ttm_bo_device *bdev, unsigned type,
                return ret;
        man->bdev = bdev;
 
-       ret = 0;
        if (type != TTM_PL_SYSTEM) {
                ret = (*man->func->init)(man, p_size);
                if (ret)
index a37de5db5731da0d46276bc396cabb73c63f6b03..eeddc1e48409c87b8f45c1c44d8bdef52802a53c 100644 (file)
@@ -51,6 +51,9 @@
 #if IS_ENABLED(CONFIG_AGP)
 #include <asm/agp.h>
 #endif
+#ifdef CONFIG_X86
+#include <asm/set_memory.h>
+#endif
 
 #define NUM_PAGES_TO_ALLOC             (PAGE_SIZE/sizeof(struct page *))
 #define SMALL_ALLOCATION               16
index cec4b4baa17987fcdca8b911af67b4183adfbc7d..90ddbdca93bdb8ddb65b97c31ac628e24f1bffeb 100644 (file)
@@ -53,6 +53,9 @@
 #if IS_ENABLED(CONFIG_AGP)
 #include <asm/agp.h>
 #endif
+#ifdef CONFIG_X86
+#include <asm/set_memory.h>
+#endif
 
 #define NUM_PAGES_TO_ALLOC             (PAGE_SIZE/sizeof(struct page *))
 #define SMALL_ALLOCATION               4
index aee3c00f836e723fed991843c22eea5ca0b974d0..5260179d788acea899ef4bbb17949ec97e07659e 100644 (file)
@@ -44,6 +44,9 @@
 #include <drm/ttm/ttm_bo_driver.h>
 #include <drm/ttm/ttm_placement.h>
 #include <drm/ttm/ttm_page_alloc.h>
+#ifdef CONFIG_X86
+#include <asm/set_memory.h>
+#endif
 
 /**
  * Allocates storage for pointers to the pages that back the ttm.
index 491866865c3397b4c2e73fdfc3444aac301f9ee4..1e1c90b30d4ad9b6cac056169d6f6eea7acede00 100644 (file)
@@ -175,8 +175,7 @@ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags)
        DRM_INFO("virgl 3d acceleration not supported by guest\n");
 #endif
 
-       ret = vgdev->vdev->config->find_vqs(vgdev->vdev, 2, vqs,
-                                           callbacks, names, NULL);
+       ret = virtio_find_vqs(vgdev->vdev, 2, vqs, callbacks, names, NULL);
        if (ret) {
                DRM_ERROR("failed to find virt queues\n");
                goto err_vqs;
index 3ac4c03ba77ba3e0c79fd4dc11c606c09c8b3cbf..c13a4fd86b3cbaf47f48e1d7a24fa2c845513743 100644 (file)
@@ -604,6 +604,13 @@ static int coretemp_cpu_online(unsigned int cpu)
        struct cpuinfo_x86 *c = &cpu_data(cpu);
        struct platform_data *pdata;
 
+       /*
+        * Don't execute this on resume as the offline callback did
+        * not get executed on suspend.
+        */
+       if (cpuhp_tasks_frozen)
+               return 0;
+
        /*
         * CPUID.06H.EAX[0] indicates whether the CPU has thermal
         * sensors. We check this bit only, all the early CPUs
@@ -654,6 +661,13 @@ static int coretemp_cpu_offline(unsigned int cpu)
        struct temp_data *tdata;
        int indx, target;
 
+       /*
+        * Don't execute this on suspend as the device remove locks
+        * up the machine.
+        */
+       if (cpuhp_tasks_frozen)
+               return 0;
+
        /* If the physical CPU device does not exist, just return */
        if (!pdev)
                return 0;
index e88afe1a435cc7fc9be0cb15cf7eee8bfcf8ff6e..dbbe31df74df17a4d55a02a30acb643937f0fd5a 100644 (file)
@@ -27,7 +27,9 @@
 #include <linux/io.h>
 #include <linux/dma-mapping.h>
 
-#include <asm/cacheflush.h>
+#ifdef CONFIG_X86
+#include <asm/set_memory.h>
+#endif
 
 #include "intel_th.h"
 #include "msu.h"
index 45c5c488302282876032e4fc7da289af00d1e1e1..6e6bf46bcb52312527fa34bd05c2c23bf15b8ec2 100644 (file)
 /* If force_addr is set to anything different from 0, we forcibly enable
    the device at the given address. */
 static u16 force_addr;
-module_param(force_addr, ushort, 0);
+module_param_hw(force_addr, ushort, ioport, 0);
 MODULE_PARM_DESC(force_addr,
                 "Initialize the base address of the i2c controller");
 
index 5a4eb6b6bd9295b0b0acfbd3ace526947d686647..6283b99d2b17f8ec3e22e4d4b0c08dad78d15d2b 100644 (file)
@@ -96,6 +96,7 @@ static int dw_i2c_acpi_configure(struct platform_device *pdev)
        struct dw_i2c_dev *dev = platform_get_drvdata(pdev);
        acpi_handle handle = ACPI_HANDLE(&pdev->dev);
        const struct acpi_device_id *id;
+       u32 ss_ht, fp_ht, hs_ht, fs_ht;
        struct acpi_device *adev;
        const char *uid;
 
@@ -107,23 +108,24 @@ static int dw_i2c_acpi_configure(struct platform_device *pdev)
         * Try to get SDA hold time and *CNT values from an ACPI method for
         * selected speed modes.
         */
+       dw_i2c_acpi_params(pdev, "SSCN", &dev->ss_hcnt, &dev->ss_lcnt, &ss_ht);
+       dw_i2c_acpi_params(pdev, "FPCN", &dev->fp_hcnt, &dev->fp_lcnt, &fp_ht);
+       dw_i2c_acpi_params(pdev, "HSCN", &dev->hs_hcnt, &dev->hs_lcnt, &hs_ht);
+       dw_i2c_acpi_params(pdev, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt, &fs_ht);
+
        switch (dev->clk_freq) {
        case 100000:
-               dw_i2c_acpi_params(pdev, "SSCN", &dev->ss_hcnt, &dev->ss_lcnt,
-                                  &dev->sda_hold_time);
+               dev->sda_hold_time = ss_ht;
                break;
        case 1000000:
-               dw_i2c_acpi_params(pdev, "FPCN", &dev->fp_hcnt, &dev->fp_lcnt,
-                                  &dev->sda_hold_time);
+               dev->sda_hold_time = fp_ht;
                break;
        case 3400000:
-               dw_i2c_acpi_params(pdev, "HSCN", &dev->hs_hcnt, &dev->hs_lcnt,
-                                  &dev->sda_hold_time);
+               dev->sda_hold_time = hs_ht;
                break;
        case 400000:
        default:
-               dw_i2c_acpi_params(pdev, "FMCN", &dev->fs_hcnt, &dev->fs_lcnt,
-                                  &dev->sda_hold_time);
+               dev->sda_hold_time = fs_ht;
                break;
        }
 
@@ -157,6 +159,8 @@ static const struct acpi_device_id dw_i2c_acpi_match[] = {
        { "AMDI0010", ACCESS_INTR_MASK },
        { "AMDI0510", 0 },
        { "APMC0D0F", 0 },
+       { "HISI02A1", 0 },
+       { "HISI02A2", 0 },
        { }
 };
 MODULE_DEVICE_TABLE(acpi, dw_i2c_acpi_match);
index 8af62fb3fe4140e5ed8e66000eaa48a237d8f095..5416003e0605d4d4abe2e268391eba58d3485f70 100644 (file)
@@ -323,9 +323,9 @@ MODULE_AUTHOR("Hans Berglund <hb@spacetec.no>");
 MODULE_DESCRIPTION("I2C-Bus adapter routines for PCF8584 ISA bus adapter");
 MODULE_LICENSE("GPL");
 
-module_param(base, int, 0);
-module_param(irq, int, 0);
+module_param_hw(base, int, ioport_or_iomem, 0);
+module_param_hw(irq, int, irq, 0);
 module_param(clock, int, 0);
 module_param(own, int, 0);
-module_param(mmapped, int, 0);
+module_param_hw(mmapped, int, other, 0);
 module_isa_driver(i2c_elektor_driver, 1);
index cf737ec8563b873042a519e6f1337e3f095e10dd..5c4db65c5019b7692c645dfaec9d391623355a81 100644 (file)
@@ -819,7 +819,6 @@ mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
                rc = -EINVAL;
                goto out;
        }
-       drv_data->irq = irq_of_parse_and_map(np, 0);
 
        drv_data->rstc = devm_reset_control_get_optional(dev, NULL);
        if (IS_ERR(drv_data->rstc)) {
@@ -902,10 +901,11 @@ mv64xxx_i2c_probe(struct platform_device *pd)
        if (!IS_ERR(drv_data->clk))
                clk_prepare_enable(drv_data->clk);
 
+       drv_data->irq = platform_get_irq(pd, 0);
+
        if (pdata) {
                drv_data->freq_m = pdata->freq_m;
                drv_data->freq_n = pdata->freq_n;
-               drv_data->irq = platform_get_irq(pd, 0);
                drv_data->adapter.timeout = msecs_to_jiffies(pdata->timeout);
                drv_data->offload_enabled = false;
                memcpy(&drv_data->reg_offsets, &mv64xxx_i2c_regs_mv64xxx, sizeof(drv_data->reg_offsets));
@@ -915,7 +915,7 @@ mv64xxx_i2c_probe(struct platform_device *pd)
                        goto exit_clk;
        }
        if (drv_data->irq < 0) {
-               rc = -ENXIO;
+               rc = drv_data->irq;
                goto exit_reset;
        }
 
index 1bcdd10b68b970687025075efcc9d60bfc4eff05..faa8fb8f2b8fb103afd902114026d4e10b9f4812 100644 (file)
 static struct platform_device *pdev;
 
 static u16 base;
-module_param(base, ushort, 0);
+module_param_hw(base, ushort, ioport, 0);
 MODULE_PARM_DESC(base, "Base I/O address");
 
 static int irq;
-module_param(irq, int, 0);
+module_param_hw(irq, int, irq, 0);
 MODULE_PARM_DESC(irq, "IRQ (optional)");
 
 /* ----- Low-level parallel port access ----------------------------------- */
index ba88f17f636cc6b14d65a7ae1419d8e9ced2bb77..946ac646de2ab6cbfb061b653c822a5914cdbefe 100644 (file)
@@ -197,9 +197,9 @@ MODULE_AUTHOR("Ian Campbell <icampbell@arcom.com>");
 MODULE_DESCRIPTION("ISA base PCA9564/PCA9665 driver");
 MODULE_LICENSE("GPL");
 
-module_param(base, ulong, 0);
+module_param_hw(base, ulong, ioport, 0);
 MODULE_PARM_DESC(base, "I/O base address");
-module_param(irq, int, 0);
+module_param_hw(irq, int, irq, 0);
 MODULE_PARM_DESC(irq, "IRQ");
 module_param(clock, int, 0);
 MODULE_PARM_DESC(clock, "Clock rate in hertz.\n\t\t"
index c21ca7bf2efe4f02d420ef53c679b321eceb8fe6..0ecdb47a23abcbf9691bf809b126d72d6c3a46f8 100644 (file)
@@ -106,7 +106,7 @@ MODULE_PARM_DESC(force, "Forcibly enable the PIIX4. DANGEROUS!");
 /* If force_addr is set to anything different from 0, we forcibly enable
    the PIIX4 at the given address. VERY DANGEROUS! */
 static int force_addr;
-module_param (force_addr, int, 0);
+module_param_hw(force_addr, int, ioport, 0);
 MODULE_PARM_DESC(force_addr,
                 "Forcibly enable the PIIX4 at the given address. "
                 "EXTREMELY DANGEROUS!");
index 7d58a40faf2dc8713d6cad4662c7adadf6a0a8a6..d543a9867ba44957c09e778e62e0f9f395fb7548 100644 (file)
@@ -119,7 +119,7 @@ static int blacklist[] = {
 /* If force_addr is set to anything different from 0, we forcibly enable
    the device at the given address. */
 static u16 force_addr;
-module_param(force_addr, ushort, 0);
+module_param_hw(force_addr, ushort, ioport, 0);
 MODULE_PARM_DESC(force_addr, "Initialize the base address of the i2c controller");
 
 static struct pci_driver sis5595_driver;
index 0ee2646f3b006bb7710cf9474ce2ccae366e4ef3..0dc45e12bb1d2f1ea4978b8b4b90fe346cfe9903 100644 (file)
@@ -94,7 +94,7 @@ MODULE_PARM_DESC(force, "Forcibly enable the SMBus. DANGEROUS!");
 /* If force_addr is set to anything different from 0, we forcibly enable
    the VT596 at the given address. VERY DANGEROUS! */
 static u16 force_addr;
-module_param(force_addr, ushort, 0);
+module_param_hw(force_addr, ushort, ioport, 0);
 MODULE_PARM_DESC(force_addr,
                 "Forcibly enable the SMBus at the given address. "
                 "EXTREMELY DANGEROUS!");
index dbe7e44c9321279bbcd7b3f8d2006dbe1365e0b7..6ba6c83ca8f1bc9ee0c22bbb99e004e6bb50a77f 100644 (file)
@@ -416,6 +416,7 @@ static int xgene_slimpro_i2c_probe(struct platform_device *pdev)
        adapter->class = I2C_CLASS_HWMON;
        adapter->dev.parent = &pdev->dev;
        adapter->dev.of_node = pdev->dev.of_node;
+       ACPI_COMPANION_SET(&adapter->dev, ACPI_COMPANION(&pdev->dev));
        i2c_set_adapdata(adapter, ctx);
        rc = i2c_add_adapter(adapter);
        if (rc) {
index 0a7e410b619529a44fa17706fe4ced3c9197c8ba..e0923bee8d1f1e6575cccc77d640f3d3be53924b 100644 (file)
@@ -42,7 +42,7 @@ MODULE_LICENSE("GPL");
 
 #define MAX_DEVICES 4
 static int base[MAX_DEVICES] = { 0x820, 0x840 };
-module_param_array(base, int, NULL, 0);
+module_param_hw_array(base, int, ioport, NULL, 0);
 MODULE_PARM_DESC(base, "Base addresses for the ACCESS.bus controllers");
 
 #define POLL_TIMEOUT   (HZ/5)
index 26f7237558bad75f8a111037e725a37b519d751e..9669ca4937b891063d4cd63e552344d818f5eefa 100644 (file)
@@ -395,18 +395,20 @@ int i2c_mux_add_adapter(struct i2c_mux_core *muxc,
        if (force_nr) {
                priv->adap.nr = force_nr;
                ret = i2c_add_numbered_adapter(&priv->adap);
-               dev_err(&parent->dev,
-                       "failed to add mux-adapter %u as bus %u (error=%d)\n",
-                       chan_id, force_nr, ret);
+               if (ret < 0) {
+                       dev_err(&parent->dev,
+                               "failed to add mux-adapter %u as bus %u (error=%d)\n",
+                               chan_id, force_nr, ret);
+                       goto err_free_priv;
+               }
        } else {
                ret = i2c_add_adapter(&priv->adap);
-               dev_err(&parent->dev,
-                       "failed to add mux-adapter %u (error=%d)\n",
-                       chan_id, ret);
-       }
-       if (ret < 0) {
-               kfree(priv);
-               return ret;
+               if (ret < 0) {
+                       dev_err(&parent->dev,
+                               "failed to add mux-adapter %u (error=%d)\n",
+                               chan_id, ret);
+                       goto err_free_priv;
+               }
        }
 
        WARN(sysfs_create_link(&priv->adap.dev.kobj, &muxc->dev->kobj,
@@ -422,6 +424,10 @@ int i2c_mux_add_adapter(struct i2c_mux_core *muxc,
 
        muxc->adapter[muxc->num_adapters++] = &priv->adap;
        return 0;
+
+err_free_priv:
+       kfree(priv);
+       return ret;
 }
 EXPORT_SYMBOL_GPL(i2c_mux_add_adapter);
 
index 406d5059072cbe41964105d752a42236e66f7c8d..d97031804de8b477e9e77da0b2b31bb1abdcc907 100644 (file)
@@ -196,20 +196,25 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
                res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
                mux->data.reg_size = resource_size(res);
                mux->data.reg = devm_ioremap_resource(&pdev->dev, res);
-               if (IS_ERR(mux->data.reg))
-                       return PTR_ERR(mux->data.reg);
+               if (IS_ERR(mux->data.reg)) {
+                       ret = PTR_ERR(mux->data.reg);
+                       goto err_put_parent;
+               }
        }
 
        if (mux->data.reg_size != 4 && mux->data.reg_size != 2 &&
            mux->data.reg_size != 1) {
                dev_err(&pdev->dev, "Invalid register size\n");
-               return -EINVAL;
+               ret = -EINVAL;
+               goto err_put_parent;
        }
 
        muxc = i2c_mux_alloc(parent, &pdev->dev, mux->data.n_values, 0, 0,
                             i2c_mux_reg_select, NULL);
-       if (!muxc)
-               return -ENOMEM;
+       if (!muxc) {
+               ret = -ENOMEM;
+               goto err_put_parent;
+       }
        muxc->priv = mux;
 
        platform_set_drvdata(pdev, muxc);
@@ -223,7 +228,7 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
 
                ret = i2c_mux_add_adapter(muxc, nr, mux->data.values[i], class);
                if (ret)
-                       goto add_adapter_failed;
+                       goto err_del_mux_adapters;
        }
 
        dev_dbg(&pdev->dev, "%d port mux on %s adapter\n",
@@ -231,8 +236,10 @@ static int i2c_mux_reg_probe(struct platform_device *pdev)
 
        return 0;
 
-add_adapter_failed:
+err_del_mux_adapters:
        i2c_mux_del_adapters(muxc);
+err_put_parent:
+       i2c_put_adapter(parent);
 
        return ret;
 }
index 45b3f41a43d4112a7c587c45f25b89b281bfcac3..323af721f8cb96e01393124b85c2342b6e9f8ff8 100644 (file)
@@ -107,7 +107,7 @@ void ide_complete_cmd(ide_drive_t *drive, struct ide_cmd *cmd, u8 stat, u8 err)
 
                if (cmd->tf_flags & IDE_TFLAG_DYN)
                        kfree(orig_cmd);
-               else
+               else if (cmd != orig_cmd)
                        memcpy(orig_cmd, cmd, sizeof(*cmd));
        }
 }
index a74ae8df4bb834464fee6f60ea0cc8c7441fdbc0..023562565d118d11dbcc936d0f2374645a52341d 100644 (file)
@@ -1183,9 +1183,7 @@ static void ide_init_port_data(ide_hwif_t *hwif, unsigned int index)
 
        spin_lock_init(&hwif->lock);
 
-       init_timer(&hwif->timer);
-       hwif->timer.function = &ide_timer_expiry;
-       hwif->timer.data = (unsigned long)hwif;
+       setup_timer(&hwif->timer, &ide_timer_expiry, (unsigned long)hwif);
 
        init_completion(&hwif->gendev_rel_comp);
 
index 5805b041dd0fc1a42c59a856663869e590e95a46..216d7ec88c0c7d55eca7ef198a53fb754da3c182 100644 (file)
@@ -1097,6 +1097,7 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = {
        ICPU(INTEL_FAM6_XEON_PHI_KNL,           idle_cpu_knl),
        ICPU(INTEL_FAM6_XEON_PHI_KNM,           idle_cpu_knl),
        ICPU(INTEL_FAM6_ATOM_GOLDMONT,          idle_cpu_bxt),
+       ICPU(INTEL_FAM6_ATOM_GEMINI_LAKE,       idle_cpu_bxt),
        ICPU(INTEL_FAM6_ATOM_DENVERTON,         idle_cpu_dnv),
        {}
 };
@@ -1309,6 +1310,7 @@ static void intel_idle_state_table_update(void)
                ivt_idle_state_table_update();
                break;
        case INTEL_FAM6_ATOM_GOLDMONT:
+       case INTEL_FAM6_ATOM_GEMINI_LAKE:
                bxt_idle_state_table_update();
                break;
        case INTEL_FAM6_SKYLAKE_DESKTOP:
index 2df84fa5e3fcd3d9fd89de1790979fbdd1633435..2da741d27540f8369f19534f872cc3a846c3d2b6 100644 (file)
@@ -49,7 +49,7 @@
 
 static unsigned int base[max_num_isa_dev(STX104_EXTENT)];
 static unsigned int num_stx104;
-module_param_array(base, uint, &num_stx104, 0);
+module_param_hw_array(base, uint, ioport, &num_stx104, 0);
 MODULE_PARM_DESC(base, "Apex Embedded Systems STX104 base addresses");
 
 /**
index a0464227a3a0dfb9153f8c285332587f8c2c395f..a8dffd9386153f0aa13d7eed8f3f80ab64d52938 100644 (file)
@@ -39,7 +39,7 @@
 
 static unsigned int base[max_num_isa_dev(CIO_DAC_EXTENT)];
 static unsigned int num_cio_dac;
-module_param_array(base, uint, &num_cio_dac, 0);
+module_param_hw_array(base, uint, ioport, &num_cio_dac, 0);
 MODULE_PARM_DESC(base, "Measurement Computing CIO-DAC base addresses");
 
 /**
index 0f6916d2d5499cc8ba02202ecfd47afd14ab93a8..5d6b1eeaa9a0a14c1088655cd5f049b5d3defa91 100644 (file)
@@ -1055,7 +1055,7 @@ static void handle_pio_err(struct hfi1_devdata *dd, u32 unused, u64 reg);
 static void handle_sdma_err(struct hfi1_devdata *dd, u32 unused, u64 reg);
 static void handle_egress_err(struct hfi1_devdata *dd, u32 unused, u64 reg);
 static void handle_txe_err(struct hfi1_devdata *dd, u32 unused, u64 reg);
-static void set_partition_keys(struct hfi1_pportdata *);
+static void set_partition_keys(struct hfi1_pportdata *ppd);
 static const char *link_state_name(u32 state);
 static const char *link_state_reason_name(struct hfi1_pportdata *ppd,
                                          u32 state);
@@ -1068,9 +1068,9 @@ static int wait_logical_linkstate(struct hfi1_pportdata *ppd, u32 state,
                                  int msecs);
 static void read_planned_down_reason_code(struct hfi1_devdata *dd, u8 *pdrrc);
 static void read_link_down_reason(struct hfi1_devdata *dd, u8 *ldr);
-static void handle_temp_err(struct hfi1_devdata *);
-static void dc_shutdown(struct hfi1_devdata *);
-static void dc_start(struct hfi1_devdata *);
+static void handle_temp_err(struct hfi1_devdata *dd);
+static void dc_shutdown(struct hfi1_devdata *dd);
+static void dc_start(struct hfi1_devdata *dd);
 static int qos_rmt_entries(struct hfi1_devdata *dd, unsigned int *mp,
                           unsigned int *np);
 static void clear_full_mgmt_pkey(struct hfi1_pportdata *ppd);
@@ -10233,7 +10233,7 @@ static int goto_offline(struct hfi1_pportdata *ppd, u8 rem_reason)
        if (pstate == PLS_OFFLINE) {
                do_transition = 0;      /* in right state */
                do_wait = 0;            /* ...no need to wait */
-       } else if ((pstate & 0xff) == PLS_OFFLINE) {
+       } else if ((pstate & 0xf0) == PLS_OFFLINE) {
                do_transition = 0;      /* in an offline transient state */
                do_wait = 1;            /* ...wait for it to settle */
        } else {
@@ -12662,7 +12662,7 @@ u8 hfi1_ibphys_portstate(struct hfi1_pportdata *ppd)
 #define SET_STATIC_RATE_CONTROL_SMASK(r) \
 (r |= SEND_CTXT_CHECK_ENABLE_DISALLOW_PBC_STATIC_RATE_CONTROL_SMASK)
 
-int hfi1_init_ctxt(struct send_context *sc)
+void hfi1_init_ctxt(struct send_context *sc)
 {
        if (sc) {
                struct hfi1_devdata *dd = sc->dd;
@@ -12679,7 +12679,6 @@ int hfi1_init_ctxt(struct send_context *sc)
                write_kctxt_csr(dd, sc->hw_context,
                                SEND_CTXT_CHECK_ENABLE, reg);
        }
-       return 0;
 }
 
 int hfi1_tempsense_rd(struct hfi1_devdata *dd, struct hfi1_temp *temp)
@@ -13841,14 +13840,14 @@ static void init_chip(struct hfi1_devdata *dd)
                dd_dev_info(dd, "Resetting CSRs with FLR\n");
 
                /* do the FLR, the DC reset will remain */
-               hfi1_pcie_flr(dd);
+               pcie_flr(dd->pcidev);
 
                /* restore command and BARs */
                restore_pci_variables(dd);
 
                if (is_ax(dd)) {
                        dd_dev_info(dd, "Resetting CSRs with FLR\n");
-                       hfi1_pcie_flr(dd);
+                       pcie_flr(dd->pcidev);
                        restore_pci_variables(dd);
                }
        } else {
@@ -14528,30 +14527,24 @@ done:
        return ret;
 }
 
-int hfi1_clear_ctxt_pkey(struct hfi1_devdata *dd, unsigned ctxt)
+int hfi1_clear_ctxt_pkey(struct hfi1_devdata *dd, struct hfi1_ctxtdata *ctxt)
 {
-       struct hfi1_ctxtdata *rcd;
-       unsigned sctxt;
-       int ret = 0;
+       u8 hw_ctxt;
        u64 reg;
 
-       if (ctxt < dd->num_rcv_contexts) {
-               rcd = dd->rcd[ctxt];
-       } else {
-               ret = -EINVAL;
-               goto done;
-       }
-       if (!rcd || !rcd->sc) {
-               ret = -EINVAL;
-               goto done;
-       }
-       sctxt = rcd->sc->hw_context;
-       reg = read_kctxt_csr(dd, sctxt, SEND_CTXT_CHECK_ENABLE);
+       if (!ctxt || !ctxt->sc)
+               return -EINVAL;
+
+       if (ctxt->ctxt >= dd->num_rcv_contexts)
+               return -EINVAL;
+
+       hw_ctxt = ctxt->sc->hw_context;
+       reg = read_kctxt_csr(dd, hw_ctxt, SEND_CTXT_CHECK_ENABLE);
        reg &= ~SEND_CTXT_CHECK_ENABLE_CHECK_PARTITION_KEY_SMASK;
-       write_kctxt_csr(dd, sctxt, SEND_CTXT_CHECK_ENABLE, reg);
-       write_kctxt_csr(dd, sctxt, SEND_CTXT_CHECK_PARTITION_KEY, 0);
-done:
-       return ret;
+       write_kctxt_csr(dd, hw_ctxt, SEND_CTXT_CHECK_ENABLE, reg);
+       write_kctxt_csr(dd, hw_ctxt, SEND_CTXT_CHECK_PARTITION_KEY, 0);
+
+       return 0;
 }
 
 /*
index b9dbf16d7703e7a20f5d0eec030efbcb73873827..cbe455d9ab8b65547849011b6e2e2ffd937ee0bb 100644 (file)
@@ -636,7 +636,8 @@ static inline void write_uctxt_csr(struct hfi1_devdata *dd, int ctxt,
        write_csr(dd, offset0 + (0x1000 * ctxt), value);
 }
 
-u64 create_pbc(struct hfi1_pportdata *ppd, u64, int, u32, u32);
+u64 create_pbc(struct hfi1_pportdata *ppd, u64 flags, int srate_mbs, u32 vl,
+              u32 dw_len);
 
 /* firmware.c */
 #define SBUS_MASTER_BROADCAST 0xfd
@@ -728,7 +729,8 @@ int bringup_serdes(struct hfi1_pportdata *ppd);
 void set_intr_state(struct hfi1_devdata *dd, u32 enable);
 void apply_link_downgrade_policy(struct hfi1_pportdata *ppd,
                                 int refresh_widths);
-void update_usrhead(struct hfi1_ctxtdata *, u32, u32, u32, u32, u32);
+void update_usrhead(struct hfi1_ctxtdata *rcd, u32 hd, u32 updegr, u32 egrhd,
+                   u32 intr_adjust, u32 npkts);
 int stop_drain_data_vls(struct hfi1_devdata *dd);
 int open_fill_data_vls(struct hfi1_devdata *dd);
 u32 ns_to_cclock(struct hfi1_devdata *dd, u32 ns);
@@ -1347,7 +1349,7 @@ void hfi1_start_cleanup(struct hfi1_devdata *dd);
 void hfi1_clear_tids(struct hfi1_ctxtdata *rcd);
 struct ib_header *hfi1_get_msgheader(
                                struct hfi1_devdata *dd, __le32 *rhf_addr);
-int hfi1_init_ctxt(struct send_context *sc);
+void hfi1_init_ctxt(struct send_context *sc);
 void hfi1_put_tid(struct hfi1_devdata *dd, u32 index,
                  u32 type, unsigned long pa, u16 order);
 void hfi1_quiet_serdes(struct hfi1_pportdata *ppd);
@@ -1360,7 +1362,7 @@ int hfi1_set_ib_cfg(struct hfi1_pportdata *ppd, int which, u32 val);
 int hfi1_set_ctxt_jkey(struct hfi1_devdata *dd, unsigned ctxt, u16 jkey);
 int hfi1_clear_ctxt_jkey(struct hfi1_devdata *dd, unsigned ctxt);
 int hfi1_set_ctxt_pkey(struct hfi1_devdata *dd, unsigned ctxt, u16 pkey);
-int hfi1_clear_ctxt_pkey(struct hfi1_devdata *dd, unsigned ctxt);
+int hfi1_clear_ctxt_pkey(struct hfi1_devdata *dd, struct hfi1_ctxtdata *ctxt);
 void hfi1_read_link_quality(struct hfi1_devdata *dd, u8 *link_quality);
 void hfi1_init_vnic_rsm(struct hfi1_devdata *dd);
 void hfi1_deinit_vnic_rsm(struct hfi1_devdata *dd);
index 5278954871755e0fa9afca7409942433361e87c1..a50870e455a30156a75c7527e4ec2b7646b8de9b 100644 (file)
@@ -85,8 +85,8 @@ module_param_named(cu, hfi1_cu, uint, S_IRUGO);
 MODULE_PARM_DESC(cu, "Credit return units");
 
 unsigned long hfi1_cap_mask = HFI1_CAP_MASK_DEFAULT;
-static int hfi1_caps_set(const char *, const struct kernel_param *);
-static int hfi1_caps_get(char *, const struct kernel_param *);
+static int hfi1_caps_set(const char *val, const struct kernel_param *kp);
+static int hfi1_caps_get(char *buffer, const struct kernel_param *kp);
 static const struct kernel_param_ops cap_ops = {
        .set = hfi1_caps_set,
        .get = hfi1_caps_get
@@ -210,42 +210,6 @@ int hfi1_count_active_units(void)
        return nunits_active;
 }
 
-/*
- * Return count of all units, optionally return in arguments
- * the number of usable (present) units, and the number of
- * ports that are up.
- */
-int hfi1_count_units(int *npresentp, int *nupp)
-{
-       int nunits = 0, npresent = 0, nup = 0;
-       struct hfi1_devdata *dd;
-       unsigned long flags;
-       int pidx;
-       struct hfi1_pportdata *ppd;
-
-       spin_lock_irqsave(&hfi1_devs_lock, flags);
-
-       list_for_each_entry(dd, &hfi1_dev_list, list) {
-               nunits++;
-               if ((dd->flags & HFI1_PRESENT) && dd->kregbase)
-                       npresent++;
-               for (pidx = 0; pidx < dd->num_pports; ++pidx) {
-                       ppd = dd->pport + pidx;
-                       if (ppd->lid && ppd->linkup)
-                               nup++;
-               }
-       }
-
-       spin_unlock_irqrestore(&hfi1_devs_lock, flags);
-
-       if (npresentp)
-               *npresentp = npresent;
-       if (nupp)
-               *nupp = nup;
-
-       return nunits;
-}
-
 /*
  * Get address of eager buffer from it's index (allocated in chunks, not
  * contiguous).
@@ -1325,7 +1289,7 @@ int hfi1_reset_device(int unit)
        if (dd->rcd)
                for (i = dd->first_dyn_alloc_ctxt;
                     i < dd->num_rcv_contexts; i++) {
-                       if (!dd->rcd[i] || !dd->rcd[i]->cnt)
+                       if (!dd->rcd[i])
                                continue;
                        spin_unlock_irqrestore(&dd->uctxt_lock, flags);
                        ret = -EBUSY;
index 3d9bce4bfcc7ac26c7b60d5a002881d3face49c9..3158128d57e8df4461256330db551a69b2d59b28 100644 (file)
@@ -49,6 +49,7 @@
 #include <linux/vmalloc.h>
 #include <linux/io.h>
 #include <linux/sched/mm.h>
+#include <linux/bitmap.h>
 
 #include <rdma/ib.h>
 
 /*
  * File operation functions
  */
-static int hfi1_file_open(struct inode *, struct file *);
-static int hfi1_file_close(struct inode *, struct file *);
-static ssize_t hfi1_write_iter(struct kiocb *, struct iov_iter *);
-static unsigned int hfi1_poll(struct file *, struct poll_table_struct *);
-static int hfi1_file_mmap(struct file *, struct vm_area_struct *);
-
-static u64 kvirt_to_phys(void *);
-static int assign_ctxt(struct file *, struct hfi1_user_info *);
-static int init_subctxts(struct hfi1_ctxtdata *, const struct hfi1_user_info *);
-static int user_init(struct file *);
-static int get_ctxt_info(struct file *, void __user *, __u32);
-static int get_base_info(struct file *, void __user *, __u32);
-static int setup_ctxt(struct file *);
-static int setup_subctxt(struct hfi1_ctxtdata *);
-static int get_user_context(struct file *, struct hfi1_user_info *, int);
-static int find_shared_ctxt(struct file *, const struct hfi1_user_info *);
-static int allocate_ctxt(struct file *, struct hfi1_devdata *,
-                        struct hfi1_user_info *);
-static unsigned int poll_urgent(struct file *, struct poll_table_struct *);
-static unsigned int poll_next(struct file *, struct poll_table_struct *);
-static int user_event_ack(struct hfi1_ctxtdata *, int, unsigned long);
-static int set_ctxt_pkey(struct hfi1_ctxtdata *, unsigned, u16);
-static int manage_rcvq(struct hfi1_ctxtdata *, unsigned, int);
-static int vma_fault(struct vm_fault *);
+static int hfi1_file_open(struct inode *inode, struct file *fp);
+static int hfi1_file_close(struct inode *inode, struct file *fp);
+static ssize_t hfi1_write_iter(struct kiocb *kiocb, struct iov_iter *from);
+static unsigned int hfi1_poll(struct file *fp, struct poll_table_struct *pt);
+static int hfi1_file_mmap(struct file *fp, struct vm_area_struct *vma);
+
+static u64 kvirt_to_phys(void *addr);
+static int assign_ctxt(struct hfi1_filedata *fd, struct hfi1_user_info *uinfo);
+static int init_subctxts(struct hfi1_ctxtdata *uctxt,
+                        const struct hfi1_user_info *uinfo);
+static int init_user_ctxt(struct hfi1_filedata *fd);
+static void user_init(struct hfi1_ctxtdata *uctxt);
+static int get_ctxt_info(struct hfi1_filedata *fd, void __user *ubase,
+                        __u32 len);
+static int get_base_info(struct hfi1_filedata *fd, void __user *ubase,
+                        __u32 len);
+static int setup_base_ctxt(struct hfi1_filedata *fd);
+static int setup_subctxt(struct hfi1_ctxtdata *uctxt);
+
+static int find_sub_ctxt(struct hfi1_filedata *fd,
+                        const struct hfi1_user_info *uinfo);
+static int allocate_ctxt(struct hfi1_filedata *fd, struct hfi1_devdata *dd,
+                        struct hfi1_user_info *uinfo);
+static unsigned int poll_urgent(struct file *fp, struct poll_table_struct *pt);
+static unsigned int poll_next(struct file *fp, struct poll_table_struct *pt);
+static int user_event_ack(struct hfi1_ctxtdata *uctxt, u16 subctxt,
+                         unsigned long events);
+static int set_ctxt_pkey(struct hfi1_ctxtdata *uctxt, u16 subctxt, u16 pkey);
+static int manage_rcvq(struct hfi1_ctxtdata *uctxt, u16 subctxt,
+                      int start_stop);
+static int vma_fault(struct vm_fault *vmf);
 static long hfi1_file_ioctl(struct file *fp, unsigned int cmd,
                            unsigned long arg);
 
@@ -173,6 +181,9 @@ static int hfi1_file_open(struct inode *inode, struct file *fp)
                                               struct hfi1_devdata,
                                               user_cdev);
 
+       if (!((dd->flags & HFI1_PRESENT) && dd->kregbase))
+               return -EINVAL;
+
        if (!atomic_inc_not_zero(&dd->user_refcount))
                return -ENXIO;
 
@@ -187,6 +198,7 @@ static int hfi1_file_open(struct inode *inode, struct file *fp)
                fd->rec_cpu_num = -1; /* no cpu affinity by default */
                fd->mm = current->mm;
                mmgrab(fd->mm);
+               fd->dd = dd;
                fp->private_data = fd;
        } else {
                fp->private_data = NULL;
@@ -229,20 +241,14 @@ static long hfi1_file_ioctl(struct file *fp, unsigned int cmd,
                                   sizeof(uinfo)))
                        return -EFAULT;
 
-               ret = assign_ctxt(fp, &uinfo);
-               if (ret < 0)
-                       return ret;
-               ret = setup_ctxt(fp);
-               if (ret)
-                       return ret;
-               ret = user_init(fp);
+               ret = assign_ctxt(fd, &uinfo);
                break;
        case HFI1_IOCTL_CTXT_INFO:
-               ret = get_ctxt_info(fp, (void __user *)(unsigned long)arg,
+               ret = get_ctxt_info(fd, (void __user *)(unsigned long)arg,
                                    sizeof(struct hfi1_ctxt_info));
                break;
        case HFI1_IOCTL_USER_INFO:
-               ret = get_base_info(fp, (void __user *)(unsigned long)arg,
+               ret = get_base_info(fd, (void __user *)(unsigned long)arg,
                                    sizeof(struct hfi1_base_info));
                break;
        case HFI1_IOCTL_CREDIT_UPD:
@@ -256,7 +262,7 @@ static long hfi1_file_ioctl(struct file *fp, unsigned int cmd,
                                   sizeof(tinfo)))
                        return -EFAULT;
 
-               ret = hfi1_user_exp_rcv_setup(fp, &tinfo);
+               ret = hfi1_user_exp_rcv_setup(fd, &tinfo);
                if (!ret) {
                        /*
                         * Copy the number of tidlist entries we used
@@ -278,7 +284,7 @@ static long hfi1_file_ioctl(struct file *fp, unsigned int cmd,
                                   sizeof(tinfo)))
                        return -EFAULT;
 
-               ret = hfi1_user_exp_rcv_clear(fp, &tinfo);
+               ret = hfi1_user_exp_rcv_clear(fd, &tinfo);
                if (ret)
                        break;
                addr = arg + offsetof(struct hfi1_tid_info, tidcnt);
@@ -293,7 +299,7 @@ static long hfi1_file_ioctl(struct file *fp, unsigned int cmd,
                                   sizeof(tinfo)))
                        return -EFAULT;
 
-               ret = hfi1_user_exp_rcv_invalid(fp, &tinfo);
+               ret = hfi1_user_exp_rcv_invalid(fd, &tinfo);
                if (ret)
                        break;
                addr = arg + offsetof(struct hfi1_tid_info, tidcnt);
@@ -430,7 +436,7 @@ static ssize_t hfi1_write_iter(struct kiocb *kiocb, struct iov_iter *from)
                unsigned long count = 0;
 
                ret = hfi1_user_sdma_process_request(
-                       kiocb->ki_filp, (struct iovec *)(from->iov + done),
+                       fd, (struct iovec *)(from->iov + done),
                        dim, &count);
                if (ret) {
                        reqs = ret;
@@ -756,6 +762,9 @@ static int hfi1_file_close(struct inode *inode, struct file *fp)
        /* release the cpu */
        hfi1_put_proc_affinity(fdata->rec_cpu_num);
 
+       /* clean up rcv side */
+       hfi1_user_exp_rcv_free(fdata);
+
        /*
         * Clear any left over, unhandled events so the next process that
         * gets this context doesn't get confused.
@@ -764,8 +773,8 @@ static int hfi1_file_close(struct inode *inode, struct file *fp)
                           HFI1_MAX_SHARED_CTXTS) + fdata->subctxt;
        *ev = 0;
 
-       if (--uctxt->cnt) {
-               uctxt->active_slaves &= ~(1 << fdata->subctxt);
+       __clear_bit(fdata->subctxt, uctxt->in_use_ctxts);
+       if (!bitmap_empty(uctxt->in_use_ctxts, HFI1_MAX_SHARED_CTXTS)) {
                mutex_unlock(&hfi1_mutex);
                goto done;
        }
@@ -795,8 +804,8 @@ static int hfi1_file_close(struct inode *inode, struct file *fp)
 
        dd->rcd[uctxt->ctxt] = NULL;
 
-       hfi1_user_exp_rcv_free(fdata);
-       hfi1_clear_ctxt_pkey(dd, uctxt->ctxt);
+       hfi1_user_exp_rcv_grp_free(uctxt);
+       hfi1_clear_ctxt_pkey(dd, uctxt);
 
        uctxt->rcvwait_to = 0;
        uctxt->piowait_to = 0;
@@ -836,127 +845,135 @@ static u64 kvirt_to_phys(void *addr)
        return paddr;
 }
 
-static int assign_ctxt(struct file *fp, struct hfi1_user_info *uinfo)
+static int assign_ctxt(struct hfi1_filedata *fd, struct hfi1_user_info *uinfo)
 {
-       int i_minor, ret = 0;
+       int ret;
        unsigned int swmajor, swminor;
 
        swmajor = uinfo->userversion >> 16;
-       if (swmajor != HFI1_USER_SWMAJOR) {
-               ret = -ENODEV;
-               goto done;
-       }
+       if (swmajor != HFI1_USER_SWMAJOR)
+               return -ENODEV;
 
        swminor = uinfo->userversion & 0xffff;
 
        mutex_lock(&hfi1_mutex);
-       /* First, lets check if we need to setup a shared context? */
+       /*
+        * Get a sub context if necessary.
+        * ret < 0 error, 0 no context, 1 sub-context found
+        */
+       ret = 0;
        if (uinfo->subctxt_cnt) {
-               struct hfi1_filedata *fd = fp->private_data;
-
-               ret = find_shared_ctxt(fp, uinfo);
-               if (ret < 0)
-                       goto done_unlock;
-               if (ret) {
+               ret = find_sub_ctxt(fd, uinfo);
+               if (ret > 0)
                        fd->rec_cpu_num =
                                hfi1_get_proc_affinity(fd->uctxt->numa_id);
-               }
        }
 
        /*
-        * We execute the following block if we couldn't find a
-        * shared context or if context sharing is not required.
+        * Allocate a base context if context sharing is not required or we
+        * couldn't find a sub context.
         */
-       if (!ret) {
-               i_minor = iminor(file_inode(fp)) - HFI1_USER_MINOR_BASE;
-               ret = get_user_context(fp, uinfo, i_minor);
-       }
-done_unlock:
+       if (!ret)
+               ret = allocate_ctxt(fd, fd->dd, uinfo);
+
        mutex_unlock(&hfi1_mutex);
-done:
+
+       /* Depending on the context type, do the appropriate init */
+       if (ret > 0) {
+               /*
+                * sub-context info can only be set up after the base
+                * context has been completed.
+                */
+               ret = wait_event_interruptible(fd->uctxt->wait, !test_bit(
+                                              HFI1_CTXT_BASE_UNINIT,
+                                              &fd->uctxt->event_flags));
+               if (test_bit(HFI1_CTXT_BASE_FAILED, &fd->uctxt->event_flags)) {
+                       clear_bit(fd->subctxt, fd->uctxt->in_use_ctxts);
+                       return -ENOMEM;
+               }
+               /* The only thing a sub context needs is the user_xxx stuff */
+               if (!ret)
+                       ret = init_user_ctxt(fd);
+
+               if (ret)
+                       clear_bit(fd->subctxt, fd->uctxt->in_use_ctxts);
+       } else if (!ret) {
+               ret = setup_base_ctxt(fd);
+               if (fd->uctxt->subctxt_cnt) {
+                       /* If there is an error, set the failed bit. */
+                       if (ret)
+                               set_bit(HFI1_CTXT_BASE_FAILED,
+                                       &fd->uctxt->event_flags);
+                       /*
+                        * Base context is done, notify anybody using a
+                        * sub-context that is waiting for this completion
+                        */
+                       clear_bit(HFI1_CTXT_BASE_UNINIT,
+                                 &fd->uctxt->event_flags);
+                       wake_up(&fd->uctxt->wait);
+               }
+       }
+
        return ret;
 }
 
-static int get_user_context(struct file *fp, struct hfi1_user_info *uinfo,
-                           int devno)
+/*
+ * The hfi1_mutex must be held when this function is called.  It is
+ * necessary to ensure serialized access to the bitmask in_use_ctxts.
+ */
+static int find_sub_ctxt(struct hfi1_filedata *fd,
+                        const struct hfi1_user_info *uinfo)
 {
-       struct hfi1_devdata *dd = NULL;
-       int devmax, npresent, nup;
+       int i;
+       struct hfi1_devdata *dd = fd->dd;
+       u16 subctxt;
 
-       devmax = hfi1_count_units(&npresent, &nup);
-       if (!npresent)
-               return -ENXIO;
+       for (i = dd->first_dyn_alloc_ctxt; i < dd->num_rcv_contexts; i++) {
+               struct hfi1_ctxtdata *uctxt = dd->rcd[i];
 
-       if (!nup)
-               return -ENETDOWN;
+               /* Skip ctxts which are not yet open */
+               if (!uctxt ||
+                   bitmap_empty(uctxt->in_use_ctxts,
+                                HFI1_MAX_SHARED_CTXTS))
+                       continue;
 
-       dd = hfi1_lookup(devno);
-       if (!dd)
-               return -ENODEV;
-       else if (!dd->freectxts)
-               return -EBUSY;
+               /* Skip dynamically allocted kernel contexts */
+               if (uctxt->sc && (uctxt->sc->type == SC_KERNEL))
+                       continue;
 
-       return allocate_ctxt(fp, dd, uinfo);
-}
+               /* Skip ctxt if it doesn't match the requested one */
+               if (memcmp(uctxt->uuid, uinfo->uuid,
+                          sizeof(uctxt->uuid)) ||
+                   uctxt->jkey != generate_jkey(current_uid()) ||
+                   uctxt->subctxt_id != uinfo->subctxt_id ||
+                   uctxt->subctxt_cnt != uinfo->subctxt_cnt)
+                       continue;
 
-static int find_shared_ctxt(struct file *fp,
-                           const struct hfi1_user_info *uinfo)
-{
-       int devmax, ndev, i;
-       int ret = 0;
-       struct hfi1_filedata *fd = fp->private_data;
+               /* Verify the sharing process matches the master */
+               if (uctxt->userversion != uinfo->userversion)
+                       return -EINVAL;
 
-       devmax = hfi1_count_units(NULL, NULL);
+               /* Find an unused context */
+               subctxt = find_first_zero_bit(uctxt->in_use_ctxts,
+                                             HFI1_MAX_SHARED_CTXTS);
+               if (subctxt >= uctxt->subctxt_cnt)
+                       return -EBUSY;
 
-       for (ndev = 0; ndev < devmax; ndev++) {
-               struct hfi1_devdata *dd = hfi1_lookup(ndev);
+               fd->uctxt = uctxt;
+               fd->subctxt = subctxt;
+               __set_bit(fd->subctxt, uctxt->in_use_ctxts);
 
-               if (!(dd && (dd->flags & HFI1_PRESENT) && dd->kregbase))
-                       continue;
-               for (i = dd->first_dyn_alloc_ctxt;
-                    i < dd->num_rcv_contexts; i++) {
-                       struct hfi1_ctxtdata *uctxt = dd->rcd[i];
-
-                       /* Skip ctxts which are not yet open */
-                       if (!uctxt || !uctxt->cnt)
-                               continue;
-
-                       /* Skip dynamically allocted kernel contexts */
-                       if (uctxt->sc && (uctxt->sc->type == SC_KERNEL))
-                               continue;
-
-                       /* Skip ctxt if it doesn't match the requested one */
-                       if (memcmp(uctxt->uuid, uinfo->uuid,
-                                  sizeof(uctxt->uuid)) ||
-                           uctxt->jkey != generate_jkey(current_uid()) ||
-                           uctxt->subctxt_id != uinfo->subctxt_id ||
-                           uctxt->subctxt_cnt != uinfo->subctxt_cnt)
-                               continue;
-
-                       /* Verify the sharing process matches the master */
-                       if (uctxt->userversion != uinfo->userversion ||
-                           uctxt->cnt >= uctxt->subctxt_cnt) {
-                               ret = -EINVAL;
-                               goto done;
-                       }
-                       fd->uctxt = uctxt;
-                       fd->subctxt  = uctxt->cnt++;
-                       uctxt->active_slaves |= 1 << fd->subctxt;
-                       ret = 1;
-                       goto done;
-               }
+               return 1;
        }
 
-done:
-       return ret;
+       return 0;
 }
 
-static int allocate_ctxt(struct file *fp, struct hfi1_devdata *dd,
+static int allocate_ctxt(struct hfi1_filedata *fd, struct hfi1_devdata *dd,
                         struct hfi1_user_info *uinfo)
 {
-       struct hfi1_filedata *fd = fp->private_data;
        struct hfi1_ctxtdata *uctxt;
-       unsigned ctxt;
+       unsigned int ctxt;
        int ret, numa;
 
        if (dd->flags & HFI1_FROZEN) {
@@ -970,6 +987,14 @@ static int allocate_ctxt(struct file *fp, struct hfi1_devdata *dd,
                return -EIO;
        }
 
+       /*
+        * This check is sort of redundant to the next EBUSY error. It would
+        * also indicate an inconsistancy in the driver if this value was
+        * zero, but there were still contexts available.
+        */
+       if (!dd->freectxts)
+               return -EBUSY;
+
        for (ctxt = dd->first_dyn_alloc_ctxt;
             ctxt < dd->num_rcv_contexts; ctxt++)
                if (!dd->rcd[ctxt])
@@ -1013,12 +1038,12 @@ static int allocate_ctxt(struct file *fp, struct hfi1_devdata *dd,
                goto ctxdata_free;
 
        /*
-        * Setup shared context resources if the user-level has requested
-        * shared contexts and this is the 'master' process.
+        * Setup sub context resources if the user-level has requested
+        * sub contexts.
         * This has to be done here so the rest of the sub-contexts find the
         * proper master.
         */
-       if (uinfo->subctxt_cnt && !fd->subctxt) {
+       if (uinfo->subctxt_cnt) {
                ret = init_subctxts(uctxt, uinfo);
                /*
                 * On error, we don't need to disable and de-allocate the
@@ -1055,7 +1080,7 @@ ctxdata_free:
 static int init_subctxts(struct hfi1_ctxtdata *uctxt,
                         const struct hfi1_user_info *uinfo)
 {
-       unsigned num_subctxts;
+       u16 num_subctxts;
 
        num_subctxts = uinfo->subctxt_cnt;
        if (num_subctxts > HFI1_MAX_SHARED_CTXTS)
@@ -1063,9 +1088,8 @@ static int init_subctxts(struct hfi1_ctxtdata *uctxt,
 
        uctxt->subctxt_cnt = uinfo->subctxt_cnt;
        uctxt->subctxt_id = uinfo->subctxt_id;
-       uctxt->active_slaves = 1;
        uctxt->redirect_seq_cnt = 1;
-       set_bit(HFI1_CTXT_MASTER_UNINIT, &uctxt->event_flags);
+       set_bit(HFI1_CTXT_BASE_UNINIT, &uctxt->event_flags);
 
        return 0;
 }
@@ -1073,13 +1097,12 @@ static int init_subctxts(struct hfi1_ctxtdata *uctxt,
 static int setup_subctxt(struct hfi1_ctxtdata *uctxt)
 {
        int ret = 0;
-       unsigned num_subctxts = uctxt->subctxt_cnt;
+       u16 num_subctxts = uctxt->subctxt_cnt;
 
        uctxt->subctxt_uregbase = vmalloc_user(PAGE_SIZE);
-       if (!uctxt->subctxt_uregbase) {
-               ret = -ENOMEM;
-               goto bail;
-       }
+       if (!uctxt->subctxt_uregbase)
+               return -ENOMEM;
+
        /* We can take the size of the RcvHdr Queue from the master */
        uctxt->subctxt_rcvhdr_base = vmalloc_user(uctxt->rcvhdrq_size *
                                                  num_subctxts);
@@ -1094,25 +1117,22 @@ static int setup_subctxt(struct hfi1_ctxtdata *uctxt)
                ret = -ENOMEM;
                goto bail_rhdr;
        }
-       goto bail;
+
+       return 0;
+
 bail_rhdr:
        vfree(uctxt->subctxt_rcvhdr_base);
+       uctxt->subctxt_rcvhdr_base = NULL;
 bail_ureg:
        vfree(uctxt->subctxt_uregbase);
        uctxt->subctxt_uregbase = NULL;
-bail:
+
        return ret;
 }
 
-static int user_init(struct file *fp)
+static void user_init(struct hfi1_ctxtdata *uctxt)
 {
        unsigned int rcvctrl_ops = 0;
-       struct hfi1_filedata *fd = fp->private_data;
-       struct hfi1_ctxtdata *uctxt = fd->uctxt;
-
-       /* make sure that the context has already been setup */
-       if (!test_bit(HFI1_CTXT_SETUP_DONE, &uctxt->event_flags))
-               return -EFAULT;
 
        /* initialize poll variables... */
        uctxt->urgent = 0;
@@ -1160,20 +1180,12 @@ static int user_init(struct file *fp)
        else
                rcvctrl_ops |= HFI1_RCVCTRL_TAILUPD_DIS;
        hfi1_rcvctrl(uctxt->dd, rcvctrl_ops, uctxt->ctxt);
-
-       /* Notify any waiting slaves */
-       if (uctxt->subctxt_cnt) {
-               clear_bit(HFI1_CTXT_MASTER_UNINIT, &uctxt->event_flags);
-               wake_up(&uctxt->wait);
-       }
-
-       return 0;
 }
 
-static int get_ctxt_info(struct file *fp, void __user *ubase, __u32 len)
+static int get_ctxt_info(struct hfi1_filedata *fd, void __user *ubase,
+                        __u32 len)
 {
        struct hfi1_ctxt_info cinfo;
-       struct hfi1_filedata *fd = fp->private_data;
        struct hfi1_ctxtdata *uctxt = fd->uctxt;
        int ret = 0;
 
@@ -1211,75 +1223,71 @@ static int get_ctxt_info(struct file *fp, void __user *ubase, __u32 len)
        return ret;
 }
 
-static int setup_ctxt(struct file *fp)
+static int init_user_ctxt(struct hfi1_filedata *fd)
+{
+       struct hfi1_ctxtdata *uctxt = fd->uctxt;
+       int ret;
+
+       ret = hfi1_user_sdma_alloc_queues(uctxt, fd);
+       if (ret)
+               return ret;
+
+       ret = hfi1_user_exp_rcv_init(fd);
+
+       return ret;
+}
+
+static int setup_base_ctxt(struct hfi1_filedata *fd)
 {
-       struct hfi1_filedata *fd = fp->private_data;
        struct hfi1_ctxtdata *uctxt = fd->uctxt;
        struct hfi1_devdata *dd = uctxt->dd;
        int ret = 0;
 
-       /*
-        * Context should be set up only once, including allocation and
-        * programming of eager buffers. This is done if context sharing
-        * is not requested or by the master process.
-        */
-       if (!uctxt->subctxt_cnt || !fd->subctxt) {
-               ret = hfi1_init_ctxt(uctxt->sc);
-               if (ret)
-                       goto done;
+       hfi1_init_ctxt(uctxt->sc);
 
-               /* Now allocate the RcvHdr queue and eager buffers. */
-               ret = hfi1_create_rcvhdrq(dd, uctxt);
-               if (ret)
-                       goto done;
-               ret = hfi1_setup_eagerbufs(uctxt);
-               if (ret)
-                       goto done;
-               if (uctxt->subctxt_cnt && !fd->subctxt) {
-                       ret = setup_subctxt(uctxt);
-                       if (ret)
-                               goto done;
-               }
-       } else {
-               ret = wait_event_interruptible(uctxt->wait, !test_bit(
-                                              HFI1_CTXT_MASTER_UNINIT,
-                                              &uctxt->event_flags));
-               if (ret)
-                       goto done;
-       }
+       /* Now allocate the RcvHdr queue and eager buffers. */
+       ret = hfi1_create_rcvhdrq(dd, uctxt);
+       if (ret)
+               return ret;
 
-       ret = hfi1_user_sdma_alloc_queues(uctxt, fp);
+       ret = hfi1_setup_eagerbufs(uctxt);
        if (ret)
-               goto done;
-       /*
-        * Expected receive has to be setup for all processes (including
-        * shared contexts). However, it has to be done after the master
-        * context has been fully configured as it depends on the
-        * eager/expected split of the RcvArray entries.
-        * Setting it up here ensures that the subcontexts will be waiting
-        * (due to the above wait_event_interruptible() until the master
-        * is setup.
-        */
-       ret = hfi1_user_exp_rcv_init(fp);
+               goto setup_failed;
+
+       /* If sub-contexts are enabled, do the appropriate setup */
+       if (uctxt->subctxt_cnt)
+               ret = setup_subctxt(uctxt);
        if (ret)
-               goto done;
+               goto setup_failed;
 
-       set_bit(HFI1_CTXT_SETUP_DONE, &uctxt->event_flags);
-done:
+       ret = hfi1_user_exp_rcv_grp_init(fd);
+       if (ret)
+               goto setup_failed;
+
+       ret = init_user_ctxt(fd);
+       if (ret)
+               goto setup_failed;
+
+       user_init(uctxt);
+
+       return 0;
+
+setup_failed:
+       hfi1_free_ctxtdata(dd, uctxt);
        return ret;
 }
 
-static int get_base_info(struct file *fp, void __user *ubase, __u32 len)
+static int get_base_info(struct hfi1_filedata *fd, void __user *ubase,
+                        __u32 len)
 {
        struct hfi1_base_info binfo;
-       struct hfi1_filedata *fd = fp->private_data;
        struct hfi1_ctxtdata *uctxt = fd->uctxt;
        struct hfi1_devdata *dd = uctxt->dd;
        ssize_t sz;
        unsigned offset;
        int ret = 0;
 
-       trace_hfi1_uctxtdata(uctxt->dd, uctxt);
+       trace_hfi1_uctxtdata(uctxt->dd, uctxt, fd->subctxt);
 
        memset(&binfo, 0, sizeof(binfo));
        binfo.hw_version = dd->revision;
@@ -1443,7 +1451,7 @@ done:
  * overflow conditions.  start_stop==1 re-enables, to be used to
  * re-init the software copy of the head register
  */
-static int manage_rcvq(struct hfi1_ctxtdata *uctxt, unsigned subctxt,
+static int manage_rcvq(struct hfi1_ctxtdata *uctxt, u16 subctxt,
                       int start_stop)
 {
        struct hfi1_devdata *dd = uctxt->dd;
@@ -1478,7 +1486,7 @@ bail:
  * User process then performs actions appropriate to bit having been
  * set, if desired, and checks again in future.
  */
-static int user_event_ack(struct hfi1_ctxtdata *uctxt, int subctxt,
+static int user_event_ack(struct hfi1_ctxtdata *uctxt, u16 subctxt,
                          unsigned long events)
 {
        int i;
@@ -1499,8 +1507,7 @@ static int user_event_ack(struct hfi1_ctxtdata *uctxt, int subctxt,
        return 0;
 }
 
-static int set_ctxt_pkey(struct hfi1_ctxtdata *uctxt, unsigned subctxt,
-                        u16 pkey)
+static int set_ctxt_pkey(struct hfi1_ctxtdata *uctxt, u16 subctxt, u16 pkey)
 {
        int ret = -ENOENT, i, intable = 0;
        struct hfi1_pportdata *ppd = uctxt->ppd;
index f06674317abfcd010b192b57ebed503ad59e6e3c..da322e6668cc5893262c3316486147cac6df1ca9 100644 (file)
@@ -196,12 +196,6 @@ struct hfi1_ctxtdata {
        void *rcvhdrq;
        /* kernel virtual address where hdrqtail is updated */
        volatile __le64 *rcvhdrtail_kvaddr;
-       /*
-        * Shared page for kernel to signal user processes that send buffers
-        * need disarming.  The process should call HFI1_CMD_DISARM_BUFS
-        * or HFI1_CMD_ACK_EVENT with IPATH_EVENT_DISARM_BUFS set.
-        */
-       unsigned long *user_event_mask;
        /* when waiting for rcv or pioavail */
        wait_queue_head_t wait;
        /* rcvhdrq size (for freeing) */
@@ -224,13 +218,12 @@ struct hfi1_ctxtdata {
         * (ignoring forks, dup, etc. for now)
         */
        int cnt;
+       /* Device context index */
+       unsigned ctxt;
        /*
-        * how much space to leave at start of eager TID entries for
-        * protocol use, on each TID
+        * non-zero if ctxt can be shared, and defines the maximum number of
+        * sub-contexts for this device context.
         */
-       /* instead of calculating it */
-       unsigned ctxt;
-       /* non-zero if ctxt is being shared. */
        u16 subctxt_cnt;
        /* non-zero if ctxt is being shared. */
        u16 subctxt_id;
@@ -288,10 +281,10 @@ struct hfi1_ctxtdata {
        void *subctxt_rcvegrbuf;
        /* An array of pages for the eager header queue entries * N */
        void *subctxt_rcvhdr_base;
+       /* Bitmask of in use context(s) */
+       DECLARE_BITMAP(in_use_ctxts, HFI1_MAX_SHARED_CTXTS);
        /* The version of the library which opened this ctxt */
        u32 userversion;
-       /* Bitmask of active slaves */
-       u32 active_slaves;
        /* Type of packets or conditions we want to poll for */
        u16 poll_type;
        /* receive packet sequence counter */
@@ -1238,10 +1231,11 @@ struct mmu_rb_handler;
 
 /* Private data for file operations */
 struct hfi1_filedata {
+       struct hfi1_devdata *dd;
        struct hfi1_ctxtdata *uctxt;
-       unsigned subctxt;
        struct hfi1_user_sdma_comp_q *cq;
        struct hfi1_user_sdma_pkt_q *pq;
+       u16 subctxt;
        /* for cpu affinity; -1 if none */
        int rec_cpu_num;
        u32 tid_n_pinned;
@@ -1263,27 +1257,27 @@ struct hfi1_devdata *hfi1_lookup(int unit);
 extern u32 hfi1_cpulist_count;
 extern unsigned long *hfi1_cpulist;
 
-int hfi1_init(struct hfi1_devdata *, int);
-int hfi1_count_units(int *npresentp, int *nupp);
+int hfi1_init(struct hfi1_devdata *dd, int reinit);
 int hfi1_count_active_units(void);
 
-int hfi1_diag_add(struct hfi1_devdata *);
-void hfi1_diag_remove(struct hfi1_devdata *);
+int hfi1_diag_add(struct hfi1_devdata *dd);
+void hfi1_diag_remove(struct hfi1_devdata *dd);
 void handle_linkup_change(struct hfi1_devdata *dd, u32 linkup);
 
 void handle_user_interrupt(struct hfi1_ctxtdata *rcd);
 
-int hfi1_create_rcvhdrq(struct hfi1_devdata *, struct hfi1_ctxtdata *);
-int hfi1_setup_eagerbufs(struct hfi1_ctxtdata *);
+int hfi1_create_rcvhdrq(struct hfi1_devdata *dd, struct hfi1_ctxtdata *rcd);
+int hfi1_setup_eagerbufs(struct hfi1_ctxtdata *rcd);
 int hfi1_create_ctxts(struct hfi1_devdata *dd);
-struct hfi1_ctxtdata *hfi1_create_ctxtdata(struct hfi1_pportdata *, u32, int);
-void hfi1_init_pportdata(struct pci_dev *, struct hfi1_pportdata *,
-                        struct hfi1_devdata *, u8, u8);
-void hfi1_free_ctxtdata(struct hfi1_devdata *, struct hfi1_ctxtdata *);
-
-int handle_receive_interrupt(struct hfi1_ctxtdata *, int);
-int handle_receive_interrupt_nodma_rtail(struct hfi1_ctxtdata *, int);
-int handle_receive_interrupt_dma_rtail(struct hfi1_ctxtdata *, int);
+struct hfi1_ctxtdata *hfi1_create_ctxtdata(struct hfi1_pportdata *ppd, u32 ctxt,
+                                          int numa);
+void hfi1_init_pportdata(struct pci_dev *pdev, struct hfi1_pportdata *ppd,
+                        struct hfi1_devdata *dd, u8 hw_pidx, u8 port);
+void hfi1_free_ctxtdata(struct hfi1_devdata *dd, struct hfi1_ctxtdata *rcd);
+
+int handle_receive_interrupt(struct hfi1_ctxtdata *rcd, int thread);
+int handle_receive_interrupt_nodma_rtail(struct hfi1_ctxtdata *rcd, int thread);
+int handle_receive_interrupt_dma_rtail(struct hfi1_ctxtdata *rcd, int thread);
 void set_all_slowpath(struct hfi1_devdata *dd);
 void hfi1_vnic_synchronize_irq(struct hfi1_devdata *dd);
 void hfi1_set_vnic_msix_info(struct hfi1_ctxtdata *rcd);
@@ -1580,7 +1574,7 @@ bad:
 
 u32 lrh_max_header_bytes(struct hfi1_devdata *dd);
 int mtu_to_enum(u32 mtu, int default_if_bad);
-u16 enum_to_mtu(int);
+u16 enum_to_mtu(int mtu);
 static inline int valid_ib_mtu(unsigned int mtu)
 {
        return mtu == 256 || mtu == 512 ||
@@ -1594,15 +1588,15 @@ static inline int valid_opa_max_mtu(unsigned int mtu)
                (valid_ib_mtu(mtu) || mtu == 8192 || mtu == 10240);
 }
 
-int set_mtu(struct hfi1_pportdata *);
+int set_mtu(struct hfi1_pportdata *ppd);
 
-int hfi1_set_lid(struct hfi1_pportdata *, u32, u8);
-void hfi1_disable_after_error(struct hfi1_devdata *);
-int hfi1_set_uevent_bits(struct hfi1_pportdata *, const int);
-int hfi1_rcvbuf_validate(u32, u8, u16 *);
+int hfi1_set_lid(struct hfi1_pportdata *ppd, u32 lid, u8 lmc);
+void hfi1_disable_after_error(struct hfi1_devdata *dd);
+int hfi1_set_uevent_bits(struct hfi1_pportdata *ppd, const int evtbit);
+int hfi1_rcvbuf_validate(u32 size, u8 type, u16 *encode);
 
-int fm_get_table(struct hfi1_pportdata *, int, void *);
-int fm_set_table(struct hfi1_pportdata *, int, void *);
+int fm_get_table(struct hfi1_pportdata *ppd, int which, void *t);
+int fm_set_table(struct hfi1_pportdata *ppd, int which, void *t);
 
 void set_up_vl15(struct hfi1_devdata *dd, u8 vau, u16 vl15buf);
 void reset_link_credits(struct hfi1_devdata *dd);
@@ -1724,19 +1718,19 @@ struct cc_state *get_cc_state_protected(struct hfi1_pportdata *ppd)
 #define HFI1_PBC_LENGTH_MASK                     ((1 << 11) - 1)
 
 /* ctxt_flag bit offsets */
-               /* context has been setup */
-#define HFI1_CTXT_SETUP_DONE 1
+               /* base context has not finished initializing */
+#define HFI1_CTXT_BASE_UNINIT 1
+               /* base context initaliation failed */
+#define HFI1_CTXT_BASE_FAILED 2
                /* waiting for a packet to arrive */
-#define HFI1_CTXT_WAITING_RCV   2
-               /* master has not finished initializing */
-#define HFI1_CTXT_MASTER_UNINIT 4
+#define HFI1_CTXT_WAITING_RCV 3
                /* waiting for an urgent packet to arrive */
-#define HFI1_CTXT_WAITING_URG 5
+#define HFI1_CTXT_WAITING_URG 4
 
 /* free up any allocated data at closes */
-struct hfi1_devdata *hfi1_init_dd(struct pci_dev *,
-                                 const struct pci_device_id *);
-void hfi1_free_devdata(struct hfi1_devdata *);
+struct hfi1_devdata *hfi1_init_dd(struct pci_dev *pdev,
+                                 const struct pci_device_id *ent);
+void hfi1_free_devdata(struct hfi1_devdata *dd);
 struct hfi1_devdata *hfi1_alloc_devdata(struct pci_dev *pdev, size_t extra);
 
 /* LED beaconing functions */
@@ -1811,24 +1805,24 @@ static inline u32 get_rcvhdrtail(const struct hfi1_ctxtdata *rcd)
 
 extern const char ib_hfi1_version[];
 
-int hfi1_device_create(struct hfi1_devdata *);
-void hfi1_device_remove(struct hfi1_devdata *);
+int hfi1_device_create(struct hfi1_devdata *dd);
+void hfi1_device_remove(struct hfi1_devdata *dd);
 
 int hfi1_create_port_files(struct ib_device *ibdev, u8 port_num,
                           struct kobject *kobj);
-int hfi1_verbs_register_sysfs(struct hfi1_devdata *);
-void hfi1_verbs_unregister_sysfs(struct hfi1_devdata *);
+int hfi1_verbs_register_sysfs(struct hfi1_devdata *dd);
+void hfi1_verbs_unregister_sysfs(struct hfi1_devdata *dd);
 /* Hook for sysfs read of QSFP */
 int qsfp_dump(struct hfi1_pportdata *ppd, char *buf, int len);
 
-int hfi1_pcie_init(struct pci_dev *, const struct pci_device_id *);
-void hfi1_pcie_cleanup(struct pci_dev *);
-int hfi1_pcie_ddinit(struct hfi1_devdata *, struct pci_dev *);
+int hfi1_pcie_init(struct pci_dev *pdev, const struct pci_device_id *ent);
+void hfi1_pcie_cleanup(struct pci_dev *pdev);
+int hfi1_pcie_ddinit(struct hfi1_devdata *dd, struct pci_dev *pdev);
 void hfi1_pcie_ddcleanup(struct hfi1_devdata *);
-void hfi1_pcie_flr(struct hfi1_devdata *);
-int pcie_speeds(struct hfi1_devdata *);
-void request_msix(struct hfi1_devdata *, u32 *, struct hfi1_msix_entry *);
-void hfi1_enable_intx(struct pci_dev *);
+int pcie_speeds(struct hfi1_devdata *dd);
+void request_msix(struct hfi1_devdata *dd, u32 *nent,
+                 struct hfi1_msix_entry *entry);
+void hfi1_enable_intx(struct pci_dev *pdev);
 void restore_pci_variables(struct hfi1_devdata *dd);
 int do_pcie_gen3_transition(struct hfi1_devdata *dd);
 int parse_platform_config(struct hfi1_devdata *dd);
index 4d6b9f82efa355e0f542b3cc0ce9a487497d2e5e..4a11d4da4c9201ce4ba8d8df12b7895ff75c07ec 100644 (file)
@@ -53,6 +53,7 @@
 #include <linux/module.h>
 #include <linux/printk.h>
 #include <linux/hrtimer.h>
+#include <linux/bitmap.h>
 #include <rdma/rdma_vt.h>
 
 #include "hfi.h"
@@ -70,6 +71,7 @@
 #undef pr_fmt
 #define pr_fmt(fmt) DRIVER_NAME ": " fmt
 
+#define HFI1_MAX_ACTIVE_WORKQUEUE_ENTRIES 5
 /*
  * min buffers we want to have per context, after driver
  */
@@ -101,9 +103,9 @@ static unsigned hfi1_rcvarr_split = 25;
 module_param_named(rcvarr_split, hfi1_rcvarr_split, uint, S_IRUGO);
 MODULE_PARM_DESC(rcvarr_split, "Percent of context's RcvArray entries used for Eager buffers");
 
-static uint eager_buffer_size = (2 << 20); /* 2MB */
+static uint eager_buffer_size = (8 << 20); /* 8MB */
 module_param(eager_buffer_size, uint, S_IRUGO);
-MODULE_PARM_DESC(eager_buffer_size, "Size of the eager buffers, default: 2MB");
+MODULE_PARM_DESC(eager_buffer_size, "Size of the eager buffers, default: 8MB");
 
 static uint rcvhdrcnt = 2048; /* 2x the max eager buffer count */
 module_param_named(rcvhdrcnt, rcvhdrcnt, uint, S_IRUGO);
@@ -117,7 +119,7 @@ unsigned int user_credit_return_threshold = 33;     /* default is 33% */
 module_param(user_credit_return_threshold, uint, S_IRUGO);
 MODULE_PARM_DESC(user_credit_return_threshold, "Credit return threshold for user send contexts, return when unreturned credits passes this many blocks (in percent of allocated blocks, 0 is off)");
 
-static inline u64 encode_rcv_header_entry_size(u16);
+static inline u64 encode_rcv_header_entry_size(u16 size);
 
 static struct idr hfi1_unit_table;
 u32 hfi1_cpulist_count;
@@ -175,13 +177,7 @@ int hfi1_create_ctxts(struct hfi1_devdata *dd)
                        goto nomem;
                }
 
-               ret = hfi1_init_ctxt(rcd->sc);
-               if (ret < 0) {
-                       dd_dev_err(dd,
-                                  "Failed to setup kernel receive context, failing\n");
-                       ret = -EFAULT;
-                       goto bail;
-               }
+               hfi1_init_ctxt(rcd->sc);
        }
 
        /*
@@ -193,7 +189,7 @@ int hfi1_create_ctxts(struct hfi1_devdata *dd)
        return 0;
 nomem:
        ret = -ENOMEM;
-bail:
+
        if (dd->rcd) {
                for (i = 0; i < dd->num_rcv_contexts; ++i)
                        hfi1_free_ctxtdata(dd, dd->rcd[i]);
@@ -227,7 +223,7 @@ struct hfi1_ctxtdata *hfi1_create_ctxtdata(struct hfi1_pportdata *ppd, u32 ctxt,
                INIT_LIST_HEAD(&rcd->qp_wait_list);
                rcd->ppd = ppd;
                rcd->dd = dd;
-               rcd->cnt = 1;
+               __set_bit(0, rcd->in_use_ctxts);
                rcd->ctxt = ctxt;
                dd->rcd[ctxt] = rcd;
                rcd->numa_id = numa;
@@ -623,7 +619,7 @@ static int create_workqueues(struct hfi1_devdata *dd)
                                alloc_workqueue(
                                    "hfi%d_%d",
                                    WQ_SYSFS | WQ_HIGHPRI | WQ_CPU_INTENSIVE,
-                                   dd->num_sdma,
+                                   HFI1_MAX_ACTIVE_WORKQUEUE_ENTRIES,
                                    dd->unit, pidx);
                        if (!ppd->hfi1_wq)
                                goto wq_error;
@@ -968,7 +964,6 @@ void hfi1_free_ctxtdata(struct hfi1_devdata *dd, struct hfi1_ctxtdata *rcd)
        kfree(rcd->egrbufs.buffers);
 
        sc_free(rcd->sc);
-       vfree(rcd->user_event_mask);
        vfree(rcd->subctxt_uregbase);
        vfree(rcd->subctxt_rcvegrbuf);
        vfree(rcd->subctxt_rcvhdr_base);
@@ -1687,8 +1682,6 @@ bail_free:
        dd_dev_err(dd,
                   "attempt to allocate 1 page for ctxt %u rcvhdrqtailaddr failed\n",
                   rcd->ctxt);
-       vfree(rcd->user_event_mask);
-       rcd->user_event_mask = NULL;
        dma_free_coherent(&dd->pcidev->dev, amt, rcd->rcvhdrq,
                          rcd->rcvhdrq_dma);
        rcd->rcvhdrq = NULL;
@@ -1777,6 +1770,7 @@ int hfi1_setup_eagerbufs(struct hfi1_ctxtdata *rcd)
                            !HFI1_CAP_KGET_MASK(rcd->flags, MULTI_PKT_EGR)) {
                                dd_dev_err(dd, "ctxt%u: Failed to allocate eager buffers\n",
                                           rcd->ctxt);
+                               ret = -ENOMEM;
                                goto bail_rcvegrbuf_phys;
                        }
 
@@ -1854,7 +1848,7 @@ int hfi1_setup_eagerbufs(struct hfi1_ctxtdata *rcd)
                          "ctxt%u: current Eager buffer size is invalid %u\n",
                          rcd->ctxt, rcd->egrbufs.rcvtid_size);
                ret = -EINVAL;
-               goto bail;
+               goto bail_rcvegrbuf_phys;
        }
 
        for (idx = 0; idx < rcd->egrbufs.alloced; idx++) {
@@ -1862,7 +1856,8 @@ int hfi1_setup_eagerbufs(struct hfi1_ctxtdata *rcd)
                             rcd->egrbufs.rcvtids[idx].dma, order);
                cond_resched();
        }
-       goto bail;
+
+       return 0;
 
 bail_rcvegrbuf_phys:
        for (idx = 0; idx < rcd->egrbufs.alloced &&
@@ -1876,6 +1871,6 @@ bail_rcvegrbuf_phys:
                rcd->egrbufs.buffers[idx].dma = 0;
                rcd->egrbufs.buffers[idx].len = 0;
        }
-bail:
+
        return ret;
 }
index 232014d46f7998f8319c753bb98b363e5f7afd00..ba265d0ae93b4a96d6c29364f30b34c6046c335b 100644 (file)
@@ -47,6 +47,7 @@
 
 #include <linux/pci.h>
 #include <linux/delay.h>
+#include <linux/bitmap.h>
 
 #include "hfi.h"
 #include "common.h"
@@ -189,7 +190,7 @@ void handle_user_interrupt(struct hfi1_ctxtdata *rcd)
        unsigned long flags;
 
        spin_lock_irqsave(&dd->uctxt_lock, flags);
-       if (!rcd->cnt)
+       if (bitmap_empty(rcd->in_use_ctxts, HFI1_MAX_SHARED_CTXTS))
                goto done;
 
        if (test_and_clear_bit(HFI1_CTXT_WAITING_RCV, &rcd->event_flags)) {
index e39e01b793823cad3274429cfe1115337c6bdf0a..93faf86d54b620fb2cc621844932d811c17868dd 100644 (file)
@@ -240,36 +240,6 @@ void hfi1_pcie_ddcleanup(struct hfi1_devdata *dd)
                iounmap(dd->piobase);
 }
 
-/*
- * Do a Function Level Reset (FLR) on the device.
- * Based on static function drivers/pci/pci.c:pcie_flr().
- */
-void hfi1_pcie_flr(struct hfi1_devdata *dd)
-{
-       int i;
-       u16 status;
-
-       /* no need to check for the capability - we know the device has it */
-
-       /* wait for Transaction Pending bit to clear, at most a few ms */
-       for (i = 0; i < 4; i++) {
-               if (i)
-                       msleep((1 << (i - 1)) * 100);
-
-               pcie_capability_read_word(dd->pcidev, PCI_EXP_DEVSTA, &status);
-               if (!(status & PCI_EXP_DEVSTA_TRPND))
-                       goto clear;
-       }
-
-       dd_dev_err(dd, "Transaction Pending bit is not clearing, proceeding with reset anyway\n");
-
-clear:
-       pcie_capability_set_word(dd->pcidev, PCI_EXP_DEVCTL,
-                                PCI_EXP_DEVCTL_BCR_FLR);
-       /* PCIe spec requires the function to be back within 100ms */
-       msleep(100);
-}
-
 static void msix_setup(struct hfi1_devdata *dd, int pos, u32 *msixcnt,
                       struct hfi1_msix_entry *hfi1_msix_entry)
 {
index 4573e4c9f35cc7ed9577cc970d228334c29134b1..650305cc037306923e5e742c02f7977e672a70f9 100644 (file)
@@ -731,9 +731,7 @@ void quiesce_qp(struct rvt_qp *qp)
 
 void notify_qp_reset(struct rvt_qp *qp)
 {
-       struct hfi1_qp_priv *priv = qp->priv;
-
-       priv->r_adefered = 0;
+       qp->r_adefered = 0;
        clear_ahg(qp);
 }
 
index 75a729cd0c3dfbd4639561e4a3b0161ff75b2573..069bdaf061ab923cbc8b123ab182806fdb3c4dac 100644 (file)
@@ -727,10 +727,9 @@ void hfi1_send_rc_ack(struct hfi1_ctxtdata *rcd, struct rvt_qp *qp,
        struct ib_header hdr;
        struct ib_other_headers *ohdr;
        unsigned long flags;
-       struct hfi1_qp_priv *priv = qp->priv;
 
        /* clear the defer count */
-       priv->r_adefered = 0;
+       qp->r_adefered = 0;
 
        /* Don't send ACK or NAK if a RDMA read or atomic is pending. */
        if (qp->s_flags & RVT_S_RESP_PENDING)
@@ -1604,9 +1603,7 @@ static inline void rc_defered_ack(struct hfi1_ctxtdata *rcd,
 
 static inline void rc_cancel_ack(struct rvt_qp *qp)
 {
-       struct hfi1_qp_priv *priv = qp->priv;
-
-       priv->r_adefered = 0;
+       qp->r_adefered = 0;
        if (list_empty(&qp->rspwait))
                return;
        list_del_init(&qp->rspwait);
@@ -2314,13 +2311,11 @@ send_last:
        qp->r_nak_state = 0;
        /* Send an ACK if requested or required. */
        if (psn & IB_BTH_REQ_ACK) {
-               struct hfi1_qp_priv *priv = qp->priv;
-
                if (packet->numpkt == 0) {
                        rc_cancel_ack(qp);
                        goto send_ack;
                }
-               if (priv->r_adefered >= HFI1_PSN_CREDIT) {
+               if (qp->r_adefered >= HFI1_PSN_CREDIT) {
                        rc_cancel_ack(qp);
                        goto send_ack;
                }
@@ -2328,7 +2323,7 @@ send_last:
                        rc_cancel_ack(qp);
                        goto send_ack;
                }
-               priv->r_adefered++;
+               qp->r_adefered++;
                rc_defered_ack(rcd, qp);
        }
        return;
index 891ba0a81bbdfc0533dbfed956989c14c9630efc..3a17daba28a935535904ed3596e9745a9f6c763b 100644 (file)
@@ -800,6 +800,43 @@ void hfi1_make_ruc_header(struct rvt_qp *qp, struct ib_other_headers *ohdr,
 /* when sending, force a reschedule every one of these periods */
 #define SEND_RESCHED_TIMEOUT (5 * HZ)  /* 5s in jiffies */
 
+/**
+ * schedule_send_yield - test for a yield required for QP send engine
+ * @timeout: Final time for timeout slice for jiffies
+ * @qp: a pointer to QP
+ * @ps: a pointer to a structure with commonly lookup values for
+ *      the the send engine progress
+ *
+ * This routine checks if the time slice for the QP has expired
+ * for RC QPs, if so an additional work entry is queued. At this
+ * point, other QPs have an opportunity to be scheduled. It
+ * returns true if a yield is required, otherwise, false
+ * is returned.
+ */
+static bool schedule_send_yield(struct rvt_qp *qp,
+                               struct hfi1_pkt_state *ps)
+{
+       if (unlikely(time_after(jiffies, ps->timeout))) {
+               if (!ps->in_thread ||
+                   workqueue_congested(ps->cpu, ps->ppd->hfi1_wq)) {
+                       spin_lock_irqsave(&qp->s_lock, ps->flags);
+                       qp->s_flags &= ~RVT_S_BUSY;
+                       hfi1_schedule_send(qp);
+                       spin_unlock_irqrestore(&qp->s_lock, ps->flags);
+                       this_cpu_inc(*ps->ppd->dd->send_schedule);
+                       trace_hfi1_rc_expired_time_slice(qp, true);
+                       return true;
+               }
+
+               cond_resched();
+               this_cpu_inc(*ps->ppd->dd->send_schedule);
+               ps->timeout = jiffies + ps->timeout_int;
+       }
+
+       trace_hfi1_rc_expired_time_slice(qp, false);
+       return false;
+}
+
 void hfi1_do_send_from_rvt(struct rvt_qp *qp)
 {
        hfi1_do_send(qp, false);
@@ -827,13 +864,13 @@ void hfi1_do_send(struct rvt_qp *qp, bool in_thread)
        struct hfi1_pkt_state ps;
        struct hfi1_qp_priv *priv = qp->priv;
        int (*make_req)(struct rvt_qp *qp, struct hfi1_pkt_state *ps);
-       unsigned long timeout;
-       unsigned long timeout_int;
-       int cpu;
 
        ps.dev = to_idev(qp->ibqp.device);
        ps.ibp = to_iport(qp->ibqp.device, qp->port_num);
        ps.ppd = ppd_from_ibp(ps.ibp);
+       ps.in_thread = in_thread;
+
+       trace_hfi1_rc_do_send(qp, in_thread);
 
        switch (qp->ibqp.qp_type) {
        case IB_QPT_RC:
@@ -844,7 +881,7 @@ void hfi1_do_send(struct rvt_qp *qp, bool in_thread)
                        return;
                }
                make_req = hfi1_make_rc_req;
-               timeout_int = (qp->timeout_jiffies);
+               ps.timeout_int = qp->timeout_jiffies;
                break;
        case IB_QPT_UC:
                if (!loopback && ((rdma_ah_get_dlid(&qp->remote_ah_attr) &
@@ -854,11 +891,11 @@ void hfi1_do_send(struct rvt_qp *qp, bool in_thread)
                        return;
                }
                make_req = hfi1_make_uc_req;
-               timeout_int = SEND_RESCHED_TIMEOUT;
+               ps.timeout_int = SEND_RESCHED_TIMEOUT;
                break;
        default:
                make_req = hfi1_make_ud_req;
-               timeout_int = SEND_RESCHED_TIMEOUT;
+               ps.timeout_int = SEND_RESCHED_TIMEOUT;
        }
 
        spin_lock_irqsave(&qp->s_lock, ps.flags);
@@ -871,9 +908,11 @@ void hfi1_do_send(struct rvt_qp *qp, bool in_thread)
 
        qp->s_flags |= RVT_S_BUSY;
 
-       timeout = jiffies + (timeout_int) / 8;
-       cpu = priv->s_sde ? priv->s_sde->cpu :
+       ps.timeout_int = ps.timeout_int / 8;
+       ps.timeout = jiffies + ps.timeout_int;
+       ps.cpu = priv->s_sde ? priv->s_sde->cpu :
                        cpumask_first(cpumask_of_node(ps.ppd->dd->node));
+
        /* insure a pre-built packet is handled  */
        ps.s_txreq = get_waiting_verbs_txreq(qp);
        do {
@@ -889,28 +928,9 @@ void hfi1_do_send(struct rvt_qp *qp, bool in_thread)
                        /* Record that s_ahg is empty. */
                        qp->s_hdrwords = 0;
                        /* allow other tasks to run */
-                       if (unlikely(time_after(jiffies, timeout))) {
-                               if (!in_thread ||
-                                   workqueue_congested(
-                                               cpu,
-                                               ps.ppd->hfi1_wq)) {
-                                       spin_lock_irqsave(
-                                               &qp->s_lock,
-                                               ps.flags);
-                                       qp->s_flags &= ~RVT_S_BUSY;
-                                       hfi1_schedule_send(qp);
-                                       spin_unlock_irqrestore(
-                                               &qp->s_lock,
-                                               ps.flags);
-                                       this_cpu_inc(
-                                               *ps.ppd->dd->send_schedule);
-                                       return;
-                               }
-                               cond_resched();
-                               this_cpu_inc(
-                                       *ps.ppd->dd->send_schedule);
-                               timeout = jiffies + (timeout_int) / 8;
-                       }
+                       if (schedule_send_yield(qp, &ps))
+                               return;
+
                        spin_lock_irqsave(&qp->s_lock, ps.flags);
                }
        } while (make_req(qp, &ps));
index 26ae789e47cf9451d7982351152518be2c367112..4eb4cc798035ffd58e23ac3b8719a5e3c9449232 100644 (file)
 
 #define UCTXT_FMT \
        "cred:%u, credaddr:0x%llx, piobase:0x%p, rcvhdr_cnt:%u, "       \
-       "rcvbase:0x%llx, rcvegrc:%u, rcvegrb:0x%llx"
+       "rcvbase:0x%llx, rcvegrc:%u, rcvegrb:0x%llx, subctxt_cnt:%u"
 TRACE_EVENT(hfi1_uctxtdata,
-           TP_PROTO(struct hfi1_devdata *dd, struct hfi1_ctxtdata *uctxt),
-           TP_ARGS(dd, uctxt),
+           TP_PROTO(struct hfi1_devdata *dd, struct hfi1_ctxtdata *uctxt,
+                    unsigned int subctxt),
+           TP_ARGS(dd, uctxt, subctxt),
            TP_STRUCT__entry(DD_DEV_ENTRY(dd)
                             __field(unsigned int, ctxt)
+                            __field(unsigned int, subctxt)
                             __field(u32, credits)
                             __field(u64, hw_free)
                             __field(void __iomem *, piobase)
@@ -70,9 +72,11 @@ TRACE_EVENT(hfi1_uctxtdata,
                             __field(u64, rcvhdrq_dma)
                             __field(u32, eager_cnt)
                             __field(u64, rcvegr_dma)
+                            __field(unsigned int, subctxt_cnt)
                             ),
            TP_fast_assign(DD_DEV_ASSIGN(dd);
                           __entry->ctxt = uctxt->ctxt;
+                          __entry->subctxt = subctxt;
                           __entry->credits = uctxt->sc->credits;
                           __entry->hw_free = le64_to_cpu(*uctxt->sc->hw_free);
                           __entry->piobase = uctxt->sc->base_addr;
@@ -80,17 +84,20 @@ TRACE_EVENT(hfi1_uctxtdata,
                           __entry->rcvhdrq_dma = uctxt->rcvhdrq_dma;
                           __entry->eager_cnt = uctxt->egrbufs.alloced;
                           __entry->rcvegr_dma = uctxt->egrbufs.rcvtids[0].dma;
+                          __entry->subctxt_cnt = uctxt->subctxt_cnt;
                           ),
-           TP_printk("[%s] ctxt %u " UCTXT_FMT,
+           TP_printk("[%s] ctxt %u:%u " UCTXT_FMT,
                      __get_str(dev),
                      __entry->ctxt,
+                     __entry->subctxt,
                      __entry->credits,
                      __entry->hw_free,
                      __entry->piobase,
                      __entry->rcvhdrq_cnt,
                      __entry->rcvhdrq_dma,
                      __entry->eager_cnt,
-                     __entry->rcvegr_dma
+                     __entry->rcvegr_dma,
+                     __entry->subctxt_cnt
                      )
 );
 
index 2c9ac57657d3f031b200b4ca22538f3c10c60607..c59809a7f121a5e9f8cc63036994736dada66037 100644 (file)
@@ -676,6 +676,40 @@ TRACE_EVENT(
        )
 );
 
+DECLARE_EVENT_CLASS(
+       hfi1_do_send_template,
+       TP_PROTO(struct rvt_qp *qp, bool flag),
+       TP_ARGS(qp, flag),
+       TP_STRUCT__entry(
+               DD_DEV_ENTRY(dd_from_ibdev(qp->ibqp.device))
+               __field(u32, qpn)
+               __field(bool, flag)
+       ),
+       TP_fast_assign(
+               DD_DEV_ASSIGN(dd_from_ibdev(qp->ibqp.device))
+               __entry->qpn = qp->ibqp.qp_num;
+               __entry->flag = flag;
+       ),
+       TP_printk(
+               "[%s] qpn %x flag %d",
+               __get_str(dev),
+               __entry->qpn,
+               __entry->flag
+       )
+);
+
+DEFINE_EVENT(
+       hfi1_do_send_template, hfi1_rc_do_send,
+       TP_PROTO(struct rvt_qp *qp, bool flag),
+       TP_ARGS(qp, flag)
+);
+
+DEFINE_EVENT(
+       hfi1_do_send_template, hfi1_rc_expired_time_slice,
+       TP_PROTO(struct rvt_qp *qp, bool flag),
+       TP_ARGS(qp, flag)
+);
+
 #endif /* __HFI1_TRACE_TX_H */
 
 #undef TRACE_INCLUDE_PATH
index 35c6e7ec8ad6beb311b9e8177a09c40ff82b351d..a8f0aa4722f6adfb1e045fc800a5e999ce18a2a3 100644 (file)
@@ -53,7 +53,7 @@
 
 struct tid_group {
        struct list_head list;
-       unsigned base;
+       u32 base;
        u8 size;
        u8 used;
        u8 map;
@@ -82,20 +82,25 @@ struct tid_pageset {
                 (unsigned long)(len) - 1) & PAGE_MASK) -              \
               ((unsigned long)vaddr & PAGE_MASK)) >> PAGE_SHIFT))
 
-static void unlock_exp_tids(struct hfi1_ctxtdata *, struct exp_tid_set *,
-                           struct hfi1_filedata *);
-static u32 find_phys_blocks(struct page **, unsigned, struct tid_pageset *);
-static int set_rcvarray_entry(struct file *, unsigned long, u32,
-                             struct tid_group *, struct page **, unsigned);
-static int tid_rb_insert(void *, struct mmu_rb_node *);
+static void unlock_exp_tids(struct hfi1_ctxtdata *uctxt,
+                           struct exp_tid_set *set,
+                           struct hfi1_filedata *fd);
+static u32 find_phys_blocks(struct page **pages, unsigned npages,
+                           struct tid_pageset *list);
+static int set_rcvarray_entry(struct hfi1_filedata *fd, unsigned long vaddr,
+                             u32 rcventry, struct tid_group *grp,
+                             struct page **pages, unsigned npages);
+static int tid_rb_insert(void *arg, struct mmu_rb_node *node);
 static void cacheless_tid_rb_remove(struct hfi1_filedata *fdata,
                                    struct tid_rb_node *tnode);
-static void tid_rb_remove(void *, struct mmu_rb_node *);
-static int tid_rb_invalidate(void *, struct mmu_rb_node *);
-static int program_rcvarray(struct file *, unsigned long, struct tid_group *,
-                           struct tid_pageset *, unsigned, u16, struct page **,
-                           u32 *, unsigned *, unsigned *);
-static int unprogram_rcvarray(struct file *, u32, struct tid_group **);
+static void tid_rb_remove(void *arg, struct mmu_rb_node *node);
+static int tid_rb_invalidate(void *arg, struct mmu_rb_node *mnode);
+static int program_rcvarray(struct hfi1_filedata *fd, unsigned long vaddr,
+                           struct tid_group *grp, struct tid_pageset *sets,
+                           unsigned start, u16 count, struct page **pages,
+                           u32 *tidlist, unsigned *tididx, unsigned *pmapped);
+static int unprogram_rcvarray(struct hfi1_filedata *fd, u32 tidinfo,
+                             struct tid_group **grp);
 static void clear_tid_node(struct hfi1_filedata *fd, struct tid_rb_node *node);
 
 static struct mmu_rb_ops tid_rb_ops = {
@@ -149,52 +154,60 @@ static inline void tid_group_move(struct tid_group *group,
        tid_group_add_tail(group, s2);
 }
 
+int hfi1_user_exp_rcv_grp_init(struct hfi1_filedata *fd)
+{
+       struct hfi1_ctxtdata *uctxt = fd->uctxt;
+       struct hfi1_devdata *dd = fd->dd;
+       u32 tidbase;
+       u32 i;
+       struct tid_group *grp, *gptr;
+
+       exp_tid_group_init(&uctxt->tid_group_list);
+       exp_tid_group_init(&uctxt->tid_used_list);
+       exp_tid_group_init(&uctxt->tid_full_list);
+
+       tidbase = uctxt->expected_base;
+       for (i = 0; i < uctxt->expected_count /
+                    dd->rcv_entries.group_size; i++) {
+               grp = kzalloc(sizeof(*grp), GFP_KERNEL);
+               if (!grp)
+                       goto grp_failed;
+
+               grp->size = dd->rcv_entries.group_size;
+               grp->base = tidbase;
+               tid_group_add_tail(grp, &uctxt->tid_group_list);
+               tidbase += dd->rcv_entries.group_size;
+       }
+
+       return 0;
+
+grp_failed:
+       list_for_each_entry_safe(grp, gptr, &uctxt->tid_group_list.list,
+                                list) {
+               list_del_init(&grp->list);
+               kfree(grp);
+       }
+
+       return -ENOMEM;
+}
+
 /*
  * Initialize context and file private data needed for Expected
  * receive caching. This needs to be done after the context has
  * been configured with the eager/expected RcvEntry counts.
  */
-int hfi1_user_exp_rcv_init(struct file *fp)
+int hfi1_user_exp_rcv_init(struct hfi1_filedata *fd)
 {
-       struct hfi1_filedata *fd = fp->private_data;
        struct hfi1_ctxtdata *uctxt = fd->uctxt;
        struct hfi1_devdata *dd = uctxt->dd;
-       unsigned tidbase;
-       int i, ret = 0;
+       int ret = 0;
 
        spin_lock_init(&fd->tid_lock);
        spin_lock_init(&fd->invalid_lock);
 
-       if (!uctxt->subctxt_cnt || !fd->subctxt) {
-               exp_tid_group_init(&uctxt->tid_group_list);
-               exp_tid_group_init(&uctxt->tid_used_list);
-               exp_tid_group_init(&uctxt->tid_full_list);
-
-               tidbase = uctxt->expected_base;
-               for (i = 0; i < uctxt->expected_count /
-                            dd->rcv_entries.group_size; i++) {
-                       struct tid_group *grp;
-
-                       grp = kzalloc(sizeof(*grp), GFP_KERNEL);
-                       if (!grp) {
-                               /*
-                                * If we fail here, the groups already
-                                * allocated will be freed by the close
-                                * call.
-                                */
-                               ret = -ENOMEM;
-                               goto done;
-                       }
-                       grp->size = dd->rcv_entries.group_size;
-                       grp->base = tidbase;
-                       tid_group_add_tail(grp, &uctxt->tid_group_list);
-                       tidbase += dd->rcv_entries.group_size;
-               }
-       }
-
        fd->entry_to_rb = kcalloc(uctxt->expected_count,
-                                    sizeof(struct rb_node *),
-                                    GFP_KERNEL);
+                                 sizeof(struct rb_node *),
+                                 GFP_KERNEL);
        if (!fd->entry_to_rb)
                return -ENOMEM;
 
@@ -204,8 +217,9 @@ int hfi1_user_exp_rcv_init(struct file *fp)
                                           sizeof(*fd->invalid_tids),
                                           GFP_KERNEL);
                if (!fd->invalid_tids) {
-                       ret = -ENOMEM;
-                       goto done;
+                       kfree(fd->entry_to_rb);
+                       fd->entry_to_rb = NULL;
+                       return -ENOMEM;
                }
 
                /*
@@ -248,41 +262,44 @@ int hfi1_user_exp_rcv_init(struct file *fp)
                fd->tid_limit = uctxt->expected_count;
        }
        spin_unlock(&fd->tid_lock);
-done:
+
        return ret;
 }
 
-int hfi1_user_exp_rcv_free(struct hfi1_filedata *fd)
+void hfi1_user_exp_rcv_grp_free(struct hfi1_ctxtdata *uctxt)
 {
-       struct hfi1_ctxtdata *uctxt = fd->uctxt;
        struct tid_group *grp, *gptr;
 
-       if (!test_bit(HFI1_CTXT_SETUP_DONE, &uctxt->event_flags))
-               return 0;
+       list_for_each_entry_safe(grp, gptr, &uctxt->tid_group_list.list,
+                                list) {
+               list_del_init(&grp->list);
+               kfree(grp);
+       }
+       hfi1_clear_tids(uctxt);
+}
+
+void hfi1_user_exp_rcv_free(struct hfi1_filedata *fd)
+{
+       struct hfi1_ctxtdata *uctxt = fd->uctxt;
+
        /*
         * The notifier would have been removed when the process'es mm
         * was freed.
         */
-       if (fd->handler)
+       if (fd->handler) {
                hfi1_mmu_rb_unregister(fd->handler);
-
-       kfree(fd->invalid_tids);
-
-       if (!uctxt->cnt) {
+       } else {
                if (!EXP_TID_SET_EMPTY(uctxt->tid_full_list))
                        unlock_exp_tids(uctxt, &uctxt->tid_full_list, fd);
                if (!EXP_TID_SET_EMPTY(uctxt->tid_used_list))
                        unlock_exp_tids(uctxt, &uctxt->tid_used_list, fd);
-               list_for_each_entry_safe(grp, gptr, &uctxt->tid_group_list.list,
-                                        list) {
-                       list_del_init(&grp->list);
-                       kfree(grp);
-               }
-               hfi1_clear_tids(uctxt);
        }
 
+       kfree(fd->invalid_tids);
+       fd->invalid_tids = NULL;
+
        kfree(fd->entry_to_rb);
-       return 0;
+       fd->entry_to_rb = NULL;
 }
 
 /*
@@ -351,10 +368,10 @@ static inline void rcv_array_wc_fill(struct hfi1_devdata *dd, u32 index)
  *          can fit into the group. If the group becomes fully
  *          used, move it to tid_full_list.
  */
-int hfi1_user_exp_rcv_setup(struct file *fp, struct hfi1_tid_info *tinfo)
+int hfi1_user_exp_rcv_setup(struct hfi1_filedata *fd,
+                           struct hfi1_tid_info *tinfo)
 {
        int ret = 0, need_group = 0, pinned;
-       struct hfi1_filedata *fd = fp->private_data;
        struct hfi1_ctxtdata *uctxt = fd->uctxt;
        struct hfi1_devdata *dd = uctxt->dd;
        unsigned npages, ngroups, pageidx = 0, pageset_count, npagesets,
@@ -451,7 +468,7 @@ int hfi1_user_exp_rcv_setup(struct file *fp, struct hfi1_tid_info *tinfo)
                struct tid_group *grp =
                        tid_group_pop(&uctxt->tid_group_list);
 
-               ret = program_rcvarray(fp, vaddr, grp, pagesets,
+               ret = program_rcvarray(fd, vaddr, grp, pagesets,
                                       pageidx, dd->rcv_entries.group_size,
                                       pages, tidlist, &tididx, &mapped);
                /*
@@ -497,7 +514,7 @@ int hfi1_user_exp_rcv_setup(struct file *fp, struct hfi1_tid_info *tinfo)
                        unsigned use = min_t(unsigned, pageset_count - pageidx,
                                             grp->size - grp->used);
 
-                       ret = program_rcvarray(fp, vaddr, grp, pagesets,
+                       ret = program_rcvarray(fd, vaddr, grp, pagesets,
                                               pageidx, use, pages, tidlist,
                                               &tididx, &mapped);
                        if (ret < 0) {
@@ -547,7 +564,7 @@ nomem:
                         * everything done so far so we don't leak resources.
                         */
                        tinfo->tidlist = (unsigned long)&tidlist;
-                       hfi1_user_exp_rcv_clear(fp, tinfo);
+                       hfi1_user_exp_rcv_clear(fd, tinfo);
                        tinfo->tidlist = 0;
                        ret = -EFAULT;
                        goto bail;
@@ -571,10 +588,10 @@ bail:
        return ret > 0 ? 0 : ret;
 }
 
-int hfi1_user_exp_rcv_clear(struct file *fp, struct hfi1_tid_info *tinfo)
+int hfi1_user_exp_rcv_clear(struct hfi1_filedata *fd,
+                           struct hfi1_tid_info *tinfo)
 {
        int ret = 0;
-       struct hfi1_filedata *fd = fp->private_data;
        struct hfi1_ctxtdata *uctxt = fd->uctxt;
        u32 *tidinfo;
        unsigned tididx;
@@ -589,7 +606,7 @@ int hfi1_user_exp_rcv_clear(struct file *fp, struct hfi1_tid_info *tinfo)
 
        mutex_lock(&uctxt->exp_lock);
        for (tididx = 0; tididx < tinfo->tidcnt; tididx++) {
-               ret = unprogram_rcvarray(fp, tidinfo[tididx], NULL);
+               ret = unprogram_rcvarray(fd, tidinfo[tididx], NULL);
                if (ret) {
                        hfi1_cdbg(TID, "Failed to unprogram rcv array %d",
                                  ret);
@@ -606,9 +623,9 @@ int hfi1_user_exp_rcv_clear(struct file *fp, struct hfi1_tid_info *tinfo)
        return ret;
 }
 
-int hfi1_user_exp_rcv_invalid(struct file *fp, struct hfi1_tid_info *tinfo)
+int hfi1_user_exp_rcv_invalid(struct hfi1_filedata *fd,
+                             struct hfi1_tid_info *tinfo)
 {
-       struct hfi1_filedata *fd = fp->private_data;
        struct hfi1_ctxtdata *uctxt = fd->uctxt;
        unsigned long *ev = uctxt->dd->events +
                (((uctxt->ctxt - uctxt->dd->first_dyn_alloc_ctxt) *
@@ -723,7 +740,7 @@ static u32 find_phys_blocks(struct page **pages, unsigned npages,
 
 /**
  * program_rcvarray() - program an RcvArray group with receive buffers
- * @fp: file pointer
+ * @fd: filedata pointer
  * @vaddr: starting user virtual address
  * @grp: RcvArray group
  * @sets: array of struct tid_pageset holding information on physically
@@ -748,13 +765,12 @@ static u32 find_phys_blocks(struct page **pages, unsigned npages,
  * -ENOMEM or -EFAULT on error from set_rcvarray_entry(), or
  * number of RcvArray entries programmed.
  */
-static int program_rcvarray(struct file *fp, unsigned long vaddr,
+static int program_rcvarray(struct hfi1_filedata *fd, unsigned long vaddr,
                            struct tid_group *grp,
                            struct tid_pageset *sets,
                            unsigned start, u16 count, struct page **pages,
                            u32 *tidlist, unsigned *tididx, unsigned *pmapped)
 {
-       struct hfi1_filedata *fd = fp->private_data;
        struct hfi1_ctxtdata *uctxt = fd->uctxt;
        struct hfi1_devdata *dd = uctxt->dd;
        u16 idx;
@@ -795,7 +811,7 @@ static int program_rcvarray(struct file *fp, unsigned long vaddr,
                npages = sets[setidx].count;
                pageidx = sets[setidx].idx;
 
-               ret = set_rcvarray_entry(fp, vaddr + (pageidx * PAGE_SIZE),
+               ret = set_rcvarray_entry(fd, vaddr + (pageidx * PAGE_SIZE),
                                         rcventry, grp, pages + pageidx,
                                         npages);
                if (ret)
@@ -817,12 +833,11 @@ static int program_rcvarray(struct file *fp, unsigned long vaddr,
        return idx;
 }
 
-static int set_rcvarray_entry(struct file *fp, unsigned long vaddr,
+static int set_rcvarray_entry(struct hfi1_filedata *fd, unsigned long vaddr,
                              u32 rcventry, struct tid_group *grp,
                              struct page **pages, unsigned npages)
 {
        int ret;
-       struct hfi1_filedata *fd = fp->private_data;
        struct hfi1_ctxtdata *uctxt = fd->uctxt;
        struct tid_rb_node *node;
        struct hfi1_devdata *dd = uctxt->dd;
@@ -876,10 +891,9 @@ static int set_rcvarray_entry(struct file *fp, unsigned long vaddr,
        return 0;
 }
 
-static int unprogram_rcvarray(struct file *fp, u32 tidinfo,
+static int unprogram_rcvarray(struct hfi1_filedata *fd, u32 tidinfo,
                              struct tid_group **grp)
 {
-       struct hfi1_filedata *fd = fp->private_data;
        struct hfi1_ctxtdata *uctxt = fd->uctxt;
        struct hfi1_devdata *dd = uctxt->dd;
        struct tid_rb_node *node;
index 9bc8d9fba87ee1dc00156483fc615c412a5fe575..5250c897298ded7b0004b09d07cc138182f7822d 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef _HFI1_USER_EXP_RCV_H
 #define _HFI1_USER_EXP_RCV_H
 /*
- * Copyright(c) 2015, 2016 Intel Corporation.
+ * Copyright(c) 2015 - 2017 Intel Corporation.
  *
  * This file is provided under a dual BSD/GPLv2 license.  When using or
  * redistributing this file, you may do so under either license.
                (tid) |= EXP_TID_SET(field, (value));                   \
        } while (0)
 
-int hfi1_user_exp_rcv_init(struct file *);
-int hfi1_user_exp_rcv_free(struct hfi1_filedata *);
-int hfi1_user_exp_rcv_setup(struct file *, struct hfi1_tid_info *);
-int hfi1_user_exp_rcv_clear(struct file *, struct hfi1_tid_info *);
-int hfi1_user_exp_rcv_invalid(struct file *, struct hfi1_tid_info *);
+void hfi1_user_exp_rcv_grp_free(struct hfi1_ctxtdata *uctxt);
+int hfi1_user_exp_rcv_grp_init(struct hfi1_filedata *fd);
+int hfi1_user_exp_rcv_init(struct hfi1_filedata *fd);
+void hfi1_user_exp_rcv_free(struct hfi1_filedata *fd);
+int hfi1_user_exp_rcv_setup(struct hfi1_filedata *fd,
+                           struct hfi1_tid_info *tinfo);
+int hfi1_user_exp_rcv_clear(struct hfi1_filedata *fd,
+                           struct hfi1_tid_info *tinfo);
+int hfi1_user_exp_rcv_invalid(struct hfi1_filedata *fd,
+                             struct hfi1_tid_info *tinfo);
 
 #endif /* _HFI1_USER_EXP_RCV_H */
index 0749689d76439f7ac95efdfceb04c5299bd80f26..d55339f5d73ba67b83feeead1a5a5d27d63b064e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright(c) 2015, 2016 Intel Corporation.
+ * Copyright(c) 2015 - 2017 Intel Corporation.
  *
  * This file is provided under a dual BSD/GPLv2 license.  When using or
  * redistributing this file, you may do so under either license.
@@ -143,7 +143,9 @@ MODULE_PARM_DESC(sdma_comp_size, "Size of User SDMA completion ring. Default: 12
 
 /* KDETH OM multipliers and switch over point */
 #define KDETH_OM_SMALL     4
+#define KDETH_OM_SMALL_SHIFT     2
 #define KDETH_OM_LARGE     64
+#define KDETH_OM_LARGE_SHIFT     6
 #define KDETH_OM_MAX_SIZE  (1 << ((KDETH_OM_LARGE / KDETH_OM_SMALL) + 1))
 
 /* Tx request flag bits */
@@ -153,9 +155,8 @@ MODULE_PARM_DESC(sdma_comp_size, "Size of User SDMA completion ring. Default: 12
 /* SDMA request flag bits */
 #define SDMA_REQ_FOR_THREAD 1
 #define SDMA_REQ_SEND_DONE  2
-#define SDMA_REQ_HAVE_AHG   3
-#define SDMA_REQ_HAS_ERROR  4
-#define SDMA_REQ_DONE_ERROR 5
+#define SDMA_REQ_HAS_ERROR  3
+#define SDMA_REQ_DONE_ERROR 4
 
 #define SDMA_PKT_Q_INACTIVE BIT(0)
 #define SDMA_PKT_Q_ACTIVE   BIT(1)
@@ -214,7 +215,7 @@ struct user_sdma_request {
         * each request will need it's own engine pointer.
         */
        struct sdma_engine *sde;
-       u8 ahg_idx;
+       s8 ahg_idx;
        u32 ahg[9];
        /*
         * KDETH.Offset (Eager) field
@@ -228,12 +229,6 @@ struct user_sdma_request {
         * size of the TID entry.
         */
        u32 tidoffset;
-       /*
-        * KDETH.OM
-        * Remember this because the header template always sets it
-        * to 0.
-        */
-       u8 omfactor;
        /*
         * We copy the iovs for this request (based on
         * info.iovcnt). These are only the data vectors
@@ -284,39 +279,43 @@ struct user_sdma_txreq {
        hfi1_cdbg(SDMA, "[%u:%u:%u] " fmt, (pq)->dd->unit, (pq)->ctxt, \
                 (pq)->subctxt, ##__VA_ARGS__)
 
-static int user_sdma_send_pkts(struct user_sdma_request *, unsigned);
-static int num_user_pages(const struct iovec *);
-static void user_sdma_txreq_cb(struct sdma_txreq *, int);
-static inline void pq_update(struct hfi1_user_sdma_pkt_q *);
-static void user_sdma_free_request(struct user_sdma_request *, bool);
-static int pin_vector_pages(struct user_sdma_request *,
-                           struct user_sdma_iovec *);
-static void unpin_vector_pages(struct mm_struct *, struct page **, unsigned,
-                              unsigned);
-static int check_header_template(struct user_sdma_request *,
-                                struct hfi1_pkt_header *, u32, u32);
-static int set_txreq_header(struct user_sdma_request *,
-                           struct user_sdma_txreq *, u32);
-static int set_txreq_header_ahg(struct user_sdma_request *,
-                               struct user_sdma_txreq *, u32);
-static inline void set_comp_state(struct hfi1_user_sdma_pkt_q *,
-                                 struct hfi1_user_sdma_comp_q *,
-                                 u16, enum hfi1_sdma_comp_state, int);
-static inline u32 set_pkt_bth_psn(__be32, u8, u32);
+static int user_sdma_send_pkts(struct user_sdma_request *req,
+                              unsigned maxpkts);
+static int num_user_pages(const struct iovec *iov);
+static void user_sdma_txreq_cb(struct sdma_txreq *txreq, int status);
+static inline void pq_update(struct hfi1_user_sdma_pkt_q *pq);
+static void user_sdma_free_request(struct user_sdma_request *req, bool unpin);
+static int pin_vector_pages(struct user_sdma_request *req,
+                           struct user_sdma_iovec *iovec);
+static void unpin_vector_pages(struct mm_struct *mm, struct page **pages,
+                              unsigned start, unsigned npages);
+static int check_header_template(struct user_sdma_request *req,
+                                struct hfi1_pkt_header *hdr, u32 lrhlen,
+                                u32 datalen);
+static int set_txreq_header(struct user_sdma_request *req,
+                           struct user_sdma_txreq *tx, u32 datalen);
+static int set_txreq_header_ahg(struct user_sdma_request *req,
+                               struct user_sdma_txreq *tx, u32 len);
+static inline void set_comp_state(struct hfi1_user_sdma_pkt_q *pq,
+                                 struct hfi1_user_sdma_comp_q *cq,
+                                 u16 idx, enum hfi1_sdma_comp_state state,
+                                 int ret);
+static inline u32 set_pkt_bth_psn(__be32 bthpsn, u8 expct, u32 frags);
 static inline u32 get_lrh_len(struct hfi1_pkt_header, u32 len);
 
 static int defer_packet_queue(
-       struct sdma_engine *,
-       struct iowait *,
-       struct sdma_txreq *,
-       unsigned seq);
-static void activate_packet_queue(struct iowait *, int);
-static bool sdma_rb_filter(struct mmu_rb_node *, unsigned long, unsigned long);
-static int sdma_rb_insert(void *, struct mmu_rb_node *);
+       struct sdma_engine *sde,
+       struct iowait *wait,
+       struct sdma_txreq *txreq,
+       unsigned int seq);
+static void activate_packet_queue(struct iowait *wait, int reason);
+static bool sdma_rb_filter(struct mmu_rb_node *node, unsigned long addr,
+                          unsigned long len);
+static int sdma_rb_insert(void *arg, struct mmu_rb_node *mnode);
 static int sdma_rb_evict(void *arg, struct mmu_rb_node *mnode,
                         void *arg2, bool *stop);
-static void sdma_rb_remove(void *, struct mmu_rb_node *);
-static int sdma_rb_invalidate(void *, struct mmu_rb_node *);
+static void sdma_rb_remove(void *arg, struct mmu_rb_node *mnode);
+static int sdma_rb_invalidate(void *arg, struct mmu_rb_node *mnode);
 
 static struct mmu_rb_ops sdma_rb_ops = {
        .filter = sdma_rb_filter,
@@ -372,45 +371,27 @@ static void sdma_kmem_cache_ctor(void *obj)
        memset(tx, 0, sizeof(*tx));
 }
 
-int hfi1_user_sdma_alloc_queues(struct hfi1_ctxtdata *uctxt, struct file *fp)
+int hfi1_user_sdma_alloc_queues(struct hfi1_ctxtdata *uctxt,
+                               struct hfi1_filedata *fd)
 {
-       struct hfi1_filedata *fd;
-       int ret = 0;
+       int ret = -ENOMEM;
        char buf[64];
        struct hfi1_devdata *dd;
        struct hfi1_user_sdma_comp_q *cq;
        struct hfi1_user_sdma_pkt_q *pq;
        unsigned long flags;
 
-       if (!uctxt || !fp) {
-               ret = -EBADF;
-               goto done;
-       }
-
-       fd = fp->private_data;
+       if (!uctxt || !fd)
+               return -EBADF;
 
-       if (!hfi1_sdma_comp_ring_size) {
-               ret = -EINVAL;
-               goto done;
-       }
+       if (!hfi1_sdma_comp_ring_size)
+               return -EINVAL;
 
        dd = uctxt->dd;
 
        pq = kzalloc(sizeof(*pq), GFP_KERNEL);
        if (!pq)
-               goto pq_nomem;
-
-       pq->reqs = kcalloc(hfi1_sdma_comp_ring_size,
-                          sizeof(*pq->reqs),
-                          GFP_KERNEL);
-       if (!pq->reqs)
-               goto pq_reqs_nomem;
-
-       pq->req_in_use = kcalloc(BITS_TO_LONGS(hfi1_sdma_comp_ring_size),
-                                sizeof(*pq->req_in_use),
-                                GFP_KERNEL);
-       if (!pq->req_in_use)
-               goto pq_reqs_no_in_use;
+               return -ENOMEM;
 
        INIT_LIST_HEAD(&pq->list);
        pq->dd = dd;
@@ -426,10 +407,23 @@ int hfi1_user_sdma_alloc_queues(struct hfi1_ctxtdata *uctxt, struct file *fp)
        iowait_init(&pq->busy, 0, NULL, defer_packet_queue,
                    activate_packet_queue, NULL);
        pq->reqidx = 0;
+
+       pq->reqs = kcalloc(hfi1_sdma_comp_ring_size,
+                          sizeof(*pq->reqs),
+                          GFP_KERNEL);
+       if (!pq->reqs)
+               goto pq_reqs_nomem;
+
+       pq->req_in_use = kcalloc(BITS_TO_LONGS(hfi1_sdma_comp_ring_size),
+                                sizeof(*pq->req_in_use),
+                                GFP_KERNEL);
+       if (!pq->req_in_use)
+               goto pq_reqs_no_in_use;
+
        snprintf(buf, 64, "txreq-kmem-cache-%u-%u-%u", dd->unit, uctxt->ctxt,
                 fd->subctxt);
        pq->txreq_cache = kmem_cache_create(buf,
-                              sizeof(struct user_sdma_txreq),
+                                           sizeof(struct user_sdma_txreq),
                                            L1_CACHE_BYTES,
                                            SLAB_HWCACHE_ALIGN,
                                            sdma_kmem_cache_ctor);
@@ -438,7 +432,7 @@ int hfi1_user_sdma_alloc_queues(struct hfi1_ctxtdata *uctxt, struct file *fp)
                           uctxt->ctxt);
                goto pq_txreq_nomem;
        }
-       fd->pq = pq;
+
        cq = kzalloc(sizeof(*cq), GFP_KERNEL);
        if (!cq)
                goto cq_nomem;
@@ -449,20 +443,25 @@ int hfi1_user_sdma_alloc_queues(struct hfi1_ctxtdata *uctxt, struct file *fp)
                goto cq_comps_nomem;
 
        cq->nentries = hfi1_sdma_comp_ring_size;
-       fd->cq = cq;
 
        ret = hfi1_mmu_rb_register(pq, pq->mm, &sdma_rb_ops, dd->pport->hfi1_wq,
                                   &pq->handler);
        if (ret) {
                dd_dev_err(dd, "Failed to register with MMU %d", ret);
-               goto done;
+               goto pq_mmu_fail;
        }
 
+       fd->pq = pq;
+       fd->cq = cq;
+
        spin_lock_irqsave(&uctxt->sdma_qlock, flags);
        list_add(&pq->list, &uctxt->sdma_queues);
        spin_unlock_irqrestore(&uctxt->sdma_qlock, flags);
-       goto done;
 
+       return 0;
+
+pq_mmu_fail:
+       vfree(cq->comps);
 cq_comps_nomem:
        kfree(cq);
 cq_nomem:
@@ -473,10 +472,7 @@ pq_reqs_no_in_use:
        kfree(pq->reqs);
 pq_reqs_nomem:
        kfree(pq);
-       fd->pq = NULL;
-pq_nomem:
-       ret = -ENOMEM;
-done:
+
        return ret;
 }
 
@@ -536,11 +532,11 @@ static u8 dlid_to_selector(u16 dlid)
        return mapping[hash];
 }
 
-int hfi1_user_sdma_process_request(struct file *fp, struct iovec *iovec,
-                                  unsigned long dim, unsigned long *count)
+int hfi1_user_sdma_process_request(struct hfi1_filedata *fd,
+                                  struct iovec *iovec, unsigned long dim,
+                                  unsigned long *count)
 {
        int ret = 0, i;
-       struct hfi1_filedata *fd = fp->private_data;
        struct hfi1_ctxtdata *uctxt = fd->uctxt;
        struct hfi1_user_sdma_pkt_q *pq = fd->pq;
        struct hfi1_user_sdma_comp_q *cq = fd->cq;
@@ -616,6 +612,7 @@ int hfi1_user_sdma_process_request(struct file *fp, struct iovec *iovec,
        req->pq = pq;
        req->cq = cq;
        req->status = -1;
+       req->ahg_idx = -1;
        INIT_LIST_HEAD(&req->txps);
 
        memcpy(&req->info, &info, sizeof(info));
@@ -766,14 +763,8 @@ int hfi1_user_sdma_process_request(struct file *fp, struct iovec *iovec,
        }
 
        /* We don't need an AHG entry if the request contains only one packet */
-       if (req->info.npkts > 1 && HFI1_CAP_IS_USET(SDMA_AHG)) {
-               int ahg = sdma_ahg_alloc(req->sde);
-
-               if (likely(ahg >= 0)) {
-                       req->ahg_idx = (u8)ahg;
-                       set_bit(SDMA_REQ_HAVE_AHG, &req->flags);
-               }
-       }
+       if (req->info.npkts > 1 && HFI1_CAP_IS_USET(SDMA_AHG))
+               req->ahg_idx = sdma_ahg_alloc(req->sde);
 
        set_comp_state(pq, cq, info.comp_idx, QUEUED, 0);
        atomic_inc(&pq->n_reqs);
@@ -991,7 +982,7 @@ static int user_sdma_send_pkts(struct user_sdma_request *req, unsigned maxpkts)
                        }
                }
 
-               if (test_bit(SDMA_REQ_HAVE_AHG, &req->flags)) {
+               if (req->ahg_idx >= 0) {
                        if (!req->seqnum) {
                                u16 pbclen = le16_to_cpu(req->hdr.pbc[0]);
                                u32 lrhlen = get_lrh_len(req->hdr,
@@ -1121,7 +1112,7 @@ dosend:
                 * happen due to the sequential manner in which
                 * descriptors are processed.
                 */
-               if (test_bit(SDMA_REQ_HAVE_AHG, &req->flags))
+               if (req->ahg_idx >= 0)
                        sdma_ahg_free(req->sde, req->ahg_idx);
        }
        return ret;
@@ -1323,6 +1314,7 @@ static int set_txreq_header(struct user_sdma_request *req,
 {
        struct hfi1_user_sdma_pkt_q *pq = req->pq;
        struct hfi1_pkt_header *hdr = &tx->hdr;
+       u8 omfactor; /* KDETH.OM */
        u16 pbclen;
        int ret;
        u32 tidval = 0, lrhlen = get_lrh_len(*hdr, pad_len(datalen));
@@ -1400,8 +1392,9 @@ static int set_txreq_header(struct user_sdma_request *req,
                        }
                        tidval = req->tids[req->tididx];
                }
-               req->omfactor = EXP_TID_GET(tidval, LEN) * PAGE_SIZE >=
-                       KDETH_OM_MAX_SIZE ? KDETH_OM_LARGE : KDETH_OM_SMALL;
+               omfactor = EXP_TID_GET(tidval, LEN) * PAGE_SIZE >=
+                       KDETH_OM_MAX_SIZE ? KDETH_OM_LARGE_SHIFT :
+                       KDETH_OM_SMALL_SHIFT;
                /* Set KDETH.TIDCtrl based on value for this TID. */
                KDETH_SET(hdr->kdeth.ver_tid_offset, TIDCTRL,
                          EXP_TID_GET(tidval, CTRL));
@@ -1416,12 +1409,12 @@ static int set_txreq_header(struct user_sdma_request *req,
                 * transfer.
                 */
                SDMA_DBG(req, "TID offset %ubytes %uunits om%u",
-                        req->tidoffset, req->tidoffset / req->omfactor,
-                        req->omfactor != KDETH_OM_SMALL);
+                        req->tidoffset, req->tidoffset >> omfactor,
+                        omfactor != KDETH_OM_SMALL_SHIFT);
                KDETH_SET(hdr->kdeth.ver_tid_offset, OFFSET,
-                         req->tidoffset / req->omfactor);
+                         req->tidoffset >> omfactor);
                KDETH_SET(hdr->kdeth.ver_tid_offset, OM,
-                         req->omfactor != KDETH_OM_SMALL);
+                         omfactor != KDETH_OM_SMALL_SHIFT);
        }
 done:
        trace_hfi1_sdma_user_header(pq->dd, pq->ctxt, pq->subctxt,
@@ -1433,6 +1426,7 @@ static int set_txreq_header_ahg(struct user_sdma_request *req,
                                struct user_sdma_txreq *tx, u32 len)
 {
        int diff = 0;
+       u8 omfactor; /* KDETH.OM */
        struct hfi1_user_sdma_pkt_q *pq = req->pq;
        struct hfi1_pkt_header *hdr = &req->hdr;
        u16 pbclen = le16_to_cpu(hdr->pbc[0]);
@@ -1484,14 +1478,15 @@ static int set_txreq_header_ahg(struct user_sdma_request *req,
                        }
                        tidval = req->tids[req->tididx];
                }
-               req->omfactor = ((EXP_TID_GET(tidval, LEN) *
+               omfactor = ((EXP_TID_GET(tidval, LEN) *
                                  PAGE_SIZE) >=
-                                KDETH_OM_MAX_SIZE) ? KDETH_OM_LARGE :
-                       KDETH_OM_SMALL;
+                                KDETH_OM_MAX_SIZE) ? KDETH_OM_LARGE_SHIFT :
+                                KDETH_OM_SMALL_SHIFT;
                /* KDETH.OM and KDETH.OFFSET (TID) */
                AHG_HEADER_SET(req->ahg, diff, 7, 0, 16,
-                              ((!!(req->omfactor - KDETH_OM_SMALL)) << 15 |
-                               ((req->tidoffset / req->omfactor) & 0x7fff)));
+                              ((!!(omfactor - KDETH_OM_SMALL_SHIFT)) << 15 |
+                               ((req->tidoffset >> omfactor)
+                                & 0x7fff)));
                /* KDETH.TIDCtrl, KDETH.TID, KDETH.Intr, KDETH.SH */
                val = cpu_to_le16(((EXP_TID_GET(tidval, CTRL) & 0x3) << 10) |
                                   (EXP_TID_GET(tidval, IDX) & 0x3ff));
index 39001714f5517ecc8c2e74a4769a589d7e6ee06a..e5b10aefe212ae08113854ea4dce4180189b524e 100644 (file)
@@ -1,5 +1,7 @@
+#ifndef _HFI1_USER_SDMA_H
+#define _HFI1_USER_SDMA_H
 /*
- * Copyright(c) 2015, 2016 Intel Corporation.
+ * Copyright(c) 2015 - 2017 Intel Corporation.
  *
  * This file is provided under a dual BSD/GPLv2 license.  When using or
  * redistributing this file, you may do so under either license.
@@ -56,7 +58,7 @@ extern uint extended_psn;
 struct hfi1_user_sdma_pkt_q {
        struct list_head list;
        unsigned ctxt;
-       unsigned subctxt;
+       u16 subctxt;
        u16 n_max_reqs;
        atomic_t n_reqs;
        u16 reqidx;
@@ -78,7 +80,11 @@ struct hfi1_user_sdma_comp_q {
        struct hfi1_sdma_comp_entry *comps;
 };
 
-int hfi1_user_sdma_alloc_queues(struct hfi1_ctxtdata *, struct file *);
-int hfi1_user_sdma_free_queues(struct hfi1_filedata *);
-int hfi1_user_sdma_process_request(struct file *, struct iovec *, unsigned long,
-                                  unsigned long *);
+int hfi1_user_sdma_alloc_queues(struct hfi1_ctxtdata *uctxt,
+                               struct hfi1_filedata *fd);
+int hfi1_user_sdma_free_queues(struct hfi1_filedata *fd);
+int hfi1_user_sdma_process_request(struct hfi1_filedata *fd,
+                                  struct iovec *iovec, unsigned long dim,
+                                  unsigned long *count);
+
+#endif /* _HFI1_USER_SDMA_H */
index 52ff275caf540f3b7928e6e85d995784db59aef8..cd635d0c1d3b32eb8fbd3a0303e03f532eca4a09 100644 (file)
@@ -125,7 +125,6 @@ struct hfi1_qp_priv {
        struct sdma_engine *s_sde;                /* current sde */
        struct send_context *s_sendcontext;       /* current sendcontext */
        u8 s_sc;                                  /* SC[0..4] for next packet */
-       u8 r_adefered;                            /* number of acks defered */
        struct iowait s_iowait;
        struct rvt_qp *owner;
 };
@@ -140,6 +139,10 @@ struct hfi1_pkt_state {
        struct hfi1_pportdata *ppd;
        struct verbs_txreq *s_txreq;
        unsigned long flags;
+       unsigned long timeout;
+       unsigned long timeout_int;
+       int cpu;
+       bool in_thread;
 };
 
 #define HFI1_PSN_CREDIT  16
index 392f4d57f3e3748c31f064552e53742abef01f37..b601c2929f8f1afd78a16609b297de7afdc86ff3 100644 (file)
@@ -67,9 +67,7 @@ static int setup_vnic_ctxt(struct hfi1_devdata *dd, struct hfi1_ctxtdata *uctxt)
        unsigned int rcvctrl_ops = 0;
        int ret;
 
-       ret = hfi1_init_ctxt(uctxt->sc);
-       if (ret)
-               goto done;
+       hfi1_init_ctxt(uctxt->sc);
 
        uctxt->do_interrupt = &handle_receive_interrupt;
 
@@ -82,8 +80,6 @@ static int setup_vnic_ctxt(struct hfi1_devdata *dd, struct hfi1_ctxtdata *uctxt)
        if (ret)
                goto done;
 
-       set_bit(HFI1_CTXT_SETUP_DONE, &uctxt->event_flags);
-
        if (uctxt->rcvhdrtail_kvaddr)
                clear_rcvhdrtail(uctxt);
 
@@ -209,7 +205,7 @@ static void deallocate_vnic_ctxt(struct hfi1_devdata *dd,
        uctxt->event_flags = 0;
 
        hfi1_clear_tids(uctxt);
-       hfi1_clear_ctxt_pkey(dd, uctxt->ctxt);
+       hfi1_clear_ctxt_pkey(dd, uctxt);
 
        hfi1_stats.sps_ctxts--;
        hfi1_free_ctxtdata(dd, uctxt);
index 014c8262bfff055f3e480eee53f64e4bb8e9ee89..37d5d29597a449d23bf34587024b83e4c55bb657 100644 (file)
@@ -1721,7 +1721,7 @@ int hns_roce_v1_write_mtpt(void *mb_buf, struct hns_roce_mr *mr,
        roce_set_field(mpt_entry->mpt_byte_64, MPT_BYTE_64_L_KEY_IDX_H_M,
                       MPT_BYTE_64_L_KEY_IDX_H_S, mtpt_idx >> MTPT_IDX_SHIFT);
 
-       /* DMA momery regsiter */
+       /* DMA memory register */
        if (mr->type == MR_TYPE_DMA)
                return 0;
 
index dc5c97c8f070c9c02ac79fb8d51211df5271ee3b..80fc01ffd8bdd48d552b4919a7eda668efe98fa4 100644 (file)
@@ -205,7 +205,7 @@ int hns_roce_mtt_init(struct hns_roce_dev *hr_dev, int npages, int page_shift,
                return 0;
        }
 
-       /* Note: if page_shift is zero, FAST memory regsiter */
+       /* Note: if page_shift is zero, FAST memory register */
        mtt->page_shift = page_shift;
 
        /* Compute MTT entry necessary */
index 9f3ba320ce70ee245ffcfb5242037cd1560f6e9f..d45772da09635c2164f4cef8bcf5255c17fe8cff 100644 (file)
@@ -3530,6 +3530,26 @@ static int mlx5_ib_get_hw_stats(struct ib_device *ibdev,
        return num_counters;
 }
 
+static struct net_device*
+mlx5_ib_alloc_rdma_netdev(struct ib_device *hca,
+                         u8 port_num,
+                         enum rdma_netdev_t type,
+                         const char *name,
+                         unsigned char name_assign_type,
+                         void (*setup)(struct net_device *))
+{
+       if (type != RDMA_NETDEV_IPOIB)
+               return ERR_PTR(-EOPNOTSUPP);
+
+       return mlx5_rdma_netdev_alloc(to_mdev(hca)->mdev, hca,
+                                     name, setup);
+}
+
+static void mlx5_ib_free_rdma_netdev(struct net_device *netdev)
+{
+       return mlx5_rdma_netdev_free(netdev);
+}
+
 static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
 {
        struct mlx5_ib_dev *dev;
@@ -3660,6 +3680,8 @@ static void *mlx5_ib_add(struct mlx5_core_dev *mdev)
        dev->ib_dev.check_mr_status     = mlx5_ib_check_mr_status;
        dev->ib_dev.get_port_immutable  = mlx5_port_immutable;
        dev->ib_dev.get_dev_fw_str      = get_dev_fw_str;
+       dev->ib_dev.alloc_rdma_netdev   = mlx5_ib_alloc_rdma_netdev;
+       dev->ib_dev.free_rdma_netdev    = mlx5_ib_free_rdma_netdev;
        if (mlx5_core_is_pf(mdev)) {
                dev->ib_dev.get_vf_config       = mlx5_ib_get_vf_config;
                dev->ib_dev.set_vf_link_state   = mlx5_ib_set_vf_link_state;
index ef11e770f82235c46aa91f8753f2332a0c25903a..6a72095d6c7acf7b4c62ce6720118f8a128de523 100644 (file)
@@ -35,6 +35,7 @@
 #include <rdma/ib_user_verbs.h>
 #include <linux/netdevice.h>
 #include <linux/iommu.h>
+#include <linux/pci.h>
 #include <net/addrconf.h>
 #include <linux/qed/qede_roce.h>
 #include <linux/qed/qed_chain.h>
index f1e66efea98a87f1a5327cbb638c51a7688bc3cc..1d940a2885c98fa93e17332572c86a3e73ece983 100644 (file)
@@ -512,7 +512,7 @@ static int qibfs_fill_super(struct super_block *sb, void *data, int silent)
        unsigned long flags;
        int ret;
 
-       static struct tree_descr files[] = {
+       static const struct tree_descr files[] = {
                [2] = {"driver_stats", &driver_ops[0], S_IRUGO},
                [3] = {"driver_stats_names", &driver_ops[1], S_IRUGO},
                {""},
index ced15c4446bd90b4c8d13abaf21925423e7f4345..e37cc89987e12c1d99ed60fe1a8464e92f70b3cd 100644 (file)
@@ -368,7 +368,7 @@ int rxe_mem_copy(struct rxe_mem *mem, u64 iova, void *addr, int length,
                        ((void *)(uintptr_t)iova) : addr;
 
                if (crcp)
-                       crc = rxe_crc32(to_rdev(mem->pd->ibpd.device),
+                       *crcp = rxe_crc32(to_rdev(mem->pd->ibpd.device),
                                        *crcp, src, length);
 
                memcpy(dest, src, length);
index 13ed2cc6eaa2ac743877cf06b6687907baa40cf9..1b596fbbe2516f2ad550e21995452adef0fe3cc1 100644 (file)
@@ -114,7 +114,6 @@ enum rxe_device_param {
        RXE_MAX_UCONTEXT                = 512,
 
        RXE_NUM_PORT                    = 1,
-       RXE_NUM_COMP_VECTORS            = 1,
 
        RXE_MIN_QP_INDEX                = 16,
        RXE_MAX_QP_INDEX                = 0x00020000,
index 299b0f8423f2cb1ed070a3716ec44c3183b680e3..83d709e74dfb87ab0dcec30c87f0e49cd57022d2 100644 (file)
@@ -1239,7 +1239,7 @@ int rxe_register_device(struct rxe_dev *rxe)
        dev->owner = THIS_MODULE;
        dev->node_type = RDMA_NODE_IB_CA;
        dev->phys_port_cnt = 1;
-       dev->num_comp_vectors = RXE_NUM_COMP_VECTORS;
+       dev->num_comp_vectors = num_possible_cpus();
        dev->dev.parent = rxe_dma_device(rxe);
        dev->local_dma_lkey = 0;
        addrconf_addr_eui48((unsigned char *)&dev->node_guid,
index 379c02fb4181cc6e83a033ed526778312197d0ef..874b24366e4dd744cc9ddf1c4b561a5a050641d1 100644 (file)
@@ -155,7 +155,66 @@ static int ipoib_get_sset_count(struct net_device __always_unused *dev,
        return -EOPNOTSUPP;
 }
 
+/* Return lane speed in unit of 1e6 bit/sec */
+static inline int ib_speed_enum_to_int(int speed)
+{
+       switch (speed) {
+       case IB_SPEED_SDR:
+               return SPEED_2500;
+       case IB_SPEED_DDR:
+               return SPEED_5000;
+       case IB_SPEED_QDR:
+       case IB_SPEED_FDR10:
+               return SPEED_10000;
+       case IB_SPEED_FDR:
+               return SPEED_14000;
+       case IB_SPEED_EDR:
+               return SPEED_25000;
+       }
+
+       return SPEED_UNKNOWN;
+}
+
+static int ipoib_get_link_ksettings(struct net_device *netdev,
+                                   struct ethtool_link_ksettings *cmd)
+{
+       struct ipoib_dev_priv *priv = netdev_priv(netdev);
+       struct ib_port_attr attr;
+       int ret, speed, width;
+
+       if (!netif_carrier_ok(netdev)) {
+               cmd->base.speed = SPEED_UNKNOWN;
+               cmd->base.duplex = DUPLEX_UNKNOWN;
+               return 0;
+       }
+
+       ret = ib_query_port(priv->ca, priv->port, &attr);
+       if (ret < 0)
+               return -EINVAL;
+
+       speed = ib_speed_enum_to_int(attr.active_speed);
+       width = ib_width_enum_to_int(attr.active_width);
+
+       if (speed < 0 || width < 0)
+               return -EINVAL;
+
+       /* Except the following are set, the other members of
+        * the struct ethtool_link_settings are initialized to
+        * zero in the function __ethtool_get_link_ksettings.
+        */
+       cmd->base.speed          = speed * width;
+       cmd->base.duplex         = DUPLEX_FULL;
+
+       cmd->base.phy_address    = 0xFF;
+
+       cmd->base.autoneg        = AUTONEG_ENABLE;
+       cmd->base.port           = PORT_OTHER;
+
+       return 0;
+}
+
 static const struct ethtool_ops ipoib_ethtool_ops = {
+       .get_link_ksettings     = ipoib_get_link_ksettings,
        .get_drvinfo            = ipoib_get_drvinfo,
        .get_coalesce           = ipoib_get_coalesce,
        .set_coalesce           = ipoib_set_coalesce,
index 7d6c199de2d6430b52f8d387786db6055525dbc6..1ced0731c1400950f59e31b1638800afec92daad 100644 (file)
@@ -2302,12 +2302,8 @@ static void srpt_queue_response(struct se_cmd *cmd)
        }
        spin_unlock_irqrestore(&ioctx->spinlock, flags);
 
-       if (unlikely(transport_check_aborted_status(&ioctx->cmd, false)
-                    || WARN_ON_ONCE(state == SRPT_STATE_CMD_RSP_SENT))) {
-               atomic_inc(&ch->req_lim_delta);
-               srpt_abort_cmd(ioctx);
+       if (unlikely(WARN_ON_ONCE(state == SRPT_STATE_CMD_RSP_SENT)))
                return;
-       }
 
        /* For read commands, transfer the data to the initiator. */
        if (ioctx->cmd.data_direction == DMA_FROM_DEVICE &&
@@ -2689,7 +2685,8 @@ static void srpt_release_cmd(struct se_cmd *se_cmd)
        struct srpt_rdma_ch *ch = ioctx->ch;
        unsigned long flags;
 
-       WARN_ON(ioctx->state != SRPT_STATE_DONE);
+       WARN_ON_ONCE(ioctx->state != SRPT_STATE_DONE &&
+                    !(ioctx->cmd.transport_state & CMD_T_ABORTED));
 
        if (ioctx->n_rw_ctx) {
                srpt_free_rw_ctxs(ch, ioctx);
index 4215b5382092c15d693e62de6e029626e9fa551d..f3c2f6ea8b447395fd4fc241735a0b4d8f4a6bd1 100644 (file)
@@ -330,4 +330,25 @@ config JOYSTICK_MAPLE
          To compile this as a module choose M here: the module will be called
          maplecontrol.
 
+config JOYSTICK_PSXPAD_SPI
+       tristate "PlayStation 1/2 joypads via SPI interface"
+       depends on SPI
+       select INPUT_POLLDEV
+       help
+         Say Y here if you wish to connect PlayStation 1/2 joypads
+         via SPI interface.
+
+         To compile this driver as a module, choose M here: the
+         module will be called psxpad-spi.
+
+config JOYSTICK_PSXPAD_SPI_FF
+       bool "PlayStation 1/2 joypads force feedback (rumble) support"
+       depends on JOYSTICK_PSXPAD_SPI
+       select INPUT_FF_MEMLESS
+       help
+         Say Y here if you want to take advantage of PlayStation 1/2
+         joypads rumble features.
+
+         To drive rumble motor a dedicated power supply is required.
+
 endif
index 92dc0de9dfeda43171a901f96c40bebe0e7a5ae2..496fd56b3f1bccee496b363fd214c5451a594ced 100644 (file)
@@ -21,6 +21,7 @@ obj-$(CONFIG_JOYSTICK_INTERACT)               += interact.o
 obj-$(CONFIG_JOYSTICK_JOYDUMP)         += joydump.o
 obj-$(CONFIG_JOYSTICK_MAGELLAN)                += magellan.o
 obj-$(CONFIG_JOYSTICK_MAPLE)           += maplecontrol.o
+obj-$(CONFIG_JOYSTICK_PSXPAD_SPI)      += psxpad-spi.o
 obj-$(CONFIG_JOYSTICK_SIDEWINDER)      += sidewinder.o
 obj-$(CONFIG_JOYSTICK_SPACEBALL)       += spaceball.o
 obj-$(CONFIG_JOYSTICK_SPACEORB)                += spaceorb.o
diff --git a/drivers/input/joystick/psxpad-spi.c b/drivers/input/joystick/psxpad-spi.c
new file mode 100644 (file)
index 0000000..28b473f
--- /dev/null
@@ -0,0 +1,401 @@
+/*
+ * PlayStation 1/2 joypads via SPI interface Driver
+ *
+ * Copyright (C) 2017 Tomohiro Yoshidomi <sylph23k@gmail.com>
+ * Licensed under the GPL-2 or later.
+ *
+ * PlayStation 1/2 joypad's plug (not socket)
+ *  123 456 789
+ * (...|...|...)
+ *
+ * 1: DAT -> MISO (pullup with 1k owm to 3.3V)
+ * 2: CMD -> MOSI
+ * 3: 9V (for motor, if not use N.C.)
+ * 4: GND
+ * 5: 3.3V
+ * 6: Attention -> CS(SS)
+ * 7: SCK -> SCK
+ * 8: N.C.
+ * 9: ACK -> N.C.
+ */
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/input.h>
+#include <linux/input-polldev.h>
+#include <linux/module.h>
+#include <linux/spi/spi.h>
+#include <linux/types.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+
+#define REVERSE_BIT(x) ((((x) & 0x80) >> 7) | (((x) & 0x40) >> 5) | \
+       (((x) & 0x20) >> 3) | (((x) & 0x10) >> 1) | (((x) & 0x08) << 1) | \
+       (((x) & 0x04) << 3) | (((x) & 0x02) << 5) | (((x) & 0x01) << 7))
+
+/* PlayStation 1/2 joypad command and response are LSBFIRST. */
+
+/*
+ *     0x01, 0x42, 0x00, 0x00, 0x00,
+ *     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ *     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ */
+static const u8 PSX_CMD_POLL[] = {
+       0x80, 0x42, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+/*     0x01, 0x43, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 */
+static const u8 PSX_CMD_ENTER_CFG[] = {
+       0x80, 0xC2, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+/*     0x01, 0x43, 0x00, 0x00, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A */
+static const u8 PSX_CMD_EXIT_CFG[] = {
+       0x80, 0xC2, 0x00, 0x00, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A
+};
+/*     0x01, 0x4D, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF */
+static const u8 PSX_CMD_ENABLE_MOTOR[] = {
+       0x80, 0xB2, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+struct psxpad {
+       struct spi_device *spi;
+       struct input_polled_dev *pdev;
+       char phys[0x20];
+       bool motor1enable;
+       bool motor2enable;
+       u8 motor1level;
+       u8 motor2level;
+       u8 sendbuf[0x20] ____cacheline_aligned;
+       u8 response[sizeof(PSX_CMD_POLL)] ____cacheline_aligned;
+};
+
+static int psxpad_command(struct psxpad *pad, const u8 sendcmdlen)
+{
+       struct spi_transfer xfers = {
+               .tx_buf         = pad->sendbuf,
+               .rx_buf         = pad->response,
+               .len            = sendcmdlen,
+       };
+       int err;
+
+       err = spi_sync_transfer(pad->spi, &xfers, 1);
+       if (err) {
+               dev_err(&pad->spi->dev,
+                       "%s: failed to SPI xfers mode: %d\n",
+                       __func__, err);
+               return err;
+       }
+
+       return 0;
+}
+
+#ifdef CONFIG_JOYSTICK_PSXPAD_SPI_FF
+static void psxpad_control_motor(struct psxpad *pad,
+                                bool motor1enable, bool motor2enable)
+{
+       int err;
+
+       pad->motor1enable = motor1enable;
+       pad->motor2enable = motor2enable;
+
+       memcpy(pad->sendbuf, PSX_CMD_ENTER_CFG, sizeof(PSX_CMD_ENTER_CFG));
+       err = psxpad_command(pad, sizeof(PSX_CMD_ENTER_CFG));
+       if (err) {
+               dev_err(&pad->spi->dev,
+                       "%s: failed to enter config mode: %d\n",
+                       __func__, err);
+               return;
+       }
+
+       memcpy(pad->sendbuf, PSX_CMD_ENABLE_MOTOR,
+              sizeof(PSX_CMD_ENABLE_MOTOR));
+       pad->sendbuf[3] = pad->motor1enable ? 0x00 : 0xFF;
+       pad->sendbuf[4] = pad->motor2enable ? 0x80 : 0xFF;
+       err = psxpad_command(pad, sizeof(PSX_CMD_ENABLE_MOTOR));
+       if (err) {
+               dev_err(&pad->spi->dev,
+                       "%s: failed to enable motor mode: %d\n",
+                       __func__, err);
+               return;
+       }
+
+       memcpy(pad->sendbuf, PSX_CMD_EXIT_CFG, sizeof(PSX_CMD_EXIT_CFG));
+       err = psxpad_command(pad, sizeof(PSX_CMD_EXIT_CFG));
+       if (err) {
+               dev_err(&pad->spi->dev,
+                       "%s: failed to exit config mode: %d\n",
+                       __func__, err);
+               return;
+       }
+}
+
+static void psxpad_set_motor_level(struct psxpad *pad,
+                                  u8 motor1level, u8 motor2level)
+{
+       pad->motor1level = motor1level ? 0xFF : 0x00;
+       pad->motor2level = REVERSE_BIT(motor2level);
+}
+
+static int psxpad_spi_play_effect(struct input_dev *idev,
+                                 void *data, struct ff_effect *effect)
+{
+       struct input_polled_dev *pdev = input_get_drvdata(idev);
+       struct psxpad *pad = pdev->private;
+
+       switch (effect->type) {
+       case FF_RUMBLE:
+               psxpad_set_motor_level(pad,
+                       (effect->u.rumble.weak_magnitude >> 8) & 0xFFU,
+                       (effect->u.rumble.strong_magnitude >> 8) & 0xFFU);
+               break;
+       }
+
+       return 0;
+}
+
+static int psxpad_spi_init_ff(struct psxpad *pad)
+{
+       int err;
+
+       input_set_capability(pad->pdev->input, EV_FF, FF_RUMBLE);
+
+       err = input_ff_create_memless(pad->pdev->input, NULL,
+                                     psxpad_spi_play_effect);
+       if (err) {
+               dev_err(&pad->spi->dev,
+                       "input_ff_create_memless() failed: %d\n", err);
+               return err;
+       }
+
+       return 0;
+}
+
+#else  /* CONFIG_JOYSTICK_PSXPAD_SPI_FF */
+
+static void psxpad_control_motor(struct psxpad *pad,
+                                bool motor1enable, bool motor2enable)
+{
+}
+
+static void psxpad_set_motor_level(struct psxpad *pad,
+                                  u8 motor1level, u8 motor2level)
+{
+}
+
+static inline int psxpad_spi_init_ff(struct psxpad *pad)
+{
+       return 0;
+}
+#endif /* CONFIG_JOYSTICK_PSXPAD_SPI_FF */
+
+static void psxpad_spi_poll_open(struct input_polled_dev *pdev)
+{
+       struct psxpad *pad = pdev->private;
+
+       pm_runtime_get_sync(&pad->spi->dev);
+}
+
+static void psxpad_spi_poll_close(struct input_polled_dev *pdev)
+{
+       struct psxpad *pad = pdev->private;
+
+       pm_runtime_put_sync(&pad->spi->dev);
+}
+
+static void psxpad_spi_poll(struct input_polled_dev *pdev)
+{
+       struct psxpad *pad = pdev->private;
+       struct input_dev *input = pdev->input;
+       u8 b_rsp3, b_rsp4;
+       int err;
+
+       psxpad_control_motor(pad, true, true);
+
+       memcpy(pad->sendbuf, PSX_CMD_POLL, sizeof(PSX_CMD_POLL));
+       pad->sendbuf[3] = pad->motor1enable ? pad->motor1level : 0x00;
+       pad->sendbuf[4] = pad->motor2enable ? pad->motor2level : 0x00;
+       err = psxpad_command(pad, sizeof(PSX_CMD_POLL));
+       if (err) {
+               dev_err(&pad->spi->dev,
+                       "%s: poll command failed mode: %d\n", __func__, err);
+               return;
+       }
+
+       switch (pad->response[1]) {
+       case 0xCE:      /* 0x73 : analog 1 */
+               /* button data is inverted */
+               b_rsp3 = ~pad->response[3];
+               b_rsp4 = ~pad->response[4];
+
+               input_report_abs(input, ABS_X, REVERSE_BIT(pad->response[7]));
+               input_report_abs(input, ABS_Y, REVERSE_BIT(pad->response[8]));
+               input_report_abs(input, ABS_RX, REVERSE_BIT(pad->response[5]));
+               input_report_abs(input, ABS_RY, REVERSE_BIT(pad->response[6]));
+               input_report_key(input, BTN_DPAD_UP, b_rsp3 & BIT(3));
+               input_report_key(input, BTN_DPAD_DOWN, b_rsp3 & BIT(1));
+               input_report_key(input, BTN_DPAD_LEFT, b_rsp3 & BIT(0));
+               input_report_key(input, BTN_DPAD_RIGHT, b_rsp3 & BIT(2));
+               input_report_key(input, BTN_X, b_rsp4 & BIT(3));
+               input_report_key(input, BTN_A, b_rsp4 & BIT(2));
+               input_report_key(input, BTN_B, b_rsp4 & BIT(1));
+               input_report_key(input, BTN_Y, b_rsp4 & BIT(0));
+               input_report_key(input, BTN_TL, b_rsp4 & BIT(5));
+               input_report_key(input, BTN_TR, b_rsp4 & BIT(4));
+               input_report_key(input, BTN_TL2, b_rsp4 & BIT(7));
+               input_report_key(input, BTN_TR2, b_rsp4 & BIT(6));
+               input_report_key(input, BTN_THUMBL, b_rsp3 & BIT(6));
+               input_report_key(input, BTN_THUMBR, b_rsp3 & BIT(5));
+               input_report_key(input, BTN_SELECT, b_rsp3 & BIT(7));
+               input_report_key(input, BTN_START, b_rsp3 & BIT(4));
+               break;
+
+       case 0x82:      /* 0x41 : digital */
+               /* button data is inverted */
+               b_rsp3 = ~pad->response[3];
+               b_rsp4 = ~pad->response[4];
+
+               input_report_abs(input, ABS_X, 0x80);
+               input_report_abs(input, ABS_Y, 0x80);
+               input_report_abs(input, ABS_RX, 0x80);
+               input_report_abs(input, ABS_RY, 0x80);
+               input_report_key(input, BTN_DPAD_UP, b_rsp3 & BIT(3));
+               input_report_key(input, BTN_DPAD_DOWN, b_rsp3 & BIT(1));
+               input_report_key(input, BTN_DPAD_LEFT, b_rsp3 & BIT(0));
+               input_report_key(input, BTN_DPAD_RIGHT, b_rsp3 & BIT(2));
+               input_report_key(input, BTN_X, b_rsp4 & BIT(3));
+               input_report_key(input, BTN_A, b_rsp4 & BIT(2));
+               input_report_key(input, BTN_B, b_rsp4 & BIT(1));
+               input_report_key(input, BTN_Y, b_rsp4 & BIT(0));
+               input_report_key(input, BTN_TL, b_rsp4 & BIT(5));
+               input_report_key(input, BTN_TR, b_rsp4 & BIT(4));
+               input_report_key(input, BTN_TL2, b_rsp4 & BIT(7));
+               input_report_key(input, BTN_TR2, b_rsp4 & BIT(6));
+               input_report_key(input, BTN_THUMBL, false);
+               input_report_key(input, BTN_THUMBR, false);
+               input_report_key(input, BTN_SELECT, b_rsp3 & BIT(7));
+               input_report_key(input, BTN_START, b_rsp3 & BIT(4));
+               break;
+       }
+
+       input_sync(input);
+}
+
+static int psxpad_spi_probe(struct spi_device *spi)
+{
+       struct psxpad *pad;
+       struct input_polled_dev *pdev;
+       struct input_dev *idev;
+       int err;
+
+       pad = devm_kzalloc(&spi->dev, sizeof(struct psxpad), GFP_KERNEL);
+       if (!pad)
+               return -ENOMEM;
+
+       pdev = input_allocate_polled_device();
+       if (!pdev) {
+               dev_err(&spi->dev, "failed to allocate input device\n");
+               return -ENOMEM;
+       }
+
+       /* input poll device settings */
+       pad->pdev = pdev;
+       pad->spi = spi;
+
+       pdev->private = pad;
+       pdev->open = psxpad_spi_poll_open;
+       pdev->close = psxpad_spi_poll_close;
+       pdev->poll = psxpad_spi_poll;
+       /* poll interval is about 60fps */
+       pdev->poll_interval = 16;
+       pdev->poll_interval_min = 8;
+       pdev->poll_interval_max = 32;
+
+       /* input device settings */
+       idev = pdev->input;
+       idev->name = "PlayStation 1/2 joypad";
+       snprintf(pad->phys, sizeof(pad->phys), "%s/input", dev_name(&spi->dev));
+       idev->id.bustype = BUS_SPI;
+
+       /* key/value map settings */
+       input_set_abs_params(idev, ABS_X, 0, 255, 0, 0);
+       input_set_abs_params(idev, ABS_Y, 0, 255, 0, 0);
+       input_set_abs_params(idev, ABS_RX, 0, 255, 0, 0);
+       input_set_abs_params(idev, ABS_RY, 0, 255, 0, 0);
+       input_set_capability(idev, EV_KEY, BTN_DPAD_UP);
+       input_set_capability(idev, EV_KEY, BTN_DPAD_DOWN);
+       input_set_capability(idev, EV_KEY, BTN_DPAD_LEFT);
+       input_set_capability(idev, EV_KEY, BTN_DPAD_RIGHT);
+       input_set_capability(idev, EV_KEY, BTN_A);
+       input_set_capability(idev, EV_KEY, BTN_B);
+       input_set_capability(idev, EV_KEY, BTN_X);
+       input_set_capability(idev, EV_KEY, BTN_Y);
+       input_set_capability(idev, EV_KEY, BTN_TL);
+       input_set_capability(idev, EV_KEY, BTN_TR);
+       input_set_capability(idev, EV_KEY, BTN_TL2);
+       input_set_capability(idev, EV_KEY, BTN_TR2);
+       input_set_capability(idev, EV_KEY, BTN_THUMBL);
+       input_set_capability(idev, EV_KEY, BTN_THUMBR);
+       input_set_capability(idev, EV_KEY, BTN_SELECT);
+       input_set_capability(idev, EV_KEY, BTN_START);
+
+       err = psxpad_spi_init_ff(pad);
+       if (err)
+               return err;
+
+       /* SPI settings */
+       spi->mode = SPI_MODE_3;
+       spi->bits_per_word = 8;
+       /* (PlayStation 1/2 joypad might be possible works 250kHz/500kHz) */
+       spi->master->min_speed_hz = 125000;
+       spi->master->max_speed_hz = 125000;
+       spi_setup(spi);
+
+       /* pad settings */
+       psxpad_set_motor_level(pad, 0, 0);
+
+       /* register input poll device */
+       err = input_register_polled_device(pdev);
+       if (err) {
+               dev_err(&spi->dev,
+                       "failed to register input poll device: %d\n", err);
+               return err;
+       }
+
+       pm_runtime_enable(&spi->dev);
+
+       return 0;
+}
+
+static int __maybe_unused psxpad_spi_suspend(struct device *dev)
+{
+       struct spi_device *spi = to_spi_device(dev);
+       struct psxpad *pad = spi_get_drvdata(spi);
+
+       psxpad_set_motor_level(pad, 0, 0);
+
+       return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(psxpad_spi_pm, psxpad_spi_suspend, NULL);
+
+static const struct spi_device_id psxpad_spi_id[] = {
+       { "psxpad-spi", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(spi, psxpad_spi_id);
+
+static struct spi_driver psxpad_spi_driver = {
+       .driver = {
+               .name = "psxpad-spi",
+               .pm = &psxpad_spi_pm,
+       },
+       .id_table = psxpad_spi_id,
+       .probe   = psxpad_spi_probe,
+};
+
+module_spi_driver(psxpad_spi_driver);
+
+MODULE_AUTHOR("Tomohiro Yoshidomi <sylph23k@gmail.com>");
+MODULE_DESCRIPTION("PlayStation 1/2 joypads via SPI interface Driver");
+MODULE_LICENSE("GPL");
index df83fdc6c0e7bd3b692c85ebf869b52142a4cf03..def96cd2479bafa04da2e15557d2bd83ebd123d3 100644 (file)
@@ -126,25 +126,26 @@ static const struct xpad_device {
        u8 mapping;
        u8 xtype;
 } xpad_device[] = {
+       { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX },
+       { 0x044f, 0xb326, "Thrustmaster Gamepad GP XID", 0, XTYPE_XBOX360 },
        { 0x045e, 0x0202, "Microsoft X-Box pad v1 (US)", 0, XTYPE_XBOX },
        { 0x045e, 0x0285, "Microsoft X-Box pad (Japan)", 0, XTYPE_XBOX },
        { 0x045e, 0x0287, "Microsoft Xbox Controller S", 0, XTYPE_XBOX },
        { 0x045e, 0x0289, "Microsoft X-Box pad v2 (US)", 0, XTYPE_XBOX },
        { 0x045e, 0x028e, "Microsoft X-Box 360 pad", 0, XTYPE_XBOX360 },
+       { 0x045e, 0x0291, "Xbox 360 Wireless Receiver (XBOX)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },
        { 0x045e, 0x02d1, "Microsoft X-Box One pad", 0, XTYPE_XBOXONE },
        { 0x045e, 0x02dd, "Microsoft X-Box One pad (Firmware 2015)", 0, XTYPE_XBOXONE },
        { 0x045e, 0x02e3, "Microsoft X-Box One Elite pad", 0, XTYPE_XBOXONE },
        { 0x045e, 0x02ea, "Microsoft X-Box One S pad", 0, XTYPE_XBOXONE },
-       { 0x045e, 0x0291, "Xbox 360 Wireless Receiver (XBOX)", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },
        { 0x045e, 0x0719, "Xbox 360 Wireless Receiver", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360W },
-       { 0x044f, 0x0f07, "Thrustmaster, Inc. Controller", 0, XTYPE_XBOX },
-       { 0x044f, 0xb326, "Thrustmaster Gamepad GP XID", 0, XTYPE_XBOX360 },
        { 0x046d, 0xc21d, "Logitech Gamepad F310", 0, XTYPE_XBOX360 },
        { 0x046d, 0xc21e, "Logitech Gamepad F510", 0, XTYPE_XBOX360 },
        { 0x046d, 0xc21f, "Logitech Gamepad F710", 0, XTYPE_XBOX360 },
        { 0x046d, 0xc242, "Logitech Chillstream Controller", 0, XTYPE_XBOX360 },
        { 0x046d, 0xca84, "Logitech Xbox Cordless Controller", 0, XTYPE_XBOX },
        { 0x046d, 0xca88, "Logitech Compact Controller for Xbox", 0, XTYPE_XBOX },
+       { 0x056e, 0x2004, "Elecom JC-U3613M", 0, XTYPE_XBOX360 },
        { 0x05fd, 0x1007, "Mad Catz Controller (unverified)", 0, XTYPE_XBOX },
        { 0x05fd, 0x107a, "InterAct 'PowerPad Pro' X-Box pad (Germany)", 0, XTYPE_XBOX },
        { 0x0738, 0x4516, "Mad Catz Control Pad", 0, XTYPE_XBOX },
@@ -179,13 +180,15 @@ static const struct xpad_device {
        { 0x0e6f, 0x0006, "Edge wireless Controller", 0, XTYPE_XBOX },
        { 0x0e6f, 0x0105, "HSM3 Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
        { 0x0e6f, 0x0113, "Afterglow AX.1 Gamepad for Xbox 360", 0, XTYPE_XBOX360 },
+       { 0x0e6f, 0x011f, "Rock Candy Gamepad Wired Controller", 0, XTYPE_XBOX360 },
        { 0x0e6f, 0x0139, "Afterglow Prismatic Wired Controller", 0, XTYPE_XBOXONE },
+       { 0x0e6f, 0x0146, "Rock Candy Wired Controller for Xbox One", 0, XTYPE_XBOXONE },
        { 0x0e6f, 0x0201, "Pelican PL-3601 'TSZ' Wired Xbox 360 Controller", 0, XTYPE_XBOX360 },
        { 0x0e6f, 0x0213, "Afterglow Gamepad for Xbox 360", 0, XTYPE_XBOX360 },
        { 0x0e6f, 0x021f, "Rock Candy Gamepad for Xbox 360", 0, XTYPE_XBOX360 },
-       { 0x0e6f, 0x0146, "Rock Candy Wired Controller for Xbox One", 0, XTYPE_XBOXONE },
        { 0x0e6f, 0x0301, "Logic3 Controller", 0, XTYPE_XBOX360 },
        { 0x0e6f, 0x0401, "Logic3 Controller", 0, XTYPE_XBOX360 },
+       { 0x0e6f, 0x0413, "Afterglow AX.1 Gamepad for Xbox 360", 0, XTYPE_XBOX360 },
        { 0x0e8f, 0x0201, "SmartJoy Frag Xpad/PS2 adaptor", 0, XTYPE_XBOX },
        { 0x0e8f, 0x3008, "Generic xbox control (dealextreme)", 0, XTYPE_XBOX },
        { 0x0f0d, 0x000a, "Hori Co. DOA4 FightStick", 0, XTYPE_XBOX360 },
@@ -209,27 +212,38 @@ static const struct xpad_device {
        { 0x162e, 0xbeef, "Joytech Neo-Se Take2", 0, XTYPE_XBOX360 },
        { 0x1689, 0xfd00, "Razer Onza Tournament Edition", 0, XTYPE_XBOX360 },
        { 0x1689, 0xfd01, "Razer Onza Classic Edition", 0, XTYPE_XBOX360 },
-       { 0x24c6, 0x542a, "Xbox ONE spectra", 0, XTYPE_XBOXONE },
-       { 0x24c6, 0x5d04, "Razer Sabertooth", 0, XTYPE_XBOX360 },
+       { 0x1689, 0xfe00, "Razer Sabertooth", 0, XTYPE_XBOX360 },
        { 0x1bad, 0x0002, "Harmonix Rock Band Guitar", 0, XTYPE_XBOX360 },
        { 0x1bad, 0x0003, "Harmonix Rock Band Drumkit", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
        { 0x1bad, 0xf016, "Mad Catz Xbox 360 Controller", 0, XTYPE_XBOX360 },
+       { 0x1bad, 0xf018, "Mad Catz Street Fighter IV SE Fighting Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
+       { 0x1bad, 0xf019, "Mad Catz Brawlstick for Xbox 360", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
+       { 0x1bad, 0xf021, "Mad Cats Ghost Recon FS GamePad", 0, XTYPE_XBOX360 },
        { 0x1bad, 0xf023, "MLG Pro Circuit Controller (Xbox)", 0, XTYPE_XBOX360 },
        { 0x1bad, 0xf028, "Street Fighter IV FightPad", 0, XTYPE_XBOX360 },
+       { 0x1bad, 0xf02e, "Mad Catz Fightpad", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
        { 0x1bad, 0xf038, "Street Fighter IV FightStick TE", 0, XTYPE_XBOX360 },
+       { 0x1bad, 0xf03a, "Mad Catz SFxT Fightstick Pro", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
        { 0x1bad, 0xf900, "Harmonix Xbox 360 Controller", 0, XTYPE_XBOX360 },
        { 0x1bad, 0xf901, "Gamestop Xbox 360 Controller", 0, XTYPE_XBOX360 },
        { 0x1bad, 0xf903, "Tron Xbox 360 controller", 0, XTYPE_XBOX360 },
+       { 0x1bad, 0xfa01, "MadCatz GamePad", 0, XTYPE_XBOX360 },
        { 0x24c6, 0x5000, "Razer Atrox Arcade Stick", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
        { 0x24c6, 0x5300, "PowerA MINI PROEX Controller", 0, XTYPE_XBOX360 },
        { 0x24c6, 0x5303, "Xbox Airflo wired controller", 0, XTYPE_XBOX360 },
+       { 0x24c6, 0x531a, "PowerA Pro Ex", 0, XTYPE_XBOX360 },
+       { 0x24c6, 0x5397, "FUS1ON Tournament Controller", 0, XTYPE_XBOX360 },
        { 0x24c6, 0x541a, "PowerA Xbox One Mini Wired Controller", 0, XTYPE_XBOXONE },
+       { 0x24c6, 0x542a, "Xbox ONE spectra", 0, XTYPE_XBOXONE },
        { 0x24c6, 0x543a, "PowerA Xbox One wired controller", 0, XTYPE_XBOXONE },
        { 0x24c6, 0x5500, "Hori XBOX 360 EX 2 with Turbo", 0, XTYPE_XBOX360 },
        { 0x24c6, 0x5501, "Hori Real Arcade Pro VX-SA", 0, XTYPE_XBOX360 },
+       { 0x24c6, 0x5503, "Hori Fighting Edge", MAP_TRIGGERS_TO_BUTTONS, XTYPE_XBOX360 },
        { 0x24c6, 0x5506, "Hori SOULCALIBUR V Stick", 0, XTYPE_XBOX360 },
+       { 0x24c6, 0x550d, "Hori GEM Xbox controller", 0, XTYPE_XBOX360 },
        { 0x24c6, 0x5b02, "Thrustmaster, Inc. GPX Controller", 0, XTYPE_XBOX360 },
        { 0x24c6, 0x5b03, "Thrustmaster Ferrari 458 Racing Wheel", 0, XTYPE_XBOX360 },
+       { 0x24c6, 0x5d04, "Razer Sabertooth", 0, XTYPE_XBOX360 },
        { 0xffff, 0xffff, "Chinese-made Xbox Controller", 0, XTYPE_XBOX },
        { 0x0000, 0x0000, "Generic X-Box pad", 0, XTYPE_UNKNOWN }
 };
@@ -316,6 +330,7 @@ static struct usb_device_id xpad_table[] = {
        XPAD_XBOX360_VENDOR(0x045e),            /* Microsoft X-Box 360 controllers */
        XPAD_XBOXONE_VENDOR(0x045e),            /* Microsoft X-Box One controllers */
        XPAD_XBOX360_VENDOR(0x046d),            /* Logitech X-Box 360 style controllers */
+       XPAD_XBOX360_VENDOR(0x056e),            /* Elecom JC-U3613M */
        XPAD_XBOX360_VENDOR(0x0738),            /* Mad Catz X-Box 360 controllers */
        { USB_DEVICE(0x0738, 0x4540) },         /* Mad Catz Beat Pad */
        XPAD_XBOXONE_VENDOR(0x0738),            /* Mad Catz FightStick TE 2 */
index c7a8120b13c0921c55010eaf4819f8bb5f68b0db..79eb29550c348864d183fbee50715a3e9a4d0dbe 100644 (file)
@@ -660,7 +660,7 @@ static const struct of_device_id cros_ec_keyb_of_match[] = {
 MODULE_DEVICE_TABLE(of, cros_ec_keyb_of_match);
 #endif
 
-static const SIMPLE_DEV_PM_OPS(cros_ec_keyb_pm_ops, NULL, cros_ec_keyb_resume);
+static SIMPLE_DEV_PM_OPS(cros_ec_keyb_pm_ops, NULL, cros_ec_keyb_resume);
 
 static struct platform_driver cros_ec_keyb_driver = {
        .probe = cros_ec_keyb_probe,
index 3827a22362deb97ae3b71c21370935350cfb09eb..9ce71dfa0de148bf4e1b033184d7220696833741 100644 (file)
@@ -78,7 +78,7 @@ MODULE_LICENSE("GPL");
 #define INPORT_IRQ             5
 
 static int inport_irq = INPORT_IRQ;
-module_param_named(irq, inport_irq, uint, 0);
+module_param_hw_named(irq, inport_irq, uint, irq, 0);
 MODULE_PARM_DESC(irq, "IRQ number (5=default)");
 
 static struct input_dev *inport_dev;
index e2413113df22a171e4c3d0eef73f70e98941c2bf..6f165e053f4dfd0cd8e253258870c1a59950e1d1 100644 (file)
@@ -69,7 +69,7 @@ MODULE_LICENSE("GPL");
 #define LOGIBM_IRQ             5
 
 static int logibm_irq = LOGIBM_IRQ;
-module_param_named(irq, logibm_irq, uint, 0);
+module_param_hw_named(irq, logibm_irq, uint, irq, 0);
 MODULE_PARM_DESC(irq, "IRQ number (5=default)");
 
 static struct input_dev *logibm_dev;
index 36e57deacd03543b885c79c67601d206a56e290a..bd5352824f7792b8218fb836ccc54708f4b2a2ee 100644 (file)
@@ -50,11 +50,11 @@ MODULE_DESCRIPTION("ICS MicroClock MK712 TouchScreen driver");
 MODULE_LICENSE("GPL");
 
 static unsigned int mk712_io = 0x260;  /* Also 0x200, 0x208, 0x300 */
-module_param_named(io, mk712_io, uint, 0);
+module_param_hw_named(io, mk712_io, uint, ioport, 0);
 MODULE_PARM_DESC(io, "I/O base address of MK712 touchscreen controller");
 
 static unsigned int mk712_irq = 10;    /* Also 12, 14, 15 */
-module_param_named(irq, mk712_irq, uint, 0);
+module_param_hw_named(irq, mk712_irq, uint, irq, 0);
 MODULE_PARM_DESC(irq, "IRQ of MK712 touchscreen controller");
 
 /* eight 8-bit registers */
index 063343909b0d12f31fac8682058b2eaed4ad2b91..6629c472eafd828bb45a9e7fe3a4260c2e199de2 100644 (file)
@@ -696,9 +696,9 @@ out_clear_state:
 
 out_unregister:
        mmu_notifier_unregister(&pasid_state->mn, mm);
+       mmput(mm);
 
 out_free:
-       mmput(mm);
        free_pasid_state(pasid_state);
 
 out:
index 591bb96047c9765fd3e0fb536d3f26ca0a5f187f..380969aa60d5a6070765d4eaae3532c1b3324a8c 100644 (file)
@@ -554,9 +554,14 @@ struct arm_smmu_s2_cfg {
 };
 
 struct arm_smmu_strtab_ent {
-       bool                            valid;
-
-       bool                            bypass; /* Overrides s1/s2 config */
+       /*
+        * An STE is "assigned" if the master emitting the corresponding SID
+        * is attached to a domain. The behaviour of an unassigned STE is
+        * determined by the disable_bypass parameter, whereas an assigned
+        * STE behaves according to s1_cfg/s2_cfg, which themselves are
+        * configured according to the domain type.
+        */
+       bool                            assigned;
        struct arm_smmu_s1_cfg          *s1_cfg;
        struct arm_smmu_s2_cfg          *s2_cfg;
 };
@@ -632,6 +637,7 @@ enum arm_smmu_domain_stage {
        ARM_SMMU_DOMAIN_S1 = 0,
        ARM_SMMU_DOMAIN_S2,
        ARM_SMMU_DOMAIN_NESTED,
+       ARM_SMMU_DOMAIN_BYPASS,
 };
 
 struct arm_smmu_domain {
@@ -1005,9 +1011,9 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid,
         * This is hideously complicated, but we only really care about
         * three cases at the moment:
         *
-        * 1. Invalid (all zero) -> bypass  (init)
-        * 2. Bypass -> translation (attach)
-        * 3. Translation -> bypass (detach)
+        * 1. Invalid (all zero) -> bypass/fault (init)
+        * 2. Bypass/fault -> translation/bypass (attach)
+        * 3. Translation/bypass -> bypass/fault (detach)
         *
         * Given that we can't update the STE atomically and the SMMU
         * doesn't read the thing in a defined order, that leaves us
@@ -1046,11 +1052,15 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid,
        }
 
        /* Nuke the existing STE_0 value, as we're going to rewrite it */
-       val = ste->valid ? STRTAB_STE_0_V : 0;
+       val = STRTAB_STE_0_V;
+
+       /* Bypass/fault */
+       if (!ste->assigned || !(ste->s1_cfg || ste->s2_cfg)) {
+               if (!ste->assigned && disable_bypass)
+                       val |= STRTAB_STE_0_CFG_ABORT;
+               else
+                       val |= STRTAB_STE_0_CFG_BYPASS;
 
-       if (ste->bypass) {
-               val |= disable_bypass ? STRTAB_STE_0_CFG_ABORT
-                                     : STRTAB_STE_0_CFG_BYPASS;
                dst[0] = cpu_to_le64(val);
                dst[1] = cpu_to_le64(STRTAB_STE_1_SHCFG_INCOMING
                         << STRTAB_STE_1_SHCFG_SHIFT);
@@ -1111,10 +1121,7 @@ static void arm_smmu_write_strtab_ent(struct arm_smmu_device *smmu, u32 sid,
 static void arm_smmu_init_bypass_stes(u64 *strtab, unsigned int nent)
 {
        unsigned int i;
-       struct arm_smmu_strtab_ent ste = {
-               .valid  = true,
-               .bypass = true,
-       };
+       struct arm_smmu_strtab_ent ste = { .assigned = false };
 
        for (i = 0; i < nent; ++i) {
                arm_smmu_write_strtab_ent(NULL, -1, strtab, &ste);
@@ -1378,7 +1385,9 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
 {
        struct arm_smmu_domain *smmu_domain;
 
-       if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_DMA)
+       if (type != IOMMU_DOMAIN_UNMANAGED &&
+           type != IOMMU_DOMAIN_DMA &&
+           type != IOMMU_DOMAIN_IDENTITY)
                return NULL;
 
        /*
@@ -1509,6 +1518,11 @@ static int arm_smmu_domain_finalise(struct iommu_domain *domain)
        struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
        struct arm_smmu_device *smmu = smmu_domain->smmu;
 
+       if (domain->type == IOMMU_DOMAIN_IDENTITY) {
+               smmu_domain->stage = ARM_SMMU_DOMAIN_BYPASS;
+               return 0;
+       }
+
        /* Restrict the stage to what we can actually support */
        if (!(smmu->features & ARM_SMMU_FEAT_TRANS_S1))
                smmu_domain->stage = ARM_SMMU_DOMAIN_S2;
@@ -1579,7 +1593,7 @@ static __le64 *arm_smmu_get_step_for_sid(struct arm_smmu_device *smmu, u32 sid)
        return step;
 }
 
-static int arm_smmu_install_ste_for_dev(struct iommu_fwspec *fwspec)
+static void arm_smmu_install_ste_for_dev(struct iommu_fwspec *fwspec)
 {
        int i;
        struct arm_smmu_master_data *master = fwspec->iommu_priv;
@@ -1591,17 +1605,14 @@ static int arm_smmu_install_ste_for_dev(struct iommu_fwspec *fwspec)
 
                arm_smmu_write_strtab_ent(smmu, sid, step, &master->ste);
        }
-
-       return 0;
 }
 
 static void arm_smmu_detach_dev(struct device *dev)
 {
        struct arm_smmu_master_data *master = dev->iommu_fwspec->iommu_priv;
 
-       master->ste.bypass = true;
-       if (arm_smmu_install_ste_for_dev(dev->iommu_fwspec) < 0)
-               dev_warn(dev, "failed to install bypass STE\n");
+       master->ste.assigned = false;
+       arm_smmu_install_ste_for_dev(dev->iommu_fwspec);
 }
 
 static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
@@ -1620,7 +1631,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
        ste = &master->ste;
 
        /* Already attached to a different domain? */
-       if (!ste->bypass)
+       if (ste->assigned)
                arm_smmu_detach_dev(dev);
 
        mutex_lock(&smmu_domain->init_mutex);
@@ -1641,10 +1652,12 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
                goto out_unlock;
        }
 
-       ste->bypass = false;
-       ste->valid = true;
+       ste->assigned = true;
 
-       if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) {
+       if (smmu_domain->stage == ARM_SMMU_DOMAIN_BYPASS) {
+               ste->s1_cfg = NULL;
+               ste->s2_cfg = NULL;
+       } else if (smmu_domain->stage == ARM_SMMU_DOMAIN_S1) {
                ste->s1_cfg = &smmu_domain->s1_cfg;
                ste->s2_cfg = NULL;
                arm_smmu_write_ctx_desc(smmu, ste->s1_cfg);
@@ -1653,10 +1666,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
                ste->s2_cfg = &smmu_domain->s2_cfg;
        }
 
-       ret = arm_smmu_install_ste_for_dev(dev->iommu_fwspec);
-       if (ret < 0)
-               ste->valid = false;
-
+       arm_smmu_install_ste_for_dev(dev->iommu_fwspec);
 out_unlock:
        mutex_unlock(&smmu_domain->init_mutex);
        return ret;
@@ -1704,6 +1714,9 @@ arm_smmu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova)
        struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
        struct io_pgtable_ops *ops = smmu_domain->pgtbl_ops;
 
+       if (domain->type == IOMMU_DOMAIN_IDENTITY)
+               return iova;
+
        if (!ops)
                return 0;
 
@@ -1807,7 +1820,7 @@ static void arm_smmu_remove_device(struct device *dev)
 
        master = fwspec->iommu_priv;
        smmu = master->smmu;
-       if (master && master->ste.valid)
+       if (master && master->ste.assigned)
                arm_smmu_detach_dev(dev);
        iommu_group_remove_device(dev);
        iommu_device_unlink(&smmu->iommu, dev);
@@ -1837,6 +1850,9 @@ static int arm_smmu_domain_get_attr(struct iommu_domain *domain,
 {
        struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
 
+       if (domain->type != IOMMU_DOMAIN_UNMANAGED)
+               return -EINVAL;
+
        switch (attr) {
        case DOMAIN_ATTR_NESTING:
                *(int *)data = (smmu_domain->stage == ARM_SMMU_DOMAIN_NESTED);
@@ -1852,6 +1868,9 @@ static int arm_smmu_domain_set_attr(struct iommu_domain *domain,
        int ret = 0;
        struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
 
+       if (domain->type != IOMMU_DOMAIN_UNMANAGED)
+               return -EINVAL;
+
        mutex_lock(&smmu_domain->init_mutex);
 
        switch (attr) {
@@ -1893,6 +1912,8 @@ static void arm_smmu_get_resv_regions(struct device *dev,
                return;
 
        list_add_tail(&region->list, head);
+
+       iommu_dma_get_resv_regions(dev, head);
 }
 
 static void arm_smmu_put_resv_regions(struct device *dev,
@@ -2761,51 +2782,9 @@ static struct platform_driver arm_smmu_driver = {
        .probe  = arm_smmu_device_probe,
        .remove = arm_smmu_device_remove,
 };
+module_platform_driver(arm_smmu_driver);
 
-static int __init arm_smmu_init(void)
-{
-       static bool registered;
-       int ret = 0;
-
-       if (!registered) {
-               ret = platform_driver_register(&arm_smmu_driver);
-               registered = !ret;
-       }
-       return ret;
-}
-
-static void __exit arm_smmu_exit(void)
-{
-       return platform_driver_unregister(&arm_smmu_driver);
-}
-
-subsys_initcall(arm_smmu_init);
-module_exit(arm_smmu_exit);
-
-static int __init arm_smmu_of_init(struct device_node *np)
-{
-       int ret = arm_smmu_init();
-
-       if (ret)
-               return ret;
-
-       if (!of_platform_device_create(np, NULL, platform_bus_type.dev_root))
-               return -ENODEV;
-
-       return 0;
-}
-IOMMU_OF_DECLARE(arm_smmuv3, "arm,smmu-v3", arm_smmu_of_init);
-
-#ifdef CONFIG_ACPI
-static int __init acpi_smmu_v3_init(struct acpi_table_header *table)
-{
-       if (iort_node_match(ACPI_IORT_NODE_SMMU_V3))
-               return arm_smmu_init();
-
-       return 0;
-}
-IORT_ACPI_DECLARE(arm_smmu_v3, ACPI_SIG_IORT, acpi_smmu_v3_init);
-#endif
+IOMMU_OF_DECLARE(arm_smmuv3, "arm,smmu-v3", NULL);
 
 MODULE_DESCRIPTION("IOMMU API for ARM architected SMMUv3 implementations");
 MODULE_AUTHOR("Will Deacon <will.deacon@arm.com>");
index b493c99e17f74de338805167c3ddb104e3354b62..7ec30b08b3bdc285872e0139997a300497450f98 100644 (file)
 #define ARM_SMMU_GR0_sTLBGSTATUS       0x74
 #define sTLBGSTATUS_GSACTIVE           (1 << 0)
 #define TLB_LOOP_TIMEOUT               1000000 /* 1s! */
+#define TLB_SPIN_COUNT                 10
 
 /* Stream mapping registers */
 #define ARM_SMMU_GR0_SMR(n)            (0x800 + ((n) << 2))
@@ -216,8 +217,7 @@ enum arm_smmu_s2cr_privcfg {
 #define CBA2R_VMID_MASK                        0xffff
 
 /* Translation context bank */
-#define ARM_SMMU_CB_BASE(smmu)         ((smmu)->base + ((smmu)->size >> 1))
-#define ARM_SMMU_CB(smmu, n)           ((n) * (1 << (smmu)->pgshift))
+#define ARM_SMMU_CB(smmu, n)   ((smmu)->cb_base + ((n) << (smmu)->pgshift))
 
 #define ARM_SMMU_CB_SCTLR              0x0
 #define ARM_SMMU_CB_ACTLR              0x4
@@ -238,6 +238,8 @@ enum arm_smmu_s2cr_privcfg {
 #define ARM_SMMU_CB_S1_TLBIVAL         0x620
 #define ARM_SMMU_CB_S2_TLBIIPAS2       0x630
 #define ARM_SMMU_CB_S2_TLBIIPAS2L      0x638
+#define ARM_SMMU_CB_TLBSYNC            0x7f0
+#define ARM_SMMU_CB_TLBSTATUS          0x7f4
 #define ARM_SMMU_CB_ATS1PR             0x800
 #define ARM_SMMU_CB_ATSR               0x8f0
 
@@ -344,7 +346,7 @@ struct arm_smmu_device {
        struct device                   *dev;
 
        void __iomem                    *base;
-       unsigned long                   size;
+       void __iomem                    *cb_base;
        unsigned long                   pgshift;
 
 #define ARM_SMMU_FEAT_COHERENT_WALK    (1 << 0)
@@ -404,18 +406,20 @@ enum arm_smmu_context_fmt {
 struct arm_smmu_cfg {
        u8                              cbndx;
        u8                              irptndx;
+       union {
+               u16                     asid;
+               u16                     vmid;
+       };
        u32                             cbar;
        enum arm_smmu_context_fmt       fmt;
 };
 #define INVALID_IRPTNDX                        0xff
 
-#define ARM_SMMU_CB_ASID(smmu, cfg) ((u16)(smmu)->cavium_id_base + (cfg)->cbndx)
-#define ARM_SMMU_CB_VMID(smmu, cfg) ((u16)(smmu)->cavium_id_base + (cfg)->cbndx + 1)
-
 enum arm_smmu_domain_stage {
        ARM_SMMU_DOMAIN_S1 = 0,
        ARM_SMMU_DOMAIN_S2,
        ARM_SMMU_DOMAIN_NESTED,
+       ARM_SMMU_DOMAIN_BYPASS,
 };
 
 struct arm_smmu_domain {
@@ -569,49 +573,67 @@ static void __arm_smmu_free_bitmap(unsigned long *map, int idx)
 }
 
 /* Wait for any pending TLB invalidations to complete */
-static void __arm_smmu_tlb_sync(struct arm_smmu_device *smmu)
+static void __arm_smmu_tlb_sync(struct arm_smmu_device *smmu,
+                               void __iomem *sync, void __iomem *status)
 {
-       int count = 0;
-       void __iomem *gr0_base = ARM_SMMU_GR0(smmu);
-
-       writel_relaxed(0, gr0_base + ARM_SMMU_GR0_sTLBGSYNC);
-       while (readl_relaxed(gr0_base + ARM_SMMU_GR0_sTLBGSTATUS)
-              & sTLBGSTATUS_GSACTIVE) {
-               cpu_relax();
-               if (++count == TLB_LOOP_TIMEOUT) {
-                       dev_err_ratelimited(smmu->dev,
-                       "TLB sync timed out -- SMMU may be deadlocked\n");
-                       return;
+       unsigned int spin_cnt, delay;
+
+       writel_relaxed(0, sync);
+       for (delay = 1; delay < TLB_LOOP_TIMEOUT; delay *= 2) {
+               for (spin_cnt = TLB_SPIN_COUNT; spin_cnt > 0; spin_cnt--) {
+                       if (!(readl_relaxed(status) & sTLBGSTATUS_GSACTIVE))
+                               return;
+                       cpu_relax();
                }
-               udelay(1);
+               udelay(delay);
        }
+       dev_err_ratelimited(smmu->dev,
+                           "TLB sync timed out -- SMMU may be deadlocked\n");
 }
 
-static void arm_smmu_tlb_sync(void *cookie)
+static void arm_smmu_tlb_sync_global(struct arm_smmu_device *smmu)
+{
+       void __iomem *base = ARM_SMMU_GR0(smmu);
+
+       __arm_smmu_tlb_sync(smmu, base + ARM_SMMU_GR0_sTLBGSYNC,
+                           base + ARM_SMMU_GR0_sTLBGSTATUS);
+}
+
+static void arm_smmu_tlb_sync_context(void *cookie)
 {
        struct arm_smmu_domain *smmu_domain = cookie;
-       __arm_smmu_tlb_sync(smmu_domain->smmu);
+       struct arm_smmu_device *smmu = smmu_domain->smmu;
+       void __iomem *base = ARM_SMMU_CB(smmu, smmu_domain->cfg.cbndx);
+
+       __arm_smmu_tlb_sync(smmu, base + ARM_SMMU_CB_TLBSYNC,
+                           base + ARM_SMMU_CB_TLBSTATUS);
 }
 
-static void arm_smmu_tlb_inv_context(void *cookie)
+static void arm_smmu_tlb_sync_vmid(void *cookie)
+{
+       struct arm_smmu_domain *smmu_domain = cookie;
+
+       arm_smmu_tlb_sync_global(smmu_domain->smmu);
+}
+
+static void arm_smmu_tlb_inv_context_s1(void *cookie)
 {
        struct arm_smmu_domain *smmu_domain = cookie;
        struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
-       struct arm_smmu_device *smmu = smmu_domain->smmu;
-       bool stage1 = cfg->cbar != CBAR_TYPE_S2_TRANS;
-       void __iomem *base;
+       void __iomem *base = ARM_SMMU_CB(smmu_domain->smmu, cfg->cbndx);
 
-       if (stage1) {
-               base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);
-               writel_relaxed(ARM_SMMU_CB_ASID(smmu, cfg),
-                              base + ARM_SMMU_CB_S1_TLBIASID);
-       } else {
-               base = ARM_SMMU_GR0(smmu);
-               writel_relaxed(ARM_SMMU_CB_VMID(smmu, cfg),
-                              base + ARM_SMMU_GR0_TLBIVMID);
-       }
+       writel_relaxed(cfg->asid, base + ARM_SMMU_CB_S1_TLBIASID);
+       arm_smmu_tlb_sync_context(cookie);
+}
+
+static void arm_smmu_tlb_inv_context_s2(void *cookie)
+{
+       struct arm_smmu_domain *smmu_domain = cookie;
+       struct arm_smmu_device *smmu = smmu_domain->smmu;
+       void __iomem *base = ARM_SMMU_GR0(smmu);
 
-       __arm_smmu_tlb_sync(smmu);
+       writel_relaxed(smmu_domain->cfg.vmid, base + ARM_SMMU_GR0_TLBIVMID);
+       arm_smmu_tlb_sync_global(smmu);
 }
 
 static void arm_smmu_tlb_inv_range_nosync(unsigned long iova, size_t size,
@@ -619,31 +641,28 @@ static void arm_smmu_tlb_inv_range_nosync(unsigned long iova, size_t size,
 {
        struct arm_smmu_domain *smmu_domain = cookie;
        struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
-       struct arm_smmu_device *smmu = smmu_domain->smmu;
        bool stage1 = cfg->cbar != CBAR_TYPE_S2_TRANS;
-       void __iomem *reg;
+       void __iomem *reg = ARM_SMMU_CB(smmu_domain->smmu, cfg->cbndx);
 
        if (stage1) {
-               reg = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);
                reg += leaf ? ARM_SMMU_CB_S1_TLBIVAL : ARM_SMMU_CB_S1_TLBIVA;
 
                if (cfg->fmt != ARM_SMMU_CTX_FMT_AARCH64) {
                        iova &= ~12UL;
-                       iova |= ARM_SMMU_CB_ASID(smmu, cfg);
+                       iova |= cfg->asid;
                        do {
                                writel_relaxed(iova, reg);
                                iova += granule;
                        } while (size -= granule);
                } else {
                        iova >>= 12;
-                       iova |= (u64)ARM_SMMU_CB_ASID(smmu, cfg) << 48;
+                       iova |= (u64)cfg->asid << 48;
                        do {
                                writeq_relaxed(iova, reg);
                                iova += granule >> 12;
                        } while (size -= granule);
                }
-       } else if (smmu->version == ARM_SMMU_V2) {
-               reg = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);
+       } else {
                reg += leaf ? ARM_SMMU_CB_S2_TLBIIPAS2L :
                              ARM_SMMU_CB_S2_TLBIIPAS2;
                iova >>= 12;
@@ -651,16 +670,40 @@ static void arm_smmu_tlb_inv_range_nosync(unsigned long iova, size_t size,
                        smmu_write_atomic_lq(iova, reg);
                        iova += granule >> 12;
                } while (size -= granule);
-       } else {
-               reg = ARM_SMMU_GR0(smmu) + ARM_SMMU_GR0_TLBIVMID;
-               writel_relaxed(ARM_SMMU_CB_VMID(smmu, cfg), reg);
        }
 }
 
-static const struct iommu_gather_ops arm_smmu_gather_ops = {
-       .tlb_flush_all  = arm_smmu_tlb_inv_context,
+/*
+ * On MMU-401 at least, the cost of firing off multiple TLBIVMIDs appears
+ * almost negligible, but the benefit of getting the first one in as far ahead
+ * of the sync as possible is significant, hence we don't just make this a
+ * no-op and set .tlb_sync to arm_smmu_inv_context_s2() as you might think.
+ */
+static void arm_smmu_tlb_inv_vmid_nosync(unsigned long iova, size_t size,
+                                        size_t granule, bool leaf, void *cookie)
+{
+       struct arm_smmu_domain *smmu_domain = cookie;
+       void __iomem *base = ARM_SMMU_GR0(smmu_domain->smmu);
+
+       writel_relaxed(smmu_domain->cfg.vmid, base + ARM_SMMU_GR0_TLBIVMID);
+}
+
+static const struct iommu_gather_ops arm_smmu_s1_tlb_ops = {
+       .tlb_flush_all  = arm_smmu_tlb_inv_context_s1,
        .tlb_add_flush  = arm_smmu_tlb_inv_range_nosync,
-       .tlb_sync       = arm_smmu_tlb_sync,
+       .tlb_sync       = arm_smmu_tlb_sync_context,
+};
+
+static const struct iommu_gather_ops arm_smmu_s2_tlb_ops_v2 = {
+       .tlb_flush_all  = arm_smmu_tlb_inv_context_s2,
+       .tlb_add_flush  = arm_smmu_tlb_inv_range_nosync,
+       .tlb_sync       = arm_smmu_tlb_sync_context,
+};
+
+static const struct iommu_gather_ops arm_smmu_s2_tlb_ops_v1 = {
+       .tlb_flush_all  = arm_smmu_tlb_inv_context_s2,
+       .tlb_add_flush  = arm_smmu_tlb_inv_vmid_nosync,
+       .tlb_sync       = arm_smmu_tlb_sync_vmid,
 };
 
 static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
@@ -673,7 +716,7 @@ static irqreturn_t arm_smmu_context_fault(int irq, void *dev)
        struct arm_smmu_device *smmu = smmu_domain->smmu;
        void __iomem *cb_base;
 
-       cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);
+       cb_base = ARM_SMMU_CB(smmu, cfg->cbndx);
        fsr = readl_relaxed(cb_base + ARM_SMMU_CB_FSR);
 
        if (!(fsr & FSR_FAULT))
@@ -726,7 +769,7 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
 
        gr1_base = ARM_SMMU_GR1(smmu);
        stage1 = cfg->cbar != CBAR_TYPE_S2_TRANS;
-       cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);
+       cb_base = ARM_SMMU_CB(smmu, cfg->cbndx);
 
        if (smmu->version > ARM_SMMU_V1) {
                if (cfg->fmt == ARM_SMMU_CTX_FMT_AARCH64)
@@ -735,7 +778,7 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
                        reg = CBA2R_RW64_32BIT;
                /* 16-bit VMIDs live in CBA2R */
                if (smmu->features & ARM_SMMU_FEAT_VMID16)
-                       reg |= ARM_SMMU_CB_VMID(smmu, cfg) << CBA2R_VMID_SHIFT;
+                       reg |= cfg->vmid << CBA2R_VMID_SHIFT;
 
                writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBA2R(cfg->cbndx));
        }
@@ -754,34 +797,15 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
                        (CBAR_S1_MEMATTR_WB << CBAR_S1_MEMATTR_SHIFT);
        } else if (!(smmu->features & ARM_SMMU_FEAT_VMID16)) {
                /* 8-bit VMIDs live in CBAR */
-               reg |= ARM_SMMU_CB_VMID(smmu, cfg) << CBAR_VMID_SHIFT;
+               reg |= cfg->vmid << CBAR_VMID_SHIFT;
        }
        writel_relaxed(reg, gr1_base + ARM_SMMU_GR1_CBAR(cfg->cbndx));
 
-       /* TTBRs */
-       if (stage1) {
-               u16 asid = ARM_SMMU_CB_ASID(smmu, cfg);
-
-               if (cfg->fmt == ARM_SMMU_CTX_FMT_AARCH32_S) {
-                       reg = pgtbl_cfg->arm_v7s_cfg.ttbr[0];
-                       writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBR0);
-                       reg = pgtbl_cfg->arm_v7s_cfg.ttbr[1];
-                       writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBR1);
-                       writel_relaxed(asid, cb_base + ARM_SMMU_CB_CONTEXTIDR);
-               } else {
-                       reg64 = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[0];
-                       reg64 |= (u64)asid << TTBRn_ASID_SHIFT;
-                       writeq_relaxed(reg64, cb_base + ARM_SMMU_CB_TTBR0);
-                       reg64 = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[1];
-                       reg64 |= (u64)asid << TTBRn_ASID_SHIFT;
-                       writeq_relaxed(reg64, cb_base + ARM_SMMU_CB_TTBR1);
-               }
-       } else {
-               reg64 = pgtbl_cfg->arm_lpae_s2_cfg.vttbr;
-               writeq_relaxed(reg64, cb_base + ARM_SMMU_CB_TTBR0);
-       }
-
-       /* TTBCR */
+       /*
+        * TTBCR
+        * We must write this before the TTBRs, since it determines the
+        * access behaviour of some fields (in particular, ASID[15:8]).
+        */
        if (stage1) {
                if (cfg->fmt == ARM_SMMU_CTX_FMT_AARCH32_S) {
                        reg = pgtbl_cfg->arm_v7s_cfg.tcr;
@@ -800,6 +824,27 @@ static void arm_smmu_init_context_bank(struct arm_smmu_domain *smmu_domain,
        }
        writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBCR);
 
+       /* TTBRs */
+       if (stage1) {
+               if (cfg->fmt == ARM_SMMU_CTX_FMT_AARCH32_S) {
+                       reg = pgtbl_cfg->arm_v7s_cfg.ttbr[0];
+                       writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBR0);
+                       reg = pgtbl_cfg->arm_v7s_cfg.ttbr[1];
+                       writel_relaxed(reg, cb_base + ARM_SMMU_CB_TTBR1);
+                       writel_relaxed(cfg->asid, cb_base + ARM_SMMU_CB_CONTEXTIDR);
+               } else {
+                       reg64 = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[0];
+                       reg64 |= (u64)cfg->asid << TTBRn_ASID_SHIFT;
+                       writeq_relaxed(reg64, cb_base + ARM_SMMU_CB_TTBR0);
+                       reg64 = pgtbl_cfg->arm_lpae_s1_cfg.ttbr[1];
+                       reg64 |= (u64)cfg->asid << TTBRn_ASID_SHIFT;
+                       writeq_relaxed(reg64, cb_base + ARM_SMMU_CB_TTBR1);
+               }
+       } else {
+               reg64 = pgtbl_cfg->arm_lpae_s2_cfg.vttbr;
+               writeq_relaxed(reg64, cb_base + ARM_SMMU_CB_TTBR0);
+       }
+
        /* MAIRs (stage-1 only) */
        if (stage1) {
                if (cfg->fmt == ARM_SMMU_CTX_FMT_AARCH32_S) {
@@ -833,11 +878,18 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
        enum io_pgtable_fmt fmt;
        struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
        struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
+       const struct iommu_gather_ops *tlb_ops;
 
        mutex_lock(&smmu_domain->init_mutex);
        if (smmu_domain->smmu)
                goto out_unlock;
 
+       if (domain->type == IOMMU_DOMAIN_IDENTITY) {
+               smmu_domain->stage = ARM_SMMU_DOMAIN_BYPASS;
+               smmu_domain->smmu = smmu;
+               goto out_unlock;
+       }
+
        /*
         * Mapping the requested stage onto what we support is surprisingly
         * complicated, mainly because the spec allows S1+S2 SMMUs without
@@ -904,6 +956,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
                        ias = min(ias, 32UL);
                        oas = min(oas, 32UL);
                }
+               tlb_ops = &arm_smmu_s1_tlb_ops;
                break;
        case ARM_SMMU_DOMAIN_NESTED:
                /*
@@ -922,12 +975,15 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
                        ias = min(ias, 40UL);
                        oas = min(oas, 40UL);
                }
+               if (smmu->version == ARM_SMMU_V2)
+                       tlb_ops = &arm_smmu_s2_tlb_ops_v2;
+               else
+                       tlb_ops = &arm_smmu_s2_tlb_ops_v1;
                break;
        default:
                ret = -EINVAL;
                goto out_unlock;
        }
-
        ret = __arm_smmu_alloc_bitmap(smmu->context_map, start,
                                      smmu->num_context_banks);
        if (ret < 0)
@@ -941,11 +997,16 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
                cfg->irptndx = cfg->cbndx;
        }
 
+       if (smmu_domain->stage == ARM_SMMU_DOMAIN_S2)
+               cfg->vmid = cfg->cbndx + 1 + smmu->cavium_id_base;
+       else
+               cfg->asid = cfg->cbndx + smmu->cavium_id_base;
+
        pgtbl_cfg = (struct io_pgtable_cfg) {
                .pgsize_bitmap  = smmu->pgsize_bitmap,
                .ias            = ias,
                .oas            = oas,
-               .tlb            = &arm_smmu_gather_ops,
+               .tlb            = tlb_ops,
                .iommu_dev      = smmu->dev,
        };
 
@@ -998,14 +1059,14 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
        void __iomem *cb_base;
        int irq;
 
-       if (!smmu)
+       if (!smmu || domain->type == IOMMU_DOMAIN_IDENTITY)
                return;
 
        /*
         * Disable the context bank and free the page tables before freeing
         * it.
         */
-       cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);
+       cb_base = ARM_SMMU_CB(smmu, cfg->cbndx);
        writel_relaxed(0, cb_base + ARM_SMMU_CB_SCTLR);
 
        if (cfg->irptndx != INVALID_IRPTNDX) {
@@ -1021,7 +1082,9 @@ static struct iommu_domain *arm_smmu_domain_alloc(unsigned type)
 {
        struct arm_smmu_domain *smmu_domain;
 
-       if (type != IOMMU_DOMAIN_UNMANAGED && type != IOMMU_DOMAIN_DMA)
+       if (type != IOMMU_DOMAIN_UNMANAGED &&
+           type != IOMMU_DOMAIN_DMA &&
+           type != IOMMU_DOMAIN_IDENTITY)
                return NULL;
        /*
         * Allocate the domain and initialise some of its data structures.
@@ -1250,10 +1313,15 @@ static int arm_smmu_domain_add_master(struct arm_smmu_domain *smmu_domain,
 {
        struct arm_smmu_device *smmu = smmu_domain->smmu;
        struct arm_smmu_s2cr *s2cr = smmu->s2crs;
-       enum arm_smmu_s2cr_type type = S2CR_TYPE_TRANS;
        u8 cbndx = smmu_domain->cfg.cbndx;
+       enum arm_smmu_s2cr_type type;
        int i, idx;
 
+       if (smmu_domain->stage == ARM_SMMU_DOMAIN_BYPASS)
+               type = S2CR_TYPE_BYPASS;
+       else
+               type = S2CR_TYPE_TRANS;
+
        for_each_cfg_sme(fwspec, i, idx) {
                if (type == s2cr[idx].type && cbndx == s2cr[idx].cbndx)
                        continue;
@@ -1356,7 +1424,7 @@ static phys_addr_t arm_smmu_iova_to_phys_hard(struct iommu_domain *domain,
        u64 phys;
        unsigned long va;
 
-       cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, cfg->cbndx);
+       cb_base = ARM_SMMU_CB(smmu, cfg->cbndx);
 
        /* ATS1 registers can only be written atomically */
        va = iova & ~0xfffUL;
@@ -1391,6 +1459,9 @@ static phys_addr_t arm_smmu_iova_to_phys(struct iommu_domain *domain,
        struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
        struct io_pgtable_ops *ops= smmu_domain->pgtbl_ops;
 
+       if (domain->type == IOMMU_DOMAIN_IDENTITY)
+               return iova;
+
        if (!ops)
                return 0;
 
@@ -1467,7 +1538,7 @@ static int arm_smmu_add_device(struct device *dev)
                }
                if (mask & ~smmu->smr_mask_mask) {
                        dev_err(dev, "SMR mask 0x%x out of range for SMMU (0x%x)\n",
-                               sid, smmu->smr_mask_mask);
+                               mask, smmu->smr_mask_mask);
                        goto out_free;
                }
        }
@@ -1549,6 +1620,9 @@ static int arm_smmu_domain_get_attr(struct iommu_domain *domain,
 {
        struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
 
+       if (domain->type != IOMMU_DOMAIN_UNMANAGED)
+               return -EINVAL;
+
        switch (attr) {
        case DOMAIN_ATTR_NESTING:
                *(int *)data = (smmu_domain->stage == ARM_SMMU_DOMAIN_NESTED);
@@ -1564,6 +1638,9 @@ static int arm_smmu_domain_set_attr(struct iommu_domain *domain,
        int ret = 0;
        struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
 
+       if (domain->type != IOMMU_DOMAIN_UNMANAGED)
+               return -EINVAL;
+
        mutex_lock(&smmu_domain->init_mutex);
 
        switch (attr) {
@@ -1590,13 +1667,15 @@ out_unlock:
 
 static int arm_smmu_of_xlate(struct device *dev, struct of_phandle_args *args)
 {
-       u32 fwid = 0;
+       u32 mask, fwid = 0;
 
        if (args->args_count > 0)
                fwid |= (u16)args->args[0];
 
        if (args->args_count > 1)
                fwid |= (u16)args->args[1] << SMR_MASK_SHIFT;
+       else if (!of_property_read_u32(args->np, "stream-match-mask", &mask))
+               fwid |= (u16)mask << SMR_MASK_SHIFT;
 
        return iommu_fwspec_add_ids(dev, &fwid, 1);
 }
@@ -1613,6 +1692,8 @@ static void arm_smmu_get_resv_regions(struct device *dev,
                return;
 
        list_add_tail(&region->list, head);
+
+       iommu_dma_get_resv_regions(dev, head);
 }
 
 static void arm_smmu_put_resv_regions(struct device *dev,
@@ -1683,7 +1764,7 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
 
        /* Make sure all context banks are disabled and clear CB_FSR  */
        for (i = 0; i < smmu->num_context_banks; ++i) {
-               cb_base = ARM_SMMU_CB_BASE(smmu) + ARM_SMMU_CB(smmu, i);
+               cb_base = ARM_SMMU_CB(smmu, i);
                writel_relaxed(0, cb_base + ARM_SMMU_CB_SCTLR);
                writel_relaxed(FSR_FAULT, cb_base + ARM_SMMU_CB_FSR);
                /*
@@ -1729,7 +1810,7 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu)
                reg |= sCR0_EXIDENABLE;
 
        /* Push the button */
-       __arm_smmu_tlb_sync(smmu);
+       arm_smmu_tlb_sync_global(smmu);
        writel(reg, ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0);
 }
 
@@ -1863,11 +1944,11 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
 
        /* Check for size mismatch of SMMU address space from mapped region */
        size = 1 << (((id >> ID1_NUMPAGENDXB_SHIFT) & ID1_NUMPAGENDXB_MASK) + 1);
-       size *= 2 << smmu->pgshift;
-       if (smmu->size != size)
+       size <<= smmu->pgshift;
+       if (smmu->cb_base != gr0_base + size)
                dev_warn(smmu->dev,
-                       "SMMU address space size (0x%lx) differs from mapped region size (0x%lx)!\n",
-                       size, smmu->size);
+                       "SMMU address space size (0x%lx) differs from mapped region size (0x%tx)!\n",
+                       size * 2, (smmu->cb_base - gr0_base) * 2);
 
        smmu->num_s2_context_banks = (id >> ID1_NUMS2CB_SHIFT) & ID1_NUMS2CB_MASK;
        smmu->num_context_banks = (id >> ID1_NUMCB_SHIFT) & ID1_NUMCB_MASK;
@@ -1887,6 +1968,7 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu)
                        atomic_add_return(smmu->num_context_banks,
                                          &cavium_smmu_context_count);
                smmu->cavium_id_base -= smmu->num_context_banks;
+               dev_notice(smmu->dev, "\tenabling workaround for Cavium erratum 27704\n");
        }
 
        /* ID2 */
@@ -2075,6 +2157,23 @@ static int arm_smmu_device_dt_probe(struct platform_device *pdev,
        return 0;
 }
 
+static void arm_smmu_bus_init(void)
+{
+       /* Oh, for a proper bus abstraction */
+       if (!iommu_present(&platform_bus_type))
+               bus_set_iommu(&platform_bus_type, &arm_smmu_ops);
+#ifdef CONFIG_ARM_AMBA
+       if (!iommu_present(&amba_bustype))
+               bus_set_iommu(&amba_bustype, &arm_smmu_ops);
+#endif
+#ifdef CONFIG_PCI
+       if (!iommu_present(&pci_bus_type)) {
+               pci_request_acs();
+               bus_set_iommu(&pci_bus_type, &arm_smmu_ops);
+       }
+#endif
+}
+
 static int arm_smmu_device_probe(struct platform_device *pdev)
 {
        struct resource *res;
@@ -2103,7 +2202,7 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
        smmu->base = devm_ioremap_resource(dev, res);
        if (IS_ERR(smmu->base))
                return PTR_ERR(smmu->base);
-       smmu->size = resource_size(res);
+       smmu->cb_base = smmu->base + resource_size(res) / 2;
 
        num_irqs = 0;
        while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, num_irqs))) {
@@ -2180,21 +2279,30 @@ static int arm_smmu_device_probe(struct platform_device *pdev)
        arm_smmu_device_reset(smmu);
        arm_smmu_test_smr_masks(smmu);
 
-       /* Oh, for a proper bus abstraction */
-       if (!iommu_present(&platform_bus_type))
-               bus_set_iommu(&platform_bus_type, &arm_smmu_ops);
-#ifdef CONFIG_ARM_AMBA
-       if (!iommu_present(&amba_bustype))
-               bus_set_iommu(&amba_bustype, &arm_smmu_ops);
-#endif
-#ifdef CONFIG_PCI
-       if (!iommu_present(&pci_bus_type)) {
-               pci_request_acs();
-               bus_set_iommu(&pci_bus_type, &arm_smmu_ops);
-       }
-#endif
+       /*
+        * For ACPI and generic DT bindings, an SMMU will be probed before
+        * any device which might need it, so we want the bus ops in place
+        * ready to handle default domain setup as soon as any SMMU exists.
+        */
+       if (!using_legacy_binding)
+               arm_smmu_bus_init();
+
+       return 0;
+}
+
+/*
+ * With the legacy DT binding in play, though, we have no guarantees about
+ * probe order, but then we're also not doing default domains, so we can
+ * delay setting bus ops until we're sure every possible SMMU is ready,
+ * and that way ensure that no add_device() calls get missed.
+ */
+static int arm_smmu_legacy_bus_init(void)
+{
+       if (using_legacy_binding)
+               arm_smmu_bus_init();
        return 0;
 }
+device_initcall_sync(arm_smmu_legacy_bus_init);
 
 static int arm_smmu_device_remove(struct platform_device *pdev)
 {
@@ -2219,56 +2327,14 @@ static struct platform_driver arm_smmu_driver = {
        .probe  = arm_smmu_device_probe,
        .remove = arm_smmu_device_remove,
 };
-
-static int __init arm_smmu_init(void)
-{
-       static bool registered;
-       int ret = 0;
-
-       if (!registered) {
-               ret = platform_driver_register(&arm_smmu_driver);
-               registered = !ret;
-       }
-       return ret;
-}
-
-static void __exit arm_smmu_exit(void)
-{
-       return platform_driver_unregister(&arm_smmu_driver);
-}
-
-subsys_initcall(arm_smmu_init);
-module_exit(arm_smmu_exit);
-
-static int __init arm_smmu_of_init(struct device_node *np)
-{
-       int ret = arm_smmu_init();
-
-       if (ret)
-               return ret;
-
-       if (!of_platform_device_create(np, NULL, platform_bus_type.dev_root))
-               return -ENODEV;
-
-       return 0;
-}
-IOMMU_OF_DECLARE(arm_smmuv1, "arm,smmu-v1", arm_smmu_of_init);
-IOMMU_OF_DECLARE(arm_smmuv2, "arm,smmu-v2", arm_smmu_of_init);
-IOMMU_OF_DECLARE(arm_mmu400, "arm,mmu-400", arm_smmu_of_init);
-IOMMU_OF_DECLARE(arm_mmu401, "arm,mmu-401", arm_smmu_of_init);
-IOMMU_OF_DECLARE(arm_mmu500, "arm,mmu-500", arm_smmu_of_init);
-IOMMU_OF_DECLARE(cavium_smmuv2, "cavium,smmu-v2", arm_smmu_of_init);
-
-#ifdef CONFIG_ACPI
-static int __init arm_smmu_acpi_init(struct acpi_table_header *table)
-{
-       if (iort_node_match(ACPI_IORT_NODE_SMMU))
-               return arm_smmu_init();
-
-       return 0;
-}
-IORT_ACPI_DECLARE(arm_smmu, ACPI_SIG_IORT, arm_smmu_acpi_init);
-#endif
+module_platform_driver(arm_smmu_driver);
+
+IOMMU_OF_DECLARE(arm_smmuv1, "arm,smmu-v1", NULL);
+IOMMU_OF_DECLARE(arm_smmuv2, "arm,smmu-v2", NULL);
+IOMMU_OF_DECLARE(arm_mmu400, "arm,mmu-400", NULL);
+IOMMU_OF_DECLARE(arm_mmu401, "arm,mmu-401", NULL);
+IOMMU_OF_DECLARE(arm_mmu500, "arm,mmu-500", NULL);
+IOMMU_OF_DECLARE(cavium_smmuv2, "cavium,smmu-v2", NULL);
 
 MODULE_DESCRIPTION("IOMMU API for ARM architected SMMU implementations");
 MODULE_AUTHOR("Will Deacon <will.deacon@arm.com>");
index 48d36ce59efbfd6305f8e85e9ae85875f71215f8..62618e77bedc9e2e8bf9ae241fcf127383735a73 100644 (file)
@@ -61,15 +61,6 @@ static inline size_t cookie_msi_granule(struct iommu_dma_cookie *cookie)
        return PAGE_SIZE;
 }
 
-static inline struct iova_domain *cookie_iovad(struct iommu_domain *domain)
-{
-       struct iommu_dma_cookie *cookie = domain->iova_cookie;
-
-       if (cookie->type == IOMMU_DMA_IOVA_COOKIE)
-               return &cookie->iovad;
-       return NULL;
-}
-
 static struct iommu_dma_cookie *cookie_alloc(enum iommu_dma_cookie_type type)
 {
        struct iommu_dma_cookie *cookie;
@@ -167,22 +158,99 @@ void iommu_put_dma_cookie(struct iommu_domain *domain)
 }
 EXPORT_SYMBOL(iommu_put_dma_cookie);
 
-static void iova_reserve_pci_windows(struct pci_dev *dev,
-               struct iova_domain *iovad)
+/**
+ * iommu_dma_get_resv_regions - Reserved region driver helper
+ * @dev: Device from iommu_get_resv_regions()
+ * @list: Reserved region list from iommu_get_resv_regions()
+ *
+ * IOMMU drivers can use this to implement their .get_resv_regions callback
+ * for general non-IOMMU-specific reservations. Currently, this covers host
+ * bridge windows for PCI devices.
+ */
+void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list)
 {
-       struct pci_host_bridge *bridge = pci_find_host_bridge(dev->bus);
+       struct pci_host_bridge *bridge;
        struct resource_entry *window;
-       unsigned long lo, hi;
 
+       if (!dev_is_pci(dev))
+               return;
+
+       bridge = pci_find_host_bridge(to_pci_dev(dev)->bus);
        resource_list_for_each_entry(window, &bridge->windows) {
-               if (resource_type(window->res) != IORESOURCE_MEM &&
-                   resource_type(window->res) != IORESOURCE_IO)
+               struct iommu_resv_region *region;
+               phys_addr_t start;
+               size_t length;
+
+               if (resource_type(window->res) != IORESOURCE_MEM)
+                       continue;
+
+               start = window->res->start - window->offset;
+               length = window->res->end - window->res->start + 1;
+               region = iommu_alloc_resv_region(start, length, 0,
+                               IOMMU_RESV_RESERVED);
+               if (!region)
+                       return;
+
+               list_add_tail(&region->list, list);
+       }
+}
+EXPORT_SYMBOL(iommu_dma_get_resv_regions);
+
+static int cookie_init_hw_msi_region(struct iommu_dma_cookie *cookie,
+               phys_addr_t start, phys_addr_t end)
+{
+       struct iova_domain *iovad = &cookie->iovad;
+       struct iommu_dma_msi_page *msi_page;
+       int i, num_pages;
+
+       start -= iova_offset(iovad, start);
+       num_pages = iova_align(iovad, end - start) >> iova_shift(iovad);
+
+       msi_page = kcalloc(num_pages, sizeof(*msi_page), GFP_KERNEL);
+       if (!msi_page)
+               return -ENOMEM;
+
+       for (i = 0; i < num_pages; i++) {
+               msi_page[i].phys = start;
+               msi_page[i].iova = start;
+               INIT_LIST_HEAD(&msi_page[i].list);
+               list_add(&msi_page[i].list, &cookie->msi_page_list);
+               start += iovad->granule;
+       }
+
+       return 0;
+}
+
+static int iova_reserve_iommu_regions(struct device *dev,
+               struct iommu_domain *domain)
+{
+       struct iommu_dma_cookie *cookie = domain->iova_cookie;
+       struct iova_domain *iovad = &cookie->iovad;
+       struct iommu_resv_region *region;
+       LIST_HEAD(resv_regions);
+       int ret = 0;
+
+       iommu_get_resv_regions(dev, &resv_regions);
+       list_for_each_entry(region, &resv_regions, list) {
+               unsigned long lo, hi;
+
+               /* We ARE the software that manages these! */
+               if (region->type == IOMMU_RESV_SW_MSI)
                        continue;
 
-               lo = iova_pfn(iovad, window->res->start - window->offset);
-               hi = iova_pfn(iovad, window->res->end - window->offset);
+               lo = iova_pfn(iovad, region->start);
+               hi = iova_pfn(iovad, region->start + region->length - 1);
                reserve_iova(iovad, lo, hi);
+
+               if (region->type == IOMMU_RESV_MSI)
+                       ret = cookie_init_hw_msi_region(cookie, region->start,
+                                       region->start + region->length);
+               if (ret)
+                       break;
        }
+       iommu_put_resv_regions(dev, &resv_regions);
+
+       return ret;
 }
 
 /**
@@ -203,7 +271,6 @@ int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base,
        struct iommu_dma_cookie *cookie = domain->iova_cookie;
        struct iova_domain *iovad = &cookie->iovad;
        unsigned long order, base_pfn, end_pfn;
-       bool pci = dev && dev_is_pci(dev);
 
        if (!cookie || cookie->type != IOMMU_DMA_IOVA_COOKIE)
                return -EINVAL;
@@ -233,7 +300,7 @@ int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base,
         * leave the cache limit at the top of their range to save an rb_last()
         * traversal on every allocation.
         */
-       if (pci)
+       if (dev && dev_is_pci(dev))
                end_pfn &= DMA_BIT_MASK(32) >> order;
 
        /* start_pfn is always nonzero for an already-initialised domain */
@@ -248,12 +315,15 @@ int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base,
                 * area cache limit down for the benefit of the smaller one.
                 */
                iovad->dma_32bit_pfn = min(end_pfn, iovad->dma_32bit_pfn);
-       } else {
-               init_iova_domain(iovad, 1UL << order, base_pfn, end_pfn);
-               if (pci)
-                       iova_reserve_pci_windows(to_pci_dev(dev), iovad);
+
+               return 0;
        }
-       return 0;
+
+       init_iova_domain(iovad, 1UL << order, base_pfn, end_pfn);
+       if (!dev)
+               return 0;
+
+       return iova_reserve_iommu_regions(dev, domain);
 }
 EXPORT_SYMBOL(iommu_dma_init_domain);
 
@@ -286,48 +356,67 @@ int dma_info_to_prot(enum dma_data_direction dir, bool coherent,
        }
 }
 
-static struct iova *__alloc_iova(struct iommu_domain *domain, size_t size,
-               dma_addr_t dma_limit, struct device *dev)
+static dma_addr_t iommu_dma_alloc_iova(struct iommu_domain *domain,
+               size_t size, dma_addr_t dma_limit, struct device *dev)
 {
-       struct iova_domain *iovad = cookie_iovad(domain);
-       unsigned long shift = iova_shift(iovad);
-       unsigned long length = iova_align(iovad, size) >> shift;
-       struct iova *iova = NULL;
+       struct iommu_dma_cookie *cookie = domain->iova_cookie;
+       struct iova_domain *iovad = &cookie->iovad;
+       unsigned long shift, iova_len, iova = 0;
+
+       if (cookie->type == IOMMU_DMA_MSI_COOKIE) {
+               cookie->msi_iova += size;
+               return cookie->msi_iova - size;
+       }
+
+       shift = iova_shift(iovad);
+       iova_len = size >> shift;
+       /*
+        * Freeing non-power-of-two-sized allocations back into the IOVA caches
+        * will come back to bite us badly, so we have to waste a bit of space
+        * rounding up anything cacheable to make sure that can't happen. The
+        * order of the unadjusted size will still match upon freeing.
+        */
+       if (iova_len < (1 << (IOVA_RANGE_CACHE_MAX_SIZE - 1)))
+               iova_len = roundup_pow_of_two(iova_len);
 
        if (domain->geometry.force_aperture)
                dma_limit = min(dma_limit, domain->geometry.aperture_end);
 
        /* Try to get PCI devices a SAC address */
        if (dma_limit > DMA_BIT_MASK(32) && dev_is_pci(dev))
-               iova = alloc_iova(iovad, length, DMA_BIT_MASK(32) >> shift,
-                                 true);
-       /*
-        * Enforce size-alignment to be safe - there could perhaps be an
-        * attribute to control this per-device, or at least per-domain...
-        */
+               iova = alloc_iova_fast(iovad, iova_len, DMA_BIT_MASK(32) >> shift);
+
        if (!iova)
-               iova = alloc_iova(iovad, length, dma_limit >> shift, true);
+               iova = alloc_iova_fast(iovad, iova_len, dma_limit >> shift);
 
-       return iova;
+       return (dma_addr_t)iova << shift;
 }
 
-/* The IOVA allocator knows what we mapped, so just unmap whatever that was */
-static void __iommu_dma_unmap(struct iommu_domain *domain, dma_addr_t dma_addr)
+static void iommu_dma_free_iova(struct iommu_dma_cookie *cookie,
+               dma_addr_t iova, size_t size)
 {
-       struct iova_domain *iovad = cookie_iovad(domain);
-       unsigned long shift = iova_shift(iovad);
-       unsigned long pfn = dma_addr >> shift;
-       struct iova *iova = find_iova(iovad, pfn);
-       size_t size;
+       struct iova_domain *iovad = &cookie->iovad;
 
-       if (WARN_ON(!iova))
-               return;
+       /* The MSI case is only ever cleaning up its most recent allocation */
+       if (cookie->type == IOMMU_DMA_MSI_COOKIE)
+               cookie->msi_iova -= size;
+       else
+               free_iova_fast(iovad, iova_pfn(iovad, iova),
+                               size >> iova_shift(iovad));
+}
+
+static void __iommu_dma_unmap(struct iommu_domain *domain, dma_addr_t dma_addr,
+               size_t size)
+{
+       struct iommu_dma_cookie *cookie = domain->iova_cookie;
+       struct iova_domain *iovad = &cookie->iovad;
+       size_t iova_off = iova_offset(iovad, dma_addr);
 
-       size = iova_size(iova) << shift;
-       size -= iommu_unmap(domain, pfn << shift, size);
-       /* ...and if we can't, then something is horribly, horribly wrong */
-       WARN_ON(size > 0);
-       __free_iova(iovad, iova);
+       dma_addr -= iova_off;
+       size = iova_align(iovad, size + iova_off);
+
+       WARN_ON(iommu_unmap(domain, dma_addr, size) != size);
+       iommu_dma_free_iova(cookie, dma_addr, size);
 }
 
 static void __iommu_dma_free_pages(struct page **pages, int count)
@@ -409,7 +498,7 @@ static struct page **__iommu_dma_alloc_pages(unsigned int count,
 void iommu_dma_free(struct device *dev, struct page **pages, size_t size,
                dma_addr_t *handle)
 {
-       __iommu_dma_unmap(iommu_get_domain_for_dev(dev), *handle);
+       __iommu_dma_unmap(iommu_get_domain_for_dev(dev), *handle, size);
        __iommu_dma_free_pages(pages, PAGE_ALIGN(size) >> PAGE_SHIFT);
        *handle = DMA_ERROR_CODE;
 }
@@ -437,11 +526,11 @@ struct page **iommu_dma_alloc(struct device *dev, size_t size, gfp_t gfp,
                void (*flush_page)(struct device *, const void *, phys_addr_t))
 {
        struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
-       struct iova_domain *iovad = cookie_iovad(domain);
-       struct iova *iova;
+       struct iommu_dma_cookie *cookie = domain->iova_cookie;
+       struct iova_domain *iovad = &cookie->iovad;
        struct page **pages;
        struct sg_table sgt;
-       dma_addr_t dma_addr;
+       dma_addr_t iova;
        unsigned int count, min_size, alloc_sizes = domain->pgsize_bitmap;
 
        *handle = DMA_ERROR_CODE;
@@ -461,11 +550,11 @@ struct page **iommu_dma_alloc(struct device *dev, size_t size, gfp_t gfp,
        if (!pages)
                return NULL;
 
-       iova = __alloc_iova(domain, size, dev->coherent_dma_mask, dev);
+       size = iova_align(iovad, size);
+       iova = iommu_dma_alloc_iova(domain, size, dev->coherent_dma_mask, dev);
        if (!iova)
                goto out_free_pages;
 
-       size = iova_align(iovad, size);
        if (sg_alloc_table_from_pages(&sgt, pages, count, 0, size, GFP_KERNEL))
                goto out_free_iova;
 
@@ -481,19 +570,18 @@ struct page **iommu_dma_alloc(struct device *dev, size_t size, gfp_t gfp,
                sg_miter_stop(&miter);
        }
 
-       dma_addr = iova_dma_addr(iovad, iova);
-       if (iommu_map_sg(domain, dma_addr, sgt.sgl, sgt.orig_nents, prot)
+       if (iommu_map_sg(domain, iova, sgt.sgl, sgt.orig_nents, prot)
                        < size)
                goto out_free_sg;
 
-       *handle = dma_addr;
+       *handle = iova;
        sg_free_table(&sgt);
        return pages;
 
 out_free_sg:
        sg_free_table(&sgt);
 out_free_iova:
-       __free_iova(iovad, iova);
+       iommu_dma_free_iova(cookie, iova, size);
 out_free_pages:
        __iommu_dma_free_pages(pages, count);
        return NULL;
@@ -527,22 +615,25 @@ int iommu_dma_mmap(struct page **pages, size_t size, struct vm_area_struct *vma)
 static dma_addr_t __iommu_dma_map(struct device *dev, phys_addr_t phys,
                size_t size, int prot)
 {
-       dma_addr_t dma_addr;
        struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
-       struct iova_domain *iovad = cookie_iovad(domain);
-       size_t iova_off = iova_offset(iovad, phys);
-       size_t len = iova_align(iovad, size + iova_off);
-       struct iova *iova = __alloc_iova(domain, len, dma_get_mask(dev), dev);
+       struct iommu_dma_cookie *cookie = domain->iova_cookie;
+       size_t iova_off = 0;
+       dma_addr_t iova;
 
+       if (cookie->type == IOMMU_DMA_IOVA_COOKIE) {
+               iova_off = iova_offset(&cookie->iovad, phys);
+               size = iova_align(&cookie->iovad, size + iova_off);
+       }
+
+       iova = iommu_dma_alloc_iova(domain, size, dma_get_mask(dev), dev);
        if (!iova)
                return DMA_ERROR_CODE;
 
-       dma_addr = iova_dma_addr(iovad, iova);
-       if (iommu_map(domain, dma_addr, phys - iova_off, len, prot)) {
-               __free_iova(iovad, iova);
+       if (iommu_map(domain, iova, phys - iova_off, size, prot)) {
+               iommu_dma_free_iova(cookie, iova, size);
                return DMA_ERROR_CODE;
        }
-       return dma_addr + iova_off;
+       return iova + iova_off;
 }
 
 dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page,
@@ -554,7 +645,7 @@ dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page,
 void iommu_dma_unmap_page(struct device *dev, dma_addr_t handle, size_t size,
                enum dma_data_direction dir, unsigned long attrs)
 {
-       __iommu_dma_unmap(iommu_get_domain_for_dev(dev), handle);
+       __iommu_dma_unmap(iommu_get_domain_for_dev(dev), handle, size);
 }
 
 /*
@@ -643,10 +734,10 @@ int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg,
                int nents, int prot)
 {
        struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
-       struct iova_domain *iovad = cookie_iovad(domain);
-       struct iova *iova;
+       struct iommu_dma_cookie *cookie = domain->iova_cookie;
+       struct iova_domain *iovad = &cookie->iovad;
        struct scatterlist *s, *prev = NULL;
-       dma_addr_t dma_addr;
+       dma_addr_t iova;
        size_t iova_len = 0;
        unsigned long mask = dma_get_seg_boundary(dev);
        int i;
@@ -690,7 +781,7 @@ int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg,
                prev = s;
        }
 
-       iova = __alloc_iova(domain, iova_len, dma_get_mask(dev), dev);
+       iova = iommu_dma_alloc_iova(domain, iova_len, dma_get_mask(dev), dev);
        if (!iova)
                goto out_restore_sg;
 
@@ -698,14 +789,13 @@ int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg,
         * We'll leave any physical concatenation to the IOMMU driver's
         * implementation - it knows better than we do.
         */
-       dma_addr = iova_dma_addr(iovad, iova);
-       if (iommu_map_sg(domain, dma_addr, sg, nents, prot) < iova_len)
+       if (iommu_map_sg(domain, iova, sg, nents, prot) < iova_len)
                goto out_free_iova;
 
-       return __finalise_sg(dev, sg, nents, dma_addr);
+       return __finalise_sg(dev, sg, nents, iova);
 
 out_free_iova:
-       __free_iova(iovad, iova);
+       iommu_dma_free_iova(cookie, iova, iova_len);
 out_restore_sg:
        __invalidate_sg(sg, nents);
        return 0;
@@ -714,11 +804,21 @@ out_restore_sg:
 void iommu_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
                enum dma_data_direction dir, unsigned long attrs)
 {
+       dma_addr_t start, end;
+       struct scatterlist *tmp;
+       int i;
        /*
         * The scatterlist segments are mapped into a single
         * contiguous IOVA allocation, so this is incredibly easy.
         */
-       __iommu_dma_unmap(iommu_get_domain_for_dev(dev), sg_dma_address(sg));
+       start = sg_dma_address(sg);
+       for_each_sg(sg_next(sg), tmp, nents - 1, i) {
+               if (sg_dma_len(tmp) == 0)
+                       break;
+               sg = tmp;
+       }
+       end = sg_dma_address(sg) + sg_dma_len(sg);
+       __iommu_dma_unmap(iommu_get_domain_for_dev(dev), start, end - start);
 }
 
 dma_addr_t iommu_dma_map_resource(struct device *dev, phys_addr_t phys,
@@ -731,7 +831,7 @@ dma_addr_t iommu_dma_map_resource(struct device *dev, phys_addr_t phys,
 void iommu_dma_unmap_resource(struct device *dev, dma_addr_t handle,
                size_t size, enum dma_data_direction dir, unsigned long attrs)
 {
-       __iommu_dma_unmap(iommu_get_domain_for_dev(dev), handle);
+       __iommu_dma_unmap(iommu_get_domain_for_dev(dev), handle, size);
 }
 
 int iommu_dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
@@ -744,8 +844,7 @@ static struct iommu_dma_msi_page *iommu_dma_get_msi_page(struct device *dev,
 {
        struct iommu_dma_cookie *cookie = domain->iova_cookie;
        struct iommu_dma_msi_page *msi_page;
-       struct iova_domain *iovad = cookie_iovad(domain);
-       struct iova *iova;
+       dma_addr_t iova;
        int prot = IOMMU_WRITE | IOMMU_NOEXEC | IOMMU_MMIO;
        size_t size = cookie_msi_granule(cookie);
 
@@ -758,29 +857,16 @@ static struct iommu_dma_msi_page *iommu_dma_get_msi_page(struct device *dev,
        if (!msi_page)
                return NULL;
 
-       msi_page->phys = msi_addr;
-       if (iovad) {
-               iova = __alloc_iova(domain, size, dma_get_mask(dev), dev);
-               if (!iova)
-                       goto out_free_page;
-               msi_page->iova = iova_dma_addr(iovad, iova);
-       } else {
-               msi_page->iova = cookie->msi_iova;
-               cookie->msi_iova += size;
-       }
-
-       if (iommu_map(domain, msi_page->iova, msi_addr, size, prot))
-               goto out_free_iova;
+       iova = __iommu_dma_map(dev, msi_addr, size, prot);
+       if (iommu_dma_mapping_error(dev, iova))
+               goto out_free_page;
 
        INIT_LIST_HEAD(&msi_page->list);
+       msi_page->phys = msi_addr;
+       msi_page->iova = iova;
        list_add(&msi_page->list, &cookie->msi_page_list);
        return msi_page;
 
-out_free_iova:
-       if (iovad)
-               __free_iova(iovad, iova);
-       else
-               cookie->msi_iova -= size;
 out_free_page:
        kfree(msi_page);
        return NULL;
index 36e3f430d2651af655480ae323dff48d919c5ecc..cbf7763d8091035deb45d2c36a7fc7201e6b4ab0 100644 (file)
@@ -311,7 +311,7 @@ static int dmar_pci_bus_add_dev(struct dmar_pci_notify_info *info)
                                ((void *)drhd) + drhd->header.length,
                                dmaru->segment,
                                dmaru->devices, dmaru->devices_cnt);
-               if (ret != 0)
+               if (ret)
                        break;
        }
        if (ret >= 0)
@@ -391,7 +391,7 @@ static int dmar_parse_one_drhd(struct acpi_dmar_header *header, void *arg)
 {
        struct acpi_dmar_hardware_unit *drhd;
        struct dmar_drhd_unit *dmaru;
-       int ret = 0;
+       int ret;
 
        drhd = (struct acpi_dmar_hardware_unit *)header;
        dmaru = dmar_find_dmaru(drhd);
@@ -551,17 +551,16 @@ static int __init dmar_table_detect(void)
                status = AE_NOT_FOUND;
        }
 
-       return (ACPI_SUCCESS(status) ? 1 : 0);
+       return ACPI_SUCCESS(status) ? 0 : -ENOENT;
 }
 
 static int dmar_walk_remapping_entries(struct acpi_dmar_header *start,
                                       size_t len, struct dmar_res_callback *cb)
 {
-       int ret = 0;
        struct acpi_dmar_header *iter, *next;
        struct acpi_dmar_header *end = ((void *)start) + len;
 
-       for (iter = start; iter < end && ret == 0; iter = next) {
+       for (iter = start; iter < end; iter = next) {
                next = (void *)iter + iter->length;
                if (iter->length == 0) {
                        /* Avoid looping forever on bad ACPI tables */
@@ -570,8 +569,7 @@ static int dmar_walk_remapping_entries(struct acpi_dmar_header *start,
                } else if (next > end) {
                        /* Avoid passing table end */
                        pr_warn(FW_BUG "Record passes table end\n");
-                       ret = -EINVAL;
-                       break;
+                       return -EINVAL;
                }
 
                if (cb->print_entry)
@@ -582,15 +580,19 @@ static int dmar_walk_remapping_entries(struct acpi_dmar_header *start,
                        pr_debug("Unknown DMAR structure type %d\n",
                                 iter->type);
                } else if (cb->cb[iter->type]) {
+                       int ret;
+
                        ret = cb->cb[iter->type](iter, cb->arg[iter->type]);
+                       if (ret)
+                               return ret;
                } else if (!cb->ignore_unhandled) {
                        pr_warn("No handler for DMAR structure type %d\n",
                                iter->type);
-                       ret = -EINVAL;
+                       return -EINVAL;
                }
        }
 
-       return ret;
+       return 0;
 }
 
 static inline int dmar_walk_dmar_table(struct acpi_table_dmar *dmar,
@@ -607,8 +609,8 @@ static int __init
 parse_dmar_table(void)
 {
        struct acpi_table_dmar *dmar;
-       int ret = 0;
        int drhd_count = 0;
+       int ret;
        struct dmar_res_callback cb = {
                .print_entry = true,
                .ignore_unhandled = true,
@@ -891,17 +893,17 @@ int __init detect_intel_iommu(void)
 
        down_write(&dmar_global_lock);
        ret = dmar_table_detect();
-       if (ret)
-               ret = !dmar_walk_dmar_table((struct acpi_table_dmar *)dmar_tbl,
-                                           &validate_drhd_cb);
-       if (ret && !no_iommu && !iommu_detected && !dmar_disabled) {
+       if (!ret)
+               ret = dmar_walk_dmar_table((struct acpi_table_dmar *)dmar_tbl,
+                                          &validate_drhd_cb);
+       if (!ret && !no_iommu && !iommu_detected && !dmar_disabled) {
                iommu_detected = 1;
                /* Make sure ACS will be enabled */
                pci_request_acs();
        }
 
 #ifdef CONFIG_X86
-       if (ret)
+       if (!ret)
                x86_init.iommu.iommu_init = intel_iommu_init;
 #endif
 
@@ -911,10 +913,9 @@ int __init detect_intel_iommu(void)
        }
        up_write(&dmar_global_lock);
 
-       return ret ? 1 : -ENODEV;
+       return ret ? ret : 1;
 }
 
-
 static void unmap_iommu(struct intel_iommu *iommu)
 {
        iounmap(iommu->reg);
index c01bfcdb238316c049ae0dd6b4bf2d43c6c61440..2395478dde7518cb7e74049765888fbef1c64510 100644 (file)
@@ -171,6 +171,9 @@ static u32 lv2ent_offset(sysmmu_iova_t iova)
 #define REG_V5_PT_BASE_PFN     0x00C
 #define REG_V5_MMU_FLUSH_ALL   0x010
 #define REG_V5_MMU_FLUSH_ENTRY 0x014
+#define REG_V5_MMU_FLUSH_RANGE 0x018
+#define REG_V5_MMU_FLUSH_START 0x020
+#define REG_V5_MMU_FLUSH_END   0x024
 #define REG_V5_INT_STATUS      0x060
 #define REG_V5_INT_CLEAR       0x064
 #define REG_V5_FAULT_AR_VA     0x070
@@ -319,14 +322,23 @@ static void __sysmmu_tlb_invalidate_entry(struct sysmmu_drvdata *data,
 {
        unsigned int i;
 
-       for (i = 0; i < num_inv; i++) {
-               if (MMU_MAJ_VER(data->version) < 5)
+       if (MMU_MAJ_VER(data->version) < 5) {
+               for (i = 0; i < num_inv; i++) {
                        writel((iova & SPAGE_MASK) | 1,
                                     data->sfrbase + REG_MMU_FLUSH_ENTRY);
-               else
+                       iova += SPAGE_SIZE;
+               }
+       } else {
+               if (num_inv == 1) {
                        writel((iova & SPAGE_MASK) | 1,
                                     data->sfrbase + REG_V5_MMU_FLUSH_ENTRY);
-               iova += SPAGE_SIZE;
+               } else {
+                       writel((iova & SPAGE_MASK),
+                                    data->sfrbase + REG_V5_MMU_FLUSH_START);
+                       writel((iova & SPAGE_MASK) + (num_inv - 1) * SPAGE_SIZE,
+                                    data->sfrbase + REG_V5_MMU_FLUSH_END);
+                       writel(1, data->sfrbase + REG_V5_MMU_FLUSH_RANGE);
+               }
        }
 }
 
@@ -747,16 +759,8 @@ static struct iommu_domain *exynos_iommu_domain_alloc(unsigned type)
                goto err_counter;
 
        /* Workaround for System MMU v3.3 to prevent caching 1MiB mapping */
-       for (i = 0; i < NUM_LV1ENTRIES; i += 8) {
-               domain->pgtable[i + 0] = ZERO_LV2LINK;
-               domain->pgtable[i + 1] = ZERO_LV2LINK;
-               domain->pgtable[i + 2] = ZERO_LV2LINK;
-               domain->pgtable[i + 3] = ZERO_LV2LINK;
-               domain->pgtable[i + 4] = ZERO_LV2LINK;
-               domain->pgtable[i + 5] = ZERO_LV2LINK;
-               domain->pgtable[i + 6] = ZERO_LV2LINK;
-               domain->pgtable[i + 7] = ZERO_LV2LINK;
-       }
+       for (i = 0; i < NUM_LV1ENTRIES; i++)
+               domain->pgtable[i] = ZERO_LV2LINK;
 
        handle = dma_map_single(dma_dev, domain->pgtable, LV1TABLE_SIZE,
                                DMA_TO_DEVICE);
index aab723f91f1294e8e59659e25659c8d8e1cada68..c3434f29c9671378281c8c87f4ca960251a6ffe6 100644 (file)
@@ -20,6 +20,7 @@
 #define __FSL_PAMU_H
 
 #include <linux/iommu.h>
+#include <linux/pci.h>
 
 #include <asm/fsl_pamu_stash.h>
 
index d412a313a37232997d406e53379e1466d10b93e7..fc2765ccdb57496e257a0da0fd2177431a1c8713 100644 (file)
@@ -183,6 +183,7 @@ static int rwbf_quirk;
  * (used when kernel is launched w/ TXT)
  */
 static int force_on = 0;
+int intel_iommu_tboot_noforce;
 
 /*
  * 0: Present
@@ -607,6 +608,10 @@ static int __init intel_iommu_setup(char *str)
                                "Intel-IOMMU: enable pre-production PASID support\n");
                        intel_iommu_pasid28 = 1;
                        iommu_identity_mapping |= IDENTMAP_GFX;
+               } else if (!strncmp(str, "tboot_noforce", 13)) {
+                       printk(KERN_INFO
+                               "Intel-IOMMU: not forcing on after tboot. This could expose security risk for tboot\n");
+                       intel_iommu_tboot_noforce = 1;
                }
 
                str += strcspn(str, ",");
@@ -2050,11 +2055,14 @@ static int domain_context_mapping_one(struct dmar_domain *domain,
        if (context_copied(context)) {
                u16 did_old = context_domain_id(context);
 
-               if (did_old >= 0 && did_old < cap_ndoms(iommu->cap))
+               if (did_old >= 0 && did_old < cap_ndoms(iommu->cap)) {
                        iommu->flush.flush_context(iommu, did_old,
                                                   (((u16)bus) << 8) | devfn,
                                                   DMA_CCMD_MASK_NOBIT,
                                                   DMA_CCMD_DEVICE_INVL);
+                       iommu->flush.flush_iotlb(iommu, did_old, 0, 0,
+                                                DMA_TLB_DSI_FLUSH);
+               }
        }
 
        pgd = domain->pgd;
@@ -4730,6 +4738,15 @@ static int intel_iommu_cpu_dead(unsigned int cpu)
        return 0;
 }
 
+static void intel_disable_iommus(void)
+{
+       struct intel_iommu *iommu = NULL;
+       struct dmar_drhd_unit *drhd;
+
+       for_each_iommu(iommu, drhd)
+               iommu_disable_translation(iommu);
+}
+
 static inline struct intel_iommu *dev_to_intel_iommu(struct device *dev)
 {
        return container_of(dev, struct intel_iommu, iommu.dev);
@@ -4840,8 +4857,28 @@ int __init intel_iommu_init(void)
                goto out_free_dmar;
        }
 
-       if (no_iommu || dmar_disabled)
+       if (no_iommu || dmar_disabled) {
+               /*
+                * We exit the function here to ensure IOMMU's remapping and
+                * mempool aren't setup, which means that the IOMMU's PMRs
+                * won't be disabled via the call to init_dmars(). So disable
+                * it explicitly here. The PMRs were setup by tboot prior to
+                * calling SENTER, but the kernel is expected to reset/tear
+                * down the PMRs.
+                */
+               if (intel_iommu_tboot_noforce) {
+                       for_each_iommu(iommu, drhd)
+                               iommu_disable_protect_mem_regions(iommu);
+               }
+
+               /*
+                * Make sure the IOMMUs are switched off, even when we
+                * boot into a kexec kernel and the previous kernel left
+                * them enabled
+                */
+               intel_disable_iommus();
                goto out_free_dmar;
+       }
 
        if (list_empty(&dmar_rmrr_units))
                pr_info("No RMRR found\n");
index ac596928f6b40af32e9c44ecf388ebf7ed4b10ed..a190cbd76ef7113f850b3c09d8b513367d7eb496 100644 (file)
@@ -408,14 +408,6 @@ static int iommu_load_old_irte(struct intel_iommu *iommu)
        size_t size;
        u64 irta;
 
-       if (!is_kdump_kernel()) {
-               pr_warn("IRQ remapping was enabled on %s but we are not in kdump mode\n",
-                       iommu->name);
-               clear_ir_pre_enabled(iommu);
-               iommu_disable_irq_remapping(iommu);
-               return -EINVAL;
-       }
-
        /* Check whether the old ir-table has the same size as ours */
        irta = dmar_readq(iommu->reg + DMAR_IRTA_REG);
        if ((irta & INTR_REMAP_TABLE_REG_SIZE_MASK)
@@ -567,7 +559,12 @@ static int intel_setup_irq_remapping(struct intel_iommu *iommu)
        init_ir_status(iommu);
 
        if (ir_pre_enabled(iommu)) {
-               if (iommu_load_old_irte(iommu))
+               if (!is_kdump_kernel()) {
+                       pr_warn("IRQ remapping was enabled on %s but we are not in kdump mode\n",
+                               iommu->name);
+                       clear_ir_pre_enabled(iommu);
+                       iommu_disable_irq_remapping(iommu);
+               } else if (iommu_load_old_irte(iommu))
                        pr_err("Failed to copy IR table for %s from previous kernel\n",
                               iommu->name);
                else
index f9bc6ebb8140b06c845355560fd6e5d113912073..6e5df5e0a3bdc574a766fbfe8069a4b46f4f0836 100644 (file)
@@ -74,7 +74,7 @@
 
 /* Calculate the block/page mapping size at level l for pagetable in d. */
 #define ARM_LPAE_BLOCK_SIZE(l,d)                                       \
-       (1 << (ilog2(sizeof(arm_lpae_iopte)) +                          \
+       (1ULL << (ilog2(sizeof(arm_lpae_iopte)) +                       \
                ((ARM_LPAE_MAX_LEVELS - (l)) * (d)->bits_per_level)))
 
 /* Page table bits */
index 3b67144dead2e3811918af8fa44ec6e67a19c955..cf7ca7e70777d6498f751fac98bc29fef9ba8ce6 100644 (file)
@@ -36,6 +36,7 @@
 
 static struct kset *iommu_group_kset;
 static DEFINE_IDA(iommu_group_ida);
+static unsigned int iommu_def_domain_type = IOMMU_DOMAIN_DMA;
 
 struct iommu_callback_data {
        const struct iommu_ops *ops;
@@ -112,6 +113,18 @@ static int __iommu_attach_group(struct iommu_domain *domain,
 static void __iommu_detach_group(struct iommu_domain *domain,
                                 struct iommu_group *group);
 
+static int __init iommu_set_def_domain_type(char *str)
+{
+       bool pt;
+
+       if (!str || strtobool(str, &pt))
+               return -EINVAL;
+
+       iommu_def_domain_type = pt ? IOMMU_DOMAIN_IDENTITY : IOMMU_DOMAIN_DMA;
+       return 0;
+}
+early_param("iommu.passthrough", iommu_set_def_domain_type);
+
 static ssize_t iommu_group_attr_show(struct kobject *kobj,
                                     struct attribute *__attr, char *buf)
 {
@@ -1015,10 +1028,19 @@ struct iommu_group *iommu_group_get_for_dev(struct device *dev)
         * IOMMU driver.
         */
        if (!group->default_domain) {
-               group->default_domain = __iommu_domain_alloc(dev->bus,
-                                                            IOMMU_DOMAIN_DMA);
+               struct iommu_domain *dom;
+
+               dom = __iommu_domain_alloc(dev->bus, iommu_def_domain_type);
+               if (!dom && iommu_def_domain_type != IOMMU_DOMAIN_DMA) {
+                       dev_warn(dev,
+                                "failed to allocate default IOMMU domain of type %u; falling back to IOMMU_DOMAIN_DMA",
+                                iommu_def_domain_type);
+                       dom = __iommu_domain_alloc(dev->bus, IOMMU_DOMAIN_DMA);
+               }
+
+               group->default_domain = dom;
                if (!group->domain)
-                       group->domain = group->default_domain;
+                       group->domain = dom;
        }
 
        ret = iommu_group_add_device(group, dev);
@@ -1083,8 +1105,12 @@ static int iommu_bus_notifier(struct notifier_block *nb,
         * result in ADD/DEL notifiers to group->notifier
         */
        if (action == BUS_NOTIFY_ADD_DEVICE) {
-               if (ops->add_device)
-                       return ops->add_device(dev);
+               if (ops->add_device) {
+                       int ret;
+
+                       ret = ops->add_device(dev);
+                       return (ret) ? NOTIFY_DONE : NOTIFY_OK;
+               }
        } else if (action == BUS_NOTIFY_REMOVED_DEVICE) {
                if (ops->remove_device && dev->iommu_group) {
                        ops->remove_device(dev);
@@ -1652,6 +1678,48 @@ void iommu_domain_window_disable(struct iommu_domain *domain, u32 wnd_nr)
 }
 EXPORT_SYMBOL_GPL(iommu_domain_window_disable);
 
+/**
+ * report_iommu_fault() - report about an IOMMU fault to the IOMMU framework
+ * @domain: the iommu domain where the fault has happened
+ * @dev: the device where the fault has happened
+ * @iova: the faulting address
+ * @flags: mmu fault flags (e.g. IOMMU_FAULT_READ/IOMMU_FAULT_WRITE/...)
+ *
+ * This function should be called by the low-level IOMMU implementations
+ * whenever IOMMU faults happen, to allow high-level users, that are
+ * interested in such events, to know about them.
+ *
+ * This event may be useful for several possible use cases:
+ * - mere logging of the event
+ * - dynamic TLB/PTE loading
+ * - if restarting of the faulting device is required
+ *
+ * Returns 0 on success and an appropriate error code otherwise (if dynamic
+ * PTE/TLB loading will one day be supported, implementations will be able
+ * to tell whether it succeeded or not according to this return value).
+ *
+ * Specifically, -ENOSYS is returned if a fault handler isn't installed
+ * (though fault handlers can also return -ENOSYS, in case they want to
+ * elicit the default behavior of the IOMMU drivers).
+ */
+int report_iommu_fault(struct iommu_domain *domain, struct device *dev,
+                      unsigned long iova, int flags)
+{
+       int ret = -ENOSYS;
+
+       /*
+        * if upper layers showed interest and installed a fault handler,
+        * invoke it.
+        */
+       if (domain->handler)
+               ret = domain->handler(domain, dev, iova, flags,
+                                               domain->handler_token);
+
+       trace_io_page_fault(dev, iova, flags);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(report_iommu_fault);
+
 static int __init iommu_init(void)
 {
        iommu_group_kset = kset_create_and_add("iommu_groups",
index e80a4105ac2abe55d365a9a5f03220f97417c9ac..5c88ba70e4e0fe92b282ebf1e8a1d0b2857677d4 100644 (file)
@@ -166,7 +166,7 @@ static int __alloc_and_insert_iova_range(struct iova_domain *iovad,
                                break;  /* found a free slot */
                }
 adjust_limit_pfn:
-               limit_pfn = curr_iova->pfn_lo - 1;
+               limit_pfn = curr_iova->pfn_lo ? (curr_iova->pfn_lo - 1) : 0;
 move_left:
                prev = curr;
                curr = rb_prev(curr);
index 19e010083408cc5415db432aa10bc332e3158c5e..bc1efbfb9ddf0f121a213f9919f7e3ea0fa957ca 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/clk.h>
 #include <linux/component.h>
 #include <linux/device.h>
+#include <linux/dma-mapping.h>
 #include <linux/dma-iommu.h>
 #include <linux/err.h>
 #include <linux/interrupt.h>
@@ -431,9 +432,10 @@ err_release_mapping:
 
 static int mtk_iommu_add_device(struct device *dev)
 {
-       struct iommu_group *group;
        struct of_phandle_args iommu_spec;
        struct of_phandle_iterator it;
+       struct mtk_iommu_data *data;
+       struct iommu_group *group;
        int err;
 
        of_for_each_phandle(&it, err, dev->of_node, "iommus",
@@ -450,6 +452,9 @@ static int mtk_iommu_add_device(struct device *dev)
        if (!dev->iommu_fwspec || dev->iommu_fwspec->ops != &mtk_iommu_ops)
                return -ENODEV; /* Not a iommu client device */
 
+       data = dev->iommu_fwspec->iommu_priv;
+       iommu_device_link(&data->iommu, dev);
+
        group = iommu_group_get_for_dev(dev);
        if (IS_ERR(group))
                return PTR_ERR(group);
@@ -460,9 +465,14 @@ static int mtk_iommu_add_device(struct device *dev)
 
 static void mtk_iommu_remove_device(struct device *dev)
 {
+       struct mtk_iommu_data *data;
+
        if (!dev->iommu_fwspec || dev->iommu_fwspec->ops != &mtk_iommu_ops)
                return;
 
+       data = dev->iommu_fwspec->iommu_priv;
+       iommu_device_unlink(&data->iommu, dev);
+
        iommu_group_remove_device(dev);
        iommu_fwspec_free(dev);
 }
@@ -627,6 +637,17 @@ static int mtk_iommu_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
+       ret = iommu_device_sysfs_add(&data->iommu, &pdev->dev, NULL,
+                                    dev_name(&pdev->dev));
+       if (ret)
+               return ret;
+
+       iommu_device_set_ops(&data->iommu, &mtk_iommu_ops);
+
+       ret = iommu_device_register(&data->iommu);
+       if (ret)
+               return ret;
+
        if (!iommu_present(&platform_bus_type))
                bus_set_iommu(&platform_bus_type,  &mtk_iommu_ops);
 
@@ -637,6 +658,9 @@ static int mtk_iommu_remove(struct platform_device *pdev)
 {
        struct mtk_iommu_data *data = platform_get_drvdata(pdev);
 
+       iommu_device_sysfs_remove(&data->iommu);
+       iommu_device_unregister(&data->iommu);
+
        if (iommu_present(&platform_bus_type))
                bus_set_iommu(&platform_bus_type, NULL);
 
index 2683e9fc0dcf5cc0886034b7fccafb8861d958f1..9f44ee8ea1bc8a10a6ff4c0dad297b78b8c2f57a 100644 (file)
@@ -96,6 +96,49 @@ int of_get_dma_window(struct device_node *dn, const char *prefix, int index,
 }
 EXPORT_SYMBOL_GPL(of_get_dma_window);
 
+static bool of_iommu_driver_present(struct device_node *np)
+{
+       /*
+        * If the IOMMU still isn't ready by the time we reach init, assume
+        * it never will be. We don't want to defer indefinitely, nor attempt
+        * to dereference __iommu_of_table after it's been freed.
+        */
+       if (system_state > SYSTEM_BOOTING)
+               return false;
+
+       return of_match_node(&__iommu_of_table, np);
+}
+
+static const struct iommu_ops
+*of_iommu_xlate(struct device *dev, struct of_phandle_args *iommu_spec)
+{
+       const struct iommu_ops *ops;
+       struct fwnode_handle *fwnode = &iommu_spec->np->fwnode;
+       int err;
+
+       ops = iommu_ops_from_fwnode(fwnode);
+       if ((ops && !ops->of_xlate) ||
+           (!ops && !of_iommu_driver_present(iommu_spec->np)))
+               return NULL;
+
+       err = iommu_fwspec_init(dev, &iommu_spec->np->fwnode, ops);
+       if (err)
+               return ERR_PTR(err);
+       /*
+        * The otherwise-empty fwspec handily serves to indicate the specific
+        * IOMMU device we're waiting for, which will be useful if we ever get
+        * a proper probe-ordering dependency mechanism in future.
+        */
+       if (!ops)
+               return ERR_PTR(-EPROBE_DEFER);
+
+       err = ops->of_xlate(dev, iommu_spec);
+       if (err)
+               return ERR_PTR(err);
+
+       return ops;
+}
+
 static int __get_pci_rid(struct pci_dev *pdev, u16 alias, void *data)
 {
        struct of_phandle_args *iommu_spec = data;
@@ -105,10 +148,11 @@ static int __get_pci_rid(struct pci_dev *pdev, u16 alias, void *data)
 }
 
 static const struct iommu_ops
-*of_pci_iommu_configure(struct pci_dev *pdev, struct device_node *bridge_np)
+*of_pci_iommu_init(struct pci_dev *pdev, struct device_node *bridge_np)
 {
        const struct iommu_ops *ops;
        struct of_phandle_args iommu_spec;
+       int err;
 
        /*
         * Start by tracing the RID alias down the PCI topology as
@@ -123,56 +167,76 @@ static const struct iommu_ops
         * bus into the system beyond, and which IOMMU it ends up at.
         */
        iommu_spec.np = NULL;
-       if (of_pci_map_rid(bridge_np, iommu_spec.args[0], "iommu-map",
-                          "iommu-map-mask", &iommu_spec.np, iommu_spec.args))
-               return NULL;
+       err = of_pci_map_rid(bridge_np, iommu_spec.args[0], "iommu-map",
+                            "iommu-map-mask", &iommu_spec.np,
+                            iommu_spec.args);
+       if (err)
+               return err == -ENODEV ? NULL : ERR_PTR(err);
 
-       ops = iommu_ops_from_fwnode(&iommu_spec.np->fwnode);
-       if (!ops || !ops->of_xlate ||
-           iommu_fwspec_init(&pdev->dev, &iommu_spec.np->fwnode, ops) ||
-           ops->of_xlate(&pdev->dev, &iommu_spec))
-               ops = NULL;
+       ops = of_iommu_xlate(&pdev->dev, &iommu_spec);
 
        of_node_put(iommu_spec.np);
        return ops;
 }
 
-const struct iommu_ops *of_iommu_configure(struct device *dev,
-                                          struct device_node *master_np)
+static const struct iommu_ops
+*of_platform_iommu_init(struct device *dev, struct device_node *np)
 {
        struct of_phandle_args iommu_spec;
-       struct device_node *np;
        const struct iommu_ops *ops = NULL;
        int idx = 0;
 
-       if (dev_is_pci(dev))
-               return of_pci_iommu_configure(to_pci_dev(dev), master_np);
-
        /*
         * We don't currently walk up the tree looking for a parent IOMMU.
         * See the `Notes:' section of
         * Documentation/devicetree/bindings/iommu/iommu.txt
         */
-       while (!of_parse_phandle_with_args(master_np, "iommus",
-                                          "#iommu-cells", idx,
-                                          &iommu_spec)) {
-               np = iommu_spec.np;
-               ops = iommu_ops_from_fwnode(&np->fwnode);
-
-               if (!ops || !ops->of_xlate ||
-                   iommu_fwspec_init(dev, &np->fwnode, ops) ||
-                   ops->of_xlate(dev, &iommu_spec))
-                       goto err_put_node;
-
-               of_node_put(np);
+       while (!of_parse_phandle_with_args(np, "iommus", "#iommu-cells",
+                                          idx, &iommu_spec)) {
+               ops = of_iommu_xlate(dev, &iommu_spec);
+               of_node_put(iommu_spec.np);
                idx++;
+               if (IS_ERR_OR_NULL(ops))
+                       break;
        }
 
        return ops;
+}
+
+const struct iommu_ops *of_iommu_configure(struct device *dev,
+                                          struct device_node *master_np)
+{
+       const struct iommu_ops *ops;
+       struct iommu_fwspec *fwspec = dev->iommu_fwspec;
+
+       if (!master_np)
+               return NULL;
+
+       if (fwspec) {
+               if (fwspec->ops)
+                       return fwspec->ops;
+
+               /* In the deferred case, start again from scratch */
+               iommu_fwspec_free(dev);
+       }
 
-err_put_node:
-       of_node_put(np);
-       return NULL;
+       if (dev_is_pci(dev))
+               ops = of_pci_iommu_init(to_pci_dev(dev), master_np);
+       else
+               ops = of_platform_iommu_init(dev, master_np);
+       /*
+        * If we have reason to believe the IOMMU driver missed the initial
+        * add_device callback for dev, replay it to get things in order.
+        */
+       if (!IS_ERR_OR_NULL(ops) && ops->add_device &&
+           dev->bus && !dev->iommu_group) {
+               int err = ops->add_device(dev);
+
+               if (err)
+                       ops = ERR_PTR(err);
+       }
+
+       return ops;
 }
 
 static int __init of_iommu_init(void)
@@ -183,7 +247,7 @@ static int __init of_iommu_init(void)
        for_each_matching_node_and_match(np, matches, &match) {
                const of_iommu_init_fn init_fn = match->data;
 
-               if (init_fn(np))
+               if (init_fn && init_fn(np))
                        pr_err("Failed to initialise IOMMU %s\n",
                                of_node_full_name(np));
        }
index e2583cce2cc12bc59c4b08ee8769ee4f423c660b..95dfca36ccb993e90c21aadb8454272a1838b7b7 100644 (file)
 #include "omap-iopgtable.h"
 #include "omap-iommu.h"
 
+static const struct iommu_ops omap_iommu_ops;
+
 #define to_iommu(dev)                                                  \
        ((struct omap_iommu *)platform_get_drvdata(to_platform_device(dev)))
 
 /* bitmap of the page sizes currently supported */
 #define OMAP_IOMMU_PGSIZES     (SZ_4K | SZ_64K | SZ_1M | SZ_16M)
 
-/**
- * struct omap_iommu_domain - omap iommu domain
- * @pgtable:   the page table
- * @iommu_dev: an omap iommu device attached to this domain. only a single
- *             iommu device can be attached for now.
- * @dev:       Device using this domain.
- * @lock:      domain lock, should be taken when attaching/detaching
- */
-struct omap_iommu_domain {
-       u32 *pgtable;
-       struct omap_iommu *iommu_dev;
-       struct device *dev;
-       spinlock_t lock;
-       struct iommu_domain domain;
-};
-
 #define MMU_LOCK_BASE_SHIFT    10
 #define MMU_LOCK_BASE_MASK     (0x1f << MMU_LOCK_BASE_SHIFT)
 #define MMU_LOCK_BASE(x)       \
@@ -818,33 +804,14 @@ static irqreturn_t iommu_fault_handler(int irq, void *data)
        return IRQ_NONE;
 }
 
-static int device_match_by_alias(struct device *dev, void *data)
-{
-       struct omap_iommu *obj = to_iommu(dev);
-       const char *name = data;
-
-       pr_debug("%s: %s %s\n", __func__, obj->name, name);
-
-       return strcmp(obj->name, name) == 0;
-}
-
 /**
  * omap_iommu_attach() - attach iommu device to an iommu domain
- * @name:      name of target omap iommu device
+ * @obj:       target omap iommu device
  * @iopgd:     page table
  **/
-static struct omap_iommu *omap_iommu_attach(const char *name, u32 *iopgd)
+static int omap_iommu_attach(struct omap_iommu *obj, u32 *iopgd)
 {
        int err;
-       struct device *dev;
-       struct omap_iommu *obj;
-
-       dev = driver_find_device(&omap_iommu_driver.driver, NULL, (void *)name,
-                                device_match_by_alias);
-       if (!dev)
-               return ERR_PTR(-ENODEV);
-
-       obj = to_iommu(dev);
 
        spin_lock(&obj->iommu_lock);
 
@@ -857,11 +824,13 @@ static struct omap_iommu *omap_iommu_attach(const char *name, u32 *iopgd)
        spin_unlock(&obj->iommu_lock);
 
        dev_dbg(obj->dev, "%s: %s\n", __func__, obj->name);
-       return obj;
+
+       return 0;
 
 err_enable:
        spin_unlock(&obj->iommu_lock);
-       return ERR_PTR(err);
+
+       return err;
 }
 
 /**
@@ -928,28 +897,26 @@ static int omap_iommu_probe(struct platform_device *pdev)
        int irq;
        struct omap_iommu *obj;
        struct resource *res;
-       struct iommu_platform_data *pdata = dev_get_platdata(&pdev->dev);
        struct device_node *of = pdev->dev.of_node;
 
+       if (!of) {
+               pr_err("%s: only DT-based devices are supported\n", __func__);
+               return -ENODEV;
+       }
+
        obj = devm_kzalloc(&pdev->dev, sizeof(*obj) + MMU_REG_SIZE, GFP_KERNEL);
        if (!obj)
                return -ENOMEM;
 
-       if (of) {
-               obj->name = dev_name(&pdev->dev);
-               obj->nr_tlb_entries = 32;
-               err = of_property_read_u32(of, "ti,#tlb-entries",
-                                          &obj->nr_tlb_entries);
-               if (err && err != -EINVAL)
-                       return err;
-               if (obj->nr_tlb_entries != 32 && obj->nr_tlb_entries != 8)
-                       return -EINVAL;
-               if (of_find_property(of, "ti,iommu-bus-err-back", NULL))
-                       obj->has_bus_err_back = MMU_GP_REG_BUS_ERR_BACK_EN;
-       } else {
-               obj->nr_tlb_entries = pdata->nr_tlb_entries;
-               obj->name = pdata->name;
-       }
+       obj->name = dev_name(&pdev->dev);
+       obj->nr_tlb_entries = 32;
+       err = of_property_read_u32(of, "ti,#tlb-entries", &obj->nr_tlb_entries);
+       if (err && err != -EINVAL)
+               return err;
+       if (obj->nr_tlb_entries != 32 && obj->nr_tlb_entries != 8)
+               return -EINVAL;
+       if (of_find_property(of, "ti,iommu-bus-err-back", NULL))
+               obj->has_bus_err_back = MMU_GP_REG_BUS_ERR_BACK_EN;
 
        obj->dev = &pdev->dev;
        obj->ctx = (void *)obj + sizeof(*obj);
@@ -976,19 +943,46 @@ static int omap_iommu_probe(struct platform_device *pdev)
                return err;
        platform_set_drvdata(pdev, obj);
 
+       obj->group = iommu_group_alloc();
+       if (IS_ERR(obj->group))
+               return PTR_ERR(obj->group);
+
+       err = iommu_device_sysfs_add(&obj->iommu, obj->dev, NULL, obj->name);
+       if (err)
+               goto out_group;
+
+       iommu_device_set_ops(&obj->iommu, &omap_iommu_ops);
+
+       err = iommu_device_register(&obj->iommu);
+       if (err)
+               goto out_sysfs;
+
        pm_runtime_irq_safe(obj->dev);
        pm_runtime_enable(obj->dev);
 
        omap_iommu_debugfs_add(obj);
 
        dev_info(&pdev->dev, "%s registered\n", obj->name);
+
        return 0;
+
+out_sysfs:
+       iommu_device_sysfs_remove(&obj->iommu);
+out_group:
+       iommu_group_put(obj->group);
+       return err;
 }
 
 static int omap_iommu_remove(struct platform_device *pdev)
 {
        struct omap_iommu *obj = platform_get_drvdata(pdev);
 
+       iommu_group_put(obj->group);
+       obj->group = NULL;
+
+       iommu_device_sysfs_remove(&obj->iommu);
+       iommu_device_unregister(&obj->iommu);
+
        omap_iommu_debugfs_remove(obj);
 
        pm_runtime_disable(obj->dev);
@@ -1077,11 +1071,11 @@ static int
 omap_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
 {
        struct omap_iommu_domain *omap_domain = to_omap_domain(domain);
-       struct omap_iommu *oiommu;
        struct omap_iommu_arch_data *arch_data = dev->archdata.iommu;
+       struct omap_iommu *oiommu;
        int ret = 0;
 
-       if (!arch_data || !arch_data->name) {
+       if (!arch_data || !arch_data->iommu_dev) {
                dev_err(dev, "device doesn't have an associated iommu\n");
                return -EINVAL;
        }
@@ -1095,15 +1089,16 @@ omap_iommu_attach_dev(struct iommu_domain *domain, struct device *dev)
                goto out;
        }
 
+       oiommu = arch_data->iommu_dev;
+
        /* get a handle to and enable the omap iommu */
-       oiommu = omap_iommu_attach(arch_data->name, omap_domain->pgtable);
-       if (IS_ERR(oiommu)) {
-               ret = PTR_ERR(oiommu);
+       ret = omap_iommu_attach(oiommu, omap_domain->pgtable);
+       if (ret) {
                dev_err(dev, "can't get omap iommu: %d\n", ret);
                goto out;
        }
 
-       omap_domain->iommu_dev = arch_data->iommu_dev = oiommu;
+       omap_domain->iommu_dev = oiommu;
        omap_domain->dev = dev;
        oiommu->domain = domain;
 
@@ -1116,7 +1111,6 @@ static void _omap_iommu_detach_dev(struct omap_iommu_domain *omap_domain,
                                   struct device *dev)
 {
        struct omap_iommu *oiommu = dev_to_omap_iommu(dev);
-       struct omap_iommu_arch_data *arch_data = dev->archdata.iommu;
 
        /* only a single device is supported per domain for now */
        if (omap_domain->iommu_dev != oiommu) {
@@ -1128,7 +1122,7 @@ static void _omap_iommu_detach_dev(struct omap_iommu_domain *omap_domain,
 
        omap_iommu_detach(oiommu);
 
-       omap_domain->iommu_dev = arch_data->iommu_dev = NULL;
+       omap_domain->iommu_dev = NULL;
        omap_domain->dev = NULL;
        oiommu->domain = NULL;
 }
@@ -1232,8 +1226,11 @@ static phys_addr_t omap_iommu_iova_to_phys(struct iommu_domain *domain,
 static int omap_iommu_add_device(struct device *dev)
 {
        struct omap_iommu_arch_data *arch_data;
+       struct omap_iommu *oiommu;
+       struct iommu_group *group;
        struct device_node *np;
        struct platform_device *pdev;
+       int ret;
 
        /*
         * Allocate the archdata iommu structure for DT-based devices.
@@ -1254,15 +1251,41 @@ static int omap_iommu_add_device(struct device *dev)
                return -EINVAL;
        }
 
+       oiommu = platform_get_drvdata(pdev);
+       if (!oiommu) {
+               of_node_put(np);
+               return -EINVAL;
+       }
+
        arch_data = kzalloc(sizeof(*arch_data), GFP_KERNEL);
        if (!arch_data) {
                of_node_put(np);
                return -ENOMEM;
        }
 
-       arch_data->name = kstrdup(dev_name(&pdev->dev), GFP_KERNEL);
+       ret = iommu_device_link(&oiommu->iommu, dev);
+       if (ret) {
+               kfree(arch_data);
+               of_node_put(np);
+               return ret;
+       }
+
+       arch_data->iommu_dev = oiommu;
        dev->archdata.iommu = arch_data;
 
+       /*
+        * IOMMU group initialization calls into omap_iommu_device_group, which
+        * needs a valid dev->archdata.iommu pointer
+        */
+       group = iommu_group_get_for_dev(dev);
+       if (IS_ERR(group)) {
+               iommu_device_unlink(&oiommu->iommu, dev);
+               dev->archdata.iommu = NULL;
+               kfree(arch_data);
+               return PTR_ERR(group);
+       }
+       iommu_group_put(group);
+
        of_node_put(np);
 
        return 0;
@@ -1275,8 +1298,23 @@ static void omap_iommu_remove_device(struct device *dev)
        if (!dev->of_node || !arch_data)
                return;
 
-       kfree(arch_data->name);
+       iommu_device_unlink(&arch_data->iommu_dev->iommu, dev);
+       iommu_group_remove_device(dev);
+
+       dev->archdata.iommu = NULL;
        kfree(arch_data);
+
+}
+
+static struct iommu_group *omap_iommu_device_group(struct device *dev)
+{
+       struct omap_iommu_arch_data *arch_data = dev->archdata.iommu;
+       struct iommu_group *group = NULL;
+
+       if (arch_data->iommu_dev)
+               group = arch_data->iommu_dev->group;
+
+       return group;
 }
 
 static const struct iommu_ops omap_iommu_ops = {
@@ -1290,6 +1328,7 @@ static const struct iommu_ops omap_iommu_ops = {
        .iova_to_phys   = omap_iommu_iova_to_phys,
        .add_device     = omap_iommu_add_device,
        .remove_device  = omap_iommu_remove_device,
+       .device_group   = omap_iommu_device_group,
        .pgsize_bitmap  = OMAP_IOMMU_PGSIZES,
 };
 
@@ -1299,6 +1338,7 @@ static int __init omap_iommu_init(void)
        const unsigned long flags = SLAB_HWCACHE_ALIGN;
        size_t align = 1 << 10; /* L2 pagetable alignement */
        struct device_node *np;
+       int ret;
 
        np = of_find_matching_node(NULL, omap_iommu_of_match);
        if (!np)
@@ -1312,11 +1352,25 @@ static int __init omap_iommu_init(void)
                return -ENOMEM;
        iopte_cachep = p;
 
-       bus_set_iommu(&platform_bus_type, &omap_iommu_ops);
-
        omap_iommu_debugfs_init();
 
-       return platform_driver_register(&omap_iommu_driver);
+       ret = platform_driver_register(&omap_iommu_driver);
+       if (ret) {
+               pr_err("%s: failed to register driver\n", __func__);
+               goto fail_driver;
+       }
+
+       ret = bus_set_iommu(&platform_bus_type, &omap_iommu_ops);
+       if (ret)
+               goto fail_bus;
+
+       return 0;
+
+fail_bus:
+       platform_driver_unregister(&omap_iommu_driver);
+fail_driver:
+       kmem_cache_destroy(iopte_cachep);
+       return ret;
 }
 subsys_initcall(omap_iommu_init);
 /* must be ready before omap3isp is probed */
index 59628e5017b4944381065993a7aa64e54f28c0b4..6e70515e60385bfdadb520242107d045f8e82ec4 100644 (file)
@@ -14,6 +14,7 @@
 #define _OMAP_IOMMU_H
 
 #include <linux/bitops.h>
+#include <linux/iommu.h>
 
 #define for_each_iotlb_cr(obj, n, __i, cr)                             \
        for (__i = 0;                                                   \
@@ -27,6 +28,23 @@ struct iotlb_entry {
        u32 endian, elsz, mixed;
 };
 
+/**
+ * struct omap_iommu_domain - omap iommu domain
+ * @pgtable:   the page table
+ * @iommu_dev: an omap iommu device attached to this domain. only a single
+ *             iommu device can be attached for now.
+ * @dev:       Device using this domain.
+ * @lock:      domain lock, should be taken when attaching/detaching
+ * @domain:    generic domain handle used by iommu core code
+ */
+struct omap_iommu_domain {
+       u32 *pgtable;
+       struct omap_iommu *iommu_dev;
+       struct device *dev;
+       spinlock_t lock;
+       struct iommu_domain domain;
+};
+
 struct omap_iommu {
        const char      *name;
        void __iomem    *regbase;
@@ -50,6 +68,22 @@ struct omap_iommu {
 
        int has_bus_err_back;
        u32 id;
+
+       struct iommu_device iommu;
+       struct iommu_group *group;
+};
+
+/**
+ * struct omap_iommu_arch_data - omap iommu private data
+ * @iommu_dev: handle of the iommu device
+ *
+ * This is an omap iommu private data object, which binds an iommu user
+ * to its iommu device. This object should be placed at the iommu user's
+ * dev_archdata so generic IOMMU API can be used without having to
+ * utilize omap-specific plumbing anymore.
+ */
+struct omap_iommu_arch_data {
+       struct omap_iommu *iommu_dev;
 };
 
 struct cr_regs {
index 9afcbf79f0b0b739ac506f82148bf708ead805f3..4ba48a26b389406af5a0d6636ecb7d1fa4e03346 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/dma-iommu.h>
+#include <linux/dma-mapping.h>
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
@@ -90,6 +91,7 @@ struct rk_iommu {
        void __iomem **bases;
        int num_mmu;
        int irq;
+       struct iommu_device iommu;
        struct list_head node; /* entry in rk_iommu_domain.iommus */
        struct iommu_domain *domain; /* domain to which iommu is attached */
 };
@@ -1032,6 +1034,7 @@ static int rk_iommu_group_set_iommudata(struct iommu_group *group,
 static int rk_iommu_add_device(struct device *dev)
 {
        struct iommu_group *group;
+       struct rk_iommu *iommu;
        int ret;
 
        if (!rk_iommu_is_dev_iommu_master(dev))
@@ -1054,6 +1057,10 @@ static int rk_iommu_add_device(struct device *dev)
        if (ret)
                goto err_remove_device;
 
+       iommu = rk_iommu_from_dev(dev);
+       if (iommu)
+               iommu_device_link(&iommu->iommu, dev);
+
        iommu_group_put(group);
 
        return 0;
@@ -1067,9 +1074,15 @@ err_put_group:
 
 static void rk_iommu_remove_device(struct device *dev)
 {
+       struct rk_iommu *iommu;
+
        if (!rk_iommu_is_dev_iommu_master(dev))
                return;
 
+       iommu = rk_iommu_from_dev(dev);
+       if (iommu)
+               iommu_device_unlink(&iommu->iommu, dev);
+
        iommu_group_remove_device(dev);
 }
 
@@ -1117,7 +1130,7 @@ static int rk_iommu_probe(struct platform_device *pdev)
        struct rk_iommu *iommu;
        struct resource *res;
        int num_res = pdev->num_resources;
-       int i;
+       int err, i;
 
        iommu = devm_kzalloc(dev, sizeof(*iommu), GFP_KERNEL);
        if (!iommu)
@@ -1150,11 +1163,25 @@ static int rk_iommu_probe(struct platform_device *pdev)
                return -ENXIO;
        }
 
-       return 0;
+       err = iommu_device_sysfs_add(&iommu->iommu, dev, NULL, dev_name(dev));
+       if (err)
+               return err;
+
+       iommu_device_set_ops(&iommu->iommu, &rk_iommu_ops);
+       err = iommu_device_register(&iommu->iommu);
+
+       return err;
 }
 
 static int rk_iommu_remove(struct platform_device *pdev)
 {
+       struct rk_iommu *iommu = platform_get_drvdata(pdev);
+
+       if (iommu) {
+               iommu_device_sysfs_remove(&iommu->iommu);
+               iommu_device_unregister(&iommu->iommu);
+       }
+
        return 0;
 }
 
index 9305964250acaf94cef7da5ce7f5a2fb6e78b5ce..eeb19f560a05ee54d87da40859e206626f1418a6 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <linux/dma-mapping.h>
 
 #include <soc/tegra/ahb.h>
 #include <soc/tegra/mc.h>
index 595d0c95563b08c14983d38d117422c4b7b50ba6..478f8ace266418d73e357c7eb09ba882818afb90 100644 (file)
@@ -134,7 +134,9 @@ config IMGPDC_IRQ
 config IRQ_MIPS_CPU
        bool
        select GENERIC_IRQ_CHIP
+       select GENERIC_IRQ_IPI if SYS_SUPPORTS_MULTITHREADING
        select IRQ_DOMAIN
+       select IRQ_DOMAIN_HIERARCHY if GENERIC_IRQ_IPI
 
 config CLPS711X_IRQCHIP
        bool
index 8c504f562e9dcdb5c5fd2a9b88ab591dd763782c..b247f3c743ac2492a105d90c39b9fbd3bdabcc41 100644 (file)
 /*
  * Almost all MIPS CPUs define 8 interrupt sources.  They are typically
  * level triggered (i.e., cannot be cleared from CPU; must be cleared from
- * device).  The first two are software interrupts which we don't really
- * use or support.  The last one is usually the CPU timer interrupt if
- * counter register is present or, for CPUs with an external FPU, by
- * convention it's the FPU exception interrupt.
+ * device).
  *
- * Don't even think about using this on SMP.  You have been warned.
+ * The first two are software interrupts (i.e. not exposed as pins) which
+ * may be used for IPIs in multi-threaded single-core systems.
  *
- * This file exports one global function:
- *     void mips_cpu_irq_init(void);
+ * The last one is usually the CPU timer interrupt if the counter register
+ * is present, or for old CPUs with an external FPU by convention it's the
+ * FPU exception interrupt.
  */
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <asm/mipsmtregs.h>
 #include <asm/setup.h>
 
+static struct irq_domain *irq_domain;
+static struct irq_domain *ipi_domain;
+
 static inline void unmask_mips_irq(struct irq_data *d)
 {
-       set_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
+       set_c0_status(IE_SW0 << d->hwirq);
        irq_enable_hazard();
 }
 
 static inline void mask_mips_irq(struct irq_data *d)
 {
-       clear_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
+       clear_c0_status(IE_SW0 << d->hwirq);
        irq_disable_hazard();
 }
 
@@ -70,7 +72,7 @@ static unsigned int mips_mt_cpu_irq_startup(struct irq_data *d)
 {
        unsigned int vpflags = dvpe();
 
-       clear_c0_cause(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
+       clear_c0_cause(C_SW0 << d->hwirq);
        evpe(vpflags);
        unmask_mips_irq(d);
        return 0;
@@ -83,11 +85,34 @@ static unsigned int mips_mt_cpu_irq_startup(struct irq_data *d)
 static void mips_mt_cpu_irq_ack(struct irq_data *d)
 {
        unsigned int vpflags = dvpe();
-       clear_c0_cause(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
+       clear_c0_cause(C_SW0 << d->hwirq);
        evpe(vpflags);
        mask_mips_irq(d);
 }
 
+#ifdef CONFIG_GENERIC_IRQ_IPI
+
+static void mips_mt_send_ipi(struct irq_data *d, unsigned int cpu)
+{
+       irq_hw_number_t hwirq = irqd_to_hwirq(d);
+       unsigned long flags;
+       int vpflags;
+
+       local_irq_save(flags);
+
+       /* We can only send IPIs to VPEs within the local core */
+       WARN_ON(cpu_data[cpu].core != current_cpu_data.core);
+
+       vpflags = dvpe();
+       settc(cpu_vpe_id(&cpu_data[cpu]));
+       write_vpe_c0_cause(read_vpe_c0_cause() | (C_SW0 << hwirq));
+       evpe(vpflags);
+
+       local_irq_restore(flags);
+}
+
+#endif /* CONFIG_GENERIC_IRQ_IPI */
+
 static struct irq_chip mips_mt_cpu_irq_controller = {
        .name           = "MIPS",
        .irq_startup    = mips_mt_cpu_irq_startup,
@@ -98,11 +123,15 @@ static struct irq_chip mips_mt_cpu_irq_controller = {
        .irq_eoi        = unmask_mips_irq,
        .irq_disable    = mask_mips_irq,
        .irq_enable     = unmask_mips_irq,
+#ifdef CONFIG_GENERIC_IRQ_IPI
+       .ipi_send_single = mips_mt_send_ipi,
+#endif
 };
 
 asmlinkage void __weak plat_irq_dispatch(void)
 {
        unsigned long pending = read_c0_cause() & read_c0_status() & ST0_IM;
+       unsigned int virq;
        int irq;
 
        if (!pending) {
@@ -113,7 +142,11 @@ asmlinkage void __weak plat_irq_dispatch(void)
        pending >>= CAUSEB_IP;
        while (pending) {
                irq = fls(pending) - 1;
-               do_IRQ(MIPS_CPU_IRQ_BASE + irq);
+               if (IS_ENABLED(CONFIG_GENERIC_IRQ_IPI) && irq < 2)
+                       virq = irq_linear_revmap(ipi_domain, irq);
+               else
+                       virq = irq_linear_revmap(irq_domain, irq);
+               do_IRQ(virq);
                pending &= ~BIT(irq);
        }
 }
@@ -143,18 +176,97 @@ static const struct irq_domain_ops mips_cpu_intc_irq_domain_ops = {
        .xlate = irq_domain_xlate_onecell,
 };
 
-static void __init __mips_cpu_irq_init(struct device_node *of_node)
+#ifdef CONFIG_GENERIC_IRQ_IPI
+
+struct cpu_ipi_domain_state {
+       DECLARE_BITMAP(allocated, 2);
+};
+
+static int mips_cpu_ipi_alloc(struct irq_domain *domain, unsigned int virq,
+                             unsigned int nr_irqs, void *arg)
 {
-       struct irq_domain *domain;
+       struct cpu_ipi_domain_state *state = domain->host_data;
+       unsigned int i, hwirq;
+       int ret;
 
+       for (i = 0; i < nr_irqs; i++) {
+               hwirq = find_first_zero_bit(state->allocated, 2);
+               if (hwirq == 2)
+                       return -EBUSY;
+               bitmap_set(state->allocated, hwirq, 1);
+
+               ret = irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq,
+                                                   &mips_mt_cpu_irq_controller,
+                                                   NULL);
+               if (ret)
+                       return ret;
+
+               ret = irq_set_irq_type(virq + i, IRQ_TYPE_LEVEL_HIGH);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int mips_cpu_ipi_match(struct irq_domain *d, struct device_node *node,
+                             enum irq_domain_bus_token bus_token)
+{
+       bool is_ipi;
+
+       switch (bus_token) {
+       case DOMAIN_BUS_IPI:
+               is_ipi = d->bus_token == bus_token;
+               return (!node || (to_of_node(d->fwnode) == node)) && is_ipi;
+       default:
+               return 0;
+       }
+}
+
+static const struct irq_domain_ops mips_cpu_ipi_chip_ops = {
+       .alloc  = mips_cpu_ipi_alloc,
+       .match  = mips_cpu_ipi_match,
+};
+
+static void mips_cpu_register_ipi_domain(struct device_node *of_node)
+{
+       struct cpu_ipi_domain_state *ipi_domain_state;
+
+       ipi_domain_state = kzalloc(sizeof(*ipi_domain_state), GFP_KERNEL);
+       ipi_domain = irq_domain_add_hierarchy(irq_domain,
+                                             IRQ_DOMAIN_FLAG_IPI_SINGLE,
+                                             2, of_node,
+                                             &mips_cpu_ipi_chip_ops,
+                                             ipi_domain_state);
+       if (!ipi_domain)
+               panic("Failed to add MIPS CPU IPI domain");
+       ipi_domain->bus_token = DOMAIN_BUS_IPI;
+}
+
+#else /* !CONFIG_GENERIC_IRQ_IPI */
+
+static inline void mips_cpu_register_ipi_domain(struct device_node *of_node) {}
+
+#endif /* !CONFIG_GENERIC_IRQ_IPI */
+
+static void __init __mips_cpu_irq_init(struct device_node *of_node)
+{
        /* Mask interrupts. */
        clear_c0_status(ST0_IM);
        clear_c0_cause(CAUSEF_IP);
 
-       domain = irq_domain_add_legacy(of_node, 8, MIPS_CPU_IRQ_BASE, 0,
-                                      &mips_cpu_intc_irq_domain_ops, NULL);
-       if (!domain)
+       irq_domain = irq_domain_add_legacy(of_node, 8, MIPS_CPU_IRQ_BASE, 0,
+                                          &mips_cpu_intc_irq_domain_ops,
+                                          NULL);
+       if (!irq_domain)
                panic("Failed to add irqdomain for MIPS CPU");
+
+       /*
+        * Only proceed to register the software interrupt IPI implementation
+        * for CPUs which implement the MIPS MT (multi-threading) ASE.
+        */
+       if (cpu_has_mipsmt)
+               mips_cpu_register_ipi_domain(of_node);
 }
 
 void __init mips_cpu_irq_init(void)
index 31ef8130a87ffcae6c62b903cb4397e7b93b19aa..54e871a473870a59b7f72e6bef888d0910e3233d 100644 (file)
@@ -169,8 +169,8 @@ static struct pci_dev isa_dev[MAX_CARDS];
 static int io[MAX_CARDS];
 static int irq[MAX_CARDS];
 
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
+module_param_hw_array(io, int, ioport, NULL, 0);
+module_param_hw_array(irq, int, irq, NULL, 0);
 MODULE_PARM_DESC(io, "I/O base address(es)");
 MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
 
index 72ef188539512d079774c02f2fcf9428c9ab5d5a..9516203c735f9fa0598c6c8a9c0eb895e2fdc73f 100644 (file)
@@ -516,8 +516,8 @@ static int io[MAX_CARDS];
 static int irq[MAX_CARDS];
 static int cardnr[MAX_CARDS];
 
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
+module_param_hw_array(io, int, ioport, NULL, 0);
+module_param_hw_array(irq, int, irq, NULL, 0);
 module_param_array(cardnr, int, NULL, 0);
 MODULE_PARM_DESC(io, "I/O base address(es)");
 MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
index 2d12c6ceeb89ae08bb6c100fd77320386010a043..c7d68675b02874e3661af07d1b8ad22ae8bcb887 100644 (file)
@@ -350,13 +350,13 @@ MODULE_AUTHOR("Karsten Keil");
 MODULE_LICENSE("GPL");
 module_param_array(type, int, NULL, 0);
 module_param_array(protocol, int, NULL, 0);
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
-module_param_array(mem, int, NULL, 0);
+module_param_hw_array(io, int, ioport, NULL, 0);
+module_param_hw_array(irq, int, irq, NULL, 0);
+module_param_hw_array(mem, int, iomem, NULL, 0);
 module_param(id, charp, 0);
 #ifdef IO0_IO1
-module_param_array(io0, int, NULL, 0);
-module_param_array(io1, int, NULL, 0);
+module_param_hw_array(io0, int, ioport, NULL, 0);
+module_param_hw_array(io1, int, ioport, NULL, 0);
 #endif
 #endif /* MODULE */
 
index 549b315ca8fe820932816d6c84e3d705bd876c99..f53c8cda1bde03e95753f7ddbf6acb58cc429fb4 100644 (file)
@@ -281,7 +281,7 @@ static void lp5521_firmware_loaded(struct lp55xx_chip *chip)
        }
 
        /*
-        * Program momery sequence
+        * Program memory sequence
         *  1) set engine mode to "LOAD"
         *  2) write firmware data into program memory
         */
index c5b30f06218a3af833c3dd9724f8871f19048d17..e9ba8cd32d66071b11c7b0baf4238d13cd1cfe8d 100644 (file)
@@ -387,7 +387,7 @@ static void lp5523_firmware_loaded(struct lp55xx_chip *chip)
        }
 
        /*
-        * Program momery sequence
+        * Program memory sequence
         *  1) set engine mode to "LOAD"
         *  2) write firmware data into program memory
         */
index b75333803a63776608acf7e5810c118123c6e166..90892585bcb55350b3b11a9f4b729f4112c92515 100644 (file)
@@ -270,7 +270,7 @@ static void lp5562_firmware_loaded(struct lp55xx_chip *chip)
        }
 
        /*
-        * Program momery sequence
+        * Program memory sequence
         *  1) set engine mode to "LOAD"
         *  2) write firmware data into program memory
         */
index 85e3f21c251485ecfd56780110896c05c8429cef..e57353e39168120dccdfe34965ac9360b58fd2db 100644 (file)
@@ -767,16 +767,12 @@ static int bcache_device_init(struct bcache_device *d, unsigned block_size,
        }
 
        n = d->nr_stripes * sizeof(atomic_t);
-       d->stripe_sectors_dirty = n < PAGE_SIZE << 6
-               ? kzalloc(n, GFP_KERNEL)
-               : vzalloc(n);
+       d->stripe_sectors_dirty = kvzalloc(n, GFP_KERNEL);
        if (!d->stripe_sectors_dirty)
                return -ENOMEM;
 
        n = BITS_TO_LONGS(d->nr_stripes) * sizeof(unsigned long);
-       d->full_dirty_stripes = n < PAGE_SIZE << 6
-               ? kzalloc(n, GFP_KERNEL)
-               : vzalloc(n);
+       d->full_dirty_stripes = kvzalloc(n, GFP_KERNEL);
        if (!d->full_dirty_stripes)
                return -ENOMEM;
 
index 5d13930f0f22fc42e40228cee8eee1ecb7cfa8e5..cb8d2ccbb6c6e7223aa0f806d45546c56421de7e 100644 (file)
@@ -43,11 +43,7 @@ struct closure;
        (heap)->used = 0;                                               \
        (heap)->size = (_size);                                         \
        _bytes = (heap)->size * sizeof(*(heap)->data);                  \
-       (heap)->data = NULL;                                            \
-       if (_bytes < KMALLOC_MAX_SIZE)                                  \
-               (heap)->data = kmalloc(_bytes, (gfp));                  \
-       if ((!(heap)->data) && ((gfp) & GFP_KERNEL))                    \
-               (heap)->data = vmalloc(_bytes);                         \
+       (heap)->data = kvmalloc(_bytes, (gfp) & GFP_KERNEL);            \
        (heap)->data;                                                   \
 })
 
@@ -136,12 +132,8 @@ do {                                                                       \
                                                                        \
        (fifo)->mask = _allocated_size - 1;                             \
        (fifo)->front = (fifo)->back = 0;                               \
-       (fifo)->data = NULL;                                            \
                                                                        \
-       if (_bytes < KMALLOC_MAX_SIZE)                                  \
-               (fifo)->data = kmalloc(_bytes, (gfp));                  \
-       if ((!(fifo)->data) && ((gfp) & GFP_KERNEL))                    \
-               (fifo)->data = vmalloc(_bytes);                         \
+       (fifo)->data = kvmalloc(_bytes, (gfp) & GFP_KERNEL);            \
        (fifo)->data;                                                   \
 })
 
index c92c31b23e543b8b68fec94918348f79740a9a61..cd8139593ccd50655a2329460cc8de9d175eac86 100644 (file)
@@ -218,7 +218,7 @@ static DEFINE_SPINLOCK(param_spinlock);
  * Buffers are freed after this timeout
  */
 static unsigned dm_bufio_max_age = DM_BUFIO_DEFAULT_AGE_SECS;
-static unsigned dm_bufio_retain_bytes = DM_BUFIO_DEFAULT_RETAIN_BYTES;
+static unsigned long dm_bufio_retain_bytes = DM_BUFIO_DEFAULT_RETAIN_BYTES;
 
 static unsigned long dm_bufio_peak_allocated;
 static unsigned long dm_bufio_allocated_kmem_cache;
@@ -406,7 +406,7 @@ static void *alloc_buffer_data(struct dm_bufio_client *c, gfp_t gfp_mask,
        if (gfp_mask & __GFP_NORETRY)
                noio_flag = memalloc_noio_save();
 
-       ptr = __vmalloc(c->block_size, gfp_mask | __GFP_HIGHMEM, PAGE_KERNEL);
+       ptr = __vmalloc(c->block_size, gfp_mask, PAGE_KERNEL);
 
        if (gfp_mask & __GFP_NORETRY)
                memalloc_noio_restore(noio_flag);
@@ -1558,10 +1558,10 @@ static bool __try_evict_buffer(struct dm_buffer *b, gfp_t gfp)
        return true;
 }
 
-static unsigned get_retain_buffers(struct dm_bufio_client *c)
+static unsigned long get_retain_buffers(struct dm_bufio_client *c)
 {
-        unsigned retain_bytes = ACCESS_ONCE(dm_bufio_retain_bytes);
-        return retain_bytes / c->block_size;
+        unsigned long retain_bytes = ACCESS_ONCE(dm_bufio_retain_bytes);
+        return retain_bytes >> (c->sectors_per_block_bits + SECTOR_SHIFT);
 }
 
 static unsigned long __scan(struct dm_bufio_client *c, unsigned long nr_to_scan,
@@ -1571,7 +1571,7 @@ static unsigned long __scan(struct dm_bufio_client *c, unsigned long nr_to_scan,
        struct dm_buffer *b, *tmp;
        unsigned long freed = 0;
        unsigned long count = nr_to_scan;
-       unsigned retain_target = get_retain_buffers(c);
+       unsigned long retain_target = get_retain_buffers(c);
 
        for (l = 0; l < LIST_SIZE; l++) {
                list_for_each_entry_safe_reverse(b, tmp, &c->lru[l], lru_list) {
@@ -1794,8 +1794,8 @@ static bool older_than(struct dm_buffer *b, unsigned long age_hz)
 static void __evict_old_buffers(struct dm_bufio_client *c, unsigned long age_hz)
 {
        struct dm_buffer *b, *tmp;
-       unsigned retain_target = get_retain_buffers(c);
-       unsigned count;
+       unsigned long retain_target = get_retain_buffers(c);
+       unsigned long count;
        LIST_HEAD(write_list);
 
        dm_bufio_lock(c);
@@ -1955,7 +1955,7 @@ MODULE_PARM_DESC(max_cache_size_bytes, "Size of metadata cache");
 module_param_named(max_age_seconds, dm_bufio_max_age, uint, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(max_age_seconds, "Max age of a buffer in seconds");
 
-module_param_named(retain_bytes, dm_bufio_retain_bytes, uint, S_IRUGO | S_IWUSR);
+module_param_named(retain_bytes, dm_bufio_retain_bytes, ulong, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(retain_bytes, "Try to keep at least this many bytes cached in memory");
 
 module_param_named(peak_allocated_bytes, dm_bufio_peak_allocated, ulong, S_IRUGO | S_IWUSR);
index 9b1afdfb13f0f9510183ab916e642206023a60c5..70723389129163146666664e053d03e4263d677a 100644 (file)
@@ -33,6 +33,11 @@ struct background_tracker *btracker_create(unsigned max_work)
 {
        struct background_tracker *b = kmalloc(sizeof(*b), GFP_KERNEL);
 
+       if (!b) {
+               DMERR("couldn't create background_tracker");
+               return NULL;
+       }
+
        b->max_work = max_work;
        atomic_set(&b->pending_promotes, 0);
        atomic_set(&b->pending_writebacks, 0);
index 72479bd61e118e51c4bada036901ebe1bc4b1091..e5eb9c9b4bc8e8265c90debdc3d86eea98f08d96 100644 (file)
@@ -1120,8 +1120,6 @@ static bool clean_target_met(struct smq_policy *mq, bool idle)
         * Cache entries may not be populated.  So we cannot rely on the
         * size of the clean queue.
         */
-       unsigned nr_clean;
-
        if (idle) {
                /*
                 * We'd like to clean everything.
@@ -1129,18 +1127,16 @@ static bool clean_target_met(struct smq_policy *mq, bool idle)
                return q_size(&mq->dirty) == 0u;
        }
 
-       nr_clean = from_cblock(mq->cache_size) - q_size(&mq->dirty);
-       return (nr_clean + btracker_nr_writebacks_queued(mq->bg_work)) >=
-               percent_to_target(mq, CLEAN_TARGET);
+       /*
+        * If we're busy we don't worry about cleaning at all.
+        */
+       return true;
 }
 
-static bool free_target_met(struct smq_policy *mq, bool idle)
+static bool free_target_met(struct smq_policy *mq)
 {
        unsigned nr_free;
 
-       if (!idle)
-               return true;
-
        nr_free = from_cblock(mq->cache_size) - mq->cache_alloc.nr_allocated;
        return (nr_free + btracker_nr_demotions_queued(mq->bg_work)) >=
                percent_to_target(mq, FREE_TARGET);
@@ -1190,9 +1186,9 @@ static void queue_demotion(struct smq_policy *mq)
        if (unlikely(WARN_ON_ONCE(!mq->migrations_allowed)))
                return;
 
-       e = q_peek(&mq->clean, mq->clean.nr_levels, true);
+       e = q_peek(&mq->clean, mq->clean.nr_levels / 2, true);
        if (!e) {
-               if (!clean_target_met(mq, false))
+               if (!clean_target_met(mq, true))
                        queue_writeback(mq);
                return;
        }
@@ -1220,7 +1216,7 @@ static void queue_promotion(struct smq_policy *mq, dm_oblock_t oblock,
                 * We always claim to be 'idle' to ensure some demotions happen
                 * with continuous loads.
                 */
-               if (!free_target_met(mq, true))
+               if (!free_target_met(mq))
                        queue_demotion(mq);
                return;
        }
@@ -1421,14 +1417,10 @@ static int smq_get_background_work(struct dm_cache_policy *p, bool idle,
        spin_lock_irqsave(&mq->lock, flags);
        r = btracker_issue(mq->bg_work, result);
        if (r == -ENODATA) {
-               /* find some writeback work to do */
-               if (mq->migrations_allowed && !free_target_met(mq, idle))
-                       queue_demotion(mq);
-
-               else if (!clean_target_met(mq, idle))
+               if (!clean_target_met(mq, idle)) {
                        queue_writeback(mq);
-
-               r = btracker_issue(mq->bg_work, result);
+                       r = btracker_issue(mq->bg_work, result);
+               }
        }
        spin_unlock_irqrestore(&mq->lock, flags);
 
@@ -1452,6 +1444,7 @@ static void __complete_background_work(struct smq_policy *mq,
                clear_pending(mq, e);
                if (success) {
                        e->oblock = work->oblock;
+                       e->level = NR_CACHE_LEVELS - 1;
                        push(mq, e);
                        // h, q, a
                } else {
index 1db375f50a1321aae81492d1b3ac6392c52a00c2..d682a0511381aad0cadb7ab1f4eae9f815639aa1 100644 (file)
@@ -94,6 +94,9 @@ static void iot_io_begin(struct io_tracker *iot, sector_t len)
 
 static void __iot_io_end(struct io_tracker *iot, sector_t len)
 {
+       if (!len)
+               return;
+
        iot->in_flight -= len;
        if (!iot->in_flight)
                iot->idle_time = jiffies;
@@ -474,7 +477,7 @@ struct cache {
        spinlock_t invalidation_lock;
        struct list_head invalidation_requests;
 
-       struct io_tracker origin_tracker;
+       struct io_tracker tracker;
 
        struct work_struct commit_ws;
        struct batcher committer;
@@ -901,8 +904,7 @@ static dm_oblock_t get_bio_block(struct cache *cache, struct bio *bio)
 
 static bool accountable_bio(struct cache *cache, struct bio *bio)
 {
-       return ((bio->bi_bdev == cache->origin_dev->bdev) &&
-               bio_op(bio) != REQ_OP_DISCARD);
+       return bio_op(bio) != REQ_OP_DISCARD;
 }
 
 static void accounted_begin(struct cache *cache, struct bio *bio)
@@ -912,7 +914,7 @@ static void accounted_begin(struct cache *cache, struct bio *bio)
 
        if (accountable_bio(cache, bio)) {
                pb->len = bio_sectors(bio);
-               iot_io_begin(&cache->origin_tracker, pb->len);
+               iot_io_begin(&cache->tracker, pb->len);
        }
 }
 
@@ -921,7 +923,7 @@ static void accounted_complete(struct cache *cache, struct bio *bio)
        size_t pb_data_size = get_per_bio_data_size(cache);
        struct per_bio_data *pb = get_per_bio_data(bio, pb_data_size);
 
-       iot_io_end(&cache->origin_tracker, pb->len);
+       iot_io_end(&cache->tracker, pb->len);
 }
 
 static void accounted_request(struct cache *cache, struct bio *bio)
@@ -1716,20 +1718,19 @@ static int invalidate_start(struct cache *cache, dm_cblock_t cblock,
 
 enum busy {
        IDLE,
-       MODERATE,
        BUSY
 };
 
 static enum busy spare_migration_bandwidth(struct cache *cache)
 {
-       bool idle = iot_idle_for(&cache->origin_tracker, HZ);
+       bool idle = iot_idle_for(&cache->tracker, HZ);
        sector_t current_volume = (atomic_read(&cache->nr_io_migrations) + 1) *
                cache->sectors_per_block;
 
-       if (current_volume <= cache->migration_threshold)
-               return idle ? IDLE : MODERATE;
+       if (idle && current_volume <= cache->migration_threshold)
+               return IDLE;
        else
-               return idle ? MODERATE : BUSY;
+               return BUSY;
 }
 
 static void inc_hit_counter(struct cache *cache, struct bio *bio)
@@ -2045,8 +2046,6 @@ static void check_migrations(struct work_struct *ws)
 
        for (;;) {
                b = spare_migration_bandwidth(cache);
-               if (b == BUSY)
-                       break;
 
                r = policy_get_background_work(cache->policy, b == IDLE, &op);
                if (r == -ENODATA)
@@ -2717,7 +2716,7 @@ static int cache_create(struct cache_args *ca, struct cache **result)
 
        batcher_init(&cache->committer, commit_op, cache,
                     issue_op, cache, cache->wq);
-       iot_init(&cache->origin_tracker);
+       iot_init(&cache->tracker);
 
        init_rwsem(&cache->background_work_lock);
        prevent_background_work(cache);
@@ -2941,7 +2940,7 @@ static void cache_postsuspend(struct dm_target *ti)
 
        cancel_delayed_work(&cache->waker);
        flush_workqueue(cache->wq);
-       WARN_ON(cache->origin_tracker.in_flight);
+       WARN_ON(cache->tracker.in_flight);
 
        /*
         * If it's a flush suspend there won't be any deferred bios, so this
index 2d5d7064acbf129bac46db6f2ceca86bcf6db4c6..0555b4410e0598a6096642f10978ad6798bc5f98 100644 (file)
@@ -1691,6 +1691,7 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kern
        struct dm_ioctl *dmi;
        int secure_data;
        const size_t minimum_data_size = offsetof(struct dm_ioctl, data);
+       unsigned noio_flag;
 
        if (copy_from_user(param_kernel, user, minimum_data_size))
                return -EFAULT;
@@ -1713,15 +1714,9 @@ static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl *param_kern
         * Use kmalloc() rather than vmalloc() when we can.
         */
        dmi = NULL;
-       if (param_kernel->data_size <= KMALLOC_MAX_SIZE)
-               dmi = kmalloc(param_kernel->data_size, GFP_NOIO | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN);
-
-       if (!dmi) {
-               unsigned noio_flag;
-               noio_flag = memalloc_noio_save();
-               dmi = __vmalloc(param_kernel->data_size, GFP_NOIO | __GFP_HIGH | __GFP_HIGHMEM, PAGE_KERNEL);
-               memalloc_noio_restore(noio_flag);
-       }
+       noio_flag = memalloc_noio_save();
+       dmi = kvmalloc(param_kernel->data_size, GFP_KERNEL);
+       memalloc_noio_restore(noio_flag);
 
        if (!dmi) {
                if (secure_data && clear_user(user, param_kernel->data_size))
index 926a6bcb32c8600118696119fd8ebe521cadbe5e..3df056b73b6610927a57058394a5bbe08f1b3404 100644 (file)
@@ -447,7 +447,7 @@ failed:
  * it has been invoked.
  */
 #define dm_report_EIO(m)                                               \
-({                                                                     \
+do {                                                                   \
        struct mapped_device *md = dm_table_get_md((m)->ti->table);     \
                                                                        \
        pr_debug("%s: returning EIO; QIFNP = %d; SQIFNP = %d; DNFS = %d\n", \
@@ -455,8 +455,7 @@ failed:
                 test_bit(MPATHF_QUEUE_IF_NO_PATH, &(m)->flags),        \
                 test_bit(MPATHF_SAVED_QUEUE_IF_NO_PATH, &(m)->flags),  \
                 dm_noflush_suspending((m)->ti));                       \
-       -EIO;                                                           \
-})
+} while (0)
 
 /*
  * Map cloned requests (request-based multipath)
@@ -481,7 +480,8 @@ static int multipath_clone_and_map(struct dm_target *ti, struct request *rq,
        if (!pgpath) {
                if (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags))
                        return DM_MAPIO_DELAY_REQUEUE;
-               return dm_report_EIO(m);        /* Failed */
+               dm_report_EIO(m);       /* Failed */
+               return DM_MAPIO_KILL;
        } else if (test_bit(MPATHF_QUEUE_IO, &m->flags) ||
                   test_bit(MPATHF_PG_INIT_REQUIRED, &m->flags)) {
                if (pg_init_all_paths(m))
@@ -558,7 +558,8 @@ static int __multipath_map_bio(struct multipath *m, struct bio *bio, struct dm_m
        if (!pgpath) {
                if (test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags))
                        return DM_MAPIO_REQUEUE;
-               return dm_report_EIO(m);
+               dm_report_EIO(m);
+               return -EIO;
        }
 
        mpio->pgpath = pgpath;
@@ -1493,7 +1494,7 @@ static int multipath_end_io(struct dm_target *ti, struct request *clone,
                if (atomic_read(&m->nr_valid_paths) == 0 &&
                    !test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) {
                        if (error == -EIO)
-                               error = dm_report_EIO(m);
+                               dm_report_EIO(m);
                        /* complete with the original error */
                        r = DM_ENDIO_DONE;
                }
@@ -1524,8 +1525,10 @@ static int do_end_io_bio(struct multipath *m, struct bio *clone,
                fail_path(mpio->pgpath);
 
        if (atomic_read(&m->nr_valid_paths) == 0 &&
-           !test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags))
-               return dm_report_EIO(m);
+           !test_bit(MPATHF_QUEUE_IF_NO_PATH, &m->flags)) {
+               dm_report_EIO(m);
+               return -EIO;
+       }
 
        /* Queue for the daemon to resubmit */
        dm_bio_restore(get_bio_details_from_bio(clone), clone);
index 2af27026aa2edd7ec0683c0d6f92ac3612eff0d4..b639fa7246eebec191aa8a084333391ab0435dfa 100644 (file)
@@ -507,6 +507,7 @@ static int map_request(struct dm_rq_target_io *tio)
        case DM_MAPIO_KILL:
                /* The target wants to complete the I/O */
                dm_kill_unmapped_request(rq, -EIO);
+               break;
        default:
                DMWARN("unimplemented target map return value: %d", r);
                BUG();
index 0250e7e521abcbae456b0552e774d47f507f3dc3..6028d8247f5830cd796356414980ff95a74b1647 100644 (file)
@@ -146,12 +146,7 @@ static void *dm_kvzalloc(size_t alloc_size, int node)
        if (!claim_shared_memory(alloc_size))
                return NULL;
 
-       if (alloc_size <= KMALLOC_MAX_SIZE) {
-               p = kzalloc_node(alloc_size, GFP_KERNEL | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN, node);
-               if (p)
-                       return p;
-       }
-       p = vzalloc_node(alloc_size, node);
+       p = kvzalloc_node(alloc_size, GFP_KERNEL | __GFP_NOMEMALLOC, node);
        if (p)
                return p;
 
index 0f0251d0d337fff94b1e41d11940d658874eda17..d31d18d9727c69d555d7971e53ddde6b6c401bf3 100644 (file)
@@ -484,11 +484,11 @@ static int __write_initial_superblock(struct dm_pool_metadata *pmd)
        if (r < 0)
                return r;
 
-       r = save_sm_roots(pmd);
+       r = dm_tm_pre_commit(pmd->tm);
        if (r < 0)
                return r;
 
-       r = dm_tm_pre_commit(pmd->tm);
+       r = save_sm_roots(pmd);
        if (r < 0)
                return r;
 
index 82f798be964fc51d8c1d2d5b8cf5fc88392814ee..10367ffe92e3e37704f5e32793ea97175c8b15e6 100644 (file)
@@ -8022,18 +8022,15 @@ EXPORT_SYMBOL(md_write_end);
  * may proceed without blocking.  It is important to call this before
  * attempting a GFP_KERNEL allocation while holding the mddev lock.
  * Must be called with mddev_lock held.
- *
- * In the ->external case MD_SB_CHANGE_PENDING can not be cleared until mddev->lock
- * is dropped, so return -EAGAIN after notifying userspace.
  */
-int md_allow_write(struct mddev *mddev)
+void md_allow_write(struct mddev *mddev)
 {
        if (!mddev->pers)
-               return 0;
+               return;
        if (mddev->ro)
-               return 0;
+               return;
        if (!mddev->pers->sync_request)
-               return 0;
+               return;
 
        spin_lock(&mddev->lock);
        if (mddev->in_sync) {
@@ -8046,13 +8043,12 @@ int md_allow_write(struct mddev *mddev)
                spin_unlock(&mddev->lock);
                md_update_sb(mddev, 0);
                sysfs_notify_dirent_safe(mddev->sysfs_state);
+               /* wait for the dirty state to be recorded in the metadata */
+               wait_event(mddev->sb_wait,
+                          !test_bit(MD_SB_CHANGE_CLEAN, &mddev->sb_flags) &&
+                          !test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags));
        } else
                spin_unlock(&mddev->lock);
-
-       if (test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags))
-               return -EAGAIN;
-       else
-               return 0;
 }
 EXPORT_SYMBOL_GPL(md_allow_write);
 
index 4e75d121bfcc5671640421769476c85d2843e7c9..11f15146ce5177de0468c706a5f82a037b42c132 100644 (file)
@@ -665,7 +665,7 @@ extern int sync_page_io(struct md_rdev *rdev, sector_t sector, int size,
                        bool metadata_op);
 extern void md_do_sync(struct md_thread *thread);
 extern void md_new_event(struct mddev *mddev);
-extern int md_allow_write(struct mddev *mddev);
+extern void md_allow_write(struct mddev *mddev);
 extern void md_wait_for_blocked_rdev(struct md_rdev *rdev, struct mddev *mddev);
 extern void md_set_array_sectors(struct mddev *mddev, sector_t array_sectors);
 extern int md_check_no_bitmap(struct mddev *mddev);
index ebb280a14325e1d937986926b40592c3b1847168..32adf6b4a9c7097e12796f8b396f80bfc8867c0a 100644 (file)
@@ -142,10 +142,23 @@ static int sm_disk_inc_block(struct dm_space_map *sm, dm_block_t b)
 
 static int sm_disk_dec_block(struct dm_space_map *sm, dm_block_t b)
 {
+       int r;
+       uint32_t old_count;
        enum allocation_event ev;
        struct sm_disk *smd = container_of(sm, struct sm_disk, sm);
 
-       return sm_ll_dec(&smd->ll, b, &ev);
+       r = sm_ll_dec(&smd->ll, b, &ev);
+       if (!r && (ev == SM_FREE)) {
+               /*
+                * It's only free if it's also free in the last
+                * transaction.
+                */
+               r = sm_ll_lookup(&smd->old_ll, b, &old_count);
+               if (!r && !old_count)
+                       smd->nr_allocated_this_transaction--;
+       }
+
+       return r;
 }
 
 static int sm_disk_new_block(struct dm_space_map *sm, dm_block_t *b)
index 84e58596594db79f0dde1f789de9a200fb1f0e8c..d6c0bc76e837dff8636253f4daaea0aa16ce4d89 100644 (file)
@@ -385,7 +385,7 @@ static int raid0_run(struct mddev *mddev)
                blk_queue_max_hw_sectors(mddev->queue, mddev->chunk_sectors);
                blk_queue_max_write_same_sectors(mddev->queue, mddev->chunk_sectors);
                blk_queue_max_write_zeroes_sectors(mddev->queue, mddev->chunk_sectors);
-               blk_queue_max_discard_sectors(mddev->queue, mddev->chunk_sectors);
+               blk_queue_max_discard_sectors(mddev->queue, UINT_MAX);
 
                blk_queue_io_min(mddev->queue, mddev->chunk_sectors << 9);
                blk_queue_io_opt(mddev->queue,
@@ -459,6 +459,95 @@ static inline int is_io_in_chunk_boundary(struct mddev *mddev,
        }
 }
 
+static void raid0_handle_discard(struct mddev *mddev, struct bio *bio)
+{
+       struct r0conf *conf = mddev->private;
+       struct strip_zone *zone;
+       sector_t start = bio->bi_iter.bi_sector;
+       sector_t end;
+       unsigned int stripe_size;
+       sector_t first_stripe_index, last_stripe_index;
+       sector_t start_disk_offset;
+       unsigned int start_disk_index;
+       sector_t end_disk_offset;
+       unsigned int end_disk_index;
+       unsigned int disk;
+
+       zone = find_zone(conf, &start);
+
+       if (bio_end_sector(bio) > zone->zone_end) {
+               struct bio *split = bio_split(bio,
+                       zone->zone_end - bio->bi_iter.bi_sector, GFP_NOIO,
+                       mddev->bio_set);
+               bio_chain(split, bio);
+               generic_make_request(bio);
+               bio = split;
+               end = zone->zone_end;
+       } else
+               end = bio_end_sector(bio);
+
+       if (zone != conf->strip_zone)
+               end = end - zone[-1].zone_end;
+
+       /* Now start and end is the offset in zone */
+       stripe_size = zone->nb_dev * mddev->chunk_sectors;
+
+       first_stripe_index = start;
+       sector_div(first_stripe_index, stripe_size);
+       last_stripe_index = end;
+       sector_div(last_stripe_index, stripe_size);
+
+       start_disk_index = (int)(start - first_stripe_index * stripe_size) /
+               mddev->chunk_sectors;
+       start_disk_offset = ((int)(start - first_stripe_index * stripe_size) %
+               mddev->chunk_sectors) +
+               first_stripe_index * mddev->chunk_sectors;
+       end_disk_index = (int)(end - last_stripe_index * stripe_size) /
+               mddev->chunk_sectors;
+       end_disk_offset = ((int)(end - last_stripe_index * stripe_size) %
+               mddev->chunk_sectors) +
+               last_stripe_index * mddev->chunk_sectors;
+
+       for (disk = 0; disk < zone->nb_dev; disk++) {
+               sector_t dev_start, dev_end;
+               struct bio *discard_bio = NULL;
+               struct md_rdev *rdev;
+
+               if (disk < start_disk_index)
+                       dev_start = (first_stripe_index + 1) *
+                               mddev->chunk_sectors;
+               else if (disk > start_disk_index)
+                       dev_start = first_stripe_index * mddev->chunk_sectors;
+               else
+                       dev_start = start_disk_offset;
+
+               if (disk < end_disk_index)
+                       dev_end = (last_stripe_index + 1) * mddev->chunk_sectors;
+               else if (disk > end_disk_index)
+                       dev_end = last_stripe_index * mddev->chunk_sectors;
+               else
+                       dev_end = end_disk_offset;
+
+               if (dev_end <= dev_start)
+                       continue;
+
+               rdev = conf->devlist[(zone - conf->strip_zone) *
+                       conf->strip_zone[0].nb_dev + disk];
+               if (__blkdev_issue_discard(rdev->bdev,
+                       dev_start + zone->dev_start + rdev->data_offset,
+                       dev_end - dev_start, GFP_NOIO, 0, &discard_bio) ||
+                   !discard_bio)
+                       continue;
+               bio_chain(discard_bio, bio);
+               if (mddev->gendisk)
+                       trace_block_bio_remap(bdev_get_queue(rdev->bdev),
+                               discard_bio, disk_devt(mddev->gendisk),
+                               bio->bi_iter.bi_sector);
+               generic_make_request(discard_bio);
+       }
+       bio_endio(bio);
+}
+
 static void raid0_make_request(struct mddev *mddev, struct bio *bio)
 {
        struct strip_zone *zone;
@@ -473,6 +562,11 @@ static void raid0_make_request(struct mddev *mddev, struct bio *bio)
                return;
        }
 
+       if (unlikely((bio_op(bio) == REQ_OP_DISCARD))) {
+               raid0_handle_discard(mddev, bio);
+               return;
+       }
+
        bio_sector = bio->bi_iter.bi_sector;
        sector = bio_sector;
        chunk_sects = mddev->chunk_sectors;
@@ -498,19 +592,13 @@ static void raid0_make_request(struct mddev *mddev, struct bio *bio)
        bio->bi_iter.bi_sector = sector + zone->dev_start +
                tmp_dev->data_offset;
 
-       if (unlikely((bio_op(bio) == REQ_OP_DISCARD) &&
-                    !blk_queue_discard(bdev_get_queue(bio->bi_bdev)))) {
-               /* Just ignore it */
-               bio_endio(bio);
-       } else {
-               if (mddev->gendisk)
-                       trace_block_bio_remap(bdev_get_queue(bio->bi_bdev),
-                                             bio, disk_devt(mddev->gendisk),
-                                             bio_sector);
-               mddev_check_writesame(mddev, bio);
-               mddev_check_write_zeroes(mddev, bio);
-               generic_make_request(bio);
-       }
+       if (mddev->gendisk)
+               trace_block_bio_remap(bdev_get_queue(bio->bi_bdev),
+                                     bio, disk_devt(mddev->gendisk),
+                                     bio_sector);
+       mddev_check_writesame(mddev, bio);
+       mddev_check_write_zeroes(mddev, bio);
+       generic_make_request(bio);
 }
 
 static void raid0_status(struct seq_file *seq, struct mddev *mddev)
index 7ed59351fe972d60a8bf2bb22d20f4abaa718710..af5056d568788a53f6c3a2456a353cba3bbfe35a 100644 (file)
@@ -666,8 +666,11 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect
                                        break;
                        }
                        continue;
-               } else
+               } else {
+                       if ((sectors > best_good_sectors) && (best_disk >= 0))
+                               best_disk = -1;
                        best_good_sectors = sectors;
+               }
 
                if (best_disk >= 0)
                        /* At least two disks to choose from so failfast is OK */
@@ -1529,17 +1532,16 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
                        plug = container_of(cb, struct raid1_plug_cb, cb);
                else
                        plug = NULL;
-               spin_lock_irqsave(&conf->device_lock, flags);
                if (plug) {
                        bio_list_add(&plug->pending, mbio);
                        plug->pending_cnt++;
                } else {
+                       spin_lock_irqsave(&conf->device_lock, flags);
                        bio_list_add(&conf->pending_bio_list, mbio);
                        conf->pending_count++;
-               }
-               spin_unlock_irqrestore(&conf->device_lock, flags);
-               if (!plug)
+                       spin_unlock_irqrestore(&conf->device_lock, flags);
                        md_wakeup_thread(mddev->thread);
+               }
        }
 
        r1_bio_write_done(r1_bio);
@@ -3197,7 +3199,7 @@ static int raid1_reshape(struct mddev *mddev)
        struct r1conf *conf = mddev->private;
        int cnt, raid_disks;
        unsigned long flags;
-       int d, d2, err;
+       int d, d2;
 
        /* Cannot change chunk_size, layout, or level */
        if (mddev->chunk_sectors != mddev->new_chunk_sectors ||
@@ -3209,11 +3211,8 @@ static int raid1_reshape(struct mddev *mddev)
                return -EINVAL;
        }
 
-       if (!mddev_is_clustered(mddev)) {
-               err = md_allow_write(mddev);
-               if (err)
-                       return err;
-       }
+       if (!mddev_is_clustered(mddev))
+               md_allow_write(mddev);
 
        raid_disks = mddev->raid_disks + mddev->delta_disks;
 
index 6b86a0032cf86683834c1ce82fcda6e6bd6b8e80..4343d7ff9916bee9a9a399572c2bd3313723fa3a 100644 (file)
@@ -1282,17 +1282,16 @@ static void raid10_write_one_disk(struct mddev *mddev, struct r10bio *r10_bio,
                plug = container_of(cb, struct raid10_plug_cb, cb);
        else
                plug = NULL;
-       spin_lock_irqsave(&conf->device_lock, flags);
        if (plug) {
                bio_list_add(&plug->pending, mbio);
                plug->pending_cnt++;
        } else {
+               spin_lock_irqsave(&conf->device_lock, flags);
                bio_list_add(&conf->pending_bio_list, mbio);
                conf->pending_count++;
-       }
-       spin_unlock_irqrestore(&conf->device_lock, flags);
-       if (!plug)
+               spin_unlock_irqrestore(&conf->device_lock, flags);
                md_wakeup_thread(mddev->thread);
+       }
 }
 
 static void raid10_write_request(struct mddev *mddev, struct bio *bio,
index 26ba09282e7c9691bdc352c5fb4b75b9f6e29821..4c00bc248287e4ab89b492225e0d054973725549 100644 (file)
@@ -24,6 +24,7 @@
 #include "md.h"
 #include "raid5.h"
 #include "bitmap.h"
+#include "raid5-log.h"
 
 /*
  * metadata/data stored in disk with 4k size unit (a block) regardless
@@ -622,20 +623,30 @@ static void r5l_do_submit_io(struct r5l_log *log, struct r5l_io_unit *io)
        __r5l_set_io_unit_state(io, IO_UNIT_IO_START);
        spin_unlock_irqrestore(&log->io_list_lock, flags);
 
+       /*
+        * In case of journal device failures, submit_bio will get error
+        * and calls endio, then active stripes will continue write
+        * process. Therefore, it is not necessary to check Faulty bit
+        * of journal device here.
+        *
+        * We can't check split_bio after current_bio is submitted. If
+        * io->split_bio is null, after current_bio is submitted, current_bio
+        * might already be completed and the io_unit is freed. We submit
+        * split_bio first to avoid the issue.
+        */
+       if (io->split_bio) {
+               if (io->has_flush)
+                       io->split_bio->bi_opf |= REQ_PREFLUSH;
+               if (io->has_fua)
+                       io->split_bio->bi_opf |= REQ_FUA;
+               submit_bio(io->split_bio);
+       }
+
        if (io->has_flush)
                io->current_bio->bi_opf |= REQ_PREFLUSH;
        if (io->has_fua)
                io->current_bio->bi_opf |= REQ_FUA;
        submit_bio(io->current_bio);
-
-       if (!io->split_bio)
-               return;
-
-       if (io->has_flush)
-               io->split_bio->bi_opf |= REQ_PREFLUSH;
-       if (io->has_fua)
-               io->split_bio->bi_opf |= REQ_FUA;
-       submit_bio(io->split_bio);
 }
 
 /* deferred io_unit will be dispatched here */
@@ -670,6 +681,11 @@ static void r5c_disable_writeback_async(struct work_struct *work)
                return;
        pr_info("md/raid:%s: Disabling writeback cache for degraded array.\n",
                mdname(mddev));
+
+       /* wait superblock change before suspend */
+       wait_event(mddev->sb_wait,
+                  !test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags));
+
        mddev_suspend(mddev);
        log->r5c_journal_mode = R5C_JOURNAL_MODE_WRITE_THROUGH;
        mddev_resume(mddev);
@@ -2621,8 +2637,11 @@ int r5c_try_caching_write(struct r5conf *conf,
         * When run in degraded mode, array is set to write-through mode.
         * This check helps drain pending write safely in the transition to
         * write-through mode.
+        *
+        * When a stripe is syncing, the write is also handled in write
+        * through mode.
         */
-       if (s->failed) {
+       if (s->failed || test_bit(STRIPE_SYNCING, &sh->state)) {
                r5c_make_stripe_write_out(sh);
                return -EAGAIN;
        }
@@ -2825,6 +2844,9 @@ void r5c_finish_stripe_write_out(struct r5conf *conf,
        }
 
        r5l_append_flush_payload(log, sh->sector);
+       /* stripe is flused to raid disks, we can do resync now */
+       if (test_bit(STRIPE_SYNC_REQUESTED, &sh->state))
+               set_bit(STRIPE_HANDLE, &sh->state);
 }
 
 int r5c_cache_data(struct r5l_log *log, struct stripe_head *sh)
@@ -2973,7 +2995,7 @@ ioerr:
        return ret;
 }
 
-void r5c_update_on_rdev_error(struct mddev *mddev)
+void r5c_update_on_rdev_error(struct mddev *mddev, struct md_rdev *rdev)
 {
        struct r5conf *conf = mddev->private;
        struct r5l_log *log = conf->log;
@@ -2981,7 +3003,8 @@ void r5c_update_on_rdev_error(struct mddev *mddev)
        if (!log)
                return;
 
-       if (raid5_calc_degraded(conf) > 0 &&
+       if ((raid5_calc_degraded(conf) > 0 ||
+            test_bit(Journal, &rdev->flags)) &&
            conf->log->r5c_journal_mode == R5C_JOURNAL_MODE_WRITE_BACK)
                schedule_work(&log->disable_writeback_work);
 }
index 27097101cccac90b739ce5564145114df2417f6b..328d67aedda49dcf2a7c93d1d188d77108794647 100644 (file)
@@ -28,7 +28,8 @@ extern void r5c_flush_cache(struct r5conf *conf, int num);
 extern void r5c_check_stripe_cache_usage(struct r5conf *conf);
 extern void r5c_check_cached_full_stripe(struct r5conf *conf);
 extern struct md_sysfs_entry r5c_journal_mode;
-extern void r5c_update_on_rdev_error(struct mddev *mddev);
+extern void r5c_update_on_rdev_error(struct mddev *mddev,
+                                    struct md_rdev *rdev);
 extern bool r5c_big_stripe_cached(struct r5conf *conf, sector_t sect);
 
 extern struct dma_async_tx_descriptor *
index 2e38cfac5b1dc5a318f66b4bb6e2e2195797ad53..9c4f7659f8b1337c99cfd0ab5070012e3f658849 100644 (file)
@@ -103,8 +103,7 @@ static inline void unlock_device_hash_lock(struct r5conf *conf, int hash)
 static inline void lock_all_device_hash_locks_irq(struct r5conf *conf)
 {
        int i;
-       local_irq_disable();
-       spin_lock(conf->hash_locks);
+       spin_lock_irq(conf->hash_locks);
        for (i = 1; i < NR_STRIPE_HASH_LOCKS; i++)
                spin_lock_nest_lock(conf->hash_locks + i, conf->hash_locks);
        spin_lock(&conf->device_lock);
@@ -114,9 +113,9 @@ static inline void unlock_all_device_hash_locks_irq(struct r5conf *conf)
 {
        int i;
        spin_unlock(&conf->device_lock);
-       for (i = NR_STRIPE_HASH_LOCKS; i; i--)
-               spin_unlock(conf->hash_locks + i - 1);
-       local_irq_enable();
+       for (i = NR_STRIPE_HASH_LOCKS - 1; i; i--)
+               spin_unlock(conf->hash_locks + i);
+       spin_unlock_irq(conf->hash_locks);
 }
 
 /* Find first data disk in a raid6 stripe */
@@ -234,11 +233,15 @@ static void do_release_stripe(struct r5conf *conf, struct stripe_head *sh,
                        if (test_bit(R5_InJournal, &sh->dev[i].flags))
                                injournal++;
        /*
-        * When quiesce in r5c write back, set STRIPE_HANDLE for stripes with
-        * data in journal, so they are not released to cached lists
+        * In the following cases, the stripe cannot be released to cached
+        * lists. Therefore, we make the stripe write out and set
+        * STRIPE_HANDLE:
+        *   1. when quiesce in r5c write back;
+        *   2. when resync is requested fot the stripe.
         */
-       if (conf->quiesce && r5c_is_writeback(conf->log) &&
-           !test_bit(STRIPE_HANDLE, &sh->state) && injournal != 0) {
+       if (test_bit(STRIPE_SYNC_REQUESTED, &sh->state) ||
+           (conf->quiesce && r5c_is_writeback(conf->log) &&
+            !test_bit(STRIPE_HANDLE, &sh->state) && injournal != 0)) {
                if (test_bit(STRIPE_R5C_CACHING, &sh->state))
                        r5c_make_stripe_write_out(sh);
                set_bit(STRIPE_HANDLE, &sh->state);
@@ -714,12 +717,11 @@ static bool is_full_stripe_write(struct stripe_head *sh)
 
 static void lock_two_stripes(struct stripe_head *sh1, struct stripe_head *sh2)
 {
-       local_irq_disable();
        if (sh1 > sh2) {
-               spin_lock(&sh2->stripe_lock);
+               spin_lock_irq(&sh2->stripe_lock);
                spin_lock_nested(&sh1->stripe_lock, 1);
        } else {
-               spin_lock(&sh1->stripe_lock);
+               spin_lock_irq(&sh1->stripe_lock);
                spin_lock_nested(&sh2->stripe_lock, 1);
        }
 }
@@ -727,8 +729,7 @@ static void lock_two_stripes(struct stripe_head *sh1, struct stripe_head *sh2)
 static void unlock_two_stripes(struct stripe_head *sh1, struct stripe_head *sh2)
 {
        spin_unlock(&sh1->stripe_lock);
-       spin_unlock(&sh2->stripe_lock);
-       local_irq_enable();
+       spin_unlock_irq(&sh2->stripe_lock);
 }
 
 /* Only freshly new full stripe normal write stripe can be added to a batch list */
@@ -2312,14 +2313,12 @@ static int resize_stripes(struct r5conf *conf, int newsize)
        struct stripe_head *osh, *nsh;
        LIST_HEAD(newstripes);
        struct disk_info *ndisks;
-       int err;
+       int err = 0;
        struct kmem_cache *sc;
        int i;
        int hash, cnt;
 
-       err = md_allow_write(conf->mddev);
-       if (err)
-               return err;
+       md_allow_write(conf->mddev);
 
        /* Step 1 */
        sc = kmem_cache_create(conf->cache_name[1-conf->active_name],
@@ -2694,7 +2693,7 @@ static void raid5_error(struct mddev *mddev, struct md_rdev *rdev)
                bdevname(rdev->bdev, b),
                mdname(mddev),
                conf->raid_disks - mddev->degraded);
-       r5c_update_on_rdev_error(mddev);
+       r5c_update_on_rdev_error(mddev, rdev);
 }
 
 /*
@@ -3055,6 +3054,11 @@ sector_t raid5_compute_blocknr(struct stripe_head *sh, int i, int previous)
  *      When LOG_CRITICAL, stripes with injournal == 0 will be sent to
  *      no_space_stripes list.
  *
+ *   3. during journal failure
+ *      In journal failure, we try to flush all cached data to raid disks
+ *      based on data in stripe cache. The array is read-only to upper
+ *      layers, so we would skip all pending writes.
+ *
  */
 static inline bool delay_towrite(struct r5conf *conf,
                                 struct r5dev *dev,
@@ -3068,6 +3072,9 @@ static inline bool delay_towrite(struct r5conf *conf,
        if (test_bit(R5C_LOG_CRITICAL, &conf->cache_state) &&
            s->injournal > 0)
                return true;
+       /* case 3 above */
+       if (s->log_failed && s->injournal)
+               return true;
        return false;
 }
 
@@ -4653,8 +4660,13 @@ static void handle_stripe(struct stripe_head *sh)
 
        if (test_bit(STRIPE_SYNC_REQUESTED, &sh->state) && !sh->batch_head) {
                spin_lock(&sh->stripe_lock);
-               /* Cannot process 'sync' concurrently with 'discard' */
-               if (!test_bit(STRIPE_DISCARD, &sh->state) &&
+               /*
+                * Cannot process 'sync' concurrently with 'discard'.
+                * Flush data in r5cache before 'sync'.
+                */
+               if (!test_bit(STRIPE_R5C_PARTIAL_STRIPE, &sh->state) &&
+                   !test_bit(STRIPE_R5C_FULL_STRIPE, &sh->state) &&
+                   !test_bit(STRIPE_DISCARD, &sh->state) &&
                    test_and_clear_bit(STRIPE_SYNC_REQUESTED, &sh->state)) {
                        set_bit(STRIPE_SYNCING, &sh->state);
                        clear_bit(STRIPE_INSYNC, &sh->state);
@@ -4701,10 +4713,15 @@ static void handle_stripe(struct stripe_head *sh)
               " to_write=%d failed=%d failed_num=%d,%d\n",
               s.locked, s.uptodate, s.to_read, s.to_write, s.failed,
               s.failed_num[0], s.failed_num[1]);
-       /* check if the array has lost more than max_degraded devices and,
+       /*
+        * check if the array has lost more than max_degraded devices and,
         * if so, some requests might need to be failed.
+        *
+        * When journal device failed (log_failed), we will only process
+        * the stripe if there is data need write to raid disks
         */
-       if (s.failed > conf->max_degraded || s.log_failed) {
+       if (s.failed > conf->max_degraded ||
+           (s.log_failed && s.injournal == 0)) {
                sh->check_state = 0;
                sh->reconstruct_state = 0;
                break_stripe_batch_list(sh, 0);
@@ -5277,8 +5294,10 @@ static struct stripe_head *__get_priority_stripe(struct r5conf *conf, int group)
        struct stripe_head *sh, *tmp;
        struct list_head *handle_list = NULL;
        struct r5worker_group *wg;
-       bool second_try = !r5c_is_writeback(conf->log);
-       bool try_loprio = test_bit(R5C_LOG_TIGHT, &conf->cache_state);
+       bool second_try = !r5c_is_writeback(conf->log) &&
+               !r5l_log_disk_error(conf);
+       bool try_loprio = test_bit(R5C_LOG_TIGHT, &conf->cache_state) ||
+               r5l_log_disk_error(conf);
 
 again:
        wg = NULL;
@@ -6313,7 +6332,6 @@ int
 raid5_set_cache_size(struct mddev *mddev, int size)
 {
        struct r5conf *conf = mddev->private;
-       int err;
 
        if (size <= 16 || size > 32768)
                return -EINVAL;
@@ -6325,10 +6343,7 @@ raid5_set_cache_size(struct mddev *mddev, int size)
                ;
        mutex_unlock(&conf->cache_size_mutex);
 
-
-       err = md_allow_write(mddev);
-       if (err)
-               return err;
+       md_allow_write(mddev);
 
        mutex_lock(&conf->cache_size_mutex);
        while (size > conf->max_nr_stripes)
@@ -7530,7 +7545,9 @@ static int raid5_remove_disk(struct mddev *mddev, struct md_rdev *rdev)
                 * neilb: there is no locking about new writes here,
                 * so this cannot be safe.
                 */
-               if (atomic_read(&conf->active_stripes)) {
+               if (atomic_read(&conf->active_stripes) ||
+                   atomic_read(&conf->r5c_cached_full_stripes) ||
+                   atomic_read(&conf->r5c_cached_partial_stripes)) {
                        return -EBUSY;
                }
                log_exit(conf);
index 354ec07eae876ba3ede8b3d983839a7c468e5bfc..23ae724680256cad7f0a51052111e522d7859046 100644 (file)
@@ -70,7 +70,7 @@
 * (3) both long and short but short preferred and long only when necesarry
 *
 * These modes must be selected compile time via compile switches.
-* Compile switch settings for the diffrent modes:
+* Compile switch settings for the different modes:
 * (1) DRXDAPFASI_LONG_ADDR_ALLOWED=0, DRXDAPFASI_SHORT_ADDR_ALLOWED=1
 * (2) DRXDAPFASI_LONG_ADDR_ALLOWED=1, DRXDAPFASI_SHORT_ADDR_ALLOWED=0
 * (3) DRXDAPFASI_LONG_ADDR_ALLOWED=1, DRXDAPFASI_SHORT_ADDR_ALLOWED=1
index 5266755add63de6e9f93876b8ff0e89a4d9416cb..4680f001653a6263ab7f81df47a7928ff069f540 100644 (file)
@@ -69,7 +69,7 @@ MODULE_PARM_DESC(card, "Card type");
  */
 
 static unsigned long vidmem;   /* default = 0 - Video memory base address */
-module_param(vidmem, ulong, 0444);
+module_param_hw(vidmem, ulong, iomem, 0444);
 MODULE_PARM_DESC(vidmem, "Default video memory base address");
 
 /*
index aa44e11decca380358330a21095d946961f4c6bd..853d598937f69d4667ce5a28d078e53365c2b134 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/of_reserved_mem.h>
 #include <linux/sched.h>
 #include <linux/sizes.h>
+#include <linux/dma-mapping.h>
 
 #include "mtk_vpu.h"
 
index 084ecf4aa9a4a455c468d336b7d3f4c1b3990416..0d984a28a003adb37a008751d41c34305cd7c022 100644 (file)
@@ -1943,30 +1943,13 @@ static void isp_detach_iommu(struct isp_device *isp)
 {
        arm_iommu_release_mapping(isp->mapping);
        isp->mapping = NULL;
-       iommu_group_remove_device(isp->dev);
 }
 
 static int isp_attach_iommu(struct isp_device *isp)
 {
        struct dma_iommu_mapping *mapping;
-       struct iommu_group *group;
        int ret;
 
-       /* Create a device group and add the device to it. */
-       group = iommu_group_alloc();
-       if (IS_ERR(group)) {
-               dev_err(isp->dev, "failed to allocate IOMMU group\n");
-               return PTR_ERR(group);
-       }
-
-       ret = iommu_group_add_device(group, isp->dev);
-       iommu_group_put(group);
-
-       if (ret < 0) {
-               dev_err(isp->dev, "failed to add device to IPMMU group\n");
-               return ret;
-       }
-
        /*
         * Create the ARM mapping, used by the ARM DMA mapping core to allocate
         * VAs. This will allocate a corresponding IOMMU domain.
index 7e6f6638433bbe6ecce2015be7424ecd5abffe56..2f2ae609c5488b307c2514cf2bbde9a67edc29d2 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/clk-provider.h>
 #include <linux/device.h>
 #include <linux/io.h>
-#include <linux/iommu.h>
 #include <linux/platform_device.h>
 #include <linux/wait.h>
 
index 2f0a0d24893651c97f7a469a1b92a3a4a653ec93..77d5d4cbed0a06fcb316c0fb2d6c59a470c3f585 100644 (file)
@@ -833,11 +833,11 @@ MODULE_LICENSE("GPL");
 module_param(type, int, 0444);
 MODULE_PARM_DESC(type, "Hardware type (0 = home-brew, 1 = IRdeo, 2 = IRdeo Remote, 3 = AnimaX, 4 = IgorPlug");
 
-module_param(io, int, 0444);
+module_param_hw(io, int, ioport, 0444);
 MODULE_PARM_DESC(io, "I/O address base (0x3f8 or 0x2f8)");
 
 /* some architectures (e.g. intel xscale) have memory mapped registers */
-module_param(iommap, ulong, 0444);
+module_param_hw(iommap, ulong, other, 0444);
 MODULE_PARM_DESC(iommap, "physical base for memory mapped I/O (0 = no memory mapped io)");
 
 /*
@@ -845,13 +845,13 @@ MODULE_PARM_DESC(iommap, "physical base for memory mapped I/O (0 = no memory map
  * on 32bit word boundaries.
  * See linux-kernel/drivers/tty/serial/8250/8250.c serial_in()/out()
  */
-module_param(ioshift, int, 0444);
+module_param_hw(ioshift, int, other, 0444);
 MODULE_PARM_DESC(ioshift, "shift I/O register offset (0 = no shift)");
 
-module_param(irq, int, 0444);
+module_param_hw(irq, int, irq, 0444);
 MODULE_PARM_DESC(irq, "Interrupt (4 or 3)");
 
-module_param(share_irq, bool, 0444);
+module_param_hw(share_irq, bool, other, 0444);
 MODULE_PARM_DESC(share_irq, "Share interrupts (0 = off, 1 = on)");
 
 module_param(sense, int, 0444);
index 3ecc429297a0ffed4a86ee6d478647c69e8212e1..ffc3502580413789d9bfe432c1919b022ad21fea 100644 (file)
@@ -116,7 +116,7 @@ config FSL_CORENET_CF
 
 config FSL_IFC
        bool
-       depends on FSL_SOC || ARCH_LAYERSCAPE
+       depends on FSL_SOC || ARCH_LAYERSCAPE || SOC_LS1021A
 
 config JZ4780_NEMC
        bool "Ingenic JZ4780 SoC NEMC driver"
index bf0fe0137dfed2c893001abb8cfe8b83861dae08..6d1b4b707cc287034c0d8fd225c4f7fc18e796ad 100644 (file)
@@ -512,7 +512,7 @@ static void gpmc_cs_show_timings(int cs, const char *desc)
        pr_info("gpmc cs%i access configuration:\n", cs);
        GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1,  4,  4, "time-para-granularity");
        GPMC_GET_RAW(GPMC_CS_CONFIG1,  8,  9, "mux-add-data");
-       GPMC_GET_RAW_MAX(GPMC_CS_CONFIG1, 12, 13,
+       GPMC_GET_RAW_SHIFT_MAX(GPMC_CS_CONFIG1, 12, 13, 1,
                         GPMC_CONFIG1_DEVICESIZE_MAX, "device-width");
        GPMC_GET_RAW(GPMC_CS_CONFIG1, 16, 17, "wait-pin");
        GPMC_GET_RAW_BOOL(GPMC_CS_CONFIG1, 21, 21, "wait-on-write");
index 39d1acb2745263d361306e0aeb9672e6d68ce310..2cba76e6fa3cb0bd8b2148bdd472c44f5abaf0d7 100644 (file)
@@ -490,6 +490,13 @@ config ASPEED_LPC_CTRL
          ioctl()s, the driver also provides a read/write interface to a BMC ram
          region where the host LPC read/write region can be buffered.
 
+config PCI_ENDPOINT_TEST
+       depends on PCI
+       tristate "PCI Endpoint Test driver"
+       ---help---
+           Enable this configuration option to enable the host side test driver
+           for PCI Endpoint.
+
 source "drivers/misc/c2port/Kconfig"
 source "drivers/misc/eeprom/Kconfig"
 source "drivers/misc/cb710/Kconfig"
index 4fb10af2ea1c635bf2096590b9a994500484579c..81ef3e67acc96a6dde7d5a0227760f399bb902ad 100644 (file)
@@ -53,6 +53,7 @@ obj-$(CONFIG_ECHO)            += echo/
 obj-$(CONFIG_VEXPRESS_SYSCFG)  += vexpress-syscfg.o
 obj-$(CONFIG_CXL_BASE)         += cxl/
 obj-$(CONFIG_ASPEED_LPC_CTRL)  += aspeed-lpc-ctrl.o
+obj-$(CONFIG_PCI_ENDPOINT_TEST)        += pci_endpoint_test.o
 
 lkdtm-$(CONFIG_LKDTM)          += lkdtm_core.o
 lkdtm-$(CONFIG_LKDTM)          += lkdtm_bugs.o
index 5484301d57d9f63ed8c56b5fcb49f5ae91de98b8..3dc61ea7dc644abc0f94750895c094787fcd4a99 100644 (file)
@@ -129,8 +129,8 @@ static int __init duramar2150_c2port_init(void)
 
        duramar2150_c2port_dev = c2port_device_register("uc",
                                        &duramar2150_c2port_ops, NULL);
-       if (!duramar2150_c2port_dev) {
-               ret = -ENODEV;
+       if (IS_ERR(duramar2150_c2port_dev)) {
+               ret = PTR_ERR(duramar2150_c2port_dev);
                goto free_region;
        }
 
index acbbe0390be49baadc30dd300ef996273875b0c5..76a1015d57838165750f0bcbfd7df08bb4ca941d 100644 (file)
@@ -59,6 +59,6 @@ module_exit(dummy_irq_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Jiri Kosina");
-module_param(irq, uint, 0444);
+module_param_hw(irq, uint, irq, 0444);
 MODULE_PARM_DESC(irq, "The IRQ to register for");
 MODULE_DESCRIPTION("Dummy IRQ handler driver");
index c2e29d7f0de88838d18cdb52c965dda55e16f774..a341938c7e2c6738027dd4df53cdf4da0f8b6bd1 100644 (file)
@@ -278,7 +278,7 @@ static void vop_del_vqs(struct virtio_device *dev)
 static struct virtqueue *vop_find_vq(struct virtio_device *dev,
                                     unsigned index,
                                     void (*callback)(struct virtqueue *vq),
-                                    const char *name)
+                                    const char *name, bool ctx)
 {
        struct _vop_vdev *vdev = to_vopvdev(dev);
        struct vop_device *vpdev = vdev->vpdev;
@@ -314,6 +314,7 @@ static struct virtqueue *vop_find_vq(struct virtio_device *dev,
                                le16_to_cpu(config.num), MIC_VIRTIO_RING_ALIGN,
                                dev,
                                false,
+                               ctx,
                                (void __force *)va, vop_notify, callback, name);
        if (!vq) {
                err = -ENOMEM;
@@ -374,7 +375,8 @@ unmap:
 static int vop_find_vqs(struct virtio_device *dev, unsigned nvqs,
                        struct virtqueue *vqs[],
                        vq_callback_t *callbacks[],
-                       const char * const names[], struct irq_affinity *desc)
+                       const char * const names[], const bool *ctx,
+                       struct irq_affinity *desc)
 {
        struct _vop_vdev *vdev = to_vopvdev(dev);
        struct vop_device *vpdev = vdev->vpdev;
@@ -388,7 +390,8 @@ static int vop_find_vqs(struct virtio_device *dev, unsigned nvqs,
        for (i = 0; i < nvqs; ++i) {
                dev_dbg(_vop_dev(vdev), "%s: %d: %s\n",
                        __func__, i, names[i]);
-               vqs[i] = vop_find_vq(dev, i, callbacks[i], names[i]);
+               vqs[i] = vop_find_vq(dev, i, callbacks[i], names[i],
+                                    ctx ? ctx[i] : false);
                if (IS_ERR(vqs[i])) {
                        err = PTR_ERR(vqs[i]);
                        goto error;
diff --git a/drivers/misc/pci_endpoint_test.c b/drivers/misc/pci_endpoint_test.c
new file mode 100644 (file)
index 0000000..09c10f4
--- /dev/null
@@ -0,0 +1,534 @@
+/**
+ * Host side test driver to test endpoint functionality
+ *
+ * Copyright (C) 2017 Texas Instruments
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 of
+ * the License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/crc32.h>
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/random.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+
+#include <linux/pci_regs.h>
+
+#include <uapi/linux/pcitest.h>
+
+#define DRV_MODULE_NAME                        "pci-endpoint-test"
+
+#define PCI_ENDPOINT_TEST_MAGIC                0x0
+
+#define PCI_ENDPOINT_TEST_COMMAND      0x4
+#define COMMAND_RAISE_LEGACY_IRQ       BIT(0)
+#define COMMAND_RAISE_MSI_IRQ          BIT(1)
+#define MSI_NUMBER_SHIFT               2
+/* 6 bits for MSI number */
+#define COMMAND_READ                    BIT(8)
+#define COMMAND_WRITE                   BIT(9)
+#define COMMAND_COPY                    BIT(10)
+
+#define PCI_ENDPOINT_TEST_STATUS       0x8
+#define STATUS_READ_SUCCESS             BIT(0)
+#define STATUS_READ_FAIL                BIT(1)
+#define STATUS_WRITE_SUCCESS            BIT(2)
+#define STATUS_WRITE_FAIL               BIT(3)
+#define STATUS_COPY_SUCCESS             BIT(4)
+#define STATUS_COPY_FAIL                BIT(5)
+#define STATUS_IRQ_RAISED               BIT(6)
+#define STATUS_SRC_ADDR_INVALID         BIT(7)
+#define STATUS_DST_ADDR_INVALID         BIT(8)
+
+#define PCI_ENDPOINT_TEST_LOWER_SRC_ADDR       0xc
+#define PCI_ENDPOINT_TEST_UPPER_SRC_ADDR       0x10
+
+#define PCI_ENDPOINT_TEST_LOWER_DST_ADDR       0x14
+#define PCI_ENDPOINT_TEST_UPPER_DST_ADDR       0x18
+
+#define PCI_ENDPOINT_TEST_SIZE         0x1c
+#define PCI_ENDPOINT_TEST_CHECKSUM     0x20
+
+static DEFINE_IDA(pci_endpoint_test_ida);
+
+#define to_endpoint_test(priv) container_of((priv), struct pci_endpoint_test, \
+                                           miscdev)
+enum pci_barno {
+       BAR_0,
+       BAR_1,
+       BAR_2,
+       BAR_3,
+       BAR_4,
+       BAR_5,
+};
+
+struct pci_endpoint_test {
+       struct pci_dev  *pdev;
+       void __iomem    *base;
+       void __iomem    *bar[6];
+       struct completion irq_raised;
+       int             last_irq;
+       /* mutex to protect the ioctls */
+       struct mutex    mutex;
+       struct miscdevice miscdev;
+};
+
+static int bar_size[] = { 4, 512, 1024, 16384, 131072, 1048576 };
+
+static inline u32 pci_endpoint_test_readl(struct pci_endpoint_test *test,
+                                         u32 offset)
+{
+       return readl(test->base + offset);
+}
+
+static inline void pci_endpoint_test_writel(struct pci_endpoint_test *test,
+                                           u32 offset, u32 value)
+{
+       writel(value, test->base + offset);
+}
+
+static inline u32 pci_endpoint_test_bar_readl(struct pci_endpoint_test *test,
+                                             int bar, int offset)
+{
+       return readl(test->bar[bar] + offset);
+}
+
+static inline void pci_endpoint_test_bar_writel(struct pci_endpoint_test *test,
+                                               int bar, u32 offset, u32 value)
+{
+       writel(value, test->bar[bar] + offset);
+}
+
+static irqreturn_t pci_endpoint_test_irqhandler(int irq, void *dev_id)
+{
+       struct pci_endpoint_test *test = dev_id;
+       u32 reg;
+
+       reg = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_STATUS);
+       if (reg & STATUS_IRQ_RAISED) {
+               test->last_irq = irq;
+               complete(&test->irq_raised);
+               reg &= ~STATUS_IRQ_RAISED;
+       }
+       pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_STATUS,
+                                reg);
+
+       return IRQ_HANDLED;
+}
+
+static bool pci_endpoint_test_bar(struct pci_endpoint_test *test,
+                                 enum pci_barno barno)
+{
+       int j;
+       u32 val;
+       int size;
+
+       if (!test->bar[barno])
+               return false;
+
+       size = bar_size[barno];
+
+       for (j = 0; j < size; j += 4)
+               pci_endpoint_test_bar_writel(test, barno, j, 0xA0A0A0A0);
+
+       for (j = 0; j < size; j += 4) {
+               val = pci_endpoint_test_bar_readl(test, barno, j);
+               if (val != 0xA0A0A0A0)
+                       return false;
+       }
+
+       return true;
+}
+
+static bool pci_endpoint_test_legacy_irq(struct pci_endpoint_test *test)
+{
+       u32 val;
+
+       pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
+                                COMMAND_RAISE_LEGACY_IRQ);
+       val = wait_for_completion_timeout(&test->irq_raised,
+                                         msecs_to_jiffies(1000));
+       if (!val)
+               return false;
+
+       return true;
+}
+
+static bool pci_endpoint_test_msi_irq(struct pci_endpoint_test *test,
+                                     u8 msi_num)
+{
+       u32 val;
+       struct pci_dev *pdev = test->pdev;
+
+       pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
+                                msi_num << MSI_NUMBER_SHIFT |
+                                COMMAND_RAISE_MSI_IRQ);
+       val = wait_for_completion_timeout(&test->irq_raised,
+                                         msecs_to_jiffies(1000));
+       if (!val)
+               return false;
+
+       if (test->last_irq - pdev->irq == msi_num - 1)
+               return true;
+
+       return false;
+}
+
+static bool pci_endpoint_test_copy(struct pci_endpoint_test *test, size_t size)
+{
+       bool ret = false;
+       void *src_addr;
+       void *dst_addr;
+       dma_addr_t src_phys_addr;
+       dma_addr_t dst_phys_addr;
+       struct pci_dev *pdev = test->pdev;
+       struct device *dev = &pdev->dev;
+       u32 src_crc32;
+       u32 dst_crc32;
+
+       src_addr = dma_alloc_coherent(dev, size, &src_phys_addr, GFP_KERNEL);
+       if (!src_addr) {
+               dev_err(dev, "failed to allocate source buffer\n");
+               ret = false;
+               goto err;
+       }
+
+       pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_SRC_ADDR,
+                                lower_32_bits(src_phys_addr));
+
+       pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_SRC_ADDR,
+                                upper_32_bits(src_phys_addr));
+
+       get_random_bytes(src_addr, size);
+       src_crc32 = crc32_le(~0, src_addr, size);
+
+       dst_addr = dma_alloc_coherent(dev, size, &dst_phys_addr, GFP_KERNEL);
+       if (!dst_addr) {
+               dev_err(dev, "failed to allocate destination address\n");
+               ret = false;
+               goto err_src_addr;
+       }
+
+       pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_DST_ADDR,
+                                lower_32_bits(dst_phys_addr));
+       pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_DST_ADDR,
+                                upper_32_bits(dst_phys_addr));
+
+       pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE,
+                                size);
+
+       pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
+                                1 << MSI_NUMBER_SHIFT | COMMAND_COPY);
+
+       wait_for_completion(&test->irq_raised);
+
+       dst_crc32 = crc32_le(~0, dst_addr, size);
+       if (dst_crc32 == src_crc32)
+               ret = true;
+
+       dma_free_coherent(dev, size, dst_addr, dst_phys_addr);
+
+err_src_addr:
+       dma_free_coherent(dev, size, src_addr, src_phys_addr);
+
+err:
+       return ret;
+}
+
+static bool pci_endpoint_test_write(struct pci_endpoint_test *test, size_t size)
+{
+       bool ret = false;
+       u32 reg;
+       void *addr;
+       dma_addr_t phys_addr;
+       struct pci_dev *pdev = test->pdev;
+       struct device *dev = &pdev->dev;
+       u32 crc32;
+
+       addr = dma_alloc_coherent(dev, size, &phys_addr, GFP_KERNEL);
+       if (!addr) {
+               dev_err(dev, "failed to allocate address\n");
+               ret = false;
+               goto err;
+       }
+
+       get_random_bytes(addr, size);
+
+       crc32 = crc32_le(~0, addr, size);
+       pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_CHECKSUM,
+                                crc32);
+
+       pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_SRC_ADDR,
+                                lower_32_bits(phys_addr));
+       pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_SRC_ADDR,
+                                upper_32_bits(phys_addr));
+
+       pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE, size);
+
+       pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
+                                1 << MSI_NUMBER_SHIFT | COMMAND_READ);
+
+       wait_for_completion(&test->irq_raised);
+
+       reg = pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_STATUS);
+       if (reg & STATUS_READ_SUCCESS)
+               ret = true;
+
+       dma_free_coherent(dev, size, addr, phys_addr);
+
+err:
+       return ret;
+}
+
+static bool pci_endpoint_test_read(struct pci_endpoint_test *test, size_t size)
+{
+       bool ret = false;
+       void *addr;
+       dma_addr_t phys_addr;
+       struct pci_dev *pdev = test->pdev;
+       struct device *dev = &pdev->dev;
+       u32 crc32;
+
+       addr = dma_alloc_coherent(dev, size, &phys_addr, GFP_KERNEL);
+       if (!addr) {
+               dev_err(dev, "failed to allocate destination address\n");
+               ret = false;
+               goto err;
+       }
+
+       pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_LOWER_DST_ADDR,
+                                lower_32_bits(phys_addr));
+       pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_UPPER_DST_ADDR,
+                                upper_32_bits(phys_addr));
+
+       pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_SIZE, size);
+
+       pci_endpoint_test_writel(test, PCI_ENDPOINT_TEST_COMMAND,
+                                1 << MSI_NUMBER_SHIFT | COMMAND_WRITE);
+
+       wait_for_completion(&test->irq_raised);
+
+       crc32 = crc32_le(~0, addr, size);
+       if (crc32 == pci_endpoint_test_readl(test, PCI_ENDPOINT_TEST_CHECKSUM))
+               ret = true;
+
+       dma_free_coherent(dev, size, addr, phys_addr);
+err:
+       return ret;
+}
+
+static long pci_endpoint_test_ioctl(struct file *file, unsigned int cmd,
+                                   unsigned long arg)
+{
+       int ret = -EINVAL;
+       enum pci_barno bar;
+       struct pci_endpoint_test *test = to_endpoint_test(file->private_data);
+
+       mutex_lock(&test->mutex);
+       switch (cmd) {
+       case PCITEST_BAR:
+               bar = arg;
+               if (bar < 0 || bar > 5)
+                       goto ret;
+               ret = pci_endpoint_test_bar(test, bar);
+               break;
+       case PCITEST_LEGACY_IRQ:
+               ret = pci_endpoint_test_legacy_irq(test);
+               break;
+       case PCITEST_MSI:
+               ret = pci_endpoint_test_msi_irq(test, arg);
+               break;
+       case PCITEST_WRITE:
+               ret = pci_endpoint_test_write(test, arg);
+               break;
+       case PCITEST_READ:
+               ret = pci_endpoint_test_read(test, arg);
+               break;
+       case PCITEST_COPY:
+               ret = pci_endpoint_test_copy(test, arg);
+               break;
+       }
+
+ret:
+       mutex_unlock(&test->mutex);
+       return ret;
+}
+
+static const struct file_operations pci_endpoint_test_fops = {
+       .owner = THIS_MODULE,
+       .unlocked_ioctl = pci_endpoint_test_ioctl,
+};
+
+static int pci_endpoint_test_probe(struct pci_dev *pdev,
+                                  const struct pci_device_id *ent)
+{
+       int i;
+       int err;
+       int irq;
+       int id;
+       char name[20];
+       enum pci_barno bar;
+       void __iomem *base;
+       struct device *dev = &pdev->dev;
+       struct pci_endpoint_test *test;
+       struct miscdevice *misc_device;
+
+       if (pci_is_bridge(pdev))
+               return -ENODEV;
+
+       test = devm_kzalloc(dev, sizeof(*test), GFP_KERNEL);
+       if (!test)
+               return -ENOMEM;
+
+       test->pdev = pdev;
+       init_completion(&test->irq_raised);
+       mutex_init(&test->mutex);
+
+       err = pci_enable_device(pdev);
+       if (err) {
+               dev_err(dev, "Cannot enable PCI device\n");
+               return err;
+       }
+
+       err = pci_request_regions(pdev, DRV_MODULE_NAME);
+       if (err) {
+               dev_err(dev, "Cannot obtain PCI resources\n");
+               goto err_disable_pdev;
+       }
+
+       pci_set_master(pdev);
+
+       irq = pci_alloc_irq_vectors(pdev, 1, 32, PCI_IRQ_MSI);
+       if (irq < 0)
+               dev_err(dev, "failed to get MSI interrupts\n");
+
+       err = devm_request_irq(dev, pdev->irq, pci_endpoint_test_irqhandler,
+                              IRQF_SHARED, DRV_MODULE_NAME, test);
+       if (err) {
+               dev_err(dev, "failed to request IRQ %d\n", pdev->irq);
+               goto err_disable_msi;
+       }
+
+       for (i = 1; i < irq; i++) {
+               err = devm_request_irq(dev, pdev->irq + i,
+                                      pci_endpoint_test_irqhandler,
+                                      IRQF_SHARED, DRV_MODULE_NAME, test);
+               if (err)
+                       dev_err(dev, "failed to request IRQ %d for MSI %d\n",
+                               pdev->irq + i, i + 1);
+       }
+
+       for (bar = BAR_0; bar <= BAR_5; bar++) {
+               base = pci_ioremap_bar(pdev, bar);
+               if (!base) {
+                       dev_err(dev, "failed to read BAR%d\n", bar);
+                       WARN_ON(bar == BAR_0);
+               }
+               test->bar[bar] = base;
+       }
+
+       test->base = test->bar[0];
+       if (!test->base) {
+               dev_err(dev, "Cannot perform PCI test without BAR0\n");
+               goto err_iounmap;
+       }
+
+       pci_set_drvdata(pdev, test);
+
+       id = ida_simple_get(&pci_endpoint_test_ida, 0, 0, GFP_KERNEL);
+       if (id < 0) {
+               dev_err(dev, "unable to get id\n");
+               goto err_iounmap;
+       }
+
+       snprintf(name, sizeof(name), DRV_MODULE_NAME ".%d", id);
+       misc_device = &test->miscdev;
+       misc_device->minor = MISC_DYNAMIC_MINOR;
+       misc_device->name = name;
+       misc_device->fops = &pci_endpoint_test_fops,
+
+       err = misc_register(misc_device);
+       if (err) {
+               dev_err(dev, "failed to register device\n");
+               goto err_ida_remove;
+       }
+
+       return 0;
+
+err_ida_remove:
+       ida_simple_remove(&pci_endpoint_test_ida, id);
+
+err_iounmap:
+       for (bar = BAR_0; bar <= BAR_5; bar++) {
+               if (test->bar[bar])
+                       pci_iounmap(pdev, test->bar[bar]);
+       }
+
+err_disable_msi:
+       pci_disable_msi(pdev);
+       pci_release_regions(pdev);
+
+err_disable_pdev:
+       pci_disable_device(pdev);
+
+       return err;
+}
+
+static void pci_endpoint_test_remove(struct pci_dev *pdev)
+{
+       int id;
+       enum pci_barno bar;
+       struct pci_endpoint_test *test = pci_get_drvdata(pdev);
+       struct miscdevice *misc_device = &test->miscdev;
+
+       if (sscanf(misc_device->name, DRV_MODULE_NAME ".%d", &id) != 1)
+               return;
+
+       misc_deregister(&test->miscdev);
+       ida_simple_remove(&pci_endpoint_test_ida, id);
+       for (bar = BAR_0; bar <= BAR_5; bar++) {
+               if (test->bar[bar])
+                       pci_iounmap(pdev, test->bar[bar]);
+       }
+       pci_disable_msi(pdev);
+       pci_release_regions(pdev);
+       pci_disable_device(pdev);
+}
+
+static const struct pci_device_id pci_endpoint_test_tbl[] = {
+       { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_DRA74x) },
+       { PCI_DEVICE(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_DRA72x) },
+       { }
+};
+MODULE_DEVICE_TABLE(pci, pci_endpoint_test_tbl);
+
+static struct pci_driver pci_endpoint_test_driver = {
+       .name           = DRV_MODULE_NAME,
+       .id_table       = pci_endpoint_test_tbl,
+       .probe          = pci_endpoint_test_probe,
+       .remove         = pci_endpoint_test_remove,
+};
+module_pci_driver(pci_endpoint_test_driver);
+
+MODULE_DESCRIPTION("PCI ENDPOINT TEST HOST DRIVER");
+MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
+MODULE_LICENSE("GPL v2");
index ac522417c46296685b5287ed2bddb3bd036ecf11..3d528a13b8fc657d0400aec40a0de36a424aa9db 100644 (file)
 
 #include <linux/device.h>
 #include <linux/genalloc.h>
+#include <linux/mm.h>
 #include <linux/sram.h>
 
-#include <asm/cacheflush.h>
+#include <asm/set_memory.h>
 
 #include "sram.h"
 
index 498c0854305f5a5ac0fa6f5d2b481c479e5714ff..06c4974ee8dd1ee40b328d2bc84ff751480a34c1 100644 (file)
@@ -298,8 +298,11 @@ static void *qp_alloc_queue(u64 size, u32 flags)
        size_t pas_size;
        size_t vas_size;
        size_t queue_size = sizeof(*queue) + sizeof(*queue->kernel_if);
-       const u64 num_pages = DIV_ROUND_UP(size, PAGE_SIZE) + 1;
+       u64 num_pages;
 
+       if (size > SIZE_MAX - PAGE_SIZE)
+               return NULL;
+       num_pages = DIV_ROUND_UP(size, PAGE_SIZE) + 1;
        if (num_pages >
                 (SIZE_MAX - queue_size) /
                 (sizeof(*queue->kernel_if->u.g.pas) +
@@ -624,9 +627,12 @@ static struct vmci_queue *qp_host_alloc_queue(u64 size)
 {
        struct vmci_queue *queue;
        size_t queue_page_size;
-       const u64 num_pages = DIV_ROUND_UP(size, PAGE_SIZE) + 1;
+       u64 num_pages;
        const size_t queue_size = sizeof(*queue) + sizeof(*(queue->kernel_if));
 
+       if (size > SIZE_MAX - PAGE_SIZE)
+               return NULL;
+       num_pages = DIV_ROUND_UP(size, PAGE_SIZE) + 1;
        if (num_pages > (SIZE_MAX - queue_size) /
                 sizeof(*queue->kernel_if->u.h.page))
                return NULL;
index bd04e8bae010c4f8ce9a4714b155ae06fb1ac1c0..e15a9733fcfdd9697269749c4901ed997aa4b0c1 100644 (file)
@@ -2001,11 +2001,11 @@ static void __exit wbsd_drv_exit(void)
 module_init(wbsd_drv_init);
 module_exit(wbsd_drv_exit);
 #ifdef CONFIG_PNP
-module_param_named(nopnp, param_nopnp, uint, 0444);
+module_param_hw_named(nopnp, param_nopnp, uint, other, 0444);
 #endif
-module_param_named(io, param_io, uint, 0444);
-module_param_named(irq, param_irq, uint, 0444);
-module_param_named(dma, param_dma, int, 0444);
+module_param_hw_named(io, param_io, uint, ioport, 0444);
+module_param_hw_named(irq, param_irq, uint, irq, 0444);
+module_param_hw_named(dma, param_dma, int, dma, 0444);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Pierre Ossman <pierre@ossman.eu>");
index 9dca881bb3780e9c2325318ef56f69288c4da076..56aa6b75213d86d0442823e9b4163118231f9f30 100644 (file)
@@ -323,7 +323,8 @@ static void fixup_sst38vf640x_sectorsize(struct mtd_info *mtd)
         * it should report a size of 8KBytes (0x0020*256).
         */
        cfi->cfiq->EraseRegionInfo[0] = 0x002003ff;
-       pr_warning("%s: Bad 38VF640x CFI data; adjusting sector size from 64 to 8KiB\n", mtd->name);
+       pr_warn("%s: Bad 38VF640x CFI data; adjusting sector size from 64 to 8KiB\n",
+               mtd->name);
 }
 
 static void fixup_s29gl064n_sectors(struct mtd_info *mtd)
@@ -333,7 +334,8 @@ static void fixup_s29gl064n_sectors(struct mtd_info *mtd)
 
        if ((cfi->cfiq->EraseRegionInfo[0] & 0xffff) == 0x003f) {
                cfi->cfiq->EraseRegionInfo[0] |= 0x0040;
-               pr_warning("%s: Bad S29GL064N CFI data; adjust from 64 to 128 sectors\n", mtd->name);
+               pr_warn("%s: Bad S29GL064N CFI data; adjust from 64 to 128 sectors\n",
+                       mtd->name);
        }
 }
 
@@ -344,7 +346,8 @@ static void fixup_s29gl032n_sectors(struct mtd_info *mtd)
 
        if ((cfi->cfiq->EraseRegionInfo[1] & 0xffff) == 0x007e) {
                cfi->cfiq->EraseRegionInfo[1] &= ~0x0040;
-               pr_warning("%s: Bad S29GL032N CFI data; adjust from 127 to 63 sectors\n", mtd->name);
+               pr_warn("%s: Bad S29GL032N CFI data; adjust from 127 to 63 sectors\n",
+                       mtd->name);
        }
 }
 
@@ -358,7 +361,8 @@ static void fixup_s29ns512p_sectors(struct mtd_info *mtd)
         * which is not permitted by CFI.
         */
        cfi->cfiq->EraseRegionInfo[0] = 0x020001ff;
-       pr_warning("%s: Bad S29NS512P CFI data; adjust to 512 sectors\n", mtd->name);
+       pr_warn("%s: Bad S29NS512P CFI data; adjust to 512 sectors\n",
+               mtd->name);
 }
 
 /* Used to fix CFI-Tables of chips without Extended Query Tables */
index aef1846b4de24321ca7cc65122d5cb14c1a00b6e..5a09a72ab112fd608802657462bb4ebb8c992aee 100644 (file)
@@ -17,12 +17,10 @@ obj-$(CONFIG_MTD_CK804XROM) += ck804xrom.o
 obj-$(CONFIG_MTD_TSUNAMI)      += tsunami_flash.o
 obj-$(CONFIG_MTD_PXA2XX)       += pxa2xx-flash.o
 obj-$(CONFIG_MTD_PHYSMAP)      += physmap.o
-ifdef CONFIG_MTD_PHYSMAP_OF_VERSATILE
-physmap_of-objs += physmap_of_versatile.o
-endif
-ifdef CONFIG_MTD_PHYSMAP_OF_GEMINI
-physmap_of-objs += physmap_of_gemini.o
-endif
+physmap_of-objs-y              += physmap_of_core.o
+physmap_of-objs-$(CONFIG_MTD_PHYSMAP_OF_VERSATILE) += physmap_of_versatile.o
+physmap_of-objs-$(CONFIG_MTD_PHYSMAP_OF_GEMINI) += physmap_of_gemini.o
+physmap_of-objs                        := $(physmap_of-objs-y)
 obj-$(CONFIG_MTD_PHYSMAP_OF)   += physmap_of.o
 obj-$(CONFIG_MTD_PISMO)                += pismo.o
 obj-$(CONFIG_MTD_PMC_MSP_EVM)   += pmcmsp-flash.o
similarity index 96%
rename from drivers/mtd/maps/physmap_of.c
rename to drivers/mtd/maps/physmap_of_core.c
index 14e8909c99555bb89a84f5c7671b3985b315c883..62fa6836f2186d04bfaf0c3e20e8ff3c505d190c 100644 (file)
@@ -116,32 +116,22 @@ static const char * const part_probe_types_def[] = {
 
 static const char * const *of_get_probes(struct device_node *dp)
 {
-       const char *cp;
-       int cplen;
-       unsigned int l;
-       unsigned int count;
        const char **res;
+       int count;
 
-       cp = of_get_property(dp, "linux,part-probe", &cplen);
-       if (cp == NULL)
+       count = of_property_count_strings(dp, "linux,part-probe");
+       if (count < 0)
                return part_probe_types_def;
 
-       count = 0;
-       for (l = 0; l != cplen; l++)
-               if (cp[l] == 0)
-                       count++;
-
-       res = kzalloc((count + 1)*sizeof(*res), GFP_KERNEL);
+       res = kzalloc((count + 1) * sizeof(*res), GFP_KERNEL);
        if (!res)
                return NULL;
-       count = 0;
-       while (cplen > 0) {
-               res[count] = cp;
-               l = strlen(cp) + 1;
-               cp += l;
-               cplen -= l;
-               count++;
-       }
+
+       count = of_property_read_string_array(dp, "linux,part-probe", res,
+                                             count);
+       if (count < 0)
+               return NULL;
+
        return res;
 }
 
index c40e2c951758ee0bf880159bfda32f35e67c2253..f12879a3d4ff52bc1ce0e0f794bab4d5a689c25f 100644 (file)
@@ -1235,10 +1235,8 @@ static int mtdswap_show(struct seq_file *s, void *data)
 
                if (root->rb_node) {
                        count[i] = d->trees[i].count;
-                       min[i] = rb_entry(rb_first(root), struct swap_eb,
-                                       rb)->erase_count;
-                       max[i] = rb_entry(rb_last(root), struct swap_eb,
-                                       rb)->erase_count;
+                       min[i] = MTDSWAP_ECNT_MIN(root);
+                       max[i] = MTDSWAP_ECNT_MAX(root);
                } else
                        count[i] = 0;
        }
index 6d4d5672d1d8ea0945cdaebcbf06d17f5984017b..c3029528063b8578e79746c51038d643631920b2 100644 (file)
@@ -13,7 +13,6 @@ config MTD_NAND_ECC_SMC
 menuconfig MTD_NAND
        tristate "NAND Device Support"
        depends on MTD
-       select MTD_NAND_IDS
        select MTD_NAND_ECC
        help
          This enables support for accessing all type of NAND flash
@@ -60,17 +59,6 @@ config MTD_NAND_DENALI_DT
          Enable the driver for NAND flash on platforms using a Denali NAND
          controller as a DT device.
 
-config MTD_NAND_DENALI_SCRATCH_REG_ADDR
-        hex "Denali NAND size scratch register address"
-        default "0xFF108018"
-        depends on MTD_NAND_DENALI_PCI
-        help
-          Some platforms place the NAND chip size in a scratch register
-          because (some versions of) the driver aren't able to automatically
-          determine the size of certain chips. Set the address of the
-          scratch register here to enable this feature. On Intel Moorestown
-          boards, the scratch register is at 0xFF108018.
-
 config MTD_NAND_GPIO
        tristate "GPIO assisted NAND Flash driver"
        depends on GPIOLIB || COMPILE_TEST
@@ -109,9 +97,6 @@ config MTD_NAND_OMAP_BCH
 config MTD_NAND_OMAP_BCH_BUILD
        def_tristate MTD_NAND_OMAP2 && MTD_NAND_OMAP_BCH
 
-config MTD_NAND_IDS
-       tristate
-
 config MTD_NAND_RICOH
        tristate "Ricoh xD card reader"
        default n
@@ -321,11 +306,11 @@ config MTD_NAND_CS553X
          If you say "m", the module will be called cs553x_nand.
 
 config MTD_NAND_ATMEL
-       tristate "Support for NAND Flash / SmartMedia on AT91 and AVR32"
-       depends on ARCH_AT91 || AVR32
+       tristate "Support for NAND Flash / SmartMedia on AT91"
+       depends on ARCH_AT91
        help
          Enables support for NAND Flash / Smart Media Card interface
-         on Atmel AT91 and AVR32 processors.
+         on Atmel AT91 processors.
 
 config MTD_NAND_PXA3xx
        tristate "NAND support on PXA3xx and Armada 370/XP"
@@ -443,7 +428,7 @@ config MTD_NAND_FSL_ELBC
 
 config MTD_NAND_FSL_IFC
        tristate "NAND support for Freescale IFC controller"
-       depends on FSL_SOC || ARCH_LAYERSCAPE
+       depends on FSL_SOC || ARCH_LAYERSCAPE || SOC_LS1021A
        select FSL_IFC
        select MEMORY
        help
index 19a66e404d5ba949a16a7ba358df25f033e7a51c..ade5fc4c3819a79ffd575119ed6bbf5607bd8b7f 100644 (file)
@@ -5,7 +5,6 @@
 obj-$(CONFIG_MTD_NAND)                 += nand.o
 obj-$(CONFIG_MTD_NAND_ECC)             += nand_ecc.o
 obj-$(CONFIG_MTD_NAND_BCH)             += nand_bch.o
-obj-$(CONFIG_MTD_NAND_IDS)             += nand_ids.o
 obj-$(CONFIG_MTD_SM_COMMON)            += sm_common.o
 
 obj-$(CONFIG_MTD_NAND_CAFE)            += cafe_nand.o
@@ -25,7 +24,7 @@ obj-$(CONFIG_MTD_NAND_SHARPSL)                += sharpsl.o
 obj-$(CONFIG_MTD_NAND_NANDSIM)         += nandsim.o
 obj-$(CONFIG_MTD_NAND_CS553X)          += cs553x_nand.o
 obj-$(CONFIG_MTD_NAND_NDFC)            += ndfc.o
-obj-$(CONFIG_MTD_NAND_ATMEL)           += atmel_nand.o
+obj-$(CONFIG_MTD_NAND_ATMEL)           += atmel/
 obj-$(CONFIG_MTD_NAND_GPIO)            += gpio.o
 omap2_nand-objs := omap2.o
 obj-$(CONFIG_MTD_NAND_OMAP2)           += omap2_nand.o
@@ -61,4 +60,10 @@ obj-$(CONFIG_MTD_NAND_BRCMNAND)              += brcmnand/
 obj-$(CONFIG_MTD_NAND_QCOM)            += qcom_nandc.o
 obj-$(CONFIG_MTD_NAND_MTK)             += mtk_nand.o mtk_ecc.o
 
-nand-objs := nand_base.o nand_bbt.o nand_timings.o
+nand-objs := nand_base.o nand_bbt.o nand_timings.o nand_ids.o
+nand-objs += nand_amd.o
+nand-objs += nand_hynix.o
+nand-objs += nand_macronix.o
+nand-objs += nand_micron.o
+nand-objs += nand_samsung.o
+nand-objs += nand_toshiba.o
diff --git a/drivers/mtd/nand/atmel/Makefile b/drivers/mtd/nand/atmel/Makefile
new file mode 100644 (file)
index 0000000..288db4f
--- /dev/null
@@ -0,0 +1,4 @@
+obj-$(CONFIG_MTD_NAND_ATMEL)   += atmel-nand-controller.o atmel-pmecc.o
+
+atmel-nand-controller-objs     := nand-controller.o
+atmel-pmecc-objs               := pmecc.o
diff --git a/drivers/mtd/nand/atmel/nand-controller.c b/drivers/mtd/nand/atmel/nand-controller.c
new file mode 100644 (file)
index 0000000..3b24468
--- /dev/null
@@ -0,0 +1,2197 @@
+/*
+ * Copyright 2017 ATMEL
+ * Copyright 2017 Free Electrons
+ *
+ * Author: Boris Brezillon <boris.brezillon@free-electrons.com>
+ *
+ * Derived from the atmel_nand.c driver which contained the following
+ * copyrights:
+ *
+ *   Copyright 2003 Rick Bronson
+ *
+ *   Derived from drivers/mtd/nand/autcpu12.c
+ *     Copyright 2001 Thomas Gleixner (gleixner@autronix.de)
+ *
+ *   Derived from drivers/mtd/spia.c
+ *     Copyright 2000 Steven J. Hill (sjhill@cotw.com)
+ *
+ *
+ *   Add Hardware ECC support for AT91SAM9260 / AT91SAM9263
+ *     Richard Genoud (richard.genoud@gmail.com), Adeneo Copyright 2007
+ *
+ *   Derived from Das U-Boot source code
+ *     (u-boot-1.1.5/board/atmel/at91sam9263ek/nand.c)
+ *     Copyright 2006 ATMEL Rousset, Lacressonniere Nicolas
+ *
+ *   Add Programmable Multibit ECC support for various AT91 SoC
+ *     Copyright 2012 ATMEL, Hong Xu
+ *
+ *   Add Nand Flash Controller support for SAMA5 SoC
+ *     Copyright 2013 ATMEL, Josh Wu (josh.wu@atmel.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * A few words about the naming convention in this file. This convention
+ * applies to structure and function names.
+ *
+ * Prefixes:
+ *
+ * - atmel_nand_: all generic structures/functions
+ * - atmel_smc_nand_: all structures/functions specific to the SMC interface
+ *                   (at91sam9 and avr32 SoCs)
+ * - atmel_hsmc_nand_: all structures/functions specific to the HSMC interface
+ *                    (sama5 SoCs and later)
+ * - atmel_nfc_: all structures/functions used to manipulate the NFC sub-block
+ *              that is available in the HSMC block
+ * - <soc>_nand_: all SoC specific structures/functions
+ */
+
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/genalloc.h>
+#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/atmel-matrix.h>
+#include <linux/module.h>
+#include <linux/mtd/nand.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/iopoll.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/atmel.h>
+#include <linux/regmap.h>
+
+#include "pmecc.h"
+
+#define ATMEL_HSMC_NFC_CFG                     0x0
+#define ATMEL_HSMC_NFC_CFG_SPARESIZE(x)                (((x) / 4) << 24)
+#define ATMEL_HSMC_NFC_CFG_SPARESIZE_MASK      GENMASK(30, 24)
+#define ATMEL_HSMC_NFC_CFG_DTO(cyc, mul)       (((cyc) << 16) | ((mul) << 20))
+#define ATMEL_HSMC_NFC_CFG_DTO_MAX             GENMASK(22, 16)
+#define ATMEL_HSMC_NFC_CFG_RBEDGE              BIT(13)
+#define ATMEL_HSMC_NFC_CFG_FALLING_EDGE                BIT(12)
+#define ATMEL_HSMC_NFC_CFG_RSPARE              BIT(9)
+#define ATMEL_HSMC_NFC_CFG_WSPARE              BIT(8)
+#define ATMEL_HSMC_NFC_CFG_PAGESIZE_MASK       GENMASK(2, 0)
+#define ATMEL_HSMC_NFC_CFG_PAGESIZE(x)         (fls((x) / 512) - 1)
+
+#define ATMEL_HSMC_NFC_CTRL                    0x4
+#define ATMEL_HSMC_NFC_CTRL_EN                 BIT(0)
+#define ATMEL_HSMC_NFC_CTRL_DIS                        BIT(1)
+
+#define ATMEL_HSMC_NFC_SR                      0x8
+#define ATMEL_HSMC_NFC_IER                     0xc
+#define ATMEL_HSMC_NFC_IDR                     0x10
+#define ATMEL_HSMC_NFC_IMR                     0x14
+#define ATMEL_HSMC_NFC_SR_ENABLED              BIT(1)
+#define ATMEL_HSMC_NFC_SR_RB_RISE              BIT(4)
+#define ATMEL_HSMC_NFC_SR_RB_FALL              BIT(5)
+#define ATMEL_HSMC_NFC_SR_BUSY                 BIT(8)
+#define ATMEL_HSMC_NFC_SR_WR                   BIT(11)
+#define ATMEL_HSMC_NFC_SR_CSID                 GENMASK(14, 12)
+#define ATMEL_HSMC_NFC_SR_XFRDONE              BIT(16)
+#define ATMEL_HSMC_NFC_SR_CMDDONE              BIT(17)
+#define ATMEL_HSMC_NFC_SR_DTOE                 BIT(20)
+#define ATMEL_HSMC_NFC_SR_UNDEF                        BIT(21)
+#define ATMEL_HSMC_NFC_SR_AWB                  BIT(22)
+#define ATMEL_HSMC_NFC_SR_NFCASE               BIT(23)
+#define ATMEL_HSMC_NFC_SR_ERRORS               (ATMEL_HSMC_NFC_SR_DTOE | \
+                                                ATMEL_HSMC_NFC_SR_UNDEF | \
+                                                ATMEL_HSMC_NFC_SR_AWB | \
+                                                ATMEL_HSMC_NFC_SR_NFCASE)
+#define ATMEL_HSMC_NFC_SR_RBEDGE(x)            BIT((x) + 24)
+
+#define ATMEL_HSMC_NFC_ADDR                    0x18
+#define ATMEL_HSMC_NFC_BANK                    0x1c
+
+#define ATMEL_NFC_MAX_RB_ID                    7
+
+#define ATMEL_NFC_SRAM_SIZE                    0x2400
+
+#define ATMEL_NFC_CMD(pos, cmd)                        ((cmd) << (((pos) * 8) + 2))
+#define ATMEL_NFC_VCMD2                                BIT(18)
+#define ATMEL_NFC_ACYCLE(naddrs)               ((naddrs) << 19)
+#define ATMEL_NFC_CSID(cs)                     ((cs) << 22)
+#define ATMEL_NFC_DATAEN                       BIT(25)
+#define ATMEL_NFC_NFCWR                                BIT(26)
+
+#define ATMEL_NFC_MAX_ADDR_CYCLES              5
+
+#define ATMEL_NAND_ALE_OFFSET                  BIT(21)
+#define ATMEL_NAND_CLE_OFFSET                  BIT(22)
+
+#define DEFAULT_TIMEOUT_MS                     1000
+#define MIN_DMA_LEN                            128
+
+enum atmel_nand_rb_type {
+       ATMEL_NAND_NO_RB,
+       ATMEL_NAND_NATIVE_RB,
+       ATMEL_NAND_GPIO_RB,
+};
+
+struct atmel_nand_rb {
+       enum atmel_nand_rb_type type;
+       union {
+               struct gpio_desc *gpio;
+               int id;
+       };
+};
+
+struct atmel_nand_cs {
+       int id;
+       struct atmel_nand_rb rb;
+       struct gpio_desc *csgpio;
+       struct {
+               void __iomem *virt;
+               dma_addr_t dma;
+       } io;
+};
+
+struct atmel_nand {
+       struct list_head node;
+       struct device *dev;
+       struct nand_chip base;
+       struct atmel_nand_cs *activecs;
+       struct atmel_pmecc_user *pmecc;
+       struct gpio_desc *cdgpio;
+       int numcs;
+       struct atmel_nand_cs cs[];
+};
+
+static inline struct atmel_nand *to_atmel_nand(struct nand_chip *chip)
+{
+       return container_of(chip, struct atmel_nand, base);
+}
+
+enum atmel_nfc_data_xfer {
+       ATMEL_NFC_NO_DATA,
+       ATMEL_NFC_READ_DATA,
+       ATMEL_NFC_WRITE_DATA,
+};
+
+struct atmel_nfc_op {
+       u8 cs;
+       u8 ncmds;
+       u8 cmds[2];
+       u8 naddrs;
+       u8 addrs[5];
+       enum atmel_nfc_data_xfer data;
+       u32 wait;
+       u32 errors;
+};
+
+struct atmel_nand_controller;
+struct atmel_nand_controller_caps;
+
+struct atmel_nand_controller_ops {
+       int (*probe)(struct platform_device *pdev,
+                    const struct atmel_nand_controller_caps *caps);
+       int (*remove)(struct atmel_nand_controller *nc);
+       void (*nand_init)(struct atmel_nand_controller *nc,
+                         struct atmel_nand *nand);
+       int (*ecc_init)(struct atmel_nand *nand);
+};
+
+struct atmel_nand_controller_caps {
+       bool has_dma;
+       bool legacy_of_bindings;
+       u32 ale_offs;
+       u32 cle_offs;
+       const struct atmel_nand_controller_ops *ops;
+};
+
+struct atmel_nand_controller {
+       struct nand_hw_control base;
+       const struct atmel_nand_controller_caps *caps;
+       struct device *dev;
+       struct regmap *smc;
+       struct dma_chan *dmac;
+       struct atmel_pmecc *pmecc;
+       struct list_head chips;
+       struct clk *mck;
+};
+
+static inline struct atmel_nand_controller *
+to_nand_controller(struct nand_hw_control *ctl)
+{
+       return container_of(ctl, struct atmel_nand_controller, base);
+}
+
+struct atmel_smc_nand_controller {
+       struct atmel_nand_controller base;
+       struct regmap *matrix;
+       unsigned int ebi_csa_offs;
+};
+
+static inline struct atmel_smc_nand_controller *
+to_smc_nand_controller(struct nand_hw_control *ctl)
+{
+       return container_of(to_nand_controller(ctl),
+                           struct atmel_smc_nand_controller, base);
+}
+
+struct atmel_hsmc_nand_controller {
+       struct atmel_nand_controller base;
+       struct {
+               struct gen_pool *pool;
+               void __iomem *virt;
+               dma_addr_t dma;
+       } sram;
+       struct regmap *io;
+       struct atmel_nfc_op op;
+       struct completion complete;
+       int irq;
+
+       /* Only used when instantiating from legacy DT bindings. */
+       struct clk *clk;
+};
+
+static inline struct atmel_hsmc_nand_controller *
+to_hsmc_nand_controller(struct nand_hw_control *ctl)
+{
+       return container_of(to_nand_controller(ctl),
+                           struct atmel_hsmc_nand_controller, base);
+}
+
+static bool atmel_nfc_op_done(struct atmel_nfc_op *op, u32 status)
+{
+       op->errors |= status & ATMEL_HSMC_NFC_SR_ERRORS;
+       op->wait ^= status & op->wait;
+
+       return !op->wait || op->errors;
+}
+
+static irqreturn_t atmel_nfc_interrupt(int irq, void *data)
+{
+       struct atmel_hsmc_nand_controller *nc = data;
+       u32 sr, rcvd;
+       bool done;
+
+       regmap_read(nc->base.smc, ATMEL_HSMC_NFC_SR, &sr);
+
+       rcvd = sr & (nc->op.wait | ATMEL_HSMC_NFC_SR_ERRORS);
+       done = atmel_nfc_op_done(&nc->op, sr);
+
+       if (rcvd)
+               regmap_write(nc->base.smc, ATMEL_HSMC_NFC_IDR, rcvd);
+
+       if (done)
+               complete(&nc->complete);
+
+       return rcvd ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static int atmel_nfc_wait(struct atmel_hsmc_nand_controller *nc, bool poll,
+                         unsigned int timeout_ms)
+{
+       int ret;
+
+       if (!timeout_ms)
+               timeout_ms = DEFAULT_TIMEOUT_MS;
+
+       if (poll) {
+               u32 status;
+
+               ret = regmap_read_poll_timeout(nc->base.smc,
+                                              ATMEL_HSMC_NFC_SR, status,
+                                              atmel_nfc_op_done(&nc->op,
+                                                                status),
+                                              0, timeout_ms * 1000);
+       } else {
+               init_completion(&nc->complete);
+               regmap_write(nc->base.smc, ATMEL_HSMC_NFC_IER,
+                            nc->op.wait | ATMEL_HSMC_NFC_SR_ERRORS);
+               ret = wait_for_completion_timeout(&nc->complete,
+                                               msecs_to_jiffies(timeout_ms));
+               if (!ret)
+                       ret = -ETIMEDOUT;
+               else
+                       ret = 0;
+
+               regmap_write(nc->base.smc, ATMEL_HSMC_NFC_IDR, 0xffffffff);
+       }
+
+       if (nc->op.errors & ATMEL_HSMC_NFC_SR_DTOE) {
+               dev_err(nc->base.dev, "Waiting NAND R/B Timeout\n");
+               ret = -ETIMEDOUT;
+       }
+
+       if (nc->op.errors & ATMEL_HSMC_NFC_SR_UNDEF) {
+               dev_err(nc->base.dev, "Access to an undefined area\n");
+               ret = -EIO;
+       }
+
+       if (nc->op.errors & ATMEL_HSMC_NFC_SR_AWB) {
+               dev_err(nc->base.dev, "Access while busy\n");
+               ret = -EIO;
+       }
+
+       if (nc->op.errors & ATMEL_HSMC_NFC_SR_NFCASE) {
+               dev_err(nc->base.dev, "Wrong access size\n");
+               ret = -EIO;
+       }
+
+       return ret;
+}
+
+static void atmel_nand_dma_transfer_finished(void *data)
+{
+       struct completion *finished = data;
+
+       complete(finished);
+}
+
+static int atmel_nand_dma_transfer(struct atmel_nand_controller *nc,
+                                  void *buf, dma_addr_t dev_dma, size_t len,
+                                  enum dma_data_direction dir)
+{
+       DECLARE_COMPLETION_ONSTACK(finished);
+       dma_addr_t src_dma, dst_dma, buf_dma;
+       struct dma_async_tx_descriptor *tx;
+       dma_cookie_t cookie;
+
+       buf_dma = dma_map_single(nc->dev, buf, len, dir);
+       if (dma_mapping_error(nc->dev, dev_dma)) {
+               dev_err(nc->dev,
+                       "Failed to prepare a buffer for DMA access\n");
+               goto err;
+       }
+
+       if (dir == DMA_FROM_DEVICE) {
+               src_dma = dev_dma;
+               dst_dma = buf_dma;
+       } else {
+               src_dma = buf_dma;
+               dst_dma = dev_dma;
+       }
+
+       tx = dmaengine_prep_dma_memcpy(nc->dmac, dst_dma, src_dma, len,
+                                      DMA_CTRL_ACK | DMA_PREP_INTERRUPT);
+       if (!tx) {
+               dev_err(nc->dev, "Failed to prepare DMA memcpy\n");
+               goto err_unmap;
+       }
+
+       tx->callback = atmel_nand_dma_transfer_finished;
+       tx->callback_param = &finished;
+
+       cookie = dmaengine_submit(tx);
+       if (dma_submit_error(cookie)) {
+               dev_err(nc->dev, "Failed to do DMA tx_submit\n");
+               goto err_unmap;
+       }
+
+       dma_async_issue_pending(nc->dmac);
+       wait_for_completion(&finished);
+
+       return 0;
+
+err_unmap:
+       dma_unmap_single(nc->dev, buf_dma, len, dir);
+
+err:
+       dev_dbg(nc->dev, "Fall back to CPU I/O\n");
+
+       return -EIO;
+}
+
+static u8 atmel_nand_read_byte(struct mtd_info *mtd)
+{
+       struct nand_chip *chip = mtd_to_nand(mtd);
+       struct atmel_nand *nand = to_atmel_nand(chip);
+
+       return ioread8(nand->activecs->io.virt);
+}
+
+static u16 atmel_nand_read_word(struct mtd_info *mtd)
+{
+       struct nand_chip *chip = mtd_to_nand(mtd);
+       struct atmel_nand *nand = to_atmel_nand(chip);
+
+       return ioread16(nand->activecs->io.virt);
+}
+
+static void atmel_nand_write_byte(struct mtd_info *mtd, u8 byte)
+{
+       struct nand_chip *chip = mtd_to_nand(mtd);
+       struct atmel_nand *nand = to_atmel_nand(chip);
+
+       if (chip->options & NAND_BUSWIDTH_16)
+               iowrite16(byte | (byte << 8), nand->activecs->io.virt);
+       else
+               iowrite8(byte, nand->activecs->io.virt);
+}
+
+static void atmel_nand_read_buf(struct mtd_info *mtd, u8 *buf, int len)
+{
+       struct nand_chip *chip = mtd_to_nand(mtd);
+       struct atmel_nand *nand = to_atmel_nand(chip);
+       struct atmel_nand_controller *nc;
+
+       nc = to_nand_controller(chip->controller);
+
+       /*
+        * If the controller supports DMA, the buffer address is DMA-able and
+        * len is long enough to make DMA transfers profitable, let's trigger
+        * a DMA transfer. If it fails, fallback to PIO mode.
+        */
+       if (nc->dmac && virt_addr_valid(buf) &&
+           len >= MIN_DMA_LEN &&
+           !atmel_nand_dma_transfer(nc, buf, nand->activecs->io.dma, len,
+                                    DMA_FROM_DEVICE))
+               return;
+
+       if (chip->options & NAND_BUSWIDTH_16)
+               ioread16_rep(nand->activecs->io.virt, buf, len / 2);
+       else
+               ioread8_rep(nand->activecs->io.virt, buf, len);
+}
+
+static void atmel_nand_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
+{
+       struct nand_chip *chip = mtd_to_nand(mtd);
+       struct atmel_nand *nand = to_atmel_nand(chip);
+       struct atmel_nand_controller *nc;
+
+       nc = to_nand_controller(chip->controller);
+
+       /*
+        * If the controller supports DMA, the buffer address is DMA-able and
+        * len is long enough to make DMA transfers profitable, let's trigger
+        * a DMA transfer. If it fails, fallback to PIO mode.
+        */
+       if (nc->dmac && virt_addr_valid(buf) &&
+           len >= MIN_DMA_LEN &&
+           !atmel_nand_dma_transfer(nc, (void *)buf, nand->activecs->io.dma,
+                                    len, DMA_TO_DEVICE))
+               return;
+
+       if (chip->options & NAND_BUSWIDTH_16)
+               iowrite16_rep(nand->activecs->io.virt, buf, len / 2);
+       else
+               iowrite8_rep(nand->activecs->io.virt, buf, len);
+}
+
+static int atmel_nand_dev_ready(struct mtd_info *mtd)
+{
+       struct nand_chip *chip = mtd_to_nand(mtd);
+       struct atmel_nand *nand = to_atmel_nand(chip);
+
+       return gpiod_get_value(nand->activecs->rb.gpio);
+}
+
+static void atmel_nand_select_chip(struct mtd_info *mtd, int cs)
+{
+       struct nand_chip *chip = mtd_to_nand(mtd);
+       struct atmel_nand *nand = to_atmel_nand(chip);
+
+       if (cs < 0 || cs >= nand->numcs) {
+               nand->activecs = NULL;
+               chip->dev_ready = NULL;
+               return;
+       }
+
+       nand->activecs = &nand->cs[cs];
+
+       if (nand->activecs->rb.type == ATMEL_NAND_GPIO_RB)
+               chip->dev_ready = atmel_nand_dev_ready;
+}
+
+static int atmel_hsmc_nand_dev_ready(struct mtd_info *mtd)
+{
+       struct nand_chip *chip = mtd_to_nand(mtd);
+       struct atmel_nand *nand = to_atmel_nand(chip);
+       struct atmel_hsmc_nand_controller *nc;
+       u32 status;
+
+       nc = to_hsmc_nand_controller(chip->controller);
+
+       regmap_read(nc->base.smc, ATMEL_HSMC_NFC_SR, &status);
+
+       return status & ATMEL_HSMC_NFC_SR_RBEDGE(nand->activecs->rb.id);
+}
+
+static void atmel_hsmc_nand_select_chip(struct mtd_info *mtd, int cs)
+{
+       struct nand_chip *chip = mtd_to_nand(mtd);
+       struct atmel_nand *nand = to_atmel_nand(chip);
+       struct atmel_hsmc_nand_controller *nc;
+
+       nc = to_hsmc_nand_controller(chip->controller);
+
+       atmel_nand_select_chip(mtd, cs);
+
+       if (!nand->activecs) {
+               regmap_write(nc->base.smc, ATMEL_HSMC_NFC_CTRL,
+                            ATMEL_HSMC_NFC_CTRL_DIS);
+               return;
+       }
+
+       if (nand->activecs->rb.type == ATMEL_NAND_NATIVE_RB)
+               chip->dev_ready = atmel_hsmc_nand_dev_ready;
+
+       regmap_update_bits(nc->base.smc, ATMEL_HSMC_NFC_CFG,
+                          ATMEL_HSMC_NFC_CFG_PAGESIZE_MASK |
+                          ATMEL_HSMC_NFC_CFG_SPARESIZE_MASK |
+                          ATMEL_HSMC_NFC_CFG_RSPARE |
+                          ATMEL_HSMC_NFC_CFG_WSPARE,
+                          ATMEL_HSMC_NFC_CFG_PAGESIZE(mtd->writesize) |
+                          ATMEL_HSMC_NFC_CFG_SPARESIZE(mtd->oobsize) |
+                          ATMEL_HSMC_NFC_CFG_RSPARE);
+       regmap_write(nc->base.smc, ATMEL_HSMC_NFC_CTRL,
+                    ATMEL_HSMC_NFC_CTRL_EN);
+}
+
+static int atmel_nfc_exec_op(struct atmel_hsmc_nand_controller *nc, bool poll)
+{
+       u8 *addrs = nc->op.addrs;
+       unsigned int op = 0;
+       u32 addr, val;
+       int i, ret;
+
+       nc->op.wait = ATMEL_HSMC_NFC_SR_CMDDONE;
+
+       for (i = 0; i < nc->op.ncmds; i++)
+               op |= ATMEL_NFC_CMD(i, nc->op.cmds[i]);
+
+       if (nc->op.naddrs == ATMEL_NFC_MAX_ADDR_CYCLES)
+               regmap_write(nc->base.smc, ATMEL_HSMC_NFC_ADDR, *addrs++);
+
+       op |= ATMEL_NFC_CSID(nc->op.cs) |
+             ATMEL_NFC_ACYCLE(nc->op.naddrs);
+
+       if (nc->op.ncmds > 1)
+               op |= ATMEL_NFC_VCMD2;
+
+       addr = addrs[0] | (addrs[1] << 8) | (addrs[2] << 16) |
+              (addrs[3] << 24);
+
+       if (nc->op.data != ATMEL_NFC_NO_DATA) {
+               op |= ATMEL_NFC_DATAEN;
+               nc->op.wait |= ATMEL_HSMC_NFC_SR_XFRDONE;
+
+               if (nc->op.data == ATMEL_NFC_WRITE_DATA)
+                       op |= ATMEL_NFC_NFCWR;
+       }
+
+       /* Clear all flags. */
+       regmap_read(nc->base.smc, ATMEL_HSMC_NFC_SR, &val);
+
+       /* Send the command. */
+       regmap_write(nc->io, op, addr);
+
+       ret = atmel_nfc_wait(nc, poll, 0);
+       if (ret)
+               dev_err(nc->base.dev,
+                       "Failed to send NAND command (err = %d)!",
+                       ret);
+
+       /* Reset the op state. */
+       memset(&nc->op, 0, sizeof(nc->op));
+
+       return ret;
+}
+
+static void atmel_hsmc_nand_cmd_ctrl(struct mtd_info *mtd, int dat,
+                                    unsigned int ctrl)
+{
+       struct nand_chip *chip = mtd_to_nand(mtd);
+       struct atmel_nand *nand = to_atmel_nand(chip);
+       struct atmel_hsmc_nand_controller *nc;
+
+       nc = to_hsmc_nand_controller(chip->controller);
+
+       if (ctrl & NAND_ALE) {
+               if (nc->op.naddrs == ATMEL_NFC_MAX_ADDR_CYCLES)
+                       return;
+
+               nc->op.addrs[nc->op.naddrs++] = dat;
+       } else if (ctrl & NAND_CLE) {
+               if (nc->op.ncmds > 1)
+                       return;
+
+               nc->op.cmds[nc->op.ncmds++] = dat;
+       }
+
+       if (dat == NAND_CMD_NONE) {
+               nc->op.cs = nand->activecs->id;
+               atmel_nfc_exec_op(nc, true);
+       }
+}
+
+static void atmel_nand_cmd_ctrl(struct mtd_info *mtd, int cmd,
+                               unsigned int ctrl)
+{
+       struct nand_chip *chip = mtd_to_nand(mtd);
+       struct atmel_nand *nand = to_atmel_nand(chip);
+       struct atmel_nand_controller *nc;
+
+       nc = to_nand_controller(chip->controller);
+
+       if ((ctrl & NAND_CTRL_CHANGE) && nand->activecs->csgpio) {
+               if (ctrl & NAND_NCE)
+                       gpiod_set_value(nand->activecs->csgpio, 0);
+               else
+                       gpiod_set_value(nand->activecs->csgpio, 1);
+       }
+
+       if (ctrl & NAND_ALE)
+               writeb(cmd, nand->activecs->io.virt + nc->caps->ale_offs);
+       else if (ctrl & NAND_CLE)
+               writeb(cmd, nand->activecs->io.virt + nc->caps->cle_offs);
+}
+
+static void atmel_nfc_copy_to_sram(struct nand_chip *chip, const u8 *buf,
+                                  bool oob_required)
+{
+       struct mtd_info *mtd = nand_to_mtd(chip);
+       struct atmel_hsmc_nand_controller *nc;
+       int ret = -EIO;
+
+       nc = to_hsmc_nand_controller(chip->controller);
+
+       if (nc->base.dmac)
+               ret = atmel_nand_dma_transfer(&nc->base, (void *)buf,
+                                             nc->sram.dma, mtd->writesize,
+                                             DMA_TO_DEVICE);
+
+       /* Falling back to CPU copy. */
+       if (ret)
+               memcpy_toio(nc->sram.virt, buf, mtd->writesize);
+
+       if (oob_required)
+               memcpy_toio(nc->sram.virt + mtd->writesize, chip->oob_poi,
+                           mtd->oobsize);
+}
+
+static void atmel_nfc_copy_from_sram(struct nand_chip *chip, u8 *buf,
+                                    bool oob_required)
+{
+       struct mtd_info *mtd = nand_to_mtd(chip);
+       struct atmel_hsmc_nand_controller *nc;
+       int ret = -EIO;
+
+       nc = to_hsmc_nand_controller(chip->controller);
+
+       if (nc->base.dmac)
+               ret = atmel_nand_dma_transfer(&nc->base, buf, nc->sram.dma,
+                                             mtd->writesize, DMA_FROM_DEVICE);
+
+       /* Falling back to CPU copy. */
+       if (ret)
+               memcpy_fromio(buf, nc->sram.virt, mtd->writesize);
+
+       if (oob_required)
+               memcpy_fromio(chip->oob_poi, nc->sram.virt + mtd->writesize,
+                             mtd->oobsize);
+}
+
+static void atmel_nfc_set_op_addr(struct nand_chip *chip, int page, int column)
+{
+       struct mtd_info *mtd = nand_to_mtd(chip);
+       struct atmel_hsmc_nand_controller *nc;
+
+       nc = to_hsmc_nand_controller(chip->controller);
+
+       if (column >= 0) {
+               nc->op.addrs[nc->op.naddrs++] = column;
+
+               /*
+                * 2 address cycles for the column offset on large page NANDs.
+                */
+               if (mtd->writesize > 512)
+                       nc->op.addrs[nc->op.naddrs++] = column >> 8;
+       }
+
+       if (page >= 0) {
+               nc->op.addrs[nc->op.naddrs++] = page;
+               nc->op.addrs[nc->op.naddrs++] = page >> 8;
+
+               if ((mtd->writesize > 512 && chip->chipsize > SZ_128M) ||
+                   (mtd->writesize <= 512 && chip->chipsize > SZ_32M))
+                       nc->op.addrs[nc->op.naddrs++] = page >> 16;
+       }
+}
+
+static int atmel_nand_pmecc_enable(struct nand_chip *chip, int op, bool raw)
+{
+       struct atmel_nand *nand = to_atmel_nand(chip);
+       struct atmel_nand_controller *nc;
+       int ret;
+
+       nc = to_nand_controller(chip->controller);
+
+       if (raw)
+               return 0;
+
+       ret = atmel_pmecc_enable(nand->pmecc, op);
+       if (ret)
+               dev_err(nc->dev,
+                       "Failed to enable ECC engine (err = %d)\n", ret);
+
+       return ret;
+}
+
+static void atmel_nand_pmecc_disable(struct nand_chip *chip, bool raw)
+{
+       struct atmel_nand *nand = to_atmel_nand(chip);
+
+       if (!raw)
+               atmel_pmecc_disable(nand->pmecc);
+}
+
+static int atmel_nand_pmecc_generate_eccbytes(struct nand_chip *chip, bool raw)
+{
+       struct atmel_nand *nand = to_atmel_nand(chip);
+       struct mtd_info *mtd = nand_to_mtd(chip);
+       struct atmel_nand_controller *nc;
+       struct mtd_oob_region oobregion;
+       void *eccbuf;
+       int ret, i;
+
+       nc = to_nand_controller(chip->controller);
+
+       if (raw)
+               return 0;
+
+       ret = atmel_pmecc_wait_rdy(nand->pmecc);
+       if (ret) {
+               dev_err(nc->dev,
+                       "Failed to transfer NAND page data (err = %d)\n",
+                       ret);
+               return ret;
+       }
+
+       mtd_ooblayout_ecc(mtd, 0, &oobregion);
+       eccbuf = chip->oob_poi + oobregion.offset;
+
+       for (i = 0; i < chip->ecc.steps; i++) {
+               atmel_pmecc_get_generated_eccbytes(nand->pmecc, i,
+                                                  eccbuf);
+               eccbuf += chip->ecc.bytes;
+       }
+
+       return 0;
+}
+
+static int atmel_nand_pmecc_correct_data(struct nand_chip *chip, void *buf,
+                                        bool raw)
+{
+       struct atmel_nand *nand = to_atmel_nand(chip);
+       struct mtd_info *mtd = nand_to_mtd(chip);
+       struct atmel_nand_controller *nc;
+       struct mtd_oob_region oobregion;
+       int ret, i, max_bitflips = 0;
+       void *databuf, *eccbuf;
+
+       nc = to_nand_controller(chip->controller);
+
+       if (raw)
+               return 0;
+
+       ret = atmel_pmecc_wait_rdy(nand->pmecc);
+       if (ret) {
+               dev_err(nc->dev,
+                       "Failed to read NAND page data (err = %d)\n",
+                       ret);
+               return ret;
+       }
+
+       mtd_ooblayout_ecc(mtd, 0, &oobregion);
+       eccbuf = chip->oob_poi + oobregion.offset;
+       databuf = buf;
+
+       for (i = 0; i < chip->ecc.steps; i++) {
+               ret = atmel_pmecc_correct_sector(nand->pmecc, i, databuf,
+                                                eccbuf);
+               if (ret < 0 && !atmel_pmecc_correct_erased_chunks(nand->pmecc))
+                       ret = nand_check_erased_ecc_chunk(databuf,
+                                                         chip->ecc.size,
+                                                         eccbuf,
+                                                         chip->ecc.bytes,
+                                                         NULL, 0,
+                                                         chip->ecc.strength);
+
+               if (ret >= 0)
+                       max_bitflips = max(ret, max_bitflips);
+               else
+                       mtd->ecc_stats.failed++;
+
+               databuf += chip->ecc.size;
+               eccbuf += chip->ecc.bytes;
+       }
+
+       return max_bitflips;
+}
+
+static int atmel_nand_pmecc_write_pg(struct nand_chip *chip, const u8 *buf,
+                                    bool oob_required, int page, bool raw)
+{
+       struct mtd_info *mtd = nand_to_mtd(chip);
+       struct atmel_nand *nand = to_atmel_nand(chip);
+       int ret;
+
+       ret = atmel_nand_pmecc_enable(chip, NAND_ECC_WRITE, raw);
+       if (ret)
+               return ret;
+
+       atmel_nand_write_buf(mtd, buf, mtd->writesize);
+
+       ret = atmel_nand_pmecc_generate_eccbytes(chip, raw);
+       if (ret) {
+               atmel_pmecc_disable(nand->pmecc);
+               return ret;
+       }
+
+       atmel_nand_pmecc_disable(chip, raw);
+
+       atmel_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+       return 0;
+}
+
+static int atmel_nand_pmecc_write_page(struct mtd_info *mtd,
+                                      struct nand_chip *chip, const u8 *buf,
+                                      int oob_required, int page)
+{
+       return atmel_nand_pmecc_write_pg(chip, buf, oob_required, page, false);
+}
+
+static int atmel_nand_pmecc_write_page_raw(struct mtd_info *mtd,
+                                          struct nand_chip *chip,
+                                          const u8 *buf, int oob_required,
+                                          int page)
+{
+       return atmel_nand_pmecc_write_pg(chip, buf, oob_required, page, true);
+}
+
+static int atmel_nand_pmecc_read_pg(struct nand_chip *chip, u8 *buf,
+                                   bool oob_required, int page, bool raw)
+{
+       struct mtd_info *mtd = nand_to_mtd(chip);
+       int ret;
+
+       ret = atmel_nand_pmecc_enable(chip, NAND_ECC_READ, raw);
+       if (ret)
+               return ret;
+
+       atmel_nand_read_buf(mtd, buf, mtd->writesize);
+       atmel_nand_read_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+       ret = atmel_nand_pmecc_correct_data(chip, buf, raw);
+
+       atmel_nand_pmecc_disable(chip, raw);
+
+       return ret;
+}
+
+static int atmel_nand_pmecc_read_page(struct mtd_info *mtd,
+                                     struct nand_chip *chip, u8 *buf,
+                                     int oob_required, int page)
+{
+       return atmel_nand_pmecc_read_pg(chip, buf, oob_required, page, false);
+}
+
+static int atmel_nand_pmecc_read_page_raw(struct mtd_info *mtd,
+                                         struct nand_chip *chip, u8 *buf,
+                                         int oob_required, int page)
+{
+       return atmel_nand_pmecc_read_pg(chip, buf, oob_required, page, true);
+}
+
+static int atmel_hsmc_nand_pmecc_write_pg(struct nand_chip *chip,
+                                         const u8 *buf, bool oob_required,
+                                         int page, bool raw)
+{
+       struct mtd_info *mtd = nand_to_mtd(chip);
+       struct atmel_nand *nand = to_atmel_nand(chip);
+       struct atmel_hsmc_nand_controller *nc;
+       int ret;
+
+       nc = to_hsmc_nand_controller(chip->controller);
+
+       atmel_nfc_copy_to_sram(chip, buf, false);
+
+       nc->op.cmds[0] = NAND_CMD_SEQIN;
+       nc->op.ncmds = 1;
+       atmel_nfc_set_op_addr(chip, page, 0x0);
+       nc->op.cs = nand->activecs->id;
+       nc->op.data = ATMEL_NFC_WRITE_DATA;
+
+       ret = atmel_nand_pmecc_enable(chip, NAND_ECC_WRITE, raw);
+       if (ret)
+               return ret;
+
+       ret = atmel_nfc_exec_op(nc, false);
+       if (ret) {
+               atmel_nand_pmecc_disable(chip, raw);
+               dev_err(nc->base.dev,
+                       "Failed to transfer NAND page data (err = %d)\n",
+                       ret);
+               return ret;
+       }
+
+       ret = atmel_nand_pmecc_generate_eccbytes(chip, raw);
+
+       atmel_nand_pmecc_disable(chip, raw);
+
+       if (ret)
+               return ret;
+
+       atmel_nand_write_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+       nc->op.cmds[0] = NAND_CMD_PAGEPROG;
+       nc->op.ncmds = 1;
+       nc->op.cs = nand->activecs->id;
+       ret = atmel_nfc_exec_op(nc, false);
+       if (ret)
+               dev_err(nc->base.dev, "Failed to program NAND page (err = %d)\n",
+                       ret);
+
+       return ret;
+}
+
+static int atmel_hsmc_nand_pmecc_write_page(struct mtd_info *mtd,
+                                           struct nand_chip *chip,
+                                           const u8 *buf, int oob_required,
+                                           int page)
+{
+       return atmel_hsmc_nand_pmecc_write_pg(chip, buf, oob_required, page,
+                                             false);
+}
+
+static int atmel_hsmc_nand_pmecc_write_page_raw(struct mtd_info *mtd,
+                                               struct nand_chip *chip,
+                                               const u8 *buf,
+                                               int oob_required, int page)
+{
+       return atmel_hsmc_nand_pmecc_write_pg(chip, buf, oob_required, page,
+                                             true);
+}
+
+static int atmel_hsmc_nand_pmecc_read_pg(struct nand_chip *chip, u8 *buf,
+                                        bool oob_required, int page,
+                                        bool raw)
+{
+       struct mtd_info *mtd = nand_to_mtd(chip);
+       struct atmel_nand *nand = to_atmel_nand(chip);
+       struct atmel_hsmc_nand_controller *nc;
+       int ret;
+
+       nc = to_hsmc_nand_controller(chip->controller);
+
+       /*
+        * Optimized read page accessors only work when the NAND R/B pin is
+        * connected to a native SoC R/B pin. If that's not the case, fallback
+        * to the non-optimized one.
+        */
+       if (nand->activecs->rb.type != ATMEL_NAND_NATIVE_RB) {
+               chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
+
+               return atmel_nand_pmecc_read_pg(chip, buf, oob_required, page,
+                                               raw);
+       }
+
+       nc->op.cmds[nc->op.ncmds++] = NAND_CMD_READ0;
+
+       if (mtd->writesize > 512)
+               nc->op.cmds[nc->op.ncmds++] = NAND_CMD_READSTART;
+
+       atmel_nfc_set_op_addr(chip, page, 0x0);
+       nc->op.cs = nand->activecs->id;
+       nc->op.data = ATMEL_NFC_READ_DATA;
+
+       ret = atmel_nand_pmecc_enable(chip, NAND_ECC_READ, raw);
+       if (ret)
+               return ret;
+
+       ret = atmel_nfc_exec_op(nc, false);
+       if (ret) {
+               atmel_nand_pmecc_disable(chip, raw);
+               dev_err(nc->base.dev,
+                       "Failed to load NAND page data (err = %d)\n",
+                       ret);
+               return ret;
+       }
+
+       atmel_nfc_copy_from_sram(chip, buf, true);
+
+       ret = atmel_nand_pmecc_correct_data(chip, buf, raw);
+
+       atmel_nand_pmecc_disable(chip, raw);
+
+       return ret;
+}
+
+static int atmel_hsmc_nand_pmecc_read_page(struct mtd_info *mtd,
+                                          struct nand_chip *chip, u8 *buf,
+                                          int oob_required, int page)
+{
+       return atmel_hsmc_nand_pmecc_read_pg(chip, buf, oob_required, page,
+                                            false);
+}
+
+static int atmel_hsmc_nand_pmecc_read_page_raw(struct mtd_info *mtd,
+                                              struct nand_chip *chip,
+                                              u8 *buf, int oob_required,
+                                              int page)
+{
+       return atmel_hsmc_nand_pmecc_read_pg(chip, buf, oob_required, page,
+                                            true);
+}
+
+static int atmel_nand_pmecc_init(struct nand_chip *chip)
+{
+       struct mtd_info *mtd = nand_to_mtd(chip);
+       struct atmel_nand *nand = to_atmel_nand(chip);
+       struct atmel_nand_controller *nc;
+       struct atmel_pmecc_user_req req;
+
+       nc = to_nand_controller(chip->controller);
+
+       if (!nc->pmecc) {
+               dev_err(nc->dev, "HW ECC not supported\n");
+               return -ENOTSUPP;
+       }
+
+       if (nc->caps->legacy_of_bindings) {
+               u32 val;
+
+               if (!of_property_read_u32(nc->dev->of_node, "atmel,pmecc-cap",
+                                         &val))
+                       chip->ecc.strength = val;
+
+               if (!of_property_read_u32(nc->dev->of_node,
+                                         "atmel,pmecc-sector-size",
+                                         &val))
+                       chip->ecc.size = val;
+       }
+
+       if (chip->ecc.options & NAND_ECC_MAXIMIZE)
+               req.ecc.strength = ATMEL_PMECC_MAXIMIZE_ECC_STRENGTH;
+       else if (chip->ecc.strength)
+               req.ecc.strength = chip->ecc.strength;
+       else if (chip->ecc_strength_ds)
+               req.ecc.strength = chip->ecc_strength_ds;
+       else
+               req.ecc.strength = ATMEL_PMECC_MAXIMIZE_ECC_STRENGTH;
+
+       if (chip->ecc.size)
+               req.ecc.sectorsize = chip->ecc.size;
+       else if (chip->ecc_step_ds)
+               req.ecc.sectorsize = chip->ecc_step_ds;
+       else
+               req.ecc.sectorsize = ATMEL_PMECC_SECTOR_SIZE_AUTO;
+
+       req.pagesize = mtd->writesize;
+       req.oobsize = mtd->oobsize;
+
+       if (mtd->writesize <= 512) {
+               req.ecc.bytes = 4;
+               req.ecc.ooboffset = 0;
+       } else {
+               req.ecc.bytes = mtd->oobsize - 2;
+               req.ecc.ooboffset = ATMEL_PMECC_OOBOFFSET_AUTO;
+       }
+
+       nand->pmecc = atmel_pmecc_create_user(nc->pmecc, &req);
+       if (IS_ERR(nand->pmecc))
+               return PTR_ERR(nand->pmecc);
+
+       chip->ecc.algo = NAND_ECC_BCH;
+       chip->ecc.size = req.ecc.sectorsize;
+       chip->ecc.bytes = req.ecc.bytes / req.ecc.nsectors;
+       chip->ecc.strength = req.ecc.strength;
+
+       chip->options |= NAND_NO_SUBPAGE_WRITE;
+
+       mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
+
+       return 0;
+}
+
+static int atmel_nand_ecc_init(struct atmel_nand *nand)
+{
+       struct nand_chip *chip = &nand->base;
+       struct atmel_nand_controller *nc;
+       int ret;
+
+       nc = to_nand_controller(chip->controller);
+
+       switch (chip->ecc.mode) {
+       case NAND_ECC_NONE:
+       case NAND_ECC_SOFT:
+               /*
+                * Nothing to do, the core will initialize everything for us.
+                */
+               break;
+
+       case NAND_ECC_HW:
+               ret = atmel_nand_pmecc_init(chip);
+               if (ret)
+                       return ret;
+
+               chip->ecc.read_page = atmel_nand_pmecc_read_page;
+               chip->ecc.write_page = atmel_nand_pmecc_write_page;
+               chip->ecc.read_page_raw = atmel_nand_pmecc_read_page_raw;
+               chip->ecc.write_page_raw = atmel_nand_pmecc_write_page_raw;
+               break;
+
+       default:
+               /* Other modes are not supported. */
+               dev_err(nc->dev, "Unsupported ECC mode: %d\n",
+                       chip->ecc.mode);
+               return -ENOTSUPP;
+       }
+
+       return 0;
+}
+
+static int atmel_hsmc_nand_ecc_init(struct atmel_nand *nand)
+{
+       struct nand_chip *chip = &nand->base;
+       int ret;
+
+       ret = atmel_nand_ecc_init(nand);
+       if (ret)
+               return ret;
+
+       if (chip->ecc.mode != NAND_ECC_HW)
+               return 0;
+
+       /* Adjust the ECC operations for the HSMC IP. */
+       chip->ecc.read_page = atmel_hsmc_nand_pmecc_read_page;
+       chip->ecc.write_page = atmel_hsmc_nand_pmecc_write_page;
+       chip->ecc.read_page_raw = atmel_hsmc_nand_pmecc_read_page_raw;
+       chip->ecc.write_page_raw = atmel_hsmc_nand_pmecc_write_page_raw;
+       chip->ecc.options |= NAND_ECC_CUSTOM_PAGE_ACCESS;
+
+       return 0;
+}
+
+static void atmel_nand_init(struct atmel_nand_controller *nc,
+                           struct atmel_nand *nand)
+{
+       struct nand_chip *chip = &nand->base;
+       struct mtd_info *mtd = nand_to_mtd(chip);
+
+       mtd->dev.parent = nc->dev;
+       nand->base.controller = &nc->base;
+
+       chip->cmd_ctrl = atmel_nand_cmd_ctrl;
+       chip->read_byte = atmel_nand_read_byte;
+       chip->read_word = atmel_nand_read_word;
+       chip->write_byte = atmel_nand_write_byte;
+       chip->read_buf = atmel_nand_read_buf;
+       chip->write_buf = atmel_nand_write_buf;
+       chip->select_chip = atmel_nand_select_chip;
+
+       /* Some NANDs require a longer delay than the default one (20us). */
+       chip->chip_delay = 40;
+
+       /*
+        * Use a bounce buffer when the buffer passed by the MTD user is not
+        * suitable for DMA.
+        */
+       if (nc->dmac)
+               chip->options |= NAND_USE_BOUNCE_BUFFER;
+
+       /* Default to HW ECC if pmecc is available. */
+       if (nc->pmecc)
+               chip->ecc.mode = NAND_ECC_HW;
+}
+
+static void atmel_smc_nand_init(struct atmel_nand_controller *nc,
+                               struct atmel_nand *nand)
+{
+       struct nand_chip *chip = &nand->base;
+       struct atmel_smc_nand_controller *smc_nc;
+       int i;
+
+       atmel_nand_init(nc, nand);
+
+       smc_nc = to_smc_nand_controller(chip->controller);
+       if (!smc_nc->matrix)
+               return;
+
+       /* Attach the CS to the NAND Flash logic. */
+       for (i = 0; i < nand->numcs; i++)
+               regmap_update_bits(smc_nc->matrix, smc_nc->ebi_csa_offs,
+                                  BIT(nand->cs[i].id), BIT(nand->cs[i].id));
+}
+
+static void atmel_hsmc_nand_init(struct atmel_nand_controller *nc,
+                                struct atmel_nand *nand)
+{
+       struct nand_chip *chip = &nand->base;
+
+       atmel_nand_init(nc, nand);
+
+       /* Overload some methods for the HSMC controller. */
+       chip->cmd_ctrl = atmel_hsmc_nand_cmd_ctrl;
+       chip->select_chip = atmel_hsmc_nand_select_chip;
+}
+
+static int atmel_nand_detect(struct atmel_nand *nand)
+{
+       struct nand_chip *chip = &nand->base;
+       struct mtd_info *mtd = nand_to_mtd(chip);
+       struct atmel_nand_controller *nc;
+       int ret;
+
+       nc = to_nand_controller(chip->controller);
+
+       ret = nand_scan_ident(mtd, nand->numcs, NULL);
+       if (ret)
+               dev_err(nc->dev, "nand_scan_ident() failed: %d\n", ret);
+
+       return ret;
+}
+
+static int atmel_nand_unregister(struct atmel_nand *nand)
+{
+       struct nand_chip *chip = &nand->base;
+       struct mtd_info *mtd = nand_to_mtd(chip);
+       int ret;
+
+       ret = mtd_device_unregister(mtd);
+       if (ret)
+               return ret;
+
+       nand_cleanup(chip);
+       list_del(&nand->node);
+
+       return 0;
+}
+
+static int atmel_nand_register(struct atmel_nand *nand)
+{
+       struct nand_chip *chip = &nand->base;
+       struct mtd_info *mtd = nand_to_mtd(chip);
+       struct atmel_nand_controller *nc;
+       int ret;
+
+       nc = to_nand_controller(chip->controller);
+
+       if (nc->caps->legacy_of_bindings || !nc->dev->of_node) {
+               /*
+                * We keep the MTD name unchanged to avoid breaking platforms
+                * where the MTD cmdline parser is used and the bootloader
+                * has not been updated to use the new naming scheme.
+                */
+               mtd->name = "atmel_nand";
+       } else if (!mtd->name) {
+               /*
+                * If the new bindings are used and the bootloader has not been
+                * updated to pass a new mtdparts parameter on the cmdline, you
+                * should define the following property in your nand node:
+                *
+                *      label = "atmel_nand";
+                *
+                * This way, mtd->name will be set by the core when
+                * nand_set_flash_node() is called.
+                */
+               mtd->name = devm_kasprintf(nc->dev, GFP_KERNEL,
+                                          "%s:nand.%d", dev_name(nc->dev),
+                                          nand->cs[0].id);
+               if (!mtd->name) {
+                       dev_err(nc->dev, "Failed to allocate mtd->name\n");
+                       return -ENOMEM;
+               }
+       }
+
+       ret = nand_scan_tail(mtd);
+       if (ret) {
+               dev_err(nc->dev, "nand_scan_tail() failed: %d\n", ret);
+               return ret;
+       }
+
+       ret = mtd_device_register(mtd, NULL, 0);
+       if (ret) {
+               dev_err(nc->dev, "Failed to register mtd device: %d\n", ret);
+               nand_cleanup(chip);
+               return ret;
+       }
+
+       list_add_tail(&nand->node, &nc->chips);
+
+       return 0;
+}
+
+static struct atmel_nand *atmel_nand_create(struct atmel_nand_controller *nc,
+                                           struct device_node *np,
+                                           int reg_cells)
+{
+       struct atmel_nand *nand;
+       struct gpio_desc *gpio;
+       int numcs, ret, i;
+
+       numcs = of_property_count_elems_of_size(np, "reg",
+                                               reg_cells * sizeof(u32));
+       if (numcs < 1) {
+               dev_err(nc->dev, "Missing or invalid reg property\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       nand = devm_kzalloc(nc->dev,
+                           sizeof(*nand) + (numcs * sizeof(*nand->cs)),
+                           GFP_KERNEL);
+       if (!nand) {
+               dev_err(nc->dev, "Failed to allocate NAND object\n");
+               return ERR_PTR(-ENOMEM);
+       }
+
+       nand->numcs = numcs;
+
+       gpio = devm_fwnode_get_index_gpiod_from_child(nc->dev, "det", 0,
+                                                     &np->fwnode, GPIOD_IN,
+                                                     "nand-det");
+       if (IS_ERR(gpio) && PTR_ERR(gpio) != -ENOENT) {
+               dev_err(nc->dev,
+                       "Failed to get detect gpio (err = %ld)\n",
+                       PTR_ERR(gpio));
+               return ERR_CAST(gpio);
+       }
+
+       if (!IS_ERR(gpio))
+               nand->cdgpio = gpio;
+
+       for (i = 0; i < numcs; i++) {
+               struct resource res;
+               u32 val;
+
+               ret = of_address_to_resource(np, 0, &res);
+               if (ret) {
+                       dev_err(nc->dev, "Invalid reg property (err = %d)\n",
+                               ret);
+                       return ERR_PTR(ret);
+               }
+
+               ret = of_property_read_u32_index(np, "reg", i * reg_cells,
+                                                &val);
+               if (ret) {
+                       dev_err(nc->dev, "Invalid reg property (err = %d)\n",
+                               ret);
+                       return ERR_PTR(ret);
+               }
+
+               nand->cs[i].id = val;
+
+               nand->cs[i].io.dma = res.start;
+               nand->cs[i].io.virt = devm_ioremap_resource(nc->dev, &res);
+               if (IS_ERR(nand->cs[i].io.virt))
+                       return ERR_CAST(nand->cs[i].io.virt);
+
+               if (!of_property_read_u32(np, "atmel,rb", &val)) {
+                       if (val > ATMEL_NFC_MAX_RB_ID)
+                               return ERR_PTR(-EINVAL);
+
+                       nand->cs[i].rb.type = ATMEL_NAND_NATIVE_RB;
+                       nand->cs[i].rb.id = val;
+               } else {
+                       gpio = devm_fwnode_get_index_gpiod_from_child(nc->dev,
+                                                       "rb", i, &np->fwnode,
+                                                       GPIOD_IN, "nand-rb");
+                       if (IS_ERR(gpio) && PTR_ERR(gpio) != -ENOENT) {
+                               dev_err(nc->dev,
+                                       "Failed to get R/B gpio (err = %ld)\n",
+                                       PTR_ERR(gpio));
+                               return ERR_CAST(gpio);
+                       }
+
+                       if (!IS_ERR(gpio)) {
+                               nand->cs[i].rb.type = ATMEL_NAND_GPIO_RB;
+                               nand->cs[i].rb.gpio = gpio;
+                       }
+               }
+
+               gpio = devm_fwnode_get_index_gpiod_from_child(nc->dev, "cs",
+                                                             i, &np->fwnode,
+                                                             GPIOD_OUT_HIGH,
+                                                             "nand-cs");
+               if (IS_ERR(gpio) && PTR_ERR(gpio) != -ENOENT) {
+                       dev_err(nc->dev,
+                               "Failed to get CS gpio (err = %ld)\n",
+                               PTR_ERR(gpio));
+                       return ERR_CAST(gpio);
+               }
+
+               if (!IS_ERR(gpio))
+                       nand->cs[i].csgpio = gpio;
+       }
+
+       nand_set_flash_node(&nand->base, np);
+
+       return nand;
+}
+
+static int
+atmel_nand_controller_add_nand(struct atmel_nand_controller *nc,
+                              struct atmel_nand *nand)
+{
+       int ret;
+
+       /* No card inserted, skip this NAND. */
+       if (nand->cdgpio && gpiod_get_value(nand->cdgpio)) {
+               dev_info(nc->dev, "No SmartMedia card inserted.\n");
+               return 0;
+       }
+
+       nc->caps->ops->nand_init(nc, nand);
+
+       ret = atmel_nand_detect(nand);
+       if (ret)
+               return ret;
+
+       ret = nc->caps->ops->ecc_init(nand);
+       if (ret)
+               return ret;
+
+       return atmel_nand_register(nand);
+}
+
+static int
+atmel_nand_controller_remove_nands(struct atmel_nand_controller *nc)
+{
+       struct atmel_nand *nand, *tmp;
+       int ret;
+
+       list_for_each_entry_safe(nand, tmp, &nc->chips, node) {
+               ret = atmel_nand_unregister(nand);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static int
+atmel_nand_controller_legacy_add_nands(struct atmel_nand_controller *nc)
+{
+       struct device *dev = nc->dev;
+       struct platform_device *pdev = to_platform_device(dev);
+       struct atmel_nand *nand;
+       struct gpio_desc *gpio;
+       struct resource *res;
+
+       /*
+        * Legacy bindings only allow connecting a single NAND with a unique CS
+        * line to the controller.
+        */
+       nand = devm_kzalloc(nc->dev, sizeof(*nand) + sizeof(*nand->cs),
+                           GFP_KERNEL);
+       if (!nand)
+               return -ENOMEM;
+
+       nand->numcs = 1;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       nand->cs[0].io.virt = devm_ioremap_resource(dev, res);
+       if (IS_ERR(nand->cs[0].io.virt))
+               return PTR_ERR(nand->cs[0].io.virt);
+
+       nand->cs[0].io.dma = res->start;
+
+       /*
+        * The old driver was hardcoding the CS id to 3 for all sama5
+        * controllers. Since this id is only meaningful for the sama5
+        * controller we can safely assign this id to 3 no matter the
+        * controller.
+        * If one wants to connect a NAND to a different CS line, he will
+        * have to use the new bindings.
+        */
+       nand->cs[0].id = 3;
+
+       /* R/B GPIO. */
+       gpio = devm_gpiod_get_index_optional(dev, NULL, 0,  GPIOD_IN);
+       if (IS_ERR(gpio)) {
+               dev_err(dev, "Failed to get R/B gpio (err = %ld)\n",
+                       PTR_ERR(gpio));
+               return PTR_ERR(gpio);
+       }
+
+       if (gpio) {
+               nand->cs[0].rb.type = ATMEL_NAND_GPIO_RB;
+               nand->cs[0].rb.gpio = gpio;
+       }
+
+       /* CS GPIO. */
+       gpio = devm_gpiod_get_index_optional(dev, NULL, 1, GPIOD_OUT_HIGH);
+       if (IS_ERR(gpio)) {
+               dev_err(dev, "Failed to get CS gpio (err = %ld)\n",
+                       PTR_ERR(gpio));
+               return PTR_ERR(gpio);
+       }
+
+       nand->cs[0].csgpio = gpio;
+
+       /* Card detect GPIO. */
+       gpio = devm_gpiod_get_index_optional(nc->dev, NULL, 2, GPIOD_IN);
+       if (IS_ERR(gpio)) {
+               dev_err(dev,
+                       "Failed to get detect gpio (err = %ld)\n",
+                       PTR_ERR(gpio));
+               return PTR_ERR(gpio);
+       }
+
+       nand->cdgpio = gpio;
+
+       nand_set_flash_node(&nand->base, nc->dev->of_node);
+
+       return atmel_nand_controller_add_nand(nc, nand);
+}
+
+static int atmel_nand_controller_add_nands(struct atmel_nand_controller *nc)
+{
+       struct device_node *np, *nand_np;
+       struct device *dev = nc->dev;
+       int ret, reg_cells;
+       u32 val;
+
+       /* We do not retrieve the SMC syscon when parsing old DTs. */
+       if (nc->caps->legacy_of_bindings)
+               return atmel_nand_controller_legacy_add_nands(nc);
+
+       np = dev->of_node;
+
+       ret = of_property_read_u32(np, "#address-cells", &val);
+       if (ret) {
+               dev_err(dev, "missing #address-cells property\n");
+               return ret;
+       }
+
+       reg_cells = val;
+
+       ret = of_property_read_u32(np, "#size-cells", &val);
+       if (ret) {
+               dev_err(dev, "missing #address-cells property\n");
+               return ret;
+       }
+
+       reg_cells += val;
+
+       for_each_child_of_node(np, nand_np) {
+               struct atmel_nand *nand;
+
+               nand = atmel_nand_create(nc, nand_np, reg_cells);
+               if (IS_ERR(nand)) {
+                       ret = PTR_ERR(nand);
+                       goto err;
+               }
+
+               ret = atmel_nand_controller_add_nand(nc, nand);
+               if (ret)
+                       goto err;
+       }
+
+       return 0;
+
+err:
+       atmel_nand_controller_remove_nands(nc);
+
+       return ret;
+}
+
+static void atmel_nand_controller_cleanup(struct atmel_nand_controller *nc)
+{
+       if (nc->dmac)
+               dma_release_channel(nc->dmac);
+
+       clk_put(nc->mck);
+}
+
+static const struct of_device_id atmel_matrix_of_ids[] = {
+       {
+               .compatible = "atmel,at91sam9260-matrix",
+               .data = (void *)AT91SAM9260_MATRIX_EBICSA,
+       },
+       {
+               .compatible = "atmel,at91sam9261-matrix",
+               .data = (void *)AT91SAM9261_MATRIX_EBICSA,
+       },
+       {
+               .compatible = "atmel,at91sam9263-matrix",
+               .data = (void *)AT91SAM9263_MATRIX_EBI0CSA,
+       },
+       {
+               .compatible = "atmel,at91sam9rl-matrix",
+               .data = (void *)AT91SAM9RL_MATRIX_EBICSA,
+       },
+       {
+               .compatible = "atmel,at91sam9g45-matrix",
+               .data = (void *)AT91SAM9G45_MATRIX_EBICSA,
+       },
+       {
+               .compatible = "atmel,at91sam9n12-matrix",
+               .data = (void *)AT91SAM9N12_MATRIX_EBICSA,
+       },
+       {
+               .compatible = "atmel,at91sam9x5-matrix",
+               .data = (void *)AT91SAM9X5_MATRIX_EBICSA,
+       },
+       { /* sentinel */ },
+};
+
+static int atmel_nand_controller_init(struct atmel_nand_controller *nc,
+                               struct platform_device *pdev,
+                               const struct atmel_nand_controller_caps *caps)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       int ret;
+
+       nand_hw_control_init(&nc->base);
+       INIT_LIST_HEAD(&nc->chips);
+       nc->dev = dev;
+       nc->caps = caps;
+
+       platform_set_drvdata(pdev, nc);
+
+       nc->pmecc = devm_atmel_pmecc_get(dev);
+       if (IS_ERR(nc->pmecc)) {
+               ret = PTR_ERR(nc->pmecc);
+               if (ret != -EPROBE_DEFER)
+                       dev_err(dev, "Could not get PMECC object (err = %d)\n",
+                               ret);
+               return ret;
+       }
+
+       if (nc->caps->has_dma) {
+               dma_cap_mask_t mask;
+
+               dma_cap_zero(mask);
+               dma_cap_set(DMA_MEMCPY, mask);
+
+               nc->dmac = dma_request_channel(mask, NULL, NULL);
+               if (!nc->dmac)
+                       dev_err(nc->dev, "Failed to request DMA channel\n");
+       }
+
+       /* We do not retrieve the SMC syscon when parsing old DTs. */
+       if (nc->caps->legacy_of_bindings)
+               return 0;
+
+       np = of_parse_phandle(dev->parent->of_node, "atmel,smc", 0);
+       if (!np) {
+               dev_err(dev, "Missing or invalid atmel,smc property\n");
+               return -EINVAL;
+       }
+
+       nc->smc = syscon_node_to_regmap(np);
+       of_node_put(np);
+       if (IS_ERR(nc->smc)) {
+               ret = PTR_ERR(nc->smc);
+               dev_err(dev, "Could not get SMC regmap (err = %d)\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+static int
+atmel_smc_nand_controller_init(struct atmel_smc_nand_controller *nc)
+{
+       struct device *dev = nc->base.dev;
+       const struct of_device_id *match;
+       struct device_node *np;
+       int ret;
+
+       /* We do not retrieve the matrix syscon when parsing old DTs. */
+       if (nc->base.caps->legacy_of_bindings)
+               return 0;
+
+       np = of_parse_phandle(dev->parent->of_node, "atmel,matrix", 0);
+       if (!np)
+               return 0;
+
+       match = of_match_node(atmel_matrix_of_ids, np);
+       if (!match) {
+               of_node_put(np);
+               return 0;
+       }
+
+       nc->matrix = syscon_node_to_regmap(np);
+       of_node_put(np);
+       if (IS_ERR(nc->matrix)) {
+               ret = PTR_ERR(nc->matrix);
+               dev_err(dev, "Could not get Matrix regmap (err = %d)\n", ret);
+               return ret;
+       }
+
+       nc->ebi_csa_offs = (unsigned int)match->data;
+
+       /*
+        * The at91sam9263 has 2 EBIs, if the NAND controller is under EBI1
+        * add 4 to ->ebi_csa_offs.
+        */
+       if (of_device_is_compatible(dev->parent->of_node,
+                                   "atmel,at91sam9263-ebi1"))
+               nc->ebi_csa_offs += 4;
+
+       return 0;
+}
+
+static int
+atmel_hsmc_nand_controller_legacy_init(struct atmel_hsmc_nand_controller *nc)
+{
+       struct regmap_config regmap_conf = {
+               .reg_bits = 32,
+               .val_bits = 32,
+               .reg_stride = 4,
+       };
+
+       struct device *dev = nc->base.dev;
+       struct device_node *nand_np, *nfc_np;
+       void __iomem *iomem;
+       struct resource res;
+       int ret;
+
+       nand_np = dev->of_node;
+       nfc_np = of_find_compatible_node(dev->of_node, NULL,
+                                        "atmel,sama5d3-nfc");
+
+       nc->clk = of_clk_get(nfc_np, 0);
+       if (IS_ERR(nc->clk)) {
+               ret = PTR_ERR(nc->clk);
+               dev_err(dev, "Failed to retrieve HSMC clock (err = %d)\n",
+                       ret);
+               goto out;
+       }
+
+       ret = clk_prepare_enable(nc->clk);
+       if (ret) {
+               dev_err(dev, "Failed to enable the HSMC clock (err = %d)\n",
+                       ret);
+               goto out;
+       }
+
+       nc->irq = of_irq_get(nand_np, 0);
+       if (nc->irq < 0) {
+               ret = nc->irq;
+               if (ret != -EPROBE_DEFER)
+                       dev_err(dev, "Failed to get IRQ number (err = %d)\n",
+                               ret);
+               goto out;
+       }
+
+       ret = of_address_to_resource(nfc_np, 0, &res);
+       if (ret) {
+               dev_err(dev, "Invalid or missing NFC IO resource (err = %d)\n",
+                       ret);
+               goto out;
+       }
+
+       iomem = devm_ioremap_resource(dev, &res);
+       if (IS_ERR(iomem)) {
+               ret = PTR_ERR(iomem);
+               goto out;
+       }
+
+       regmap_conf.name = "nfc-io";
+       regmap_conf.max_register = resource_size(&res) - 4;
+       nc->io = devm_regmap_init_mmio(dev, iomem, &regmap_conf);
+       if (IS_ERR(nc->io)) {
+               ret = PTR_ERR(nc->io);
+               dev_err(dev, "Could not create NFC IO regmap (err = %d)\n",
+                       ret);
+               goto out;
+       }
+
+       ret = of_address_to_resource(nfc_np, 1, &res);
+       if (ret) {
+               dev_err(dev, "Invalid or missing HSMC resource (err = %d)\n",
+                       ret);
+               goto out;
+       }
+
+       iomem = devm_ioremap_resource(dev, &res);
+       if (IS_ERR(iomem)) {
+               ret = PTR_ERR(iomem);
+               goto out;
+       }
+
+       regmap_conf.name = "smc";
+       regmap_conf.max_register = resource_size(&res) - 4;
+       nc->base.smc = devm_regmap_init_mmio(dev, iomem, &regmap_conf);
+       if (IS_ERR(nc->base.smc)) {
+               ret = PTR_ERR(nc->base.smc);
+               dev_err(dev, "Could not create NFC IO regmap (err = %d)\n",
+                       ret);
+               goto out;
+       }
+
+       ret = of_address_to_resource(nfc_np, 2, &res);
+       if (ret) {
+               dev_err(dev, "Invalid or missing SRAM resource (err = %d)\n",
+                       ret);
+               goto out;
+       }
+
+       nc->sram.virt = devm_ioremap_resource(dev, &res);
+       if (IS_ERR(nc->sram.virt)) {
+               ret = PTR_ERR(nc->sram.virt);
+               goto out;
+       }
+
+       nc->sram.dma = res.start;
+
+out:
+       of_node_put(nfc_np);
+
+       return ret;
+}
+
+static int
+atmel_hsmc_nand_controller_init(struct atmel_hsmc_nand_controller *nc)
+{
+       struct device *dev = nc->base.dev;
+       struct device_node *np;
+       int ret;
+
+       np = of_parse_phandle(dev->parent->of_node, "atmel,smc", 0);
+       if (!np) {
+               dev_err(dev, "Missing or invalid atmel,smc property\n");
+               return -EINVAL;
+       }
+
+       nc->irq = of_irq_get(np, 0);
+       of_node_put(np);
+       if (nc->irq < 0) {
+               if (nc->irq != -EPROBE_DEFER)
+                       dev_err(dev, "Failed to get IRQ number (err = %d)\n",
+                               nc->irq);
+               return nc->irq;
+       }
+
+       np = of_parse_phandle(dev->of_node, "atmel,nfc-io", 0);
+       if (!np) {
+               dev_err(dev, "Missing or invalid atmel,nfc-io property\n");
+               return -EINVAL;
+       }
+
+       nc->io = syscon_node_to_regmap(np);
+       of_node_put(np);
+       if (IS_ERR(nc->io)) {
+               ret = PTR_ERR(nc->io);
+               dev_err(dev, "Could not get NFC IO regmap (err = %d)\n", ret);
+               return ret;
+       }
+
+       nc->sram.pool = of_gen_pool_get(nc->base.dev->of_node,
+                                        "atmel,nfc-sram", 0);
+       if (!nc->sram.pool) {
+               dev_err(nc->base.dev, "Missing SRAM\n");
+               return -ENOMEM;
+       }
+
+       nc->sram.virt = gen_pool_dma_alloc(nc->sram.pool,
+                                           ATMEL_NFC_SRAM_SIZE,
+                                           &nc->sram.dma);
+       if (!nc->sram.virt) {
+               dev_err(nc->base.dev,
+                       "Could not allocate memory from the NFC SRAM pool\n");
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+static int
+atmel_hsmc_nand_controller_remove(struct atmel_nand_controller *nc)
+{
+       struct atmel_hsmc_nand_controller *hsmc_nc;
+       int ret;
+
+       ret = atmel_nand_controller_remove_nands(nc);
+       if (ret)
+               return ret;
+
+       hsmc_nc = container_of(nc, struct atmel_hsmc_nand_controller, base);
+       if (hsmc_nc->sram.pool)
+               gen_pool_free(hsmc_nc->sram.pool,
+                             (unsigned long)hsmc_nc->sram.virt,
+                             ATMEL_NFC_SRAM_SIZE);
+
+       if (hsmc_nc->clk) {
+               clk_disable_unprepare(hsmc_nc->clk);
+               clk_put(hsmc_nc->clk);
+       }
+
+       atmel_nand_controller_cleanup(nc);
+
+       return 0;
+}
+
+static int atmel_hsmc_nand_controller_probe(struct platform_device *pdev,
+                               const struct atmel_nand_controller_caps *caps)
+{
+       struct device *dev = &pdev->dev;
+       struct atmel_hsmc_nand_controller *nc;
+       int ret;
+
+       nc = devm_kzalloc(dev, sizeof(*nc), GFP_KERNEL);
+       if (!nc)
+               return -ENOMEM;
+
+       ret = atmel_nand_controller_init(&nc->base, pdev, caps);
+       if (ret)
+               return ret;
+
+       if (caps->legacy_of_bindings)
+               ret = atmel_hsmc_nand_controller_legacy_init(nc);
+       else
+               ret = atmel_hsmc_nand_controller_init(nc);
+
+       if (ret)
+               return ret;
+
+       /* Make sure all irqs are masked before registering our IRQ handler. */
+       regmap_write(nc->base.smc, ATMEL_HSMC_NFC_IDR, 0xffffffff);
+       ret = devm_request_irq(dev, nc->irq, atmel_nfc_interrupt,
+                              IRQF_SHARED, "nfc", nc);
+       if (ret) {
+               dev_err(dev,
+                       "Could not get register NFC interrupt handler (err = %d)\n",
+                       ret);
+               goto err;
+       }
+
+       /* Initial NFC configuration. */
+       regmap_write(nc->base.smc, ATMEL_HSMC_NFC_CFG,
+                    ATMEL_HSMC_NFC_CFG_DTO_MAX);
+
+       ret = atmel_nand_controller_add_nands(&nc->base);
+       if (ret)
+               goto err;
+
+       return 0;
+
+err:
+       atmel_hsmc_nand_controller_remove(&nc->base);
+
+       return ret;
+}
+
+static const struct atmel_nand_controller_ops atmel_hsmc_nc_ops = {
+       .probe = atmel_hsmc_nand_controller_probe,
+       .remove = atmel_hsmc_nand_controller_remove,
+       .ecc_init = atmel_hsmc_nand_ecc_init,
+       .nand_init = atmel_hsmc_nand_init,
+};
+
+static const struct atmel_nand_controller_caps atmel_sama5_nc_caps = {
+       .has_dma = true,
+       .ale_offs = BIT(21),
+       .cle_offs = BIT(22),
+       .ops = &atmel_hsmc_nc_ops,
+};
+
+/* Only used to parse old bindings. */
+static const struct atmel_nand_controller_caps atmel_sama5_nand_caps = {
+       .has_dma = true,
+       .ale_offs = BIT(21),
+       .cle_offs = BIT(22),
+       .ops = &atmel_hsmc_nc_ops,
+       .legacy_of_bindings = true,
+};
+
+static int atmel_smc_nand_controller_probe(struct platform_device *pdev,
+                               const struct atmel_nand_controller_caps *caps)
+{
+       struct device *dev = &pdev->dev;
+       struct atmel_smc_nand_controller *nc;
+       int ret;
+
+       nc = devm_kzalloc(dev, sizeof(*nc), GFP_KERNEL);
+       if (!nc)
+               return -ENOMEM;
+
+       ret = atmel_nand_controller_init(&nc->base, pdev, caps);
+       if (ret)
+               return ret;
+
+       ret = atmel_smc_nand_controller_init(nc);
+       if (ret)
+               return ret;
+
+       return atmel_nand_controller_add_nands(&nc->base);
+}
+
+static int
+atmel_smc_nand_controller_remove(struct atmel_nand_controller *nc)
+{
+       int ret;
+
+       ret = atmel_nand_controller_remove_nands(nc);
+       if (ret)
+               return ret;
+
+       atmel_nand_controller_cleanup(nc);
+
+       return 0;
+}
+
+static const struct atmel_nand_controller_ops atmel_smc_nc_ops = {
+       .probe = atmel_smc_nand_controller_probe,
+       .remove = atmel_smc_nand_controller_remove,
+       .ecc_init = atmel_nand_ecc_init,
+       .nand_init = atmel_smc_nand_init,
+};
+
+static const struct atmel_nand_controller_caps atmel_rm9200_nc_caps = {
+       .ale_offs = BIT(21),
+       .cle_offs = BIT(22),
+       .ops = &atmel_smc_nc_ops,
+};
+
+static const struct atmel_nand_controller_caps atmel_sam9261_nc_caps = {
+       .ale_offs = BIT(22),
+       .cle_offs = BIT(21),
+       .ops = &atmel_smc_nc_ops,
+};
+
+static const struct atmel_nand_controller_caps atmel_sam9g45_nc_caps = {
+       .has_dma = true,
+       .ale_offs = BIT(21),
+       .cle_offs = BIT(22),
+       .ops = &atmel_smc_nc_ops,
+};
+
+/* Only used to parse old bindings. */
+static const struct atmel_nand_controller_caps atmel_rm9200_nand_caps = {
+       .ale_offs = BIT(21),
+       .cle_offs = BIT(22),
+       .ops = &atmel_smc_nc_ops,
+       .legacy_of_bindings = true,
+};
+
+static const struct atmel_nand_controller_caps atmel_sam9261_nand_caps = {
+       .ale_offs = BIT(22),
+       .cle_offs = BIT(21),
+       .ops = &atmel_smc_nc_ops,
+       .legacy_of_bindings = true,
+};
+
+static const struct atmel_nand_controller_caps atmel_sam9g45_nand_caps = {
+       .has_dma = true,
+       .ale_offs = BIT(21),
+       .cle_offs = BIT(22),
+       .ops = &atmel_smc_nc_ops,
+       .legacy_of_bindings = true,
+};
+
+static const struct of_device_id atmel_nand_controller_of_ids[] = {
+       {
+               .compatible = "atmel,at91rm9200-nand-controller",
+               .data = &atmel_rm9200_nc_caps,
+       },
+       {
+               .compatible = "atmel,at91sam9260-nand-controller",
+               .data = &atmel_rm9200_nc_caps,
+       },
+       {
+               .compatible = "atmel,at91sam9261-nand-controller",
+               .data = &atmel_sam9261_nc_caps,
+       },
+       {
+               .compatible = "atmel,at91sam9g45-nand-controller",
+               .data = &atmel_sam9g45_nc_caps,
+       },
+       {
+               .compatible = "atmel,sama5d3-nand-controller",
+               .data = &atmel_sama5_nc_caps,
+       },
+       /* Support for old/deprecated bindings: */
+       {
+               .compatible = "atmel,at91rm9200-nand",
+               .data = &atmel_rm9200_nand_caps,
+       },
+       {
+               .compatible = "atmel,sama5d4-nand",
+               .data = &atmel_rm9200_nand_caps,
+       },
+       {
+               .compatible = "atmel,sama5d2-nand",
+               .data = &atmel_rm9200_nand_caps,
+       },
+       { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, atmel_nand_controller_of_ids);
+
+static int atmel_nand_controller_probe(struct platform_device *pdev)
+{
+       const struct atmel_nand_controller_caps *caps;
+
+       if (pdev->id_entry)
+               caps = (void *)pdev->id_entry->driver_data;
+       else
+               caps = of_device_get_match_data(&pdev->dev);
+
+       if (!caps) {
+               dev_err(&pdev->dev, "Could not retrieve NFC caps\n");
+               return -EINVAL;
+       }
+
+       if (caps->legacy_of_bindings) {
+               u32 ale_offs = 21;
+
+               /*
+                * If we are parsing legacy DT props and the DT contains a
+                * valid NFC node, forward the request to the sama5 logic.
+                */
+               if (of_find_compatible_node(pdev->dev.of_node, NULL,
+                                           "atmel,sama5d3-nfc"))
+                       caps = &atmel_sama5_nand_caps;
+
+               /*
+                * Even if the compatible says we are dealing with an
+                * at91rm9200 controller, the atmel,nand-has-dma specify that
+                * this controller supports DMA, which means we are in fact
+                * dealing with an at91sam9g45+ controller.
+                */
+               if (!caps->has_dma &&
+                   of_property_read_bool(pdev->dev.of_node,
+                                         "atmel,nand-has-dma"))
+                       caps = &atmel_sam9g45_nand_caps;
+
+               /*
+                * All SoCs except the at91sam9261 are assigning ALE to A21 and
+                * CLE to A22. If atmel,nand-addr-offset != 21 this means we're
+                * actually dealing with an at91sam9261 controller.
+                */
+               of_property_read_u32(pdev->dev.of_node,
+                                    "atmel,nand-addr-offset", &ale_offs);
+               if (ale_offs != 21)
+                       caps = &atmel_sam9261_nand_caps;
+       }
+
+       return caps->ops->probe(pdev, caps);
+}
+
+static int atmel_nand_controller_remove(struct platform_device *pdev)
+{
+       struct atmel_nand_controller *nc = platform_get_drvdata(pdev);
+
+       return nc->caps->ops->remove(nc);
+}
+
+static struct platform_driver atmel_nand_controller_driver = {
+       .driver = {
+               .name = "atmel-nand-controller",
+               .of_match_table = of_match_ptr(atmel_nand_controller_of_ids),
+       },
+       .probe = atmel_nand_controller_probe,
+       .remove = atmel_nand_controller_remove,
+};
+module_platform_driver(atmel_nand_controller_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Boris Brezillon <boris.brezillon@free-electrons.com>");
+MODULE_DESCRIPTION("NAND Flash Controller driver for Atmel SoCs");
+MODULE_ALIAS("platform:atmel-nand-controller");
diff --git a/drivers/mtd/nand/atmel/pmecc.c b/drivers/mtd/nand/atmel/pmecc.c
new file mode 100644 (file)
index 0000000..55a8ee5
--- /dev/null
@@ -0,0 +1,1020 @@
+/*
+ * Copyright 2017 ATMEL
+ * Copyright 2017 Free Electrons
+ *
+ * Author: Boris Brezillon <boris.brezillon@free-electrons.com>
+ *
+ * Derived from the atmel_nand.c driver which contained the following
+ * copyrights:
+ *
+ *   Copyright 2003 Rick Bronson
+ *
+ *   Derived from drivers/mtd/nand/autcpu12.c
+ *     Copyright 2001 Thomas Gleixner (gleixner@autronix.de)
+ *
+ *   Derived from drivers/mtd/spia.c
+ *     Copyright 2000 Steven J. Hill (sjhill@cotw.com)
+ *
+ *   Add Hardware ECC support for AT91SAM9260 / AT91SAM9263
+ *     Richard Genoud (richard.genoud@gmail.com), Adeneo Copyright 2007
+ *
+ *   Derived from Das U-Boot source code
+ *     (u-boot-1.1.5/board/atmel/at91sam9263ek/nand.c)
+ *      Copyright 2006 ATMEL Rousset, Lacressonniere Nicolas
+ *
+ *   Add Programmable Multibit ECC support for various AT91 SoC
+ *     Copyright 2012 ATMEL, Hong Xu
+ *
+ *   Add Nand Flash Controller support for SAMA5 SoC
+ *     Copyright 2013 ATMEL, Josh Wu (josh.wu@atmel.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * The PMECC is an hardware assisted BCH engine, which means part of the
+ * ECC algorithm is left to the software. The hardware/software repartition
+ * is explained in the "PMECC Controller Functional Description" chapter in
+ * Atmel datasheets, and some of the functions in this file are directly
+ * implementing the algorithms described in the "Software Implementation"
+ * sub-section.
+ *
+ * TODO: it seems that the software BCH implementation in lib/bch.c is already
+ * providing some of the logic we are implementing here. It would be smart
+ * to expose the needed lib/bch.c helpers/functions and re-use them here.
+ */
+
+#include <linux/genalloc.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/mtd/nand.h>
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "pmecc.h"
+
+/* Galois field dimension */
+#define PMECC_GF_DIMENSION_13                  13
+#define PMECC_GF_DIMENSION_14                  14
+
+/* Primitive Polynomial used by PMECC */
+#define PMECC_GF_13_PRIMITIVE_POLY             0x201b
+#define PMECC_GF_14_PRIMITIVE_POLY             0x4443
+
+#define PMECC_LOOKUP_TABLE_SIZE_512            0x2000
+#define PMECC_LOOKUP_TABLE_SIZE_1024           0x4000
+
+/* Time out value for reading PMECC status register */
+#define PMECC_MAX_TIMEOUT_MS                   100
+
+/* PMECC Register Definitions */
+#define ATMEL_PMECC_CFG                                0x0
+#define PMECC_CFG_BCH_STRENGTH(x)              (x)
+#define PMECC_CFG_BCH_STRENGTH_MASK            GENMASK(2, 0)
+#define PMECC_CFG_SECTOR512                    (0 << 4)
+#define PMECC_CFG_SECTOR1024                   (1 << 4)
+#define PMECC_CFG_NSECTORS(x)                  ((fls(x) - 1) << 8)
+#define PMECC_CFG_READ_OP                      (0 << 12)
+#define PMECC_CFG_WRITE_OP                     (1 << 12)
+#define PMECC_CFG_SPARE_ENABLE                 BIT(16)
+#define PMECC_CFG_AUTO_ENABLE                  BIT(20)
+
+#define ATMEL_PMECC_SAREA                      0x4
+#define ATMEL_PMECC_SADDR                      0x8
+#define ATMEL_PMECC_EADDR                      0xc
+
+#define ATMEL_PMECC_CLK                                0x10
+#define PMECC_CLK_133MHZ                       (2 << 0)
+
+#define ATMEL_PMECC_CTRL                       0x14
+#define PMECC_CTRL_RST                         BIT(0)
+#define PMECC_CTRL_DATA                                BIT(1)
+#define PMECC_CTRL_USER                                BIT(2)
+#define PMECC_CTRL_ENABLE                      BIT(4)
+#define PMECC_CTRL_DISABLE                     BIT(5)
+
+#define ATMEL_PMECC_SR                         0x18
+#define PMECC_SR_BUSY                          BIT(0)
+#define PMECC_SR_ENABLE                                BIT(4)
+
+#define ATMEL_PMECC_IER                                0x1c
+#define ATMEL_PMECC_IDR                                0x20
+#define ATMEL_PMECC_IMR                                0x24
+#define ATMEL_PMECC_ISR                                0x28
+#define PMECC_ERROR_INT                                BIT(0)
+
+#define ATMEL_PMECC_ECC(sector, n)             \
+       ((((sector) + 1) * 0x40) + (n))
+
+#define ATMEL_PMECC_REM(sector, n)             \
+       ((((sector) + 1) * 0x40) + ((n) * 4) + 0x200)
+
+/* PMERRLOC Register Definitions */
+#define ATMEL_PMERRLOC_ELCFG                   0x0
+#define PMERRLOC_ELCFG_SECTOR_512              (0 << 0)
+#define PMERRLOC_ELCFG_SECTOR_1024             (1 << 0)
+#define PMERRLOC_ELCFG_NUM_ERRORS(n)           ((n) << 16)
+
+#define ATMEL_PMERRLOC_ELPRIM                  0x4
+#define ATMEL_PMERRLOC_ELEN                    0x8
+#define ATMEL_PMERRLOC_ELDIS                   0xc
+#define PMERRLOC_DISABLE                       BIT(0)
+
+#define ATMEL_PMERRLOC_ELSR                    0x10
+#define PMERRLOC_ELSR_BUSY                     BIT(0)
+
+#define ATMEL_PMERRLOC_ELIER                   0x14
+#define ATMEL_PMERRLOC_ELIDR                   0x18
+#define ATMEL_PMERRLOC_ELIMR                   0x1c
+#define ATMEL_PMERRLOC_ELISR                   0x20
+#define PMERRLOC_ERR_NUM_MASK                  GENMASK(12, 8)
+#define PMERRLOC_CALC_DONE                     BIT(0)
+
+#define ATMEL_PMERRLOC_SIGMA(x)                        (((x) * 0x4) + 0x28)
+
+#define ATMEL_PMERRLOC_EL(offs, x)             (((x) * 0x4) + (offs))
+
+struct atmel_pmecc_gf_tables {
+       u16 *alpha_to;
+       u16 *index_of;
+};
+
+struct atmel_pmecc_caps {
+       const int *strengths;
+       int nstrengths;
+       int el_offset;
+       bool correct_erased_chunks;
+};
+
+struct atmel_pmecc {
+       struct device *dev;
+       const struct atmel_pmecc_caps *caps;
+
+       struct {
+               void __iomem *base;
+               void __iomem *errloc;
+       } regs;
+
+       struct mutex lock;
+};
+
+struct atmel_pmecc_user_conf_cache {
+       u32 cfg;
+       u32 sarea;
+       u32 saddr;
+       u32 eaddr;
+};
+
+struct atmel_pmecc_user {
+       struct atmel_pmecc_user_conf_cache cache;
+       struct atmel_pmecc *pmecc;
+       const struct atmel_pmecc_gf_tables *gf_tables;
+       int eccbytes;
+       s16 *partial_syn;
+       s16 *si;
+       s16 *lmu;
+       s16 *smu;
+       s32 *mu;
+       s32 *dmu;
+       s32 *delta;
+       u32 isr;
+};
+
+static DEFINE_MUTEX(pmecc_gf_tables_lock);
+static const struct atmel_pmecc_gf_tables *pmecc_gf_tables_512;
+static const struct atmel_pmecc_gf_tables *pmecc_gf_tables_1024;
+
+static inline int deg(unsigned int poly)
+{
+       /* polynomial degree is the most-significant bit index */
+       return fls(poly) - 1;
+}
+
+static int atmel_pmecc_build_gf_tables(int mm, unsigned int poly,
+                                      struct atmel_pmecc_gf_tables *gf_tables)
+{
+       unsigned int i, x = 1;
+       const unsigned int k = BIT(deg(poly));
+       unsigned int nn = BIT(mm) - 1;
+
+       /* primitive polynomial must be of degree m */
+       if (k != (1u << mm))
+               return -EINVAL;
+
+       for (i = 0; i < nn; i++) {
+               gf_tables->alpha_to[i] = x;
+               gf_tables->index_of[x] = i;
+               if (i && (x == 1))
+                       /* polynomial is not primitive (a^i=1 with 0<i<2^m-1) */
+                       return -EINVAL;
+               x <<= 1;
+               if (x & k)
+                       x ^= poly;
+       }
+       gf_tables->alpha_to[nn] = 1;
+       gf_tables->index_of[0] = 0;
+
+       return 0;
+}
+
+static const struct atmel_pmecc_gf_tables *
+atmel_pmecc_create_gf_tables(const struct atmel_pmecc_user_req *req)
+{
+       struct atmel_pmecc_gf_tables *gf_tables;
+       unsigned int poly, degree, table_size;
+       int ret;
+
+       if (req->ecc.sectorsize == 512) {
+               degree = PMECC_GF_DIMENSION_13;
+               poly = PMECC_GF_13_PRIMITIVE_POLY;
+               table_size = PMECC_LOOKUP_TABLE_SIZE_512;
+       } else {
+               degree = PMECC_GF_DIMENSION_14;
+               poly = PMECC_GF_14_PRIMITIVE_POLY;
+               table_size = PMECC_LOOKUP_TABLE_SIZE_1024;
+       }
+
+       gf_tables = kzalloc(sizeof(*gf_tables) +
+                           (2 * table_size * sizeof(u16)),
+                           GFP_KERNEL);
+       if (!gf_tables)
+               return ERR_PTR(-ENOMEM);
+
+       gf_tables->alpha_to = (void *)(gf_tables + 1);
+       gf_tables->index_of = gf_tables->alpha_to + table_size;
+
+       ret = atmel_pmecc_build_gf_tables(degree, poly, gf_tables);
+       if (ret) {
+               kfree(gf_tables);
+               return ERR_PTR(ret);
+       }
+
+       return gf_tables;
+}
+
+static const struct atmel_pmecc_gf_tables *
+atmel_pmecc_get_gf_tables(const struct atmel_pmecc_user_req *req)
+{
+       const struct atmel_pmecc_gf_tables **gf_tables, *ret;
+
+       mutex_lock(&pmecc_gf_tables_lock);
+       if (req->ecc.sectorsize == 512)
+               gf_tables = &pmecc_gf_tables_512;
+       else
+               gf_tables = &pmecc_gf_tables_1024;
+
+       ret = *gf_tables;
+
+       if (!ret) {
+               ret = atmel_pmecc_create_gf_tables(req);
+               if (!IS_ERR(ret))
+                       *gf_tables = ret;
+       }
+       mutex_unlock(&pmecc_gf_tables_lock);
+
+       return ret;
+}
+
+static int atmel_pmecc_prepare_user_req(struct atmel_pmecc *pmecc,
+                                       struct atmel_pmecc_user_req *req)
+{
+       int i, max_eccbytes, eccbytes = 0, eccstrength = 0;
+
+       if (req->pagesize <= 0 || req->oobsize <= 0 || req->ecc.bytes <= 0)
+               return -EINVAL;
+
+       if (req->ecc.ooboffset >= 0 &&
+           req->ecc.ooboffset + req->ecc.bytes > req->oobsize)
+               return -EINVAL;
+
+       if (req->ecc.sectorsize == ATMEL_PMECC_SECTOR_SIZE_AUTO) {
+               if (req->ecc.strength != ATMEL_PMECC_MAXIMIZE_ECC_STRENGTH)
+                       return -EINVAL;
+
+               if (req->pagesize > 512)
+                       req->ecc.sectorsize = 1024;
+               else
+                       req->ecc.sectorsize = 512;
+       }
+
+       if (req->ecc.sectorsize != 512 && req->ecc.sectorsize != 1024)
+               return -EINVAL;
+
+       if (req->pagesize % req->ecc.sectorsize)
+               return -EINVAL;
+
+       req->ecc.nsectors = req->pagesize / req->ecc.sectorsize;
+
+       max_eccbytes = req->ecc.bytes;
+
+       for (i = 0; i < pmecc->caps->nstrengths; i++) {
+               int nbytes, strength = pmecc->caps->strengths[i];
+
+               if (req->ecc.strength != ATMEL_PMECC_MAXIMIZE_ECC_STRENGTH &&
+                   strength < req->ecc.strength)
+                       continue;
+
+               nbytes = DIV_ROUND_UP(strength * fls(8 * req->ecc.sectorsize),
+                                     8);
+               nbytes *= req->ecc.nsectors;
+
+               if (nbytes > max_eccbytes)
+                       break;
+
+               eccstrength = strength;
+               eccbytes = nbytes;
+
+               if (req->ecc.strength != ATMEL_PMECC_MAXIMIZE_ECC_STRENGTH)
+                       break;
+       }
+
+       if (!eccstrength)
+               return -EINVAL;
+
+       req->ecc.bytes = eccbytes;
+       req->ecc.strength = eccstrength;
+
+       if (req->ecc.ooboffset < 0)
+               req->ecc.ooboffset = req->oobsize - eccbytes;
+
+       return 0;
+}
+
+struct atmel_pmecc_user *
+atmel_pmecc_create_user(struct atmel_pmecc *pmecc,
+                       struct atmel_pmecc_user_req *req)
+{
+       struct atmel_pmecc_user *user;
+       const struct atmel_pmecc_gf_tables *gf_tables;
+       int strength, size, ret;
+
+       ret = atmel_pmecc_prepare_user_req(pmecc, req);
+       if (ret)
+               return ERR_PTR(ret);
+
+       size = sizeof(*user);
+       size = ALIGN(size, sizeof(u16));
+       /* Reserve space for partial_syn, si and smu */
+       size += ((2 * req->ecc.strength) + 1) * sizeof(u16) *
+               (2 + req->ecc.strength + 2);
+       /* Reserve space for lmu. */
+       size += (req->ecc.strength + 1) * sizeof(u16);
+       /* Reserve space for mu, dmu and delta. */
+       size = ALIGN(size, sizeof(s32));
+       size += (req->ecc.strength + 1) * sizeof(s32);
+
+       user = kzalloc(size, GFP_KERNEL);
+       if (!user)
+               return ERR_PTR(-ENOMEM);
+
+       user->pmecc = pmecc;
+
+       user->partial_syn = (s16 *)PTR_ALIGN(user + 1, sizeof(u16));
+       user->si = user->partial_syn + ((2 * req->ecc.strength) + 1);
+       user->lmu = user->si + ((2 * req->ecc.strength) + 1);
+       user->smu = user->lmu + (req->ecc.strength + 1);
+       user->mu = (s32 *)PTR_ALIGN(user->smu +
+                                   (((2 * req->ecc.strength) + 1) *
+                                    (req->ecc.strength + 2)),
+                                   sizeof(s32));
+       user->dmu = user->mu + req->ecc.strength + 1;
+       user->delta = user->dmu + req->ecc.strength + 1;
+
+       gf_tables = atmel_pmecc_get_gf_tables(req);
+       if (IS_ERR(gf_tables)) {
+               kfree(user);
+               return ERR_CAST(gf_tables);
+       }
+
+       user->gf_tables = gf_tables;
+
+       user->eccbytes = req->ecc.bytes / req->ecc.nsectors;
+
+       for (strength = 0; strength < pmecc->caps->nstrengths; strength++) {
+               if (pmecc->caps->strengths[strength] == req->ecc.strength)
+                       break;
+       }
+
+       user->cache.cfg = PMECC_CFG_BCH_STRENGTH(strength) |
+                         PMECC_CFG_NSECTORS(req->ecc.nsectors);
+
+       if (req->ecc.sectorsize == 1024)
+               user->cache.cfg |= PMECC_CFG_SECTOR1024;
+
+       user->cache.sarea = req->oobsize - 1;
+       user->cache.saddr = req->ecc.ooboffset;
+       user->cache.eaddr = req->ecc.ooboffset + req->ecc.bytes - 1;
+
+       return user;
+}
+EXPORT_SYMBOL_GPL(atmel_pmecc_create_user);
+
+void atmel_pmecc_destroy_user(struct atmel_pmecc_user *user)
+{
+       kfree(user);
+}
+EXPORT_SYMBOL_GPL(atmel_pmecc_destroy_user);
+
+static int get_strength(struct atmel_pmecc_user *user)
+{
+       const int *strengths = user->pmecc->caps->strengths;
+
+       return strengths[user->cache.cfg & PMECC_CFG_BCH_STRENGTH_MASK];
+}
+
+static int get_sectorsize(struct atmel_pmecc_user *user)
+{
+       return user->cache.cfg & PMECC_LOOKUP_TABLE_SIZE_1024 ? 1024 : 512;
+}
+
+static void atmel_pmecc_gen_syndrome(struct atmel_pmecc_user *user, int sector)
+{
+       int strength = get_strength(user);
+       u32 value;
+       int i;
+
+       /* Fill odd syndromes */
+       for (i = 0; i < strength; i++) {
+               value = readl_relaxed(user->pmecc->regs.base +
+                                     ATMEL_PMECC_REM(sector, i / 2));
+               if (i & 1)
+                       value >>= 16;
+
+               user->partial_syn[(2 * i) + 1] = value;
+       }
+}
+
+static void atmel_pmecc_substitute(struct atmel_pmecc_user *user)
+{
+       int degree = get_sectorsize(user) == 512 ? 13 : 14;
+       int cw_len = BIT(degree) - 1;
+       int strength = get_strength(user);
+       s16 *alpha_to = user->gf_tables->alpha_to;
+       s16 *index_of = user->gf_tables->index_of;
+       s16 *partial_syn = user->partial_syn;
+       s16 *si;
+       int i, j;
+
+       /*
+        * si[] is a table that holds the current syndrome value,
+        * an element of that table belongs to the field
+        */
+       si = user->si;
+
+       memset(&si[1], 0, sizeof(s16) * ((2 * strength) - 1));
+
+       /* Computation 2t syndromes based on S(x) */
+       /* Odd syndromes */
+       for (i = 1; i < 2 * strength; i += 2) {
+               for (j = 0; j < degree; j++) {
+                       if (partial_syn[i] & BIT(j))
+                               si[i] = alpha_to[i * j] ^ si[i];
+               }
+       }
+       /* Even syndrome = (Odd syndrome) ** 2 */
+       for (i = 2, j = 1; j <= strength; i = ++j << 1) {
+               if (si[j] == 0) {
+                       si[i] = 0;
+               } else {
+                       s16 tmp;
+
+                       tmp = index_of[si[j]];
+                       tmp = (tmp * 2) % cw_len;
+                       si[i] = alpha_to[tmp];
+               }
+       }
+}
+
+static void atmel_pmecc_get_sigma(struct atmel_pmecc_user *user)
+{
+       s16 *lmu = user->lmu;
+       s16 *si = user->si;
+       s32 *mu = user->mu;
+       s32 *dmu = user->dmu;
+       s32 *delta = user->delta;
+       int degree = get_sectorsize(user) == 512 ? 13 : 14;
+       int cw_len = BIT(degree) - 1;
+       int strength = get_strength(user);
+       int num = 2 * strength + 1;
+       s16 *index_of = user->gf_tables->index_of;
+       s16 *alpha_to = user->gf_tables->alpha_to;
+       int i, j, k;
+       u32 dmu_0_count, tmp;
+       s16 *smu = user->smu;
+
+       /* index of largest delta */
+       int ro;
+       int largest;
+       int diff;
+
+       dmu_0_count = 0;
+
+       /* First Row */
+
+       /* Mu */
+       mu[0] = -1;
+
+       memset(smu, 0, sizeof(s16) * num);
+       smu[0] = 1;
+
+       /* discrepancy set to 1 */
+       dmu[0] = 1;
+       /* polynom order set to 0 */
+       lmu[0] = 0;
+       delta[0] = (mu[0] * 2 - lmu[0]) >> 1;
+
+       /* Second Row */
+
+       /* Mu */
+       mu[1] = 0;
+       /* Sigma(x) set to 1 */
+       memset(&smu[num], 0, sizeof(s16) * num);
+       smu[num] = 1;
+
+       /* discrepancy set to S1 */
+       dmu[1] = si[1];
+
+       /* polynom order set to 0 */
+       lmu[1] = 0;
+
+       delta[1] = (mu[1] * 2 - lmu[1]) >> 1;
+
+       /* Init the Sigma(x) last row */
+       memset(&smu[(strength + 1) * num], 0, sizeof(s16) * num);
+
+       for (i = 1; i <= strength; i++) {
+               mu[i + 1] = i << 1;
+               /* Begin Computing Sigma (Mu+1) and L(mu) */
+               /* check if discrepancy is set to 0 */
+               if (dmu[i] == 0) {
+                       dmu_0_count++;
+
+                       tmp = ((strength - (lmu[i] >> 1) - 1) / 2);
+                       if ((strength - (lmu[i] >> 1) - 1) & 0x1)
+                               tmp += 2;
+                       else
+                               tmp += 1;
+
+                       if (dmu_0_count == tmp) {
+                               for (j = 0; j <= (lmu[i] >> 1) + 1; j++)
+                                       smu[(strength + 1) * num + j] =
+                                                       smu[i * num + j];
+
+                               lmu[strength + 1] = lmu[i];
+                               return;
+                       }
+
+                       /* copy polynom */
+                       for (j = 0; j <= lmu[i] >> 1; j++)
+                               smu[(i + 1) * num + j] = smu[i * num + j];
+
+                       /* copy previous polynom order to the next */
+                       lmu[i + 1] = lmu[i];
+               } else {
+                       ro = 0;
+                       largest = -1;
+                       /* find largest delta with dmu != 0 */
+                       for (j = 0; j < i; j++) {
+                               if ((dmu[j]) && (delta[j] > largest)) {
+                                       largest = delta[j];
+                                       ro = j;
+                               }
+                       }
+
+                       /* compute difference */
+                       diff = (mu[i] - mu[ro]);
+
+                       /* Compute degree of the new smu polynomial */
+                       if ((lmu[i] >> 1) > ((lmu[ro] >> 1) + diff))
+                               lmu[i + 1] = lmu[i];
+                       else
+                               lmu[i + 1] = ((lmu[ro] >> 1) + diff) * 2;
+
+                       /* Init smu[i+1] with 0 */
+                       for (k = 0; k < num; k++)
+                               smu[(i + 1) * num + k] = 0;
+
+                       /* Compute smu[i+1] */
+                       for (k = 0; k <= lmu[ro] >> 1; k++) {
+                               s16 a, b, c;
+
+                               if (!(smu[ro * num + k] && dmu[i]))
+                                       continue;
+
+                               a = index_of[dmu[i]];
+                               b = index_of[dmu[ro]];
+                               c = index_of[smu[ro * num + k]];
+                               tmp = a + (cw_len - b) + c;
+                               a = alpha_to[tmp % cw_len];
+                               smu[(i + 1) * num + (k + diff)] = a;
+                       }
+
+                       for (k = 0; k <= lmu[i] >> 1; k++)
+                               smu[(i + 1) * num + k] ^= smu[i * num + k];
+               }
+
+               /* End Computing Sigma (Mu+1) and L(mu) */
+               /* In either case compute delta */
+               delta[i + 1] = (mu[i + 1] * 2 - lmu[i + 1]) >> 1;
+
+               /* Do not compute discrepancy for the last iteration */
+               if (i >= strength)
+                       continue;
+
+               for (k = 0; k <= (lmu[i + 1] >> 1); k++) {
+                       tmp = 2 * (i - 1);
+                       if (k == 0) {
+                               dmu[i + 1] = si[tmp + 3];
+                       } else if (smu[(i + 1) * num + k] && si[tmp + 3 - k]) {
+                               s16 a, b, c;
+
+                               a = index_of[smu[(i + 1) * num + k]];
+                               b = si[2 * (i - 1) + 3 - k];
+                               c = index_of[b];
+                               tmp = a + c;
+                               tmp %= cw_len;
+                               dmu[i + 1] = alpha_to[tmp] ^ dmu[i + 1];
+                       }
+               }
+       }
+}
+
+static int atmel_pmecc_err_location(struct atmel_pmecc_user *user)
+{
+       int sector_size = get_sectorsize(user);
+       int degree = sector_size == 512 ? 13 : 14;
+       struct atmel_pmecc *pmecc = user->pmecc;
+       int strength = get_strength(user);
+       int ret, roots_nbr, i, err_nbr = 0;
+       int num = (2 * strength) + 1;
+       s16 *smu = user->smu;
+       u32 val;
+
+       writel(PMERRLOC_DISABLE, pmecc->regs.errloc + ATMEL_PMERRLOC_ELDIS);
+
+       for (i = 0; i <= user->lmu[strength + 1] >> 1; i++) {
+               writel_relaxed(smu[(strength + 1) * num + i],
+                              pmecc->regs.errloc + ATMEL_PMERRLOC_SIGMA(i));
+               err_nbr++;
+       }
+
+       val = (err_nbr - 1) << 16;
+       if (sector_size == 1024)
+               val |= 1;
+
+       writel(val, pmecc->regs.errloc + ATMEL_PMERRLOC_ELCFG);
+       writel((sector_size * 8) + (degree * strength),
+              pmecc->regs.errloc + ATMEL_PMERRLOC_ELEN);
+
+       ret = readl_relaxed_poll_timeout(pmecc->regs.errloc +
+                                        ATMEL_PMERRLOC_ELISR,
+                                        val, val & PMERRLOC_CALC_DONE, 0,
+                                        PMECC_MAX_TIMEOUT_MS * 1000);
+       if (ret) {
+               dev_err(pmecc->dev,
+                       "PMECC: Timeout to calculate error location.\n");
+               return ret;
+       }
+
+       roots_nbr = (val & PMERRLOC_ERR_NUM_MASK) >> 8;
+       /* Number of roots == degree of smu hence <= cap */
+       if (roots_nbr == user->lmu[strength + 1] >> 1)
+               return err_nbr - 1;
+
+       /*
+        * Number of roots does not match the degree of smu
+        * unable to correct error.
+        */
+       return -EBADMSG;
+}
+
+int atmel_pmecc_correct_sector(struct atmel_pmecc_user *user, int sector,
+                              void *data, void *ecc)
+{
+       struct atmel_pmecc *pmecc = user->pmecc;
+       int sectorsize = get_sectorsize(user);
+       int eccbytes = user->eccbytes;
+       int i, nerrors;
+
+       if (!(user->isr & BIT(sector)))
+               return 0;
+
+       atmel_pmecc_gen_syndrome(user, sector);
+       atmel_pmecc_substitute(user);
+       atmel_pmecc_get_sigma(user);
+
+       nerrors = atmel_pmecc_err_location(user);
+       if (nerrors < 0)
+               return nerrors;
+
+       for (i = 0; i < nerrors; i++) {
+               const char *area;
+               int byte, bit;
+               u32 errpos;
+               u8 *ptr;
+
+               errpos = readl_relaxed(pmecc->regs.errloc +
+                               ATMEL_PMERRLOC_EL(pmecc->caps->el_offset, i));
+               errpos--;
+
+               byte = errpos / 8;
+               bit = errpos % 8;
+
+               if (byte < sectorsize) {
+                       ptr = data + byte;
+                       area = "data";
+               } else if (byte < sectorsize + eccbytes) {
+                       ptr = ecc + byte - sectorsize;
+                       area = "ECC";
+               } else {
+                       dev_dbg(pmecc->dev,
+                               "Invalid errpos value (%d, max is %d)\n",
+                               errpos, (sectorsize + eccbytes) * 8);
+                       return -EINVAL;
+               }
+
+               dev_dbg(pmecc->dev,
+                       "Bit flip in %s area, byte %d: 0x%02x -> 0x%02x\n",
+                       area, byte, *ptr, (unsigned int)(*ptr ^ BIT(bit)));
+
+               *ptr ^= BIT(bit);
+       }
+
+       return nerrors;
+}
+EXPORT_SYMBOL_GPL(atmel_pmecc_correct_sector);
+
+bool atmel_pmecc_correct_erased_chunks(struct atmel_pmecc_user *user)
+{
+       return user->pmecc->caps->correct_erased_chunks;
+}
+EXPORT_SYMBOL_GPL(atmel_pmecc_correct_erased_chunks);
+
+void atmel_pmecc_get_generated_eccbytes(struct atmel_pmecc_user *user,
+                                       int sector, void *ecc)
+{
+       struct atmel_pmecc *pmecc = user->pmecc;
+       u8 *ptr = ecc;
+       int i;
+
+       for (i = 0; i < user->eccbytes; i++)
+               ptr[i] = readb_relaxed(pmecc->regs.base +
+                                      ATMEL_PMECC_ECC(sector, i));
+}
+EXPORT_SYMBOL_GPL(atmel_pmecc_get_generated_eccbytes);
+
+int atmel_pmecc_enable(struct atmel_pmecc_user *user, int op)
+{
+       struct atmel_pmecc *pmecc = user->pmecc;
+       u32 cfg;
+
+       if (op != NAND_ECC_READ && op != NAND_ECC_WRITE) {
+               dev_err(pmecc->dev, "Bad ECC operation!");
+               return -EINVAL;
+       }
+
+       mutex_lock(&user->pmecc->lock);
+
+       cfg = user->cache.cfg;
+       if (op == NAND_ECC_WRITE)
+               cfg |= PMECC_CFG_WRITE_OP;
+       else
+               cfg |= PMECC_CFG_AUTO_ENABLE;
+
+       writel(cfg, pmecc->regs.base + ATMEL_PMECC_CFG);
+       writel(user->cache.sarea, pmecc->regs.base + ATMEL_PMECC_SAREA);
+       writel(user->cache.saddr, pmecc->regs.base + ATMEL_PMECC_SADDR);
+       writel(user->cache.eaddr, pmecc->regs.base + ATMEL_PMECC_EADDR);
+
+       writel(PMECC_CTRL_ENABLE, pmecc->regs.base + ATMEL_PMECC_CTRL);
+       writel(PMECC_CTRL_DATA, pmecc->regs.base + ATMEL_PMECC_CTRL);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(atmel_pmecc_enable);
+
+void atmel_pmecc_disable(struct atmel_pmecc_user *user)
+{
+       struct atmel_pmecc *pmecc = user->pmecc;
+
+       writel(PMECC_CTRL_RST, pmecc->regs.base + ATMEL_PMECC_CTRL);
+       writel(PMECC_CTRL_DISABLE, pmecc->regs.base + ATMEL_PMECC_CTRL);
+       mutex_unlock(&user->pmecc->lock);
+}
+EXPORT_SYMBOL_GPL(atmel_pmecc_disable);
+
+int atmel_pmecc_wait_rdy(struct atmel_pmecc_user *user)
+{
+       struct atmel_pmecc *pmecc = user->pmecc;
+       u32 status;
+       int ret;
+
+       ret = readl_relaxed_poll_timeout(pmecc->regs.base +
+                                        ATMEL_PMECC_SR,
+                                        status, !(status & PMECC_SR_BUSY), 0,
+                                        PMECC_MAX_TIMEOUT_MS * 1000);
+       if (ret) {
+               dev_err(pmecc->dev,
+                       "Timeout while waiting for PMECC ready.\n");
+               return ret;
+       }
+
+       user->isr = readl_relaxed(pmecc->regs.base + ATMEL_PMECC_ISR);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(atmel_pmecc_wait_rdy);
+
+static struct atmel_pmecc *atmel_pmecc_create(struct platform_device *pdev,
+                                       const struct atmel_pmecc_caps *caps,
+                                       int pmecc_res_idx, int errloc_res_idx)
+{
+       struct device *dev = &pdev->dev;
+       struct atmel_pmecc *pmecc;
+       struct resource *res;
+
+       pmecc = devm_kzalloc(dev, sizeof(*pmecc), GFP_KERNEL);
+       if (!pmecc)
+               return ERR_PTR(-ENOMEM);
+
+       pmecc->caps = caps;
+       pmecc->dev = dev;
+       mutex_init(&pmecc->lock);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, pmecc_res_idx);
+       pmecc->regs.base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(pmecc->regs.base))
+               return ERR_CAST(pmecc->regs.base);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, errloc_res_idx);
+       pmecc->regs.errloc = devm_ioremap_resource(dev, res);
+       if (IS_ERR(pmecc->regs.errloc))
+               return ERR_CAST(pmecc->regs.errloc);
+
+       /* Disable all interrupts before registering the PMECC handler. */
+       writel(0xffffffff, pmecc->regs.base + ATMEL_PMECC_IDR);
+
+       /* Reset the ECC engine */
+       writel(PMECC_CTRL_RST, pmecc->regs.base + ATMEL_PMECC_CTRL);
+       writel(PMECC_CTRL_DISABLE, pmecc->regs.base + ATMEL_PMECC_CTRL);
+
+       return pmecc;
+}
+
+static void devm_atmel_pmecc_put(struct device *dev, void *res)
+{
+       struct atmel_pmecc **pmecc = res;
+
+       put_device((*pmecc)->dev);
+}
+
+static struct atmel_pmecc *atmel_pmecc_get_by_node(struct device *userdev,
+                                                  struct device_node *np)
+{
+       struct platform_device *pdev;
+       struct atmel_pmecc *pmecc, **ptr;
+
+       pdev = of_find_device_by_node(np);
+       if (!pdev || !platform_get_drvdata(pdev))
+               return ERR_PTR(-EPROBE_DEFER);
+
+       ptr = devres_alloc(devm_atmel_pmecc_put, sizeof(*ptr), GFP_KERNEL);
+       if (!ptr)
+               return ERR_PTR(-ENOMEM);
+
+       get_device(&pdev->dev);
+       pmecc = platform_get_drvdata(pdev);
+
+       *ptr = pmecc;
+
+       devres_add(userdev, ptr);
+
+       return pmecc;
+}
+
+static const int atmel_pmecc_strengths[] = { 2, 4, 8, 12, 24, 32 };
+
+static struct atmel_pmecc_caps at91sam9g45_caps = {
+       .strengths = atmel_pmecc_strengths,
+       .nstrengths = 5,
+       .el_offset = 0x8c,
+};
+
+static struct atmel_pmecc_caps sama5d4_caps = {
+       .strengths = atmel_pmecc_strengths,
+       .nstrengths = 5,
+       .el_offset = 0x8c,
+       .correct_erased_chunks = true,
+};
+
+static struct atmel_pmecc_caps sama5d2_caps = {
+       .strengths = atmel_pmecc_strengths,
+       .nstrengths = 6,
+       .el_offset = 0xac,
+       .correct_erased_chunks = true,
+};
+
+static const struct of_device_id atmel_pmecc_legacy_match[] = {
+       { .compatible = "atmel,sama5d4-nand", &sama5d4_caps },
+       { .compatible = "atmel,sama5d2-nand", &sama5d2_caps },
+       { /* sentinel */ }
+};
+
+struct atmel_pmecc *devm_atmel_pmecc_get(struct device *userdev)
+{
+       struct atmel_pmecc *pmecc;
+       struct device_node *np;
+
+       if (!userdev)
+               return ERR_PTR(-EINVAL);
+
+       if (!userdev->of_node)
+               return NULL;
+
+       np = of_parse_phandle(userdev->of_node, "ecc-engine", 0);
+       if (np) {
+               pmecc = atmel_pmecc_get_by_node(userdev, np);
+               of_node_put(np);
+       } else {
+               /*
+                * Support old DT bindings: in this case the PMECC iomem
+                * resources are directly defined in the user pdev at position
+                * 1 and 2. Extract all relevant information from there.
+                */
+               struct platform_device *pdev = to_platform_device(userdev);
+               const struct atmel_pmecc_caps *caps;
+
+               /* No PMECC engine available. */
+               if (!of_property_read_bool(userdev->of_node,
+                                          "atmel,has-pmecc"))
+                       return NULL;
+
+               caps = &at91sam9g45_caps;
+
+               /*
+                * Try to find the NFC subnode and extract the associated caps
+                * from there.
+                */
+               np = of_find_compatible_node(userdev->of_node, NULL,
+                                            "atmel,sama5d3-nfc");
+               if (np) {
+                       const struct of_device_id *match;
+
+                       match = of_match_node(atmel_pmecc_legacy_match, np);
+                       if (match && match->data)
+                               caps = match->data;
+
+                       of_node_put(np);
+               }
+
+               pmecc = atmel_pmecc_create(pdev, caps, 1, 2);
+       }
+
+       return pmecc;
+}
+EXPORT_SYMBOL(devm_atmel_pmecc_get);
+
+static const struct of_device_id atmel_pmecc_match[] = {
+       { .compatible = "atmel,at91sam9g45-pmecc", &at91sam9g45_caps },
+       { .compatible = "atmel,sama5d4-pmecc", &sama5d4_caps },
+       { .compatible = "atmel,sama5d2-pmecc", &sama5d2_caps },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, atmel_pmecc_match);
+
+static int atmel_pmecc_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       const struct atmel_pmecc_caps *caps;
+       struct atmel_pmecc *pmecc;
+
+       caps = of_device_get_match_data(&pdev->dev);
+       if (!caps) {
+               dev_err(dev, "Invalid caps\n");
+               return -EINVAL;
+       }
+
+       pmecc = atmel_pmecc_create(pdev, caps, 0, 1);
+       if (IS_ERR(pmecc))
+               return PTR_ERR(pmecc);
+
+       platform_set_drvdata(pdev, pmecc);
+
+       return 0;
+}
+
+static struct platform_driver atmel_pmecc_driver = {
+       .driver = {
+               .name = "atmel-pmecc",
+               .of_match_table = of_match_ptr(atmel_pmecc_match),
+       },
+       .probe = atmel_pmecc_probe,
+};
+module_platform_driver(atmel_pmecc_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Boris Brezillon <boris.brezillon@free-electrons.com>");
+MODULE_DESCRIPTION("PMECC engine driver");
+MODULE_ALIAS("platform:atmel_pmecc");
diff --git a/drivers/mtd/nand/atmel/pmecc.h b/drivers/mtd/nand/atmel/pmecc.h
new file mode 100644 (file)
index 0000000..a8ddbfc
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * © Copyright 2016 ATMEL
+ * © Copyright 2016 Free Electrons
+ *
+ * Author: Boris Brezillon <boris.brezillon@free-electrons.com>
+ *
+ * Derived from the atmel_nand.c driver which contained the following
+ * copyrights:
+ *
+ *    Copyright © 2003 Rick Bronson
+ *
+ *    Derived from drivers/mtd/nand/autcpu12.c
+ *        Copyright © 2001 Thomas Gleixner (gleixner@autronix.de)
+ *
+ *    Derived from drivers/mtd/spia.c
+ *        Copyright © 2000 Steven J. Hill (sjhill@cotw.com)
+ *
+ *
+ *    Add Hardware ECC support for AT91SAM9260 / AT91SAM9263
+ *        Richard Genoud (richard.genoud@gmail.com), Adeneo Copyright © 2007
+ *
+ *        Derived from Das U-Boot source code
+ *              (u-boot-1.1.5/board/atmel/at91sam9263ek/nand.c)
+ *        © Copyright 2006 ATMEL Rousset, Lacressonniere Nicolas
+ *
+ *    Add Programmable Multibit ECC support for various AT91 SoC
+ *        © Copyright 2012 ATMEL, Hong Xu
+ *
+ *    Add Nand Flash Controller support for SAMA5 SoC
+ *        © Copyright 2013 ATMEL, Josh Wu (josh.wu@atmel.com)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#ifndef ATMEL_PMECC_H
+#define ATMEL_PMECC_H
+
+#define ATMEL_PMECC_MAXIMIZE_ECC_STRENGTH      0
+#define ATMEL_PMECC_SECTOR_SIZE_AUTO           0
+#define ATMEL_PMECC_OOBOFFSET_AUTO             -1
+
+struct atmel_pmecc_user_req {
+       int pagesize;
+       int oobsize;
+       struct {
+               int strength;
+               int bytes;
+               int sectorsize;
+               int nsectors;
+               int ooboffset;
+       } ecc;
+};
+
+struct atmel_pmecc *devm_atmel_pmecc_get(struct device *dev);
+
+struct atmel_pmecc_user *
+atmel_pmecc_create_user(struct atmel_pmecc *pmecc,
+                       struct atmel_pmecc_user_req *req);
+void atmel_pmecc_destroy_user(struct atmel_pmecc_user *user);
+
+int atmel_pmecc_enable(struct atmel_pmecc_user *user, int op);
+void atmel_pmecc_disable(struct atmel_pmecc_user *user);
+int atmel_pmecc_wait_rdy(struct atmel_pmecc_user *user);
+int atmel_pmecc_correct_sector(struct atmel_pmecc_user *user, int sector,
+                              void *data, void *ecc);
+bool atmel_pmecc_correct_erased_chunks(struct atmel_pmecc_user *user);
+void atmel_pmecc_get_generated_eccbytes(struct atmel_pmecc_user *user,
+                                       int sector, void *ecc);
+
+#endif /* ATMEL_PMECC_H */
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
deleted file mode 100644 (file)
index 9ebd5ec..0000000
+++ /dev/null
@@ -1,2479 +0,0 @@
-/*
- *  Copyright © 2003 Rick Bronson
- *
- *  Derived from drivers/mtd/nand/autcpu12.c
- *      Copyright © 2001 Thomas Gleixner (gleixner@autronix.de)
- *
- *  Derived from drivers/mtd/spia.c
- *      Copyright © 2000 Steven J. Hill (sjhill@cotw.com)
- *
- *
- *  Add Hardware ECC support for AT91SAM9260 / AT91SAM9263
- *     Richard Genoud (richard.genoud@gmail.com), Adeneo Copyright © 2007
- *
- *     Derived from Das U-Boot source code
- *                     (u-boot-1.1.5/board/atmel/at91sam9263ek/nand.c)
- *     © Copyright 2006 ATMEL Rousset, Lacressonniere Nicolas
- *
- *  Add Programmable Multibit ECC support for various AT91 SoC
- *     © Copyright 2012 ATMEL, Hong Xu
- *
- *  Add Nand Flash Controller support for SAMA5 SoC
- *     © Copyright 2013 ATMEL, Josh Wu (josh.wu@atmel.com)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#include <linux/clk.h>
-#include <linux/dma-mapping.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/platform_device.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include <linux/of_gpio.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/partitions.h>
-
-#include <linux/delay.h>
-#include <linux/dmaengine.h>
-#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/platform_data/atmel.h>
-
-static int use_dma = 1;
-module_param(use_dma, int, 0);
-
-static int on_flash_bbt = 0;
-module_param(on_flash_bbt, int, 0);
-
-/* Register access macros */
-#define ecc_readl(add, reg)                            \
-       __raw_readl(add + ATMEL_ECC_##reg)
-#define ecc_writel(add, reg, value)                    \
-       __raw_writel((value), add + ATMEL_ECC_##reg)
-
-#include "atmel_nand_ecc.h"    /* Hardware ECC registers */
-#include "atmel_nand_nfc.h"    /* Nand Flash Controller definition */
-
-struct atmel_nand_caps {
-       bool pmecc_correct_erase_page;
-       uint8_t pmecc_max_correction;
-};
-
-/*
- * oob layout for large page size
- * bad block info is on bytes 0 and 1
- * the bytes have to be consecutives to avoid
- * several NAND_CMD_RNDOUT during read
- *
- * oob layout for small page size
- * bad block info is on bytes 4 and 5
- * the bytes have to be consecutives to avoid
- * several NAND_CMD_RNDOUT during read
- */
-static int atmel_ooblayout_ecc_sp(struct mtd_info *mtd, int section,
-                                 struct mtd_oob_region *oobregion)
-{
-       if (section)
-               return -ERANGE;
-
-       oobregion->length = 4;
-       oobregion->offset = 0;
-
-       return 0;
-}
-
-static int atmel_ooblayout_free_sp(struct mtd_info *mtd, int section,
-                                  struct mtd_oob_region *oobregion)
-{
-       if (section)
-               return -ERANGE;
-
-       oobregion->offset = 6;
-       oobregion->length = mtd->oobsize - oobregion->offset;
-
-       return 0;
-}
-
-static const struct mtd_ooblayout_ops atmel_ooblayout_sp_ops = {
-       .ecc = atmel_ooblayout_ecc_sp,
-       .free = atmel_ooblayout_free_sp,
-};
-
-struct atmel_nfc {
-       void __iomem            *base_cmd_regs;
-       void __iomem            *hsmc_regs;
-       void                    *sram_bank0;
-       dma_addr_t              sram_bank0_phys;
-       bool                    use_nfc_sram;
-       bool                    write_by_sram;
-
-       struct clk              *clk;
-
-       bool                    is_initialized;
-       struct completion       comp_ready;
-       struct completion       comp_cmd_done;
-       struct completion       comp_xfer_done;
-
-       /* Point to the sram bank which include readed data via NFC */
-       void                    *data_in_sram;
-       bool                    will_write_sram;
-};
-static struct atmel_nfc        nand_nfc;
-
-struct atmel_nand_host {
-       struct nand_chip        nand_chip;
-       void __iomem            *io_base;
-       dma_addr_t              io_phys;
-       struct atmel_nand_data  board;
-       struct device           *dev;
-       void __iomem            *ecc;
-
-       struct completion       comp;
-       struct dma_chan         *dma_chan;
-
-       struct atmel_nfc        *nfc;
-
-       const struct atmel_nand_caps    *caps;
-       bool                    has_pmecc;
-       u8                      pmecc_corr_cap;
-       u16                     pmecc_sector_size;
-       bool                    has_no_lookup_table;
-       u32                     pmecc_lookup_table_offset;
-       u32                     pmecc_lookup_table_offset_512;
-       u32                     pmecc_lookup_table_offset_1024;
-
-       int                     pmecc_degree;   /* Degree of remainders */
-       int                     pmecc_cw_len;   /* Length of codeword */
-
-       void __iomem            *pmerrloc_base;
-       void __iomem            *pmerrloc_el_base;
-       void __iomem            *pmecc_rom_base;
-
-       /* lookup table for alpha_to and index_of */
-       void __iomem            *pmecc_alpha_to;
-       void __iomem            *pmecc_index_of;
-
-       /* data for pmecc computation */
-       int16_t                 *pmecc_partial_syn;
-       int16_t                 *pmecc_si;
-       int16_t                 *pmecc_smu;     /* Sigma table */
-       int16_t                 *pmecc_lmu;     /* polynomal order */
-       int                     *pmecc_mu;
-       int                     *pmecc_dmu;
-       int                     *pmecc_delta;
-};
-
-/*
- * Enable NAND.
- */
-static void atmel_nand_enable(struct atmel_nand_host *host)
-{
-       if (gpio_is_valid(host->board.enable_pin))
-               gpio_set_value(host->board.enable_pin, 0);
-}
-
-/*
- * Disable NAND.
- */
-static void atmel_nand_disable(struct atmel_nand_host *host)
-{
-       if (gpio_is_valid(host->board.enable_pin))
-               gpio_set_value(host->board.enable_pin, 1);
-}
-
-/*
- * Hardware specific access to control-lines
- */
-static void atmel_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
-{
-       struct nand_chip *nand_chip = mtd_to_nand(mtd);
-       struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
-
-       if (ctrl & NAND_CTRL_CHANGE) {
-               if (ctrl & NAND_NCE)
-                       atmel_nand_enable(host);
-               else
-                       atmel_nand_disable(host);
-       }
-       if (cmd == NAND_CMD_NONE)
-               return;
-
-       if (ctrl & NAND_CLE)
-               writeb(cmd, host->io_base + (1 << host->board.cle));
-       else
-               writeb(cmd, host->io_base + (1 << host->board.ale));
-}
-
-/*
- * Read the Device Ready pin.
- */
-static int atmel_nand_device_ready(struct mtd_info *mtd)
-{
-       struct nand_chip *nand_chip = mtd_to_nand(mtd);
-       struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
-
-       return gpio_get_value(host->board.rdy_pin) ^
-                !!host->board.rdy_pin_active_low;
-}
-
-/* Set up for hardware ready pin and enable pin. */
-static int atmel_nand_set_enable_ready_pins(struct mtd_info *mtd)
-{
-       struct nand_chip *chip = mtd_to_nand(mtd);
-       struct atmel_nand_host *host = nand_get_controller_data(chip);
-       int res = 0;
-
-       if (gpio_is_valid(host->board.rdy_pin)) {
-               res = devm_gpio_request(host->dev,
-                               host->board.rdy_pin, "nand_rdy");
-               if (res < 0) {
-                       dev_err(host->dev,
-                               "can't request rdy gpio %d\n",
-                               host->board.rdy_pin);
-                       return res;
-               }
-
-               res = gpio_direction_input(host->board.rdy_pin);
-               if (res < 0) {
-                       dev_err(host->dev,
-                               "can't request input direction rdy gpio %d\n",
-                               host->board.rdy_pin);
-                       return res;
-               }
-
-               chip->dev_ready = atmel_nand_device_ready;
-       }
-
-       if (gpio_is_valid(host->board.enable_pin)) {
-               res = devm_gpio_request(host->dev,
-                               host->board.enable_pin, "nand_enable");
-               if (res < 0) {
-                       dev_err(host->dev,
-                               "can't request enable gpio %d\n",
-                               host->board.enable_pin);
-                       return res;
-               }
-
-               res = gpio_direction_output(host->board.enable_pin, 1);
-               if (res < 0) {
-                       dev_err(host->dev,
-                               "can't request output direction enable gpio %d\n",
-                               host->board.enable_pin);
-                       return res;
-               }
-       }
-
-       return res;
-}
-
-/*
- * Minimal-overhead PIO for data access.
- */
-static void atmel_read_buf8(struct mtd_info *mtd, u8 *buf, int len)
-{
-       struct nand_chip        *nand_chip = mtd_to_nand(mtd);
-       struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
-
-       if (host->nfc && host->nfc->use_nfc_sram && host->nfc->data_in_sram) {
-               memcpy(buf, host->nfc->data_in_sram, len);
-               host->nfc->data_in_sram += len;
-       } else {
-               __raw_readsb(nand_chip->IO_ADDR_R, buf, len);
-       }
-}
-
-static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len)
-{
-       struct nand_chip        *nand_chip = mtd_to_nand(mtd);
-       struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
-
-       if (host->nfc && host->nfc->use_nfc_sram && host->nfc->data_in_sram) {
-               memcpy(buf, host->nfc->data_in_sram, len);
-               host->nfc->data_in_sram += len;
-       } else {
-               __raw_readsw(nand_chip->IO_ADDR_R, buf, len / 2);
-       }
-}
-
-static void atmel_write_buf8(struct mtd_info *mtd, const u8 *buf, int len)
-{
-       struct nand_chip        *nand_chip = mtd_to_nand(mtd);
-
-       __raw_writesb(nand_chip->IO_ADDR_W, buf, len);
-}
-
-static void atmel_write_buf16(struct mtd_info *mtd, const u8 *buf, int len)
-{
-       struct nand_chip        *nand_chip = mtd_to_nand(mtd);
-
-       __raw_writesw(nand_chip->IO_ADDR_W, buf, len / 2);
-}
-
-static void dma_complete_func(void *completion)
-{
-       complete(completion);
-}
-
-static int nfc_set_sram_bank(struct atmel_nand_host *host, unsigned int bank)
-{
-       /* NFC only has two banks. Must be 0 or 1 */
-       if (bank > 1)
-               return -EINVAL;
-
-       if (bank) {
-               struct mtd_info *mtd = nand_to_mtd(&host->nand_chip);
-
-               /* Only for a 2k-page or lower flash, NFC can handle 2 banks */
-               if (mtd->writesize > 2048)
-                       return -EINVAL;
-               nfc_writel(host->nfc->hsmc_regs, BANK, ATMEL_HSMC_NFC_BANK1);
-       } else {
-               nfc_writel(host->nfc->hsmc_regs, BANK, ATMEL_HSMC_NFC_BANK0);
-       }
-
-       return 0;
-}
-
-static uint nfc_get_sram_off(struct atmel_nand_host *host)
-{
-       if (nfc_readl(host->nfc->hsmc_regs, BANK) & ATMEL_HSMC_NFC_BANK1)
-               return NFC_SRAM_BANK1_OFFSET;
-       else
-               return 0;
-}
-
-static dma_addr_t nfc_sram_phys(struct atmel_nand_host *host)
-{
-       if (nfc_readl(host->nfc->hsmc_regs, BANK) & ATMEL_HSMC_NFC_BANK1)
-               return host->nfc->sram_bank0_phys + NFC_SRAM_BANK1_OFFSET;
-       else
-               return host->nfc->sram_bank0_phys;
-}
-
-static int atmel_nand_dma_op(struct mtd_info *mtd, void *buf, int len,
-                              int is_read)
-{
-       struct dma_device *dma_dev;
-       enum dma_ctrl_flags flags;
-       dma_addr_t dma_src_addr, dma_dst_addr, phys_addr;
-       struct dma_async_tx_descriptor *tx = NULL;
-       dma_cookie_t cookie;
-       struct nand_chip *chip = mtd_to_nand(mtd);
-       struct atmel_nand_host *host = nand_get_controller_data(chip);
-       void *p = buf;
-       int err = -EIO;
-       enum dma_data_direction dir = is_read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
-       struct atmel_nfc *nfc = host->nfc;
-
-       if (buf >= high_memory)
-               goto err_buf;
-
-       dma_dev = host->dma_chan->device;
-
-       flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
-
-       phys_addr = dma_map_single(dma_dev->dev, p, len, dir);
-       if (dma_mapping_error(dma_dev->dev, phys_addr)) {
-               dev_err(host->dev, "Failed to dma_map_single\n");
-               goto err_buf;
-       }
-
-       if (is_read) {
-               if (nfc && nfc->data_in_sram)
-                       dma_src_addr = nfc_sram_phys(host) + (nfc->data_in_sram
-                               - (nfc->sram_bank0 + nfc_get_sram_off(host)));
-               else
-                       dma_src_addr = host->io_phys;
-
-               dma_dst_addr = phys_addr;
-       } else {
-               dma_src_addr = phys_addr;
-
-               if (nfc && nfc->write_by_sram)
-                       dma_dst_addr = nfc_sram_phys(host);
-               else
-                       dma_dst_addr = host->io_phys;
-       }
-
-       tx = dma_dev->device_prep_dma_memcpy(host->dma_chan, dma_dst_addr,
-                                            dma_src_addr, len, flags);
-       if (!tx) {
-               dev_err(host->dev, "Failed to prepare DMA memcpy\n");
-               goto err_dma;
-       }
-
-       init_completion(&host->comp);
-       tx->callback = dma_complete_func;
-       tx->callback_param = &host->comp;
-
-       cookie = tx->tx_submit(tx);
-       if (dma_submit_error(cookie)) {
-               dev_err(host->dev, "Failed to do DMA tx_submit\n");
-               goto err_dma;
-       }
-
-       dma_async_issue_pending(host->dma_chan);
-       wait_for_completion(&host->comp);
-
-       if (is_read && nfc && nfc->data_in_sram)
-               /* After read data from SRAM, need to increase the position */
-               nfc->data_in_sram += len;
-
-       err = 0;
-
-err_dma:
-       dma_unmap_single(dma_dev->dev, phys_addr, len, dir);
-err_buf:
-       if (err != 0)
-               dev_dbg(host->dev, "Fall back to CPU I/O\n");
-       return err;
-}
-
-static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len)
-{
-       struct nand_chip *chip = mtd_to_nand(mtd);
-
-       if (use_dma && len > mtd->oobsize)
-               /* only use DMA for bigger than oob size: better performances */
-               if (atmel_nand_dma_op(mtd, buf, len, 1) == 0)
-                       return;
-
-       if (chip->options & NAND_BUSWIDTH_16)
-               atmel_read_buf16(mtd, buf, len);
-       else
-               atmel_read_buf8(mtd, buf, len);
-}
-
-static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
-{
-       struct nand_chip *chip = mtd_to_nand(mtd);
-
-       if (use_dma && len > mtd->oobsize)
-               /* only use DMA for bigger than oob size: better performances */
-               if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) == 0)
-                       return;
-
-       if (chip->options & NAND_BUSWIDTH_16)
-               atmel_write_buf16(mtd, buf, len);
-       else
-               atmel_write_buf8(mtd, buf, len);
-}
-
-/*
- * Return number of ecc bytes per sector according to sector size and
- * correction capability
- *
- * Following table shows what at91 PMECC supported:
- * Correction Capability       Sector_512_bytes        Sector_1024_bytes
- * =====================       ================        =================
- *                2-bits                 4-bytes                  4-bytes
- *                4-bits                 7-bytes                  7-bytes
- *                8-bits                13-bytes                 14-bytes
- *               12-bits                20-bytes                 21-bytes
- *               24-bits                39-bytes                 42-bytes
- *               32-bits                52-bytes                 56-bytes
- */
-static int pmecc_get_ecc_bytes(int cap, int sector_size)
-{
-       int m = 12 + sector_size / 512;
-       return (m * cap + 7) / 8;
-}
-
-static void __iomem *pmecc_get_alpha_to(struct atmel_nand_host *host)
-{
-       int table_size;
-
-       table_size = host->pmecc_sector_size == 512 ?
-               PMECC_LOOKUP_TABLE_SIZE_512 : PMECC_LOOKUP_TABLE_SIZE_1024;
-
-       return host->pmecc_rom_base + host->pmecc_lookup_table_offset +
-                       table_size * sizeof(int16_t);
-}
-
-static int pmecc_data_alloc(struct atmel_nand_host *host)
-{
-       const int cap = host->pmecc_corr_cap;
-       int size;
-
-       size = (2 * cap + 1) * sizeof(int16_t);
-       host->pmecc_partial_syn = devm_kzalloc(host->dev, size, GFP_KERNEL);
-       host->pmecc_si = devm_kzalloc(host->dev, size, GFP_KERNEL);
-       host->pmecc_lmu = devm_kzalloc(host->dev,
-                       (cap + 1) * sizeof(int16_t), GFP_KERNEL);
-       host->pmecc_smu = devm_kzalloc(host->dev,
-                       (cap + 2) * size, GFP_KERNEL);
-
-       size = (cap + 1) * sizeof(int);
-       host->pmecc_mu = devm_kzalloc(host->dev, size, GFP_KERNEL);
-       host->pmecc_dmu = devm_kzalloc(host->dev, size, GFP_KERNEL);
-       host->pmecc_delta = devm_kzalloc(host->dev, size, GFP_KERNEL);
-
-       if (!host->pmecc_partial_syn ||
-               !host->pmecc_si ||
-               !host->pmecc_lmu ||
-               !host->pmecc_smu ||
-               !host->pmecc_mu ||
-               !host->pmecc_dmu ||
-               !host->pmecc_delta)
-               return -ENOMEM;
-
-       return 0;
-}
-
-static void pmecc_gen_syndrome(struct mtd_info *mtd, int sector)
-{
-       struct nand_chip *nand_chip = mtd_to_nand(mtd);
-       struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
-       int i;
-       uint32_t value;
-
-       /* Fill odd syndromes */
-       for (i = 0; i < host->pmecc_corr_cap; i++) {
-               value = pmecc_readl_rem_relaxed(host->ecc, sector, i / 2);
-               if (i & 1)
-                       value >>= 16;
-               value &= 0xffff;
-               host->pmecc_partial_syn[(2 * i) + 1] = (int16_t)value;
-       }
-}
-
-static void pmecc_substitute(struct mtd_info *mtd)
-{
-       struct nand_chip *nand_chip = mtd_to_nand(mtd);
-       struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
-       int16_t __iomem *alpha_to = host->pmecc_alpha_to;
-       int16_t __iomem *index_of = host->pmecc_index_of;
-       int16_t *partial_syn = host->pmecc_partial_syn;
-       const int cap = host->pmecc_corr_cap;
-       int16_t *si;
-       int i, j;
-
-       /* si[] is a table that holds the current syndrome value,
-        * an element of that table belongs to the field
-        */
-       si = host->pmecc_si;
-
-       memset(&si[1], 0, sizeof(int16_t) * (2 * cap - 1));
-
-       /* Computation 2t syndromes based on S(x) */
-       /* Odd syndromes */
-       for (i = 1; i < 2 * cap; i += 2) {
-               for (j = 0; j < host->pmecc_degree; j++) {
-                       if (partial_syn[i] & ((unsigned short)0x1 << j))
-                               si[i] = readw_relaxed(alpha_to + i * j) ^ si[i];
-               }
-       }
-       /* Even syndrome = (Odd syndrome) ** 2 */
-       for (i = 2, j = 1; j <= cap; i = ++j << 1) {
-               if (si[j] == 0) {
-                       si[i] = 0;
-               } else {
-                       int16_t tmp;
-
-                       tmp = readw_relaxed(index_of + si[j]);
-                       tmp = (tmp * 2) % host->pmecc_cw_len;
-                       si[i] = readw_relaxed(alpha_to + tmp);
-               }
-       }
-
-       return;
-}
-
-static void pmecc_get_sigma(struct mtd_info *mtd)
-{
-       struct nand_chip *nand_chip = mtd_to_nand(mtd);
-       struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
-
-       int16_t *lmu = host->pmecc_lmu;
-       int16_t *si = host->pmecc_si;
-       int *mu = host->pmecc_mu;
-       int *dmu = host->pmecc_dmu;     /* Discrepancy */
-       int *delta = host->pmecc_delta; /* Delta order */
-       int cw_len = host->pmecc_cw_len;
-       const int16_t cap = host->pmecc_corr_cap;
-       const int num = 2 * cap + 1;
-       int16_t __iomem *index_of = host->pmecc_index_of;
-       int16_t __iomem *alpha_to = host->pmecc_alpha_to;
-       int i, j, k;
-       uint32_t dmu_0_count, tmp;
-       int16_t *smu = host->pmecc_smu;
-
-       /* index of largest delta */
-       int ro;
-       int largest;
-       int diff;
-
-       dmu_0_count = 0;
-
-       /* First Row */
-
-       /* Mu */
-       mu[0] = -1;
-
-       memset(smu, 0, sizeof(int16_t) * num);
-       smu[0] = 1;
-
-       /* discrepancy set to 1 */
-       dmu[0] = 1;
-       /* polynom order set to 0 */
-       lmu[0] = 0;
-       delta[0] = (mu[0] * 2 - lmu[0]) >> 1;
-
-       /* Second Row */
-
-       /* Mu */
-       mu[1] = 0;
-       /* Sigma(x) set to 1 */
-       memset(&smu[num], 0, sizeof(int16_t) * num);
-       smu[num] = 1;
-
-       /* discrepancy set to S1 */
-       dmu[1] = si[1];
-
-       /* polynom order set to 0 */
-       lmu[1] = 0;
-
-       delta[1] = (mu[1] * 2 - lmu[1]) >> 1;
-
-       /* Init the Sigma(x) last row */
-       memset(&smu[(cap + 1) * num], 0, sizeof(int16_t) * num);
-
-       for (i = 1; i <= cap; i++) {
-               mu[i + 1] = i << 1;
-               /* Begin Computing Sigma (Mu+1) and L(mu) */
-               /* check if discrepancy is set to 0 */
-               if (dmu[i] == 0) {
-                       dmu_0_count++;
-
-                       tmp = ((cap - (lmu[i] >> 1) - 1) / 2);
-                       if ((cap - (lmu[i] >> 1) - 1) & 0x1)
-                               tmp += 2;
-                       else
-                               tmp += 1;
-
-                       if (dmu_0_count == tmp) {
-                               for (j = 0; j <= (lmu[i] >> 1) + 1; j++)
-                                       smu[(cap + 1) * num + j] =
-                                                       smu[i * num + j];
-
-                               lmu[cap + 1] = lmu[i];
-                               return;
-                       }
-
-                       /* copy polynom */
-                       for (j = 0; j <= lmu[i] >> 1; j++)
-                               smu[(i + 1) * num + j] = smu[i * num + j];
-
-                       /* copy previous polynom order to the next */
-                       lmu[i + 1] = lmu[i];
-               } else {
-                       ro = 0;
-                       largest = -1;
-                       /* find largest delta with dmu != 0 */
-                       for (j = 0; j < i; j++) {
-                               if ((dmu[j]) && (delta[j] > largest)) {
-                                       largest = delta[j];
-                                       ro = j;
-                               }
-                       }
-
-                       /* compute difference */
-                       diff = (mu[i] - mu[ro]);
-
-                       /* Compute degree of the new smu polynomial */
-                       if ((lmu[i] >> 1) > ((lmu[ro] >> 1) + diff))
-                               lmu[i + 1] = lmu[i];
-                       else
-                               lmu[i + 1] = ((lmu[ro] >> 1) + diff) * 2;
-
-                       /* Init smu[i+1] with 0 */
-                       for (k = 0; k < num; k++)
-                               smu[(i + 1) * num + k] = 0;
-
-                       /* Compute smu[i+1] */
-                       for (k = 0; k <= lmu[ro] >> 1; k++) {
-                               int16_t a, b, c;
-
-                               if (!(smu[ro * num + k] && dmu[i]))
-                                       continue;
-                               a = readw_relaxed(index_of + dmu[i]);
-                               b = readw_relaxed(index_of + dmu[ro]);
-                               c = readw_relaxed(index_of + smu[ro * num + k]);
-                               tmp = a + (cw_len - b) + c;
-                               a = readw_relaxed(alpha_to + tmp % cw_len);
-                               smu[(i + 1) * num + (k + diff)] = a;
-                       }
-
-                       for (k = 0; k <= lmu[i] >> 1; k++)
-                               smu[(i + 1) * num + k] ^= smu[i * num + k];
-               }
-
-               /* End Computing Sigma (Mu+1) and L(mu) */
-               /* In either case compute delta */
-               delta[i + 1] = (mu[i + 1] * 2 - lmu[i + 1]) >> 1;
-
-               /* Do not compute discrepancy for the last iteration */
-               if (i >= cap)
-                       continue;
-
-               for (k = 0; k <= (lmu[i + 1] >> 1); k++) {
-                       tmp = 2 * (i - 1);
-                       if (k == 0) {
-                               dmu[i + 1] = si[tmp + 3];
-                       } else if (smu[(i + 1) * num + k] && si[tmp + 3 - k]) {
-                               int16_t a, b, c;
-                               a = readw_relaxed(index_of +
-                                               smu[(i + 1) * num + k]);
-                               b = si[2 * (i - 1) + 3 - k];
-                               c = readw_relaxed(index_of + b);
-                               tmp = a + c;
-                               tmp %= cw_len;
-                               dmu[i + 1] = readw_relaxed(alpha_to + tmp) ^
-                                       dmu[i + 1];
-                       }
-               }
-       }
-
-       return;
-}
-
-static int pmecc_err_location(struct mtd_info *mtd)
-{
-       struct nand_chip *nand_chip = mtd_to_nand(mtd);
-       struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
-       unsigned long end_time;
-       const int cap = host->pmecc_corr_cap;
-       const int num = 2 * cap + 1;
-       int sector_size = host->pmecc_sector_size;
-       int err_nbr = 0;        /* number of error */
-       int roots_nbr;          /* number of roots */
-       int i;
-       uint32_t val;
-       int16_t *smu = host->pmecc_smu;
-
-       pmerrloc_writel(host->pmerrloc_base, ELDIS, PMERRLOC_DISABLE);
-
-       for (i = 0; i <= host->pmecc_lmu[cap + 1] >> 1; i++) {
-               pmerrloc_writel_sigma_relaxed(host->pmerrloc_base, i,
-                                     smu[(cap + 1) * num + i]);
-               err_nbr++;
-       }
-
-       val = (err_nbr - 1) << 16;
-       if (sector_size == 1024)
-               val |= 1;
-
-       pmerrloc_writel(host->pmerrloc_base, ELCFG, val);
-       pmerrloc_writel(host->pmerrloc_base, ELEN,
-                       sector_size * 8 + host->pmecc_degree * cap);
-
-       end_time = jiffies + msecs_to_jiffies(PMECC_MAX_TIMEOUT_MS);
-       while (!(pmerrloc_readl_relaxed(host->pmerrloc_base, ELISR)
-                & PMERRLOC_CALC_DONE)) {
-               if (unlikely(time_after(jiffies, end_time))) {
-                       dev_err(host->dev, "PMECC: Timeout to calculate error location.\n");
-                       return -1;
-               }
-               cpu_relax();
-       }
-
-       roots_nbr = (pmerrloc_readl_relaxed(host->pmerrloc_base, ELISR)
-               & PMERRLOC_ERR_NUM_MASK) >> 8;
-       /* Number of roots == degree of smu hence <= cap */
-       if (roots_nbr == host->pmecc_lmu[cap + 1] >> 1)
-               return err_nbr - 1;
-
-       /* Number of roots does not match the degree of smu
-        * unable to correct error */
-       return -1;
-}
-
-static void pmecc_correct_data(struct mtd_info *mtd, uint8_t *buf, uint8_t *ecc,
-               int sector_num, int extra_bytes, int err_nbr)
-{
-       struct nand_chip *nand_chip = mtd_to_nand(mtd);
-       struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
-       int i = 0;
-       int byte_pos, bit_pos, sector_size, pos;
-       uint32_t tmp;
-       uint8_t err_byte;
-
-       sector_size = host->pmecc_sector_size;
-
-       while (err_nbr) {
-               tmp = pmerrloc_readl_el_relaxed(host->pmerrloc_el_base, i) - 1;
-               byte_pos = tmp / 8;
-               bit_pos  = tmp % 8;
-
-               if (byte_pos >= (sector_size + extra_bytes))
-                       BUG();  /* should never happen */
-
-               if (byte_pos < sector_size) {
-                       err_byte = *(buf + byte_pos);
-                       *(buf + byte_pos) ^= (1 << bit_pos);
-
-                       pos = sector_num * host->pmecc_sector_size + byte_pos;
-                       dev_dbg(host->dev, "Bit flip in data area, byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n",
-                               pos, bit_pos, err_byte, *(buf + byte_pos));
-               } else {
-                       struct mtd_oob_region oobregion;
-
-                       /* Bit flip in OOB area */
-                       tmp = sector_num * nand_chip->ecc.bytes
-                                       + (byte_pos - sector_size);
-                       err_byte = ecc[tmp];
-                       ecc[tmp] ^= (1 << bit_pos);
-
-                       mtd_ooblayout_ecc(mtd, 0, &oobregion);
-                       pos = tmp + oobregion.offset;
-                       dev_dbg(host->dev, "Bit flip in OOB, oob_byte_pos: %d, bit_pos: %d, 0x%02x -> 0x%02x\n",
-                               pos, bit_pos, err_byte, ecc[tmp]);
-               }
-
-               i++;
-               err_nbr--;
-       }
-
-       return;
-}
-
-static int pmecc_correction(struct mtd_info *mtd, u32 pmecc_stat, uint8_t *buf,
-       u8 *ecc)
-{
-       struct nand_chip *nand_chip = mtd_to_nand(mtd);
-       struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
-       int i, err_nbr;
-       uint8_t *buf_pos;
-       int max_bitflips = 0;
-
-       for (i = 0; i < nand_chip->ecc.steps; i++) {
-               err_nbr = 0;
-               if (pmecc_stat & 0x1) {
-                       buf_pos = buf + i * host->pmecc_sector_size;
-
-                       pmecc_gen_syndrome(mtd, i);
-                       pmecc_substitute(mtd);
-                       pmecc_get_sigma(mtd);
-
-                       err_nbr = pmecc_err_location(mtd);
-                       if (err_nbr >= 0) {
-                               pmecc_correct_data(mtd, buf_pos, ecc, i,
-                                                  nand_chip->ecc.bytes,
-                                                  err_nbr);
-                       } else if (!host->caps->pmecc_correct_erase_page) {
-                               u8 *ecc_pos = ecc + (i * nand_chip->ecc.bytes);
-
-                               /* Try to detect erased pages */
-                               err_nbr = nand_check_erased_ecc_chunk(buf_pos,
-                                                       host->pmecc_sector_size,
-                                                       ecc_pos,
-                                                       nand_chip->ecc.bytes,
-                                                       NULL, 0,
-                                                       nand_chip->ecc.strength);
-                       }
-
-                       if (err_nbr < 0) {
-                               dev_err(host->dev, "PMECC: Too many errors\n");
-                               mtd->ecc_stats.failed++;
-                               return -EIO;
-                       }
-
-                       mtd->ecc_stats.corrected += err_nbr;
-                       max_bitflips = max_t(int, max_bitflips, err_nbr);
-               }
-               pmecc_stat >>= 1;
-       }
-
-       return max_bitflips;
-}
-
-static void pmecc_enable(struct atmel_nand_host *host, int ecc_op)
-{
-       u32 val;
-
-       if (ecc_op != NAND_ECC_READ && ecc_op != NAND_ECC_WRITE) {
-               dev_err(host->dev, "atmel_nand: wrong pmecc operation type!");
-               return;
-       }
-
-       pmecc_writel(host->ecc, CTRL, PMECC_CTRL_RST);
-       pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE);
-       val = pmecc_readl_relaxed(host->ecc, CFG);
-
-       if (ecc_op == NAND_ECC_READ)
-               pmecc_writel(host->ecc, CFG, (val & ~PMECC_CFG_WRITE_OP)
-                       | PMECC_CFG_AUTO_ENABLE);
-       else
-               pmecc_writel(host->ecc, CFG, (val | PMECC_CFG_WRITE_OP)
-                       & ~PMECC_CFG_AUTO_ENABLE);
-
-       pmecc_writel(host->ecc, CTRL, PMECC_CTRL_ENABLE);
-       pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DATA);
-}
-
-static int atmel_nand_pmecc_read_page(struct mtd_info *mtd,
-       struct nand_chip *chip, uint8_t *buf, int oob_required, int page)
-{
-       struct atmel_nand_host *host = nand_get_controller_data(chip);
-       int eccsize = chip->ecc.size * chip->ecc.steps;
-       uint8_t *oob = chip->oob_poi;
-       uint32_t stat;
-       unsigned long end_time;
-       int bitflips = 0;
-
-       if (!host->nfc || !host->nfc->use_nfc_sram)
-               pmecc_enable(host, NAND_ECC_READ);
-
-       chip->read_buf(mtd, buf, eccsize);
-       chip->read_buf(mtd, oob, mtd->oobsize);
-
-       end_time = jiffies + msecs_to_jiffies(PMECC_MAX_TIMEOUT_MS);
-       while ((pmecc_readl_relaxed(host->ecc, SR) & PMECC_SR_BUSY)) {
-               if (unlikely(time_after(jiffies, end_time))) {
-                       dev_err(host->dev, "PMECC: Timeout to get error status.\n");
-                       return -EIO;
-               }
-               cpu_relax();
-       }
-
-       stat = pmecc_readl_relaxed(host->ecc, ISR);
-       if (stat != 0) {
-               struct mtd_oob_region oobregion;
-
-               mtd_ooblayout_ecc(mtd, 0, &oobregion);
-               bitflips = pmecc_correction(mtd, stat, buf,
-                                           &oob[oobregion.offset]);
-               if (bitflips < 0)
-                       /* uncorrectable errors */
-                       return 0;
-       }
-
-       return bitflips;
-}
-
-static int atmel_nand_pmecc_write_page(struct mtd_info *mtd,
-               struct nand_chip *chip, const uint8_t *buf, int oob_required,
-               int page)
-{
-       struct atmel_nand_host *host = nand_get_controller_data(chip);
-       struct mtd_oob_region oobregion = { };
-       int i, j, section = 0;
-       unsigned long end_time;
-
-       if (!host->nfc || !host->nfc->write_by_sram) {
-               pmecc_enable(host, NAND_ECC_WRITE);
-               chip->write_buf(mtd, (u8 *)buf, mtd->writesize);
-       }
-
-       end_time = jiffies + msecs_to_jiffies(PMECC_MAX_TIMEOUT_MS);
-       while ((pmecc_readl_relaxed(host->ecc, SR) & PMECC_SR_BUSY)) {
-               if (unlikely(time_after(jiffies, end_time))) {
-                       dev_err(host->dev, "PMECC: Timeout to get ECC value.\n");
-                       return -EIO;
-               }
-               cpu_relax();
-       }
-
-       for (i = 0; i < chip->ecc.steps; i++) {
-               for (j = 0; j < chip->ecc.bytes; j++) {
-                       if (!oobregion.length)
-                               mtd_ooblayout_ecc(mtd, section, &oobregion);
-
-                       chip->oob_poi[oobregion.offset] =
-                               pmecc_readb_ecc_relaxed(host->ecc, i, j);
-                       oobregion.length--;
-                       oobregion.offset++;
-                       section++;
-               }
-       }
-       chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
-
-       return 0;
-}
-
-static void atmel_pmecc_core_init(struct mtd_info *mtd)
-{
-       struct nand_chip *nand_chip = mtd_to_nand(mtd);
-       struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
-       int eccbytes = mtd_ooblayout_count_eccbytes(mtd);
-       uint32_t val = 0;
-       struct mtd_oob_region oobregion;
-
-       pmecc_writel(host->ecc, CTRL, PMECC_CTRL_RST);
-       pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE);
-
-       switch (host->pmecc_corr_cap) {
-       case 2:
-               val = PMECC_CFG_BCH_ERR2;
-               break;
-       case 4:
-               val = PMECC_CFG_BCH_ERR4;
-               break;
-       case 8:
-               val = PMECC_CFG_BCH_ERR8;
-               break;
-       case 12:
-               val = PMECC_CFG_BCH_ERR12;
-               break;
-       case 24:
-               val = PMECC_CFG_BCH_ERR24;
-               break;
-       case 32:
-               val = PMECC_CFG_BCH_ERR32;
-               break;
-       }
-
-       if (host->pmecc_sector_size == 512)
-               val |= PMECC_CFG_SECTOR512;
-       else if (host->pmecc_sector_size == 1024)
-               val |= PMECC_CFG_SECTOR1024;
-
-       switch (nand_chip->ecc.steps) {
-       case 1:
-               val |= PMECC_CFG_PAGE_1SECTOR;
-               break;
-       case 2:
-               val |= PMECC_CFG_PAGE_2SECTORS;
-               break;
-       case 4:
-               val |= PMECC_CFG_PAGE_4SECTORS;
-               break;
-       case 8:
-               val |= PMECC_CFG_PAGE_8SECTORS;
-               break;
-       }
-
-       val |= (PMECC_CFG_READ_OP | PMECC_CFG_SPARE_DISABLE
-               | PMECC_CFG_AUTO_DISABLE);
-       pmecc_writel(host->ecc, CFG, val);
-
-       pmecc_writel(host->ecc, SAREA, mtd->oobsize - 1);
-       mtd_ooblayout_ecc(mtd, 0, &oobregion);
-       pmecc_writel(host->ecc, SADDR, oobregion.offset);
-       pmecc_writel(host->ecc, EADDR,
-                    oobregion.offset + eccbytes - 1);
-       /* See datasheet about PMECC Clock Control Register */
-       pmecc_writel(host->ecc, CLK, 2);
-       pmecc_writel(host->ecc, IDR, 0xff);
-       pmecc_writel(host->ecc, CTRL, PMECC_CTRL_ENABLE);
-}
-
-/*
- * Get minimum ecc requirements from NAND.
- * If pmecc-cap, pmecc-sector-size in DTS are not specified, this function
- * will set them according to minimum ecc requirement. Otherwise, use the
- * value in DTS file.
- * return 0 if success. otherwise return error code.
- */
-static int pmecc_choose_ecc(struct atmel_nand_host *host,
-               int *cap, int *sector_size)
-{
-       /* Get minimum ECC requirements */
-       if (host->nand_chip.ecc_strength_ds) {
-               *cap = host->nand_chip.ecc_strength_ds;
-               *sector_size = host->nand_chip.ecc_step_ds;
-               dev_info(host->dev, "minimum ECC: %d bits in %d bytes\n",
-                               *cap, *sector_size);
-       } else {
-               *cap = 2;
-               *sector_size = 512;
-               dev_info(host->dev, "can't detect min. ECC, assume 2 bits in 512 bytes\n");
-       }
-
-       /* If device tree doesn't specify, use NAND's minimum ECC parameters */
-       if (host->pmecc_corr_cap == 0) {
-               if (*cap > host->caps->pmecc_max_correction)
-                       return -EINVAL;
-
-               /* use the most fitable ecc bits (the near bigger one ) */
-               if (*cap <= 2)
-                       host->pmecc_corr_cap = 2;
-               else if (*cap <= 4)
-                       host->pmecc_corr_cap = 4;
-               else if (*cap <= 8)
-                       host->pmecc_corr_cap = 8;
-               else if (*cap <= 12)
-                       host->pmecc_corr_cap = 12;
-               else if (*cap <= 24)
-                       host->pmecc_corr_cap = 24;
-               else if (*cap <= 32)
-                       host->pmecc_corr_cap = 32;
-               else
-                       return -EINVAL;
-       }
-       if (host->pmecc_sector_size == 0) {
-               /* use the most fitable sector size (the near smaller one ) */
-               if (*sector_size >= 1024)
-                       host->pmecc_sector_size = 1024;
-               else if (*sector_size >= 512)
-                       host->pmecc_sector_size = 512;
-               else
-                       return -EINVAL;
-       }
-       return 0;
-}
-
-static inline int deg(unsigned int poly)
-{
-       /* polynomial degree is the most-significant bit index */
-       return fls(poly) - 1;
-}
-
-static int build_gf_tables(int mm, unsigned int poly,
-               int16_t *index_of, int16_t *alpha_to)
-{
-       unsigned int i, x = 1;
-       const unsigned int k = 1 << deg(poly);
-       unsigned int nn = (1 << mm) - 1;
-
-       /* primitive polynomial must be of degree m */
-       if (k != (1u << mm))
-               return -EINVAL;
-
-       for (i = 0; i < nn; i++) {
-               alpha_to[i] = x;
-               index_of[x] = i;
-               if (i && (x == 1))
-                       /* polynomial is not primitive (a^i=1 with 0<i<2^m-1) */
-                       return -EINVAL;
-               x <<= 1;
-               if (x & k)
-                       x ^= poly;
-       }
-       alpha_to[nn] = 1;
-       index_of[0] = 0;
-
-       return 0;
-}
-
-static uint16_t *create_lookup_table(struct device *dev, int sector_size)
-{
-       int degree = (sector_size == 512) ?
-                       PMECC_GF_DIMENSION_13 :
-                       PMECC_GF_DIMENSION_14;
-       unsigned int poly = (sector_size == 512) ?
-                       PMECC_GF_13_PRIMITIVE_POLY :
-                       PMECC_GF_14_PRIMITIVE_POLY;
-       int table_size = (sector_size == 512) ?
-                       PMECC_LOOKUP_TABLE_SIZE_512 :
-                       PMECC_LOOKUP_TABLE_SIZE_1024;
-
-       int16_t *addr = devm_kzalloc(dev, 2 * table_size * sizeof(uint16_t),
-                       GFP_KERNEL);
-       if (addr && build_gf_tables(degree, poly, addr, addr + table_size))
-               return NULL;
-
-       return addr;
-}
-
-static int atmel_pmecc_nand_init_params(struct platform_device *pdev,
-                                        struct atmel_nand_host *host)
-{
-       struct nand_chip *nand_chip = &host->nand_chip;
-       struct mtd_info *mtd = nand_to_mtd(nand_chip);
-       struct resource *regs, *regs_pmerr, *regs_rom;
-       uint16_t *galois_table;
-       int cap, sector_size, err_no;
-
-       err_no = pmecc_choose_ecc(host, &cap, &sector_size);
-       if (err_no) {
-               dev_err(host->dev, "The NAND flash's ECC requirement are not support!");
-               return err_no;
-       }
-
-       if (cap > host->pmecc_corr_cap ||
-                       sector_size != host->pmecc_sector_size)
-               dev_info(host->dev, "WARNING: Be Caution! Using different PMECC parameters from Nand ONFI ECC reqirement.\n");
-
-       cap = host->pmecc_corr_cap;
-       sector_size = host->pmecc_sector_size;
-       host->pmecc_lookup_table_offset = (sector_size == 512) ?
-                       host->pmecc_lookup_table_offset_512 :
-                       host->pmecc_lookup_table_offset_1024;
-
-       dev_info(host->dev, "Initialize PMECC params, cap: %d, sector: %d\n",
-                cap, sector_size);
-
-       regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       if (!regs) {
-               dev_warn(host->dev,
-                       "Can't get I/O resource regs for PMECC controller, rolling back on software ECC\n");
-               nand_chip->ecc.mode = NAND_ECC_SOFT;
-               nand_chip->ecc.algo = NAND_ECC_HAMMING;
-               return 0;
-       }
-
-       host->ecc = devm_ioremap_resource(&pdev->dev, regs);
-       if (IS_ERR(host->ecc)) {
-               err_no = PTR_ERR(host->ecc);
-               goto err;
-       }
-
-       regs_pmerr = platform_get_resource(pdev, IORESOURCE_MEM, 2);
-       host->pmerrloc_base = devm_ioremap_resource(&pdev->dev, regs_pmerr);
-       if (IS_ERR(host->pmerrloc_base)) {
-               err_no = PTR_ERR(host->pmerrloc_base);
-               goto err;
-       }
-       host->pmerrloc_el_base = host->pmerrloc_base + ATMEL_PMERRLOC_SIGMAx +
-               (host->caps->pmecc_max_correction + 1) * 4;
-
-       if (!host->has_no_lookup_table) {
-               regs_rom = platform_get_resource(pdev, IORESOURCE_MEM, 3);
-               host->pmecc_rom_base = devm_ioremap_resource(&pdev->dev,
-                                                               regs_rom);
-               if (IS_ERR(host->pmecc_rom_base)) {
-                       dev_err(host->dev, "Can not get I/O resource for ROM, will build a lookup table in runtime!\n");
-                       host->has_no_lookup_table = true;
-               }
-       }
-
-       if (host->has_no_lookup_table) {
-               /* Build the look-up table in runtime */
-               galois_table = create_lookup_table(host->dev, sector_size);
-               if (!galois_table) {
-                       dev_err(host->dev, "Failed to build a lookup table in runtime!\n");
-                       err_no = -EINVAL;
-                       goto err;
-               }
-
-               host->pmecc_rom_base = (void __iomem *)galois_table;
-               host->pmecc_lookup_table_offset = 0;
-       }
-
-       nand_chip->ecc.size = sector_size;
-
-       /* set ECC page size and oob layout */
-       switch (mtd->writesize) {
-       case 512:
-       case 1024:
-       case 2048:
-       case 4096:
-       case 8192:
-               if (sector_size > mtd->writesize) {
-                       dev_err(host->dev, "pmecc sector size is bigger than the page size!\n");
-                       err_no = -EINVAL;
-                       goto err;
-               }
-
-               host->pmecc_degree = (sector_size == 512) ?
-                       PMECC_GF_DIMENSION_13 : PMECC_GF_DIMENSION_14;
-               host->pmecc_cw_len = (1 << host->pmecc_degree) - 1;
-               host->pmecc_alpha_to = pmecc_get_alpha_to(host);
-               host->pmecc_index_of = host->pmecc_rom_base +
-                       host->pmecc_lookup_table_offset;
-
-               nand_chip->ecc.strength = cap;
-               nand_chip->ecc.bytes = pmecc_get_ecc_bytes(cap, sector_size);
-               nand_chip->ecc.steps = mtd->writesize / sector_size;
-               nand_chip->ecc.total = nand_chip->ecc.bytes *
-                       nand_chip->ecc.steps;
-               if (nand_chip->ecc.total >
-                               mtd->oobsize - PMECC_OOB_RESERVED_BYTES) {
-                       dev_err(host->dev, "No room for ECC bytes\n");
-                       err_no = -EINVAL;
-                       goto err;
-               }
-
-               mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
-               break;
-       default:
-               dev_warn(host->dev,
-                       "Unsupported page size for PMECC, use Software ECC\n");
-               /* page size not handled by HW ECC */
-               /* switching back to soft ECC */
-               nand_chip->ecc.mode = NAND_ECC_SOFT;
-               nand_chip->ecc.algo = NAND_ECC_HAMMING;
-               return 0;
-       }
-
-       /* Allocate data for PMECC computation */
-       err_no = pmecc_data_alloc(host);
-       if (err_no) {
-               dev_err(host->dev,
-                               "Cannot allocate memory for PMECC computation!\n");
-               goto err;
-       }
-
-       nand_chip->options |= NAND_NO_SUBPAGE_WRITE;
-       nand_chip->ecc.read_page = atmel_nand_pmecc_read_page;
-       nand_chip->ecc.write_page = atmel_nand_pmecc_write_page;
-
-       atmel_pmecc_core_init(mtd);
-
-       return 0;
-
-err:
-       return err_no;
-}
-
-/*
- * Calculate HW ECC
- *
- * function called after a write
- *
- * mtd:        MTD block structure
- * dat:        raw data (unused)
- * ecc_code:   buffer for ECC
- */
-static int atmel_nand_calculate(struct mtd_info *mtd,
-               const u_char *dat, unsigned char *ecc_code)
-{
-       struct nand_chip *nand_chip = mtd_to_nand(mtd);
-       struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
-       unsigned int ecc_value;
-
-       /* get the first 2 ECC bytes */
-       ecc_value = ecc_readl(host->ecc, PR);
-
-       ecc_code[0] = ecc_value & 0xFF;
-       ecc_code[1] = (ecc_value >> 8) & 0xFF;
-
-       /* get the last 2 ECC bytes */
-       ecc_value = ecc_readl(host->ecc, NPR) & ATMEL_ECC_NPARITY;
-
-       ecc_code[2] = ecc_value & 0xFF;
-       ecc_code[3] = (ecc_value >> 8) & 0xFF;
-
-       return 0;
-}
-
-/*
- * HW ECC read page function
- *
- * mtd:        mtd info structure
- * chip:       nand chip info structure
- * buf:        buffer to store read data
- * oob_required:    caller expects OOB data read to chip->oob_poi
- */
-static int atmel_nand_read_page(struct mtd_info *mtd, struct nand_chip *chip,
-                               uint8_t *buf, int oob_required, int page)
-{
-       int eccsize = chip->ecc.size;
-       int eccbytes = chip->ecc.bytes;
-       uint8_t *p = buf;
-       uint8_t *oob = chip->oob_poi;
-       uint8_t *ecc_pos;
-       int stat;
-       unsigned int max_bitflips = 0;
-       struct mtd_oob_region oobregion = {};
-
-       /*
-        * Errata: ALE is incorrectly wired up to the ECC controller
-        * on the AP7000, so it will include the address cycles in the
-        * ECC calculation.
-        *
-        * Workaround: Reset the parity registers before reading the
-        * actual data.
-        */
-       struct atmel_nand_host *host = nand_get_controller_data(chip);
-       if (host->board.need_reset_workaround)
-               ecc_writel(host->ecc, CR, ATMEL_ECC_RST);
-
-       /* read the page */
-       chip->read_buf(mtd, p, eccsize);
-
-       /* move to ECC position if needed */
-       mtd_ooblayout_ecc(mtd, 0, &oobregion);
-       if (oobregion.offset != 0) {
-               /*
-                * This only works on large pages because the ECC controller
-                * waits for NAND_CMD_RNDOUTSTART after the NAND_CMD_RNDOUT.
-                * Anyway, for small pages, the first ECC byte is at offset
-                * 0 in the OOB area.
-                */
-               chip->cmdfunc(mtd, NAND_CMD_RNDOUT,
-                             mtd->writesize + oobregion.offset, -1);
-       }
-
-       /* the ECC controller needs to read the ECC just after the data */
-       ecc_pos = oob + oobregion.offset;
-       chip->read_buf(mtd, ecc_pos, eccbytes);
-
-       /* check if there's an error */
-       stat = chip->ecc.correct(mtd, p, oob, NULL);
-
-       if (stat < 0) {
-               mtd->ecc_stats.failed++;
-       } else {
-               mtd->ecc_stats.corrected += stat;
-               max_bitflips = max_t(unsigned int, max_bitflips, stat);
-       }
-
-       /* get back to oob start (end of page) */
-       chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1);
-
-       /* read the oob */
-       chip->read_buf(mtd, oob, mtd->oobsize);
-
-       return max_bitflips;
-}
-
-/*
- * HW ECC Correction
- *
- * function called after a read
- *
- * mtd:        MTD block structure
- * dat:        raw data read from the chip
- * read_ecc:   ECC from the chip (unused)
- * isnull:     unused
- *
- * Detect and correct a 1 bit error for a page
- */
-static int atmel_nand_correct(struct mtd_info *mtd, u_char *dat,
-               u_char *read_ecc, u_char *isnull)
-{
-       struct nand_chip *nand_chip = mtd_to_nand(mtd);
-       struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
-       unsigned int ecc_status;
-       unsigned int ecc_word, ecc_bit;
-
-       /* get the status from the Status Register */
-       ecc_status = ecc_readl(host->ecc, SR);
-
-       /* if there's no error */
-       if (likely(!(ecc_status & ATMEL_ECC_RECERR)))
-               return 0;
-
-       /* get error bit offset (4 bits) */
-       ecc_bit = ecc_readl(host->ecc, PR) & ATMEL_ECC_BITADDR;
-       /* get word address (12 bits) */
-       ecc_word = ecc_readl(host->ecc, PR) & ATMEL_ECC_WORDADDR;
-       ecc_word >>= 4;
-
-       /* if there are multiple errors */
-       if (ecc_status & ATMEL_ECC_MULERR) {
-               /* check if it is a freshly erased block
-                * (filled with 0xff) */
-               if ((ecc_bit == ATMEL_ECC_BITADDR)
-                               && (ecc_word == (ATMEL_ECC_WORDADDR >> 4))) {
-                       /* the block has just been erased, return OK */
-                       return 0;
-               }
-               /* it doesn't seems to be a freshly
-                * erased block.
-                * We can't correct so many errors */
-               dev_dbg(host->dev, "atmel_nand : multiple errors detected."
-                               " Unable to correct.\n");
-               return -EBADMSG;
-       }
-
-       /* if there's a single bit error : we can correct it */
-       if (ecc_status & ATMEL_ECC_ECCERR) {
-               /* there's nothing much to do here.
-                * the bit error is on the ECC itself.
-                */
-               dev_dbg(host->dev, "atmel_nand : one bit error on ECC code."
-                               " Nothing to correct\n");
-               return 0;
-       }
-
-       dev_dbg(host->dev, "atmel_nand : one bit error on data."
-                       " (word offset in the page :"
-                       " 0x%x bit offset : 0x%x)\n",
-                       ecc_word, ecc_bit);
-       /* correct the error */
-       if (nand_chip->options & NAND_BUSWIDTH_16) {
-               /* 16 bits words */
-               ((unsigned short *) dat)[ecc_word] ^= (1 << ecc_bit);
-       } else {
-               /* 8 bits words */
-               dat[ecc_word] ^= (1 << ecc_bit);
-       }
-       dev_dbg(host->dev, "atmel_nand : error corrected\n");
-       return 1;
-}
-
-/*
- * Enable HW ECC : unused on most chips
- */
-static void atmel_nand_hwctl(struct mtd_info *mtd, int mode)
-{
-       struct nand_chip *nand_chip = mtd_to_nand(mtd);
-       struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
-
-       if (host->board.need_reset_workaround)
-               ecc_writel(host->ecc, CR, ATMEL_ECC_RST);
-}
-
-static int atmel_of_init_ecc(struct atmel_nand_host *host,
-                            struct device_node *np)
-{
-       u32 offset[2];
-       u32 val;
-
-       host->has_pmecc = of_property_read_bool(np, "atmel,has-pmecc");
-
-       /* Not using PMECC */
-       if (!(host->nand_chip.ecc.mode == NAND_ECC_HW) || !host->has_pmecc)
-               return 0;
-
-       /* use PMECC, get correction capability, sector size and lookup
-        * table offset.
-        * If correction bits and sector size are not specified, then find
-        * them from NAND ONFI parameters.
-        */
-       if (of_property_read_u32(np, "atmel,pmecc-cap", &val) == 0) {
-               if (val > host->caps->pmecc_max_correction) {
-                       dev_err(host->dev,
-                               "Required ECC strength too high: %u max %u\n",
-                               val, host->caps->pmecc_max_correction);
-                       return -EINVAL;
-               }
-               if ((val != 2)  && (val != 4)  && (val != 8) &&
-                   (val != 12) && (val != 24) && (val != 32)) {
-                       dev_err(host->dev,
-                               "Required ECC strength not supported: %u\n",
-                               val);
-                       return -EINVAL;
-               }
-               host->pmecc_corr_cap = (u8)val;
-       }
-
-       if (of_property_read_u32(np, "atmel,pmecc-sector-size", &val) == 0) {
-               if ((val != 512) && (val != 1024)) {
-                       dev_err(host->dev,
-                               "Required ECC sector size not supported: %u\n",
-                               val);
-                       return -EINVAL;
-               }
-               host->pmecc_sector_size = (u16)val;
-       }
-
-       if (of_property_read_u32_array(np, "atmel,pmecc-lookup-table-offset",
-                       offset, 2) != 0) {
-               dev_err(host->dev, "Cannot get PMECC lookup table offset, will build a lookup table in runtime.\n");
-               host->has_no_lookup_table = true;
-               /* Will build a lookup table and initialize the offset later */
-               return 0;
-       }
-
-       if (!offset[0] && !offset[1]) {
-               dev_err(host->dev, "Invalid PMECC lookup table offset\n");
-               return -EINVAL;
-       }
-
-       host->pmecc_lookup_table_offset_512 = offset[0];
-       host->pmecc_lookup_table_offset_1024 = offset[1];
-
-       return 0;
-}
-
-static int atmel_of_init_port(struct atmel_nand_host *host,
-                             struct device_node *np)
-{
-       u32 val;
-       struct atmel_nand_data *board = &host->board;
-       enum of_gpio_flags flags = 0;
-
-       host->caps = (struct atmel_nand_caps *)
-               of_device_get_match_data(host->dev);
-
-       if (of_property_read_u32(np, "atmel,nand-addr-offset", &val) == 0) {
-               if (val >= 32) {
-                       dev_err(host->dev, "invalid addr-offset %u\n", val);
-                       return -EINVAL;
-               }
-               board->ale = val;
-       }
-
-       if (of_property_read_u32(np, "atmel,nand-cmd-offset", &val) == 0) {
-               if (val >= 32) {
-                       dev_err(host->dev, "invalid cmd-offset %u\n", val);
-                       return -EINVAL;
-               }
-               board->cle = val;
-       }
-
-       board->has_dma = of_property_read_bool(np, "atmel,nand-has-dma");
-
-       board->rdy_pin = of_get_gpio_flags(np, 0, &flags);
-       board->rdy_pin_active_low = (flags == OF_GPIO_ACTIVE_LOW);
-
-       board->enable_pin = of_get_gpio(np, 1);
-       board->det_pin = of_get_gpio(np, 2);
-
-       /* load the nfc driver if there is */
-       of_platform_populate(np, NULL, NULL, host->dev);
-
-       /*
-        * Initialize ECC mode to NAND_ECC_SOFT so that we have a correct value
-        * even if the nand-ecc-mode property is not defined.
-        */
-       host->nand_chip.ecc.mode = NAND_ECC_SOFT;
-       host->nand_chip.ecc.algo = NAND_ECC_HAMMING;
-
-       return 0;
-}
-
-static int atmel_hw_nand_init_params(struct platform_device *pdev,
-                                        struct atmel_nand_host *host)
-{
-       struct nand_chip *nand_chip = &host->nand_chip;
-       struct mtd_info *mtd = nand_to_mtd(nand_chip);
-       struct resource         *regs;
-
-       regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       if (!regs) {
-               dev_err(host->dev,
-                       "Can't get I/O resource regs, use software ECC\n");
-               nand_chip->ecc.mode = NAND_ECC_SOFT;
-               nand_chip->ecc.algo = NAND_ECC_HAMMING;
-               return 0;
-       }
-
-       host->ecc = devm_ioremap_resource(&pdev->dev, regs);
-       if (IS_ERR(host->ecc))
-               return PTR_ERR(host->ecc);
-
-       /* ECC is calculated for the whole page (1 step) */
-       nand_chip->ecc.size = mtd->writesize;
-
-       /* set ECC page size and oob layout */
-       switch (mtd->writesize) {
-       case 512:
-               mtd_set_ooblayout(mtd, &atmel_ooblayout_sp_ops);
-               ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_528);
-               break;
-       case 1024:
-               mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
-               ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_1056);
-               break;
-       case 2048:
-               mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
-               ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_2112);
-               break;
-       case 4096:
-               mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
-               ecc_writel(host->ecc, MR, ATMEL_ECC_PAGESIZE_4224);
-               break;
-       default:
-               /* page size not handled by HW ECC */
-               /* switching back to soft ECC */
-               nand_chip->ecc.mode = NAND_ECC_SOFT;
-               nand_chip->ecc.algo = NAND_ECC_HAMMING;
-               return 0;
-       }
-
-       /* set up for HW ECC */
-       nand_chip->ecc.calculate = atmel_nand_calculate;
-       nand_chip->ecc.correct = atmel_nand_correct;
-       nand_chip->ecc.hwctl = atmel_nand_hwctl;
-       nand_chip->ecc.read_page = atmel_nand_read_page;
-       nand_chip->ecc.bytes = 4;
-       nand_chip->ecc.strength = 1;
-
-       return 0;
-}
-
-static inline u32 nfc_read_status(struct atmel_nand_host *host)
-{
-       u32 err_flags = NFC_SR_DTOE | NFC_SR_UNDEF | NFC_SR_AWB | NFC_SR_ASE;
-       u32 nfc_status = nfc_readl(host->nfc->hsmc_regs, SR);
-
-       if (unlikely(nfc_status & err_flags)) {
-               if (nfc_status & NFC_SR_DTOE)
-                       dev_err(host->dev, "NFC: Waiting Nand R/B Timeout Error\n");
-               else if (nfc_status & NFC_SR_UNDEF)
-                       dev_err(host->dev, "NFC: Access Undefined Area Error\n");
-               else if (nfc_status & NFC_SR_AWB)
-                       dev_err(host->dev, "NFC: Access memory While NFC is busy\n");
-               else if (nfc_status & NFC_SR_ASE)
-                       dev_err(host->dev, "NFC: Access memory Size Error\n");
-       }
-
-       return nfc_status;
-}
-
-/* SMC interrupt service routine */
-static irqreturn_t hsmc_interrupt(int irq, void *dev_id)
-{
-       struct atmel_nand_host *host = dev_id;
-       u32 status, mask, pending;
-       irqreturn_t ret = IRQ_NONE;
-
-       status = nfc_read_status(host);
-       mask = nfc_readl(host->nfc->hsmc_regs, IMR);
-       pending = status & mask;
-
-       if (pending & NFC_SR_XFR_DONE) {
-               complete(&host->nfc->comp_xfer_done);
-               nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_XFR_DONE);
-               ret = IRQ_HANDLED;
-       }
-       if (pending & NFC_SR_RB_EDGE) {
-               complete(&host->nfc->comp_ready);
-               nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_RB_EDGE);
-               ret = IRQ_HANDLED;
-       }
-       if (pending & NFC_SR_CMD_DONE) {
-               complete(&host->nfc->comp_cmd_done);
-               nfc_writel(host->nfc->hsmc_regs, IDR, NFC_SR_CMD_DONE);
-               ret = IRQ_HANDLED;
-       }
-
-       return ret;
-}
-
-/* NFC(Nand Flash Controller) related functions */
-static void nfc_prepare_interrupt(struct atmel_nand_host *host, u32 flag)
-{
-       if (flag & NFC_SR_XFR_DONE)
-               init_completion(&host->nfc->comp_xfer_done);
-
-       if (flag & NFC_SR_RB_EDGE)
-               init_completion(&host->nfc->comp_ready);
-
-       if (flag & NFC_SR_CMD_DONE)
-               init_completion(&host->nfc->comp_cmd_done);
-
-       /* Enable interrupt that need to wait for */
-       nfc_writel(host->nfc->hsmc_regs, IER, flag);
-}
-
-static int nfc_wait_interrupt(struct atmel_nand_host *host, u32 flag)
-{
-       int i, index = 0;
-       struct completion *comp[3];     /* Support 3 interrupt completion */
-
-       if (flag & NFC_SR_XFR_DONE)
-               comp[index++] = &host->nfc->comp_xfer_done;
-
-       if (flag & NFC_SR_RB_EDGE)
-               comp[index++] = &host->nfc->comp_ready;
-
-       if (flag & NFC_SR_CMD_DONE)
-               comp[index++] = &host->nfc->comp_cmd_done;
-
-       if (index == 0) {
-               dev_err(host->dev, "Unknown interrupt flag: 0x%08x\n", flag);
-               return -EINVAL;
-       }
-
-       for (i = 0; i < index; i++) {
-               if (wait_for_completion_timeout(comp[i],
-                               msecs_to_jiffies(NFC_TIME_OUT_MS)))
-                       continue;       /* wait for next completion */
-               else
-                       goto err_timeout;
-       }
-
-       return 0;
-
-err_timeout:
-       dev_err(host->dev, "Time out to wait for interrupt: 0x%08x\n", flag);
-       /* Disable the interrupt as it is not handled by interrupt handler */
-       nfc_writel(host->nfc->hsmc_regs, IDR, flag);
-       return -ETIMEDOUT;
-}
-
-static int nfc_send_command(struct atmel_nand_host *host,
-       unsigned int cmd, unsigned int addr, unsigned char cycle0)
-{
-       unsigned long timeout;
-       u32 flag = NFC_SR_CMD_DONE;
-       flag |= cmd & NFCADDR_CMD_DATAEN ? NFC_SR_XFR_DONE : 0;
-
-       dev_dbg(host->dev,
-               "nfc_cmd: 0x%08x, addr1234: 0x%08x, cycle0: 0x%02x\n",
-               cmd, addr, cycle0);
-
-       timeout = jiffies + msecs_to_jiffies(NFC_TIME_OUT_MS);
-       while (nfc_readl(host->nfc->hsmc_regs, SR) & NFC_SR_BUSY) {
-               if (time_after(jiffies, timeout)) {
-                       dev_err(host->dev,
-                               "Time out to wait for NFC ready!\n");
-                       return -ETIMEDOUT;
-               }
-       }
-
-       nfc_prepare_interrupt(host, flag);
-       nfc_writel(host->nfc->hsmc_regs, CYCLE0, cycle0);
-       nfc_cmd_addr1234_writel(cmd, addr, host->nfc->base_cmd_regs);
-       return nfc_wait_interrupt(host, flag);
-}
-
-static int nfc_device_ready(struct mtd_info *mtd)
-{
-       u32 status, mask;
-       struct nand_chip *nand_chip = mtd_to_nand(mtd);
-       struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
-
-       status = nfc_read_status(host);
-       mask = nfc_readl(host->nfc->hsmc_regs, IMR);
-
-       /* The mask should be 0. If not we may lost interrupts */
-       if (unlikely(mask & status))
-               dev_err(host->dev, "Lost the interrupt flags: 0x%08x\n",
-                               mask & status);
-
-       return status & NFC_SR_RB_EDGE;
-}
-
-static void nfc_select_chip(struct mtd_info *mtd, int chip)
-{
-       struct nand_chip *nand_chip = mtd_to_nand(mtd);
-       struct atmel_nand_host *host = nand_get_controller_data(nand_chip);
-
-       if (chip == -1)
-               nfc_writel(host->nfc->hsmc_regs, CTRL, NFC_CTRL_DISABLE);
-       else
-               nfc_writel(host->nfc->hsmc_regs, CTRL, NFC_CTRL_ENABLE);
-}
-
-static int nfc_make_addr(struct mtd_info *mtd, int command, int column,
-               int page_addr, unsigned int *addr1234, unsigned int *cycle0)
-{
-       struct nand_chip *chip = mtd_to_nand(mtd);
-
-       int acycle = 0;
-       unsigned char addr_bytes[8];
-       int index = 0, bit_shift;
-
-       BUG_ON(addr1234 == NULL || cycle0 == NULL);
-
-       *cycle0 = 0;
-       *addr1234 = 0;
-
-       if (column != -1) {
-               if (chip->options & NAND_BUSWIDTH_16 &&
-                               !nand_opcode_8bits(command))
-                       column >>= 1;
-               addr_bytes[acycle++] = column & 0xff;
-               if (mtd->writesize > 512)
-                       addr_bytes[acycle++] = (column >> 8) & 0xff;
-       }
-
-       if (page_addr != -1) {
-               addr_bytes[acycle++] = page_addr & 0xff;
-               addr_bytes[acycle++] = (page_addr >> 8) & 0xff;
-               if (chip->chipsize > (128 << 20))
-                       addr_bytes[acycle++] = (page_addr >> 16) & 0xff;
-       }
-
-       if (acycle > 4)
-               *cycle0 = addr_bytes[index++];
-
-       for (bit_shift = 0; index < acycle; bit_shift += 8)
-               *addr1234 += addr_bytes[index++] << bit_shift;
-
-       /* return acycle in cmd register */
-       return acycle << NFCADDR_CMD_ACYCLE_BIT_POS;
-}
-
-static void nfc_nand_command(struct mtd_info *mtd, unsigned int command,
-                               int column, int page_addr)
-{
-       struct nand_chip *chip = mtd_to_nand(mtd);
-       struct atmel_nand_host *host = nand_get_controller_data(chip);
-       unsigned long timeout;
-       unsigned int nfc_addr_cmd = 0;
-
-       unsigned int cmd1 = command << NFCADDR_CMD_CMD1_BIT_POS;
-
-       /* Set default settings: no cmd2, no addr cycle. read from nand */
-       unsigned int cmd2 = 0;
-       unsigned int vcmd2 = 0;
-       int acycle = NFCADDR_CMD_ACYCLE_NONE;
-       int csid = NFCADDR_CMD_CSID_3;
-       int dataen = NFCADDR_CMD_DATADIS;
-       int nfcwr = NFCADDR_CMD_NFCRD;
-       unsigned int addr1234 = 0;
-       unsigned int cycle0 = 0;
-       bool do_addr = true;
-       host->nfc->data_in_sram = NULL;
-
-       dev_dbg(host->dev, "%s: cmd = 0x%02x, col = 0x%08x, page = 0x%08x\n",
-            __func__, command, column, page_addr);
-
-       switch (command) {
-       case NAND_CMD_RESET:
-               nfc_addr_cmd = cmd1 | acycle | csid | dataen | nfcwr;
-               nfc_send_command(host, nfc_addr_cmd, addr1234, cycle0);
-               udelay(chip->chip_delay);
-
-               nfc_nand_command(mtd, NAND_CMD_STATUS, -1, -1);
-               timeout = jiffies + msecs_to_jiffies(NFC_TIME_OUT_MS);
-               while (!(chip->read_byte(mtd) & NAND_STATUS_READY)) {
-                       if (time_after(jiffies, timeout)) {
-                               dev_err(host->dev,
-                                       "Time out to wait status ready!\n");
-                               break;
-                       }
-               }
-               return;
-       case NAND_CMD_STATUS:
-               do_addr = false;
-               break;
-       case NAND_CMD_PARAM:
-       case NAND_CMD_READID:
-               do_addr = false;
-               acycle = NFCADDR_CMD_ACYCLE_1;
-               if (column != -1)
-                       addr1234 = column;
-               break;
-       case NAND_CMD_RNDOUT:
-               cmd2 = NAND_CMD_RNDOUTSTART << NFCADDR_CMD_CMD2_BIT_POS;
-               vcmd2 = NFCADDR_CMD_VCMD2;
-               break;
-       case NAND_CMD_READ0:
-       case NAND_CMD_READOOB:
-               if (command == NAND_CMD_READOOB) {
-                       column += mtd->writesize;
-                       command = NAND_CMD_READ0; /* only READ0 is valid */
-                       cmd1 = command << NFCADDR_CMD_CMD1_BIT_POS;
-               }
-               if (host->nfc->use_nfc_sram) {
-                       /* Enable Data transfer to sram */
-                       dataen = NFCADDR_CMD_DATAEN;
-
-                       /* Need enable PMECC now, since NFC will transfer
-                        * data in bus after sending nfc read command.
-                        */
-                       if (chip->ecc.mode == NAND_ECC_HW && host->has_pmecc)
-                               pmecc_enable(host, NAND_ECC_READ);
-               }
-
-               cmd2 = NAND_CMD_READSTART << NFCADDR_CMD_CMD2_BIT_POS;
-               vcmd2 = NFCADDR_CMD_VCMD2;
-               break;
-       /* For prgramming command, the cmd need set to write enable */
-       case NAND_CMD_PAGEPROG:
-       case NAND_CMD_SEQIN:
-       case NAND_CMD_RNDIN:
-               nfcwr = NFCADDR_CMD_NFCWR;
-               if (host->nfc->will_write_sram && command == NAND_CMD_SEQIN)
-                       dataen = NFCADDR_CMD_DATAEN;
-               break;
-       default:
-               break;
-       }
-
-       if (do_addr)
-               acycle = nfc_make_addr(mtd, command, column, page_addr,
-                               &addr1234, &cycle0);
-
-       nfc_addr_cmd = cmd1 | cmd2 | vcmd2 | acycle | csid | dataen | nfcwr;
-       nfc_send_command(host, nfc_addr_cmd, addr1234, cycle0);
-
-       /*
-        * Program and erase have their own busy handlers status, sequential
-        * in, and deplete1 need no delay.
-        */
-       switch (command) {
-       case NAND_CMD_CACHEDPROG:
-       case NAND_CMD_PAGEPROG:
-       case NAND_CMD_ERASE1:
-       case NAND_CMD_ERASE2:
-       case NAND_CMD_RNDIN:
-       case NAND_CMD_STATUS:
-       case NAND_CMD_RNDOUT:
-       case NAND_CMD_SEQIN:
-       case NAND_CMD_READID:
-               return;
-
-       case NAND_CMD_READ0:
-               if (dataen == NFCADDR_CMD_DATAEN) {
-                       host->nfc->data_in_sram = host->nfc->sram_bank0 +
-                               nfc_get_sram_off(host);
-                       return;
-               }
-               /* fall through */
-       default:
-               nfc_prepare_interrupt(host, NFC_SR_RB_EDGE);
-               nfc_wait_interrupt(host, NFC_SR_RB_EDGE);
-       }
-}
-
-static int nfc_sram_write_page(struct mtd_info *mtd, struct nand_chip *chip,
-                       uint32_t offset, int data_len, const uint8_t *buf,
-                       int oob_required, int page, int cached, int raw)
-{
-       int cfg, len;
-       int status = 0;
-       struct atmel_nand_host *host = nand_get_controller_data(chip);
-       void *sram = host->nfc->sram_bank0 + nfc_get_sram_off(host);
-
-       /* Subpage write is not supported */
-       if (offset || (data_len < mtd->writesize))
-               return -EINVAL;
-
-       len = mtd->writesize;
-       /* Copy page data to sram that will write to nand via NFC */
-       if (use_dma) {
-               if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) != 0)
-                       /* Fall back to use cpu copy */
-                       memcpy(sram, buf, len);
-       } else {
-               memcpy(sram, buf, len);
-       }
-
-       cfg = nfc_readl(host->nfc->hsmc_regs, CFG);
-       if (unlikely(raw) && oob_required) {
-               memcpy(sram + len, chip->oob_poi, mtd->oobsize);
-               len += mtd->oobsize;
-               nfc_writel(host->nfc->hsmc_regs, CFG, cfg | NFC_CFG_WSPARE);
-       } else {
-               nfc_writel(host->nfc->hsmc_regs, CFG, cfg & ~NFC_CFG_WSPARE);
-       }
-
-       if (chip->ecc.mode == NAND_ECC_HW && host->has_pmecc)
-               /*
-                * When use NFC sram, need set up PMECC before send
-                * NAND_CMD_SEQIN command. Since when the nand command
-                * is sent, nfc will do transfer from sram and nand.
-                */
-               pmecc_enable(host, NAND_ECC_WRITE);
-
-       host->nfc->will_write_sram = true;
-       chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
-       host->nfc->will_write_sram = false;
-
-       if (likely(!raw))
-               /* Need to write ecc into oob */
-               status = chip->ecc.write_page(mtd, chip, buf, oob_required,
-                                             page);
-
-       if (status < 0)
-               return status;
-
-       chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
-       status = chip->waitfunc(mtd, chip);
-
-       if ((status & NAND_STATUS_FAIL) && (chip->errstat))
-               status = chip->errstat(mtd, chip, FL_WRITING, status, page);
-
-       if (status & NAND_STATUS_FAIL)
-               return -EIO;
-
-       return 0;
-}
-
-static int nfc_sram_init(struct mtd_info *mtd)
-{
-       struct nand_chip *chip = mtd_to_nand(mtd);
-       struct atmel_nand_host *host = nand_get_controller_data(chip);
-       int res = 0;
-
-       /* Initialize the NFC CFG register */
-       unsigned int cfg_nfc = 0;
-
-       /* set page size and oob layout */
-       switch (mtd->writesize) {
-       case 512:
-               cfg_nfc = NFC_CFG_PAGESIZE_512;
-               break;
-       case 1024:
-               cfg_nfc = NFC_CFG_PAGESIZE_1024;
-               break;
-       case 2048:
-               cfg_nfc = NFC_CFG_PAGESIZE_2048;
-               break;
-       case 4096:
-               cfg_nfc = NFC_CFG_PAGESIZE_4096;
-               break;
-       case 8192:
-               cfg_nfc = NFC_CFG_PAGESIZE_8192;
-               break;
-       default:
-               dev_err(host->dev, "Unsupported page size for NFC.\n");
-               res = -ENXIO;
-               return res;
-       }
-
-       /* oob bytes size = (NFCSPARESIZE + 1) * 4
-        * Max support spare size is 512 bytes. */
-       cfg_nfc |= (((mtd->oobsize / 4) - 1) << NFC_CFG_NFC_SPARESIZE_BIT_POS
-               & NFC_CFG_NFC_SPARESIZE);
-       /* default set a max timeout */
-       cfg_nfc |= NFC_CFG_RSPARE |
-                       NFC_CFG_NFC_DTOCYC | NFC_CFG_NFC_DTOMUL;
-
-       nfc_writel(host->nfc->hsmc_regs, CFG, cfg_nfc);
-
-       host->nfc->will_write_sram = false;
-       nfc_set_sram_bank(host, 0);
-
-       /* Use Write page with NFC SRAM only for PMECC or ECC NONE. */
-       if (host->nfc->write_by_sram) {
-               if ((chip->ecc.mode == NAND_ECC_HW && host->has_pmecc) ||
-                               chip->ecc.mode == NAND_ECC_NONE)
-                       chip->write_page = nfc_sram_write_page;
-               else
-                       host->nfc->write_by_sram = false;
-       }
-
-       dev_info(host->dev, "Using NFC Sram read %s\n",
-                       host->nfc->write_by_sram ? "and write" : "");
-       return 0;
-}
-
-static struct platform_driver atmel_nand_nfc_driver;
-/*
- * Probe for the NAND device.
- */
-static int atmel_nand_probe(struct platform_device *pdev)
-{
-       struct atmel_nand_host *host;
-       struct mtd_info *mtd;
-       struct nand_chip *nand_chip;
-       struct resource *mem;
-       int res, irq;
-
-       /* Allocate memory for the device structure (and zero it) */
-       host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
-       if (!host)
-               return -ENOMEM;
-
-       res = platform_driver_register(&atmel_nand_nfc_driver);
-       if (res)
-               dev_err(&pdev->dev, "atmel_nand: can't register NFC driver\n");
-
-       mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       host->io_base = devm_ioremap_resource(&pdev->dev, mem);
-       if (IS_ERR(host->io_base)) {
-               res = PTR_ERR(host->io_base);
-               goto err_nand_ioremap;
-       }
-       host->io_phys = (dma_addr_t)mem->start;
-
-       nand_chip = &host->nand_chip;
-       mtd = nand_to_mtd(nand_chip);
-       host->dev = &pdev->dev;
-       if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) {
-               nand_set_flash_node(nand_chip, pdev->dev.of_node);
-               /* Only when CONFIG_OF is enabled of_node can be parsed */
-               res = atmel_of_init_port(host, pdev->dev.of_node);
-               if (res)
-                       goto err_nand_ioremap;
-       } else {
-               memcpy(&host->board, dev_get_platdata(&pdev->dev),
-                      sizeof(struct atmel_nand_data));
-               nand_chip->ecc.mode = host->board.ecc_mode;
-
-               /*
-                * When using software ECC every supported avr32 board means
-                * Hamming algorithm. If that ever changes we'll need to add
-                * ecc_algo field to the struct atmel_nand_data.
-                */
-               if (nand_chip->ecc.mode == NAND_ECC_SOFT)
-                       nand_chip->ecc.algo = NAND_ECC_HAMMING;
-
-               /* 16-bit bus width */
-               if (host->board.bus_width_16)
-                       nand_chip->options |= NAND_BUSWIDTH_16;
-       }
-
-        /* link the private data structures */
-       nand_set_controller_data(nand_chip, host);
-       mtd->dev.parent = &pdev->dev;
-
-       /* Set address of NAND IO lines */
-       nand_chip->IO_ADDR_R = host->io_base;
-       nand_chip->IO_ADDR_W = host->io_base;
-
-       if (nand_nfc.is_initialized) {
-               /* NFC driver is probed and initialized */
-               host->nfc = &nand_nfc;
-
-               nand_chip->select_chip = nfc_select_chip;
-               nand_chip->dev_ready = nfc_device_ready;
-               nand_chip->cmdfunc = nfc_nand_command;
-
-               /* Initialize the interrupt for NFC */
-               irq = platform_get_irq(pdev, 0);
-               if (irq < 0) {
-                       dev_err(host->dev, "Cannot get HSMC irq!\n");
-                       res = irq;
-                       goto err_nand_ioremap;
-               }
-
-               res = devm_request_irq(&pdev->dev, irq, hsmc_interrupt,
-                               0, "hsmc", host);
-               if (res) {
-                       dev_err(&pdev->dev, "Unable to request HSMC irq %d\n",
-                               irq);
-                       goto err_nand_ioremap;
-               }
-       } else {
-               res = atmel_nand_set_enable_ready_pins(mtd);
-               if (res)
-                       goto err_nand_ioremap;
-
-               nand_chip->cmd_ctrl = atmel_nand_cmd_ctrl;
-       }
-
-       nand_chip->chip_delay = 40;             /* 40us command delay time */
-
-
-       nand_chip->read_buf = atmel_read_buf;
-       nand_chip->write_buf = atmel_write_buf;
-
-       platform_set_drvdata(pdev, host);
-       atmel_nand_enable(host);
-
-       if (gpio_is_valid(host->board.det_pin)) {
-               res = devm_gpio_request(&pdev->dev,
-                               host->board.det_pin, "nand_det");
-               if (res < 0) {
-                       dev_err(&pdev->dev,
-                               "can't request det gpio %d\n",
-                               host->board.det_pin);
-                       goto err_no_card;
-               }
-
-               res = gpio_direction_input(host->board.det_pin);
-               if (res < 0) {
-                       dev_err(&pdev->dev,
-                               "can't request input direction det gpio %d\n",
-                               host->board.det_pin);
-                       goto err_no_card;
-               }
-
-               if (gpio_get_value(host->board.det_pin)) {
-                       dev_info(&pdev->dev, "No SmartMedia card inserted.\n");
-                       res = -ENXIO;
-                       goto err_no_card;
-               }
-       }
-
-       if (!host->board.has_dma)
-               use_dma = 0;
-
-       if (use_dma) {
-               dma_cap_mask_t mask;
-
-               dma_cap_zero(mask);
-               dma_cap_set(DMA_MEMCPY, mask);
-               host->dma_chan = dma_request_channel(mask, NULL, NULL);
-               if (!host->dma_chan) {
-                       dev_err(host->dev, "Failed to request DMA channel\n");
-                       use_dma = 0;
-               }
-       }
-       if (use_dma)
-               dev_info(host->dev, "Using %s for DMA transfers.\n",
-                                       dma_chan_name(host->dma_chan));
-       else
-               dev_info(host->dev, "No DMA support for NAND access.\n");
-
-       /* first scan to find the device and get the page size */
-       res = nand_scan_ident(mtd, 1, NULL);
-       if (res)
-               goto err_scan_ident;
-
-       if (host->board.on_flash_bbt || on_flash_bbt)
-               nand_chip->bbt_options |= NAND_BBT_USE_FLASH;
-
-       if (nand_chip->bbt_options & NAND_BBT_USE_FLASH)
-               dev_info(&pdev->dev, "Use On Flash BBT\n");
-
-       if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) {
-               res = atmel_of_init_ecc(host, pdev->dev.of_node);
-               if (res)
-                       goto err_hw_ecc;
-       }
-
-       if (nand_chip->ecc.mode == NAND_ECC_HW) {
-               if (host->has_pmecc)
-                       res = atmel_pmecc_nand_init_params(pdev, host);
-               else
-                       res = atmel_hw_nand_init_params(pdev, host);
-
-               if (res != 0)
-                       goto err_hw_ecc;
-       }
-
-       /* initialize the nfc configuration register */
-       if (host->nfc && host->nfc->use_nfc_sram) {
-               res = nfc_sram_init(mtd);
-               if (res) {
-                       host->nfc->use_nfc_sram = false;
-                       dev_err(host->dev, "Disable use nfc sram for data transfer.\n");
-               }
-       }
-
-       /* second phase scan */
-       res = nand_scan_tail(mtd);
-       if (res)
-               goto err_scan_tail;
-
-       mtd->name = "atmel_nand";
-       res = mtd_device_register(mtd, host->board.parts,
-                                 host->board.num_parts);
-       if (!res)
-               return res;
-
-err_scan_tail:
-       if (host->has_pmecc && host->nand_chip.ecc.mode == NAND_ECC_HW)
-               pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE);
-err_hw_ecc:
-err_scan_ident:
-err_no_card:
-       atmel_nand_disable(host);
-       if (host->dma_chan)
-               dma_release_channel(host->dma_chan);
-err_nand_ioremap:
-       return res;
-}
-
-/*
- * Remove a NAND device.
- */
-static int atmel_nand_remove(struct platform_device *pdev)
-{
-       struct atmel_nand_host *host = platform_get_drvdata(pdev);
-       struct mtd_info *mtd = nand_to_mtd(&host->nand_chip);
-
-       nand_release(mtd);
-
-       atmel_nand_disable(host);
-
-       if (host->has_pmecc && host->nand_chip.ecc.mode == NAND_ECC_HW) {
-               pmecc_writel(host->ecc, CTRL, PMECC_CTRL_DISABLE);
-               pmerrloc_writel(host->pmerrloc_base, ELDIS,
-                               PMERRLOC_DISABLE);
-       }
-
-       if (host->dma_chan)
-               dma_release_channel(host->dma_chan);
-
-       platform_driver_unregister(&atmel_nand_nfc_driver);
-
-       return 0;
-}
-
-/*
- * AT91RM9200 does not have PMECC or PMECC Errloc peripherals for
- * BCH ECC. Combined with the "atmel,has-pmecc", it is used to describe
- * devices from the SAM9 family that have those.
- */
-static const struct atmel_nand_caps at91rm9200_caps = {
-       .pmecc_correct_erase_page = false,
-       .pmecc_max_correction = 24,
-};
-
-static const struct atmel_nand_caps sama5d4_caps = {
-       .pmecc_correct_erase_page = true,
-       .pmecc_max_correction = 24,
-};
-
-/*
- * The PMECC Errloc controller starting in SAMA5D2 is not compatible,
- * as the increased correction strength requires more registers.
- */
-static const struct atmel_nand_caps sama5d2_caps = {
-       .pmecc_correct_erase_page = true,
-       .pmecc_max_correction = 32,
-};
-
-static const struct of_device_id atmel_nand_dt_ids[] = {
-       { .compatible = "atmel,at91rm9200-nand", .data = &at91rm9200_caps },
-       { .compatible = "atmel,sama5d4-nand", .data = &sama5d4_caps },
-       { .compatible = "atmel,sama5d2-nand", .data = &sama5d2_caps },
-       { /* sentinel */ }
-};
-
-MODULE_DEVICE_TABLE(of, atmel_nand_dt_ids);
-
-static int atmel_nand_nfc_probe(struct platform_device *pdev)
-{
-       struct atmel_nfc *nfc = &nand_nfc;
-       struct resource *nfc_cmd_regs, *nfc_hsmc_regs, *nfc_sram;
-       int ret;
-
-       nfc_cmd_regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       nfc->base_cmd_regs = devm_ioremap_resource(&pdev->dev, nfc_cmd_regs);
-       if (IS_ERR(nfc->base_cmd_regs))
-               return PTR_ERR(nfc->base_cmd_regs);
-
-       nfc_hsmc_regs = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-       nfc->hsmc_regs = devm_ioremap_resource(&pdev->dev, nfc_hsmc_regs);
-       if (IS_ERR(nfc->hsmc_regs))
-               return PTR_ERR(nfc->hsmc_regs);
-
-       nfc_sram = platform_get_resource(pdev, IORESOURCE_MEM, 2);
-       if (nfc_sram) {
-               nfc->sram_bank0 = (void * __force)
-                               devm_ioremap_resource(&pdev->dev, nfc_sram);
-               if (IS_ERR(nfc->sram_bank0)) {
-                       dev_warn(&pdev->dev, "Fail to ioremap the NFC sram with error: %ld. So disable NFC sram.\n",
-                                       PTR_ERR(nfc->sram_bank0));
-               } else {
-                       nfc->use_nfc_sram = true;
-                       nfc->sram_bank0_phys = (dma_addr_t)nfc_sram->start;
-
-                       if (pdev->dev.of_node)
-                               nfc->write_by_sram = of_property_read_bool(
-                                               pdev->dev.of_node,
-                                               "atmel,write-by-sram");
-               }
-       }
-
-       nfc_writel(nfc->hsmc_regs, IDR, 0xffffffff);
-       nfc_readl(nfc->hsmc_regs, SR);  /* clear the NFC_SR */
-
-       nfc->clk = devm_clk_get(&pdev->dev, NULL);
-       if (!IS_ERR(nfc->clk)) {
-               ret = clk_prepare_enable(nfc->clk);
-               if (ret)
-                       return ret;
-       } else {
-               dev_warn(&pdev->dev, "NFC clock missing, update your Device Tree");
-       }
-
-       nfc->is_initialized = true;
-       dev_info(&pdev->dev, "NFC is probed.\n");
-
-       return 0;
-}
-
-static int atmel_nand_nfc_remove(struct platform_device *pdev)
-{
-       struct atmel_nfc *nfc = &nand_nfc;
-
-       if (!IS_ERR(nfc->clk))
-               clk_disable_unprepare(nfc->clk);
-
-       return 0;
-}
-
-static const struct of_device_id atmel_nand_nfc_match[] = {
-       { .compatible = "atmel,sama5d3-nfc" },
-       { /* sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, atmel_nand_nfc_match);
-
-static struct platform_driver atmel_nand_nfc_driver = {
-       .driver = {
-               .name = "atmel_nand_nfc",
-               .of_match_table = of_match_ptr(atmel_nand_nfc_match),
-       },
-       .probe = atmel_nand_nfc_probe,
-       .remove = atmel_nand_nfc_remove,
-};
-
-static struct platform_driver atmel_nand_driver = {
-       .probe          = atmel_nand_probe,
-       .remove         = atmel_nand_remove,
-       .driver         = {
-               .name   = "atmel_nand",
-               .of_match_table = of_match_ptr(atmel_nand_dt_ids),
-       },
-};
-
-module_platform_driver(atmel_nand_driver);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Rick Bronson");
-MODULE_DESCRIPTION("NAND/SmartMedia driver for AT91 / AVR32");
-MODULE_ALIAS("platform:atmel_nand");
diff --git a/drivers/mtd/nand/atmel_nand_ecc.h b/drivers/mtd/nand/atmel_nand_ecc.h
deleted file mode 100644 (file)
index 834d694..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Error Corrected Code Controller (ECC) - System peripherals regsters.
- * Based on AT91SAM9260 datasheet revision B.
- *
- * Copyright (C) 2007 Andrew Victor
- * Copyright (C) 2007 - 2012 Atmel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#ifndef ATMEL_NAND_ECC_H
-#define ATMEL_NAND_ECC_H
-
-#define ATMEL_ECC_CR           0x00                    /* Control register */
-#define                ATMEL_ECC_RST           (1 << 0)                /* Reset parity */
-
-#define ATMEL_ECC_MR           0x04                    /* Mode register */
-#define                ATMEL_ECC_PAGESIZE      (3 << 0)                /* Page Size */
-#define                        ATMEL_ECC_PAGESIZE_528          (0)
-#define                        ATMEL_ECC_PAGESIZE_1056         (1)
-#define                        ATMEL_ECC_PAGESIZE_2112         (2)
-#define                        ATMEL_ECC_PAGESIZE_4224         (3)
-
-#define ATMEL_ECC_SR           0x08                    /* Status register */
-#define                ATMEL_ECC_RECERR                (1 << 0)                /* Recoverable Error */
-#define                ATMEL_ECC_ECCERR                (1 << 1)                /* ECC Single Bit Error */
-#define                ATMEL_ECC_MULERR                (1 << 2)                /* Multiple Errors */
-
-#define ATMEL_ECC_PR           0x0c                    /* Parity register */
-#define                ATMEL_ECC_BITADDR       (0xf << 0)              /* Bit Error Address */
-#define                ATMEL_ECC_WORDADDR      (0xfff << 4)            /* Word Error Address */
-
-#define ATMEL_ECC_NPR          0x10                    /* NParity register */
-#define                ATMEL_ECC_NPARITY       (0xffff << 0)           /* NParity */
-
-/* PMECC Register Definitions */
-#define ATMEL_PMECC_CFG                        0x000   /* Configuration Register */
-#define                PMECC_CFG_BCH_ERR2              (0 << 0)
-#define                PMECC_CFG_BCH_ERR4              (1 << 0)
-#define                PMECC_CFG_BCH_ERR8              (2 << 0)
-#define                PMECC_CFG_BCH_ERR12             (3 << 0)
-#define                PMECC_CFG_BCH_ERR24             (4 << 0)
-#define                PMECC_CFG_BCH_ERR32             (5 << 0)
-
-#define                PMECC_CFG_SECTOR512             (0 << 4)
-#define                PMECC_CFG_SECTOR1024            (1 << 4)
-
-#define                PMECC_CFG_PAGE_1SECTOR          (0 << 8)
-#define                PMECC_CFG_PAGE_2SECTORS         (1 << 8)
-#define                PMECC_CFG_PAGE_4SECTORS         (2 << 8)
-#define                PMECC_CFG_PAGE_8SECTORS         (3 << 8)
-
-#define                PMECC_CFG_READ_OP               (0 << 12)
-#define                PMECC_CFG_WRITE_OP              (1 << 12)
-
-#define                PMECC_CFG_SPARE_ENABLE          (1 << 16)
-#define                PMECC_CFG_SPARE_DISABLE         (0 << 16)
-
-#define                PMECC_CFG_AUTO_ENABLE           (1 << 20)
-#define                PMECC_CFG_AUTO_DISABLE          (0 << 20)
-
-#define ATMEL_PMECC_SAREA              0x004   /* Spare area size */
-#define ATMEL_PMECC_SADDR              0x008   /* PMECC starting address */
-#define ATMEL_PMECC_EADDR              0x00c   /* PMECC ending address */
-#define ATMEL_PMECC_CLK                        0x010   /* PMECC clock control */
-#define                PMECC_CLK_133MHZ                (2 << 0)
-
-#define ATMEL_PMECC_CTRL               0x014   /* PMECC control register */
-#define                PMECC_CTRL_RST                  (1 << 0)
-#define                PMECC_CTRL_DATA                 (1 << 1)
-#define                PMECC_CTRL_USER                 (1 << 2)
-#define                PMECC_CTRL_ENABLE               (1 << 4)
-#define                PMECC_CTRL_DISABLE              (1 << 5)
-
-#define ATMEL_PMECC_SR                 0x018   /* PMECC status register */
-#define                PMECC_SR_BUSY                   (1 << 0)
-#define                PMECC_SR_ENABLE                 (1 << 4)
-
-#define ATMEL_PMECC_IER                        0x01c   /* PMECC interrupt enable */
-#define                PMECC_IER_ENABLE                (1 << 0)
-#define ATMEL_PMECC_IDR                        0x020   /* PMECC interrupt disable */
-#define                PMECC_IER_DISABLE               (1 << 0)
-#define ATMEL_PMECC_IMR                        0x024   /* PMECC interrupt mask */
-#define                PMECC_IER_MASK                  (1 << 0)
-#define ATMEL_PMECC_ISR                        0x028   /* PMECC interrupt status */
-#define ATMEL_PMECC_ECCx               0x040   /* PMECC ECC x */
-#define ATMEL_PMECC_REMx               0x240   /* PMECC REM x */
-
-/* PMERRLOC Register Definitions */
-#define ATMEL_PMERRLOC_ELCFG           0x000   /* Error location config */
-#define                PMERRLOC_ELCFG_SECTOR_512       (0 << 0)
-#define                PMERRLOC_ELCFG_SECTOR_1024      (1 << 0)
-#define                PMERRLOC_ELCFG_NUM_ERRORS(n)    ((n) << 16)
-
-#define ATMEL_PMERRLOC_ELPRIM          0x004   /* Error location primitive */
-#define ATMEL_PMERRLOC_ELEN            0x008   /* Error location enable */
-#define ATMEL_PMERRLOC_ELDIS           0x00c   /* Error location disable */
-#define                PMERRLOC_DISABLE                (1 << 0)
-
-#define ATMEL_PMERRLOC_ELSR            0x010   /* Error location status */
-#define                PMERRLOC_ELSR_BUSY              (1 << 0)
-#define ATMEL_PMERRLOC_ELIER           0x014   /* Error location int enable */
-#define ATMEL_PMERRLOC_ELIDR           0x018   /* Error location int disable */
-#define ATMEL_PMERRLOC_ELIMR           0x01c   /* Error location int mask */
-#define ATMEL_PMERRLOC_ELISR           0x020   /* Error location int status */
-#define                PMERRLOC_ERR_NUM_MASK           (0x1f << 8)
-#define                PMERRLOC_CALC_DONE              (1 << 0)
-#define ATMEL_PMERRLOC_SIGMAx          0x028   /* Error location SIGMA x */
-
-/*
- * The ATMEL_PMERRLOC_ELx register location depends from the number of
- * bits corrected by the PMECC controller. Do not use it.
- */
-
-/* Register access macros for PMECC */
-#define pmecc_readl_relaxed(addr, reg) \
-       readl_relaxed((addr) + ATMEL_PMECC_##reg)
-
-#define pmecc_writel(addr, reg, value) \
-       writel((value), (addr) + ATMEL_PMECC_##reg)
-
-#define pmecc_readb_ecc_relaxed(addr, sector, n) \
-       readb_relaxed((addr) + ATMEL_PMECC_ECCx + ((sector) * 0x40) + (n))
-
-#define pmecc_readl_rem_relaxed(addr, sector, n) \
-       readl_relaxed((addr) + ATMEL_PMECC_REMx + ((sector) * 0x40) + ((n) * 4))
-
-#define pmerrloc_readl_relaxed(addr, reg) \
-       readl_relaxed((addr) + ATMEL_PMERRLOC_##reg)
-
-#define pmerrloc_writel(addr, reg, value) \
-       writel((value), (addr) + ATMEL_PMERRLOC_##reg)
-
-#define pmerrloc_writel_sigma_relaxed(addr, n, value) \
-       writel_relaxed((value), (addr) + ATMEL_PMERRLOC_SIGMAx + ((n) * 4))
-
-#define pmerrloc_readl_sigma_relaxed(addr, n) \
-       readl_relaxed((addr) + ATMEL_PMERRLOC_SIGMAx + ((n) * 4))
-
-#define pmerrloc_readl_el_relaxed(addr, n) \
-       readl_relaxed((addr) + ((n) * 4))
-
-/* Galois field dimension */
-#define PMECC_GF_DIMENSION_13                  13
-#define PMECC_GF_DIMENSION_14                  14
-
-/* Primitive Polynomial used by PMECC */
-#define PMECC_GF_13_PRIMITIVE_POLY             0x201b
-#define PMECC_GF_14_PRIMITIVE_POLY             0x4443
-
-#define PMECC_LOOKUP_TABLE_SIZE_512            0x2000
-#define PMECC_LOOKUP_TABLE_SIZE_1024           0x4000
-
-/* Time out value for reading PMECC status register */
-#define PMECC_MAX_TIMEOUT_MS                   100
-
-/* Reserved bytes in oob area */
-#define PMECC_OOB_RESERVED_BYTES               2
-
-#endif
diff --git a/drivers/mtd/nand/atmel_nand_nfc.h b/drivers/mtd/nand/atmel_nand_nfc.h
deleted file mode 100644 (file)
index 4d5d262..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Atmel Nand Flash Controller (NFC) - System peripherals regsters.
- * Based on SAMA5D3 datasheet.
- *
- * © Copyright 2013 Atmel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-
-#ifndef ATMEL_NAND_NFC_H
-#define ATMEL_NAND_NFC_H
-
-/*
- * HSMC NFC registers
- */
-#define ATMEL_HSMC_NFC_CFG     0x00            /* NFC Configuration Register */
-#define                NFC_CFG_PAGESIZE        (7 << 0)
-#define                        NFC_CFG_PAGESIZE_512    (0 << 0)
-#define                        NFC_CFG_PAGESIZE_1024   (1 << 0)
-#define                        NFC_CFG_PAGESIZE_2048   (2 << 0)
-#define                        NFC_CFG_PAGESIZE_4096   (3 << 0)
-#define                        NFC_CFG_PAGESIZE_8192   (4 << 0)
-#define                NFC_CFG_WSPARE          (1 << 8)
-#define                NFC_CFG_RSPARE          (1 << 9)
-#define                NFC_CFG_NFC_DTOCYC      (0xf << 16)
-#define                NFC_CFG_NFC_DTOMUL      (0x7 << 20)
-#define                NFC_CFG_NFC_SPARESIZE   (0x7f << 24)
-#define                NFC_CFG_NFC_SPARESIZE_BIT_POS   24
-
-#define ATMEL_HSMC_NFC_CTRL    0x04            /* NFC Control Register */
-#define                NFC_CTRL_ENABLE         (1 << 0)
-#define                NFC_CTRL_DISABLE        (1 << 1)
-
-#define ATMEL_HSMC_NFC_SR      0x08            /* NFC Status Register */
-#define                NFC_SR_BUSY             (1 << 8)
-#define                NFC_SR_XFR_DONE         (1 << 16)
-#define                NFC_SR_CMD_DONE         (1 << 17)
-#define                NFC_SR_DTOE             (1 << 20)
-#define                NFC_SR_UNDEF            (1 << 21)
-#define                NFC_SR_AWB              (1 << 22)
-#define                NFC_SR_ASE              (1 << 23)
-#define                NFC_SR_RB_EDGE          (1 << 24)
-
-#define ATMEL_HSMC_NFC_IER     0x0c
-#define ATMEL_HSMC_NFC_IDR     0x10
-#define ATMEL_HSMC_NFC_IMR     0x14
-#define ATMEL_HSMC_NFC_CYCLE0  0x18            /* NFC Address Cycle Zero */
-#define                ATMEL_HSMC_NFC_ADDR_CYCLE0      (0xff)
-
-#define ATMEL_HSMC_NFC_BANK    0x1c            /* NFC Bank Register */
-#define                ATMEL_HSMC_NFC_BANK0            (0 << 0)
-#define                ATMEL_HSMC_NFC_BANK1            (1 << 0)
-
-#define nfc_writel(addr, reg, value) \
-       writel((value), (addr) + ATMEL_HSMC_NFC_##reg)
-
-#define nfc_readl(addr, reg) \
-       readl_relaxed((addr) + ATMEL_HSMC_NFC_##reg)
-
-/*
- * NFC Address Command definitions
- */
-#define NFCADDR_CMD_CMD1       (0xff << 2)     /* Command for Cycle 1 */
-#define NFCADDR_CMD_CMD1_BIT_POS       2
-#define NFCADDR_CMD_CMD2       (0xff << 10)    /* Command for Cycle 2 */
-#define NFCADDR_CMD_CMD2_BIT_POS       10
-#define NFCADDR_CMD_VCMD2      (0x1 << 18)     /* Valid Cycle 2 Command */
-#define NFCADDR_CMD_ACYCLE     (0x7 << 19)     /* Number of Address required */
-#define                NFCADDR_CMD_ACYCLE_NONE         (0x0 << 19)
-#define                NFCADDR_CMD_ACYCLE_1            (0x1 << 19)
-#define                NFCADDR_CMD_ACYCLE_2            (0x2 << 19)
-#define                NFCADDR_CMD_ACYCLE_3            (0x3 << 19)
-#define                NFCADDR_CMD_ACYCLE_4            (0x4 << 19)
-#define                NFCADDR_CMD_ACYCLE_5            (0x5 << 19)
-#define NFCADDR_CMD_ACYCLE_BIT_POS     19
-#define NFCADDR_CMD_CSID       (0x7 << 22)     /* Chip Select Identifier */
-#define                NFCADDR_CMD_CSID_0              (0x0 << 22)
-#define                NFCADDR_CMD_CSID_1              (0x1 << 22)
-#define                NFCADDR_CMD_CSID_2              (0x2 << 22)
-#define                NFCADDR_CMD_CSID_3              (0x3 << 22)
-#define                NFCADDR_CMD_CSID_4              (0x4 << 22)
-#define                NFCADDR_CMD_CSID_5              (0x5 << 22)
-#define                NFCADDR_CMD_CSID_6              (0x6 << 22)
-#define                NFCADDR_CMD_CSID_7              (0x7 << 22)
-#define NFCADDR_CMD_DATAEN     (0x1 << 25)     /* Data Transfer Enable */
-#define NFCADDR_CMD_DATADIS    (0x0 << 25)     /* Data Transfer Disable */
-#define NFCADDR_CMD_NFCRD      (0x0 << 26)     /* NFC Read Enable */
-#define NFCADDR_CMD_NFCWR      (0x1 << 26)     /* NFC Write Enable */
-#define NFCADDR_CMD_NFCBUSY    (0x1 << 27)     /* NFC Busy */
-
-#define nfc_cmd_addr1234_writel(cmd, addr1234, nfc_base) \
-       writel((addr1234), (cmd) + nfc_base)
-
-#define nfc_cmd_readl(bitstatus, nfc_base) \
-       readl_relaxed((bitstatus) + nfc_base)
-
-#define NFC_TIME_OUT_MS                100
-#define        NFC_SRAM_BANK1_OFFSET   0x1200
-
-#endif
index 42ebd73f821dd47b9346113d06375af31b68f68c..7419c5ce63f8bc46ea02e59600e68be0217de7e7 100644 (file)
@@ -101,6 +101,9 @@ struct brcm_nand_dma_desc {
 #define BRCMNAND_MIN_BLOCKSIZE (8 * 1024)
 #define BRCMNAND_MIN_DEVSIZE   (4ULL * 1024 * 1024)
 
+#define NAND_CTRL_RDY                  (INTFC_CTLR_READY | INTFC_FLASH_READY)
+#define NAND_POLL_STATUS_TIMEOUT_MS    100
+
 /* Controller feature flags */
 enum {
        BRCMNAND_HAS_1K_SECTORS                 = BIT(0),
@@ -765,6 +768,31 @@ enum {
        CS_SELECT_AUTO_DEVICE_ID_CFG            = BIT(30),
 };
 
+static int bcmnand_ctrl_poll_status(struct brcmnand_controller *ctrl,
+                                   u32 mask, u32 expected_val,
+                                   unsigned long timeout_ms)
+{
+       unsigned long limit;
+       u32 val;
+
+       if (!timeout_ms)
+               timeout_ms = NAND_POLL_STATUS_TIMEOUT_MS;
+
+       limit = jiffies + msecs_to_jiffies(timeout_ms);
+       do {
+               val = brcmnand_read_reg(ctrl, BRCMNAND_INTFC_STATUS);
+               if ((val & mask) == expected_val)
+                       return 0;
+
+               cpu_relax();
+       } while (time_after(limit, jiffies));
+
+       dev_warn(ctrl->dev, "timeout on status poll (expected %x got %x)\n",
+                expected_val, val & mask);
+
+       return -ETIMEDOUT;
+}
+
 static inline void brcmnand_set_wp(struct brcmnand_controller *ctrl, bool en)
 {
        u32 val = en ? CS_SELECT_NAND_WP : 0;
@@ -1024,12 +1052,39 @@ static void brcmnand_wp(struct mtd_info *mtd, int wp)
 
        if ((ctrl->features & BRCMNAND_HAS_WP) && wp_on == 1) {
                static int old_wp = -1;
+               int ret;
 
                if (old_wp != wp) {
                        dev_dbg(ctrl->dev, "WP %s\n", wp ? "on" : "off");
                        old_wp = wp;
                }
+
+               /*
+                * make sure ctrl/flash ready before and after
+                * changing state of #WP pin
+                */
+               ret = bcmnand_ctrl_poll_status(ctrl, NAND_CTRL_RDY |
+                                              NAND_STATUS_READY,
+                                              NAND_CTRL_RDY |
+                                              NAND_STATUS_READY, 0);
+               if (ret)
+                       return;
+
                brcmnand_set_wp(ctrl, wp);
+               chip->cmdfunc(mtd, NAND_CMD_STATUS, -1, -1);
+               /* NAND_STATUS_WP 0x00 = protected, 0x80 = not protected */
+               ret = bcmnand_ctrl_poll_status(ctrl,
+                                              NAND_CTRL_RDY |
+                                              NAND_STATUS_READY |
+                                              NAND_STATUS_WP,
+                                              NAND_CTRL_RDY |
+                                              NAND_STATUS_READY |
+                                              (wp ? 0 : NAND_STATUS_WP), 0);
+
+               if (ret)
+                       dev_err_ratelimited(&host->pdev->dev,
+                                           "nand #WP expected %s\n",
+                                           wp ? "on" : "off");
        }
 }
 
@@ -1157,15 +1212,15 @@ static irqreturn_t brcmnand_dma_irq(int irq, void *data)
 static void brcmnand_send_cmd(struct brcmnand_host *host, int cmd)
 {
        struct brcmnand_controller *ctrl = host->ctrl;
-       u32 intfc;
+       int ret;
 
        dev_dbg(ctrl->dev, "send native cmd %d addr_lo 0x%x\n", cmd,
                brcmnand_read_reg(ctrl, BRCMNAND_CMD_ADDRESS));
        BUG_ON(ctrl->cmd_pending != 0);
        ctrl->cmd_pending = cmd;
 
-       intfc = brcmnand_read_reg(ctrl, BRCMNAND_INTFC_STATUS);
-       WARN_ON(!(intfc & INTFC_CTLR_READY));
+       ret = bcmnand_ctrl_poll_status(ctrl, NAND_CTRL_RDY, NAND_CTRL_RDY, 0);
+       WARN_ON(ret);
 
        mb(); /* flush previous writes */
        brcmnand_write_reg(ctrl, BRCMNAND_CMD_START,
index 226ac0bcafc6539ba6389cf1170f05ee05a2acc6..949b9400dcb7cb7302f4a54fff73b6082de40a4a 100644 (file)
@@ -145,7 +145,7 @@ static int __init cmx270_init(void)
 
        ret = gpio_request(GPIO_NAND_CS, "NAND CS");
        if (ret) {
-               pr_warning("CM-X270: failed to request NAND CS gpio\n");
+               pr_warn("CM-X270: failed to request NAND CS gpio\n");
                return ret;
        }
 
@@ -153,7 +153,7 @@ static int __init cmx270_init(void)
 
        ret = gpio_request(GPIO_NAND_RB, "NAND R/B");
        if (ret) {
-               pr_warning("CM-X270: failed to request NAND R/B gpio\n");
+               pr_warn("CM-X270: failed to request NAND R/B gpio\n");
                goto err_gpio_request;
        }
 
index 27fa8b87cd5fc6a779e0509ce78c010527747268..531c51991e5747b35fc68114ace9d534a1ea430e 100644 (file)
@@ -581,6 +581,17 @@ static struct davinci_nand_pdata
                        "ti,davinci-nand-use-bbt"))
                        pdata->bbt_options = NAND_BBT_USE_FLASH;
 
+               /*
+                * Since kernel v4.8, this driver has been fixed to enable
+                * use of 4-bit hardware ECC with subpages and verified on
+                * TI's keystone EVMs (K2L, K2HK and K2E).
+                * However, in the interest of not breaking systems using
+                * existing UBI partitions, sub-page writes are not being
+                * (re)enabled. If you want to use subpage writes on Keystone
+                * platforms (i.e. do not have any existing UBI partitions),
+                * then use "ti,davinci-nand" as the compatible in your
+                * device-tree file.
+                */
                if (of_device_is_compatible(pdev->dev.of_node,
                                            "ti,keystone-nand")) {
                        pdata->options |= NAND_NO_SUBPAGE_WRITE;
index 73b9d4e2dca0a4c7b7f198cb6fdae0922cfb864f..16634df2e39a77ae1e34f68a7b4af0c642232b1e 100644 (file)
@@ -45,16 +45,16 @@ MODULE_PARM_DESC(onfi_timing_mode,
  * We define a macro here that combines all interrupts this driver uses into
  * a single constant value, for convenience.
  */
-#define DENALI_IRQ_ALL (INTR_STATUS__DMA_CMD_COMP | \
-                       INTR_STATUS__ECC_TRANSACTION_DONE | \
-                       INTR_STATUS__ECC_ERR | \
-                       INTR_STATUS__PROGRAM_FAIL | \
-                       INTR_STATUS__LOAD_COMP | \
-                       INTR_STATUS__PROGRAM_COMP | \
-                       INTR_STATUS__TIME_OUT | \
-                       INTR_STATUS__ERASE_FAIL | \
-                       INTR_STATUS__RST_COMP | \
-                       INTR_STATUS__ERASE_COMP)
+#define DENALI_IRQ_ALL (INTR__DMA_CMD_COMP | \
+                       INTR__ECC_TRANSACTION_DONE | \
+                       INTR__ECC_ERR | \
+                       INTR__PROGRAM_FAIL | \
+                       INTR__LOAD_COMP | \
+                       INTR__PROGRAM_COMP | \
+                       INTR__TIME_OUT | \
+                       INTR__ERASE_FAIL | \
+                       INTR__RST_COMP | \
+                       INTR__ERASE_COMP)
 
 /*
  * indicates whether or not the internal value for the flash bank is
@@ -62,8 +62,6 @@ MODULE_PARM_DESC(onfi_timing_mode,
  */
 #define CHIP_SELECT_INVALID    -1
 
-#define SUPPORT_8BITECC                1
-
 /*
  * This macro divides two integers and rounds fractional values up
  * to the nearest integer value.
@@ -86,16 +84,10 @@ static inline struct denali_nand_info *mtd_to_denali(struct mtd_info *mtd)
 #define SPARE_ACCESS           0x41
 #define MAIN_ACCESS            0x42
 #define MAIN_SPARE_ACCESS      0x43
-#define PIPELINE_ACCESS                0x2000
 
 #define DENALI_READ    0
 #define DENALI_WRITE   0x100
 
-/* types of device accesses. We can issue commands and get status */
-#define COMMAND_CYCLE  0
-#define ADDR_CYCLE     1
-#define STATUS_CYCLE   2
-
 /*
  * this is a helper macro that allows us to
  * format the bank into the proper bits for the controller
@@ -164,7 +156,7 @@ static void read_status(struct denali_nand_info *denali)
 static void reset_bank(struct denali_nand_info *denali)
 {
        uint32_t irq_status;
-       uint32_t irq_mask = INTR_STATUS__RST_COMP | INTR_STATUS__TIME_OUT;
+       uint32_t irq_mask = INTR__RST_COMP | INTR__TIME_OUT;
 
        clear_interrupts(denali);
 
@@ -172,7 +164,7 @@ static void reset_bank(struct denali_nand_info *denali)
 
        irq_status = wait_for_irq(denali, irq_mask);
 
-       if (irq_status & INTR_STATUS__TIME_OUT)
+       if (irq_status & INTR__TIME_OUT)
                dev_err(denali->dev, "reset bank failed.\n");
 }
 
@@ -182,22 +174,22 @@ static uint16_t denali_nand_reset(struct denali_nand_info *denali)
        int i;
 
        for (i = 0; i < denali->max_banks; i++)
-               iowrite32(INTR_STATUS__RST_COMP | INTR_STATUS__TIME_OUT,
+               iowrite32(INTR__RST_COMP | INTR__TIME_OUT,
                denali->flash_reg + INTR_STATUS(i));
 
        for (i = 0; i < denali->max_banks; i++) {
                iowrite32(1 << i, denali->flash_reg + DEVICE_RESET);
                while (!(ioread32(denali->flash_reg + INTR_STATUS(i)) &
-                       (INTR_STATUS__RST_COMP | INTR_STATUS__TIME_OUT)))
+                       (INTR__RST_COMP | INTR__TIME_OUT)))
                        cpu_relax();
                if (ioread32(denali->flash_reg + INTR_STATUS(i)) &
-                       INTR_STATUS__TIME_OUT)
+                       INTR__TIME_OUT)
                        dev_dbg(denali->dev,
                        "NAND Reset operation timed out on bank %d\n", i);
        }
 
        for (i = 0; i < denali->max_banks; i++)
-               iowrite32(INTR_STATUS__RST_COMP | INTR_STATUS__TIME_OUT,
+               iowrite32(INTR__RST_COMP | INTR__TIME_OUT,
                          denali->flash_reg + INTR_STATUS(i));
 
        return PASS;
@@ -347,52 +339,25 @@ static void get_samsung_nand_para(struct denali_nand_info *denali,
 
 static void get_toshiba_nand_para(struct denali_nand_info *denali)
 {
-       uint32_t tmp;
-
        /*
         * Workaround to fix a controller bug which reports a wrong
         * spare area size for some kind of Toshiba NAND device
         */
        if ((ioread32(denali->flash_reg + DEVICE_MAIN_AREA_SIZE) == 4096) &&
-               (ioread32(denali->flash_reg + DEVICE_SPARE_AREA_SIZE) == 64)) {
+               (ioread32(denali->flash_reg + DEVICE_SPARE_AREA_SIZE) == 64))
                iowrite32(216, denali->flash_reg + DEVICE_SPARE_AREA_SIZE);
-               tmp = ioread32(denali->flash_reg + DEVICES_CONNECTED) *
-                       ioread32(denali->flash_reg + DEVICE_SPARE_AREA_SIZE);
-               iowrite32(tmp,
-                               denali->flash_reg + LOGICAL_PAGE_SPARE_SIZE);
-#if SUPPORT_15BITECC
-               iowrite32(15, denali->flash_reg + ECC_CORRECTION);
-#elif SUPPORT_8BITECC
-               iowrite32(8, denali->flash_reg + ECC_CORRECTION);
-#endif
-       }
 }
 
 static void get_hynix_nand_para(struct denali_nand_info *denali,
                                                        uint8_t device_id)
 {
-       uint32_t main_size, spare_size;
-
        switch (device_id) {
        case 0xD5: /* Hynix H27UAG8T2A, H27UBG8U5A or H27UCG8VFA */
        case 0xD7: /* Hynix H27UDG8VEM, H27UCG8UDM or H27UCG8V5A */
                iowrite32(128, denali->flash_reg + PAGES_PER_BLOCK);
                iowrite32(4096, denali->flash_reg + DEVICE_MAIN_AREA_SIZE);
                iowrite32(224, denali->flash_reg + DEVICE_SPARE_AREA_SIZE);
-               main_size = 4096 *
-                       ioread32(denali->flash_reg + DEVICES_CONNECTED);
-               spare_size = 224 *
-                       ioread32(denali->flash_reg + DEVICES_CONNECTED);
-               iowrite32(main_size,
-                               denali->flash_reg + LOGICAL_PAGE_DATA_SIZE);
-               iowrite32(spare_size,
-                               denali->flash_reg + LOGICAL_PAGE_SPARE_SIZE);
                iowrite32(0, denali->flash_reg + DEVICE_WIDTH);
-#if SUPPORT_15BITECC
-               iowrite32(15, denali->flash_reg + ECC_CORRECTION);
-#elif SUPPORT_8BITECC
-               iowrite32(8, denali->flash_reg + ECC_CORRECTION);
-#endif
                break;
        default:
                dev_warn(denali->dev,
@@ -454,17 +419,12 @@ static void find_valid_banks(struct denali_nand_info *denali)
 static void detect_max_banks(struct denali_nand_info *denali)
 {
        uint32_t features = ioread32(denali->flash_reg + FEATURES);
-       /*
-        * Read the revision register, so we can calculate the max_banks
-        * properly: the encoding changed from rev 5.0 to 5.1
-        */
-       u32 revision = MAKE_COMPARABLE_REVISION(
-                               ioread32(denali->flash_reg + REVISION));
 
-       if (revision < REVISION_5_1)
-               denali->max_banks = 2 << (features & FEATURES__N_BANKS);
-       else
-               denali->max_banks = 1 << (features & FEATURES__N_BANKS);
+       denali->max_banks = 1 << (features & FEATURES__N_BANKS);
+
+       /* the encoding changed from rev 5.0 to 5.1 */
+       if (denali->revision < 0x0501)
+               denali->max_banks <<= 1;
 }
 
 static uint16_t denali_nand_timing_set(struct denali_nand_info *denali)
@@ -653,7 +613,6 @@ static irqreturn_t denali_isr(int irq, void *dev_id)
        spin_unlock(&denali->irq_lock);
        return result;
 }
-#define BANK(x) ((x) << 24)
 
 static uint32_t wait_for_irq(struct denali_nand_info *denali, uint32_t irq_mask)
 {
@@ -718,15 +677,7 @@ static int denali_send_pipeline_cmd(struct denali_nand_info *denali,
                                    int access_type, int op)
 {
        int status = PASS;
-       uint32_t page_count = 1;
-       uint32_t addr, cmd, irq_status, irq_mask;
-
-       if (op == DENALI_READ)
-               irq_mask = INTR_STATUS__LOAD_COMP;
-       else if (op == DENALI_WRITE)
-               irq_mask = 0;
-       else
-               BUG();
+       uint32_t addr, cmd;
 
        setup_ecc_for_xfer(denali, ecc_en, transfer_spare);
 
@@ -749,35 +700,8 @@ static int denali_send_pipeline_cmd(struct denali_nand_info *denali,
                cmd = MODE_10 | addr;
                index_addr(denali, cmd, access_type);
 
-               /*
-                * page 33 of the NAND controller spec indicates we should not
-                * use the pipeline commands in Spare area only mode.
-                * So we don't.
-                */
-               if (access_type == SPARE_ACCESS) {
-                       cmd = MODE_01 | addr;
-                       iowrite32(cmd, denali->flash_mem);
-               } else {
-                       index_addr(denali, cmd,
-                                       PIPELINE_ACCESS | op | page_count);
-
-                       /*
-                        * wait for command to be accepted
-                        * can always use status0 bit as the
-                        * mask is identical for each bank.
-                        */
-                       irq_status = wait_for_irq(denali, irq_mask);
-
-                       if (irq_status == 0) {
-                               dev_err(denali->dev,
-                                       "cmd, page, addr on timeout (0x%x, 0x%x, 0x%x)\n",
-                                       cmd, denali->page, addr);
-                               status = FAIL;
-                       } else {
-                               cmd = MODE_01 | addr;
-                               iowrite32(cmd, denali->flash_mem);
-                       }
-               }
+               cmd = MODE_01 | addr;
+               iowrite32(cmd, denali->flash_mem);
        }
        return status;
 }
@@ -829,8 +753,7 @@ static int write_oob_data(struct mtd_info *mtd, uint8_t *buf, int page)
 {
        struct denali_nand_info *denali = mtd_to_denali(mtd);
        uint32_t irq_status;
-       uint32_t irq_mask = INTR_STATUS__PROGRAM_COMP |
-                                               INTR_STATUS__PROGRAM_FAIL;
+       uint32_t irq_mask = INTR__PROGRAM_COMP | INTR__PROGRAM_FAIL;
        int status = 0;
 
        denali->page = page;
@@ -857,7 +780,7 @@ static int write_oob_data(struct mtd_info *mtd, uint8_t *buf, int page)
 static void read_oob_data(struct mtd_info *mtd, uint8_t *buf, int page)
 {
        struct denali_nand_info *denali = mtd_to_denali(mtd);
-       uint32_t irq_mask = INTR_STATUS__LOAD_COMP;
+       uint32_t irq_mask = INTR__LOAD_COMP;
        uint32_t irq_status, addr, cmd;
 
        denali->page = page;
@@ -890,98 +813,158 @@ static void read_oob_data(struct mtd_info *mtd, uint8_t *buf, int page)
        }
 }
 
-/*
- * this function examines buffers to see if they contain data that
- * indicate that the buffer is part of an erased region of flash.
- */
-static bool is_erased(uint8_t *buf, int len)
+static int denali_check_erased_page(struct mtd_info *mtd,
+                                   struct nand_chip *chip, uint8_t *buf,
+                                   unsigned long uncor_ecc_flags,
+                                   unsigned int max_bitflips)
 {
-       int i;
+       uint8_t *ecc_code = chip->buffers->ecccode;
+       int ecc_steps = chip->ecc.steps;
+       int ecc_size = chip->ecc.size;
+       int ecc_bytes = chip->ecc.bytes;
+       int i, ret, stat;
+
+       ret = mtd_ooblayout_get_eccbytes(mtd, ecc_code, chip->oob_poi, 0,
+                                        chip->ecc.total);
+       if (ret)
+               return ret;
+
+       for (i = 0; i < ecc_steps; i++) {
+               if (!(uncor_ecc_flags & BIT(i)))
+                       continue;
 
-       for (i = 0; i < len; i++)
-               if (buf[i] != 0xFF)
-                       return false;
-       return true;
+               stat = nand_check_erased_ecc_chunk(buf, ecc_size,
+                                                 ecc_code, ecc_bytes,
+                                                 NULL, 0,
+                                                 chip->ecc.strength);
+               if (stat < 0) {
+                       mtd->ecc_stats.failed++;
+               } else {
+                       mtd->ecc_stats.corrected += stat;
+                       max_bitflips = max_t(unsigned int, max_bitflips, stat);
+               }
+
+               buf += ecc_size;
+               ecc_code += ecc_bytes;
+       }
+
+       return max_bitflips;
+}
+
+static int denali_hw_ecc_fixup(struct mtd_info *mtd,
+                              struct denali_nand_info *denali,
+                              unsigned long *uncor_ecc_flags)
+{
+       struct nand_chip *chip = mtd_to_nand(mtd);
+       int bank = denali->flash_bank;
+       uint32_t ecc_cor;
+       unsigned int max_bitflips;
+
+       ecc_cor = ioread32(denali->flash_reg + ECC_COR_INFO(bank));
+       ecc_cor >>= ECC_COR_INFO__SHIFT(bank);
+
+       if (ecc_cor & ECC_COR_INFO__UNCOR_ERR) {
+               /*
+                * This flag is set when uncorrectable error occurs at least in
+                * one ECC sector.  We can not know "how many sectors", or
+                * "which sector(s)".  We need erase-page check for all sectors.
+                */
+               *uncor_ecc_flags = GENMASK(chip->ecc.steps - 1, 0);
+               return 0;
+       }
+
+       max_bitflips = ecc_cor & ECC_COR_INFO__MAX_ERRORS;
+
+       /*
+        * The register holds the maximum of per-sector corrected bitflips.
+        * This is suitable for the return value of the ->read_page() callback.
+        * Unfortunately, we can not know the total number of corrected bits in
+        * the page.  Increase the stats by max_bitflips. (compromised solution)
+        */
+       mtd->ecc_stats.corrected += max_bitflips;
+
+       return max_bitflips;
 }
+
 #define ECC_SECTOR_SIZE 512
 
 #define ECC_SECTOR(x)  (((x) & ECC_ERROR_ADDRESS__SECTOR_NR) >> 12)
 #define ECC_BYTE(x)    (((x) & ECC_ERROR_ADDRESS__OFFSET))
 #define ECC_CORRECTION_VALUE(x) ((x) & ERR_CORRECTION_INFO__BYTEMASK)
-#define ECC_ERROR_CORRECTABLE(x) (!((x) & ERR_CORRECTION_INFO__ERROR_TYPE))
+#define ECC_ERROR_UNCORRECTABLE(x) ((x) & ERR_CORRECTION_INFO__ERROR_TYPE)
 #define ECC_ERR_DEVICE(x)      (((x) & ERR_CORRECTION_INFO__DEVICE_NR) >> 8)
 #define ECC_LAST_ERR(x)                ((x) & ERR_CORRECTION_INFO__LAST_ERR_INFO)
 
-static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf,
-                      uint32_t irq_status, unsigned int *max_bitflips)
+static int denali_sw_ecc_fixup(struct mtd_info *mtd,
+                              struct denali_nand_info *denali,
+                              unsigned long *uncor_ecc_flags, uint8_t *buf)
 {
-       bool check_erased_page = false;
        unsigned int bitflips = 0;
+       unsigned int max_bitflips = 0;
+       uint32_t err_addr, err_cor_info;
+       unsigned int err_byte, err_sector, err_device;
+       uint8_t err_cor_value;
+       unsigned int prev_sector = 0;
 
-       if (irq_status & INTR_STATUS__ECC_ERR) {
-               /* read the ECC errors. we'll ignore them for now */
-               uint32_t err_address, err_correction_info, err_byte,
-                        err_sector, err_device, err_correction_value;
-               denali_set_intr_modes(denali, false);
-
-               do {
-                       err_address = ioread32(denali->flash_reg +
-                                               ECC_ERROR_ADDRESS);
-                       err_sector = ECC_SECTOR(err_address);
-                       err_byte = ECC_BYTE(err_address);
-
-                       err_correction_info = ioread32(denali->flash_reg +
-                                               ERR_CORRECTION_INFO);
-                       err_correction_value =
-                               ECC_CORRECTION_VALUE(err_correction_info);
-                       err_device = ECC_ERR_DEVICE(err_correction_info);
-
-                       if (ECC_ERROR_CORRECTABLE(err_correction_info)) {
-                               /*
-                                * If err_byte is larger than ECC_SECTOR_SIZE,
-                                * means error happened in OOB, so we ignore
-                                * it. It's no need for us to correct it
-                                * err_device is represented the NAND error
-                                * bits are happened in if there are more
-                                * than one NAND connected.
-                                */
-                               if (err_byte < ECC_SECTOR_SIZE) {
-                                       struct mtd_info *mtd =
-                                               nand_to_mtd(&denali->nand);
-                                       int offset;
-
-                                       offset = (err_sector *
-                                                       ECC_SECTOR_SIZE +
-                                                       err_byte) *
-                                                       denali->devnum +
-                                                       err_device;
-                                       /* correct the ECC error */
-                                       buf[offset] ^= err_correction_value;
-                                       mtd->ecc_stats.corrected++;
-                                       bitflips++;
-                               }
-                       } else {
-                               /*
-                                * if the error is not correctable, need to
-                                * look at the page to see if it is an erased
-                                * page. if so, then it's not a real ECC error
-                                */
-                               check_erased_page = true;
-                       }
-               } while (!ECC_LAST_ERR(err_correction_info));
-               /*
-                * Once handle all ecc errors, controller will triger
-                * a ECC_TRANSACTION_DONE interrupt, so here just wait
-                * for a while for this interrupt
-                */
-               while (!(read_interrupt_status(denali) &
-                               INTR_STATUS__ECC_TRANSACTION_DONE))
-                       cpu_relax();
-               clear_interrupts(denali);
-               denali_set_intr_modes(denali, true);
-       }
-       *max_bitflips = bitflips;
-       return check_erased_page;
+       /* read the ECC errors. we'll ignore them for now */
+       denali_set_intr_modes(denali, false);
+
+       do {
+               err_addr = ioread32(denali->flash_reg + ECC_ERROR_ADDRESS);
+               err_sector = ECC_SECTOR(err_addr);
+               err_byte = ECC_BYTE(err_addr);
+
+               err_cor_info = ioread32(denali->flash_reg + ERR_CORRECTION_INFO);
+               err_cor_value = ECC_CORRECTION_VALUE(err_cor_info);
+               err_device = ECC_ERR_DEVICE(err_cor_info);
+
+               /* reset the bitflip counter when crossing ECC sector */
+               if (err_sector != prev_sector)
+                       bitflips = 0;
+
+               if (ECC_ERROR_UNCORRECTABLE(err_cor_info)) {
+                       /*
+                        * Check later if this is a real ECC error, or
+                        * an erased sector.
+                        */
+                       *uncor_ecc_flags |= BIT(err_sector);
+               } else if (err_byte < ECC_SECTOR_SIZE) {
+                       /*
+                        * If err_byte is larger than ECC_SECTOR_SIZE, means error
+                        * happened in OOB, so we ignore it. It's no need for
+                        * us to correct it err_device is represented the NAND
+                        * error bits are happened in if there are more than
+                        * one NAND connected.
+                        */
+                       int offset;
+                       unsigned int flips_in_byte;
+
+                       offset = (err_sector * ECC_SECTOR_SIZE + err_byte) *
+                                               denali->devnum + err_device;
+
+                       /* correct the ECC error */
+                       flips_in_byte = hweight8(buf[offset] ^ err_cor_value);
+                       buf[offset] ^= err_cor_value;
+                       mtd->ecc_stats.corrected += flips_in_byte;
+                       bitflips += flips_in_byte;
+
+                       max_bitflips = max(max_bitflips, bitflips);
+               }
+
+               prev_sector = err_sector;
+       } while (!ECC_LAST_ERR(err_cor_info));
+
+       /*
+        * Once handle all ecc errors, controller will trigger a
+        * ECC_TRANSACTION_DONE interrupt, so here just wait for
+        * a while for this interrupt
+        */
+       while (!(read_interrupt_status(denali) & INTR__ECC_TRANSACTION_DONE))
+               cpu_relax();
+       clear_interrupts(denali);
+       denali_set_intr_modes(denali, true);
+
+       return max_bitflips;
 }
 
 /* programs the controller to either enable/disable DMA transfers */
@@ -991,8 +974,30 @@ static void denali_enable_dma(struct denali_nand_info *denali, bool en)
        ioread32(denali->flash_reg + DMA_ENABLE);
 }
 
-/* setups the HW to perform the data DMA */
-static void denali_setup_dma(struct denali_nand_info *denali, int op)
+static void denali_setup_dma64(struct denali_nand_info *denali, int op)
+{
+       uint32_t mode;
+       const int page_count = 1;
+       uint64_t addr = denali->buf.dma_buf;
+
+       mode = MODE_10 | BANK(denali->flash_bank) | denali->page;
+
+       /* DMA is a three step process */
+
+       /*
+        * 1. setup transfer type, interrupt when complete,
+        *    burst len = 64 bytes, the number of pages
+        */
+       index_addr(denali, mode, 0x01002000 | (64 << 16) | op | page_count);
+
+       /* 2. set memory low address */
+       index_addr(denali, mode, addr);
+
+       /* 3. set memory high address */
+       index_addr(denali, mode, addr >> 32);
+}
+
+static void denali_setup_dma32(struct denali_nand_info *denali, int op)
 {
        uint32_t mode;
        const int page_count = 1;
@@ -1015,6 +1020,14 @@ static void denali_setup_dma(struct denali_nand_info *denali, int op)
        index_addr(denali, mode | 0x14000, 0x2400);
 }
 
+static void denali_setup_dma(struct denali_nand_info *denali, int op)
+{
+       if (denali->caps & DENALI_CAP_DMA_64BIT)
+               denali_setup_dma64(denali, op);
+       else
+               denali_setup_dma32(denali, op);
+}
+
 /*
  * writes a page. user specifies type, and this function handles the
  * configuration details.
@@ -1026,8 +1039,7 @@ static int write_page(struct mtd_info *mtd, struct nand_chip *chip,
        dma_addr_t addr = denali->buf.dma_buf;
        size_t size = mtd->writesize + mtd->oobsize;
        uint32_t irq_status;
-       uint32_t irq_mask = INTR_STATUS__DMA_CMD_COMP |
-                                               INTR_STATUS__PROGRAM_FAIL;
+       uint32_t irq_mask = INTR__DMA_CMD_COMP | INTR__PROGRAM_FAIL;
 
        /*
         * if it is a raw xfer, we want to disable ecc and send the spare area.
@@ -1118,16 +1130,15 @@ static int denali_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
 static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
                            uint8_t *buf, int oob_required, int page)
 {
-       unsigned int max_bitflips;
        struct denali_nand_info *denali = mtd_to_denali(mtd);
-
        dma_addr_t addr = denali->buf.dma_buf;
        size_t size = mtd->writesize + mtd->oobsize;
-
        uint32_t irq_status;
-       uint32_t irq_mask = INTR_STATUS__ECC_TRANSACTION_DONE |
-                           INTR_STATUS__ECC_ERR;
-       bool check_erased_page = false;
+       uint32_t irq_mask = denali->caps & DENALI_CAP_HW_ECC_FIXUP ?
+                               INTR__DMA_CMD_COMP | INTR__ECC_UNCOR_ERR :
+                               INTR__ECC_TRANSACTION_DONE | INTR__ECC_ERR;
+       unsigned long uncor_ecc_flags = 0;
+       int stat = 0;
 
        if (page != denali->page) {
                dev_err(denali->dev,
@@ -1151,21 +1162,23 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
 
        memcpy(buf, denali->buf.buf, mtd->writesize);
 
-       check_erased_page = handle_ecc(denali, buf, irq_status, &max_bitflips);
+       if (denali->caps & DENALI_CAP_HW_ECC_FIXUP)
+               stat = denali_hw_ecc_fixup(mtd, denali, &uncor_ecc_flags);
+       else if (irq_status & INTR__ECC_ERR)
+               stat = denali_sw_ecc_fixup(mtd, denali, &uncor_ecc_flags, buf);
        denali_enable_dma(denali, false);
 
-       if (check_erased_page) {
+       if (stat < 0)
+               return stat;
+
+       if (uncor_ecc_flags) {
                read_oob_data(mtd, chip->oob_poi, denali->page);
 
-               /* check ECC failures that may have occurred on erased pages */
-               if (check_erased_page) {
-                       if (!is_erased(buf, mtd->writesize))
-                               mtd->ecc_stats.failed++;
-                       if (!is_erased(buf, mtd->oobsize))
-                               mtd->ecc_stats.failed++;
-               }
+               stat = denali_check_erased_page(mtd, chip, buf,
+                                               uncor_ecc_flags, stat);
        }
-       return max_bitflips;
+
+       return stat;
 }
 
 static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
@@ -1174,7 +1187,7 @@ static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
        struct denali_nand_info *denali = mtd_to_denali(mtd);
        dma_addr_t addr = denali->buf.dma_buf;
        size_t size = mtd->writesize + mtd->oobsize;
-       uint32_t irq_mask = INTR_STATUS__DMA_CMD_COMP;
+       uint32_t irq_mask = INTR__DMA_CMD_COMP;
 
        if (page != denali->page) {
                dev_err(denali->dev,
@@ -1247,10 +1260,9 @@ static int denali_erase(struct mtd_info *mtd, int page)
        index_addr(denali, cmd, 0x1);
 
        /* wait for erase to complete or failure to occur */
-       irq_status = wait_for_irq(denali, INTR_STATUS__ERASE_COMP |
-                                       INTR_STATUS__ERASE_FAIL);
+       irq_status = wait_for_irq(denali, INTR__ERASE_COMP | INTR__ERASE_FAIL);
 
-       return irq_status & INTR_STATUS__ERASE_FAIL ? NAND_STATUS_FAIL : PASS;
+       return irq_status & INTR__ERASE_FAIL ? NAND_STATUS_FAIL : PASS;
 }
 
 static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col,
@@ -1302,6 +1314,14 @@ static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col,
 /* Initialization code to bring the device up to a known good state */
 static void denali_hw_init(struct denali_nand_info *denali)
 {
+       /*
+        * The REVISION register may not be reliable.  Platforms are allowed to
+        * override it.
+        */
+       if (!denali->revision)
+               denali->revision =
+                               swab16(ioread32(denali->flash_reg + REVISION));
+
        /*
         * tell driver how many bit controller will skip before
         * writing ECC code in OOB, this register may be already
@@ -1413,9 +1433,61 @@ static void denali_drv_init(struct denali_nand_info *denali)
        denali->irq_status = 0;
 }
 
+static int denali_multidev_fixup(struct denali_nand_info *denali)
+{
+       struct nand_chip *chip = &denali->nand;
+       struct mtd_info *mtd = nand_to_mtd(chip);
+
+       /*
+        * Support for multi device:
+        * When the IP configuration is x16 capable and two x8 chips are
+        * connected in parallel, DEVICES_CONNECTED should be set to 2.
+        * In this case, the core framework knows nothing about this fact,
+        * so we should tell it the _logical_ pagesize and anything necessary.
+        */
+       denali->devnum = ioread32(denali->flash_reg + DEVICES_CONNECTED);
+
+       /*
+        * On some SoCs, DEVICES_CONNECTED is not auto-detected.
+        * For those, DEVICES_CONNECTED is left to 0.  Set 1 if it is the case.
+        */
+       if (denali->devnum == 0) {
+               denali->devnum = 1;
+               iowrite32(1, denali->flash_reg + DEVICES_CONNECTED);
+       }
+
+       if (denali->devnum == 1)
+               return 0;
+
+       if (denali->devnum != 2) {
+               dev_err(denali->dev, "unsupported number of devices %d\n",
+                       denali->devnum);
+               return -EINVAL;
+       }
+
+       /* 2 chips in parallel */
+       mtd->size <<= 1;
+       mtd->erasesize <<= 1;
+       mtd->writesize <<= 1;
+       mtd->oobsize <<= 1;
+       chip->chipsize <<= 1;
+       chip->page_shift += 1;
+       chip->phys_erase_shift += 1;
+       chip->bbt_erase_shift += 1;
+       chip->chip_shift += 1;
+       chip->pagemask <<= 1;
+       chip->ecc.size <<= 1;
+       chip->ecc.bytes <<= 1;
+       chip->ecc.strength <<= 1;
+       denali->bbtskipbytes <<= 1;
+
+       return 0;
+}
+
 int denali_init(struct denali_nand_info *denali)
 {
-       struct mtd_info *mtd = nand_to_mtd(&denali->nand);
+       struct nand_chip *chip = &denali->nand;
+       struct mtd_info *mtd = nand_to_mtd(chip);
        int ret;
 
        if (denali->platform == INTEL_CE4100) {
@@ -1449,13 +1521,16 @@ int denali_init(struct denali_nand_info *denali)
 
        /* now that our ISR is registered, we can enable interrupts */
        denali_set_intr_modes(denali, true);
-       mtd->name = "denali-nand";
+       nand_set_flash_node(chip, denali->dev->of_node);
+       /* Fallback to the default name if DT did not give "label" property */
+       if (!mtd->name)
+               mtd->name = "denali-nand";
 
        /* register the driver with the NAND core subsystem */
-       denali->nand.select_chip = denali_select_chip;
-       denali->nand.cmdfunc = denali_cmdfunc;
-       denali->nand.read_byte = denali_read_byte;
-       denali->nand.waitfunc = denali_waitfunc;
+       chip->select_chip = denali_select_chip;
+       chip->cmdfunc = denali_cmdfunc;
+       chip->read_byte = denali_read_byte;
+       chip->waitfunc = denali_waitfunc;
 
        /*
         * scan for NAND devices attached to the controller
@@ -1476,8 +1551,9 @@ int denali_init(struct denali_nand_info *denali)
                goto failed_req_irq;
        }
 
-       /* Is 32-bit DMA supported? */
-       ret = dma_set_mask(denali->dev, DMA_BIT_MASK(32));
+       ret = dma_set_mask(denali->dev,
+                          DMA_BIT_MASK(denali->caps & DENALI_CAP_DMA_64BIT ?
+                                       64 : 32));
        if (ret) {
                dev_err(denali->dev, "No usable DMA configuration\n");
                goto failed_req_irq;
@@ -1492,25 +1568,6 @@ int denali_init(struct denali_nand_info *denali)
                goto failed_req_irq;
        }
 
-       /*
-        * support for multi nand
-        * MTD known nothing about multi nand, so we should tell it
-        * the real pagesize and anything necessery
-        */
-       denali->devnum = ioread32(denali->flash_reg + DEVICES_CONNECTED);
-       denali->nand.chipsize <<= denali->devnum - 1;
-       denali->nand.page_shift += denali->devnum - 1;
-       denali->nand.pagemask = (denali->nand.chipsize >>
-                                               denali->nand.page_shift) - 1;
-       denali->nand.bbt_erase_shift += denali->devnum - 1;
-       denali->nand.phys_erase_shift = denali->nand.bbt_erase_shift;
-       denali->nand.chip_shift += denali->devnum - 1;
-       mtd->writesize <<= denali->devnum - 1;
-       mtd->oobsize <<= denali->devnum - 1;
-       mtd->erasesize <<= denali->devnum - 1;
-       mtd->size = denali->nand.numchips * denali->nand.chipsize;
-       denali->bbtskipbytes *= denali->devnum;
-
        /*
         * second stage of the NAND scan
         * this stage requires information regarding ECC and
@@ -1518,29 +1575,29 @@ int denali_init(struct denali_nand_info *denali)
         */
 
        /* Bad block management */
-       denali->nand.bbt_td = &bbt_main_descr;
-       denali->nand.bbt_md = &bbt_mirror_descr;
+       chip->bbt_td = &bbt_main_descr;
+       chip->bbt_md = &bbt_mirror_descr;
 
        /* skip the scan for now until we have OOB read and write support */
-       denali->nand.bbt_options |= NAND_BBT_USE_FLASH;
-       denali->nand.options |= NAND_SKIP_BBTSCAN;
-       denali->nand.ecc.mode = NAND_ECC_HW_SYNDROME;
+       chip->bbt_options |= NAND_BBT_USE_FLASH;
+       chip->options |= NAND_SKIP_BBTSCAN;
+       chip->ecc.mode = NAND_ECC_HW_SYNDROME;
 
        /* no subpage writes on denali */
-       denali->nand.options |= NAND_NO_SUBPAGE_WRITE;
+       chip->options |= NAND_NO_SUBPAGE_WRITE;
 
        /*
         * Denali Controller only support 15bit and 8bit ECC in MRST,
         * so just let controller do 15bit ECC for MLC and 8bit ECC for
         * SLC if possible.
         * */
-       if (!nand_is_slc(&denali->nand) &&
+       if (!nand_is_slc(chip) &&
                        (mtd->oobsize > (denali->bbtskipbytes +
                        ECC_15BITS * (mtd->writesize /
                        ECC_SECTOR_SIZE)))) {
                /* if MLC OOB size is large enough, use 15bit ECC*/
-               denali->nand.ecc.strength = 15;
-               denali->nand.ecc.bytes = ECC_15BITS;
+               chip->ecc.strength = 15;
+               chip->ecc.bytes = ECC_15BITS;
                iowrite32(15, denali->flash_reg + ECC_CORRECTION);
        } else if (mtd->oobsize < (denali->bbtskipbytes +
                        ECC_8BITS * (mtd->writesize /
@@ -1548,24 +1605,26 @@ int denali_init(struct denali_nand_info *denali)
                pr_err("Your NAND chip OOB is not large enough to contain 8bit ECC correction codes");
                goto failed_req_irq;
        } else {
-               denali->nand.ecc.strength = 8;
-               denali->nand.ecc.bytes = ECC_8BITS;
+               chip->ecc.strength = 8;
+               chip->ecc.bytes = ECC_8BITS;
                iowrite32(8, denali->flash_reg + ECC_CORRECTION);
        }
 
        mtd_set_ooblayout(mtd, &denali_ooblayout_ops);
-       denali->nand.ecc.bytes *= denali->devnum;
-       denali->nand.ecc.strength *= denali->devnum;
 
        /* override the default read operations */
-       denali->nand.ecc.size = ECC_SECTOR_SIZE * denali->devnum;
-       denali->nand.ecc.read_page = denali_read_page;
-       denali->nand.ecc.read_page_raw = denali_read_page_raw;
-       denali->nand.ecc.write_page = denali_write_page;
-       denali->nand.ecc.write_page_raw = denali_write_page_raw;
-       denali->nand.ecc.read_oob = denali_read_oob;
-       denali->nand.ecc.write_oob = denali_write_oob;
-       denali->nand.erase = denali_erase;
+       chip->ecc.size = ECC_SECTOR_SIZE;
+       chip->ecc.read_page = denali_read_page;
+       chip->ecc.read_page_raw = denali_read_page_raw;
+       chip->ecc.write_page = denali_write_page;
+       chip->ecc.write_page_raw = denali_write_page_raw;
+       chip->ecc.read_oob = denali_read_oob;
+       chip->ecc.write_oob = denali_write_oob;
+       chip->erase = denali_erase;
+
+       ret = denali_multidev_fixup(denali);
+       if (ret)
+               goto failed_req_irq;
 
        ret = nand_scan_tail(mtd);
        if (ret)
index ea22191e85157c1603c798fef6147a4934c9f50a..ec004850652a7a67df8be4c984d70db6faf86954 100644 (file)
@@ -20,6 +20,7 @@
 #ifndef __DENALI_H__
 #define __DENALI_H__
 
+#include <linux/bitops.h>
 #include <linux/mtd/nand.h>
 
 #define DEVICE_RESET                           0x0
 
 #define REVISION                               0x370
 #define     REVISION__VALUE                            0xffff
-#define MAKE_COMPARABLE_REVISION(x)            swab16((x) & REVISION__VALUE)
-#define REVISION_5_1                           0x00000501
 
 #define ONFI_DEVICE_FEATURES                   0x380
 #define     ONFI_DEVICE_FEATURES__VALUE                        0x003f
 
 #define INTR_STATUS(__bank)    (0x410 + ((__bank) * 0x50))
 #define INTR_EN(__bank)                (0x420 + ((__bank) * 0x50))
-
-#define     INTR_STATUS__ECC_TRANSACTION_DONE          0x0001
-#define     INTR_STATUS__ECC_ERR                       0x0002
-#define     INTR_STATUS__DMA_CMD_COMP                  0x0004
-#define     INTR_STATUS__TIME_OUT                      0x0008
-#define     INTR_STATUS__PROGRAM_FAIL                  0x0010
-#define     INTR_STATUS__ERASE_FAIL                    0x0020
-#define     INTR_STATUS__LOAD_COMP                     0x0040
-#define     INTR_STATUS__PROGRAM_COMP                  0x0080
-#define     INTR_STATUS__ERASE_COMP                    0x0100
-#define     INTR_STATUS__PIPE_CPYBCK_CMD_COMP          0x0200
-#define     INTR_STATUS__LOCKED_BLK                    0x0400
-#define     INTR_STATUS__UNSUP_CMD                     0x0800
-#define     INTR_STATUS__INT_ACT                       0x1000
-#define     INTR_STATUS__RST_COMP                      0x2000
-#define     INTR_STATUS__PIPE_CMD_ERR                  0x4000
-#define     INTR_STATUS__PAGE_XFER_INC                 0x8000
-
-#define     INTR_EN__ECC_TRANSACTION_DONE              0x0001
-#define     INTR_EN__ECC_ERR                           0x0002
-#define     INTR_EN__DMA_CMD_COMP                      0x0004
-#define     INTR_EN__TIME_OUT                          0x0008
-#define     INTR_EN__PROGRAM_FAIL                      0x0010
-#define     INTR_EN__ERASE_FAIL                                0x0020
-#define     INTR_EN__LOAD_COMP                         0x0040
-#define     INTR_EN__PROGRAM_COMP                      0x0080
-#define     INTR_EN__ERASE_COMP                                0x0100
-#define     INTR_EN__PIPE_CPYBCK_CMD_COMP              0x0200
-#define     INTR_EN__LOCKED_BLK                                0x0400
-#define     INTR_EN__UNSUP_CMD                         0x0800
-#define     INTR_EN__INT_ACT                           0x1000
-#define     INTR_EN__RST_COMP                          0x2000
-#define     INTR_EN__PIPE_CMD_ERR                      0x4000
-#define     INTR_EN__PAGE_XFER_INC                     0x8000
+/* bit[1:0] is used differently depending on IP version */
+#define     INTR__ECC_UNCOR_ERR                                0x0001  /* new IP */
+#define     INTR__ECC_TRANSACTION_DONE                 0x0001  /* old IP */
+#define     INTR__ECC_ERR                              0x0002  /* old IP */
+#define     INTR__DMA_CMD_COMP                         0x0004
+#define     INTR__TIME_OUT                             0x0008
+#define     INTR__PROGRAM_FAIL                         0x0010
+#define     INTR__ERASE_FAIL                           0x0020
+#define     INTR__LOAD_COMP                            0x0040
+#define     INTR__PROGRAM_COMP                         0x0080
+#define     INTR__ERASE_COMP                           0x0100
+#define     INTR__PIPE_CPYBCK_CMD_COMP                 0x0200
+#define     INTR__LOCKED_BLK                           0x0400
+#define     INTR__UNSUP_CMD                            0x0800
+#define     INTR__INT_ACT                              0x1000
+#define     INTR__RST_COMP                             0x2000
+#define     INTR__PIPE_CMD_ERR                         0x4000
+#define     INTR__PAGE_XFER_INC                                0x8000
 
 #define PAGE_CNT(__bank)       (0x430 + ((__bank) * 0x50))
 #define ERR_PAGE_ADDR(__bank)  (0x440 + ((__bank) * 0x50))
 #define ERR_BLOCK_ADDR(__bank) (0x450 + ((__bank) * 0x50))
 
-#define DATA_INTR                              0x550
-#define     DATA_INTR__WRITE_SPACE_AV                  0x0001
-#define     DATA_INTR__READ_DATA_AV                    0x0002
-
-#define DATA_INTR_EN                           0x560
-#define     DATA_INTR_EN__WRITE_SPACE_AV               0x0001
-#define     DATA_INTR_EN__READ_DATA_AV                 0x0002
-
-#define GPREG_0                                        0x570
-#define     GPREG_0__VALUE                             0xffff
-
-#define GPREG_1                                        0x580
-#define     GPREG_1__VALUE                             0xffff
-
-#define GPREG_2                                        0x590
-#define     GPREG_2__VALUE                             0xffff
-
-#define GPREG_3                                        0x5a0
-#define     GPREG_3__VALUE                             0xffff
-
 #define ECC_THRESHOLD                          0x600
 #define     ECC_THRESHOLD__VALUE                       0x03ff
 
 #define     ERR_CORRECTION_INFO__ERROR_TYPE            0x4000
 #define     ERR_CORRECTION_INFO__LAST_ERR_INFO         0x8000
 
+#define ECC_COR_INFO(bank)                     (0x650 + (bank) / 2 * 0x10)
+#define     ECC_COR_INFO__SHIFT(bank)                  ((bank) % 2 * 8)
+#define     ECC_COR_INFO__MAX_ERRORS                   0x007f
+#define     ECC_COR_INFO__UNCOR_ERR                    0x0080
+
 #define DMA_ENABLE                             0x700
 #define     DMA_ENABLE__FLAG                           0x0001
 
 #define     IGNORE_ECC_DONE__FLAG                      0x0001
 
 #define DMA_INTR                               0x720
+#define DMA_INTR_EN                            0x730
 #define     DMA_INTR__TARGET_ERROR                     0x0001
 #define     DMA_INTR__DESC_COMP_CHANNEL0               0x0002
 #define     DMA_INTR__DESC_COMP_CHANNEL1               0x0004
 #define     DMA_INTR__DESC_COMP_CHANNEL2               0x0008
 #define     DMA_INTR__DESC_COMP_CHANNEL3               0x0010
-#define     DMA_INTR__MEMCOPY_DESC_COMP                0x0020
-
-#define DMA_INTR_EN                            0x730
-#define     DMA_INTR_EN__TARGET_ERROR                  0x0001
-#define     DMA_INTR_EN__DESC_COMP_CHANNEL0            0x0002
-#define     DMA_INTR_EN__DESC_COMP_CHANNEL1            0x0004
-#define     DMA_INTR_EN__DESC_COMP_CHANNEL2            0x0008
-#define     DMA_INTR_EN__DESC_COMP_CHANNEL3            0x0010
-#define     DMA_INTR_EN__MEMCOPY_DESC_COMP             0x0020
+#define     DMA_INTR__MEMCOPY_DESC_COMP                        0x0020
 
 #define TARGET_ERR_ADDR_LO                     0x740
 #define     TARGET_ERR_ADDR_LO__VALUE                  0xffff
 #define     CHNL_ACTIVE__CHANNEL2                      0x0004
 #define     CHNL_ACTIVE__CHANNEL3                      0x0008
 
-#define ACTIVE_SRC_ID                          0x800
-#define     ACTIVE_SRC_ID__VALUE                       0x00ff
-
-#define PTN_INTR                                       0x810
-#define     PTN_INTR__CONFIG_ERROR                     0x0001
-#define     PTN_INTR__ACCESS_ERROR_BANK0               0x0002
-#define     PTN_INTR__ACCESS_ERROR_BANK1               0x0004
-#define     PTN_INTR__ACCESS_ERROR_BANK2               0x0008
-#define     PTN_INTR__ACCESS_ERROR_BANK3               0x0010
-#define     PTN_INTR__REG_ACCESS_ERROR                 0x0020
-
-#define PTN_INTR_EN                            0x820
-#define     PTN_INTR_EN__CONFIG_ERROR                  0x0001
-#define     PTN_INTR_EN__ACCESS_ERROR_BANK0            0x0002
-#define     PTN_INTR_EN__ACCESS_ERROR_BANK1            0x0004
-#define     PTN_INTR_EN__ACCESS_ERROR_BANK2            0x0008
-#define     PTN_INTR_EN__ACCESS_ERROR_BANK3            0x0010
-#define     PTN_INTR_EN__REG_ACCESS_ERROR              0x0020
-
-#define PERM_SRC_ID(__bank)    (0x830 + ((__bank) * 0x40))
-#define     PERM_SRC_ID__SRCID                         0x00ff
-#define     PERM_SRC_ID__DIRECT_ACCESS_ACTIVE          0x0800
-#define     PERM_SRC_ID__WRITE_ACTIVE                  0x2000
-#define     PERM_SRC_ID__READ_ACTIVE                   0x4000
-#define     PERM_SRC_ID__PARTITION_VALID               0x8000
-
-#define MIN_BLK_ADDR(__bank)   (0x840 + ((__bank) * 0x40))
-#define     MIN_BLK_ADDR__VALUE                                0xffff
-
-#define MAX_BLK_ADDR(__bank)   (0x850 + ((__bank) * 0x40))
-#define     MAX_BLK_ADDR__VALUE                                0xffff
-
-#define MIN_MAX_BANK(__bank)   (0x860 + ((__bank) * 0x40))
-#define     MIN_MAX_BANK__MIN_VALUE                    0x0003
-#define     MIN_MAX_BANK__MAX_VALUE                    0x000c
-
-
-/* ffsdefs.h */
-#define CLEAR 0                 /*use this to clear a field instead of "fail"*/
-#define SET   1                 /*use this to set a field instead of "pass"*/
 #define FAIL 1                  /*failed flag*/
 #define PASS 0                  /*success flag*/
-#define ERR -1                  /*error flag*/
-
-/* lld.h */
-#define GOOD_BLOCK 0
-#define DEFECTIVE_BLOCK 1
-#define READ_ERROR 2
 
 #define CLK_X  5
 #define CLK_MULTI 4
 
-/* KBV - Updated to LNW scratch register address */
-#define SCRATCH_REG_ADDR    CONFIG_MTD_NAND_DENALI_SCRATCH_REG_ADDR
-#define SCRATCH_REG_SIZE    64
-
-#define GLOB_HWCTL_DEFAULT_BLKS    2048
-
-#define SUPPORT_15BITECC        1
-#define SUPPORT_8BITECC         1
-
-#define CUSTOM_CONF_PARAMS      0
-
 #define ONFI_BLOOM_TIME         1
 #define MODE5_WORKAROUND        0
 
 #define MODE_10    0x08000000
 #define MODE_11    0x0C000000
 
-
-#define DATA_TRANSFER_MODE              0
-#define PROTECTION_PER_BLOCK            1
-#define LOAD_WAIT_COUNT                 2
-#define PROGRAM_WAIT_COUNT              3
-#define ERASE_WAIT_COUNT                4
-#define INT_MONITOR_CYCLE_COUNT         5
-#define READ_BUSY_PIN_ENABLED           6
-#define MULTIPLANE_OPERATION_SUPPORT    7
-#define PRE_FETCH_MODE                  8
-#define CE_DONT_CARE_SUPPORT            9
-#define COPYBACK_SUPPORT                10
-#define CACHE_WRITE_SUPPORT             11
-#define CACHE_READ_SUPPORT              12
-#define NUM_PAGES_IN_BLOCK              13
-#define ECC_ENABLE_SELECT               14
-#define WRITE_ENABLE_2_READ_ENABLE      15
-#define ADDRESS_2_DATA                  16
-#define READ_ENABLE_2_WRITE_ENABLE      17
-#define TWO_ROW_ADDRESS_CYCLES          18
-#define MULTIPLANE_ADDRESS_RESTRICT     19
-#define ACC_CLOCKS                      20
-#define READ_WRITE_ENABLE_LOW_COUNT     21
-#define READ_WRITE_ENABLE_HIGH_COUNT    22
-
 #define ECC_SECTOR_SIZE     512
 
 struct nand_buf {
@@ -449,23 +328,26 @@ struct denali_nand_info {
        struct nand_buf buf;
        struct device *dev;
        int total_used_banks;
-       uint32_t block;  /* stored for future use */
-       uint16_t page;
-       void __iomem *flash_reg;  /* Mapped io reg base address */
-       void __iomem *flash_mem;  /* Mapped io reg base address */
+       int page;
+       void __iomem *flash_reg;        /* Register Interface */
+       void __iomem *flash_mem;        /* Host Data/Command Interface */
 
        /* elements used by ISR */
        struct completion complete;
        spinlock_t irq_lock;
        uint32_t irq_status;
-       int irq_debug_array[32];
        int irq;
 
-       uint32_t devnum;        /* represent how many nands connected */
-       uint32_t bbtskipbytes;
-       uint32_t max_banks;
+       int devnum;     /* represent how many nands connected */
+       int bbtskipbytes;
+       int max_banks;
+       unsigned int revision;
+       unsigned int caps;
 };
 
+#define DENALI_CAP_HW_ECC_FIXUP                        BIT(0)
+#define DENALI_CAP_DMA_64BIT                   BIT(1)
+
 extern int denali_init(struct denali_nand_info *denali);
 extern void denali_remove(struct denali_nand_info *denali);
 
index 5607fcd3b8ed5f765219ca5bfb084290d18a962b..df9ef36cc2ce3323da883e722152bf0b5a1d2f8b 100644 (file)
@@ -29,64 +29,66 @@ struct denali_dt {
        struct clk              *clk;
 };
 
-static const struct of_device_id denali_nand_dt_ids[] = {
-               { .compatible = "denali,denali-nand-dt" },
-               { /* sentinel */ }
-       };
+struct denali_dt_data {
+       unsigned int revision;
+       unsigned int caps;
+};
 
-MODULE_DEVICE_TABLE(of, denali_nand_dt_ids);
+static const struct denali_dt_data denali_socfpga_data = {
+       .caps = DENALI_CAP_HW_ECC_FIXUP,
+};
 
-static u64 denali_dma_mask;
+static const struct of_device_id denali_nand_dt_ids[] = {
+       {
+               .compatible = "altr,socfpga-denali-nand",
+               .data = &denali_socfpga_data,
+       },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, denali_nand_dt_ids);
 
-static int denali_dt_probe(struct platform_device *ofdev)
+static int denali_dt_probe(struct platform_device *pdev)
 {
        struct resource *denali_reg, *nand_data;
        struct denali_dt *dt;
+       const struct denali_dt_data *data;
        struct denali_nand_info *denali;
        int ret;
-       const struct of_device_id *of_id;
 
-       of_id = of_match_device(denali_nand_dt_ids, &ofdev->dev);
-       if (of_id) {
-               ofdev->id_entry = of_id->data;
-       } else {
-               pr_err("Failed to find the right device id.\n");
-               return -ENOMEM;
-       }
-
-       dt = devm_kzalloc(&ofdev->dev, sizeof(*dt), GFP_KERNEL);
+       dt = devm_kzalloc(&pdev->dev, sizeof(*dt), GFP_KERNEL);
        if (!dt)
                return -ENOMEM;
        denali = &dt->denali;
 
+       data = of_device_get_match_data(&pdev->dev);
+       if (data) {
+               denali->revision = data->revision;
+               denali->caps = data->caps;
+       }
+
        denali->platform = DT;
-       denali->dev = &ofdev->dev;
-       denali->irq = platform_get_irq(ofdev, 0);
+       denali->dev = &pdev->dev;
+       denali->irq = platform_get_irq(pdev, 0);
        if (denali->irq < 0) {
-               dev_err(&ofdev->dev, "no irq defined\n");
+               dev_err(&pdev->dev, "no irq defined\n");
                return denali->irq;
        }
 
-       denali_reg = platform_get_resource_byname(ofdev, IORESOURCE_MEM, "denali_reg");
-       denali->flash_reg = devm_ioremap_resource(&ofdev->dev, denali_reg);
+       denali_reg = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+                                                 "denali_reg");
+       denali->flash_reg = devm_ioremap_resource(&pdev->dev, denali_reg);
        if (IS_ERR(denali->flash_reg))
                return PTR_ERR(denali->flash_reg);
 
-       nand_data = platform_get_resource_byname(ofdev, IORESOURCE_MEM, "nand_data");
-       denali->flash_mem = devm_ioremap_resource(&ofdev->dev, nand_data);
+       nand_data = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+                                                "nand_data");
+       denali->flash_mem = devm_ioremap_resource(&pdev->dev, nand_data);
        if (IS_ERR(denali->flash_mem))
                return PTR_ERR(denali->flash_mem);
 
-       if (!of_property_read_u32(ofdev->dev.of_node,
-               "dma-mask", (u32 *)&denali_dma_mask)) {
-               denali->dev->dma_mask = &denali_dma_mask;
-       } else {
-               denali->dev->dma_mask = NULL;
-       }
-
-       dt->clk = devm_clk_get(&ofdev->dev, NULL);
+       dt->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(dt->clk)) {
-               dev_err(&ofdev->dev, "no clk available\n");
+               dev_err(&pdev->dev, "no clk available\n");
                return PTR_ERR(dt->clk);
        }
        clk_prepare_enable(dt->clk);
@@ -95,7 +97,7 @@ static int denali_dt_probe(struct platform_device *ofdev)
        if (ret)
                goto out_disable_clk;
 
-       platform_set_drvdata(ofdev, dt);
+       platform_set_drvdata(pdev, dt);
        return 0;
 
 out_disable_clk:
@@ -104,9 +106,9 @@ out_disable_clk:
        return ret;
 }
 
-static int denali_dt_remove(struct platform_device *ofdev)
+static int denali_dt_remove(struct platform_device *pdev)
 {
-       struct denali_dt *dt = platform_get_drvdata(ofdev);
+       struct denali_dt *dt = platform_get_drvdata(pdev);
 
        denali_remove(&dt->denali);
        clk_disable_unprepare(dt->clk);
index bda1e4667138ab3cc392f961f7db6da377829b03..cea50d2f218c1d33c09005f3a5084372fa7a18e1 100644 (file)
 #include <linux/amba/bus.h>
 #include <mtd/mtd-abi.h>
 
-#define FSMC_NAND_BW8          1
-#define FSMC_NAND_BW16         2
-
-#define FSMC_MAX_NOR_BANKS     4
-#define FSMC_MAX_NAND_BANKS    4
-
-#define FSMC_FLASH_WIDTH8      1
-#define FSMC_FLASH_WIDTH16     2
-
 /* fsmc controller registers for NOR flash */
 #define CTRL                   0x0
        /* ctrl register definitions */
@@ -133,33 +124,48 @@ enum access_mode {
 };
 
 /**
- * fsmc_nand_platform_data - platform specific NAND controller config
- * @nand_timings: timing setup for the physical NAND interface
- * @partitions: partition table for the platform, use a default fallback
- * if this is NULL
- * @nr_partitions: the number of partitions in the previous entry
- * @options: different options for the driver
- * @width: bus width
- * @bank: default bank
- * @select_bank: callback to select a certain bank, this is
- * platform-specific. If the controller only supports one bank
- * this may be set to NULL
+ * struct fsmc_nand_data - structure for FSMC NAND device state
+ *
+ * @pid:               Part ID on the AMBA PrimeCell format
+ * @mtd:               MTD info for a NAND flash.
+ * @nand:              Chip related info for a NAND flash.
+ * @partitions:                Partition info for a NAND Flash.
+ * @nr_partitions:     Total number of partition of a NAND flash.
+ *
+ * @bank:              Bank number for probed device.
+ * @clk:               Clock structure for FSMC.
+ *
+ * @read_dma_chan:     DMA channel for read access
+ * @write_dma_chan:    DMA channel for write access to NAND
+ * @dma_access_complete: Completion structure
+ *
+ * @data_pa:           NAND Physical port for Data.
+ * @data_va:           NAND port for Data.
+ * @cmd_va:            NAND port for Command.
+ * @addr_va:           NAND port for Address.
+ * @regs_va:           FSMC regs base address.
  */
-struct fsmc_nand_platform_data {
-       struct fsmc_nand_timings *nand_timings;
-       struct mtd_partition    *partitions;
-       unsigned int            nr_partitions;
-       unsigned int            options;
-       unsigned int            width;
-       unsigned int            bank;
+struct fsmc_nand_data {
+       u32                     pid;
+       struct nand_chip        nand;
 
+       unsigned int            bank;
+       struct device           *dev;
        enum access_mode        mode;
+       struct clk              *clk;
 
-       void                    (*select_bank)(uint32_t bank, uint32_t busw);
+       /* DMA related objects */
+       struct dma_chan         *read_dma_chan;
+       struct dma_chan         *write_dma_chan;
+       struct completion       dma_access_complete;
 
-       /* priv structures for dma accesses */
-       void                    *read_dma_priv;
-       void                    *write_dma_priv;
+       struct fsmc_nand_timings *dev_timings;
+
+       dma_addr_t              data_pa;
+       void __iomem            *data_va;
+       void __iomem            *cmd_va;
+       void __iomem            *addr_va;
+       void __iomem            *regs_va;
 };
 
 static int fsmc_ecc1_ooblayout_ecc(struct mtd_info *mtd, int section,
@@ -246,86 +252,11 @@ static const struct mtd_ooblayout_ops fsmc_ecc4_ooblayout_ops = {
        .free = fsmc_ecc4_ooblayout_free,
 };
 
-/**
- * struct fsmc_nand_data - structure for FSMC NAND device state
- *
- * @pid:               Part ID on the AMBA PrimeCell format
- * @mtd:               MTD info for a NAND flash.
- * @nand:              Chip related info for a NAND flash.
- * @partitions:                Partition info for a NAND Flash.
- * @nr_partitions:     Total number of partition of a NAND flash.
- *
- * @bank:              Bank number for probed device.
- * @clk:               Clock structure for FSMC.
- *
- * @read_dma_chan:     DMA channel for read access
- * @write_dma_chan:    DMA channel for write access to NAND
- * @dma_access_complete: Completion structure
- *
- * @data_pa:           NAND Physical port for Data.
- * @data_va:           NAND port for Data.
- * @cmd_va:            NAND port for Command.
- * @addr_va:           NAND port for Address.
- * @regs_va:           FSMC regs base address.
- */
-struct fsmc_nand_data {
-       u32                     pid;
-       struct nand_chip        nand;
-       struct mtd_partition    *partitions;
-       unsigned int            nr_partitions;
-
-       unsigned int            bank;
-       struct device           *dev;
-       enum access_mode        mode;
-       struct clk              *clk;
-
-       /* DMA related objects */
-       struct dma_chan         *read_dma_chan;
-       struct dma_chan         *write_dma_chan;
-       struct completion       dma_access_complete;
-
-       struct fsmc_nand_timings *dev_timings;
-
-       dma_addr_t              data_pa;
-       void __iomem            *data_va;
-       void __iomem            *cmd_va;
-       void __iomem            *addr_va;
-       void __iomem            *regs_va;
-
-       void                    (*select_chip)(uint32_t bank, uint32_t busw);
-};
-
 static inline struct fsmc_nand_data *mtd_to_fsmc(struct mtd_info *mtd)
 {
        return container_of(mtd_to_nand(mtd), struct fsmc_nand_data, nand);
 }
 
-/* Assert CS signal based on chipnr */
-static void fsmc_select_chip(struct mtd_info *mtd, int chipnr)
-{
-       struct nand_chip *chip = mtd_to_nand(mtd);
-       struct fsmc_nand_data *host;
-
-       host = mtd_to_fsmc(mtd);
-
-       switch (chipnr) {
-       case -1:
-               chip->cmd_ctrl(mtd, NAND_CMD_NONE, 0 | NAND_CTRL_CHANGE);
-               break;
-       case 0:
-       case 1:
-       case 2:
-       case 3:
-               if (host->select_chip)
-                       host->select_chip(chipnr,
-                                       chip->options & NAND_BUSWIDTH_16);
-               break;
-
-       default:
-               dev_err(host->dev, "unsupported chip-select %d\n", chipnr);
-       }
-}
-
 /*
  * fsmc_cmd_ctrl - For facilitaing Hardware access
  * This routine allows hardware specific access to control-lines(ALE,CLE)
@@ -838,44 +769,46 @@ static bool filter(struct dma_chan *chan, void *slave)
 }
 
 static int fsmc_nand_probe_config_dt(struct platform_device *pdev,
-                                    struct device_node *np)
+                                    struct fsmc_nand_data *host,
+                                    struct nand_chip *nand)
 {
-       struct fsmc_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
+       struct device_node *np = pdev->dev.of_node;
        u32 val;
        int ret;
 
-       /* Set default NAND width to 8 bits */
-       pdata->width = 8;
+       nand->options = 0;
+
        if (!of_property_read_u32(np, "bank-width", &val)) {
                if (val == 2) {
-                       pdata->width = 16;
+                       nand->options |= NAND_BUSWIDTH_16;
                } else if (val != 1) {
                        dev_err(&pdev->dev, "invalid bank-width %u\n", val);
                        return -EINVAL;
                }
        }
+
        if (of_get_property(np, "nand-skip-bbtscan", NULL))
-               pdata->options = NAND_SKIP_BBTSCAN;
+               nand->options |= NAND_SKIP_BBTSCAN;
 
-       pdata->nand_timings = devm_kzalloc(&pdev->dev,
-                               sizeof(*pdata->nand_timings), GFP_KERNEL);
-       if (!pdata->nand_timings)
+       host->dev_timings = devm_kzalloc(&pdev->dev,
+                               sizeof(*host->dev_timings), GFP_KERNEL);
+       if (!host->dev_timings)
                return -ENOMEM;
-       ret = of_property_read_u8_array(np, "timings", (u8 *)pdata->nand_timings,
-                                               sizeof(*pdata->nand_timings));
+       ret = of_property_read_u8_array(np, "timings", (u8 *)host->dev_timings,
+                                               sizeof(*host->dev_timings));
        if (ret) {
                dev_info(&pdev->dev, "No timings in dts specified, using default timings!\n");
-               pdata->nand_timings = NULL;
+               host->dev_timings = NULL;
        }
 
        /* Set default NAND bank to 0 */
-       pdata->bank = 0;
+       host->bank = 0;
        if (!of_property_read_u32(np, "bank", &val)) {
                if (val > 3) {
                        dev_err(&pdev->dev, "invalid bank %u\n", val);
                        return -EINVAL;
                }
-               pdata->bank = val;
+               host->bank = val;
        }
        return 0;
 }
@@ -886,8 +819,6 @@ static int fsmc_nand_probe_config_dt(struct platform_device *pdev,
  */
 static int __init fsmc_nand_probe(struct platform_device *pdev)
 {
-       struct fsmc_nand_platform_data *pdata = dev_get_platdata(&pdev->dev);
-       struct device_node __maybe_unused *np = pdev->dev.of_node;
        struct fsmc_nand_data *host;
        struct mtd_info *mtd;
        struct nand_chip *nand;
@@ -897,22 +828,17 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
        u32 pid;
        int i;
 
-       pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
-       if (!pdata)
-               return -ENOMEM;
-
-       pdev->dev.platform_data = pdata;
-       ret = fsmc_nand_probe_config_dt(pdev, np);
-       if (ret) {
-               dev_err(&pdev->dev, "no platform data\n");
-               return -ENODEV;
-       }
-
        /* Allocate memory for the device structure (and zero it) */
        host = devm_kzalloc(&pdev->dev, sizeof(*host), GFP_KERNEL);
        if (!host)
                return -ENOMEM;
 
+       nand = &host->nand;
+
+       ret = fsmc_nand_probe_config_dt(pdev, host, nand);
+       if (ret)
+               return ret;
+
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "nand_data");
        host->data_va = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(host->data_va))
@@ -935,7 +861,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
        if (IS_ERR(host->regs_va))
                return PTR_ERR(host->regs_va);
 
-       host->clk = clk_get(&pdev->dev, NULL);
+       host->clk = devm_clk_get(&pdev->dev, NULL);
        if (IS_ERR(host->clk)) {
                dev_err(&pdev->dev, "failed to fetch block clock\n");
                return PTR_ERR(host->clk);
@@ -943,7 +869,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
 
        ret = clk_prepare_enable(host->clk);
        if (ret)
-               goto err_clk_prepare_enable;
+               return ret;
 
        /*
         * This device ID is actually a common AMBA ID as used on the
@@ -957,22 +883,15 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
                 AMBA_PART_BITS(pid), AMBA_MANF_BITS(pid),
                 AMBA_REV_BITS(pid), AMBA_CONFIG_BITS(pid));
 
-       host->bank = pdata->bank;
-       host->select_chip = pdata->select_bank;
-       host->partitions = pdata->partitions;
-       host->nr_partitions = pdata->nr_partitions;
        host->dev = &pdev->dev;
-       host->dev_timings = pdata->nand_timings;
-       host->mode = pdata->mode;
 
        if (host->mode == USE_DMA_ACCESS)
                init_completion(&host->dma_access_complete);
 
        /* Link all private pointers */
        mtd = nand_to_mtd(&host->nand);
-       nand = &host->nand;
        nand_set_controller_data(nand, host);
-       nand_set_flash_node(nand, np);
+       nand_set_flash_node(nand, pdev->dev.of_node);
 
        mtd->dev.parent = &pdev->dev;
        nand->IO_ADDR_R = host->data_va;
@@ -987,26 +906,18 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
        nand->ecc.mode = NAND_ECC_HW;
        nand->ecc.hwctl = fsmc_enable_hwecc;
        nand->ecc.size = 512;
-       nand->options = pdata->options;
-       nand->select_chip = fsmc_select_chip;
        nand->badblockbits = 7;
-       nand_set_flash_node(nand, np);
-
-       if (pdata->width == FSMC_NAND_BW16)
-               nand->options |= NAND_BUSWIDTH_16;
 
        switch (host->mode) {
        case USE_DMA_ACCESS:
                dma_cap_zero(mask);
                dma_cap_set(DMA_MEMCPY, mask);
-               host->read_dma_chan = dma_request_channel(mask, filter,
-                               pdata->read_dma_priv);
+               host->read_dma_chan = dma_request_channel(mask, filter, NULL);
                if (!host->read_dma_chan) {
                        dev_err(&pdev->dev, "Unable to get read dma channel\n");
                        goto err_req_read_chnl;
                }
-               host->write_dma_chan = dma_request_channel(mask, filter,
-                               pdata->write_dma_priv);
+               host->write_dma_chan = dma_request_channel(mask, filter, NULL);
                if (!host->write_dma_chan) {
                        dev_err(&pdev->dev, "Unable to get write dma channel\n");
                        goto err_req_write_chnl;
@@ -1107,18 +1018,8 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
        if (ret)
                goto err_probe;
 
-       /*
-        * The partition information can is accessed by (in the same precedence)
-        *
-        * command line through Bootloader,
-        * platform data,
-        * default partition information present in driver.
-        */
-       /*
-        * Check for partition info passed
-        */
        mtd->name = "nand";
-       ret = mtd_device_register(mtd, host->partitions, host->nr_partitions);
+       ret = mtd_device_register(mtd, NULL, 0);
        if (ret)
                goto err_probe;
 
@@ -1135,8 +1036,6 @@ err_req_write_chnl:
                dma_release_channel(host->read_dma_chan);
 err_req_read_chnl:
        clk_disable_unprepare(host->clk);
-err_clk_prepare_enable:
-       clk_put(host->clk);
        return ret;
 }
 
@@ -1155,7 +1054,6 @@ static int fsmc_nand_remove(struct platform_device *pdev)
                        dma_release_channel(host->read_dma_chan);
                }
                clk_disable_unprepare(host->clk);
-               clk_put(host->clk);
        }
 
        return 0;
@@ -1185,20 +1083,18 @@ static int fsmc_nand_resume(struct device *dev)
 
 static SIMPLE_DEV_PM_OPS(fsmc_nand_pm_ops, fsmc_nand_suspend, fsmc_nand_resume);
 
-#ifdef CONFIG_OF
 static const struct of_device_id fsmc_nand_id_table[] = {
        { .compatible = "st,spear600-fsmc-nand" },
        { .compatible = "stericsson,fsmc-nand" },
        {}
 };
 MODULE_DEVICE_TABLE(of, fsmc_nand_id_table);
-#endif
 
 static struct platform_driver fsmc_nand_driver = {
        .remove = fsmc_nand_remove,
        .driver = {
                .name = "fsmc-nand",
-               .of_match_table = of_match_ptr(fsmc_nand_id_table),
+               .of_match_table = fsmc_nand_id_table,
                .pm = &fsmc_nand_pm_ops,
        },
 };
index 0d24857469ab396ac10c165076fd380639aa4463..85294f150f4ff36effe127722003f6e69340bbba 100644 (file)
@@ -78,7 +78,9 @@ static void gpio_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
        gpio_nand_dosync(gpiomtd);
 
        if (ctrl & NAND_CTRL_CHANGE) {
-               gpio_set_value(gpiomtd->plat.gpio_nce, !(ctrl & NAND_NCE));
+               if (gpio_is_valid(gpiomtd->plat.gpio_nce))
+                       gpio_set_value(gpiomtd->plat.gpio_nce,
+                                      !(ctrl & NAND_NCE));
                gpio_set_value(gpiomtd->plat.gpio_cle, !!(ctrl & NAND_CLE));
                gpio_set_value(gpiomtd->plat.gpio_ale, !!(ctrl & NAND_ALE));
                gpio_nand_dosync(gpiomtd);
@@ -201,7 +203,8 @@ static int gpio_nand_remove(struct platform_device *pdev)
 
        if (gpio_is_valid(gpiomtd->plat.gpio_nwp))
                gpio_set_value(gpiomtd->plat.gpio_nwp, 0);
-       gpio_set_value(gpiomtd->plat.gpio_nce, 1);
+       if (gpio_is_valid(gpiomtd->plat.gpio_nce))
+               gpio_set_value(gpiomtd->plat.gpio_nce, 1);
 
        return 0;
 }
@@ -239,10 +242,13 @@ static int gpio_nand_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-       ret = devm_gpio_request(&pdev->dev, gpiomtd->plat.gpio_nce, "NAND NCE");
-       if (ret)
-               return ret;
-       gpio_direction_output(gpiomtd->plat.gpio_nce, 1);
+       if (gpio_is_valid(gpiomtd->plat.gpio_nce)) {
+               ret = devm_gpio_request(&pdev->dev, gpiomtd->plat.gpio_nce,
+                                       "NAND NCE");
+               if (ret)
+                       return ret;
+               gpio_direction_output(gpiomtd->plat.gpio_nce, 1);
+       }
 
        if (gpio_is_valid(gpiomtd->plat.gpio_nwp)) {
                ret = devm_gpio_request(&pdev->dev, gpiomtd->plat.gpio_nwp,
diff --git a/drivers/mtd/nand/nand_amd.c b/drivers/mtd/nand/nand_amd.c
new file mode 100644 (file)
index 0000000..170403a
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2017 Free Electrons
+ * Copyright (C) 2017 NextThing Co
+ *
+ * Author: Boris Brezillon <boris.brezillon@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/mtd/nand.h>
+
+static void amd_nand_decode_id(struct nand_chip *chip)
+{
+       struct mtd_info *mtd = nand_to_mtd(chip);
+
+       nand_decode_ext_id(chip);
+
+       /*
+        * Check for Spansion/AMD ID + repeating 5th, 6th byte since
+        * some Spansion chips have erasesize that conflicts with size
+        * listed in nand_ids table.
+        * Data sheet (5 byte ID): Spansion S30ML-P ORNAND (p.39)
+        */
+       if (chip->id.data[4] != 0x00 && chip->id.data[5] == 0x00 &&
+           chip->id.data[6] == 0x00 && chip->id.data[7] == 0x00 &&
+           mtd->writesize == 512) {
+               mtd->erasesize = 128 * 1024;
+               mtd->erasesize <<= ((chip->id.data[3] & 0x03) << 1);
+       }
+}
+
+static int amd_nand_init(struct nand_chip *chip)
+{
+       if (nand_is_slc(chip))
+               chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
+
+       return 0;
+}
+
+const struct nand_manufacturer_ops amd_nand_manuf_ops = {
+       .detect = amd_nand_decode_id,
+       .init = amd_nand_init,
+};
index b0524f8accb6206f50e5b30d422b81ec311a40f3..d474378ed810b3c3ab19d8a4e85e77e0eb15511c 100644 (file)
@@ -139,6 +139,74 @@ const struct mtd_ooblayout_ops nand_ooblayout_lp_ops = {
 };
 EXPORT_SYMBOL_GPL(nand_ooblayout_lp_ops);
 
+/*
+ * Support the old "large page" layout used for 1-bit Hamming ECC where ECC
+ * are placed at a fixed offset.
+ */
+static int nand_ooblayout_ecc_lp_hamming(struct mtd_info *mtd, int section,
+                                        struct mtd_oob_region *oobregion)
+{
+       struct nand_chip *chip = mtd_to_nand(mtd);
+       struct nand_ecc_ctrl *ecc = &chip->ecc;
+
+       if (section)
+               return -ERANGE;
+
+       switch (mtd->oobsize) {
+       case 64:
+               oobregion->offset = 40;
+               break;
+       case 128:
+               oobregion->offset = 80;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       oobregion->length = ecc->total;
+       if (oobregion->offset + oobregion->length > mtd->oobsize)
+               return -ERANGE;
+
+       return 0;
+}
+
+static int nand_ooblayout_free_lp_hamming(struct mtd_info *mtd, int section,
+                                         struct mtd_oob_region *oobregion)
+{
+       struct nand_chip *chip = mtd_to_nand(mtd);
+       struct nand_ecc_ctrl *ecc = &chip->ecc;
+       int ecc_offset = 0;
+
+       if (section < 0 || section > 1)
+               return -ERANGE;
+
+       switch (mtd->oobsize) {
+       case 64:
+               ecc_offset = 40;
+               break;
+       case 128:
+               ecc_offset = 80;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (section == 0) {
+               oobregion->offset = 2;
+               oobregion->length = ecc_offset - 2;
+       } else {
+               oobregion->offset = ecc_offset + ecc->total;
+               oobregion->length = mtd->oobsize - oobregion->offset;
+       }
+
+       return 0;
+}
+
+const struct mtd_ooblayout_ops nand_ooblayout_lp_hamming_ops = {
+       .ecc = nand_ooblayout_ecc_lp_hamming,
+       .free = nand_ooblayout_free_lp_hamming,
+};
+
 static int check_offs_len(struct mtd_info *mtd,
                                        loff_t ofs, uint64_t len)
 {
@@ -354,40 +422,32 @@ static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
  */
 static int nand_block_bad(struct mtd_info *mtd, loff_t ofs)
 {
-       int page, res = 0, i = 0;
+       int page, page_end, res;
        struct nand_chip *chip = mtd_to_nand(mtd);
-       u16 bad;
+       u8 bad;
 
        if (chip->bbt_options & NAND_BBT_SCANLASTPAGE)
                ofs += mtd->erasesize - mtd->writesize;
 
        page = (int)(ofs >> chip->page_shift) & chip->pagemask;
+       page_end = page + (chip->bbt_options & NAND_BBT_SCAN2NDPAGE ? 2 : 1);
 
-       do {
-               if (chip->options & NAND_BUSWIDTH_16) {
-                       chip->cmdfunc(mtd, NAND_CMD_READOOB,
-                                       chip->badblockpos & 0xFE, page);
-                       bad = cpu_to_le16(chip->read_word(mtd));
-                       if (chip->badblockpos & 0x1)
-                               bad >>= 8;
-                       else
-                               bad &= 0xFF;
-               } else {
-                       chip->cmdfunc(mtd, NAND_CMD_READOOB, chip->badblockpos,
-                                       page);
-                       bad = chip->read_byte(mtd);
-               }
+       for (; page < page_end; page++) {
+               res = chip->ecc.read_oob(mtd, chip, page);
+               if (res)
+                       return res;
+
+               bad = chip->oob_poi[chip->badblockpos];
 
                if (likely(chip->badblockbits == 8))
                        res = bad != 0xFF;
                else
                        res = hweight8(bad) < chip->badblockbits;
-               ofs += mtd->writesize;
-               page = (int)(ofs >> chip->page_shift) & chip->pagemask;
-               i++;
-       } while (!res && i < 2 && (chip->bbt_options & NAND_BBT_SCAN2NDPAGE));
+               if (res)
+                       return res;
+       }
 
-       return res;
+       return 0;
 }
 
 /**
@@ -676,6 +736,8 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,
        case NAND_CMD_ERASE2:
        case NAND_CMD_SEQIN:
        case NAND_CMD_STATUS:
+       case NAND_CMD_READID:
+       case NAND_CMD_SET_FEATURES:
                return;
 
        case NAND_CMD_RESET:
@@ -794,6 +856,8 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
        case NAND_CMD_ERASE2:
        case NAND_CMD_SEQIN:
        case NAND_CMD_STATUS:
+       case NAND_CMD_READID:
+       case NAND_CMD_SET_FEATURES:
                return;
 
        case NAND_CMD_RNDIN:
@@ -1958,7 +2022,9 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
                if (!aligned)
                        use_bufpoi = 1;
                else if (chip->options & NAND_USE_BOUNCE_BUFFER)
-                       use_bufpoi = !virt_addr_valid(buf);
+                       use_bufpoi = !virt_addr_valid(buf) ||
+                                    !IS_ALIGNED((unsigned long)buf,
+                                                chip->buf_align);
                else
                        use_bufpoi = 0;
 
@@ -1997,8 +2063,6 @@ read_retry:
                                break;
                        }
 
-                       max_bitflips = max_t(unsigned int, max_bitflips, ret);
-
                        /* Transfer not aligned data */
                        if (use_bufpoi) {
                                if (!NAND_HAS_SUBPAGE_READ(chip) && !oob &&
@@ -2049,6 +2113,7 @@ read_retry:
                        }
 
                        buf += bytes;
+                       max_bitflips = max_t(unsigned int, max_bitflips, ret);
                } else {
                        memcpy(buf, chip->buffers->databuf + col, bytes);
                        buf += bytes;
@@ -2637,7 +2702,7 @@ static int nand_write_page_syndrome(struct mtd_info *mtd,
 }
 
 /**
- * nand_write_page - [REPLACEABLE] write one page
+ * nand_write_page - write one page
  * @mtd: MTD device structure
  * @chip: NAND chip descriptor
  * @offset: address offset within the page
@@ -2815,7 +2880,9 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
                if (part_pagewr)
                        use_bufpoi = 1;
                else if (chip->options & NAND_USE_BOUNCE_BUFFER)
-                       use_bufpoi = !virt_addr_valid(buf);
+                       use_bufpoi = !virt_addr_valid(buf) ||
+                                    !IS_ALIGNED((unsigned long)buf,
+                                                chip->buf_align);
                else
                        use_bufpoi = 0;
 
@@ -2840,9 +2907,10 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
                        /* We still need to erase leftover OOB data */
                        memset(chip->oob_poi, 0xff, mtd->oobsize);
                }
-               ret = chip->write_page(mtd, chip, column, bytes, wbuf,
-                                       oob_required, page, cached,
-                                       (ops->mode == MTD_OPS_RAW));
+
+               ret = nand_write_page(mtd, chip, column, bytes, wbuf,
+                                     oob_required, page, cached,
+                                     (ops->mode == MTD_OPS_RAW));
                if (ret)
                        break;
 
@@ -3385,8 +3453,10 @@ static void nand_shutdown(struct mtd_info *mtd)
 }
 
 /* Set default functions */
-static void nand_set_defaults(struct nand_chip *chip, int busw)
+static void nand_set_defaults(struct nand_chip *chip)
 {
+       unsigned int busw = chip->options & NAND_BUSWIDTH_16;
+
        /* check for proper chip_delay setup, set 20us if not */
        if (!chip->chip_delay)
                chip->chip_delay = 20;
@@ -3431,6 +3501,8 @@ static void nand_set_defaults(struct nand_chip *chip, int busw)
                nand_hw_control_init(chip->controller);
        }
 
+       if (!chip->buf_align)
+               chip->buf_align = 1;
 }
 
 /* Sanitize ONFI strings so we can safely print them */
@@ -3464,9 +3536,10 @@ static u16 onfi_crc16(u16 crc, u8 const *p, size_t len)
 }
 
 /* Parse the Extended Parameter Page. */
-static int nand_flash_detect_ext_param_page(struct mtd_info *mtd,
-               struct nand_chip *chip, struct nand_onfi_params *p)
+static int nand_flash_detect_ext_param_page(struct nand_chip *chip,
+                                           struct nand_onfi_params *p)
 {
+       struct mtd_info *mtd = nand_to_mtd(chip);
        struct onfi_ext_param_page *ep;
        struct onfi_ext_section *s;
        struct onfi_ext_ecc_info *ecc;
@@ -3534,36 +3607,12 @@ ext_out:
        return ret;
 }
 
-static int nand_setup_read_retry_micron(struct mtd_info *mtd, int retry_mode)
-{
-       struct nand_chip *chip = mtd_to_nand(mtd);
-       uint8_t feature[ONFI_SUBFEATURE_PARAM_LEN] = {retry_mode};
-
-       return chip->onfi_set_features(mtd, chip, ONFI_FEATURE_ADDR_READ_RETRY,
-                       feature);
-}
-
-/*
- * Configure chip properties from Micron vendor-specific ONFI table
- */
-static void nand_onfi_detect_micron(struct nand_chip *chip,
-               struct nand_onfi_params *p)
-{
-       struct nand_onfi_vendor_micron *micron = (void *)p->vendor;
-
-       if (le16_to_cpu(p->vendor_revision) < 1)
-               return;
-
-       chip->read_retries = micron->read_retry_options;
-       chip->setup_read_retry = nand_setup_read_retry_micron;
-}
-
 /*
  * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise.
  */
-static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
-                                       int *busw)
+static int nand_flash_detect_onfi(struct nand_chip *chip)
 {
+       struct mtd_info *mtd = nand_to_mtd(chip);
        struct nand_onfi_params *p = &chip->onfi_params;
        int i, j;
        int val;
@@ -3633,9 +3682,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
        chip->blocks_per_die = le32_to_cpu(p->blocks_per_lun);
 
        if (onfi_feature(chip) & ONFI_FEATURE_16_BIT_BUS)
-               *busw = NAND_BUSWIDTH_16;
-       else
-               *busw = 0;
+               chip->options |= NAND_BUSWIDTH_16;
 
        if (p->ecc_bits != 0xff) {
                chip->ecc_strength_ds = p->ecc_bits;
@@ -3653,24 +3700,21 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
                        chip->cmdfunc = nand_command_lp;
 
                /* The Extended Parameter Page is supported since ONFI 2.1. */
-               if (nand_flash_detect_ext_param_page(mtd, chip, p))
+               if (nand_flash_detect_ext_param_page(chip, p))
                        pr_warn("Failed to detect ONFI extended param page\n");
        } else {
                pr_warn("Could not retrieve ONFI ECC requirements\n");
        }
 
-       if (p->jedec_id == NAND_MFR_MICRON)
-               nand_onfi_detect_micron(chip, p);
-
        return 1;
 }
 
 /*
  * Check if the NAND chip is JEDEC compliant, returns 1 if it is, 0 otherwise.
  */
-static int nand_flash_detect_jedec(struct mtd_info *mtd, struct nand_chip *chip,
-                                       int *busw)
+static int nand_flash_detect_jedec(struct nand_chip *chip)
 {
+       struct mtd_info *mtd = nand_to_mtd(chip);
        struct nand_jedec_params *p = &chip->jedec_params;
        struct jedec_ecc_info *ecc;
        int val;
@@ -3729,9 +3773,7 @@ static int nand_flash_detect_jedec(struct mtd_info *mtd, struct nand_chip *chip,
        chip->bits_per_cell = p->bits_per_cell;
 
        if (jedec_feature(chip) & JEDEC_FEATURE_16_BIT_BUS)
-               *busw = NAND_BUSWIDTH_16;
-       else
-               *busw = 0;
+               chip->options |= NAND_BUSWIDTH_16;
 
        /* ECC info */
        ecc = &p->ecc_info[0];
@@ -3820,165 +3862,46 @@ static int nand_get_bits_per_cell(u8 cellinfo)
  * chip. The rest of the parameters must be decoded according to generic or
  * manufacturer-specific "extended ID" decoding patterns.
  */
-static void nand_decode_ext_id(struct mtd_info *mtd, struct nand_chip *chip,
-                               u8 id_data[8], int *busw)
+void nand_decode_ext_id(struct nand_chip *chip)
 {
-       int extid, id_len;
+       struct mtd_info *mtd = nand_to_mtd(chip);
+       int extid;
+       u8 *id_data = chip->id.data;
        /* The 3rd id byte holds MLC / multichip data */
        chip->bits_per_cell = nand_get_bits_per_cell(id_data[2]);
        /* The 4th id byte is the important one */
        extid = id_data[3];
 
-       id_len = nand_id_len(id_data, 8);
-
-       /*
-        * Field definitions are in the following datasheets:
-        * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32)
-        * New Samsung (6 byte ID): Samsung K9GAG08U0F (p.44)
-        * Hynix MLC   (6 byte ID): Hynix H27UBG8T2B (p.22)
-        *
-        * Check for ID length, non-zero 6th byte, cell type, and Hynix/Samsung
-        * ID to decide what to do.
-        */
-       if (id_len == 6 && id_data[0] == NAND_MFR_SAMSUNG &&
-                       !nand_is_slc(chip) && id_data[5] != 0x00) {
-               /* Calc pagesize */
-               mtd->writesize = 2048 << (extid & 0x03);
-               extid >>= 2;
-               /* Calc oobsize */
-               switch (((extid >> 2) & 0x04) | (extid & 0x03)) {
-               case 1:
-                       mtd->oobsize = 128;
-                       break;
-               case 2:
-                       mtd->oobsize = 218;
-                       break;
-               case 3:
-                       mtd->oobsize = 400;
-                       break;
-               case 4:
-                       mtd->oobsize = 436;
-                       break;
-               case 5:
-                       mtd->oobsize = 512;
-                       break;
-               case 6:
-                       mtd->oobsize = 640;
-                       break;
-               case 7:
-               default: /* Other cases are "reserved" (unknown) */
-                       mtd->oobsize = 1024;
-                       break;
-               }
-               extid >>= 2;
-               /* Calc blocksize */
-               mtd->erasesize = (128 * 1024) <<
-                       (((extid >> 1) & 0x04) | (extid & 0x03));
-               *busw = 0;
-       } else if (id_len == 6 && id_data[0] == NAND_MFR_HYNIX &&
-                       !nand_is_slc(chip)) {
-               unsigned int tmp;
-
-               /* Calc pagesize */
-               mtd->writesize = 2048 << (extid & 0x03);
-               extid >>= 2;
-               /* Calc oobsize */
-               switch (((extid >> 2) & 0x04) | (extid & 0x03)) {
-               case 0:
-                       mtd->oobsize = 128;
-                       break;
-               case 1:
-                       mtd->oobsize = 224;
-                       break;
-               case 2:
-                       mtd->oobsize = 448;
-                       break;
-               case 3:
-                       mtd->oobsize = 64;
-                       break;
-               case 4:
-                       mtd->oobsize = 32;
-                       break;
-               case 5:
-                       mtd->oobsize = 16;
-                       break;
-               default:
-                       mtd->oobsize = 640;
-                       break;
-               }
-               extid >>= 2;
-               /* Calc blocksize */
-               tmp = ((extid >> 1) & 0x04) | (extid & 0x03);
-               if (tmp < 0x03)
-                       mtd->erasesize = (128 * 1024) << tmp;
-               else if (tmp == 0x03)
-                       mtd->erasesize = 768 * 1024;
-               else
-                       mtd->erasesize = (64 * 1024) << tmp;
-               *busw = 0;
-       } else {
-               /* Calc pagesize */
-               mtd->writesize = 1024 << (extid & 0x03);
-               extid >>= 2;
-               /* Calc oobsize */
-               mtd->oobsize = (8 << (extid & 0x01)) *
-                       (mtd->writesize >> 9);
-               extid >>= 2;
-               /* Calc blocksize. Blocksize is multiples of 64KiB */
-               mtd->erasesize = (64 * 1024) << (extid & 0x03);
-               extid >>= 2;
-               /* Get buswidth information */
-               *busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0;
-
-               /*
-                * Toshiba 24nm raw SLC (i.e., not BENAND) have 32B OOB per
-                * 512B page. For Toshiba SLC, we decode the 5th/6th byte as
-                * follows:
-                * - ID byte 6, bits[2:0]: 100b -> 43nm, 101b -> 32nm,
-                *                         110b -> 24nm
-                * - ID byte 5, bit[7]:    1 -> BENAND, 0 -> raw SLC
-                */
-               if (id_len >= 6 && id_data[0] == NAND_MFR_TOSHIBA &&
-                               nand_is_slc(chip) &&
-                               (id_data[5] & 0x7) == 0x6 /* 24nm */ &&
-                               !(id_data[4] & 0x80) /* !BENAND */) {
-                       mtd->oobsize = 32 * mtd->writesize >> 9;
-               }
-
-       }
+       /* Calc pagesize */
+       mtd->writesize = 1024 << (extid & 0x03);
+       extid >>= 2;
+       /* Calc oobsize */
+       mtd->oobsize = (8 << (extid & 0x01)) * (mtd->writesize >> 9);
+       extid >>= 2;
+       /* Calc blocksize. Blocksize is multiples of 64KiB */
+       mtd->erasesize = (64 * 1024) << (extid & 0x03);
+       extid >>= 2;
+       /* Get buswidth information */
+       if (extid & 0x1)
+               chip->options |= NAND_BUSWIDTH_16;
 }
+EXPORT_SYMBOL_GPL(nand_decode_ext_id);
 
 /*
  * Old devices have chip data hardcoded in the device ID table. nand_decode_id
  * decodes a matching ID table entry and assigns the MTD size parameters for
  * the chip.
  */
-static void nand_decode_id(struct mtd_info *mtd, struct nand_chip *chip,
-                               struct nand_flash_dev *type, u8 id_data[8],
-                               int *busw)
+static void nand_decode_id(struct nand_chip *chip, struct nand_flash_dev *type)
 {
-       int maf_id = id_data[0];
+       struct mtd_info *mtd = nand_to_mtd(chip);
 
        mtd->erasesize = type->erasesize;
        mtd->writesize = type->pagesize;
        mtd->oobsize = mtd->writesize / 32;
-       *busw = type->options & NAND_BUSWIDTH_16;
 
        /* All legacy ID NAND are small-page, SLC */
        chip->bits_per_cell = 1;
-
-       /*
-        * Check for Spansion/AMD ID + repeating 5th, 6th byte since
-        * some Spansion chips have erasesize that conflicts with size
-        * listed in nand_ids table.
-        * Data sheet (5 byte ID): Spansion S30ML-P ORNAND (p.39)
-        */
-       if (maf_id == NAND_MFR_AMD && id_data[4] != 0x00 && id_data[5] == 0x00
-                       && id_data[6] == 0x00 && id_data[7] == 0x00
-                       && mtd->writesize == 512) {
-               mtd->erasesize = 128 * 1024;
-               mtd->erasesize <<= ((id_data[3] & 0x03) << 1);
-       }
 }
 
 /*
@@ -3986,36 +3909,15 @@ static void nand_decode_id(struct mtd_info *mtd, struct nand_chip *chip,
  * heuristic patterns using various detected parameters (e.g., manufacturer,
  * page size, cell-type information).
  */
-static void nand_decode_bbm_options(struct mtd_info *mtd,
-                                   struct nand_chip *chip, u8 id_data[8])
+static void nand_decode_bbm_options(struct nand_chip *chip)
 {
-       int maf_id = id_data[0];
+       struct mtd_info *mtd = nand_to_mtd(chip);
 
        /* Set the bad block position */
        if (mtd->writesize > 512 || (chip->options & NAND_BUSWIDTH_16))
                chip->badblockpos = NAND_LARGE_BADBLOCK_POS;
        else
                chip->badblockpos = NAND_SMALL_BADBLOCK_POS;
-
-       /*
-        * Bad block marker is stored in the last page of each block on Samsung
-        * and Hynix MLC devices; stored in first two pages of each block on
-        * Micron devices with 2KiB pages and on SLC Samsung, Hynix, Toshiba,
-        * AMD/Spansion, and Macronix.  All others scan only the first page.
-        */
-       if (!nand_is_slc(chip) &&
-                       (maf_id == NAND_MFR_SAMSUNG ||
-                        maf_id == NAND_MFR_HYNIX))
-               chip->bbt_options |= NAND_BBT_SCANLASTPAGE;
-       else if ((nand_is_slc(chip) &&
-                               (maf_id == NAND_MFR_SAMSUNG ||
-                                maf_id == NAND_MFR_HYNIX ||
-                                maf_id == NAND_MFR_TOSHIBA ||
-                                maf_id == NAND_MFR_AMD ||
-                                maf_id == NAND_MFR_MACRONIX)) ||
-                       (mtd->writesize == 2048 &&
-                        maf_id == NAND_MFR_MICRON))
-               chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
 }
 
 static inline bool is_full_id_nand(struct nand_flash_dev *type)
@@ -4023,9 +3925,12 @@ static inline bool is_full_id_nand(struct nand_flash_dev *type)
        return type->id_len;
 }
 
-static bool find_full_id_nand(struct mtd_info *mtd, struct nand_chip *chip,
-                  struct nand_flash_dev *type, u8 *id_data, int *busw)
+static bool find_full_id_nand(struct nand_chip *chip,
+                             struct nand_flash_dev *type)
 {
+       struct mtd_info *mtd = nand_to_mtd(chip);
+       u8 *id_data = chip->id.data;
+
        if (!strncmp(type->id, id_data, type->id_len)) {
                mtd->writesize = type->pagesize;
                mtd->erasesize = type->erasesize;
@@ -4039,8 +3944,6 @@ static bool find_full_id_nand(struct mtd_info *mtd, struct nand_chip *chip,
                chip->onfi_timing_mode_default =
                                        type->onfi_timing_mode_default;
 
-               *busw = type->options & NAND_BUSWIDTH_16;
-
                if (!mtd->name)
                        mtd->name = type->name;
 
@@ -4049,16 +3952,64 @@ static bool find_full_id_nand(struct mtd_info *mtd, struct nand_chip *chip,
        return false;
 }
 
+/*
+ * Manufacturer detection. Only used when the NAND is not ONFI or JEDEC
+ * compliant and does not have a full-id or legacy-id entry in the nand_ids
+ * table.
+ */
+static void nand_manufacturer_detect(struct nand_chip *chip)
+{
+       /*
+        * Try manufacturer detection if available and use
+        * nand_decode_ext_id() otherwise.
+        */
+       if (chip->manufacturer.desc && chip->manufacturer.desc->ops &&
+           chip->manufacturer.desc->ops->detect)
+               chip->manufacturer.desc->ops->detect(chip);
+       else
+               nand_decode_ext_id(chip);
+}
+
+/*
+ * Manufacturer initialization. This function is called for all NANDs including
+ * ONFI and JEDEC compliant ones.
+ * Manufacturer drivers should put all their specific initialization code in
+ * their ->init() hook.
+ */
+static int nand_manufacturer_init(struct nand_chip *chip)
+{
+       if (!chip->manufacturer.desc || !chip->manufacturer.desc->ops ||
+           !chip->manufacturer.desc->ops->init)
+               return 0;
+
+       return chip->manufacturer.desc->ops->init(chip);
+}
+
+/*
+ * Manufacturer cleanup. This function is called for all NANDs including
+ * ONFI and JEDEC compliant ones.
+ * Manufacturer drivers should put all their specific cleanup code in their
+ * ->cleanup() hook.
+ */
+static void nand_manufacturer_cleanup(struct nand_chip *chip)
+{
+       /* Release manufacturer private data */
+       if (chip->manufacturer.desc && chip->manufacturer.desc->ops &&
+           chip->manufacturer.desc->ops->cleanup)
+               chip->manufacturer.desc->ops->cleanup(chip);
+}
+
 /*
  * Get the flash and manufacturer id and lookup if the type is supported.
  */
-static int nand_get_flash_type(struct mtd_info *mtd, struct nand_chip *chip,
-                              int *maf_id, int *dev_id,
-                              struct nand_flash_dev *type)
+static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)
 {
+       const struct nand_manufacturer *manufacturer;
+       struct mtd_info *mtd = nand_to_mtd(chip);
        int busw;
-       int i, maf_idx;
-       u8 id_data[8];
+       int i, ret;
+       u8 *id_data = chip->id.data;
+       u8 maf_id, dev_id;
 
        /*
         * Reset the chip, required by some chips (e.g. Micron MT29FxGxxxxx)
@@ -4073,8 +4024,8 @@ static int nand_get_flash_type(struct mtd_info *mtd, struct nand_chip *chip,
        chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
 
        /* Read manufacturer and device IDs */
-       *maf_id = chip->read_byte(mtd);
-       *dev_id = chip->read_byte(mtd);
+       maf_id = chip->read_byte(mtd);
+       dev_id = chip->read_byte(mtd);
 
        /*
         * Try again to make sure, as some systems the bus-hold or other
@@ -4089,20 +4040,41 @@ static int nand_get_flash_type(struct mtd_info *mtd, struct nand_chip *chip,
        for (i = 0; i < 8; i++)
                id_data[i] = chip->read_byte(mtd);
 
-       if (id_data[0] != *maf_id || id_data[1] != *dev_id) {
+       if (id_data[0] != maf_id || id_data[1] != dev_id) {
                pr_info("second ID read did not match %02x,%02x against %02x,%02x\n",
-                       *maf_id, *dev_id, id_data[0], id_data[1]);
+                       maf_id, dev_id, id_data[0], id_data[1]);
                return -ENODEV;
        }
 
+       chip->id.len = nand_id_len(id_data, 8);
+
+       /* Try to identify manufacturer */
+       manufacturer = nand_get_manufacturer(maf_id);
+       chip->manufacturer.desc = manufacturer;
+
        if (!type)
                type = nand_flash_ids;
 
+       /*
+        * Save the NAND_BUSWIDTH_16 flag before letting auto-detection logic
+        * override it.
+        * This is required to make sure initial NAND bus width set by the
+        * NAND controller driver is coherent with the real NAND bus width
+        * (extracted by auto-detection code).
+        */
+       busw = chip->options & NAND_BUSWIDTH_16;
+
+       /*
+        * The flag is only set (never cleared), reset it to its default value
+        * before starting auto-detection.
+        */
+       chip->options &= ~NAND_BUSWIDTH_16;
+
        for (; type->name != NULL; type++) {
                if (is_full_id_nand(type)) {
-                       if (find_full_id_nand(mtd, chip, type, id_data, &busw))
+                       if (find_full_id_nand(chip, type))
                                goto ident_done;
-               } else if (*dev_id == type->dev_id) {
+               } else if (dev_id == type->dev_id) {
                        break;
                }
        }
@@ -4110,11 +4082,11 @@ static int nand_get_flash_type(struct mtd_info *mtd, struct nand_chip *chip,
        chip->onfi_version = 0;
        if (!type->name || !type->pagesize) {
                /* Check if the chip is ONFI compliant */
-               if (nand_flash_detect_onfi(mtd, chip, &busw))
+               if (nand_flash_detect_onfi(chip))
                        goto ident_done;
 
                /* Check if the chip is JEDEC compliant */
-               if (nand_flash_detect_jedec(mtd, chip, &busw))
+               if (nand_flash_detect_jedec(chip))
                        goto ident_done;
        }
 
@@ -4126,48 +4098,34 @@ static int nand_get_flash_type(struct mtd_info *mtd, struct nand_chip *chip,
 
        chip->chipsize = (uint64_t)type->chipsize << 20;
 
-       if (!type->pagesize) {
-               /* Decode parameters from extended ID */
-               nand_decode_ext_id(mtd, chip, id_data, &busw);
-       } else {
-               nand_decode_id(mtd, chip, type, id_data, &busw);
-       }
+       if (!type->pagesize)
+               nand_manufacturer_detect(chip);
+       else
+               nand_decode_id(chip, type);
+
        /* Get chip options */
        chip->options |= type->options;
 
-       /*
-        * Check if chip is not a Samsung device. Do not clear the
-        * options for chips which do not have an extended id.
-        */
-       if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize)
-               chip->options &= ~NAND_SAMSUNG_LP_OPTIONS;
 ident_done:
 
-       /* Try to identify manufacturer */
-       for (maf_idx = 0; nand_manuf_ids[maf_idx].id != 0x0; maf_idx++) {
-               if (nand_manuf_ids[maf_idx].id == *maf_id)
-                       break;
-       }
-
        if (chip->options & NAND_BUSWIDTH_AUTO) {
-               WARN_ON(chip->options & NAND_BUSWIDTH_16);
-               chip->options |= busw;
-               nand_set_defaults(chip, busw);
+               WARN_ON(busw & NAND_BUSWIDTH_16);
+               nand_set_defaults(chip);
        } else if (busw != (chip->options & NAND_BUSWIDTH_16)) {
                /*
                 * Check, if buswidth is correct. Hardware drivers should set
                 * chip correct!
                 */
                pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n",
-                       *maf_id, *dev_id);
-               pr_info("%s %s\n", nand_manuf_ids[maf_idx].name, mtd->name);
-               pr_warn("bus width %d instead %d bit\n",
-                          (chip->options & NAND_BUSWIDTH_16) ? 16 : 8,
-                          busw ? 16 : 8);
+                       maf_id, dev_id);
+               pr_info("%s %s\n", nand_manufacturer_name(manufacturer),
+                       mtd->name);
+               pr_warn("bus width %d instead of %d bits\n", busw ? 16 : 8,
+                       (chip->options & NAND_BUSWIDTH_16) ? 16 : 8);
                return -EINVAL;
        }
 
-       nand_decode_bbm_options(mtd, chip, id_data);
+       nand_decode_bbm_options(chip);
 
        /* Calculate the address shift from the page size */
        chip->page_shift = ffs(mtd->writesize) - 1;
@@ -4190,18 +4148,22 @@ ident_done:
        if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
                chip->cmdfunc = nand_command_lp;
 
+       ret = nand_manufacturer_init(chip);
+       if (ret)
+               return ret;
+
        pr_info("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n",
-               *maf_id, *dev_id);
+               maf_id, dev_id);
 
        if (chip->onfi_version)
-               pr_info("%s %s\n", nand_manuf_ids[maf_idx].name,
-                               chip->onfi_params.model);
+               pr_info("%s %s\n", nand_manufacturer_name(manufacturer),
+                       chip->onfi_params.model);
        else if (chip->jedec_version)
-               pr_info("%s %s\n", nand_manuf_ids[maf_idx].name,
-                               chip->jedec_params.model);
+               pr_info("%s %s\n", nand_manufacturer_name(manufacturer),
+                       chip->jedec_params.model);
        else
-               pr_info("%s %s\n", nand_manuf_ids[maf_idx].name,
-                               type->name);
+               pr_info("%s %s\n", nand_manufacturer_name(manufacturer),
+                       type->name);
 
        pr_info("%d MiB, %s, erase size: %d KiB, page size: %d, OOB size: %d\n",
                (int)(chip->chipsize >> 20), nand_is_slc(chip) ? "SLC" : "MLC",
@@ -4333,12 +4295,6 @@ static int nand_dt_init(struct nand_chip *chip)
        ecc_strength = of_get_nand_ecc_strength(dn);
        ecc_step = of_get_nand_ecc_step_size(dn);
 
-       if ((ecc_step >= 0 && !(ecc_strength >= 0)) ||
-           (!(ecc_step >= 0) && ecc_strength >= 0)) {
-               pr_err("must set both strength and step size in DT\n");
-               return -EINVAL;
-       }
-
        if (ecc_mode >= 0)
                chip->ecc.mode = ecc_mode;
 
@@ -4391,10 +4347,10 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
                return -EINVAL;
        }
        /* Set the default functions */
-       nand_set_defaults(chip, chip->options & NAND_BUSWIDTH_16);
+       nand_set_defaults(chip);
 
        /* Read the flash type */
-       ret = nand_get_flash_type(mtd, chip, &nand_maf_id, &nand_dev_id, table);
+       ret = nand_detect(chip, table);
        if (ret) {
                if (!(chip->options & NAND_SCAN_SILENT_NODEV))
                        pr_warn("No NAND device found\n");
@@ -4419,6 +4375,9 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
        if (ret)
                return ret;
 
+       nand_maf_id = chip->id.data[0];
+       nand_dev_id = chip->id.data[1];
+
        chip->select_chip(mtd, -1);
 
        /* Check for a chip array */
@@ -4610,7 +4569,7 @@ int nand_scan_tail(struct mtd_info *mtd)
 {
        struct nand_chip *chip = mtd_to_nand(mtd);
        struct nand_ecc_ctrl *ecc = &chip->ecc;
-       struct nand_buffers *nbuf;
+       struct nand_buffers *nbuf = NULL;
        int ret;
 
        /* New bad blocks should be marked in OOB, flash-based BBT, or both */
@@ -4624,13 +4583,28 @@ int nand_scan_tail(struct mtd_info *mtd)
        }
 
        if (!(chip->options & NAND_OWN_BUFFERS)) {
-               nbuf = kzalloc(sizeof(*nbuf) + mtd->writesize
-                               + mtd->oobsize * 3, GFP_KERNEL);
+               nbuf = kzalloc(sizeof(*nbuf), GFP_KERNEL);
                if (!nbuf)
                        return -ENOMEM;
-               nbuf->ecccalc = (uint8_t *)(nbuf + 1);
-               nbuf->ecccode = nbuf->ecccalc + mtd->oobsize;
-               nbuf->databuf = nbuf->ecccode + mtd->oobsize;
+
+               nbuf->ecccalc = kmalloc(mtd->oobsize, GFP_KERNEL);
+               if (!nbuf->ecccalc) {
+                       ret = -ENOMEM;
+                       goto err_free;
+               }
+
+               nbuf->ecccode = kmalloc(mtd->oobsize, GFP_KERNEL);
+               if (!nbuf->ecccode) {
+                       ret = -ENOMEM;
+                       goto err_free;
+               }
+
+               nbuf->databuf = kmalloc(mtd->writesize + mtd->oobsize,
+                                       GFP_KERNEL);
+               if (!nbuf->databuf) {
+                       ret = -ENOMEM;
+                       goto err_free;
+               }
 
                chip->buffers = nbuf;
        } else {
@@ -4653,7 +4627,7 @@ int nand_scan_tail(struct mtd_info *mtd)
                        break;
                case 64:
                case 128:
-                       mtd_set_ooblayout(mtd, &nand_ooblayout_lp_ops);
+                       mtd_set_ooblayout(mtd, &nand_ooblayout_lp_hamming_ops);
                        break;
                default:
                        WARN(1, "No oob scheme defined for oobsize %d\n",
@@ -4663,9 +4637,6 @@ int nand_scan_tail(struct mtd_info *mtd)
                }
        }
 
-       if (!chip->write_page)
-               chip->write_page = nand_write_page;
-
        /*
         * Check ECC mode, default to software if 3byte/512byte hardware ECC is
         * selected and we have 256 byte pagesize fallback to software ECC
@@ -4873,8 +4844,12 @@ int nand_scan_tail(struct mtd_info *mtd)
        /* Build bad block table */
        return chip->scan_bbt(mtd);
 err_free:
-       if (!(chip->options & NAND_OWN_BUFFERS))
-               kfree(chip->buffers);
+       if (nbuf) {
+               kfree(nbuf->databuf);
+               kfree(nbuf->ecccode);
+               kfree(nbuf->ecccalc);
+               kfree(nbuf);
+       }
        return ret;
 }
 EXPORT_SYMBOL(nand_scan_tail);
@@ -4925,13 +4900,20 @@ void nand_cleanup(struct nand_chip *chip)
 
        /* Free bad block table memory */
        kfree(chip->bbt);
-       if (!(chip->options & NAND_OWN_BUFFERS))
+       if (!(chip->options & NAND_OWN_BUFFERS) && chip->buffers) {
+               kfree(chip->buffers->databuf);
+               kfree(chip->buffers->ecccode);
+               kfree(chip->buffers->ecccalc);
                kfree(chip->buffers);
+       }
 
        /* Free bad block descriptor memory */
        if (chip->badblock_pattern && chip->badblock_pattern->options
                        & NAND_BBT_DYNAMICSTRUCT)
                kfree(chip->badblock_pattern);
+
+       /* Free manufacturer priv data. */
+       nand_manufacturer_cleanup(chip);
 }
 EXPORT_SYMBOL_GPL(nand_cleanup);
 
diff --git a/drivers/mtd/nand/nand_hynix.c b/drivers/mtd/nand/nand_hynix.c
new file mode 100644 (file)
index 0000000..b12dc73
--- /dev/null
@@ -0,0 +1,631 @@
+/*
+ * Copyright (C) 2017 Free Electrons
+ * Copyright (C) 2017 NextThing Co
+ *
+ * Author: Boris Brezillon <boris.brezillon@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/mtd/nand.h>
+#include <linux/sizes.h>
+#include <linux/slab.h>
+
+#define NAND_HYNIX_CMD_SET_PARAMS      0x36
+#define NAND_HYNIX_CMD_APPLY_PARAMS    0x16
+
+#define NAND_HYNIX_1XNM_RR_REPEAT      8
+
+/**
+ * struct hynix_read_retry - read-retry data
+ * @nregs: number of register to set when applying a new read-retry mode
+ * @regs: register offsets (NAND chip dependent)
+ * @values: array of values to set in registers. The array size is equal to
+ *         (nregs * nmodes)
+ */
+struct hynix_read_retry {
+       int nregs;
+       const u8 *regs;
+       u8 values[0];
+};
+
+/**
+ * struct hynix_nand - private Hynix NAND struct
+ * @nand_technology: manufacturing process expressed in picometer
+ * @read_retry: read-retry information
+ */
+struct hynix_nand {
+       const struct hynix_read_retry *read_retry;
+};
+
+/**
+ * struct hynix_read_retry_otp - structure describing how the read-retry OTP
+ *                              area
+ * @nregs: number of hynix private registers to set before reading the reading
+ *        the OTP area
+ * @regs: registers that should be configured
+ * @values: values that should be set in regs
+ * @page: the address to pass to the READ_PAGE command. Depends on the NAND
+ *       chip
+ * @size: size of the read-retry OTP section
+ */
+struct hynix_read_retry_otp {
+       int nregs;
+       const u8 *regs;
+       const u8 *values;
+       int page;
+       int size;
+};
+
+static bool hynix_nand_has_valid_jedecid(struct nand_chip *chip)
+{
+       struct mtd_info *mtd = nand_to_mtd(chip);
+       u8 jedecid[6] = { };
+       int i = 0;
+
+       chip->cmdfunc(mtd, NAND_CMD_READID, 0x40, -1);
+       for (i = 0; i < 5; i++)
+               jedecid[i] = chip->read_byte(mtd);
+
+       return !strcmp("JEDEC", jedecid);
+}
+
+static int hynix_nand_setup_read_retry(struct mtd_info *mtd, int retry_mode)
+{
+       struct nand_chip *chip = mtd_to_nand(mtd);
+       struct hynix_nand *hynix = nand_get_manufacturer_data(chip);
+       const u8 *values;
+       int status;
+       int i;
+
+       values = hynix->read_retry->values +
+                (retry_mode * hynix->read_retry->nregs);
+
+       /* Enter 'Set Hynix Parameters' mode */
+       chip->cmdfunc(mtd, NAND_HYNIX_CMD_SET_PARAMS, -1, -1);
+
+       /*
+        * Configure the NAND in the requested read-retry mode.
+        * This is done by setting pre-defined values in internal NAND
+        * registers.
+        *
+        * The set of registers is NAND specific, and the values are either
+        * predefined or extracted from an OTP area on the NAND (values are
+        * probably tweaked at production in this case).
+        */
+       for (i = 0; i < hynix->read_retry->nregs; i++) {
+               int column = hynix->read_retry->regs[i];
+
+               column |= column << 8;
+               chip->cmdfunc(mtd, NAND_CMD_NONE, column, -1);
+               chip->write_byte(mtd, values[i]);
+       }
+
+       /* Apply the new settings. */
+       chip->cmdfunc(mtd, NAND_HYNIX_CMD_APPLY_PARAMS, -1, -1);
+
+       status = chip->waitfunc(mtd, chip);
+       if (status & NAND_STATUS_FAIL)
+               return -EIO;
+
+       return 0;
+}
+
+/**
+ * hynix_get_majority - get the value that is occurring the most in a given
+ *                     set of values
+ * @in: the array of values to test
+ * @repeat: the size of the in array
+ * @out: pointer used to store the output value
+ *
+ * This function implements the 'majority check' logic that is supposed to
+ * overcome the unreliability of MLC NANDs when reading the OTP area storing
+ * the read-retry parameters.
+ *
+ * It's based on a pretty simple assumption: if we repeat the same value
+ * several times and then take the one that is occurring the most, we should
+ * find the correct value.
+ * Let's hope this dummy algorithm prevents us from losing the read-retry
+ * parameters.
+ */
+static int hynix_get_majority(const u8 *in, int repeat, u8 *out)
+{
+       int i, j, half = repeat / 2;
+
+       /*
+        * We only test the first half of the in array because we must ensure
+        * that the value is at least occurring repeat / 2 times.
+        *
+        * This loop is suboptimal since we may count the occurrences of the
+        * same value several time, but we are doing that on small sets, which
+        * makes it acceptable.
+        */
+       for (i = 0; i < half; i++) {
+               int cnt = 0;
+               u8 val = in[i];
+
+               /* Count all values that are matching the one at index i. */
+               for (j = i + 1; j < repeat; j++) {
+                       if (in[j] == val)
+                               cnt++;
+               }
+
+               /* We found a value occurring more than repeat / 2. */
+               if (cnt > half) {
+                       *out = val;
+                       return 0;
+               }
+       }
+
+       return -EIO;
+}
+
+static int hynix_read_rr_otp(struct nand_chip *chip,
+                            const struct hynix_read_retry_otp *info,
+                            void *buf)
+{
+       struct mtd_info *mtd = nand_to_mtd(chip);
+       int i;
+
+       chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
+
+       chip->cmdfunc(mtd, NAND_HYNIX_CMD_SET_PARAMS, -1, -1);
+
+       for (i = 0; i < info->nregs; i++) {
+               int column = info->regs[i];
+
+               column |= column << 8;
+               chip->cmdfunc(mtd, NAND_CMD_NONE, column, -1);
+               chip->write_byte(mtd, info->values[i]);
+       }
+
+       chip->cmdfunc(mtd, NAND_HYNIX_CMD_APPLY_PARAMS, -1, -1);
+
+       /* Sequence to enter OTP mode? */
+       chip->cmdfunc(mtd, 0x17, -1, -1);
+       chip->cmdfunc(mtd, 0x04, -1, -1);
+       chip->cmdfunc(mtd, 0x19, -1, -1);
+
+       /* Now read the page */
+       chip->cmdfunc(mtd, NAND_CMD_READ0, 0x0, info->page);
+       chip->read_buf(mtd, buf, info->size);
+
+       /* Put everything back to normal */
+       chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
+       chip->cmdfunc(mtd, NAND_HYNIX_CMD_SET_PARAMS, 0x38, -1);
+       chip->write_byte(mtd, 0x0);
+       chip->cmdfunc(mtd, NAND_HYNIX_CMD_APPLY_PARAMS, -1, -1);
+       chip->cmdfunc(mtd, NAND_CMD_READ0, 0x0, -1);
+
+       return 0;
+}
+
+#define NAND_HYNIX_1XNM_RR_COUNT_OFFS                          0
+#define NAND_HYNIX_1XNM_RR_REG_COUNT_OFFS                      8
+#define NAND_HYNIX_1XNM_RR_SET_OFFS(x, setsize, inv)           \
+       (16 + ((((x) * 2) + ((inv) ? 1 : 0)) * (setsize)))
+
+static int hynix_mlc_1xnm_rr_value(const u8 *buf, int nmodes, int nregs,
+                                  int mode, int reg, bool inv, u8 *val)
+{
+       u8 tmp[NAND_HYNIX_1XNM_RR_REPEAT];
+       int val_offs = (mode * nregs) + reg;
+       int set_size = nmodes * nregs;
+       int i, ret;
+
+       for (i = 0; i < NAND_HYNIX_1XNM_RR_REPEAT; i++) {
+               int set_offs = NAND_HYNIX_1XNM_RR_SET_OFFS(i, set_size, inv);
+
+               tmp[i] = buf[val_offs + set_offs];
+       }
+
+       ret = hynix_get_majority(tmp, NAND_HYNIX_1XNM_RR_REPEAT, val);
+       if (ret)
+               return ret;
+
+       if (inv)
+               *val = ~*val;
+
+       return 0;
+}
+
+static u8 hynix_1xnm_mlc_read_retry_regs[] = {
+       0xcc, 0xbf, 0xaa, 0xab, 0xcd, 0xad, 0xae, 0xaf
+};
+
+static int hynix_mlc_1xnm_rr_init(struct nand_chip *chip,
+                                 const struct hynix_read_retry_otp *info)
+{
+       struct hynix_nand *hynix = nand_get_manufacturer_data(chip);
+       struct hynix_read_retry *rr = NULL;
+       int ret, i, j;
+       u8 nregs, nmodes;
+       u8 *buf;
+
+       buf = kmalloc(info->size, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       ret = hynix_read_rr_otp(chip, info, buf);
+       if (ret)
+               goto out;
+
+       ret = hynix_get_majority(buf, NAND_HYNIX_1XNM_RR_REPEAT,
+                                &nmodes);
+       if (ret)
+               goto out;
+
+       ret = hynix_get_majority(buf + NAND_HYNIX_1XNM_RR_REPEAT,
+                                NAND_HYNIX_1XNM_RR_REPEAT,
+                                &nregs);
+       if (ret)
+               goto out;
+
+       rr = kzalloc(sizeof(*rr) + (nregs * nmodes), GFP_KERNEL);
+       if (!rr) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       for (i = 0; i < nmodes; i++) {
+               for (j = 0; j < nregs; j++) {
+                       u8 *val = rr->values + (i * nregs);
+
+                       ret = hynix_mlc_1xnm_rr_value(buf, nmodes, nregs, i, j,
+                                                     false, val);
+                       if (!ret)
+                               continue;
+
+                       ret = hynix_mlc_1xnm_rr_value(buf, nmodes, nregs, i, j,
+                                                     true, val);
+                       if (ret)
+                               goto out;
+               }
+       }
+
+       rr->nregs = nregs;
+       rr->regs = hynix_1xnm_mlc_read_retry_regs;
+       hynix->read_retry = rr;
+       chip->setup_read_retry = hynix_nand_setup_read_retry;
+       chip->read_retries = nmodes;
+
+out:
+       kfree(buf);
+
+       if (ret)
+               kfree(rr);
+
+       return ret;
+}
+
+static const u8 hynix_mlc_1xnm_rr_otp_regs[] = { 0x38 };
+static const u8 hynix_mlc_1xnm_rr_otp_values[] = { 0x52 };
+
+static const struct hynix_read_retry_otp hynix_mlc_1xnm_rr_otps[] = {
+       {
+               .nregs = ARRAY_SIZE(hynix_mlc_1xnm_rr_otp_regs),
+               .regs = hynix_mlc_1xnm_rr_otp_regs,
+               .values = hynix_mlc_1xnm_rr_otp_values,
+               .page = 0x21f,
+               .size = 784
+       },
+       {
+               .nregs = ARRAY_SIZE(hynix_mlc_1xnm_rr_otp_regs),
+               .regs = hynix_mlc_1xnm_rr_otp_regs,
+               .values = hynix_mlc_1xnm_rr_otp_values,
+               .page = 0x200,
+               .size = 528,
+       },
+};
+
+static int hynix_nand_rr_init(struct nand_chip *chip)
+{
+       int i, ret = 0;
+       bool valid_jedecid;
+
+       valid_jedecid = hynix_nand_has_valid_jedecid(chip);
+
+       /*
+        * We only support read-retry for 1xnm NANDs, and those NANDs all
+        * expose a valid JEDEC ID.
+        */
+       if (valid_jedecid) {
+               u8 nand_tech = chip->id.data[5] >> 4;
+
+               /* 1xnm technology */
+               if (nand_tech == 4) {
+                       for (i = 0; i < ARRAY_SIZE(hynix_mlc_1xnm_rr_otps);
+                            i++) {
+                               /*
+                                * FIXME: Hynix recommend to copy the
+                                * read-retry OTP area into a normal page.
+                                */
+                               ret = hynix_mlc_1xnm_rr_init(chip,
+                                               hynix_mlc_1xnm_rr_otps);
+                               if (!ret)
+                                       break;
+                       }
+               }
+       }
+
+       if (ret)
+               pr_warn("failed to initialize read-retry infrastructure");
+
+       return 0;
+}
+
+static void hynix_nand_extract_oobsize(struct nand_chip *chip,
+                                      bool valid_jedecid)
+{
+       struct mtd_info *mtd = nand_to_mtd(chip);
+       u8 oobsize;
+
+       oobsize = ((chip->id.data[3] >> 2) & 0x3) |
+                 ((chip->id.data[3] >> 4) & 0x4);
+
+       if (valid_jedecid) {
+               switch (oobsize) {
+               case 0:
+                       mtd->oobsize = 2048;
+                       break;
+               case 1:
+                       mtd->oobsize = 1664;
+                       break;
+               case 2:
+                       mtd->oobsize = 1024;
+                       break;
+               case 3:
+                       mtd->oobsize = 640;
+                       break;
+               default:
+                       /*
+                        * We should never reach this case, but if that
+                        * happens, this probably means Hynix decided to use
+                        * a different extended ID format, and we should find
+                        * a way to support it.
+                        */
+                       WARN(1, "Invalid OOB size");
+                       break;
+               }
+       } else {
+               switch (oobsize) {
+               case 0:
+                       mtd->oobsize = 128;
+                       break;
+               case 1:
+                       mtd->oobsize = 224;
+                       break;
+               case 2:
+                       mtd->oobsize = 448;
+                       break;
+               case 3:
+                       mtd->oobsize = 64;
+                       break;
+               case 4:
+                       mtd->oobsize = 32;
+                       break;
+               case 5:
+                       mtd->oobsize = 16;
+                       break;
+               case 6:
+                       mtd->oobsize = 640;
+                       break;
+               default:
+                       /*
+                        * We should never reach this case, but if that
+                        * happens, this probably means Hynix decided to use
+                        * a different extended ID format, and we should find
+                        * a way to support it.
+                        */
+                       WARN(1, "Invalid OOB size");
+                       break;
+               }
+       }
+}
+
+static void hynix_nand_extract_ecc_requirements(struct nand_chip *chip,
+                                               bool valid_jedecid)
+{
+       u8 ecc_level = (chip->id.data[4] >> 4) & 0x7;
+
+       if (valid_jedecid) {
+               /* Reference: H27UCG8T2E datasheet */
+               chip->ecc_step_ds = 1024;
+
+               switch (ecc_level) {
+               case 0:
+                       chip->ecc_step_ds = 0;
+                       chip->ecc_strength_ds = 0;
+                       break;
+               case 1:
+                       chip->ecc_strength_ds = 4;
+                       break;
+               case 2:
+                       chip->ecc_strength_ds = 24;
+                       break;
+               case 3:
+                       chip->ecc_strength_ds = 32;
+                       break;
+               case 4:
+                       chip->ecc_strength_ds = 40;
+                       break;
+               case 5:
+                       chip->ecc_strength_ds = 50;
+                       break;
+               case 6:
+                       chip->ecc_strength_ds = 60;
+                       break;
+               default:
+                       /*
+                        * We should never reach this case, but if that
+                        * happens, this probably means Hynix decided to use
+                        * a different extended ID format, and we should find
+                        * a way to support it.
+                        */
+                       WARN(1, "Invalid ECC requirements");
+               }
+       } else {
+               /*
+                * The ECC requirements field meaning depends on the
+                * NAND technology.
+                */
+               u8 nand_tech = chip->id.data[5] & 0x3;
+
+               if (nand_tech < 3) {
+                       /* > 26nm, reference: H27UBG8T2A datasheet */
+                       if (ecc_level < 5) {
+                               chip->ecc_step_ds = 512;
+                               chip->ecc_strength_ds = 1 << ecc_level;
+                       } else if (ecc_level < 7) {
+                               if (ecc_level == 5)
+                                       chip->ecc_step_ds = 2048;
+                               else
+                                       chip->ecc_step_ds = 1024;
+                               chip->ecc_strength_ds = 24;
+                       } else {
+                               /*
+                                * We should never reach this case, but if that
+                                * happens, this probably means Hynix decided
+                                * to use a different extended ID format, and
+                                * we should find a way to support it.
+                                */
+                               WARN(1, "Invalid ECC requirements");
+                       }
+               } else {
+                       /* <= 26nm, reference: H27UBG8T2B datasheet */
+                       if (!ecc_level) {
+                               chip->ecc_step_ds = 0;
+                               chip->ecc_strength_ds = 0;
+                       } else if (ecc_level < 5) {
+                               chip->ecc_step_ds = 512;
+                               chip->ecc_strength_ds = 1 << (ecc_level - 1);
+                       } else {
+                               chip->ecc_step_ds = 1024;
+                               chip->ecc_strength_ds = 24 +
+                                                       (8 * (ecc_level - 5));
+                       }
+               }
+       }
+}
+
+static void hynix_nand_extract_scrambling_requirements(struct nand_chip *chip,
+                                                      bool valid_jedecid)
+{
+       u8 nand_tech;
+
+       /* We need scrambling on all TLC NANDs*/
+       if (chip->bits_per_cell > 2)
+               chip->options |= NAND_NEED_SCRAMBLING;
+
+       /* And on MLC NANDs with sub-3xnm process */
+       if (valid_jedecid) {
+               nand_tech = chip->id.data[5] >> 4;
+
+               /* < 3xnm */
+               if (nand_tech > 0)
+                       chip->options |= NAND_NEED_SCRAMBLING;
+       } else {
+               nand_tech = chip->id.data[5] & 0x3;
+
+               /* < 32nm */
+               if (nand_tech > 2)
+                       chip->options |= NAND_NEED_SCRAMBLING;
+       }
+}
+
+static void hynix_nand_decode_id(struct nand_chip *chip)
+{
+       struct mtd_info *mtd = nand_to_mtd(chip);
+       bool valid_jedecid;
+       u8 tmp;
+
+       /*
+        * Exclude all SLC NANDs from this advanced detection scheme.
+        * According to the ranges defined in several datasheets, it might
+        * appear that even SLC NANDs could fall in this extended ID scheme.
+        * If that the case rework the test to let SLC NANDs go through the
+        * detection process.
+        */
+       if (chip->id.len < 6 || nand_is_slc(chip)) {
+               nand_decode_ext_id(chip);
+               return;
+       }
+
+       /* Extract pagesize */
+       mtd->writesize = 2048 << (chip->id.data[3] & 0x03);
+
+       tmp = (chip->id.data[3] >> 4) & 0x3;
+       /*
+        * When bit7 is set that means we start counting at 1MiB, otherwise
+        * we start counting at 128KiB and shift this value the content of
+        * ID[3][4:5].
+        * The only exception is when ID[3][4:5] == 3 and ID[3][7] == 0, in
+        * this case the erasesize is set to 768KiB.
+        */
+       if (chip->id.data[3] & 0x80)
+               mtd->erasesize = SZ_1M << tmp;
+       else if (tmp == 3)
+               mtd->erasesize = SZ_512K + SZ_256K;
+       else
+               mtd->erasesize = SZ_128K << tmp;
+
+       /*
+        * Modern Toggle DDR NANDs have a valid JEDECID even though they are
+        * not exposing a valid JEDEC parameter table.
+        * These NANDs use a different NAND ID scheme.
+        */
+       valid_jedecid = hynix_nand_has_valid_jedecid(chip);
+
+       hynix_nand_extract_oobsize(chip, valid_jedecid);
+       hynix_nand_extract_ecc_requirements(chip, valid_jedecid);
+       hynix_nand_extract_scrambling_requirements(chip, valid_jedecid);
+}
+
+static void hynix_nand_cleanup(struct nand_chip *chip)
+{
+       struct hynix_nand *hynix = nand_get_manufacturer_data(chip);
+
+       if (!hynix)
+               return;
+
+       kfree(hynix->read_retry);
+       kfree(hynix);
+       nand_set_manufacturer_data(chip, NULL);
+}
+
+static int hynix_nand_init(struct nand_chip *chip)
+{
+       struct hynix_nand *hynix;
+       int ret;
+
+       if (!nand_is_slc(chip))
+               chip->bbt_options |= NAND_BBT_SCANLASTPAGE;
+       else
+               chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
+
+       hynix = kzalloc(sizeof(*hynix), GFP_KERNEL);
+       if (!hynix)
+               return -ENOMEM;
+
+       nand_set_manufacturer_data(chip, hynix);
+
+       ret = hynix_nand_rr_init(chip);
+       if (ret)
+               hynix_nand_cleanup(chip);
+
+       return ret;
+}
+
+const struct nand_manufacturer_ops hynix_nand_manuf_ops = {
+       .detect = hynix_nand_decode_id,
+       .init = hynix_nand_init,
+       .cleanup = hynix_nand_cleanup,
+};
index 4a2f75b0c200a1135e64941bf24b753c356775a0..9d5ca0e540b5bc5c9e3be9a6a3b476624e63be14 100644 (file)
@@ -10,7 +10,7 @@
 #include <linux/mtd/nand.h>
 #include <linux/sizes.h>
 
-#define LP_OPTIONS NAND_SAMSUNG_LP_OPTIONS
+#define LP_OPTIONS 0
 #define LP_OPTIONS16 (LP_OPTIONS | NAND_BUSWIDTH_16)
 
 #define SP_OPTIONS NAND_NEED_READRDY
@@ -169,29 +169,40 @@ struct nand_flash_dev nand_flash_ids[] = {
 };
 
 /* Manufacturer IDs */
-struct nand_manufacturers nand_manuf_ids[] = {
-       {NAND_MFR_TOSHIBA, "Toshiba"},
+static const struct nand_manufacturer nand_manufacturers[] = {
+       {NAND_MFR_TOSHIBA, "Toshiba", &toshiba_nand_manuf_ops},
        {NAND_MFR_ESMT, "ESMT"},
-       {NAND_MFR_SAMSUNG, "Samsung"},
+       {NAND_MFR_SAMSUNG, "Samsung", &samsung_nand_manuf_ops},
        {NAND_MFR_FUJITSU, "Fujitsu"},
        {NAND_MFR_NATIONAL, "National"},
        {NAND_MFR_RENESAS, "Renesas"},
        {NAND_MFR_STMICRO, "ST Micro"},
-       {NAND_MFR_HYNIX, "Hynix"},
-       {NAND_MFR_MICRON, "Micron"},
-       {NAND_MFR_AMD, "AMD/Spansion"},
-       {NAND_MFR_MACRONIX, "Macronix"},
+       {NAND_MFR_HYNIX, "Hynix", &hynix_nand_manuf_ops},
+       {NAND_MFR_MICRON, "Micron", &micron_nand_manuf_ops},
+       {NAND_MFR_AMD, "AMD/Spansion", &amd_nand_manuf_ops},
+       {NAND_MFR_MACRONIX, "Macronix", &macronix_nand_manuf_ops},
        {NAND_MFR_EON, "Eon"},
        {NAND_MFR_SANDISK, "SanDisk"},
        {NAND_MFR_INTEL, "Intel"},
        {NAND_MFR_ATO, "ATO"},
        {NAND_MFR_WINBOND, "Winbond"},
-       {0x0, "Unknown"}
 };
 
-EXPORT_SYMBOL(nand_manuf_ids);
-EXPORT_SYMBOL(nand_flash_ids);
+/**
+ * nand_get_manufacturer - Get manufacturer information from the manufacturer
+ *                        ID
+ * @id: manufacturer ID
+ *
+ * Returns a pointer a nand_manufacturer object if the manufacturer is defined
+ * in the NAND manufacturers database, NULL otherwise.
+ */
+const struct nand_manufacturer *nand_get_manufacturer(u8 id)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(nand_manufacturers); i++)
+               if (nand_manufacturers[i].id == id)
+                       return &nand_manufacturers[i];
 
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Thomas Gleixner <tglx@linutronix.de>");
-MODULE_DESCRIPTION("Nand device & manufacturer IDs");
+       return NULL;
+}
diff --git a/drivers/mtd/nand/nand_macronix.c b/drivers/mtd/nand/nand_macronix.c
new file mode 100644 (file)
index 0000000..84855c3
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2017 Free Electrons
+ * Copyright (C) 2017 NextThing Co
+ *
+ * Author: Boris Brezillon <boris.brezillon@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/mtd/nand.h>
+
+static int macronix_nand_init(struct nand_chip *chip)
+{
+       if (nand_is_slc(chip))
+               chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
+
+       return 0;
+}
+
+const struct nand_manufacturer_ops macronix_nand_manuf_ops = {
+       .init = macronix_nand_init,
+};
diff --git a/drivers/mtd/nand/nand_micron.c b/drivers/mtd/nand/nand_micron.c
new file mode 100644 (file)
index 0000000..8770110
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2017 Free Electrons
+ * Copyright (C) 2017 NextThing Co
+ *
+ * Author: Boris Brezillon <boris.brezillon@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/mtd/nand.h>
+
+struct nand_onfi_vendor_micron {
+       u8 two_plane_read;
+       u8 read_cache;
+       u8 read_unique_id;
+       u8 dq_imped;
+       u8 dq_imped_num_settings;
+       u8 dq_imped_feat_addr;
+       u8 rb_pulldown_strength;
+       u8 rb_pulldown_strength_feat_addr;
+       u8 rb_pulldown_strength_num_settings;
+       u8 otp_mode;
+       u8 otp_page_start;
+       u8 otp_data_prot_addr;
+       u8 otp_num_pages;
+       u8 otp_feat_addr;
+       u8 read_retry_options;
+       u8 reserved[72];
+       u8 param_revision;
+} __packed;
+
+static int micron_nand_setup_read_retry(struct mtd_info *mtd, int retry_mode)
+{
+       struct nand_chip *chip = mtd_to_nand(mtd);
+       u8 feature[ONFI_SUBFEATURE_PARAM_LEN] = {retry_mode};
+
+       return chip->onfi_set_features(mtd, chip, ONFI_FEATURE_ADDR_READ_RETRY,
+                                      feature);
+}
+
+/*
+ * Configure chip properties from Micron vendor-specific ONFI table
+ */
+static int micron_nand_onfi_init(struct nand_chip *chip)
+{
+       struct nand_onfi_params *p = &chip->onfi_params;
+       struct nand_onfi_vendor_micron *micron = (void *)p->vendor;
+
+       if (!chip->onfi_version)
+               return 0;
+
+       if (le16_to_cpu(p->vendor_revision) < 1)
+               return 0;
+
+       chip->read_retries = micron->read_retry_options;
+       chip->setup_read_retry = micron_nand_setup_read_retry;
+
+       return 0;
+}
+
+static int micron_nand_init(struct nand_chip *chip)
+{
+       struct mtd_info *mtd = nand_to_mtd(chip);
+       int ret;
+
+       ret = micron_nand_onfi_init(chip);
+       if (ret)
+               return ret;
+
+       if (mtd->writesize == 2048)
+               chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
+
+       return 0;
+}
+
+const struct nand_manufacturer_ops micron_nand_manuf_ops = {
+       .init = micron_nand_init,
+};
diff --git a/drivers/mtd/nand/nand_samsung.c b/drivers/mtd/nand/nand_samsung.c
new file mode 100644 (file)
index 0000000..9cfc403
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2017 Free Electrons
+ * Copyright (C) 2017 NextThing Co
+ *
+ * Author: Boris Brezillon <boris.brezillon@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/mtd/nand.h>
+
+static void samsung_nand_decode_id(struct nand_chip *chip)
+{
+       struct mtd_info *mtd = nand_to_mtd(chip);
+
+       /* New Samsung (6 byte ID): Samsung K9GAG08U0F (p.44) */
+       if (chip->id.len == 6 && !nand_is_slc(chip) &&
+           chip->id.data[5] != 0x00) {
+               u8 extid = chip->id.data[3];
+
+               /* Get pagesize */
+               mtd->writesize = 2048 << (extid & 0x03);
+
+               extid >>= 2;
+
+               /* Get oobsize */
+               switch (((extid >> 2) & 0x4) | (extid & 0x3)) {
+               case 1:
+                       mtd->oobsize = 128;
+                       break;
+               case 2:
+                       mtd->oobsize = 218;
+                       break;
+               case 3:
+                       mtd->oobsize = 400;
+                       break;
+               case 4:
+                       mtd->oobsize = 436;
+                       break;
+               case 5:
+                       mtd->oobsize = 512;
+                       break;
+               case 6:
+                       mtd->oobsize = 640;
+                       break;
+               default:
+                       /*
+                        * We should never reach this case, but if that
+                        * happens, this probably means Samsung decided to use
+                        * a different extended ID format, and we should find
+                        * a way to support it.
+                        */
+                       WARN(1, "Invalid OOB size value");
+                       break;
+               }
+
+               /* Get blocksize */
+               extid >>= 2;
+               mtd->erasesize = (128 * 1024) <<
+                                (((extid >> 1) & 0x04) | (extid & 0x03));
+
+               /* Extract ECC requirements from 5th id byte*/
+               extid = (chip->id.data[4] >> 4) & 0x07;
+               if (extid < 5) {
+                       chip->ecc_step_ds = 512;
+                       chip->ecc_strength_ds = 1 << extid;
+               } else {
+                       chip->ecc_step_ds = 1024;
+                       switch (extid) {
+                       case 5:
+                               chip->ecc_strength_ds = 24;
+                               break;
+                       case 6:
+                               chip->ecc_strength_ds = 40;
+                               break;
+                       case 7:
+                               chip->ecc_strength_ds = 60;
+                               break;
+                       }
+               }
+       } else {
+               nand_decode_ext_id(chip);
+       }
+}
+
+static int samsung_nand_init(struct nand_chip *chip)
+{
+       struct mtd_info *mtd = nand_to_mtd(chip);
+
+       if (mtd->writesize > 512)
+               chip->options |= NAND_SAMSUNG_LP_OPTIONS;
+
+       if (!nand_is_slc(chip))
+               chip->bbt_options |= NAND_BBT_SCANLASTPAGE;
+       else
+               chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
+
+       return 0;
+}
+
+const struct nand_manufacturer_ops samsung_nand_manuf_ops = {
+       .detect = samsung_nand_decode_id,
+       .init = samsung_nand_init,
+};
diff --git a/drivers/mtd/nand/nand_toshiba.c b/drivers/mtd/nand/nand_toshiba.c
new file mode 100644 (file)
index 0000000..fa787ba
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2017 Free Electrons
+ * Copyright (C) 2017 NextThing Co
+ *
+ * Author: Boris Brezillon <boris.brezillon@free-electrons.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/mtd/nand.h>
+
+static void toshiba_nand_decode_id(struct nand_chip *chip)
+{
+       struct mtd_info *mtd = nand_to_mtd(chip);
+
+       nand_decode_ext_id(chip);
+
+       /*
+        * Toshiba 24nm raw SLC (i.e., not BENAND) have 32B OOB per
+        * 512B page. For Toshiba SLC, we decode the 5th/6th byte as
+        * follows:
+        * - ID byte 6, bits[2:0]: 100b -> 43nm, 101b -> 32nm,
+        *                         110b -> 24nm
+        * - ID byte 5, bit[7]:    1 -> BENAND, 0 -> raw SLC
+        */
+       if (chip->id.len >= 6 && nand_is_slc(chip) &&
+           (chip->id.data[5] & 0x7) == 0x6 /* 24nm */ &&
+           !(chip->id.data[4] & 0x80) /* !BENAND */)
+               mtd->oobsize = 32 * mtd->writesize >> 9;
+}
+
+static int toshiba_nand_init(struct nand_chip *chip)
+{
+       if (nand_is_slc(chip))
+               chip->bbt_options |= NAND_BBT_SCAN2NDPAGE;
+
+       return 0;
+}
+
+const struct nand_manufacturer_ops toshiba_nand_manuf_ops = {
+       .detect = toshiba_nand_decode_id,
+       .init = toshiba_nand_init,
+};
index c84742671a5f9782a23bec53b0182de0e8871289..03a0d057bf2f80b3ea4c3f397eb1f607697aad3c 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/list.h>
 #include <linux/random.h>
 #include <linux/sched.h>
+#include <linux/sched/mm.h>
 #include <linux/fs.h>
 #include <linux/pagemap.h>
 #include <linux/seq_file.h>
@@ -901,7 +902,7 @@ static int parse_weakpages(void)
                zero_ok = (*w == '0' ? 1 : 0);
                page_no = simple_strtoul(w, &w, 0);
                if (!zero_ok && !page_no) {
-                       NS_ERR("invalid weakpagess.\n");
+                       NS_ERR("invalid weakpages.\n");
                        return -EINVAL;
                }
                max_writes = 3;
@@ -1368,31 +1369,18 @@ static int get_pages(struct nandsim *ns, struct file *file, size_t count, loff_t
        return 0;
 }
 
-static int set_memalloc(void)
-{
-       if (current->flags & PF_MEMALLOC)
-               return 0;
-       current->flags |= PF_MEMALLOC;
-       return 1;
-}
-
-static void clear_memalloc(int memalloc)
-{
-       if (memalloc)
-               current->flags &= ~PF_MEMALLOC;
-}
-
 static ssize_t read_file(struct nandsim *ns, struct file *file, void *buf, size_t count, loff_t pos)
 {
        ssize_t tx;
-       int err, memalloc;
+       int err;
+       unsigned int noreclaim_flag;
 
        err = get_pages(ns, file, count, pos);
        if (err)
                return err;
-       memalloc = set_memalloc();
+       noreclaim_flag = memalloc_noreclaim_save();
        tx = kernel_read(file, pos, buf, count);
-       clear_memalloc(memalloc);
+       memalloc_noreclaim_restore(noreclaim_flag);
        put_pages(ns);
        return tx;
 }
@@ -1400,14 +1388,15 @@ static ssize_t read_file(struct nandsim *ns, struct file *file, void *buf, size_
 static ssize_t write_file(struct nandsim *ns, struct file *file, void *buf, size_t count, loff_t pos)
 {
        ssize_t tx;
-       int err, memalloc;
+       int err;
+       unsigned int noreclaim_flag;
 
        err = get_pages(ns, file, count, pos);
        if (err)
                return err;
-       memalloc = set_memalloc();
+       noreclaim_flag = memalloc_noreclaim_save();
        tx = kernel_write(file, buf, count, pos);
-       clear_memalloc(memalloc);
+       memalloc_noreclaim_restore(noreclaim_flag);
        put_pages(ns);
        return tx;
 }
index 2a52101120d466dc81d27eb8ac2c9fd10b19fb5e..084934a9f19cc4df255b8b7b0a86d3e0d28ab98c 100644 (file)
@@ -1856,6 +1856,15 @@ static int omap_nand_probe(struct platform_device *pdev)
        nand_chip->ecc.priv     = NULL;
        nand_set_flash_node(nand_chip, dev->of_node);
 
+       if (!mtd->name) {
+               mtd->name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
+                                          "omap2-nand.%d", info->gpmc_cs);
+               if (!mtd->name) {
+                       dev_err(&pdev->dev, "Failed to set MTD name\n");
+                       return -ENOMEM;
+               }
+       }
+
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        nand_chip->IO_ADDR_R = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(nand_chip->IO_ADDR_R))
index 4a91c5d000be790bc6200a50a9d00f80f4de9bc4..f8e463a97b9ee479028dd9c282ff74436d885389 100644 (file)
 #include <asm/sizes.h>
 #include <linux/platform_data/mtd-orion_nand.h>
 
+struct orion_nand_info {
+       struct nand_chip chip;
+       struct clk *clk;
+};
+
 static void orion_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 {
        struct nand_chip *nc = mtd_to_nand(mtd);
@@ -75,20 +80,21 @@ static void orion_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 
 static int __init orion_nand_probe(struct platform_device *pdev)
 {
+       struct orion_nand_info *info;
        struct mtd_info *mtd;
        struct nand_chip *nc;
        struct orion_nand_data *board;
        struct resource *res;
-       struct clk *clk;
        void __iomem *io_base;
        int ret = 0;
        u32 val = 0;
 
-       nc = devm_kzalloc(&pdev->dev,
-                       sizeof(struct nand_chip),
+       info = devm_kzalloc(&pdev->dev,
+                       sizeof(struct orion_nand_info),
                        GFP_KERNEL);
-       if (!nc)
+       if (!info)
                return -ENOMEM;
+       nc = &info->chip;
        mtd = nand_to_mtd(nc);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -145,16 +151,23 @@ static int __init orion_nand_probe(struct platform_device *pdev)
        if (board->dev_ready)
                nc->dev_ready = board->dev_ready;
 
-       platform_set_drvdata(pdev, mtd);
+       platform_set_drvdata(pdev, info);
 
        /* Not all platforms can gate the clock, so it is not
           an error if the clock does not exists. */
-       clk = clk_get(&pdev->dev, NULL);
-       if (!IS_ERR(clk)) {
-               clk_prepare_enable(clk);
-               clk_put(clk);
+       info->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(info->clk)) {
+               ret = PTR_ERR(info->clk);
+               if (ret == -ENOENT) {
+                       info->clk = NULL;
+               } else {
+                       dev_err(&pdev->dev, "failed to get clock!\n");
+                       return ret;
+               }
        }
 
+       clk_prepare_enable(info->clk);
+
        ret = nand_scan(mtd, 1);
        if (ret)
                goto no_dev;
@@ -169,26 +182,19 @@ static int __init orion_nand_probe(struct platform_device *pdev)
        return 0;
 
 no_dev:
-       if (!IS_ERR(clk)) {
-               clk_disable_unprepare(clk);
-               clk_put(clk);
-       }
-
+       clk_disable_unprepare(info->clk);
        return ret;
 }
 
 static int orion_nand_remove(struct platform_device *pdev)
 {
-       struct mtd_info *mtd = platform_get_drvdata(pdev);
-       struct clk *clk;
+       struct orion_nand_info *info = platform_get_drvdata(pdev);
+       struct nand_chip *chip = &info->chip;
+       struct mtd_info *mtd = nand_to_mtd(chip);
 
        nand_release(mtd);
 
-       clk = clk_get(&pdev->dev, NULL);
-       if (!IS_ERR(clk)) {
-               clk_disable_unprepare(clk);
-               clk_put(clk);
-       }
+       clk_disable_unprepare(info->clk);
 
        return 0;
 }
index 3e3bf3b364d2b63c1dcf1869e45b5bd5c9f63616..1b207aac840c4b169c4e2168f1104309c729ad0c 100644 (file)
@@ -91,7 +91,7 @@ static int oxnas_nand_probe(struct platform_device *pdev)
        int err = 0;
 
        /* Allocate memory for the device structure (and zero it) */
-       oxnas = devm_kzalloc(&pdev->dev, sizeof(struct nand_chip),
+       oxnas = devm_kzalloc(&pdev->dev, sizeof(*oxnas),
                             GFP_KERNEL);
        if (!oxnas)
                return -ENOMEM;
index 0eeeb8b889ea8af83a12126ded319e84f0389618..118a26fff36856dd3f47fa523494ab05909924e4 100644 (file)
@@ -2212,17 +2212,17 @@ static int sunxi_nfc_probe(struct platform_device *pdev)
                goto out_ahb_clk_unprepare;
 
        nfc->reset = devm_reset_control_get_optional(dev, "ahb");
-       if (!IS_ERR(nfc->reset)) {
-               ret = reset_control_deassert(nfc->reset);
-               if (ret) {
-                       dev_err(dev, "reset err %d\n", ret);
-                       goto out_mod_clk_unprepare;
-               }
-       } else if (PTR_ERR(nfc->reset) != -ENOENT) {
+       if (IS_ERR(nfc->reset)) {
                ret = PTR_ERR(nfc->reset);
                goto out_mod_clk_unprepare;
        }
 
+       ret = reset_control_deassert(nfc->reset);
+       if (ret) {
+               dev_err(dev, "reset err %d\n", ret);
+               goto out_mod_clk_unprepare;
+       }
+
        ret = sunxi_nfc_rst(nfc);
        if (ret)
                goto out_ahb_reset_reassert;
@@ -2262,8 +2262,7 @@ out_release_dmac:
        if (nfc->dmac)
                dma_release_channel(nfc->dmac);
 out_ahb_reset_reassert:
-       if (!IS_ERR(nfc->reset))
-               reset_control_assert(nfc->reset);
+       reset_control_assert(nfc->reset);
 out_mod_clk_unprepare:
        clk_disable_unprepare(nfc->mod_clk);
 out_ahb_clk_unprepare:
@@ -2278,8 +2277,7 @@ static int sunxi_nfc_remove(struct platform_device *pdev)
 
        sunxi_nand_chips_cleanup(nfc);
 
-       if (!IS_ERR(nfc->reset))
-               reset_control_assert(nfc->reset);
+       reset_control_assert(nfc->reset);
 
        if (nfc->dmac)
                dma_release_channel(nfc->dmac);
index 4a5e948c62df1b7d29ff9fe78b50e7d0858b01d5..05b6e106520331ddd48f619f798d21c4cfeb2059 100644 (file)
@@ -223,12 +223,13 @@ static void tango_dma_callback(void *arg)
        complete(arg);
 }
 
-static int do_dma(struct tango_nfc *nfc, int dir, int cmd, const void *buf,
-                 int len, int page)
+static int do_dma(struct tango_nfc *nfc, enum dma_data_direction dir, int cmd,
+                 const void *buf, int len, int page)
 {
        void __iomem *addr = nfc->reg_base + NFC_STATUS;
        struct dma_chan *chan = nfc->chan;
        struct dma_async_tx_descriptor *desc;
+       enum dma_transfer_direction tdir;
        struct scatterlist sg;
        struct completion tx_done;
        int err = -EIO;
@@ -238,7 +239,8 @@ static int do_dma(struct tango_nfc *nfc, int dir, int cmd, const void *buf,
        if (dma_map_sg(chan->device->dev, &sg, 1, dir) != 1)
                return -EIO;
 
-       desc = dmaengine_prep_slave_sg(chan, &sg, 1, dir, DMA_PREP_INTERRUPT);
+       tdir = dir == DMA_TO_DEVICE ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
+       desc = dmaengine_prep_slave_sg(chan, &sg, 1, tdir, DMA_PREP_INTERRUPT);
        if (!desc)
                goto dma_unmap;
 
index 4644701224931dd2860d8d332b6a1ea5adc01fa3..2861c7079d7b44be82f55e129034caf544d4c30b 100644 (file)
@@ -166,8 +166,8 @@ static int parse_ofoldpart_partitions(struct mtd_info *master,
        if (!part)
                return 0; /* No partitions found */
 
-       pr_warning("Device tree uses obsolete partition map binding: %s\n",
-                       dp->full_name);
+       pr_warn("Device tree uses obsolete partition map binding: %s\n",
+               dp->full_name);
 
        nr_parts = plen / sizeof(part[0]);
 
index 7252087ef407e40e1aaff2061ef6b7524c66749d..bfdfb1e72b38a323299ee29c8b4ffdb7e4fd21f2 100644 (file)
@@ -106,4 +106,11 @@ config SPI_INTEL_SPI_PLATFORM
          To compile this driver as a module, choose M here: the module
          will be called intel-spi-platform.
 
+config SPI_STM32_QUADSPI
+       tristate "STM32 Quad SPI controller"
+       depends on ARCH_STM32
+       help
+         This enables support for the STM32 Quad SPI controller.
+         We only connect the NOR to this controller.
+
 endif # MTD_SPI_NOR
index 72238a793198cfd1f7a2d65ee896860981939baf..285aab86c7ca142b449e22215732ca24463c515c 100644 (file)
@@ -8,3 +8,4 @@ obj-$(CONFIG_MTD_MT81xx_NOR)    += mtk-quadspi.o
 obj-$(CONFIG_SPI_NXP_SPIFI)    += nxp-spifi.o
 obj-$(CONFIG_SPI_INTEL_SPI)    += intel-spi.o
 obj-$(CONFIG_SPI_INTEL_SPI_PLATFORM)   += intel-spi-platform.o
+obj-$(CONFIG_SPI_STM32_QUADSPI)        += stm32-quadspi.o
\ No newline at end of file
index 20378b0d55e98937528e025c03bb43c5b5c497a6..a286350627a663fc878245e18fbbb328ac7aa65f 100644 (file)
@@ -448,8 +448,11 @@ static int hisi_spi_nor_probe(struct platform_device *pdev)
        if (!host->buffer)
                return -ENOMEM;
 
+       ret = clk_prepare_enable(host->clk);
+       if (ret)
+               return ret;
+
        mutex_init(&host->lock);
-       clk_prepare_enable(host->clk);
        hisi_spi_nor_init(host);
        ret = hisi_spi_nor_register_all(host);
        if (ret)
index a10f6027b38690aa6d5c599de77b2f82699377ff..986a3d020a3a154157f025f912fd88fd1c5881de 100644 (file)
@@ -704,7 +704,7 @@ static void intel_spi_fill_partition(struct intel_spi *ispi,
                 * whole partition read-only to be on the safe side.
                 */
                if (intel_spi_is_protected(ispi, base, limit))
-                       ispi->writeable = 0;
+                       ispi->writeable = false;
 
                end = (limit << 12) + 4096;
                if (end > part->size)
@@ -728,7 +728,7 @@ struct intel_spi *intel_spi_probe(struct device *dev,
 
        ispi->base = devm_ioremap_resource(dev, mem);
        if (IS_ERR(ispi->base))
-               return ispi->base;
+               return ERR_CAST(ispi->base);
 
        ispi->dev = dev;
        ispi->info = info;
index e661877c23deacbb7a6ac54603d9c0ed7e162af3..b6377707ce321e077c0d0d18005b6ccca3833f0f 100644 (file)
 #define MTK_NOR_MAX_RX_TX_SHIFT                6
 /* can shift up to 56 bits (7 bytes) transfer by MTK_NOR_PRG_CMD */
 #define MTK_NOR_MAX_SHIFT              7
+/* nor controller 4-byte address mode enable bit */
+#define MTK_NOR_4B_ADDR_EN             BIT(4)
 
 /* Helpers for accessing the program data / shift data registers */
 #define MTK_NOR_PRG_REG(n)             (MTK_NOR_PRGDATA0_REG + 4 * (n))
@@ -230,10 +232,35 @@ static int mt8173_nor_write_buffer_disable(struct mt8173_nor *mt8173_nor)
                                  10000);
 }
 
+static void mt8173_nor_set_addr_width(struct mt8173_nor *mt8173_nor)
+{
+       u8 val;
+       struct spi_nor *nor = &mt8173_nor->nor;
+
+       val = readb(mt8173_nor->base + MTK_NOR_DUAL_REG);
+
+       switch (nor->addr_width) {
+       case 3:
+               val &= ~MTK_NOR_4B_ADDR_EN;
+               break;
+       case 4:
+               val |= MTK_NOR_4B_ADDR_EN;
+               break;
+       default:
+               dev_warn(mt8173_nor->dev, "Unexpected address width %u.\n",
+                        nor->addr_width);
+               break;
+       }
+
+       writeb(val, mt8173_nor->base + MTK_NOR_DUAL_REG);
+}
+
 static void mt8173_nor_set_addr(struct mt8173_nor *mt8173_nor, u32 addr)
 {
        int i;
 
+       mt8173_nor_set_addr_width(mt8173_nor);
+
        for (i = 0; i < 3; i++) {
                writeb(addr & 0xff, mt8173_nor->base + MTK_NOR_RADR0_REG + i * 4);
                addr >>= 8;
index 747645c74134de4cd620a284e0f26ca8a61d4991..dea8c9cbadf00a75ff9e775a92c4029390c6e2b3 100644 (file)
@@ -85,6 +85,7 @@ struct flash_info {
                                         * Use dedicated 4byte address op codes
                                         * to support memory size above 128Mib.
                                         */
+#define NO_CHIP_ERASE          BIT(12) /* Chip does not support chip erase */
 };
 
 #define JEDEC_MFR(info)        ((info)->id[0])
@@ -960,6 +961,8 @@ static const struct flash_info spi_nor_ids[] = {
 
        /* ESMT */
        { "f25l32pa", INFO(0x8c2016, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_HAS_LOCK) },
+       { "f25l32qa", INFO(0x8c4116, 0, 64 * 1024, 64, SECT_4K | SPI_NOR_HAS_LOCK) },
+       { "f25l64qa", INFO(0x8c4117, 0, 64 * 1024, 128, SECT_4K | SPI_NOR_HAS_LOCK) },
 
        /* Everspin */
        { "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
@@ -1013,11 +1016,14 @@ static const struct flash_info spi_nor_ids[] = {
        { "mx25l3205d",  INFO(0xc22016, 0, 64 * 1024,  64, SECT_4K) },
        { "mx25l3255e",  INFO(0xc29e16, 0, 64 * 1024,  64, SECT_4K) },
        { "mx25l6405d",  INFO(0xc22017, 0, 64 * 1024, 128, SECT_4K) },
+       { "mx25u2033e",  INFO(0xc22532, 0, 64 * 1024,   4, SECT_4K) },
+       { "mx25u4035",   INFO(0xc22533, 0, 64 * 1024,   8, SECT_4K) },
+       { "mx25u8035",   INFO(0xc22534, 0, 64 * 1024,  16, SECT_4K) },
        { "mx25u6435f",  INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) },
        { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
        { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
        { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) },
-       { "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, SECT_4K) },
+       { "mx25u25635f", INFO(0xc22539, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_4B_OPCODES) },
        { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
        { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_QUAD_READ) },
        { "mx66l1g55g",  INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) },
@@ -1031,10 +1037,11 @@ static const struct flash_info spi_nor_ids[] = {
        { "n25q128a11",  INFO(0x20bb18, 0, 64 * 1024,  256, SECT_4K | SPI_NOR_QUAD_READ) },
        { "n25q128a13",  INFO(0x20ba18, 0, 64 * 1024,  256, SECT_4K | SPI_NOR_QUAD_READ) },
        { "n25q256a",    INFO(0x20ba19, 0, 64 * 1024,  512, SECT_4K | SPI_NOR_QUAD_READ) },
+       { "n25q256ax1",  INFO(0x20bb19, 0, 64 * 1024,  512, SECT_4K | SPI_NOR_QUAD_READ) },
        { "n25q512a",    INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
        { "n25q512ax3",  INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
-       { "n25q00",      INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
-       { "n25q00a",     INFO(0x20bb21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
+       { "n25q00",      INFO(0x20ba21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
+       { "n25q00a",     INFO(0x20bb21, 0, 64 * 1024, 2048, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ | NO_CHIP_ERASE) },
 
        /* PMC */
        { "pm25lv512",   INFO(0,        0, 32 * 1024,    2, SECT_4K_PMC) },
@@ -1128,6 +1135,9 @@ static const struct flash_info spi_nor_ids[] = {
        { "w25x80", INFO(0xef3014, 0, 64 * 1024,  16, SECT_4K) },
        { "w25x16", INFO(0xef3015, 0, 64 * 1024,  32, SECT_4K) },
        { "w25x32", INFO(0xef3016, 0, 64 * 1024,  64, SECT_4K) },
+       { "w25q20cl", INFO(0xef4012, 0, 64 * 1024,  4, SECT_4K) },
+       { "w25q20bw", INFO(0xef5012, 0, 64 * 1024,  4, SECT_4K) },
+       { "w25q20ew", INFO(0xef6012, 0, 64 * 1024,  4, SECT_4K) },
        { "w25q32", INFO(0xef4016, 0, 64 * 1024,  64, SECT_4K) },
        {
                "w25q32dw", INFO(0xef6016, 0, 64 * 1024,  64,
@@ -1629,6 +1639,8 @@ int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
                nor->flags |= SNOR_F_USE_FSR;
        if (info->flags & SPI_NOR_HAS_TB)
                nor->flags |= SNOR_F_HAS_SR_TB;
+       if (info->flags & NO_CHIP_ERASE)
+               nor->flags |= SNOR_F_NO_OP_CHIP_ERASE;
 
 #ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS
        /* prefer "small sector" erase if possible */
diff --git a/drivers/mtd/spi-nor/stm32-quadspi.c b/drivers/mtd/spi-nor/stm32-quadspi.c
new file mode 100644 (file)
index 0000000..ae45f81
--- /dev/null
@@ -0,0 +1,693 @@
+/*
+ * stm32_quadspi.c
+ *
+ * Copyright (C) 2017, Ludovic Barre
+ *
+ * License terms: GNU General Public License (GPL), version 2
+ */
+#include <linux/clk.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/spi-nor.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#define QUADSPI_CR             0x00
+#define CR_EN                  BIT(0)
+#define CR_ABORT               BIT(1)
+#define CR_DMAEN               BIT(2)
+#define CR_TCEN                        BIT(3)
+#define CR_SSHIFT              BIT(4)
+#define CR_DFM                 BIT(6)
+#define CR_FSEL                        BIT(7)
+#define CR_FTHRES_SHIFT                8
+#define CR_FTHRES_MASK         GENMASK(12, 8)
+#define CR_FTHRES(n)           (((n) << CR_FTHRES_SHIFT) & CR_FTHRES_MASK)
+#define CR_TEIE                        BIT(16)
+#define CR_TCIE                        BIT(17)
+#define CR_FTIE                        BIT(18)
+#define CR_SMIE                        BIT(19)
+#define CR_TOIE                        BIT(20)
+#define CR_PRESC_SHIFT         24
+#define CR_PRESC_MASK          GENMASK(31, 24)
+#define CR_PRESC(n)            (((n) << CR_PRESC_SHIFT) & CR_PRESC_MASK)
+
+#define QUADSPI_DCR            0x04
+#define DCR_CSHT_SHIFT         8
+#define DCR_CSHT_MASK          GENMASK(10, 8)
+#define DCR_CSHT(n)            (((n) << DCR_CSHT_SHIFT) & DCR_CSHT_MASK)
+#define DCR_FSIZE_SHIFT                16
+#define DCR_FSIZE_MASK         GENMASK(20, 16)
+#define DCR_FSIZE(n)           (((n) << DCR_FSIZE_SHIFT) & DCR_FSIZE_MASK)
+
+#define QUADSPI_SR             0x08
+#define SR_TEF                 BIT(0)
+#define SR_TCF                 BIT(1)
+#define SR_FTF                 BIT(2)
+#define SR_SMF                 BIT(3)
+#define SR_TOF                 BIT(4)
+#define SR_BUSY                        BIT(5)
+#define SR_FLEVEL_SHIFT                8
+#define SR_FLEVEL_MASK         GENMASK(13, 8)
+
+#define QUADSPI_FCR            0x0c
+#define FCR_CTCF               BIT(1)
+
+#define QUADSPI_DLR            0x10
+
+#define QUADSPI_CCR            0x14
+#define CCR_INST_SHIFT         0
+#define CCR_INST_MASK          GENMASK(7, 0)
+#define CCR_INST(n)            (((n) << CCR_INST_SHIFT) & CCR_INST_MASK)
+#define CCR_IMODE_NONE         (0U << 8)
+#define CCR_IMODE_1            (1U << 8)
+#define CCR_IMODE_2            (2U << 8)
+#define CCR_IMODE_4            (3U << 8)
+#define CCR_ADMODE_NONE                (0U << 10)
+#define CCR_ADMODE_1           (1U << 10)
+#define CCR_ADMODE_2           (2U << 10)
+#define CCR_ADMODE_4           (3U << 10)
+#define CCR_ADSIZE_SHIFT       12
+#define CCR_ADSIZE_MASK                GENMASK(13, 12)
+#define CCR_ADSIZE(n)          (((n) << CCR_ADSIZE_SHIFT) & CCR_ADSIZE_MASK)
+#define CCR_ABMODE_NONE                (0U << 14)
+#define CCR_ABMODE_1           (1U << 14)
+#define CCR_ABMODE_2           (2U << 14)
+#define CCR_ABMODE_4           (3U << 14)
+#define CCR_ABSIZE_8           (0U << 16)
+#define CCR_ABSIZE_16          (1U << 16)
+#define CCR_ABSIZE_24          (2U << 16)
+#define CCR_ABSIZE_32          (3U << 16)
+#define CCR_DCYC_SHIFT         18
+#define CCR_DCYC_MASK          GENMASK(22, 18)
+#define CCR_DCYC(n)            (((n) << CCR_DCYC_SHIFT) & CCR_DCYC_MASK)
+#define CCR_DMODE_NONE         (0U << 24)
+#define CCR_DMODE_1            (1U << 24)
+#define CCR_DMODE_2            (2U << 24)
+#define CCR_DMODE_4            (3U << 24)
+#define CCR_FMODE_INDW         (0U << 26)
+#define CCR_FMODE_INDR         (1U << 26)
+#define CCR_FMODE_APM          (2U << 26)
+#define CCR_FMODE_MM           (3U << 26)
+
+#define QUADSPI_AR             0x18
+#define QUADSPI_ABR            0x1c
+#define QUADSPI_DR             0x20
+#define QUADSPI_PSMKR          0x24
+#define QUADSPI_PSMAR          0x28
+#define QUADSPI_PIR            0x2c
+#define QUADSPI_LPTR           0x30
+#define LPTR_DFT_TIMEOUT       0x10
+
+#define FSIZE_VAL(size)                (__fls(size) - 1)
+
+#define STM32_MAX_MMAP_SZ      SZ_256M
+#define STM32_MAX_NORCHIP      2
+
+#define STM32_QSPI_FIFO_TIMEOUT_US 30000
+#define STM32_QSPI_BUSY_TIMEOUT_US 100000
+
+struct stm32_qspi_flash {
+       struct spi_nor nor;
+       struct stm32_qspi *qspi;
+       u32 cs;
+       u32 fsize;
+       u32 presc;
+       u32 read_mode;
+       bool registered;
+};
+
+struct stm32_qspi {
+       struct device *dev;
+       void __iomem *io_base;
+       void __iomem *mm_base;
+       resource_size_t mm_size;
+       u32 nor_num;
+       struct clk *clk;
+       u32 clk_rate;
+       struct stm32_qspi_flash flash[STM32_MAX_NORCHIP];
+       struct completion cmd_completion;
+
+       /*
+        * to protect device configuration, could be different between
+        * 2 flash access (bk1, bk2)
+        */
+       struct mutex lock;
+};
+
+struct stm32_qspi_cmd {
+       u8 addr_width;
+       u8 dummy;
+       bool tx_data;
+       u8 opcode;
+       u32 framemode;
+       u32 qspimode;
+       u32 addr;
+       size_t len;
+       void *buf;
+};
+
+static int stm32_qspi_wait_cmd(struct stm32_qspi *qspi)
+{
+       u32 cr;
+       int err = 0;
+
+       if (readl_relaxed(qspi->io_base + QUADSPI_SR) & SR_TCF)
+               return 0;
+
+       reinit_completion(&qspi->cmd_completion);
+       cr = readl_relaxed(qspi->io_base + QUADSPI_CR);
+       writel_relaxed(cr | CR_TCIE, qspi->io_base + QUADSPI_CR);
+
+       if (!wait_for_completion_interruptible_timeout(&qspi->cmd_completion,
+                                                      msecs_to_jiffies(1000)))
+               err = -ETIMEDOUT;
+
+       writel_relaxed(cr, qspi->io_base + QUADSPI_CR);
+       return err;
+}
+
+static int stm32_qspi_wait_nobusy(struct stm32_qspi *qspi)
+{
+       u32 sr;
+
+       return readl_relaxed_poll_timeout(qspi->io_base + QUADSPI_SR, sr,
+                                         !(sr & SR_BUSY), 10,
+                                         STM32_QSPI_BUSY_TIMEOUT_US);
+}
+
+static void stm32_qspi_set_framemode(struct spi_nor *nor,
+                                    struct stm32_qspi_cmd *cmd, bool read)
+{
+       u32 dmode = CCR_DMODE_1;
+
+       cmd->framemode = CCR_IMODE_1;
+
+       if (read) {
+               switch (nor->flash_read) {
+               case SPI_NOR_NORMAL:
+               case SPI_NOR_FAST:
+                       dmode = CCR_DMODE_1;
+                       break;
+               case SPI_NOR_DUAL:
+                       dmode = CCR_DMODE_2;
+                       break;
+               case SPI_NOR_QUAD:
+                       dmode = CCR_DMODE_4;
+                       break;
+               }
+       }
+
+       cmd->framemode |= cmd->tx_data ? dmode : 0;
+       cmd->framemode |= cmd->addr_width ? CCR_ADMODE_1 : 0;
+}
+
+static void stm32_qspi_read_fifo(u8 *val, void __iomem *addr)
+{
+       *val = readb_relaxed(addr);
+}
+
+static void stm32_qspi_write_fifo(u8 *val, void __iomem *addr)
+{
+       writeb_relaxed(*val, addr);
+}
+
+static int stm32_qspi_tx_poll(struct stm32_qspi *qspi,
+                             const struct stm32_qspi_cmd *cmd)
+{
+       void (*tx_fifo)(u8 *, void __iomem *);
+       u32 len = cmd->len, sr;
+       u8 *buf = cmd->buf;
+       int ret;
+
+       if (cmd->qspimode == CCR_FMODE_INDW)
+               tx_fifo = stm32_qspi_write_fifo;
+       else
+               tx_fifo = stm32_qspi_read_fifo;
+
+       while (len--) {
+               ret = readl_relaxed_poll_timeout(qspi->io_base + QUADSPI_SR,
+                                                sr, (sr & SR_FTF), 10,
+                                                STM32_QSPI_FIFO_TIMEOUT_US);
+               if (ret) {
+                       dev_err(qspi->dev, "fifo timeout (stat:%#x)\n", sr);
+                       break;
+               }
+               tx_fifo(buf++, qspi->io_base + QUADSPI_DR);
+       }
+
+       return ret;
+}
+
+static int stm32_qspi_tx_mm(struct stm32_qspi *qspi,
+                           const struct stm32_qspi_cmd *cmd)
+{
+       memcpy_fromio(cmd->buf, qspi->mm_base + cmd->addr, cmd->len);
+       return 0;
+}
+
+static int stm32_qspi_tx(struct stm32_qspi *qspi,
+                        const struct stm32_qspi_cmd *cmd)
+{
+       if (!cmd->tx_data)
+               return 0;
+
+       if (cmd->qspimode == CCR_FMODE_MM)
+               return stm32_qspi_tx_mm(qspi, cmd);
+
+       return stm32_qspi_tx_poll(qspi, cmd);
+}
+
+static int stm32_qspi_send(struct stm32_qspi_flash *flash,
+                          const struct stm32_qspi_cmd *cmd)
+{
+       struct stm32_qspi *qspi = flash->qspi;
+       u32 ccr, dcr, cr;
+       int err;
+
+       err = stm32_qspi_wait_nobusy(qspi);
+       if (err)
+               goto abort;
+
+       dcr = readl_relaxed(qspi->io_base + QUADSPI_DCR) & ~DCR_FSIZE_MASK;
+       dcr |= DCR_FSIZE(flash->fsize);
+       writel_relaxed(dcr, qspi->io_base + QUADSPI_DCR);
+
+       cr = readl_relaxed(qspi->io_base + QUADSPI_CR);
+       cr &= ~CR_PRESC_MASK & ~CR_FSEL;
+       cr |= CR_PRESC(flash->presc);
+       cr |= flash->cs ? CR_FSEL : 0;
+       writel_relaxed(cr, qspi->io_base + QUADSPI_CR);
+
+       if (cmd->tx_data)
+               writel_relaxed(cmd->len - 1, qspi->io_base + QUADSPI_DLR);
+
+       ccr = cmd->framemode | cmd->qspimode;
+
+       if (cmd->dummy)
+               ccr |= CCR_DCYC(cmd->dummy);
+
+       if (cmd->addr_width)
+               ccr |= CCR_ADSIZE(cmd->addr_width - 1);
+
+       ccr |= CCR_INST(cmd->opcode);
+       writel_relaxed(ccr, qspi->io_base + QUADSPI_CCR);
+
+       if (cmd->addr_width && cmd->qspimode != CCR_FMODE_MM)
+               writel_relaxed(cmd->addr, qspi->io_base + QUADSPI_AR);
+
+       err = stm32_qspi_tx(qspi, cmd);
+       if (err)
+               goto abort;
+
+       if (cmd->qspimode != CCR_FMODE_MM) {
+               err = stm32_qspi_wait_cmd(qspi);
+               if (err)
+                       goto abort;
+               writel_relaxed(FCR_CTCF, qspi->io_base + QUADSPI_FCR);
+       }
+
+       return err;
+
+abort:
+       cr = readl_relaxed(qspi->io_base + QUADSPI_CR) | CR_ABORT;
+       writel_relaxed(cr, qspi->io_base + QUADSPI_CR);
+
+       dev_err(qspi->dev, "%s abort err:%d\n", __func__, err);
+       return err;
+}
+
+static int stm32_qspi_read_reg(struct spi_nor *nor,
+                              u8 opcode, u8 *buf, int len)
+{
+       struct stm32_qspi_flash *flash = nor->priv;
+       struct device *dev = flash->qspi->dev;
+       struct stm32_qspi_cmd cmd;
+
+       dev_dbg(dev, "read_reg: cmd:%#.2x buf:%p len:%#x\n", opcode, buf, len);
+
+       memset(&cmd, 0, sizeof(cmd));
+       cmd.opcode = opcode;
+       cmd.tx_data = true;
+       cmd.len = len;
+       cmd.buf = buf;
+       cmd.qspimode = CCR_FMODE_INDR;
+
+       stm32_qspi_set_framemode(nor, &cmd, false);
+
+       return stm32_qspi_send(flash, &cmd);
+}
+
+static int stm32_qspi_write_reg(struct spi_nor *nor, u8 opcode,
+                               u8 *buf, int len)
+{
+       struct stm32_qspi_flash *flash = nor->priv;
+       struct device *dev = flash->qspi->dev;
+       struct stm32_qspi_cmd cmd;
+
+       dev_dbg(dev, "write_reg: cmd:%#.2x buf:%p len:%#x\n", opcode, buf, len);
+
+       memset(&cmd, 0, sizeof(cmd));
+       cmd.opcode = opcode;
+       cmd.tx_data = !!(buf && len > 0);
+       cmd.len = len;
+       cmd.buf = buf;
+       cmd.qspimode = CCR_FMODE_INDW;
+
+       stm32_qspi_set_framemode(nor, &cmd, false);
+
+       return stm32_qspi_send(flash, &cmd);
+}
+
+static ssize_t stm32_qspi_read(struct spi_nor *nor, loff_t from, size_t len,
+                              u_char *buf)
+{
+       struct stm32_qspi_flash *flash = nor->priv;
+       struct stm32_qspi *qspi = flash->qspi;
+       struct stm32_qspi_cmd cmd;
+       int err;
+
+       dev_dbg(qspi->dev, "read(%#.2x): buf:%p from:%#.8x len:%#x\n",
+               nor->read_opcode, buf, (u32)from, len);
+
+       memset(&cmd, 0, sizeof(cmd));
+       cmd.opcode = nor->read_opcode;
+       cmd.addr_width = nor->addr_width;
+       cmd.addr = (u32)from;
+       cmd.tx_data = true;
+       cmd.dummy = nor->read_dummy;
+       cmd.len = len;
+       cmd.buf = buf;
+       cmd.qspimode = flash->read_mode;
+
+       stm32_qspi_set_framemode(nor, &cmd, true);
+       err = stm32_qspi_send(flash, &cmd);
+
+       return err ? err : len;
+}
+
+static ssize_t stm32_qspi_write(struct spi_nor *nor, loff_t to, size_t len,
+                               const u_char *buf)
+{
+       struct stm32_qspi_flash *flash = nor->priv;
+       struct device *dev = flash->qspi->dev;
+       struct stm32_qspi_cmd cmd;
+       int err;
+
+       dev_dbg(dev, "write(%#.2x): buf:%p to:%#.8x len:%#x\n",
+               nor->program_opcode, buf, (u32)to, len);
+
+       memset(&cmd, 0, sizeof(cmd));
+       cmd.opcode = nor->program_opcode;
+       cmd.addr_width = nor->addr_width;
+       cmd.addr = (u32)to;
+       cmd.tx_data = true;
+       cmd.len = len;
+       cmd.buf = (void *)buf;
+       cmd.qspimode = CCR_FMODE_INDW;
+
+       stm32_qspi_set_framemode(nor, &cmd, false);
+       err = stm32_qspi_send(flash, &cmd);
+
+       return err ? err : len;
+}
+
+static int stm32_qspi_erase(struct spi_nor *nor, loff_t offs)
+{
+       struct stm32_qspi_flash *flash = nor->priv;
+       struct device *dev = flash->qspi->dev;
+       struct stm32_qspi_cmd cmd;
+
+       dev_dbg(dev, "erase(%#.2x):offs:%#x\n", nor->erase_opcode, (u32)offs);
+
+       memset(&cmd, 0, sizeof(cmd));
+       cmd.opcode = nor->erase_opcode;
+       cmd.addr_width = nor->addr_width;
+       cmd.addr = (u32)offs;
+       cmd.qspimode = CCR_FMODE_INDW;
+
+       stm32_qspi_set_framemode(nor, &cmd, false);
+
+       return stm32_qspi_send(flash, &cmd);
+}
+
+static irqreturn_t stm32_qspi_irq(int irq, void *dev_id)
+{
+       struct stm32_qspi *qspi = (struct stm32_qspi *)dev_id;
+       u32 cr, sr, fcr = 0;
+
+       cr = readl_relaxed(qspi->io_base + QUADSPI_CR);
+       sr = readl_relaxed(qspi->io_base + QUADSPI_SR);
+
+       if ((cr & CR_TCIE) && (sr & SR_TCF)) {
+               /* tx complete */
+               fcr |= FCR_CTCF;
+               complete(&qspi->cmd_completion);
+       } else {
+               dev_info_ratelimited(qspi->dev, "spurious interrupt\n");
+       }
+
+       writel_relaxed(fcr, qspi->io_base + QUADSPI_FCR);
+
+       return IRQ_HANDLED;
+}
+
+static int stm32_qspi_prep(struct spi_nor *nor, enum spi_nor_ops ops)
+{
+       struct stm32_qspi_flash *flash = nor->priv;
+       struct stm32_qspi *qspi = flash->qspi;
+
+       mutex_lock(&qspi->lock);
+       return 0;
+}
+
+static void stm32_qspi_unprep(struct spi_nor *nor, enum spi_nor_ops ops)
+{
+       struct stm32_qspi_flash *flash = nor->priv;
+       struct stm32_qspi *qspi = flash->qspi;
+
+       mutex_unlock(&qspi->lock);
+}
+
+static int stm32_qspi_flash_setup(struct stm32_qspi *qspi,
+                                 struct device_node *np)
+{
+       u32 width, flash_read, presc, cs_num, max_rate = 0;
+       struct stm32_qspi_flash *flash;
+       struct mtd_info *mtd;
+       int ret;
+
+       of_property_read_u32(np, "reg", &cs_num);
+       if (cs_num >= STM32_MAX_NORCHIP)
+               return -EINVAL;
+
+       of_property_read_u32(np, "spi-max-frequency", &max_rate);
+       if (!max_rate)
+               return -EINVAL;
+
+       presc = DIV_ROUND_UP(qspi->clk_rate, max_rate) - 1;
+
+       if (of_property_read_u32(np, "spi-rx-bus-width", &width))
+               width = 1;
+
+       if (width == 4)
+               flash_read = SPI_NOR_QUAD;
+       else if (width == 2)
+               flash_read = SPI_NOR_DUAL;
+       else if (width == 1)
+               flash_read = SPI_NOR_NORMAL;
+       else
+               return -EINVAL;
+
+       flash = &qspi->flash[cs_num];
+       flash->qspi = qspi;
+       flash->cs = cs_num;
+       flash->presc = presc;
+
+       flash->nor.dev = qspi->dev;
+       spi_nor_set_flash_node(&flash->nor, np);
+       flash->nor.priv = flash;
+       mtd = &flash->nor.mtd;
+
+       flash->nor.read = stm32_qspi_read;
+       flash->nor.write = stm32_qspi_write;
+       flash->nor.erase = stm32_qspi_erase;
+       flash->nor.read_reg = stm32_qspi_read_reg;
+       flash->nor.write_reg = stm32_qspi_write_reg;
+       flash->nor.prepare = stm32_qspi_prep;
+       flash->nor.unprepare = stm32_qspi_unprep;
+
+       writel_relaxed(LPTR_DFT_TIMEOUT, qspi->io_base + QUADSPI_LPTR);
+
+       writel_relaxed(CR_PRESC(presc) | CR_FTHRES(3) | CR_TCEN | CR_SSHIFT
+                      | CR_EN, qspi->io_base + QUADSPI_CR);
+
+       /*
+        * in stm32 qspi controller, QUADSPI_DCR register has a fsize field
+        * which define the size of nor flash.
+        * if fsize is NULL, the controller can't sent spi-nor command.
+        * set a temporary value just to discover the nor flash with
+        * "spi_nor_scan". After, the right value (mtd->size) can be set.
+        */
+       flash->fsize = FSIZE_VAL(SZ_1K);
+
+       ret = spi_nor_scan(&flash->nor, NULL, flash_read);
+       if (ret) {
+               dev_err(qspi->dev, "device scan failed\n");
+               return ret;
+       }
+
+       flash->fsize = FSIZE_VAL(mtd->size);
+
+       flash->read_mode = CCR_FMODE_MM;
+       if (mtd->size > qspi->mm_size)
+               flash->read_mode = CCR_FMODE_INDR;
+
+       writel_relaxed(DCR_CSHT(1), qspi->io_base + QUADSPI_DCR);
+
+       ret = mtd_device_register(mtd, NULL, 0);
+       if (ret) {
+               dev_err(qspi->dev, "mtd device parse failed\n");
+               return ret;
+       }
+
+       flash->registered = true;
+
+       dev_dbg(qspi->dev, "read mm:%s cs:%d bus:%d\n",
+               flash->read_mode == CCR_FMODE_MM ? "yes" : "no", cs_num, width);
+
+       return 0;
+}
+
+static void stm32_qspi_mtd_free(struct stm32_qspi *qspi)
+{
+       int i;
+
+       for (i = 0; i < STM32_MAX_NORCHIP; i++)
+               if (qspi->flash[i].registered)
+                       mtd_device_unregister(&qspi->flash[i].nor.mtd);
+}
+
+static int stm32_qspi_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *flash_np;
+       struct reset_control *rstc;
+       struct stm32_qspi *qspi;
+       struct resource *res;
+       int ret, irq;
+
+       qspi = devm_kzalloc(dev, sizeof(*qspi), GFP_KERNEL);
+       if (!qspi)
+               return -ENOMEM;
+
+       qspi->nor_num = of_get_child_count(dev->of_node);
+       if (!qspi->nor_num || qspi->nor_num > STM32_MAX_NORCHIP)
+               return -ENODEV;
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qspi");
+       qspi->io_base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(qspi->io_base))
+               return PTR_ERR(qspi->io_base);
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "qspi_mm");
+       qspi->mm_base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(qspi->mm_base))
+               return PTR_ERR(qspi->mm_base);
+
+       qspi->mm_size = resource_size(res);
+
+       irq = platform_get_irq(pdev, 0);
+       ret = devm_request_irq(dev, irq, stm32_qspi_irq, 0,
+                              dev_name(dev), qspi);
+       if (ret) {
+               dev_err(dev, "failed to request irq\n");
+               return ret;
+       }
+
+       init_completion(&qspi->cmd_completion);
+
+       qspi->clk = devm_clk_get(dev, NULL);
+       if (IS_ERR(qspi->clk))
+               return PTR_ERR(qspi->clk);
+
+       qspi->clk_rate = clk_get_rate(qspi->clk);
+       if (!qspi->clk_rate)
+               return -EINVAL;
+
+       ret = clk_prepare_enable(qspi->clk);
+       if (ret) {
+               dev_err(dev, "can not enable the clock\n");
+               return ret;
+       }
+
+       rstc = devm_reset_control_get(dev, NULL);
+       if (!IS_ERR(rstc)) {
+               reset_control_assert(rstc);
+               udelay(2);
+               reset_control_deassert(rstc);
+       }
+
+       qspi->dev = dev;
+       platform_set_drvdata(pdev, qspi);
+       mutex_init(&qspi->lock);
+
+       for_each_available_child_of_node(dev->of_node, flash_np) {
+               ret = stm32_qspi_flash_setup(qspi, flash_np);
+               if (ret) {
+                       dev_err(dev, "unable to setup flash chip\n");
+                       goto err_flash;
+               }
+       }
+
+       return 0;
+
+err_flash:
+       mutex_destroy(&qspi->lock);
+       stm32_qspi_mtd_free(qspi);
+
+       clk_disable_unprepare(qspi->clk);
+       return ret;
+}
+
+static int stm32_qspi_remove(struct platform_device *pdev)
+{
+       struct stm32_qspi *qspi = platform_get_drvdata(pdev);
+
+       /* disable qspi */
+       writel_relaxed(0, qspi->io_base + QUADSPI_CR);
+
+       stm32_qspi_mtd_free(qspi);
+       mutex_destroy(&qspi->lock);
+
+       clk_disable_unprepare(qspi->clk);
+       return 0;
+}
+
+static const struct of_device_id stm32_qspi_match[] = {
+       {.compatible = "st,stm32f469-qspi"},
+       {}
+};
+MODULE_DEVICE_TABLE(of, stm32_qspi_match);
+
+static struct platform_driver stm32_qspi_driver = {
+       .probe  = stm32_qspi_probe,
+       .remove = stm32_qspi_remove,
+       .driver = {
+               .name = "stm32-quadspi",
+               .of_match_table = stm32_qspi_match,
+       },
+};
+module_platform_driver(stm32_qspi_driver);
+
+MODULE_AUTHOR("Ludovic Barre <ludovic.barre@st.com>");
+MODULE_DESCRIPTION("STMicroelectronics STM32 quad spi driver");
+MODULE_LICENSE("GPL v2");
index 8bae3731d039d64c17dd1e20578644142ebea2dd..93e5d251a9e4557ecb961132bddb21048a295316 100644 (file)
@@ -74,10 +74,10 @@ struct mtd_dev_param {
 };
 
 /* Numbers of elements set in the @mtd_dev_param array */
-static int __initdata mtd_devs;
+static int mtd_devs;
 
 /* MTD devices specification parameters */
-static struct mtd_dev_param __initdata mtd_dev_param[UBI_MAX_DEVICES];
+static struct mtd_dev_param mtd_dev_param[UBI_MAX_DEVICES];
 #ifdef CONFIG_MTD_UBI_FASTMAP
 /* UBI module parameter to enable fastmap automatically on non-fastmap images */
 static bool fm_autoconvert;
@@ -1294,7 +1294,7 @@ module_exit(ubi_exit);
  * This function returns positive resulting integer in case of success and a
  * negative error code in case of failure.
  */
-static int __init bytes_str_to_int(const char *str)
+static int bytes_str_to_int(const char *str)
 {
        char *endp;
        unsigned long result;
@@ -1332,7 +1332,7 @@ static int __init bytes_str_to_int(const char *str)
  * This function returns zero in case of success and a negative error code in
  * case of error.
  */
-static int __init ubi_mtd_param_parse(const char *val, struct kernel_param *kp)
+static int ubi_mtd_param_parse(const char *val, struct kernel_param *kp)
 {
        int i, len;
        struct mtd_dev_param *p;
@@ -1413,7 +1413,7 @@ static int __init ubi_mtd_param_parse(const char *val, struct kernel_param *kp)
        return 0;
 }
 
-module_param_call(mtd, ubi_mtd_param_parse, NULL, NULL, 000);
+module_param_call(mtd, ubi_mtd_param_parse, NULL, NULL, 0400);
 MODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: mtd=<name|num|path>[,<vid_hdr_offs>[,max_beb_per1024[,ubi_num]]].\n"
                      "Multiple \"mtd\" parameters may be specified.\n"
                      "MTD devices may be specified by their number, name, or path to the MTD character device node.\n"
index f101a4985a7c39a9891fffd6a6f4f8ff36570ce4..7bc96294ae4d530ef129dff3b6c67978f6e227da 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/debugfs.h>
 #include <linux/uaccess.h>
 #include <linux/module.h>
+#include <linux/seq_file.h>
 
 
 /**
@@ -386,7 +387,9 @@ out:
        return count;
 }
 
-/* File operations for all UBI debugfs files */
+/* File operations for all UBI debugfs files except
+ * detailed_erase_block_info
+ */
 static const struct file_operations dfs_fops = {
        .read   = dfs_file_read,
        .write  = dfs_file_write,
@@ -395,6 +398,121 @@ static const struct file_operations dfs_fops = {
        .owner  = THIS_MODULE,
 };
 
+/* As long as the position is less then that total number of erase blocks,
+ * we still have more to print.
+ */
+static void *eraseblk_count_seq_start(struct seq_file *s, loff_t *pos)
+{
+       struct ubi_device *ubi = s->private;
+
+       if (*pos == 0)
+               return SEQ_START_TOKEN;
+
+       if (*pos < ubi->peb_count)
+               return pos;
+
+       return NULL;
+}
+
+/* Since we are using the position as the iterator, we just need to check if we
+ * are done and increment the position.
+ */
+static void *eraseblk_count_seq_next(struct seq_file *s, void *v, loff_t *pos)
+{
+       struct ubi_device *ubi = s->private;
+
+       if (v == SEQ_START_TOKEN)
+               return pos;
+       (*pos)++;
+
+       if (*pos < ubi->peb_count)
+               return pos;
+
+       return NULL;
+}
+
+static void eraseblk_count_seq_stop(struct seq_file *s, void *v)
+{
+}
+
+static int eraseblk_count_seq_show(struct seq_file *s, void *iter)
+{
+       struct ubi_device *ubi = s->private;
+       struct ubi_wl_entry *wl;
+       int *block_number = iter;
+       int erase_count = -1;
+       int err;
+
+       /* If this is the start, print a header */
+       if (iter == SEQ_START_TOKEN) {
+               seq_puts(s,
+                        "physical_block_number\terase_count\tblock_status\tread_status\n");
+               return 0;
+       }
+
+       err = ubi_io_is_bad(ubi, *block_number);
+       if (err)
+               return err;
+
+       spin_lock(&ubi->wl_lock);
+
+       wl = ubi->lookuptbl[*block_number];
+       if (wl)
+               erase_count = wl->ec;
+
+       spin_unlock(&ubi->wl_lock);
+
+       if (erase_count < 0)
+               return 0;
+
+       seq_printf(s, "%-22d\t%-11d\n", *block_number, erase_count);
+
+       return 0;
+}
+
+static const struct seq_operations eraseblk_count_seq_ops = {
+       .start = eraseblk_count_seq_start,
+       .next = eraseblk_count_seq_next,
+       .stop = eraseblk_count_seq_stop,
+       .show = eraseblk_count_seq_show
+};
+
+static int eraseblk_count_open(struct inode *inode, struct file *f)
+{
+       struct seq_file *s;
+       int err;
+
+       err = seq_open(f, &eraseblk_count_seq_ops);
+       if (err)
+               return err;
+
+       s = f->private_data;
+       s->private = ubi_get_device((unsigned long)inode->i_private);
+
+       if (!s->private)
+               return -ENODEV;
+       else
+               return 0;
+}
+
+static int eraseblk_count_release(struct inode *inode, struct file *f)
+{
+       struct seq_file *s = f->private_data;
+       struct ubi_device *ubi = s->private;
+
+       ubi_put_device(ubi);
+
+       return seq_release(inode, f);
+}
+
+static const struct file_operations eraseblk_count_fops = {
+       .owner = THIS_MODULE,
+       .open = eraseblk_count_open,
+       .read = seq_read,
+       .llseek = seq_lseek,
+       .release = eraseblk_count_release,
+};
+
 /**
  * ubi_debugfs_init_dev - initialize debugfs for an UBI device.
  * @ubi: UBI device description object
@@ -491,6 +609,12 @@ int ubi_debugfs_init_dev(struct ubi_device *ubi)
                goto out_remove;
        d->dfs_power_cut_max = dent;
 
+       fname = "detailed_erase_block_info";
+       dent = debugfs_create_file(fname, S_IRUSR, d->dfs_dir, (void *)ubi_num,
+                                  &eraseblk_count_fops);
+       if (IS_ERR_OR_NULL(dent))
+               goto out_remove;
+
        return 0;
 
 out_remove:
index c1f5c29e458ef86305376fa7b404f9c5b8e05681..b44c8d348e78ec0b19c884178e54c83a0967dc90 100644 (file)
@@ -828,6 +828,24 @@ static int find_fm_anchor(struct ubi_attach_info *ai)
        return ret;
 }
 
+static struct ubi_ainf_peb *clone_aeb(struct ubi_attach_info *ai,
+                                     struct ubi_ainf_peb *old)
+{
+       struct ubi_ainf_peb *new;
+
+       new = ubi_alloc_aeb(ai, old->pnum, old->ec);
+       if (!new)
+               return NULL;
+
+       new->vol_id = old->vol_id;
+       new->sqnum = old->sqnum;
+       new->lnum = old->lnum;
+       new->scrub = old->scrub;
+       new->copy_flag = old->copy_flag;
+
+       return new;
+}
+
 /**
  * ubi_scan_fastmap - scan the fastmap.
  * @ubi: UBI device object
@@ -847,7 +865,7 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai,
        struct ubi_vid_hdr *vh;
        struct ubi_ec_hdr *ech;
        struct ubi_fastmap_layout *fm;
-       struct ubi_ainf_peb *tmp_aeb, *aeb;
+       struct ubi_ainf_peb *aeb;
        int i, used_blocks, pnum, fm_anchor, ret = 0;
        size_t fm_size;
        __be32 crc, tmp_crc;
@@ -857,9 +875,16 @@ int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai,
        if (fm_anchor < 0)
                return UBI_NO_FASTMAP;
 
-       /* Move all (possible) fastmap blocks into our new attach structure. */
-       list_for_each_entry_safe(aeb, tmp_aeb, &scan_ai->fastmap, u.list)
-               list_move_tail(&aeb->u.list, &ai->fastmap);
+       /* Copy all (possible) fastmap blocks into our new attach structure. */
+       list_for_each_entry(aeb, &scan_ai->fastmap, u.list) {
+               struct ubi_ainf_peb *new;
+
+               new = clone_aeb(ai, aeb);
+               if (!new)
+                       return -ENOMEM;
+
+               list_add(&new->u.list, &ai->fastmap);
+       }
 
        down_write(&ubi->fm_protect);
        memset(ubi->fm_buf, 0, ubi->fm_size);
index 1b2e9217ec789a4b338690a9e065d06c1d1b07f5..486e1e6997fc8729922b6a90d910ac9d3bb2caf4 100644 (file)
@@ -986,9 +986,9 @@ static int cops_close(struct net_device *dev)
 static struct net_device *cops_dev;
 
 MODULE_LICENSE("GPL");
-module_param(io, int, 0);
-module_param(irq, int, 0);
-module_param(board_type, int, 0);
+module_param_hw(io, int, ioport, 0);
+module_param_hw(irq, int, irq, 0);
+module_param_hw(board_type, int, other, 0);
 
 static int __init cops_module_init(void)
 {
index 01e2ac55c137ee10f69641fcea8168aaee9696cf..ac755d2950a63e2b2421217bb3b164d496d831c5 100644 (file)
@@ -1231,9 +1231,9 @@ static struct net_device *dev_ltpc;
 
 MODULE_LICENSE("GPL");
 module_param(debug, int, 0);
-module_param(io, int, 0);
-module_param(irq, int, 0);
-module_param(dma, int, 0);
+module_param_hw(io, int, ioport, 0);
+module_param_hw(irq, int, irq, 0);
+module_param_hw(dma, int, dma, 0);
 
 
 static int __init ltpc_module_init(void)
index b9e9931353b22a727066eaef790dec1f63d3fd5f..38fa60ddaf2ea0d2c8d3d0db15640c94035ae54b 100644 (file)
@@ -129,8 +129,8 @@ static int clockp = 0;
 static int clockm = 0;
 
 module_param(node, int, 0);
-module_param(io, int, 0);
-module_param(irq, int, 0);
+module_param_hw(io, int, ioport, 0);
+module_param_hw(irq, int, irq, 0);
 module_param_string(device, device, sizeof(device), 0);
 module_param(timeout, int, 0);
 module_param(backplane, int, 0);
index b57863df5bf53e6ee0269b4d9f2055a06011b1d1..4e56aaf2b9843cb633a10cf93c0a4242b270ce8f 100644 (file)
@@ -347,8 +347,8 @@ static int io;                      /* use the insmod io= irq= shmem= options */
 static int irq;
 static char device[9];         /* use eg. device=arc1 to change name */
 
-module_param(io, int, 0);
-module_param(irq, int, 0);
+module_param_hw(io, int, ioport, 0);
+module_param_hw(irq, int, irq, 0);
 module_param_string(device, device, sizeof(device), 0);
 MODULE_LICENSE("GPL");
 
index 81f90c4703ae266eb6c894bf636059ee389d4d6e..ca4a57c30bf89ed8d565d228aca9953153a3adf4 100644 (file)
@@ -88,8 +88,8 @@ static int irq;
 static int shmem;
 static char device[9];         /* use eg. device=arc1 to change name */
 
-module_param(io, int, 0);
-module_param(irq, int, 0);
+module_param_hw(io, int, ioport, 0);
+module_param_hw(irq, int, irq, 0);
 module_param(shmem, int, 0);
 module_param_string(device, device, sizeof(device), 0);
 
index c502c139d3bc6b50eafddc257a60e43ae8100ed0..47a8103610bc9111646f9bbf12b45f1fc4ed0115 100644 (file)
@@ -549,7 +549,8 @@ static int bond_fill_info(struct sk_buff *skb,
        targets_added = 0;
        for (i = 0; i < BOND_MAX_ARP_TARGETS; i++) {
                if (bond->params.arp_targets[i]) {
-                       nla_put_be32(skb, i, bond->params.arp_targets[i]);
+                       if (nla_put_be32(skb, i, bond->params.arp_targets[i]))
+                               goto nla_put_failure;
                        targets_added = 1;
                }
        }
index bc0eb47ecceea7891c22e309f604ece0b0de9807..6122768c86444ec5b9c5fa67d7a63aa2690ba2f5 100644 (file)
@@ -679,8 +679,7 @@ static int cfv_probe(struct virtio_device *vdev)
                goto err;
 
        /* Get the TX virtio ring. This is a "guest side vring". */
-       err = vdev->config->find_vqs(vdev, 1, &cfv->vq_tx, &vq_cbs, &names,
-                       NULL);
+       err = virtio_find_vqs(vdev, 1, &cfv->vq_tx, &vq_cbs, &names, NULL);
        if (err)
                goto err;
 
index e0d15711e9ac2ae7981247400d0f294eb1c9da37..3a30fd3b449847e467e8a5efd2bd6c06c06740a2 100644 (file)
@@ -82,16 +82,16 @@ static u8 cor[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
 static u8 bcr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
 static int indirect[MAXDEV] = {[0 ... (MAXDEV - 1)] = -1};
 
-module_param_array(port, ulong, NULL, S_IRUGO);
+module_param_hw_array(port, ulong, ioport, NULL, S_IRUGO);
 MODULE_PARM_DESC(port, "I/O port number");
 
-module_param_array(mem, ulong, NULL, S_IRUGO);
+module_param_hw_array(mem, ulong, iomem, NULL, S_IRUGO);
 MODULE_PARM_DESC(mem, "I/O memory address");
 
-module_param_array(indirect, int, NULL, S_IRUGO);
+module_param_hw_array(indirect, int, ioport, NULL, S_IRUGO);
 MODULE_PARM_DESC(indirect, "Indirect access via address and data port");
 
-module_param_array(irq, int, NULL, S_IRUGO);
+module_param_hw_array(irq, int, irq, NULL, S_IRUGO);
 MODULE_PARM_DESC(irq, "IRQ number");
 
 module_param_array(clk, int, NULL, S_IRUGO);
index 4ef07d97156da838edaad4661f094d2e38d9111f..602c19e23f052ed50bd691408bc9644bf5049cb5 100644 (file)
 /* RSCFDnRPGACCr */
 #define RCANFD_C_RPGACC(r)             (0x1900 + (0x04 * (r)))
 
-/* CAN FD mode specific regsiter map */
+/* CAN FD mode specific register map */
 
 /* RSCFDnCFDCmXXX -> RCANFD_F_XXX(m) */
 #define RCANFD_F_DCFG(m)               (0x0500 + (0x20 * (m)))
index e97e6d35b3000af1e13387040edd12e0a106bba6..a89c1e92554db1418752e8f7b6c5598fba6b4edf 100644 (file)
@@ -48,16 +48,16 @@ static unsigned char ocr[MAXDEV] = {[0 ... (MAXDEV - 1)] = 0xff};
 static int indirect[MAXDEV] = {[0 ... (MAXDEV - 1)] = -1};
 static spinlock_t indirect_lock[MAXDEV];  /* lock for indirect access mode */
 
-module_param_array(port, ulong, NULL, S_IRUGO);
+module_param_hw_array(port, ulong, ioport, NULL, S_IRUGO);
 MODULE_PARM_DESC(port, "I/O port number");
 
-module_param_array(mem, ulong, NULL, S_IRUGO);
+module_param_hw_array(mem, ulong, iomem, NULL, S_IRUGO);
 MODULE_PARM_DESC(mem, "I/O memory address");
 
-module_param_array(indirect, int, NULL, S_IRUGO);
+module_param_hw_array(indirect, int, ioport, NULL, S_IRUGO);
 MODULE_PARM_DESC(indirect, "Indirect access via address and data port");
 
-module_param_array(irq, int, NULL, S_IRUGO);
+module_param_hw_array(irq, int, irq, NULL, S_IRUGO);
 MODULE_PARM_DESC(irq, "IRQ number");
 
 module_param_array(clk, int, NULL, S_IRUGO);
index f0fc4de4fc9a4854ac6b2d6926ed549fed71ce26..a19e1781e9bbf353bf747d238249f0795f2f59cd 100644 (file)
@@ -256,6 +256,9 @@ static int dsa_loop_drv_probe(struct mdio_device *mdiodev)
                return -ENOMEM;
 
        ps = devm_kzalloc(&mdiodev->dev, sizeof(*ps), GFP_KERNEL);
+       if (!ps)
+               return -ENOMEM;
+
        ps->netdev = dev_get_by_name(&init_net, pdata->netdev);
        if (!ps->netdev)
                return -EPROBE_DEFER;
index 19581d783d8ec7dc9ed9e5fd5a2891e8f2d22135..d034d8cd7d22dcde187f0becb24afd45480271f3 100644 (file)
@@ -849,6 +849,9 @@ static uint64_t _mv88e6xxx_get_ethtool_stat(struct mv88e6xxx_chip *chip,
                mv88e6xxx_g1_stats_read(chip, reg, &low);
                if (s->sizeof_stat == 8)
                        mv88e6xxx_g1_stats_read(chip, reg + 1, &high);
+               break;
+       default:
+               return UINT64_MAX;
        }
        value = (((u64)high) << 16) | low;
        return value;
index c7f9f2c77da72aefe4c9eb091216850f8e53f6b2..db8592d412abc5268ed95629666636daa496e87f 100644 (file)
@@ -1371,7 +1371,7 @@ el3_resume(struct device *pdev)
 #endif /* CONFIG_PM */
 
 module_param(debug,int, 0);
-module_param_array(irq, int, NULL, 0);
+module_param_hw_array(irq, int, irq, NULL, 0);
 module_param(max_interrupt_work, int, 0);
 MODULE_PARM_DESC(debug, "debug level (0-6)");
 MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
index 40196f41768a00b9ae63e0ee3d99547b8e7d5f39..e41245a54f8bfc6949c0c1cc0b3fe63438d16605 100644 (file)
@@ -813,8 +813,8 @@ module_param(global_enable_wol, int, 0);
 module_param_array(enable_wol, int, NULL, 0);
 module_param(rx_copybreak, int, 0);
 module_param(max_interrupt_work, int, 0);
-module_param(compaq_ioaddr, int, 0);
-module_param(compaq_irq, int, 0);
+module_param_hw(compaq_ioaddr, int, ioport, 0);
+module_param_hw(compaq_irq, int, irq, 0);
 module_param(compaq_device_id, int, 0);
 module_param(watchdog, int, 0);
 module_param(global_use_mmio, int, 0);
index c063b410a163e4b53eb5bea70e3ed423756ebc5b..66f47987e2a283b8faf35f8fb662ae41a6a463fa 100644 (file)
@@ -74,8 +74,8 @@ static int bad[MAX_NE_CARDS];
 static u32 ne_msg_enable;
 
 #ifdef MODULE
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
+module_param_hw_array(io, int, ioport, NULL, 0);
+module_param_hw_array(irq, int, irq, NULL, 0);
 module_param_array(bad, int, NULL, 0);
 module_param_named(msg_enable, ne_msg_enable, uint, (S_IRUSR|S_IRGRP|S_IROTH));
 MODULE_PARM_DESC(io, "I/O base address(es),required");
index 364b6514f65fa61b68780aa996b6747f4581f4f0..4e02f6a235753897b33dca8503792f18ec4acf80 100644 (file)
@@ -561,8 +561,8 @@ static struct net_device *dev_ultra[MAX_ULTRA_CARDS];
 static int io[MAX_ULTRA_CARDS];
 static int irq[MAX_ULTRA_CARDS];
 
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
+module_param_hw_array(io, int, ioport, NULL, 0);
+module_param_hw_array(irq, int, irq, NULL, 0);
 module_param_named(msg_enable, ultra_msg_enable, uint, (S_IRUSR|S_IRGRP|S_IROTH));
 MODULE_PARM_DESC(io, "I/O base address(es)");
 MODULE_PARM_DESC(irq, "IRQ number(s) (assigned)");
index ad019cbc698f6ea8ec9fbd648015e6630a6b5f82..6efa2722f850262a33d81c2bb37686435ba3ff79 100644 (file)
@@ -503,10 +503,10 @@ static int irq[MAX_WD_CARDS];
 static int mem[MAX_WD_CARDS];
 static int mem_end[MAX_WD_CARDS];      /* for non std. mem size */
 
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
-module_param_array(mem, int, NULL, 0);
-module_param_array(mem_end, int, NULL, 0);
+module_param_hw_array(io, int, ioport, NULL, 0);
+module_param_hw_array(irq, int, irq, NULL, 0);
+module_param_hw_array(mem, int, iomem, NULL, 0);
+module_param_hw_array(mem_end, int, iomem, NULL, 0);
 module_param_named(msg_enable, wd_msg_enable, uint, (S_IRUSR|S_IRGRP|S_IROTH));
 MODULE_PARM_DESC(io, "I/O base address(es)");
 MODULE_PARM_DESC(irq, "IRQ number(s) (ignored for PureData boards)");
index 7cdb185124073022cddb73ece5ae33decc90be53..2a57b46fd6a66b132f34a55208994493d55a3f52 100644 (file)
@@ -48,7 +48,7 @@ eg., if the value 10011010b is written into the least significant byte of a comm
 /* 32 bit registers */
 
 #define  ASF_STAT              0x00    /* ASF status register */
-#define CHIPID                 0x04    /* Chip ID regsiter */
+#define CHIPID                 0x04    /* Chip ID register */
 #define        MIB_DATA                0x10    /* MIB data register */
 #define MIB_ADDR               0x14    /* MIB address register */
 #define STAT0                  0x30    /* Status0 register */
@@ -648,7 +648,7 @@ typedef enum {
 /* driver ioctl parameters */
 #define AMD8111E_REG_DUMP_LEN   13*sizeof(u32)
 
-/* amd8111e desriptor format */
+/* amd8111e descriptor format */
 
 struct amd8111e_tx_dr{
 
index 796c37a5bbde0d6ba693eddf7b7099884de8ebcc..c5b81268c2849491ba22d26181f4c1b8332526c9 100644 (file)
@@ -42,8 +42,8 @@
 
 */
 
-static char version[] = "atarilance.c: v1.3 04/04/96 "
-                                          "Roman.Hodek@informatik.uni-erlangen.de\n";
+static const char version[] = "atarilance.c: v1.3 04/04/96 "
+                             "Roman.Hodek@informatik.uni-erlangen.de\n";
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
index 6c98901f1b8970ae4a41b02a292179262ad38eba..82cc81385033009a0147c8d647808a706a0ddfc3 100644 (file)
@@ -72,7 +72,7 @@
 #include <asm/dec/machtype.h>
 #include <asm/dec/system.h>
 
-static char version[] =
+static const char version[] =
 "declance.c: v0.011 by Linux MIPS DECstation task force\n";
 
 MODULE_AUTHOR("Linux MIPS DECstation task force");
index 61a641f2314968cda20bd2c76b5de11309efa207..12a6a93d221bb85a30af80741d18c89c85412cc5 100644 (file)
@@ -318,9 +318,9 @@ static int io[MAX_CARDS];
 static int dma[MAX_CARDS];
 static int irq[MAX_CARDS];
 
-module_param_array(io, int, NULL, 0);
-module_param_array(dma, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
+module_param_hw_array(io, int, ioport, NULL, 0);
+module_param_hw_array(dma, int, dma, NULL, 0);
+module_param_hw_array(irq, int, irq, NULL, 0);
 module_param(lance_debug, int, 0);
 MODULE_PARM_DESC(io, "LANCE/PCnet I/O base address(es),required");
 MODULE_PARM_DESC(dma, "LANCE/PCnet ISA DMA channel (ignored for some devices)");
index 5985bf220a8da9d426a38d7e593f6daaa3859de0..e248d1ab3e47cda242108accc9e62395eddaaa44 100644 (file)
@@ -1227,9 +1227,9 @@ static void set_multicast_list(struct net_device *dev)
 #ifdef MODULE
 static struct net_device *dev_ni65;
 
-module_param(irq, int, 0);
-module_param(io, int, 0);
-module_param(dma, int, 0);
+module_param_hw(irq, int, irq, 0);
+module_param_hw(io, int, ioport, 0);
+module_param_hw(dma, int, dma, 0);
 MODULE_PARM_DESC(irq, "ni6510 IRQ number (ignored for some cards)");
 MODULE_PARM_DESC(io, "ni6510 I/O base address");
 MODULE_PARM_DESC(dma, "ni6510 ISA DMA channel (ignored for some cards)");
index 12bb4f1489fc0560ff76dbaa5009a35c80a87362..77b1db2677309e639f52c75ecbc96e9e451a7bbb 100644 (file)
@@ -21,7 +21,8 @@
 
 */
 
-static char *version = "sun3lance.c: v1.2 1/12/2001  Sam Creasey (sammy@sammy.net)\n";
+static const char version[] =
+"sun3lance.c: v1.2 1/12/2001  Sam Creasey (sammy@sammy.net)\n";
 
 #include <linux/module.h>
 #include <linux/stddef.h>
index cdb02991f249c6354b7095d9d777316617c2be42..9ee1c501678409719f460912c6316b803c2dc7fc 100644 (file)
@@ -755,7 +755,7 @@ void aq_nic_get_stats(struct aq_nic_s *self, u64 *data)
        count = 0U;
 
        for (i = 0U, aq_vec = self->aq_vec[0];
-               self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i]) {
+               aq_vec && self->aq_vecs > i; ++i, aq_vec = self->aq_vec[i]) {
                data += count;
                aq_vec_get_sw_stats(aq_vec, data, &count);
        }
@@ -959,8 +959,10 @@ void aq_nic_free_hot_resources(struct aq_nic_s *self)
                goto err_exit;
 
        for (i = AQ_DIMOF(self->aq_vec); i--;) {
-               if (self->aq_vec[i])
+               if (self->aq_vec[i]) {
                        aq_vec_free(self->aq_vec[i]);
+                       self->aq_vec[i] = NULL;
+               }
        }
 
 err_exit:;
index 4ee15ff06a448b72dbd6763427d9d02dfadad268..faeb4935ef3e3af5c998ef701e1e7cd2f5d739c8 100644 (file)
@@ -200,29 +200,18 @@ err_exit:
 static int hw_atl_a0_hw_offload_set(struct aq_hw_s *self,
                                    struct aq_nic_cfg_s *aq_nic_cfg)
 {
-       int err = 0;
-
        /* TX checksums offloads*/
        tpo_ipv4header_crc_offload_en_set(self, 1);
        tpo_tcp_udp_crc_offload_en_set(self, 1);
-       if (err < 0)
-               goto err_exit;
 
        /* RX checksums offloads*/
        rpo_ipv4header_crc_offload_en_set(self, 1);
        rpo_tcp_udp_crc_offload_en_set(self, 1);
-       if (err < 0)
-               goto err_exit;
 
        /* LSO offloads*/
        tdm_large_send_offload_en_set(self, 0xFFFFFFFFU);
-       if (err < 0)
-               goto err_exit;
-
-       err = aq_hw_err_from_flags(self);
 
-err_exit:
-       return err;
+       return aq_hw_err_from_flags(self);
 }
 
 static int hw_atl_a0_hw_init_tx_path(struct aq_hw_s *self)
index 42150708191dbf67d91b33218a2a275e9b5fd45d..1bceb7358e5ca3a4455badf55bc091d3705dc89d 100644 (file)
@@ -200,25 +200,18 @@ err_exit:
 static int hw_atl_b0_hw_offload_set(struct aq_hw_s *self,
                                    struct aq_nic_cfg_s *aq_nic_cfg)
 {
-       int err = 0;
        unsigned int i;
 
        /* TX checksums offloads*/
        tpo_ipv4header_crc_offload_en_set(self, 1);
        tpo_tcp_udp_crc_offload_en_set(self, 1);
-       if (err < 0)
-               goto err_exit;
 
        /* RX checksums offloads*/
        rpo_ipv4header_crc_offload_en_set(self, 1);
        rpo_tcp_udp_crc_offload_en_set(self, 1);
-       if (err < 0)
-               goto err_exit;
 
        /* LSO offloads*/
        tdm_large_send_offload_en_set(self, 0xFFFFFFFFU);
-       if (err < 0)
-               goto err_exit;
 
 /* LRO offloads */
        {
@@ -245,10 +238,7 @@ static int hw_atl_b0_hw_offload_set(struct aq_hw_s *self,
 
                rpo_lro_en_set(self, aq_nic_cfg->is_lro ? 0xFFFFFFFFU : 0U);
        }
-       err = aq_hw_err_from_flags(self);
-
-err_exit:
-       return err;
+       return aq_hw_err_from_flags(self);
 }
 
 static int hw_atl_b0_hw_init_tx_path(struct aq_hw_s *self)
index a8c2db881b75354f6297094ddedbd26773e65601..567ee54504bcd6eba897009259f691b74b77609e 100644 (file)
@@ -838,7 +838,7 @@ static int alx_enable_msix(struct alx_priv *alx)
 
        err = pci_alloc_irq_vectors(alx->hw.pdev, num_vec, num_vec,
                        PCI_IRQ_MSIX);
-       if (err) {
+       if (err < 0) {
                netdev_warn(alx->dev, "Enabling MSI-X interrupts failed!\n");
                return err;
        }
@@ -904,7 +904,7 @@ static int alx_init_intr(struct alx_priv *alx)
 
        ret = pci_alloc_irq_vectors(alx->hw.pdev, 1, 1,
                        PCI_IRQ_MSI | PCI_IRQ_LEGACY);
-       if (ret)
+       if (ret < 0)
                return ret;
 
        alx->num_vec = 1;
index a8b80c56ac25e3b59ab28a052f99c4e46ef5c27e..73efdb05a490735a14af8e9cac72b41461d42048 100644 (file)
@@ -307,7 +307,7 @@ void atl1c_start_phy_polling(struct atl1c_hw *hw, u16 clk_sel)
 
 /*
  * atl1c_read_phy_core
- * core function to read register in PHY via MDIO control regsiter.
+ * core function to read register in PHY via MDIO control register.
  * ext: extension register (see IEEE 802.3)
  * dev: device address (see IEEE 802.3 DEVAD, PRTAD is fixed to 0)
  * reg: reg to read
index cea6bdcde33f0be220815378142ea9e8dfc7ba37..8baf9d3eb4b1c1a1dd84abe031b7c19c8dbb7370 100644 (file)
@@ -1591,7 +1591,7 @@ static int __bnx2x_vlan_mac_execute_step(struct bnx2x *bp,
        if (rc != 0) {
                __bnx2x_vlan_mac_h_pend(bp, o, *ramrod_flags);
 
-               /* Calling function should not diffrentiate between this case
+               /* Calling function should not differentiate between this case
                 * and the case in which there is already a pending ramrod
                 */
                rc = 1;
index b3ba66032980274c49313c580ec2dd6590ae77a6..03f55daecb20b70bec8924eb64f2146a90591590 100644 (file)
@@ -3000,7 +3000,8 @@ static int bnxt_alloc_ntp_fltrs(struct bnxt *bp)
                INIT_HLIST_HEAD(&bp->ntp_fltr_hash_tbl[i]);
 
        bp->ntp_fltr_count = 0;
-       bp->ntp_fltr_bmap = kzalloc(BITS_TO_LONGS(BNXT_NTP_FLTR_MAX_FLTR),
+       bp->ntp_fltr_bmap = kcalloc(BITS_TO_LONGS(BNXT_NTP_FLTR_MAX_FLTR),
+                                   sizeof(long),
                                    GFP_KERNEL);
 
        if (!bp->ntp_fltr_bmap)
@@ -7629,8 +7630,6 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        dev->min_mtu = ETH_ZLEN;
        dev->max_mtu = BNXT_MAX_MTU;
 
-       bnxt_dcb_init(bp);
-
 #ifdef CONFIG_BNXT_SRIOV
        init_waitqueue_head(&bp->sriov_cfg_wait);
 #endif
@@ -7668,6 +7667,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        bnxt_hwrm_func_qcfg(bp);
        bnxt_hwrm_port_led_qcaps(bp);
        bnxt_ethtool_init(bp);
+       bnxt_dcb_init(bp);
 
        bnxt_set_rx_skb_mode(bp, false);
        bnxt_set_tpa_flags(bp);
index 46de2f8ff024aad59341ecf5963ccbd9082dae9e..5c6dd0ce209f627e4c5bd74efa1ef581d1eb46ad 100644 (file)
@@ -553,8 +553,10 @@ static u8 bnxt_dcbnl_setdcbx(struct net_device *dev, u8 mode)
        if ((mode & DCB_CAP_DCBX_VER_CEE) || !(mode & DCB_CAP_DCBX_VER_IEEE))
                return 1;
 
-       if ((mode & DCB_CAP_DCBX_HOST) && BNXT_VF(bp))
-               return 1;
+       if (mode & DCB_CAP_DCBX_HOST) {
+               if (BNXT_VF(bp) || (bp->flags & BNXT_FLAG_FW_LLDP_AGENT))
+                       return 1;
+       }
 
        if (mode == bp->dcbx_cap)
                return 0;
index 55c8e25b43d9ad5a2bb90b1cbef1d73c91c97b31..16a0f192daecc34dea63b76ecb0046bd8c9f0bf6 100644 (file)
@@ -2641,3 +2641,4 @@ static struct platform_driver sbmac_driver = {
 };
 
 module_platform_driver(sbmac_driver);
+MODULE_LICENSE("GPL");
index 0f6811860ad51de9b871e806f3f254a1abfcf2eb..a36e3867664003dcc54a63b5f5749406b083bd74 100644 (file)
@@ -2845,7 +2845,7 @@ bfa_ioc_get_adapter_optrom_ver(struct bfa_ioc *ioc, char *optrom_ver)
 static void
 bfa_ioc_get_adapter_manufacturer(struct bfa_ioc *ioc, char *manufacturer)
 {
-       memcpy(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN);
+       strncpy(manufacturer, BFA_MFG_NAME, BFA_ADAPTER_MFG_NAME_LEN);
 }
 
 static void
index 286593922139e1f59e6c66c33df8a4d54ee33314..31032de5843b158e3a1aca0e742d60d31d1b5669 100644 (file)
@@ -547,8 +547,8 @@ bnad_get_strings(struct net_device *netdev, u32 stringset, u8 *string)
                for (i = 0; i < BNAD_ETHTOOL_STATS_NUM; i++) {
                        BUG_ON(!(strlen(bnad_net_stats_strings[i]) <
                                   ETH_GSTRING_LEN));
-                       memcpy(string, bnad_net_stats_strings[i],
-                              ETH_GSTRING_LEN);
+                       strncpy(string, bnad_net_stats_strings[i],
+                               ETH_GSTRING_LEN);
                        string += ETH_GSTRING_LEN;
                }
                bmap = bna_tx_rid_mask(&bnad->bna);
index 920d918ed193256c0f218216304779abb092ef3d..f04e81f337951c01569b74b7ba8ae7b14af26478 100644 (file)
@@ -41,9 +41,6 @@
 
 #define VALIDATE_TID 1
 
-void *cxgb_alloc_mem(unsigned long size);
-void cxgb_free_mem(void *addr);
-
 /*
  * Map an ATID or STID to their entries in the corresponding TID tables.
  */
index 76684dcb874cf90bf3d4ecd56a0ab2a200d4a974..fa81445e334cb0baa911ad308493fec69d094bff 100644 (file)
@@ -1151,27 +1151,6 @@ static void cxgb_redirect(struct dst_entry *old, struct dst_entry *new,
        l2t_release(tdev, e);
 }
 
-/*
- * Allocate a chunk of memory using kmalloc or, if that fails, vmalloc.
- * The allocated memory is cleared.
- */
-void *cxgb_alloc_mem(unsigned long size)
-{
-       void *p = kzalloc(size, GFP_KERNEL | __GFP_NOWARN);
-
-       if (!p)
-               p = vzalloc(size);
-       return p;
-}
-
-/*
- * Free memory allocated through t3_alloc_mem().
- */
-void cxgb_free_mem(void *addr)
-{
-       kvfree(addr);
-}
-
 /*
  * Allocate and initialize the TID tables.  Returns 0 on success.
  */
@@ -1182,7 +1161,7 @@ static int init_tid_tabs(struct tid_info *t, unsigned int ntids,
        unsigned long size = ntids * sizeof(*t->tid_tab) +
            natids * sizeof(*t->atid_tab) + nstids * sizeof(*t->stid_tab);
 
-       t->tid_tab = cxgb_alloc_mem(size);
+       t->tid_tab = kvzalloc(size, GFP_KERNEL);
        if (!t->tid_tab)
                return -ENOMEM;
 
@@ -1218,7 +1197,7 @@ static int init_tid_tabs(struct tid_info *t, unsigned int ntids,
 
 static void free_tid_maps(struct tid_info *t)
 {
-       cxgb_free_mem(t->tid_tab);
+       kvfree(t->tid_tab);
 }
 
 static inline void add_adapter(struct adapter *adap)
@@ -1293,7 +1272,7 @@ int cxgb3_offload_activate(struct adapter *adapter)
        return 0;
 
 out_free_l2t:
-       t3_free_l2t(l2td);
+       kvfree(l2td);
 out_free:
        kfree(t);
        return err;
@@ -1302,7 +1281,7 @@ out_free:
 static void clean_l2_data(struct rcu_head *head)
 {
        struct l2t_data *d = container_of(head, struct l2t_data, rcu_head);
-       t3_free_l2t(d);
+       kvfree(d);
 }
 
 
index 52063587e1e9a55b5afc2d261d4e713ad9d0b381..26264125865f18e29871dcde22005f89e94521db 100644 (file)
@@ -444,7 +444,7 @@ struct l2t_data *t3_init_l2t(unsigned int l2t_capacity)
        struct l2t_data *d;
        int i, size = sizeof(*d) + l2t_capacity * sizeof(struct l2t_entry);
 
-       d = cxgb_alloc_mem(size);
+       d = kvzalloc(size, GFP_KERNEL);
        if (!d)
                return NULL;
 
@@ -462,9 +462,3 @@ struct l2t_data *t3_init_l2t(unsigned int l2t_capacity)
        }
        return d;
 }
-
-void t3_free_l2t(struct l2t_data *d)
-{
-       cxgb_free_mem(d);
-}
-
index 8cffcdfd5678205e9bf9183e655f462a45233007..c2fd323c4078284ac84aa58825cc84958f108fe8 100644 (file)
@@ -115,7 +115,6 @@ int t3_l2t_send_slow(struct t3cdev *dev, struct sk_buff *skb,
                     struct l2t_entry *e);
 void t3_l2t_send_event(struct t3cdev *dev, struct l2t_entry *e);
 struct l2t_data *t3_init_l2t(unsigned int l2t_capacity);
-void t3_free_l2t(struct l2t_data *d);
 
 int cxgb3_ofld_send(struct t3cdev *dev, struct sk_buff *skb);
 
index 7ad43af6bde109a9792ac4dab4bd538f216bd74e..3103ef9b561dd8189af407dd5bd729782d84f287 100644 (file)
@@ -290,8 +290,8 @@ struct clip_tbl *t4_init_clip_tbl(unsigned int clipt_start,
        if (clipt_size < CLIPT_MIN_HASH_BUCKETS)
                return NULL;
 
-       ctbl = t4_alloc_mem(sizeof(*ctbl) +
-                           clipt_size*sizeof(struct list_head));
+       ctbl = kvzalloc(sizeof(*ctbl) +
+                           clipt_size*sizeof(struct list_head), GFP_KERNEL);
        if (!ctbl)
                return NULL;
 
@@ -305,9 +305,9 @@ struct clip_tbl *t4_init_clip_tbl(unsigned int clipt_start,
        for (i = 0; i < ctbl->clipt_size; ++i)
                INIT_LIST_HEAD(&ctbl->hash_list[i]);
 
-       cl_list = t4_alloc_mem(clipt_size*sizeof(struct clip_entry));
+       cl_list = kvzalloc(clipt_size*sizeof(struct clip_entry), GFP_KERNEL);
        if (!cl_list) {
-               t4_free_mem(ctbl);
+               kvfree(ctbl);
                return NULL;
        }
        ctbl->cl_list = (void *)cl_list;
@@ -326,8 +326,8 @@ void t4_cleanup_clip_tbl(struct adapter *adap)
 
        if (ctbl) {
                if (ctbl->cl_list)
-                       t4_free_mem(ctbl->cl_list);
-               t4_free_mem(ctbl);
+                       kvfree(ctbl->cl_list);
+               kvfree(ctbl);
        }
 }
 EXPORT_SYMBOL(t4_cleanup_clip_tbl);
index 163543b1ea0bf1bec215f0613a6bce2a729fa337..e88c1808e46f06e77671224d3a6a5edeb18ebc0d 100644 (file)
@@ -108,6 +108,12 @@ enum {
        PAUSE_AUTONEG = 1 << 2
 };
 
+enum {
+       FEC_AUTO      = 1 << 0,  /* IEEE 802.3 "automatic" */
+       FEC_RS        = 1 << 1,  /* Reed-Solomon */
+       FEC_BASER_RS  = 1 << 2   /* BaseR/Reed-Solomon */
+};
+
 struct port_stats {
        u64 tx_octets;            /* total # of octets in good frames */
        u64 tx_frames;            /* all good frames */
@@ -432,6 +438,9 @@ struct link_config {
        unsigned int   speed;            /* actual link speed */
        unsigned char  requested_fc;     /* flow control user has requested */
        unsigned char  fc;               /* actual link flow control */
+       unsigned char  auto_fec;         /* Forward Error Correction: */
+       unsigned char  requested_fec;    /* "automatic" (IEEE 802.3), */
+       unsigned char  fec;              /* requested, and actual in use */
        unsigned char  autoneg;          /* autonegotiating? */
        unsigned char  link_ok;          /* link up? */
        unsigned char  link_down_rc;     /* link down reason */
@@ -1184,8 +1193,6 @@ extern const char cxgb4_driver_version[];
 void t4_os_portmod_changed(const struct adapter *adap, int port_id);
 void t4_os_link_changed(struct adapter *adap, int port_id, int link_stat);
 
-void *t4_alloc_mem(size_t size);
-
 void t4_free_sge_resources(struct adapter *adap);
 void t4_free_ofld_rxqs(struct adapter *adap, int n, struct sge_ofld_rxq *q);
 irq_handler_t t4_intr_handler(struct adapter *adap);
@@ -1557,7 +1564,6 @@ int t4_sched_params(struct adapter *adapter, int type, int level, int mode,
                    int rateunit, int ratemode, int channel, int class,
                    int minrate, int maxrate, int weight, int pktsize);
 void t4_sge_decode_idma_state(struct adapter *adapter, int state);
-void t4_free_mem(void *addr);
 void t4_idma_monitor_init(struct adapter *adapter,
                          struct sge_idma_monitor_state *idma);
 void t4_idma_monitor(struct adapter *adapter,
index f6e739da7bb77a55f09e3121a279286034a0e7e1..1fa34b009891ba93269c27da4c48a55f4b150b68 100644 (file)
@@ -2634,7 +2634,7 @@ static ssize_t mem_read(struct file *file, char __user *buf, size_t count,
        if (count > avail - pos)
                count = avail - pos;
 
-       data = t4_alloc_mem(count);
+       data = kvzalloc(count, GFP_KERNEL);
        if (!data)
                return -ENOMEM;
 
@@ -2642,12 +2642,12 @@ static ssize_t mem_read(struct file *file, char __user *buf, size_t count,
        ret = t4_memory_rw(adap, 0, mem, pos, count, data, T4_MEMORY_READ);
        spin_unlock(&adap->win0_lock);
        if (ret) {
-               t4_free_mem(data);
+               kvfree(data);
                return ret;
        }
        ret = copy_to_user(buf, data, count);
 
-       t4_free_mem(data);
+       kvfree(data);
        if (ret)
                return -EFAULT;
 
@@ -2753,7 +2753,7 @@ static ssize_t blocked_fl_read(struct file *filp, char __user *ubuf,
                       adap->sge.egr_sz, adap->sge.blocked_fl);
        len += sprintf(buf + len, "\n");
        size = simple_read_from_buffer(ubuf, count, ppos, buf, len);
-       t4_free_mem(buf);
+       kvfree(buf);
        return size;
 }
 
@@ -2773,7 +2773,7 @@ static ssize_t blocked_fl_write(struct file *filp, const char __user *ubuf,
                return err;
 
        bitmap_copy(adap->sge.blocked_fl, t, adap->sge.egr_sz);
-       t4_free_mem(t);
+       kvfree(t);
        return count;
 }
 
index 02f80febeb91e87864fb9249b45ef794a64a028d..0ba7866c82598a5b4c2f719cfa4944c46081c04c 100644 (file)
@@ -969,7 +969,7 @@ static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *e,
 {
        int i, err = 0;
        struct adapter *adapter = netdev2adap(dev);
-       u8 *buf = t4_alloc_mem(EEPROMSIZE);
+       u8 *buf = kvzalloc(EEPROMSIZE, GFP_KERNEL);
 
        if (!buf)
                return -ENOMEM;
@@ -980,7 +980,7 @@ static int get_eeprom(struct net_device *dev, struct ethtool_eeprom *e,
 
        if (!err)
                memcpy(data, buf + e->offset, e->len);
-       t4_free_mem(buf);
+       kvfree(buf);
        return err;
 }
 
@@ -1009,7 +1009,7 @@ static int set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
        if (aligned_offset != eeprom->offset || aligned_len != eeprom->len) {
                /* RMW possibly needed for first or last words.
                 */
-               buf = t4_alloc_mem(aligned_len);
+               buf = kvzalloc(aligned_len, GFP_KERNEL);
                if (!buf)
                        return -ENOMEM;
                err = eeprom_rd_phys(adapter, aligned_offset, (u32 *)buf);
@@ -1037,7 +1037,7 @@ static int set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom,
                err = t4_seeprom_wp(adapter, true);
 out:
        if (buf != data)
-               t4_free_mem(buf);
+               kvfree(buf);
        return err;
 }
 
index c12c4a3b82b567df405a24dc72331c008973d5ce..38a5c6764bb50f45124c212db37e11d2cc777076 100644 (file)
@@ -880,27 +880,6 @@ freeout:
        return err;
 }
 
-/*
- * Allocate a chunk of memory using kmalloc or, if that fails, vmalloc.
- * The allocated memory is cleared.
- */
-void *t4_alloc_mem(size_t size)
-{
-       void *p = kzalloc(size, GFP_KERNEL | __GFP_NOWARN);
-
-       if (!p)
-               p = vzalloc(size);
-       return p;
-}
-
-/*
- * Free memory allocated through alloc_mem().
- */
-void t4_free_mem(void *addr)
-{
-       kvfree(addr);
-}
-
 static u16 cxgb_select_queue(struct net_device *dev, struct sk_buff *skb,
                             void *accel_priv, select_queue_fallback_t fallback)
 {
@@ -1299,7 +1278,7 @@ static int tid_init(struct tid_info *t)
               max_ftids * sizeof(*t->ftid_tab) +
               ftid_bmap_size * sizeof(long);
 
-       t->tid_tab = t4_alloc_mem(size);
+       t->tid_tab = kvzalloc(size, GFP_KERNEL);
        if (!t->tid_tab)
                return -ENOMEM;
 
@@ -3445,7 +3424,7 @@ static int adap_init0(struct adapter *adap)
                /* allocate memory to read the header of the firmware on the
                 * card
                 */
-               card_fw = t4_alloc_mem(sizeof(*card_fw));
+               card_fw = kvzalloc(sizeof(*card_fw), GFP_KERNEL);
 
                /* Get FW from from /lib/firmware/ */
                ret = request_firmware(&fw, fw_info->fw_mod_name,
@@ -3465,7 +3444,7 @@ static int adap_init0(struct adapter *adap)
 
                /* Cleaning up */
                release_firmware(fw);
-               t4_free_mem(card_fw);
+               kvfree(card_fw);
 
                if (ret < 0)
                        goto bye;
@@ -4470,9 +4449,9 @@ static void free_some_resources(struct adapter *adapter)
 {
        unsigned int i;
 
-       t4_free_mem(adapter->l2t);
+       kvfree(adapter->l2t);
        t4_cleanup_sched(adapter);
-       t4_free_mem(adapter->tids.tid_tab);
+       kvfree(adapter->tids.tid_tab);
        cxgb4_cleanup_tc_u32(adapter);
        kfree(adapter->sge.egr_map);
        kfree(adapter->sge.ingr_map);
index a1b19422b3395fa0645d7d0ede4ae461af644599..ef06ce8247ab65734085bf38458f65efbf009349 100644 (file)
@@ -432,9 +432,9 @@ void cxgb4_cleanup_tc_u32(struct adapter *adap)
        for (i = 0; i < t->size; i++) {
                struct cxgb4_link *link = &t->table[i];
 
-               t4_free_mem(link->tid_map);
+               kvfree(link->tid_map);
        }
-       t4_free_mem(adap->tc_u32);
+       kvfree(adap->tc_u32);
 }
 
 struct cxgb4_tc_u32_table *cxgb4_init_tc_u32(struct adapter *adap)
@@ -446,8 +446,8 @@ struct cxgb4_tc_u32_table *cxgb4_init_tc_u32(struct adapter *adap)
        if (!max_tids)
                return NULL;
 
-       t = t4_alloc_mem(sizeof(*t) +
-                        (max_tids * sizeof(struct cxgb4_link)));
+       t = kvzalloc(sizeof(*t) +
+                        (max_tids * sizeof(struct cxgb4_link)), GFP_KERNEL);
        if (!t)
                return NULL;
 
@@ -458,7 +458,7 @@ struct cxgb4_tc_u32_table *cxgb4_init_tc_u32(struct adapter *adap)
                unsigned int bmap_size;
 
                bmap_size = BITS_TO_LONGS(max_tids);
-               link->tid_map = t4_alloc_mem(sizeof(unsigned long) * bmap_size);
+               link->tid_map = kvzalloc(sizeof(unsigned long) * bmap_size, GFP_KERNEL);
                if (!link->tid_map)
                        goto out_no_mem;
                bitmap_zero(link->tid_map, max_tids);
@@ -471,11 +471,11 @@ out_no_mem:
                struct cxgb4_link *link = &t->table[i];
 
                if (link->tid_map)
-                       t4_free_mem(link->tid_map);
+                       kvfree(link->tid_map);
        }
 
        if (t)
-               t4_free_mem(t);
+               kvfree(t);
 
        return NULL;
 }
index 7c8c5b9a3c22ebb5edb67ab3be378f46bbb83baf..6f3692db29af12687e762f095a3177d81b049308 100644 (file)
@@ -646,7 +646,7 @@ struct l2t_data *t4_init_l2t(unsigned int l2t_start, unsigned int l2t_end)
        if (l2t_size < L2T_MIN_HASH_BUCKETS)
                return NULL;
 
-       d = t4_alloc_mem(sizeof(*d) + l2t_size * sizeof(struct l2t_entry));
+       d = kvzalloc(sizeof(*d) + l2t_size * sizeof(struct l2t_entry), GFP_KERNEL);
        if (!d)
                return NULL;
 
index c9026352a842191d51913f62f4424bb74f1bf7a0..02acff741f114602c3676dad846d714d0f23a99d 100644 (file)
@@ -177,7 +177,7 @@ static int t4_sched_queue_unbind(struct port_info *pi, struct ch_sched_queue *p)
                }
 
                list_del(&qe->list);
-               t4_free_mem(qe);
+               kvfree(qe);
                if (atomic_dec_and_test(&e->refcnt)) {
                        e->state = SCHED_STATE_UNUSED;
                        memset(&e->info, 0, sizeof(e->info));
@@ -201,7 +201,7 @@ static int t4_sched_queue_bind(struct port_info *pi, struct ch_sched_queue *p)
        if (p->queue < 0 || p->queue >= pi->nqsets)
                return -ERANGE;
 
-       qe = t4_alloc_mem(sizeof(struct sched_queue_entry));
+       qe = kvzalloc(sizeof(struct sched_queue_entry), GFP_KERNEL);
        if (!qe)
                return -ENOMEM;
 
@@ -211,7 +211,7 @@ static int t4_sched_queue_bind(struct port_info *pi, struct ch_sched_queue *p)
        /* Unbind queue from any existing class */
        err = t4_sched_queue_unbind(pi, p);
        if (err) {
-               t4_free_mem(qe);
+               kvfree(qe);
                goto out;
        }
 
@@ -224,7 +224,7 @@ static int t4_sched_queue_bind(struct port_info *pi, struct ch_sched_queue *p)
        spin_lock(&e->lock);
        err = t4_sched_bind_unbind_op(pi, (void *)qe, SCHED_QUEUE, true);
        if (err) {
-               t4_free_mem(qe);
+               kvfree(qe);
                spin_unlock(&e->lock);
                goto out;
        }
@@ -512,7 +512,7 @@ struct sched_table *t4_init_sched(unsigned int sched_size)
        struct sched_table *s;
        unsigned int i;
 
-       s = t4_alloc_mem(sizeof(*s) + sched_size * sizeof(struct sched_class));
+       s = kvzalloc(sizeof(*s) + sched_size * sizeof(struct sched_class), GFP_KERNEL);
        if (!s)
                return NULL;
 
@@ -548,6 +548,6 @@ void t4_cleanup_sched(struct adapter *adap)
                                t4_sched_class_free(pi, e);
                        write_unlock(&s->rw_lock);
                }
-               t4_free_mem(s);
+               kvfree(s);
        }
 }
index 0de8eb72325c53ae50cd3ec535915486a9fb5064..aded42b96f6d966ba7e814c0a89c738968a655b6 100644 (file)
@@ -3707,7 +3707,8 @@ int t4_link_l1cfg(struct adapter *adap, unsigned int mbox, unsigned int port,
                  struct link_config *lc)
 {
        struct fw_port_cmd c;
-       unsigned int fc = 0, mdi = FW_PORT_CAP_MDI_V(FW_PORT_CAP_MDI_AUTO);
+       unsigned int mdi = FW_PORT_CAP_MDI_V(FW_PORT_CAP_MDI_AUTO);
+       unsigned int fc = 0, fec = 0, fw_fec = 0;
 
        lc->link_ok = 0;
        if (lc->requested_fc & PAUSE_RX)
@@ -3715,6 +3716,13 @@ int t4_link_l1cfg(struct adapter *adap, unsigned int mbox, unsigned int port,
        if (lc->requested_fc & PAUSE_TX)
                fc |= FW_PORT_CAP_FC_TX;
 
+       fec = lc->requested_fec & FEC_AUTO ? lc->auto_fec : lc->requested_fec;
+
+       if (fec & FEC_RS)
+               fw_fec |= FW_PORT_CAP_FEC_RS;
+       if (fec & FEC_BASER_RS)
+               fw_fec |= FW_PORT_CAP_FEC_BASER_RS;
+
        memset(&c, 0, sizeof(c));
        c.op_to_portid = cpu_to_be32(FW_CMD_OP_V(FW_PORT_CMD) |
                                     FW_CMD_REQUEST_F | FW_CMD_EXEC_F |
@@ -3725,13 +3733,15 @@ int t4_link_l1cfg(struct adapter *adap, unsigned int mbox, unsigned int port,
 
        if (!(lc->supported & FW_PORT_CAP_ANEG)) {
                c.u.l1cfg.rcap = cpu_to_be32((lc->supported & ADVERT_MASK) |
-                                            fc);
+                                            fc | fw_fec);
                lc->fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
        } else if (lc->autoneg == AUTONEG_DISABLE) {
-               c.u.l1cfg.rcap = cpu_to_be32(lc->requested_speed | fc | mdi);
+               c.u.l1cfg.rcap = cpu_to_be32(lc->requested_speed | fc |
+                                            fw_fec | mdi);
                lc->fc = lc->requested_fc & (PAUSE_RX | PAUSE_TX);
        } else
-               c.u.l1cfg.rcap = cpu_to_be32(lc->advertising | fc | mdi);
+               c.u.l1cfg.rcap = cpu_to_be32(lc->advertising | fc |
+                                            fw_fec | mdi);
 
        return t4_wr_mbox(adap, mbox, &c, sizeof(c), NULL);
 }
@@ -7407,13 +7417,26 @@ static void get_pci_mode(struct adapter *adapter, struct pci_params *p)
  *     Initializes the SW state maintained for each link, including the link's
  *     capabilities and default speed/flow-control/autonegotiation settings.
  */
-static void init_link_config(struct link_config *lc, unsigned int caps)
+static void init_link_config(struct link_config *lc, unsigned int pcaps,
+                            unsigned int acaps)
 {
-       lc->supported = caps;
+       lc->supported = pcaps;
        lc->lp_advertising = 0;
        lc->requested_speed = 0;
        lc->speed = 0;
        lc->requested_fc = lc->fc = PAUSE_RX | PAUSE_TX;
+       lc->auto_fec = 0;
+
+       /* For Forward Error Control, we default to whatever the Firmware
+        * tells us the Link is currently advertising.
+        */
+       if (acaps & FW_PORT_CAP_FEC_RS)
+               lc->auto_fec |= FEC_RS;
+       if (acaps & FW_PORT_CAP_FEC_BASER_RS)
+               lc->auto_fec |= FEC_BASER_RS;
+       lc->requested_fec = FEC_AUTO;
+       lc->fec = lc->auto_fec;
+
        if (lc->supported & FW_PORT_CAP_ANEG) {
                lc->advertising = lc->supported & ADVERT_MASK;
                lc->autoneg = AUTONEG_ENABLE;
@@ -7991,7 +8014,8 @@ int t4_init_portinfo(struct port_info *pi, int mbox,
        pi->port_type = FW_PORT_CMD_PTYPE_G(ret);
        pi->mod_type = FW_PORT_MOD_TYPE_NA;
 
-       init_link_config(&pi->link_cfg, be16_to_cpu(c.u.info.pcap));
+       init_link_config(&pi->link_cfg, be16_to_cpu(c.u.info.pcap),
+                        be16_to_cpu(c.u.info.acap));
        return 0;
 }
 
index 8f8c079d0d2b89be66fc49005bc1d50bf32265c7..251a35e9795c56e943fce354f26b45bcddae8d1c 100644 (file)
@@ -2263,9 +2263,9 @@ enum fw_port_cap {
        FW_PORT_CAP_ANEG                = 0x0100,
        FW_PORT_CAP_MDIX                = 0x0200,
        FW_PORT_CAP_MDIAUTO             = 0x0400,
-       FW_PORT_CAP_FEC                 = 0x0800,
-       FW_PORT_CAP_TECHKR              = 0x1000,
-       FW_PORT_CAP_TECHKX4             = 0x2000,
+       FW_PORT_CAP_FEC_RS              = 0x0800,
+       FW_PORT_CAP_FEC_BASER_RS        = 0x1000,
+       FW_PORT_CAP_FEC_RESERVED        = 0x2000,
        FW_PORT_CAP_802_3_PAUSE         = 0x4000,
        FW_PORT_CAP_802_3_ASM_DIR       = 0x8000,
 };
index fa376444e57c5668fc4c1ff027e56fdcc11bb55a..3549d387627888a2629b5f07dd1b001d2db1fc70 100644 (file)
@@ -37,7 +37,7 @@
 
 #define T4FW_VERSION_MAJOR 0x01
 #define T4FW_VERSION_MINOR 0x10
-#define T4FW_VERSION_MICRO 0x21
+#define T4FW_VERSION_MICRO 0x2B
 #define T4FW_VERSION_BUILD 0x00
 
 #define T4FW_MIN_VERSION_MAJOR 0x01
@@ -46,7 +46,7 @@
 
 #define T5FW_VERSION_MAJOR 0x01
 #define T5FW_VERSION_MINOR 0x10
-#define T5FW_VERSION_MICRO 0x21
+#define T5FW_VERSION_MICRO 0x2B
 #define T5FW_VERSION_BUILD 0x00
 
 #define T5FW_MIN_VERSION_MAJOR 0x00
@@ -55,7 +55,7 @@
 
 #define T6FW_VERSION_MAJOR 0x01
 #define T6FW_VERSION_MINOR 0x10
-#define T6FW_VERSION_MICRO 0x21
+#define T6FW_VERSION_MICRO 0x2B
 #define T6FW_VERSION_BUILD 0x00
 
 #define T6FW_MIN_VERSION_MAJOR 0x00
index 47384f7323acb974eba4beb2f7de29ebd34ff953..da5b58b853e2947258551ebb962f30b2005746d0 100644 (file)
@@ -1704,12 +1704,12 @@ static int use_dma;                     /* These generate unused var warnings if ALLOW_DMA = 0 */
 static int dma;
 static int dmasize = 16;               /* or 64 */
 
-module_param(io, int, 0);
-module_param(irq, int, 0);
+module_param_hw(io, int, ioport, 0);
+module_param_hw(irq, int, irq, 0);
 module_param(debug, int, 0);
 module_param_string(media, media, sizeof(media), 0);
 module_param(duplex, int, 0);
-module_param(dma , int, 0);
+module_param_hw(dma , int, dma, 0);
 module_param(dmasize , int, 0);
 module_param(use_dma , int, 0);
 MODULE_PARM_DESC(io, "cs89x0 I/O base address");
index b600fbbbf679885231e7d4cd5a9628a5deb70382..f910f0f386d6321f3c80d0360376d7ea466a2710 100644 (file)
@@ -56,7 +56,7 @@
   local_irq_{dis,en}able()
 */
 
-static char *version =
+static const char version[] =
 "cs89x0.c:v1.02 11/26/96 Russell Nelson <nelson@crynwr.com>\n";
 
 /* ======================= configure the driver here ======================= */
index df4a871df633d269436a30bb108f157143b692a2..fd6bcf024729318db6a85300bfbcc73e2cbd0bc6 100644 (file)
@@ -1015,7 +1015,7 @@ static int     compact_infoblock(struct net_device *dev, u_char count, u_char *p
 
 static int io=0x0;/* EDIT THIS LINE FOR YOUR CONFIGURATION IF NEEDED        */
 
-module_param(io, int, 0);
+module_param_hw(io, int, ioport, 0);
 module_param(de4x5_debug, int, 0);
 module_param(dec_only, int, 0);
 module_param(args, charp, 0);
index 6ac336b546e6c226b1951c239a52b362052c04aa..1536356e2ea89ffaaf52974f1ed46b97ea861ae6 100644 (file)
@@ -1174,11 +1174,17 @@ static int ftmac100_remove(struct platform_device *pdev)
        return 0;
 }
 
+static const struct of_device_id ftmac100_of_ids[] = {
+       { .compatible = "andestech,atmac100" },
+       { }
+};
+
 static struct platform_driver ftmac100_driver = {
        .probe          = ftmac100_probe,
        .remove         = ftmac100_remove,
        .driver         = {
                .name   = DRV_NAME,
+               .of_match_table = ftmac100_of_ids
        },
 };
 
@@ -1202,3 +1208,4 @@ module_exit(ftmac100_exit);
 MODULE_AUTHOR("Po-Yu Chuang <ratbert@faraday-tech.com>");
 MODULE_DESCRIPTION("FTMAC100 driver");
 MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(of, ftmac100_of_ids);
index 3f7ae9f64cd8771a834b104cec0b395c473a7bf2..f77ba9fa257b41a728ddd74176a465f4fadee2b8 100644 (file)
@@ -2594,11 +2594,10 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
                } else if (ugeth->ug_info->uf_info.bd_mem_part ==
                           MEM_PART_MURAM) {
                        out_be32(&ugeth->p_send_q_mem_reg->sqqd[i].bd_ring_base,
-                                (u32) immrbar_virt_to_phys(ugeth->
-                                                           p_tx_bd_ring[i]));
+                                (u32)qe_muram_dma(ugeth->p_tx_bd_ring[i]));
                        out_be32(&ugeth->p_send_q_mem_reg->sqqd[i].
                                 last_bd_completed_address,
-                                (u32) immrbar_virt_to_phys(endOfRing));
+                                (u32)qe_muram_dma(endOfRing));
                }
        }
 
@@ -2844,8 +2843,7 @@ static int ucc_geth_startup(struct ucc_geth_private *ugeth)
                } else if (ugeth->ug_info->uf_info.bd_mem_part ==
                           MEM_PART_MURAM) {
                        out_be32(&ugeth->p_rx_bd_qs_tbl[i].externalbdbaseptr,
-                                (u32) immrbar_virt_to_phys(ugeth->
-                                                           p_rx_bd_ring[i]));
+                                (u32)qe_muram_dma(ugeth->p_rx_bd_ring[i]));
                }
                /* rest of fields handled by QE */
        }
index 24dfba53a0f216c5ce55850b4a5703a1a02772e5..bbc0a98e7ca3260c7f8b1b8cb7f7f203860bfdce 100644 (file)
@@ -405,7 +405,7 @@ struct mac_driver {
 };
 
 struct mac_stats_string {
-       char desc[ETH_GSTRING_LEN];
+       const char desc[ETH_GSTRING_LEN];
        unsigned long offset;
 };
 
index 1a31bee6e72898b64ead40dc505aac07b0cb477d..5673b071e39d00b90cd7ceb2383a817e4c0d4317 100644 (file)
@@ -2966,7 +2966,7 @@ MODULE_DESCRIPTION("HP CASCADE Architecture Driver for 100VG-AnyLan Network Adap
 #define HP100_DEVICES 5
 /* Parameters set by insmod */
 static int hp100_port[HP100_DEVICES] = { 0, [1 ... (HP100_DEVICES-1)] = -1 };
-module_param_array(hp100_port, int, NULL, 0);
+module_param_hw_array(hp100_port, int, ioport, NULL, 0);
 
 /* List of devices */
 static struct net_device *hp100_devlist[HP100_DEVICES];
index 68812d783f33e02cb34ec0a8bcc25f9eba72d354..413025bdcb50feb68c8af9bcb398bbae37811f80 100644 (file)
@@ -127,7 +127,7 @@ out:
  *  @offset: register offset to be read
  *  @data: pointer to the read data
  *
- *  Reads the MDI control regsiter in the PHY at offset and stores the
+ *  Reads the MDI control register in the PHY at offset and stores the
  *  information read to data.
  **/
 s32 igb_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
index 22a29df1d29eab871818353111e6abc9197e73bf..d39cba214320bd2565d6ad072610b48178897733 100644 (file)
@@ -7332,18 +7332,6 @@ static void ixgbe_watchdog_flush_tx(struct ixgbe_adapter *adapter)
 }
 
 #ifdef CONFIG_PCI_IOV
-static inline void ixgbe_issue_vf_flr(struct ixgbe_adapter *adapter,
-                                     struct pci_dev *vfdev)
-{
-       if (!pci_wait_for_pending_transaction(vfdev))
-               e_dev_warn("Issuing VFLR with pending transactions\n");
-
-       e_dev_err("Issuing VFLR for VF %s\n", pci_name(vfdev));
-       pcie_capability_set_word(vfdev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR);
-
-       msleep(100);
-}
-
 static void ixgbe_check_for_bad_vf(struct ixgbe_adapter *adapter)
 {
        struct ixgbe_hw *hw = &adapter->hw;
@@ -7376,7 +7364,7 @@ static void ixgbe_check_for_bad_vf(struct ixgbe_adapter *adapter)
                pci_read_config_word(vfdev, PCI_STATUS, &status_reg);
                if (status_reg != IXGBE_FAILED_READ_CFG_WORD &&
                    status_reg & PCI_STATUS_REC_MASTER_ABORT)
-                       ixgbe_issue_vf_flr(adapter, vfdev);
+                       pcie_flr(vfdev);
        }
 }
 
@@ -10602,7 +10590,7 @@ static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev,
                 * VFLR.  Just clean up the AER in that case.
                 */
                if (vfdev) {
-                       ixgbe_issue_vf_flr(adapter, vfdev);
+                       pcie_flr(vfdev);
                        /* Free device reference count */
                        pci_dev_put(vfdev);
                }
index 0e0fa70305659521ed50d1cf1bc40fd38aa3ad04..c1af47e45d3f23221f730f64375b9be771cef7c6 100644 (file)
@@ -1789,9 +1789,17 @@ static int mlx4_master_process_vhcr(struct mlx4_dev *dev, int slave,
        }
 
        if (err) {
-               if (!(dev->persist->state & MLX4_DEVICE_STATE_INTERNAL_ERROR))
-                       mlx4_warn(dev, "vhcr command:0x%x slave:%d failed with error:%d, status %d\n",
-                                 vhcr->op, slave, vhcr->errno, err);
+               if (!(dev->persist->state & MLX4_DEVICE_STATE_INTERNAL_ERROR)) {
+                       if (vhcr->op == MLX4_CMD_ALLOC_RES &&
+                           (vhcr->in_modifier & 0xff) == RES_COUNTER &&
+                           err == -EDQUOT)
+                               mlx4_dbg(dev,
+                                        "Unable to allocate counter for slave %d (%d)\n",
+                                        slave, err);
+                       else
+                               mlx4_warn(dev, "vhcr command:0x%x slave:%d failed with error:%d, status %d\n",
+                                         vhcr->op, slave, vhcr->errno, err);
+               }
                vhcr_cmd->status = mlx4_errno_to_status(err);
                goto out_status;
        }
index ffbcb27c05e55f43630a812249bab21609886dd9..ae5fdc2df65412afce4e72b8384c9c4b3302c56e 100644 (file)
@@ -1562,6 +1562,11 @@ static int mlx4_en_flow_replace(struct net_device *dev,
                qpn = priv->drop_qp.qpn;
        else if (cmd->fs.ring_cookie & EN_ETHTOOL_QP_ATTACH) {
                qpn = cmd->fs.ring_cookie & (EN_ETHTOOL_QP_ATTACH - 1);
+               if (qpn < priv->rss_map.base_qpn ||
+                   qpn >= priv->rss_map.base_qpn + priv->rx_ring_num) {
+                       en_warn(priv, "rxnfc: QP (0x%x) doesn't exist\n", qpn);
+                       return -EINVAL;
+               }
        } else {
                if (cmd->fs.ring_cookie >= priv->rx_ring_num) {
                        en_warn(priv, "rxnfc: RX ring (%llu) doesn't exist\n",
index aa074e57ce06fb2842fa1faabd156c3cd2fe10f5..77abd181304750c0e67b67526c129000d63a8e35 100644 (file)
@@ -997,7 +997,8 @@ void mlx4_en_calc_rx_buf(struct net_device *dev)
        en_dbg(DRV, priv, "Rx buffer scatter-list (effective-mtu:%d num_frags:%d):\n",
               eff_mtu, priv->num_frags);
        for (i = 0; i < priv->num_frags; i++) {
-               en_err(priv,
+               en_dbg(DRV,
+                      priv,
                       "  frag:%d - size:%d stride:%d\n",
                       i,
                       priv->frag_info[i].frag_size,
index 3ba89bc43d74d8c023776079bcd0bbadd70fb5c6..6ffd1849a604dda97e06d24074c9b27512240602 100644 (file)
@@ -70,13 +70,10 @@ int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
        ring->full_size = ring->size - HEADROOM - MAX_DESC_TXBBS;
 
        tmp = size * sizeof(struct mlx4_en_tx_info);
-       ring->tx_info = kmalloc_node(tmp, GFP_KERNEL | __GFP_NOWARN, node);
+       ring->tx_info = kvmalloc_node(tmp, GFP_KERNEL, node);
        if (!ring->tx_info) {
-               ring->tx_info = vmalloc(tmp);
-               if (!ring->tx_info) {
-                       err = -ENOMEM;
-                       goto err_ring;
-               }
+               err = -ENOMEM;
+               goto err_ring;
        }
 
        en_dbg(DRV, priv, "Allocated tx_info ring at addr:%p size:%d\n",
index 703205475524d689cd2762f2d2ce3abfd2b6ebcb..83aab1e4c8c8c76f73a598c5bdde51e185d9121a 100644 (file)
@@ -2862,12 +2862,10 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev)
        int port = 0;
 
        if (msi_x) {
-               int nreq = dev->caps.num_ports * num_online_cpus() + 1;
-
-               nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs,
-                            nreq);
-               if (nreq > MAX_MSIX)
-                       nreq = MAX_MSIX;
+               int nreq = min3(dev->caps.num_ports *
+                               (int)num_online_cpus() + 1,
+                               dev->caps.num_eqs - dev->caps.reserved_eqs,
+                               MAX_MSIX);
 
                entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL);
                if (!entries)
index db65f72879e98d0dfef54cac4b5cf2c0ac682783..ce852ca22a968673b46d3f92d3a1ab3e526864fa 100644 (file)
@@ -115,12 +115,9 @@ static int mlx4_buddy_init(struct mlx4_buddy *buddy, int max_order)
 
        for (i = 0; i <= buddy->max_order; ++i) {
                s = BITS_TO_LONGS(1 << (buddy->max_order - i));
-               buddy->bits[i] = kcalloc(s, sizeof (long), GFP_KERNEL | __GFP_NOWARN);
-               if (!buddy->bits[i]) {
-                       buddy->bits[i] = vzalloc(s * sizeof(long));
-                       if (!buddy->bits[i])
-                               goto err_out_free;
-               }
+               buddy->bits[i] = kvmalloc_array(s, sizeof(long), GFP_KERNEL | __GFP_ZERO);
+               if (!buddy->bits[i])
+                       goto err_out_free;
        }
 
        set_bit(0, buddy->bits[buddy->max_order]);
index 4aa29ee930134cc41f54839f3e6c05a828f5e0f3..07516545474f3ac76e750aaa4af2532b6ac81207 100644 (file)
@@ -311,7 +311,7 @@ static inline int mlx4_grant_resource(struct mlx4_dev *dev, int slave,
        struct mlx4_priv *priv = mlx4_priv(dev);
        struct resource_allocator *res_alloc =
                &priv->mfunc.master.res_tracker.res_alloc[res_type];
-       int err = -EINVAL;
+       int err = -EDQUOT;
        int allocated, free, reserved, guaranteed, from_free;
        int from_rsvd;
 
index a84b652f9b5401eb7655eb8f9b568d5fb72d06c8..27251a78075ccba1c4e151b54387aa987dc17210 100644 (file)
@@ -13,7 +13,7 @@ config MLX5_CORE
 
 config MLX5_CORE_EN
        bool "Mellanox Technologies ConnectX-4 Ethernet support"
-       depends on NETDEVICES && ETHERNET && PCI && MLX5_CORE
+       depends on NETDEVICES && ETHERNET && INET && PCI && MLX5_CORE
        depends on IPV6=y || IPV6=n || MLX5_CORE=m
        imply PTP_1588_CLOCK
        default n
@@ -35,6 +35,6 @@ config MLX5_CORE_EN_DCB
 config MLX5_CORE_IPOIB
        bool "Mellanox Technologies ConnectX-4 IPoIB offloads support"
        depends on MLX5_CORE_EN
-       default y
+       default n
        ---help---
          MLX5 IPoIB offloads & acceleration support.
index 0099a3e397bcf8758388b44e0e44888b35468920..2fd044b238750fedc61384fda55bf25206d25b51 100644 (file)
@@ -1003,7 +1003,7 @@ int mlx5e_create_direct_tirs(struct mlx5e_priv *priv);
 void mlx5e_destroy_direct_tirs(struct mlx5e_priv *priv);
 void mlx5e_destroy_rqt(struct mlx5e_priv *priv, struct mlx5e_rqt *rqt);
 
-int mlx5e_create_ttc_table(struct mlx5e_priv *priv, u32 underlay_qpn);
+int mlx5e_create_ttc_table(struct mlx5e_priv *priv);
 void mlx5e_destroy_ttc_table(struct mlx5e_priv *priv);
 
 int mlx5e_create_tis(struct mlx5_core_dev *mdev, int tc,
index ce7b09d72ff68b1850f6df3845f2fd9ae7f57bbd..8209affa75c3e5e0419634740d6985970f61fa67 100644 (file)
@@ -794,7 +794,6 @@ static void get_supported(u32 eth_proto_cap,
        ptys2ethtool_supported_port(link_ksettings, eth_proto_cap);
        ptys2ethtool_supported_link(supported, eth_proto_cap);
        ethtool_link_ksettings_add_link_mode(link_ksettings, supported, Pause);
-       ethtool_link_ksettings_add_link_mode(link_ksettings, supported, Asym_Pause);
 }
 
 static void get_advertising(u32 eth_proto_cap, u8 tx_pause,
@@ -804,7 +803,7 @@ static void get_advertising(u32 eth_proto_cap, u8 tx_pause,
        unsigned long *advertising = link_ksettings->link_modes.advertising;
 
        ptys2ethtool_adver_link(advertising, eth_proto_cap);
-       if (tx_pause)
+       if (rx_pause)
                ethtool_link_ksettings_add_link_mode(link_ksettings, advertising, Pause);
        if (tx_pause ^ rx_pause)
                ethtool_link_ksettings_add_link_mode(link_ksettings, advertising, Asym_Pause);
@@ -849,6 +848,8 @@ static int mlx5e_get_link_ksettings(struct net_device *netdev,
        struct mlx5e_priv *priv    = netdev_priv(netdev);
        struct mlx5_core_dev *mdev = priv->mdev;
        u32 out[MLX5_ST_SZ_DW(ptys_reg)] = {0};
+       u32 rx_pause = 0;
+       u32 tx_pause = 0;
        u32 eth_proto_cap;
        u32 eth_proto_admin;
        u32 eth_proto_lp;
@@ -871,11 +872,13 @@ static int mlx5e_get_link_ksettings(struct net_device *netdev,
        an_disable_admin = MLX5_GET(ptys_reg, out, an_disable_admin);
        an_status        = MLX5_GET(ptys_reg, out, an_status);
 
+       mlx5_query_port_pause(mdev, &rx_pause, &tx_pause);
+
        ethtool_link_ksettings_zero_link_mode(link_ksettings, supported);
        ethtool_link_ksettings_zero_link_mode(link_ksettings, advertising);
 
        get_supported(eth_proto_cap, link_ksettings);
-       get_advertising(eth_proto_admin, 0, 0, link_ksettings);
+       get_advertising(eth_proto_admin, tx_pause, rx_pause, link_ksettings);
        get_speed_duplex(netdev, eth_proto_oper, link_ksettings);
 
        eth_proto_oper = eth_proto_oper ? eth_proto_oper : eth_proto_cap;
index 576d6787b484b6387c55a172a65fa838b50e198a..53ed58320a24aef89e40230c67728ea01bd086ac 100644 (file)
@@ -800,7 +800,7 @@ void mlx5e_destroy_ttc_table(struct mlx5e_priv *priv)
        mlx5e_destroy_flow_table(&ttc->ft);
 }
 
-int mlx5e_create_ttc_table(struct mlx5e_priv *priv, u32 underlay_qpn)
+int mlx5e_create_ttc_table(struct mlx5e_priv *priv)
 {
        struct mlx5e_ttc_table *ttc = &priv->fs.ttc;
        struct mlx5_flow_table_attr ft_attr = {};
@@ -810,7 +810,6 @@ int mlx5e_create_ttc_table(struct mlx5e_priv *priv, u32 underlay_qpn)
        ft_attr.max_fte = MLX5E_TTC_TABLE_SIZE;
        ft_attr.level = MLX5E_TTC_FT_LEVEL;
        ft_attr.prio = MLX5E_NIC_PRIO;
-       ft_attr.underlay_qpn = underlay_qpn;
 
        ft->t = mlx5_create_flow_table(priv->fs.ns, &ft_attr);
        if (IS_ERR(ft->t)) {
@@ -1147,7 +1146,7 @@ int mlx5e_create_flow_steering(struct mlx5e_priv *priv)
                priv->netdev->hw_features &= ~NETIF_F_NTUPLE;
        }
 
-       err = mlx5e_create_ttc_table(priv, 0);
+       err = mlx5e_create_ttc_table(priv);
        if (err) {
                netdev_err(priv->netdev, "Failed to create ttc table, err=%d\n",
                           err);
index a61b71b6fff30358e43602b1f84e16c697e3140f..41cd22a223dccbd9dae460331525a1fc2414be9e 100644 (file)
@@ -2976,7 +2976,7 @@ static int mlx5e_setup_tc(struct net_device *netdev, u8 tc)
        new_channels.params = priv->channels.params;
        new_channels.params.num_tc = tc ? tc : 1;
 
-       if (test_bit(MLX5E_STATE_OPENED, &priv->state)) {
+       if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) {
                priv->channels.params = new_channels.params;
                goto out;
        }
index 19e3d2fc2099e09a987d0d475629580c72cd37c0..fcec7bedd3cd348f78ec25703d4e77a6e005f596 100644 (file)
 #include "eswitch.h"
 
 int mlx5_cmd_update_root_ft(struct mlx5_core_dev *dev,
-                           struct mlx5_flow_table *ft)
+                           struct mlx5_flow_table *ft, u32 underlay_qpn)
 {
        u32 in[MLX5_ST_SZ_DW(set_flow_table_root_in)]   = {0};
        u32 out[MLX5_ST_SZ_DW(set_flow_table_root_out)] = {0};
 
        if ((MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_IB) &&
-           ft->underlay_qpn == 0)
+           underlay_qpn == 0)
                return 0;
 
        MLX5_SET(set_flow_table_root_in, in, opcode,
                 MLX5_CMD_OP_SET_FLOW_TABLE_ROOT);
        MLX5_SET(set_flow_table_root_in, in, table_type, ft->type);
        MLX5_SET(set_flow_table_root_in, in, table_id, ft->id);
+       MLX5_SET(set_flow_table_root_in, in, underlay_qpn, underlay_qpn);
        if (ft->vport) {
                MLX5_SET(set_flow_table_root_in, in, vport_number, ft->vport);
                MLX5_SET(set_flow_table_root_in, in, other_vport, 1);
        }
 
-       if ((MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_IB) &&
-           ft->underlay_qpn != 0)
-               MLX5_SET(set_flow_table_root_in, in, underlay_qpn, ft->underlay_qpn);
-
        return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
 }
 
index 8fad806885362dce727791213422b7a9c0d5b897..0f98a7cf4877d8103ef03989e15d05eda570fdb2 100644 (file)
@@ -71,7 +71,8 @@ int mlx5_cmd_delete_fte(struct mlx5_core_dev *dev,
                        unsigned int index);
 
 int mlx5_cmd_update_root_ft(struct mlx5_core_dev *dev,
-                           struct mlx5_flow_table *ft);
+                           struct mlx5_flow_table *ft,
+                           u32 underlay_qpn);
 
 int mlx5_cmd_fc_alloc(struct mlx5_core_dev *dev, u16 *id);
 int mlx5_cmd_fc_free(struct mlx5_core_dev *dev, u16 id);
index b8a176503d384f863de75cacf7bd81d1f40ad9d8..0e487e8ca634bce0108979823e755918fe27c3fb 100644 (file)
@@ -650,7 +650,7 @@ static int update_root_ft_create(struct mlx5_flow_table *ft, struct fs_prio
        if (ft->level >= min_level)
                return 0;
 
-       err = mlx5_cmd_update_root_ft(root->dev, ft);
+       err = mlx5_cmd_update_root_ft(root->dev, ft, root->underlay_qpn);
        if (err)
                mlx5_core_warn(root->dev, "Update root flow table of id=%u failed\n",
                               ft->id);
@@ -818,8 +818,6 @@ static struct mlx5_flow_table *__mlx5_create_flow_table(struct mlx5_flow_namespa
                goto unlock_root;
        }
 
-       ft->underlay_qpn = ft_attr->underlay_qpn;
-
        tree_init_node(&ft->node, 1, del_flow_table);
        log_table_sz = ft->max_fte ? ilog2(ft->max_fte) : 0;
        next_ft = find_next_chained_ft(fs_prio);
@@ -1489,7 +1487,8 @@ static int update_root_ft_destroy(struct mlx5_flow_table *ft)
 
        new_root_ft = find_next_ft(ft);
        if (new_root_ft) {
-               int err = mlx5_cmd_update_root_ft(root->dev, new_root_ft);
+               int err = mlx5_cmd_update_root_ft(root->dev, new_root_ft,
+                                                 root->underlay_qpn);
 
                if (err) {
                        mlx5_core_warn(root->dev, "Update root flow table of id=%u failed\n",
@@ -2062,3 +2061,21 @@ err:
        mlx5_cleanup_fs(dev);
        return err;
 }
+
+int mlx5_fs_add_rx_underlay_qpn(struct mlx5_core_dev *dev, u32 underlay_qpn)
+{
+       struct mlx5_flow_root_namespace *root = dev->priv.steering->root_ns;
+
+       root->underlay_qpn = underlay_qpn;
+       return 0;
+}
+EXPORT_SYMBOL(mlx5_fs_add_rx_underlay_qpn);
+
+int mlx5_fs_remove_rx_underlay_qpn(struct mlx5_core_dev *dev, u32 underlay_qpn)
+{
+       struct mlx5_flow_root_namespace *root = dev->priv.steering->root_ns;
+
+       root->underlay_qpn = 0;
+       return 0;
+}
+EXPORT_SYMBOL(mlx5_fs_remove_rx_underlay_qpn);
index 81eafc7b9dd93fc4c8411aa8ad473299ca6c623e..990acee6fb091f102e7412c499df8df44eb806db 100644 (file)
@@ -118,7 +118,6 @@ struct mlx5_flow_table {
        /* FWD rules that point on this flow table */
        struct list_head                fwd_rules;
        u32                             flags;
-       u32                             underlay_qpn;
 };
 
 struct mlx5_fc_cache {
@@ -195,6 +194,7 @@ struct mlx5_flow_root_namespace {
        struct mlx5_flow_table          *root_ft;
        /* Should be held when chaining flow tables */
        struct mutex                    chain_lock;
+       u32                             underlay_qpn;
 };
 
 int mlx5_init_fc_stats(struct mlx5_core_dev *dev);
index 3c84e36af0186bea101736500cf0b20bca57ba6a..cc1858752e70818650ca86a00795b3bb48668fb6 100644 (file)
@@ -30,6 +30,7 @@
  * SOFTWARE.
  */
 
+#include <rdma/ib_verbs.h>
 #include <linux/mlx5/fs.h>
 #include "en.h"
 #include "ipoib.h"
@@ -65,6 +66,10 @@ static void mlx5i_init(struct mlx5_core_dev *mdev,
 
        mlx5e_build_nic_params(mdev, &priv->channels.params, profile->max_nch(mdev));
 
+       /* Override RQ params as IPoIB supports only LINKED LIST RQ for now */
+       mlx5e_set_rq_type_params(mdev, &priv->channels.params, MLX5_WQ_TYPE_LINKED_LIST);
+       priv->channels.params.lro_en = false;
+
        mutex_init(&priv->state_lock);
 
        netdev->hw_features    |= NETIF_F_SG;
@@ -155,6 +160,8 @@ out:
 
 static void mlx5i_destroy_underlay_qp(struct mlx5_core_dev *mdev, struct mlx5_core_qp *qp)
 {
+       mlx5_fs_remove_rx_underlay_qpn(mdev, qp->qpn);
+
        mlx5_core_destroy_qp(mdev, qp);
 }
 
@@ -169,6 +176,8 @@ static int mlx5i_init_tx(struct mlx5e_priv *priv)
                return err;
        }
 
+       mlx5_fs_add_rx_underlay_qpn(priv->mdev, ipriv->qp.qpn);
+
        err = mlx5e_create_tis(priv->mdev, 0 /* tc */, ipriv->qp.qpn, &priv->tisn[0]);
        if (err) {
                mlx5_core_warn(priv->mdev, "create tis failed, %d\n", err);
@@ -188,7 +197,6 @@ static void mlx5i_cleanup_tx(struct mlx5e_priv *priv)
 
 static int mlx5i_create_flow_steering(struct mlx5e_priv *priv)
 {
-       struct mlx5i_priv *ipriv = priv->ppriv;
        int err;
 
        priv->fs.ns = mlx5_get_flow_namespace(priv->mdev,
@@ -204,7 +212,7 @@ static int mlx5i_create_flow_steering(struct mlx5e_priv *priv)
                priv->netdev->hw_features &= ~NETIF_F_NTUPLE;
        }
 
-       err = mlx5e_create_ttc_table(priv, ipriv->qp.qpn);
+       err = mlx5e_create_ttc_table(priv);
        if (err) {
                netdev_err(priv->netdev, "Failed to create ttc table, err=%d\n",
                           err);
@@ -359,10 +367,10 @@ unlock:
        return 0;
 }
 
-#ifdef notusedyet
 /* IPoIB RDMA netdev callbacks */
 static int mlx5i_attach_mcast(struct net_device *netdev, struct ib_device *hca,
-                             union ib_gid *gid, u16 lid, int set_qkey)
+                             union ib_gid *gid, u16 lid, int set_qkey,
+                             u32 qkey)
 {
        struct mlx5e_priv    *epriv = mlx5i_epriv(netdev);
        struct mlx5_core_dev *mdev  = epriv->mdev;
@@ -375,6 +383,12 @@ static int mlx5i_attach_mcast(struct net_device *netdev, struct ib_device *hca,
                mlx5_core_warn(mdev, "failed attaching QPN 0x%x, MGID %pI6\n",
                               ipriv->qp.qpn, gid->raw);
 
+       if (set_qkey) {
+               mlx5_core_dbg(mdev, "%s setting qkey 0x%x\n",
+                             netdev->name, qkey);
+               ipriv->qkey = qkey;
+       }
+
        return err;
 }
 
@@ -397,15 +411,15 @@ static int mlx5i_detach_mcast(struct net_device *netdev, struct ib_device *hca,
 }
 
 static int mlx5i_xmit(struct net_device *dev, struct sk_buff *skb,
-              struct ib_ah *address, u32 dqpn, u32 dqkey)
+                     struct ib_ah *address, u32 dqpn)
 {
        struct mlx5e_priv *epriv = mlx5i_epriv(dev);
        struct mlx5e_txqsq *sq   = epriv->txq2sq[skb_get_queue_mapping(skb)];
        struct mlx5_ib_ah *mah   = to_mah(address);
+       struct mlx5i_priv *ipriv = epriv->ppriv;
 
-       return mlx5i_sq_xmit(sq, skb, &mah->av, dqpn, dqkey);
+       return mlx5i_sq_xmit(sq, skb, &mah->av, dqpn, ipriv->qkey);
 }
-#endif
 
 static int mlx5i_check_required_hca_cap(struct mlx5_core_dev *mdev)
 {
@@ -414,22 +428,23 @@ static int mlx5i_check_required_hca_cap(struct mlx5_core_dev *mdev)
 
        if (!MLX5_CAP_GEN(mdev, ipoib_enhanced_offloads)) {
                mlx5_core_warn(mdev, "IPoIB enhanced offloads are not supported\n");
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
        }
 
        return 0;
 }
 
-static struct net_device *mlx5_rdma_netdev_alloc(struct mlx5_core_dev *mdev,
-                                                struct ib_device *ibdev,
-                                                const char *name,
-                                                void (*setup)(struct net_device *))
+struct net_device *mlx5_rdma_netdev_alloc(struct mlx5_core_dev *mdev,
+                                         struct ib_device *ibdev,
+                                         const char *name,
+                                         void (*setup)(struct net_device *))
 {
        const struct mlx5e_profile *profile = &mlx5i_nic_profile;
        int nch = profile->max_nch(mdev);
        struct net_device *netdev;
        struct mlx5i_priv *ipriv;
        struct mlx5e_priv *epriv;
+       struct rdma_netdev *rn;
        int err;
 
        if (mlx5i_check_required_hca_cap(mdev)) {
@@ -464,13 +479,13 @@ static struct net_device *mlx5_rdma_netdev_alloc(struct mlx5_core_dev *mdev,
        mlx5e_attach_netdev(epriv);
        netif_carrier_off(netdev);
 
-       /* TODO: set rdma_netdev func pointers
-        * rn = &ipriv->rn;
-        * rn->hca  = ibdev;
-        * rn->send = mlx5i_xmit;
-        * rn->attach_mcast = mlx5i_attach_mcast;
-        * rn->detach_mcast = mlx5i_detach_mcast;
-        */
+       /* set rdma_netdev func pointers */
+       rn = &ipriv->rn;
+       rn->hca  = ibdev;
+       rn->send = mlx5i_xmit;
+       rn->attach_mcast = mlx5i_attach_mcast;
+       rn->detach_mcast = mlx5i_detach_mcast;
+
        return netdev;
 
 err_free_netdev:
@@ -482,7 +497,7 @@ free_mdev_resources:
 }
 EXPORT_SYMBOL(mlx5_rdma_netdev_alloc);
 
-static void mlx5_rdma_netdev_free(struct net_device *netdev)
+void mlx5_rdma_netdev_free(struct net_device *netdev)
 {
        struct mlx5e_priv          *priv    = mlx5i_epriv(netdev);
        const struct mlx5e_profile *profile = priv->profile;
index bae0a5cbc8ad396c846c27848f717ebc6d68a613..213191a7846479d768804a010a686f6501c268a3 100644 (file)
@@ -40,7 +40,9 @@
 
 /* ipoib rdma netdev's private data structure */
 struct mlx5i_priv {
+       struct rdma_netdev rn; /* keep this first */
        struct mlx5_core_qp qp;
+       u32    qkey;
        char  *mlx5e_priv[0];
 };
 
index ea56f6ade6b429585f35a2f72dae20f8d51d4a0f..5f0a7bc692a4b8e3efae2f8a3c8a55f5c448346d 100644 (file)
@@ -199,10 +199,11 @@ static int mlxsw_sp_erif_entry_get(struct mlxsw_sp *mlxsw_sp,
 
        entry->counter_valid = false;
        entry->counter = 0;
+       entry->index = mlxsw_sp_rif_index(rif);
+
        if (!counters_enabled)
                return 0;
 
-       entry->index = mlxsw_sp_rif_index(rif);
        err = mlxsw_sp_rif_counter_value_get(mlxsw_sp, rif,
                                             MLXSW_SP_RIF_COUNTER_EGRESS,
                                             &cnt);
index 33cec1cc164259ad9d7dd022a811e957447a61ff..9f89c4137d2137f78bcda8f79a918b8db61a5189 100644 (file)
@@ -206,6 +206,9 @@ void mlxsw_sp_rif_counter_free(struct mlxsw_sp *mlxsw_sp,
 {
        unsigned int *p_counter_index;
 
+       if (!mlxsw_sp_rif_counter_valid_get(rif, dir))
+               return;
+
        p_counter_index = mlxsw_sp_rif_p_counter_get(rif, dir);
        if (WARN_ON(!p_counter_index))
                return;
index 0d8411f1f954c5668bc3bd26f721589f2ccf205d..f4bb0c0b7c1d2689a884d64010fde0f0dfd4053c 100644 (file)
@@ -1497,8 +1497,7 @@ do_fdb_op:
        err = mlxsw_sp_port_fdb_uc_op(mlxsw_sp, local_port, mac, fid,
                                      adding, true);
        if (err) {
-               if (net_ratelimit())
-                       netdev_err(mlxsw_sp_port->dev, "Failed to set FDB entry\n");
+               dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to set FDB entry\n");
                return;
        }
 
@@ -1558,8 +1557,7 @@ do_fdb_op:
        err = mlxsw_sp_port_fdb_uc_lag_op(mlxsw_sp, lag_id, mac, fid, lag_vid,
                                          adding, true);
        if (err) {
-               if (net_ratelimit())
-                       netdev_err(mlxsw_sp_port->dev, "Failed to set FDB entry\n");
+               dev_err_ratelimited(mlxsw_sp->bus_info->dev, "Failed to set FDB entry\n");
                return;
        }
 
index 07091dd27e5df2969592a3faa54f30fdad4a4844..7b0a8db57af93b8d06feec622ff94c36e9183d54 100644 (file)
@@ -444,7 +444,7 @@ static inline __u16 sonic_rra_get(struct net_device* dev, int entry,
                             (entry * SIZEOF_SONIC_RR) + offset);
 }
 
-static const char *version =
+static const char version[] =
     "sonic.c:v0.92 20.9.98 tsbogend@alpha.franken.de\n";
 
 #endif /* SONIC_H */
index b8d5270359cd8a7109226c0be1731cbafa6d1423..e306765155290a31e390f5ddcf88b4f0aa8f973c 100644 (file)
@@ -247,7 +247,7 @@ nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu)
        cmd.req.arg3 = 0;
 
        if (recv_ctx->state == NX_HOST_CTX_STATE_ACTIVE)
-               netxen_issue_cmd(adapter, &cmd);
+               rcode = netxen_issue_cmd(adapter, &cmd);
 
        if (rcode != NX_RCODE_SUCCESS)
                return -EIO;
index b3aaa985956e4a937af56ccf2410cf9eeb884985..694845793af2790276b61e2416c2498cc7cdc3fd 100644 (file)
@@ -1460,6 +1460,7 @@ void qed_qm_init_pf(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
        params.is_first_pf = p_hwfn->first_on_engine;
        params.num_pf_cids = iids.cids;
        params.num_vf_cids = iids.vf_cids;
+       params.num_tids = iids.tids;
        params.start_pq = qm_info->start_pq;
        params.num_pf_pqs = qm_info->num_pqs - qm_info->num_vf_pqs;
        params.num_vf_pqs = qm_info->num_vf_pqs;
index bb70522ad362e913dec2a8fadff5ab1fcc0f27b7..463927f17032cf8397823969221f32d884c54d85 100644 (file)
@@ -1370,7 +1370,7 @@ qed_hw_init_pf_doorbell_bar(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
                                                   NULL) +
                       qed_cxt_get_proto_cid_count(p_hwfn, PROTOCOLID_ETH,
                                                   NULL);
-       norm_regsize = roundup(QED_PF_DEMS_SIZE * non_pwm_conn, 4096);
+       norm_regsize = roundup(QED_PF_DEMS_SIZE * non_pwm_conn, PAGE_SIZE);
        min_addr_reg1 = norm_regsize / 4096;
        pwm_regsize = db_bar_size - norm_regsize;
 
index 67200c5498ab01d3911735f25e6ccea05aed200e..0a8fde6299919b3c1e0d7382ac90be30631644e3 100644 (file)
@@ -983,7 +983,7 @@ void qed_set_rfs_mode_disable(struct qed_hwfn *p_hwfn,
        memset(&camline, 0, sizeof(union gft_cam_line_union));
        qed_wr(p_hwfn, p_ptt, PRS_REG_GFT_CAM + CAM_LINE_SIZE * pf_id,
               camline.cam_line_mapped.camline);
-       memset(&ramline, 0, sizeof(union gft_cam_line_union));
+       memset(&ramline, 0, sizeof(ramline));
 
        for (i = 0; i < RAM_LINE_SIZE / REG_SIZE; i++) {
                u32 hw_addr = PRS_REG_GFT_PROFILE_MASK_RAM;
index 0ed24d6e6c6520450ed05b50e8486e54b712a354..40f057edeafc7b91349107e780869bb6bb8bd112 100644 (file)
@@ -3058,7 +3058,7 @@ int qed_int_igu_read_cam(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt)
 
        /* There's a possibility the igu_sb_cnt_iov doesn't properly reflect
         * the number of VF SBs [especially for first VF on engine, as we can't
-        * diffrentiate between empty entries and its entries].
+        * differentiate between empty entries and its entries].
         * Since we don't really support more SBs than VFs today, prevent any
         * such configuration by sanitizing the number of SBs to equal the
         * number of VFs.
index b7ad36b91e12cb71bf6658ec8e568cc61472850f..537d1236a4fec0a2973d52ed34cf7f73d8a4b052 100644 (file)
@@ -978,7 +978,7 @@ static int qed_slowpath_start(struct qed_dev *cdev,
                if (rc)
                        goto err2;
 
-               /* First Dword used to diffrentiate between various sources */
+               /* First Dword used to differentiate between various sources */
                data = cdev->firmware->data + sizeof(u32);
 
                qed_dbg_pf_init(cdev);
@@ -1093,10 +1093,12 @@ static int qed_slowpath_stop(struct qed_dev *cdev)
                qed_free_stream_mem(cdev);
                if (IS_QED_ETH_IF(cdev))
                        qed_sriov_disable(cdev, true);
+       }
+
+       qed_nic_stop(cdev);
 
-               qed_nic_stop(cdev);
+       if (IS_PF(cdev))
                qed_slowpath_irq_free(cdev);
-       }
 
        qed_disable_msix(cdev);
 
index d5df29f787c569a16228baa3679fd5d942027756..f5ed54d611ec91ec07372fdaffca0bd18eb659b4 100644 (file)
@@ -625,7 +625,7 @@ int qed_iov_hw_info(struct qed_hwfn *p_hwfn)
         *  - If !ARI, VFs would start on next device.
         *    so offset - (256 - pf_id) would provide the number.
         * Utilize the fact that (256 - pf_id) is achieved only by later
-        * to diffrentiate between the two.
+        * to differentiate between the two.
         */
 
        if (p_hwfn->cdev->p_iov_info->offset < (256 - p_hwfn->abs_pf_id)) {
index eb5652073ca86dfcbbbdf5c73cfb998a72e09917..333876c19d7db0228fdbcc15dea4c5a2a0a4a11f 100644 (file)
@@ -1028,11 +1028,6 @@ int qede_xdp(struct net_device *dev, struct netdev_xdp *xdp)
 {
        struct qede_dev *edev = netdev_priv(dev);
 
-       if (IS_VF(edev)) {
-               DP_NOTICE(edev, "VFs don't support XDP\n");
-               return -EOPNOTSUPP;
-       }
-
        switch (xdp->command) {
        case XDP_SETUP_PROG:
                return qede_xdp_set(edev, xdp->prog);
index b9ba23d71c61a6f7cf7edc1a2ff9e5fd6e252514..38b77bbfe4eeac8cb67cbbef40d8d9eec59168ec 100644 (file)
@@ -563,6 +563,23 @@ static const struct net_device_ops qede_netdev_ops = {
 #endif
 };
 
+static const struct net_device_ops qede_netdev_vf_ops = {
+       .ndo_open = qede_open,
+       .ndo_stop = qede_close,
+       .ndo_start_xmit = qede_start_xmit,
+       .ndo_set_rx_mode = qede_set_rx_mode,
+       .ndo_set_mac_address = qede_set_mac_addr,
+       .ndo_validate_addr = eth_validate_addr,
+       .ndo_change_mtu = qede_change_mtu,
+       .ndo_vlan_rx_add_vid = qede_vlan_rx_add_vid,
+       .ndo_vlan_rx_kill_vid = qede_vlan_rx_kill_vid,
+       .ndo_set_features = qede_set_features,
+       .ndo_get_stats64 = qede_get_stats64,
+       .ndo_udp_tunnel_add = qede_udp_tunnel_add,
+       .ndo_udp_tunnel_del = qede_udp_tunnel_del,
+       .ndo_features_check = qede_features_check,
+};
+
 /* -------------------------------------------------------------------------
  * START OF PROBE / REMOVE
  * -------------------------------------------------------------------------
@@ -622,7 +639,10 @@ static void qede_init_ndev(struct qede_dev *edev)
 
        ndev->watchdog_timeo = TX_TIMEOUT;
 
-       ndev->netdev_ops = &qede_netdev_ops;
+       if (IS_VF(edev))
+               ndev->netdev_ops = &qede_netdev_vf_ops;
+       else
+               ndev->netdev_ops = &qede_netdev_ops;
 
        qede_set_ethtool_ops(ndev);
 
@@ -1313,6 +1333,9 @@ static void qede_free_mem_fp(struct qede_dev *edev, struct qede_fastpath *fp)
        if (fp->type & QEDE_FASTPATH_RX)
                qede_free_mem_rxq(edev, fp->rxq);
 
+       if (fp->type & QEDE_FASTPATH_XDP)
+               qede_free_mem_txq(edev, fp->xdp_tx);
+
        if (fp->type & QEDE_FASTPATH_TX)
                qede_free_mem_txq(edev, fp->txq);
 }
index 49bad00a0f8f994837b0554f3250d5ca0811bff7..7245b1072518fff31566c471b6eb32b512e41846 100644 (file)
@@ -37,8 +37,8 @@
 
 #define _QLCNIC_LINUX_MAJOR 5
 #define _QLCNIC_LINUX_MINOR 3
-#define _QLCNIC_LINUX_SUBVERSION 65
-#define QLCNIC_LINUX_VERSIONID  "5.3.65"
+#define _QLCNIC_LINUX_SUBVERSION 66
+#define QLCNIC_LINUX_VERSIONID  "5.3.66"
 #define QLCNIC_DRV_IDC_VER  0x01
 #define QLCNIC_DRIVER_VERSION  ((_QLCNIC_LINUX_MAJOR << 16) |\
                 (_QLCNIC_LINUX_MINOR << 8) | (_QLCNIC_LINUX_SUBVERSION))
index 718bf58a7da66284e121f3aab8e79de7a6221c67..4fb68797630e9531e7ffc4e7bc7c015313a44063 100644 (file)
@@ -3168,6 +3168,40 @@ int qlcnic_83xx_flash_read32(struct qlcnic_adapter *adapter, u32 flash_addr,
        return 0;
 }
 
+void qlcnic_83xx_get_port_type(struct qlcnic_adapter *adapter)
+{
+       struct qlcnic_hardware_context *ahw = adapter->ahw;
+       struct qlcnic_cmd_args cmd;
+       u32 config;
+       int err;
+
+       err = qlcnic_alloc_mbx_args(&cmd, adapter, QLCNIC_CMD_GET_LINK_STATUS);
+       if (err)
+               return;
+
+       err = qlcnic_issue_cmd(adapter, &cmd);
+       if (err) {
+               dev_info(&adapter->pdev->dev,
+                        "Get Link Status Command failed: 0x%x\n", err);
+               goto out;
+       } else {
+               config = cmd.rsp.arg[3];
+
+               switch (QLC_83XX_SFP_MODULE_TYPE(config)) {
+               case QLC_83XX_MODULE_FIBRE_1000BASE_SX:
+               case QLC_83XX_MODULE_FIBRE_1000BASE_LX:
+               case QLC_83XX_MODULE_FIBRE_1000BASE_CX:
+               case QLC_83XX_MODULE_TP_1000BASE_T:
+                       ahw->port_type = QLCNIC_GBE;
+                       break;
+               default:
+                       ahw->port_type = QLCNIC_XGBE;
+               }
+       }
+out:
+       qlcnic_free_mbx_args(&cmd);
+}
+
 int qlcnic_83xx_test_link(struct qlcnic_adapter *adapter)
 {
        u8 pci_func;
index 3dfe8e27b51c68de0af32af949b096d247e3ccb0..b75a812468569de7728fd9c654b6f1c7e353729f 100644 (file)
@@ -637,6 +637,7 @@ void qlcnic_83xx_get_pauseparam(struct qlcnic_adapter *,
 int qlcnic_83xx_set_pauseparam(struct qlcnic_adapter *,
                               struct ethtool_pauseparam *);
 int qlcnic_83xx_test_link(struct qlcnic_adapter *);
+void qlcnic_83xx_get_port_type(struct qlcnic_adapter *adapter);
 int qlcnic_83xx_reg_test(struct qlcnic_adapter *);
 int qlcnic_83xx_get_regs_len(struct qlcnic_adapter *);
 int qlcnic_83xx_get_registers(struct qlcnic_adapter *, u32 *);
index 9a869c15d8bfbfc64b48a831a2b4eb7b38160714..7f7deeaf1cf07913454a13b4f7801c7b3b07545f 100644 (file)
@@ -486,6 +486,9 @@ static int qlcnic_set_link_ksettings(struct net_device *dev,
        u32 ret = 0;
        struct qlcnic_adapter *adapter = netdev_priv(dev);
 
+       if (qlcnic_83xx_check(adapter))
+               qlcnic_83xx_get_port_type(adapter);
+
        if (adapter->ahw->port_type != QLCNIC_GBE)
                return -EOPNOTSUPP;
 
index 829be21f97b21dd694c6cad732b06a899be106c8..28ea0af89aefeb2a733801af03a21b20d269cb37 100644 (file)
@@ -765,7 +765,7 @@ int ql_core_dump(struct ql_adapter *qdev, struct ql_mpi_coredump *mpi_coredump)
                sizeof(struct mpi_coredump_global_header);
        mpi_coredump->mpi_global_header.imageSize =
                sizeof(struct ql_mpi_coredump);
-       memcpy(mpi_coredump->mpi_global_header.idString, "MPI Coredump",
+       strncpy(mpi_coredump->mpi_global_header.idString, "MPI Coredump",
                sizeof(mpi_coredump->mpi_global_header.idString));
 
        /* Get generic NIC reg dump */
@@ -1255,7 +1255,7 @@ static void ql_gen_reg_dump(struct ql_adapter *qdev,
                sizeof(struct mpi_coredump_global_header);
        mpi_coredump->mpi_global_header.imageSize =
                sizeof(struct ql_reg_dump);
-       memcpy(mpi_coredump->mpi_global_header.idString, "MPI Coredump",
+       strncpy(mpi_coredump->mpi_global_header.idString, "MPI Coredump",
                sizeof(mpi_coredump->mpi_global_header.idString));
 
 
index 513e6c74e1990b6fb2c8b00ee9f5a4b70076115d..24ca7df15d07d48a4214bd5df38edcceb6d284aa 100644 (file)
@@ -296,8 +296,9 @@ qcaspi_receive(struct qcaspi *qca)
 
        /* Allocate rx SKB if we don't have one available. */
        if (!qca->rx_skb) {
-               qca->rx_skb = netdev_alloc_skb(net_dev,
-                                              net_dev->mtu + VLAN_ETH_HLEN);
+               qca->rx_skb = netdev_alloc_skb_ip_align(net_dev,
+                                                       net_dev->mtu +
+                                                       VLAN_ETH_HLEN);
                if (!qca->rx_skb) {
                        netdev_dbg(net_dev, "out of RX resources\n");
                        qca->stats.out_of_mem++;
@@ -377,7 +378,7 @@ qcaspi_receive(struct qcaspi *qca)
                                        qca->rx_skb, qca->rx_skb->dev);
                                qca->rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
                                netif_rx_ni(qca->rx_skb);
-                               qca->rx_skb = netdev_alloc_skb(net_dev,
+                               qca->rx_skb = netdev_alloc_skb_ip_align(net_dev,
                                        net_dev->mtu + VLAN_ETH_HLEN);
                                if (!qca->rx_skb) {
                                        netdev_dbg(net_dev, "out of RX resources\n");
@@ -759,7 +760,8 @@ qcaspi_netdev_init(struct net_device *dev)
        if (!qca->rx_buffer)
                return -ENOBUFS;
 
-       qca->rx_skb = netdev_alloc_skb(dev, qca->net_dev->mtu + VLAN_ETH_HLEN);
+       qca->rx_skb = netdev_alloc_skb_ip_align(dev, qca->net_dev->mtu +
+                                               VLAN_ETH_HLEN);
        if (!qca->rx_skb) {
                kfree(qca->rx_buffer);
                netdev_info(qca->net_dev, "Failed to allocate RX sk_buff.\n");
index 9bcd4aefc9c507af16325c6099fdfa198998b93e..bed34684994f6899a842a0ad67d63a1e4a341214 100644 (file)
@@ -151,8 +151,8 @@ MODULE_LICENSE("GPL");
 
 module_param(max_interrupt_work, int, 0);
 module_param(debug, int, 0);
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
+module_param_hw_array(io, int, ioport, NULL, 0);
+module_param_hw_array(irq, int, irq, NULL, 0);
 module_param_array(xcvr, int, NULL, 0);
 MODULE_PARM_DESC(max_interrupt_work, "ATP maximum events handled per interrupt");
 MODULE_PARM_DESC(debug, "ATP debug level (0-7)");
index f68c4db656eda84691b411cee940528a01a2bb62..2d686ccf971b1b6525d7ded8ec5e43b65b67ee6c 100644 (file)
@@ -3220,7 +3220,8 @@ static int sh_eth_drv_probe(struct platform_device *pdev)
        /* MDIO bus init */
        ret = sh_mdio_init(mdp, pd);
        if (ret) {
-               dev_err(&ndev->dev, "failed to initialise MDIO\n");
+               if (ret != -EPROBE_DEFER)
+                       dev_err(&pdev->dev, "MDIO init failed: %d\n", ret);
                goto out_release;
        }
 
index d54490d3f7ad3228dc561fb58a51b142042259f3..1e594351a60f1db0e980491290ae09c47bb33a35 100644 (file)
@@ -387,7 +387,7 @@ static void sxgbe_free_rx_buffers(struct net_device *dev,
 /**
  * init_tx_ring - init the TX descriptor ring
  * @dev: net device structure
- * @tx_ring: ring to be intialised
+ * @tx_ring: ring to be initialised
  * @tx_rsize: ring size
  * Description:  this function initializes the DMA TX descriptor
  */
@@ -437,7 +437,7 @@ dmamem_err:
 /**
  * free_rx_ring - free the RX descriptor ring
  * @dev: net device structure
- * @rx_ring: ring to be intialised
+ * @rx_ring: ring to be initialised
  * @rx_rsize: ring size
  * Description:  this function initializes the DMA RX descriptor
  */
@@ -453,7 +453,7 @@ static void free_rx_ring(struct device *dev, struct sxgbe_rx_queue *rx_ring,
 /**
  * init_rx_ring - init the RX descriptor ring
  * @dev: net device structure
- * @rx_ring: ring to be intialised
+ * @rx_ring: ring to be initialised
  * @rx_rsize: ring size
  * Description:  this function initializes the DMA RX descriptor
  */
@@ -539,7 +539,7 @@ err_free_dma_rx:
 /**
  * free_tx_ring - free the TX descriptor ring
  * @dev: net device structure
- * @tx_ring: ring to be intialised
+ * @tx_ring: ring to be initialised
  * @tx_rsize: ring size
  * Description:  this function initializes the DMA TX descriptor
  */
index 7b916aa21bdef18896debc4bdd7384696e50f3a3..4d7fb8af880d0f36189f8475a9859b229a7bd078 100644 (file)
 #include "mcdi.h"
 
 enum {
-       EFX_REV_SIENA_A0 = 0,
-       EFX_REV_HUNT_A0 = 1,
+       /* Revisions 0-2 were Falcon A0, A1 and B0 respectively.
+        * They are not supported by this driver but these revision numbers
+        * form part of the ethtool API for register dumping.
+        */
+       EFX_REV_SIENA_A0 = 3,
+       EFX_REV_HUNT_A0 = 4,
 };
 
 static inline int efx_nic_rev(struct efx_nic *efx)
index c8d84679ede74ed2d3e3ebd87fe3acefa4d1d77d..d3bb2ba51f40754a508ca3c838f9855d5b6248be 100644 (file)
@@ -1501,8 +1501,8 @@ static void smc_set_multicast_list(struct net_device *dev)
 static struct net_device *devSMC9194;
 MODULE_LICENSE("GPL");
 
-module_param(io, int, 0);
-module_param(irq, int, 0);
+module_param_hw(io, int, ioport, 0);
+module_param_hw(irq, int, irq, 0);
 module_param(ifport, int, 0);
 MODULE_PARM_DESC(io, "SMC 99194 I/O base address");
 MODULE_PARM_DESC(irq, "SMC 99194 IRQ number");
index cd8c601323905a7ded2504fa69faa54a1c728066..a74c481401c46ee659b1244b0124966cabeafdbd 100644 (file)
@@ -3725,7 +3725,7 @@ static void sysfs_display_ring(void *head, int size, int extend_desc,
                        ep++;
                } else {
                        seq_printf(seq, "%d [0x%x]: 0x%x 0x%x 0x%x 0x%x\n",
-                                  i, (unsigned int)virt_to_phys(ep),
+                                  i, (unsigned int)virt_to_phys(p),
                                   le32_to_cpu(p->des0), le32_to_cpu(p->des1),
                                   le32_to_cpu(p->des2), le32_to_cpu(p->des3));
                        p++;
index 39be9677914559e18829c64a4df0fb31e35b4de5..22f910795be4fa8dd5bc160bca1762696d52c793 100644 (file)
@@ -70,11 +70,8 @@ static int stmmac_pci_find_phy_addr(struct stmmac_pci_info *info)
        return -ENODEV;
 }
 
-static void stmmac_default_data(struct plat_stmmacenet_data *plat)
+static void common_default_data(struct plat_stmmacenet_data *plat)
 {
-       plat->bus_id = 1;
-       plat->phy_addr = 0;
-       plat->interface = PHY_INTERFACE_MODE_GMII;
        plat->clk_csr = 2;      /* clk_csr_i = 20-35MHz & MDC = clk_csr_i/16 */
        plat->has_gmac = 1;
        plat->force_sf_dma_mode = 1;
@@ -82,10 +79,6 @@ static void stmmac_default_data(struct plat_stmmacenet_data *plat)
        plat->mdio_bus_data->phy_reset = NULL;
        plat->mdio_bus_data->phy_mask = 0;
 
-       plat->dma_cfg->pbl = 32;
-       plat->dma_cfg->pblx8 = true;
-       /* TODO: AXI */
-
        /* Set default value for multicast hash bins */
        plat->multicast_filter_bins = HASH_TABLE_SIZE;
 
@@ -107,12 +100,29 @@ static void stmmac_default_data(struct plat_stmmacenet_data *plat)
        plat->rx_queues_cfg[0].pkt_route = 0x0;
 }
 
+static void stmmac_default_data(struct plat_stmmacenet_data *plat)
+{
+       /* Set common default data first */
+       common_default_data(plat);
+
+       plat->bus_id = 1;
+       plat->phy_addr = 0;
+       plat->interface = PHY_INTERFACE_MODE_GMII;
+
+       plat->dma_cfg->pbl = 32;
+       plat->dma_cfg->pblx8 = true;
+       /* TODO: AXI */
+}
+
 static int quark_default_data(struct plat_stmmacenet_data *plat,
                              struct stmmac_pci_info *info)
 {
        struct pci_dev *pdev = info->pdev;
        int ret;
 
+       /* Set common default data first */
+       common_default_data(plat);
+
        /*
         * Refuse to load the driver and register net device if MAC controller
         * does not connect to any PHY interface.
@@ -124,27 +134,12 @@ static int quark_default_data(struct plat_stmmacenet_data *plat,
        plat->bus_id = PCI_DEVID(pdev->bus->number, pdev->devfn);
        plat->phy_addr = ret;
        plat->interface = PHY_INTERFACE_MODE_RMII;
-       plat->clk_csr = 2;
-       plat->has_gmac = 1;
-       plat->force_sf_dma_mode = 1;
-
-       plat->mdio_bus_data->phy_reset = NULL;
-       plat->mdio_bus_data->phy_mask = 0;
 
        plat->dma_cfg->pbl = 16;
        plat->dma_cfg->pblx8 = true;
        plat->dma_cfg->fixed_burst = 1;
        /* AXI (TODO) */
 
-       /* Set default value for multicast hash bins */
-       plat->multicast_filter_bins = HASH_TABLE_SIZE;
-
-       /* Set default value for unicast filter entries */
-       plat->unicast_filter_entries = 1;
-
-       /* Set the maxmtu to a default of JUMBO_LEN */
-       plat->maxmtu = JUMBO_LEN;
-
        return 0;
 }
 
index 5a90fed0626065613ba59fa7c5f8ca3c2dff6ef3..5b56c24b6ed2e0c45b5a40d32941527bb1539390 100644 (file)
@@ -411,13 +411,14 @@ static int vsw_port_remove(struct vio_dev *vdev)
 
        if (port) {
                del_timer_sync(&port->vio.timer);
+               del_timer_sync(&port->clean_timer);
 
                napi_disable(&port->napi);
+               unregister_netdev(port->dev);
 
                list_del_rcu(&port->list);
 
                synchronize_rcu();
-               del_timer_sync(&port->clean_timer);
                spin_lock_irqsave(&port->vp->lock, flags);
                sunvnet_port_rm_txq_common(port);
                spin_unlock_irqrestore(&port->vp->lock, flags);
@@ -427,7 +428,6 @@ static int vsw_port_remove(struct vio_dev *vdev)
 
                dev_set_drvdata(&vdev->dev, NULL);
 
-               unregister_netdev(port->dev);
                free_netdev(port->dev);
        }
 
index fa674a8bda0c8ff43d19699fefdd0ba718e75c90..f4d7aec5047953559b46755f694cabc191c304f9 100644 (file)
@@ -287,6 +287,10 @@ struct cpsw_ss_regs {
 /* Bit definitions for the CPSW1_TS_SEQ_LTYPE register */
 #define CPSW_V1_SEQ_ID_OFS_SHIFT       16
 
+#define CPSW_MAX_BLKS_TX               15
+#define CPSW_MAX_BLKS_TX_SHIFT         4
+#define CPSW_MAX_BLKS_RX               5
+
 struct cpsw_host_regs {
        u32     max_blks;
        u32     blk_cnt;
@@ -1278,11 +1282,23 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
        switch (cpsw->version) {
        case CPSW_VERSION_1:
                slave_write(slave, TX_PRIORITY_MAPPING, CPSW1_TX_PRI_MAP);
+               /* Increase RX FIFO size to 5 for supporting fullduplex
+                * flow control mode
+                */
+               slave_write(slave,
+                           (CPSW_MAX_BLKS_TX << CPSW_MAX_BLKS_TX_SHIFT) |
+                           CPSW_MAX_BLKS_RX, CPSW1_MAX_BLKS);
                break;
        case CPSW_VERSION_2:
        case CPSW_VERSION_3:
        case CPSW_VERSION_4:
                slave_write(slave, TX_PRIORITY_MAPPING, CPSW2_TX_PRI_MAP);
+               /* Increase RX FIFO size to 5 for supporting fullduplex
+                * flow control mode
+                */
+               slave_write(slave,
+                           (CPSW_MAX_BLKS_TX << CPSW_MAX_BLKS_TX_SHIFT) |
+                           CPSW_MAX_BLKS_RX, CPSW2_MAX_BLKS);
                break;
        }
 
index 729a7da90b5bed279d58d72cfc53cfa6fc2e9c80..e6222e535019a076ea0d4cd4c902f12332f079b2 100644 (file)
@@ -1353,9 +1353,10 @@ int netcp_txpipe_open(struct netcp_tx_pipe *tx_pipe)
 
        tx_pipe->dma_channel = knav_dma_open_channel(dev,
                                tx_pipe->dma_chan_name, &config);
-       if (IS_ERR_OR_NULL(tx_pipe->dma_channel)) {
+       if (IS_ERR(tx_pipe->dma_channel)) {
                dev_err(dev, "failed opening tx chan(%s)\n",
                        tx_pipe->dma_chan_name);
+               ret = PTR_ERR(tx_pipe->dma_channel);
                goto err;
        }
 
@@ -1673,9 +1674,10 @@ static int netcp_setup_navigator_resources(struct net_device *ndev)
 
        netcp->rx_channel = knav_dma_open_channel(netcp->netcp_device->device,
                                        netcp->dma_chan_name, &config);
-       if (IS_ERR_OR_NULL(netcp->rx_channel)) {
+       if (IS_ERR(netcp->rx_channel)) {
                dev_err(netcp->ndev_dev, "failed opening rx chan(%s\n",
                        netcp->dma_chan_name);
+               ret = PTR_ERR(netcp->rx_channel);
                goto fail;
        }
 
index 897176fc5043bf0da12fe5dcb7a659c269fdf615..dd92950a4615c3aab559c6dc383a4e90ee539160 100644 (file)
@@ -2651,7 +2651,6 @@ static int gbe_hwtstamp_set(struct gbe_intf *gbe_intf, struct ifreq *ifr)
        case HWTSTAMP_FILTER_NONE:
                cpts_rx_enable(cpts, 0);
                break;
-       case HWTSTAMP_FILTER_ALL:
        case HWTSTAMP_FILTER_PTP_V1_L4_EVENT:
        case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
        case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
index 3dadee1080b9e2e541d4b1a335671eb40d8c8205..d9db8a06afd26ef901aa0e5cf559559657ea3179 100644 (file)
@@ -23,7 +23,7 @@
  */
 
 #define DRV_VERSION    "1.39"
-static const char *version = "tc35815.c:v" DRV_VERSION "\n";
+static const char version[] = "tc35815.c:v" DRV_VERSION "\n";
 #define MODNAME                        "tc35815"
 
 #include <linux/module.h>
index b0de8ecd7fe8ed8ab030e22da50aef82e283e4b2..f4a816cf012a1b14de57b0da23db07157ce9e927 100644 (file)
 #define DRV_VERSION "v1.11"
 #define DRV_RELDATE "2014/07/01"
 
-static char version[] =
+static const char version[] =
        DRV_NAME ": " DRV_VERSION " " DRV_RELDATE
        "  Lawrence V. Stefani and others\n";
 
index 594fa1407e29103adda651cc3c58290ce609e096..1503f10122f7f141a2ad6533ae8a2dacb34f7457 100644 (file)
@@ -1176,7 +1176,7 @@ static int iobase[NR_PORTS] = { 0x378, };
 
 module_param_array(mode, charp, NULL, 0);
 MODULE_PARM_DESC(mode, "baycom operating mode");
-module_param_array(iobase, int, NULL, 0);
+module_param_hw_array(iobase, int, ioport, NULL, 0);
 MODULE_PARM_DESC(iobase, "baycom io base address");
 
 MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
index 809dc25909d1c57eabf8a7b1bedd76a7fa399678..92b13b39f426012e65cd19c5ccf7c9cb1107910f 100644 (file)
@@ -481,7 +481,7 @@ static int iobase[NR_PORTS] = { 0x378, };
 
 module_param_array(mode, charp, NULL, 0);
 MODULE_PARM_DESC(mode, "baycom operating mode; eg. par96 or picpar");
-module_param_array(iobase, int, NULL, 0);
+module_param_hw_array(iobase, int, ioport, NULL, 0);
 MODULE_PARM_DESC(iobase, "baycom io base address");
 
 MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
index ebc06822fd4d658f9259752a1d370cd3417b60a6..d9a646acca20423f56c4e8e22b9bd35cb8334734 100644 (file)
@@ -614,9 +614,9 @@ static int baud[NR_PORTS] = { [0 ... NR_PORTS-1] = 1200 };
 
 module_param_array(mode, charp, NULL, 0);
 MODULE_PARM_DESC(mode, "baycom operating mode; * for software DCD");
-module_param_array(iobase, int, NULL, 0);
+module_param_hw_array(iobase, int, ioport, NULL, 0);
 MODULE_PARM_DESC(iobase, "baycom io base address");
-module_param_array(irq, int, NULL, 0);
+module_param_hw_array(irq, int, irq, NULL, 0);
 MODULE_PARM_DESC(irq, "baycom irq number");
 module_param_array(baud, int, NULL, 0);
 MODULE_PARM_DESC(baud, "baycom baud rate (300 to 4800)");
index 60fcf512c208c8f3ed2e473f21e99701763d49b8..f1c8a9ff38914ebb9a88a95d7625071665029a0c 100644 (file)
@@ -642,9 +642,9 @@ static int irq[NR_PORTS] = { 4, };
 
 module_param_array(mode, charp, NULL, 0);
 MODULE_PARM_DESC(mode, "baycom operating mode; * for software DCD");
-module_param_array(iobase, int, NULL, 0);
+module_param_hw_array(iobase, int, ioport, NULL, 0);
 MODULE_PARM_DESC(iobase, "baycom io base address");
-module_param_array(irq, int, NULL, 0);
+module_param_hw_array(irq, int, irq, NULL, 0);
 MODULE_PARM_DESC(irq, "baycom irq number");
 
 MODULE_AUTHOR("Thomas M. Sailer, sailer@ife.ee.ethz.ch, hb9jnx@hb9w.che.eu");
index 2479072981a1329a6bcbb5cd252bbeb1fe831b05..dec6b76bc0fbdab3181864d3d3c16ccafd7b5659 100644 (file)
@@ -274,7 +274,7 @@ static unsigned long rand;
 
 MODULE_AUTHOR("Klaus Kudielka");
 MODULE_DESCRIPTION("Driver for high-speed SCC boards");
-module_param_array(io, int, NULL, 0);
+module_param_hw_array(io, int, ioport, NULL, 0);
 MODULE_LICENSE("GPL");
 
 static void __exit dmascc_exit(void)
index b6891ada1d7b7b67311fc8f1e6b04115ba341d11..7a7c5224a3368785fa046640edfbf0888c0d4128 100644 (file)
@@ -976,12 +976,10 @@ static int yam_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
        case SIOCYAMSMCS:
                if (netif_running(dev))
                        return -EINVAL;         /* Cannot change this parameter when up */
-               if ((ym = kmalloc(sizeof(struct yamdrv_ioctl_mcs), GFP_KERNEL)) == NULL)
-                       return -ENOBUFS;
-               if (copy_from_user(ym, ifr->ifr_data, sizeof(struct yamdrv_ioctl_mcs))) {
-                       kfree(ym);
-                       return -EFAULT;
-               }
+               ym = memdup_user(ifr->ifr_data,
+                                sizeof(struct yamdrv_ioctl_mcs));
+               if (IS_ERR(ym))
+                       return PTR_ERR(ym);
                if (ym->bitrate > YAM_MAXBITRATE) {
                        kfree(ym);
                        return -EINVAL;
index dd7fc6659ad40222f48d29bee637479ebc475322..1ce6239a484952739627988f307fc80da17c9eb5 100644 (file)
@@ -60,7 +60,8 @@ MODULE_AUTHOR("Jes Sorensen <jes@wildopensource.com>");
 MODULE_DESCRIPTION("Essential RoadRunner HIPPI driver");
 MODULE_LICENSE("GPL");
 
-static char version[] = "rrunner.c: v0.50 11/11/2002  Jes Sorensen (jes@wildopensource.com)\n";
+static const char version[] =
+"rrunner.c: v0.50 11/11/2002  Jes Sorensen (jes@wildopensource.com)\n";
 
 
 static const struct net_device_ops rr_netdev_ops = {
@@ -1615,17 +1616,14 @@ static int rr_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
                        return -EPERM;
                }
 
-               image = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL);
-               oldimage = kmalloc(EEPROM_WORDS * sizeof(u32), GFP_KERNEL);
-               if (!image || !oldimage) {
-                       error = -ENOMEM;
-                       goto wf_out;
-               }
+               image = memdup_user(rq->ifr_data, EEPROM_BYTES);
+               if (IS_ERR(image))
+                       return PTR_ERR(image);
 
-               error = copy_from_user(image, rq->ifr_data, EEPROM_BYTES);
-               if (error) {
-                       error = -EFAULT;
-                       goto wf_out;
+               oldimage = kmalloc(EEPROM_BYTES, GFP_KERNEL);
+               if (!oldimage) {
+                       kfree(image);
+                       return -ENOMEM;
                }
 
                if (rrpriv->fw_running){
index c285eafd3f1c11d726daf67aaff37b9abf7da6fb..35f198d8370140a78f0390857c12ed68f8a165c6 100644 (file)
@@ -2207,11 +2207,11 @@ MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:" ALI_IRCC_DRIVER_NAME);
 
 
-module_param_array(io, int, NULL, 0);
+module_param_hw_array(io, int, ioport, NULL, 0);
 MODULE_PARM_DESC(io, "Base I/O addresses");
-module_param_array(irq, int, NULL, 0);
+module_param_hw_array(irq, int, irq, NULL, 0);
 MODULE_PARM_DESC(irq, "IRQ lines");
-module_param_array(dma, int, NULL, 0);
+module_param_hw_array(dma, int, dma, NULL, 0);
 MODULE_PARM_DESC(dma, "DMA channels");
 
 module_init(ali_ircc_init);
index 8716b8c07febf5669b5fe21d78f1b68b4d10ea3f..6f3c805f72118b1b04b48cc501b8579caeddf37a 100644 (file)
@@ -1077,7 +1077,7 @@ static int stir421x_patch_device(struct irda_usb_cb *self)
          * are "42101001.sb" or "42101002.sb"
          */
         sprintf(stir421x_fw_name, "4210%4X.sb",
-                self->usbdev->descriptor.bcdDevice);
+               le16_to_cpu(self->usbdev->descriptor.bcdDevice));
         ret = request_firmware(&fw, stir421x_fw_name, &self->usbdev->dev);
         if (ret < 0)
                 return ret;
index aaecc3baaf309ed54683d9b5e93511400d5acff3..7beae147be110065cecba3431a38913c4b5099c1 100644 (file)
@@ -2396,11 +2396,11 @@ MODULE_LICENSE("GPL");
 
 module_param(qos_mtt_bits, int, 0);
 MODULE_PARM_DESC(qos_mtt_bits, "Minimum Turn Time");
-module_param_array(io, int, NULL, 0);
+module_param_hw_array(io, int, ioport, NULL, 0);
 MODULE_PARM_DESC(io, "Base I/O addresses");
-module_param_array(irq, int, NULL, 0);
+module_param_hw_array(irq, int, irq, NULL, 0);
 MODULE_PARM_DESC(irq, "IRQ lines");
-module_param_array(dma, int, NULL, 0);
+module_param_hw_array(dma, int, dma, NULL, 0);
 MODULE_PARM_DESC(dma, "DMA channels");
 module_param(dongle_id, int, 0);
 MODULE_PARM_DESC(dongle_id, "Type-id of used dongle");
index dcf92ba8087257d3ffe8c0a8dab4d5475cb43ea4..23ed89ae5ddce96ff3dd3e5c37343e6c14e9e979 100644 (file)
@@ -82,24 +82,24 @@ MODULE_PARM_DESC(nopnp, "Do not use PNP to detect controller settings, defaults
 
 #define DMA_INVAL 255
 static int ircc_dma = DMA_INVAL;
-module_param(ircc_dma, int, 0);
+module_param_hw(ircc_dma, int, dma, 0);
 MODULE_PARM_DESC(ircc_dma, "DMA channel");
 
 #define IRQ_INVAL 255
 static int ircc_irq = IRQ_INVAL;
-module_param(ircc_irq, int, 0);
+module_param_hw(ircc_irq, int, irq, 0);
 MODULE_PARM_DESC(ircc_irq, "IRQ line");
 
 static int ircc_fir;
-module_param(ircc_fir, int, 0);
+module_param_hw(ircc_fir, int, ioport, 0);
 MODULE_PARM_DESC(ircc_fir, "FIR Base Address");
 
 static int ircc_sir;
-module_param(ircc_sir, int, 0);
+module_param_hw(ircc_sir, int, ioport, 0);
 MODULE_PARM_DESC(ircc_sir, "SIR Base Address");
 
 static int ircc_cfg;
-module_param(ircc_cfg, int, 0);
+module_param_hw(ircc_cfg, int, ioport, 0);
 MODULE_PARM_DESC(ircc_cfg, "Configuration register base address");
 
 static int ircc_transceiver;
index 8d5b903d1d9dcd1f0f783f470b6fdbe482d6bbee..282b6c9ae05b3a0a8a782afea4e040fb198c59a1 100644 (file)
@@ -1263,9 +1263,9 @@ MODULE_LICENSE("GPL");
 
 module_param(qos_mtt_bits, int, 0);
 MODULE_PARM_DESC(qos_mtt_bits, "Mimimum Turn Time");
-module_param_array(io, int, NULL, 0);
+module_param_hw_array(io, int, ioport, NULL, 0);
 MODULE_PARM_DESC(io, "Base I/O addresses");
-module_param_array(irq, int, NULL, 0);
+module_param_hw_array(irq, int, irq, NULL, 0);
 MODULE_PARM_DESC(irq, "IRQ lines");
 
 /*
index b34eaaae03fd3f289aab4a90b11c05c587858ad2..346ad2ff39989d3da4cacc6ec1965ca882c475cd 100644 (file)
@@ -789,10 +789,12 @@ static int macvlan_change_mtu(struct net_device *dev, int new_mtu)
  */
 static struct lock_class_key macvlan_netdev_addr_lock_key;
 
-#define ALWAYS_ON_FEATURES \
-       (NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_GSO_SOFTWARE | NETIF_F_LLTX | \
+#define ALWAYS_ON_OFFLOADS \
+       (NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_GSO_SOFTWARE | \
         NETIF_F_GSO_ROBUST)
 
+#define ALWAYS_ON_FEATURES (ALWAYS_ON_OFFLOADS | NETIF_F_LLTX)
+
 #define MACVLAN_FEATURES \
        (NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | \
         NETIF_F_GSO | NETIF_F_TSO | NETIF_F_UFO | NETIF_F_LRO | \
@@ -827,6 +829,7 @@ static int macvlan_init(struct net_device *dev)
        dev->features           |= ALWAYS_ON_FEATURES;
        dev->hw_features        |= NETIF_F_LRO;
        dev->vlan_features      = lowerdev->vlan_features & MACVLAN_FEATURES;
+       dev->vlan_features      |= ALWAYS_ON_OFFLOADS;
        dev->gso_max_size       = lowerdev->gso_max_size;
        dev->gso_max_segs       = lowerdev->gso_max_segs;
        dev->hard_header_len    = lowerdev->hard_header_len;
index 0a0412524cec5d00898b963ffc61146eb81989e6..0a5f62e0efccd0e6055c81d06c0f360788a114a1 100644 (file)
@@ -203,11 +203,14 @@ static int mdio_mux_iproc_probe(struct platform_device *pdev)
                           &md->mux_handle, md, md->mii_bus);
        if (rc) {
                dev_info(md->dev, "mdiomux initialization failed\n");
-               goto out;
+               goto out_register;
        }
 
        dev_info(md->dev, "iProc mdiomux registered\n");
        return 0;
+
+out_register:
+       mdiobus_unregister(bus);
 out:
        mdiobus_free(bus);
        return rc;
index 963838d4fac12428e0c01f88537a72b4a2fd8703..599ce24c514f1b0eb1e8a6df1e3a0362f53bee26 100644 (file)
@@ -122,10 +122,9 @@ int mdio_mux_init(struct device *dev,
        pb = devm_kzalloc(dev, sizeof(*pb), GFP_KERNEL);
        if (pb == NULL) {
                ret_val = -ENOMEM;
-               goto err_parent_bus;
+               goto err_pb_kz;
        }
 
-
        pb->switch_data = data;
        pb->switch_fn = switch_fn;
        pb->current_child = -1;
@@ -154,6 +153,7 @@ int mdio_mux_init(struct device *dev,
                cb->mii_bus = mdiobus_alloc();
                if (!cb->mii_bus) {
                        ret_val = -ENOMEM;
+                       devm_kfree(dev, cb);
                        of_node_put(child_bus_node);
                        break;
                }
@@ -170,7 +170,6 @@ int mdio_mux_init(struct device *dev,
                        mdiobus_free(cb->mii_bus);
                        devm_kfree(dev, cb);
                } else {
-                       of_node_get(child_bus_node);
                        cb->next = pb->children;
                        pb->children = cb;
                }
@@ -181,9 +180,11 @@ int mdio_mux_init(struct device *dev,
                return 0;
        }
 
+       devm_kfree(dev, pb);
+err_pb_kz:
        /* balance the reference of_mdio_find_bus() took */
-       put_device(&pb->mii_bus->dev);
-
+       if (!mux_bus)
+               put_device(&parent_bus->dev);
 err_parent_bus:
        of_node_put(parent_bus_node);
        return ret_val;
index a898e5c4ef1b465768c3216fc1985382c23eba89..8e73f5f36e7120a5aa28b6e0dfb992eca3330e3e 100644 (file)
@@ -364,9 +364,6 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner)
 
        mutex_init(&bus->mdio_lock);
 
-       if (bus->reset)
-               bus->reset(bus);
-
        /* de-assert bus level PHY GPIO resets */
        if (bus->num_reset_gpios > 0) {
                bus->reset_gpiod = devm_kcalloc(&bus->dev,
@@ -396,6 +393,9 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner)
                }
        }
 
+       if (bus->reset)
+               bus->reset(bus);
+
        for (i = 0; i < PHY_MAX_ADDR; i++) {
                if ((bus->phy_mask & (1 << i)) == 0) {
                        struct phy_device *phydev;
index bb3f71f9fbde06ef1a8d514dbb856c8aa7ff5130..b5cec1824a7875842abaead1a888494e282f1741 100644 (file)
@@ -1088,6 +1088,7 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign)
        u16 n = 0, index, ndplen;
        u8 ready2send = 0;
        u32 delayed_ndp_size;
+       size_t padding_count;
 
        /* When our NDP gets written in cdc_ncm_ndp(), then skb_out->len gets updated
         * accordingly. Otherwise, we should check here.
@@ -1244,11 +1245,13 @@ cdc_ncm_fill_tx_frame(struct usbnet *dev, struct sk_buff *skb, __le32 sign)
         * a ZLP after full sized NTBs.
         */
        if (!(dev->driver_info->flags & FLAG_SEND_ZLP) &&
-           skb_out->len > ctx->min_tx_pkt)
-               memset(skb_put(skb_out, ctx->tx_max - skb_out->len), 0,
-                      ctx->tx_max - skb_out->len);
-       else if (skb_out->len < ctx->tx_max && (skb_out->len % dev->maxpacket) == 0)
+           skb_out->len > ctx->min_tx_pkt) {
+               padding_count = ctx->tx_max - skb_out->len;
+               memset(skb_put(skb_out, padding_count), 0, padding_count);
+       } else if (skb_out->len < ctx->tx_max &&
+                  (skb_out->len % dev->maxpacket) == 0) {
                *skb_put(skb_out, 1) = 0;       /* force short packet */
+       }
 
        /* set final frame length */
        nth16 = (struct usb_cdc_ncm_nth16 *)skb_out->data;
index c4f1c363e24b89404c6834312074f8a4451ded50..9df3c1ffff355c491ab7f0a38bdddd0276cfff92 100644 (file)
@@ -310,8 +310,8 @@ static int get_mac_address(struct usbnet *dev, unsigned char *data)
        int rd_mac_len = 0;
 
        netdev_dbg(dev->net, "get_mac_address:\n\tusbnet VID:%0x PID:%0x\n",
-                  dev->udev->descriptor.idVendor,
-                  dev->udev->descriptor.idProduct);
+                  le16_to_cpu(dev->udev->descriptor.idVendor),
+                  le16_to_cpu(dev->udev->descriptor.idProduct));
 
        memset(mac_addr, 0, sizeof(mac_addr));
        rd_mac_len = control_read(dev, REQUEST_READ, 0,
index d7165767ca9d380ed4ab03e0ac592a8ee3a69040..8f923a147fa93117296312c59fdc6761fef50f3c 100644 (file)
@@ -1196,6 +1196,8 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x1199, 0x9071, 10)},   /* Sierra Wireless MC74xx */
        {QMI_FIXED_INTF(0x1199, 0x9079, 8)},    /* Sierra Wireless EM74xx */
        {QMI_FIXED_INTF(0x1199, 0x9079, 10)},   /* Sierra Wireless EM74xx */
+       {QMI_FIXED_INTF(0x1199, 0x907b, 8)},    /* Sierra Wireless EM74xx */
+       {QMI_FIXED_INTF(0x1199, 0x907b, 10)},   /* Sierra Wireless EM74xx */
        {QMI_FIXED_INTF(0x1bbb, 0x011e, 4)},    /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */
        {QMI_FIXED_INTF(0x1bbb, 0x0203, 2)},    /* Alcatel L800MA */
        {QMI_FIXED_INTF(0x2357, 0x0201, 4)},    /* TP-LINK HSUPA Modem MA180 */
index 1c6d3923c224aad638802a8de531915c027f0b1b..9320d96a1632bbebe8bd1d4a04059e0df631ac19 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/slab.h>
 #include <linux/cpu.h>
 #include <linux/average.h>
+#include <net/route.h>
 
 static int napi_weight = NAPI_POLL_WEIGHT;
 module_param(napi_weight, int, 0444);
@@ -54,17 +55,6 @@ module_param(napi_tx, bool, 0644);
  */
 DECLARE_EWMA(pkt_len, 0, 64)
 
-/* With mergeable buffers we align buffer address and use the low bits to
- * encode its true size. Buffer size is up to 1 page so we need to align to
- * square root of page size to ensure we reserve enough bits to encode the true
- * size.
- */
-#define MERGEABLE_BUFFER_MIN_ALIGN_SHIFT ((PAGE_SHIFT + 1) / 2)
-
-/* Minimum alignment for mergeable packet buffers. */
-#define MERGEABLE_BUFFER_ALIGN max(L1_CACHE_BYTES, \
-                                  1 << MERGEABLE_BUFFER_MIN_ALIGN_SHIFT)
-
 #define VIRTNET_DRIVER_VERSION "1.0.0"
 
 struct virtnet_stats {
@@ -112,6 +102,9 @@ struct receive_queue {
        /* RX: fragments + linear part + virtio header */
        struct scatterlist sg[MAX_SKB_FRAGS + 2];
 
+       /* Min single buffer size for mergeable buffers case. */
+       unsigned int min_buf_len;
+
        /* Name of this receive queue: input.$index */
        char name[40];
 };
@@ -277,24 +270,6 @@ static void skb_xmit_done(struct virtqueue *vq)
                netif_wake_subqueue(vi->dev, vq2txq(vq));
 }
 
-static unsigned int mergeable_ctx_to_buf_truesize(unsigned long mrg_ctx)
-{
-       unsigned int truesize = mrg_ctx & (MERGEABLE_BUFFER_ALIGN - 1);
-       return (truesize + 1) * MERGEABLE_BUFFER_ALIGN;
-}
-
-static void *mergeable_ctx_to_buf_address(unsigned long mrg_ctx)
-{
-       return (void *)(mrg_ctx & -MERGEABLE_BUFFER_ALIGN);
-
-}
-
-static unsigned long mergeable_buf_to_ctx(void *buf, unsigned int truesize)
-{
-       unsigned int size = truesize / MERGEABLE_BUFFER_ALIGN;
-       return (unsigned long)buf | (size - 1);
-}
-
 /* Called from bottom half context */
 static struct sk_buff *page_to_skb(struct virtnet_info *vi,
                                   struct receive_queue *rq,
@@ -538,15 +513,13 @@ static struct page *xdp_linearize_page(struct receive_queue *rq,
 
        while (--*num_buf) {
                unsigned int buflen;
-               unsigned long ctx;
                void *buf;
                int off;
 
-               ctx = (unsigned long)virtqueue_get_buf(rq->vq, &buflen);
-               if (unlikely(!ctx))
+               buf = virtqueue_get_buf(rq->vq, &buflen);
+               if (unlikely(!buf))
                        goto err_buf;
 
-               buf = mergeable_ctx_to_buf_address(ctx);
                p = virt_to_head_page(buf);
                off = buf - page_address(p);
 
@@ -575,10 +548,10 @@ err_buf:
 static struct sk_buff *receive_mergeable(struct net_device *dev,
                                         struct virtnet_info *vi,
                                         struct receive_queue *rq,
-                                        unsigned long ctx,
+                                        void *buf,
+                                        void *ctx,
                                         unsigned int len)
 {
-       void *buf = mergeable_ctx_to_buf_address(ctx);
        struct virtio_net_hdr_mrg_rxbuf *hdr = buf;
        u16 num_buf = virtio16_to_cpu(vi->vdev, hdr->num_buffers);
        struct page *page = virt_to_head_page(buf);
@@ -666,7 +639,13 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
        }
        rcu_read_unlock();
 
-       truesize = max(len, mergeable_ctx_to_buf_truesize(ctx));
+       if (unlikely(len > (unsigned long)ctx)) {
+               pr_debug("%s: rx error: len %u exceeds truesize %lu\n",
+                        dev->name, len, (unsigned long)ctx);
+               dev->stats.rx_length_errors++;
+               goto err_skb;
+       }
+       truesize = (unsigned long)ctx;
        head_skb = page_to_skb(vi, rq, page, offset, len, truesize);
        curr_skb = head_skb;
 
@@ -675,7 +654,7 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
        while (--num_buf) {
                int num_skb_frags;
 
-               ctx = (unsigned long)virtqueue_get_buf(rq->vq, &len);
+               buf = virtqueue_get_buf_ctx(rq->vq, &len, &ctx);
                if (unlikely(!ctx)) {
                        pr_debug("%s: rx error: %d buffers out of %d missing\n",
                                 dev->name, num_buf,
@@ -685,8 +664,14 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
                        goto err_buf;
                }
 
-               buf = mergeable_ctx_to_buf_address(ctx);
                page = virt_to_head_page(buf);
+               if (unlikely(len > (unsigned long)ctx)) {
+                       pr_debug("%s: rx error: len %u exceeds truesize %lu\n",
+                                dev->name, len, (unsigned long)ctx);
+                       dev->stats.rx_length_errors++;
+                       goto err_skb;
+               }
+               truesize = (unsigned long)ctx;
 
                num_skb_frags = skb_shinfo(curr_skb)->nr_frags;
                if (unlikely(num_skb_frags == MAX_SKB_FRAGS)) {
@@ -702,7 +687,6 @@ static struct sk_buff *receive_mergeable(struct net_device *dev,
                        head_skb->truesize += nskb->truesize;
                        num_skb_frags = 0;
                }
-               truesize = max(len, mergeable_ctx_to_buf_truesize(ctx));
                if (curr_skb != head_skb) {
                        head_skb->data_len += len;
                        head_skb->len += len;
@@ -727,14 +711,14 @@ err_xdp:
 err_skb:
        put_page(page);
        while (--num_buf) {
-               ctx = (unsigned long)virtqueue_get_buf(rq->vq, &len);
-               if (unlikely(!ctx)) {
+               buf = virtqueue_get_buf(rq->vq, &len);
+               if (unlikely(!buf)) {
                        pr_debug("%s: rx error: %d buffers missing\n",
                                 dev->name, num_buf);
                        dev->stats.rx_length_errors++;
                        break;
                }
-               page = virt_to_head_page(mergeable_ctx_to_buf_address(ctx));
+               page = virt_to_head_page(buf);
                put_page(page);
        }
 err_buf:
@@ -745,7 +729,7 @@ xdp_xmit:
 }
 
 static int receive_buf(struct virtnet_info *vi, struct receive_queue *rq,
-                      void *buf, unsigned int len)
+                      void *buf, unsigned int len, void **ctx)
 {
        struct net_device *dev = vi->dev;
        struct sk_buff *skb;
@@ -756,9 +740,7 @@ static int receive_buf(struct virtnet_info *vi, struct receive_queue *rq,
                pr_debug("%s: short packet %i\n", dev->name, len);
                dev->stats.rx_length_errors++;
                if (vi->mergeable_rx_bufs) {
-                       unsigned long ctx = (unsigned long)buf;
-                       void *base = mergeable_ctx_to_buf_address(ctx);
-                       put_page(virt_to_head_page(base));
+                       put_page(virt_to_head_page(buf));
                } else if (vi->big_packets) {
                        give_pages(rq, buf);
                } else {
@@ -768,7 +750,7 @@ static int receive_buf(struct virtnet_info *vi, struct receive_queue *rq,
        }
 
        if (vi->mergeable_rx_bufs)
-               skb = receive_mergeable(dev, vi, rq, (unsigned long)buf, len);
+               skb = receive_mergeable(dev, vi, rq, buf, ctx, len);
        else if (vi->big_packets)
                skb = receive_big(dev, vi, rq, buf, len);
        else
@@ -880,14 +862,15 @@ static int add_recvbuf_big(struct virtnet_info *vi, struct receive_queue *rq,
        return err;
 }
 
-static unsigned int get_mergeable_buf_len(struct ewma_pkt_len *avg_pkt_len)
+static unsigned int get_mergeable_buf_len(struct receive_queue *rq,
+                                         struct ewma_pkt_len *avg_pkt_len)
 {
        const size_t hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf);
        unsigned int len;
 
        len = hdr_len + clamp_t(unsigned int, ewma_pkt_len_read(avg_pkt_len),
-                       GOOD_PACKET_LEN, PAGE_SIZE - hdr_len);
-       return ALIGN(len, MERGEABLE_BUFFER_ALIGN);
+                               rq->min_buf_len - hdr_len, PAGE_SIZE - hdr_len);
+       return ALIGN(len, L1_CACHE_BYTES);
 }
 
 static int add_recvbuf_mergeable(struct virtnet_info *vi,
@@ -896,17 +879,17 @@ static int add_recvbuf_mergeable(struct virtnet_info *vi,
        struct page_frag *alloc_frag = &rq->alloc_frag;
        unsigned int headroom = virtnet_get_headroom(vi);
        char *buf;
-       unsigned long ctx;
+       void *ctx;
        int err;
        unsigned int len, hole;
 
-       len = get_mergeable_buf_len(&rq->mrg_avg_pkt_len);
+       len = get_mergeable_buf_len(rq, &rq->mrg_avg_pkt_len);
        if (unlikely(!skb_page_frag_refill(len + headroom, alloc_frag, gfp)))
                return -ENOMEM;
 
        buf = (char *)page_address(alloc_frag->page) + alloc_frag->offset;
        buf += headroom; /* advance address leaving hole at front of pkt */
-       ctx = mergeable_buf_to_ctx(buf, len);
+       ctx = (void *)(unsigned long)len;
        get_page(alloc_frag->page);
        alloc_frag->offset += len + headroom;
        hole = alloc_frag->size - alloc_frag->offset;
@@ -921,7 +904,7 @@ static int add_recvbuf_mergeable(struct virtnet_info *vi,
        }
 
        sg_init_one(rq->sg, buf, len);
-       err = virtqueue_add_inbuf(rq->vq, rq->sg, 1, (void *)ctx, gfp);
+       err = virtqueue_add_inbuf_ctx(rq->vq, rq->sg, 1, buf, ctx, gfp);
        if (err < 0)
                put_page(virt_to_head_page(buf));
 
@@ -1032,10 +1015,20 @@ static int virtnet_receive(struct receive_queue *rq, int budget)
        void *buf;
        struct virtnet_stats *stats = this_cpu_ptr(vi->stats);
 
-       while (received < budget &&
-              (buf = virtqueue_get_buf(rq->vq, &len)) != NULL) {
-               bytes += receive_buf(vi, rq, buf, len);
-               received++;
+       if (vi->mergeable_rx_bufs) {
+               void *ctx;
+
+               while (received < budget &&
+                      (buf = virtqueue_get_buf_ctx(rq->vq, &len, &ctx))) {
+                       bytes += receive_buf(vi, rq, buf, len, ctx);
+                       received++;
+               }
+       } else {
+               while (received < budget &&
+                      (buf = virtqueue_get_buf(rq->vq, &len)) != NULL) {
+                       bytes += receive_buf(vi, rq, buf, len, NULL);
+                       received++;
+               }
        }
 
        if (rq->vq->num_free > virtqueue_get_vring_size(rq->vq) / 2) {
@@ -1854,7 +1847,6 @@ static int virtnet_reset(struct virtnet_info *vi, int curr_qp, int xdp_qp)
        virtnet_freeze_down(dev);
        _remove_vq_common(vi);
 
-       dev->config->reset(dev);
        virtio_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE);
        virtio_add_status(dev, VIRTIO_CONFIG_S_DRIVER);
 
@@ -2118,9 +2110,7 @@ static void free_unused_bufs(struct virtnet_info *vi)
 
                while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) {
                        if (vi->mergeable_rx_bufs) {
-                               unsigned long ctx = (unsigned long)buf;
-                               void *base = mergeable_ctx_to_buf_address(ctx);
-                               put_page(virt_to_head_page(base));
+                               put_page(virt_to_head_page(buf));
                        } else if (vi->big_packets) {
                                give_pages(&vi->rq[i], buf);
                        } else {
@@ -2141,6 +2131,21 @@ static void virtnet_del_vqs(struct virtnet_info *vi)
        virtnet_free_queues(vi);
 }
 
+/* How large should a single buffer be so a queue full of these can fit at
+ * least one full packet?
+ * Logic below assumes the mergeable buffer header is used.
+ */
+static unsigned int mergeable_min_buf_len(struct virtnet_info *vi, struct virtqueue *vq)
+{
+       const unsigned int hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf);
+       unsigned int rq_size = virtqueue_get_vring_size(vq);
+       unsigned int packet_len = vi->big_packets ? IP_MAX_MTU : vi->dev->max_mtu;
+       unsigned int buf_len = hdr_len + ETH_HLEN + VLAN_HLEN + packet_len;
+       unsigned int min_buf_len = DIV_ROUND_UP(buf_len, rq_size);
+
+       return max(min_buf_len, hdr_len);
+}
+
 static int virtnet_find_vqs(struct virtnet_info *vi)
 {
        vq_callback_t **callbacks;
@@ -2148,6 +2153,7 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
        int ret = -ENOMEM;
        int i, total_vqs;
        const char **names;
+       bool *ctx;
 
        /* We expect 1 RX virtqueue followed by 1 TX virtqueue, followed by
         * possible N-1 RX/TX queue pairs used in multiqueue mode, followed by
@@ -2166,6 +2172,13 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
        names = kmalloc(total_vqs * sizeof(*names), GFP_KERNEL);
        if (!names)
                goto err_names;
+       if (vi->mergeable_rx_bufs) {
+               ctx = kzalloc(total_vqs * sizeof(*ctx), GFP_KERNEL);
+               if (!ctx)
+                       goto err_ctx;
+       } else {
+               ctx = NULL;
+       }
 
        /* Parameters for control virtqueue, if any */
        if (vi->has_cvq) {
@@ -2181,10 +2194,12 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
                sprintf(vi->sq[i].name, "output.%d", i);
                names[rxq2vq(i)] = vi->rq[i].name;
                names[txq2vq(i)] = vi->sq[i].name;
+               if (ctx)
+                       ctx[rxq2vq(i)] = true;
        }
 
        ret = vi->vdev->config->find_vqs(vi->vdev, total_vqs, vqs, callbacks,
-                                        names, NULL);
+                                        names, ctx, NULL);
        if (ret)
                goto err_find;
 
@@ -2196,6 +2211,7 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
 
        for (i = 0; i < vi->max_queue_pairs; i++) {
                vi->rq[i].vq = vqs[rxq2vq(i)];
+               vi->rq[i].min_buf_len = mergeable_min_buf_len(vi, vi->rq[i].vq);
                vi->sq[i].vq = vqs[txq2vq(i)];
        }
 
@@ -2206,6 +2222,8 @@ static int virtnet_find_vqs(struct virtnet_info *vi)
        return 0;
 
 err_find:
+       kfree(ctx);
+err_ctx:
        kfree(names);
 err_names:
        kfree(callbacks);
@@ -2282,7 +2300,8 @@ static ssize_t mergeable_rx_buffer_size_show(struct netdev_rx_queue *queue,
 
        BUG_ON(queue_index >= vi->max_queue_pairs);
        avg = &vi->rq[queue_index].mrg_avg_pkt_len;
-       return sprintf(buf, "%u\n", get_mergeable_buf_len(avg));
+       return sprintf(buf, "%u\n",
+                      get_mergeable_buf_len(&vi->rq[queue_index], avg));
 }
 
 static struct rx_queue_attribute mergeable_rx_buffer_size_attribute =
index 25bc764ae7dc4c4dc9a5e6cb4f17f89f62464f4c..d1c7029ded7cefef468eb035f971b969da612bf5 100644 (file)
@@ -2962,6 +2962,11 @@ vmxnet3_force_close(struct vmxnet3_adapter *adapter)
        /* we need to enable NAPI, otherwise dev_close will deadlock */
        for (i = 0; i < adapter->num_rx_queues; i++)
                napi_enable(&adapter->rx_queue[i].napi);
+       /*
+        * Need to clear the quiesce bit to ensure that vmxnet3_close
+        * can quiesce the device properly
+        */
+       clear_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state);
        dev_close(adapter->netdev);
 }
 
index ceda5861da780bc64b6070acec7f37de9a8fa3e5..db882493875cd97d30ac5a2b26a764a5b65d9e2e 100644 (file)
@@ -989,6 +989,7 @@ static u32 vrf_fib_table(const struct net_device *dev)
 
 static int vrf_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
 {
+       kfree_skb(skb);
        return 0;
 }
 
@@ -998,7 +999,7 @@ static struct sk_buff *vrf_rcv_nfhook(u8 pf, unsigned int hook,
 {
        struct net *net = dev_net(dev);
 
-       if (NF_HOOK(pf, hook, net, NULL, skb, dev, NULL, vrf_rcv_finish) < 0)
+       if (nf_hook(pf, hook, net, NULL, skb, dev, NULL, vrf_rcv_finish) != 1)
                skb = NULL;    /* kfree_skb(skb) handled by nf code */
 
        return skb;
index 4ca71bca39acfcbf27b95779a625a23af9a12943..6ea16260ec7608030110aab0a7510995e8e2e298 100644 (file)
@@ -232,11 +232,11 @@ static int irq[MAX_CARDS+1] = { -1, -1, -1, -1, -1, -1, 0, };
 static struct class *cosa_class;
 
 #ifdef MODULE
-module_param_array(io, int, NULL, 0);
+module_param_hw_array(io, int, ioport, NULL, 0);
 MODULE_PARM_DESC(io, "The I/O bases of the COSA or SRP cards");
-module_param_array(irq, int, NULL, 0);
+module_param_hw_array(irq, int, irq, NULL, 0);
 MODULE_PARM_DESC(irq, "The IRQ lines of the COSA or SRP cards");
-module_param_array(dma, int, NULL, 0);
+module_param_hw_array(dma, int, dma, NULL, 0);
 MODULE_PARM_DESC(dma, "The DMA channels of the COSA or SRP cards");
 
 MODULE_AUTHOR("Jan \"Yenya\" Kasprzak, <kas@fi.muni.cz>");
index dd6bb3364ad2330ed662abbaaa192d9d24967f3d..4de0737fbf8a68e457eab0fb343b19b6b50a8e32 100644 (file)
@@ -324,11 +324,11 @@ static void sv11_shutdown(struct z8530_dev *dev)
 static int io = 0x200;
 static int irq = 9;
 
-module_param(io, int, 0);
+module_param_hw(io, int, ioport, 0);
 MODULE_PARM_DESC(io, "The I/O base of the Comtrol Hostess SV11 card");
-module_param(dma, int, 0);
+module_param_hw(dma, int, dma, 0);
 MODULE_PARM_DESC(dma, "Set this to 1 to use DMA1/DMA3 for TX/RX");
-module_param(irq, int, 0);
+module_param_hw(irq, int, irq, 0);
 MODULE_PARM_DESC(irq, "The interrupt line setting for the Comtrol Hostess SV11 card");
 
 MODULE_AUTHOR("Alan Cox");
index 3ca3419c54a047a635cdc585536ebeb4a0b38f0e..bde8c0339831934f43bfeb5bd5155802e94d5909 100644 (file)
@@ -1463,8 +1463,8 @@ set_multicast_list( struct net_device  *dev )
 
 
 #ifdef MODULE
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
+module_param_hw_array(io, int, ioport, NULL, 0);
+module_param_hw_array(irq, int, irq, NULL, 0);
 module_param_array(baud, int, NULL, 0);
 module_param_array(rxl, int, NULL, 0);
 module_param_array(mac, int, NULL, 0);
index fbb5aa2c4d8faf415c2463440f3adbfd5b0721c2..c56f2c252113a965845b1cc55c91fe412b672a85 100644 (file)
@@ -363,13 +363,13 @@ static int rxdma=3;
 static int irq=5;
 static bool slow=false;
 
-module_param(io, int, 0);
+module_param_hw(io, int, ioport, 0);
 MODULE_PARM_DESC(io, "The I/O base of the Sealevel card");
-module_param(txdma, int, 0);
+module_param_hw(txdma, int, dma, 0);
 MODULE_PARM_DESC(txdma, "Transmit DMA channel");
-module_param(rxdma, int, 0);
+module_param_hw(rxdma, int, dma, 0);
 MODULE_PARM_DESC(rxdma, "Receive DMA channel");
-module_param(irq, int, 0);
+module_param_hw(irq, int, irq, 0);
 MODULE_PARM_DESC(irq, "The interrupt line setting for the SeaLevel card");
 module_param(slow, bool, 0);
 MODULE_PARM_DESC(slow, "Set this for an older Sealevel card such as the 4012");
index 649ecad6844c73baa58a9e8b0e1850b9fdb88b36..eff4f464a23e14e92a7f57e77c08a6e1e6c8878c 100644 (file)
@@ -131,7 +131,7 @@ static inline int edc_inc(struct edc *edc, u16 max_err, u16 timeframe)
        unsigned long now;
 
        now = jiffies;
-       if (now - edc->timestart > timeframe) {
+       if (time_after(now, edc->timestart + timeframe)) {
                edc->errorcount = 1;
                edc->timestart = now;
        } else if (++edc->errorcount > max_err) {
index 68fcbe03bce2c2efd789de66d526f1cab91e3d9a..b3f20b3c02109e169d30bcef2fbcc621a6251277 100644 (file)
@@ -522,7 +522,7 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs,
        rxs->rs_moreaggr = (rxsp->status11 & AR_RxMoreAggr) ? 1 : 0;
        rxs->rs_antenna = (MS(rxsp->status4, AR_RxAntenna) & 0x7);
        rxs->enc_flags |= (rxsp->status4 & AR_GI) ? RX_ENC_FLAG_SHORT_GI : 0;
-       rxs->enc_flags |= (rxsp->status4 & AR_2040) ? RX_ENC_FLAG_40MHZ : 0;
+       rxs->bw = (rxsp->status4 & AR_2040) ? RATE_INFO_BW_40 : RATE_INFO_BW_20;
 
        rxs->evm0 = rxsp->status6;
        rxs->evm1 = rxsp->status7;
index 6128c2bb23d8d1a46b94f2bd68bffdfc52bfcedc..77c94f9e7b619248c23e11f0d619b3ada7b4747f 100644 (file)
@@ -580,8 +580,8 @@ int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds,
        /* directly mapped flags for ieee80211_rx_status */
        rs->enc_flags |=
                (ads.ds_rxstatus3 & AR_GI) ? RX_ENC_FLAG_SHORT_GI : 0;
-       rs->enc_flags |=
-               (ads.ds_rxstatus3 & AR_2040) ? RX_ENC_FLAG_40MHZ : 0;
+       rs->bw = (ads.ds_rxstatus3 & AR_2040) ? RATE_INFO_BW_40 :
+                                               RATE_INFO_BW_20;
        if (AR_SREV_9280_20_OR_LATER(ah))
                rs->enc_flags |=
                        (ads.ds_rxstatus3 & AR_STBC) ?
index 4b040451a9b8049265e4a460c314c893f924ab8d..1b7e125a28e2e0cb9ab02aea1b4ca8dd8f2fc45f 100644 (file)
@@ -246,8 +246,8 @@ MODULE_DESCRIPTION("Support for Cisco/Aironet 802.11 wireless ethernet cards.  "
                   "Direct support for ISA/PCI/MPI cards and support for PCMCIA when used with airo_cs.");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340/350");
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
+module_param_hw_array(io, int, ioport, NULL, 0);
+module_param_hw_array(irq, int, irq, NULL, 0);
 module_param_array(rates, int, NULL, 0);
 module_param_array(ssids, charp, NULL, 0);
 module_param(auto_wep, int, 0);
index 5d5faa3cad247b4a01b2bcf94fe10fedddbce54b..49a2ff15ddaead3a6f21b0d9ae801eb8383847d3 100644 (file)
@@ -734,7 +734,9 @@ il4965_hdl_rx(struct il_priv *il, struct il_rx_buf *rxb)
        if (rate_n_flags & RATE_MCS_HT_MSK)
                rx_status.encoding = RX_ENC_HT;
        if (rate_n_flags & RATE_MCS_HT40_MSK)
-               rx_status.enc_flags |= RX_ENC_FLAG_40MHZ;
+               rx_status.bw = RATE_INFO_BW_40;
+       else
+               rx_status.bw = RATE_INFO_BW_20;
        if (rate_n_flags & RATE_MCS_SGI_MSK)
                rx_status.enc_flags |= RX_ENC_FLAG_SHORT_GI;
 
index 1ee1ba9931a7b24af74015693bbf8b1b515ebe53..adfd6307edca9d21eb20f36994d10b2fb9c391a7 100644 (file)
@@ -889,7 +889,9 @@ static void iwlagn_rx_reply_rx(struct iwl_priv *priv,
        if (rate_n_flags & RATE_MCS_HT_MSK)
                rx_status.encoding = RX_ENC_HT;
        if (rate_n_flags & RATE_MCS_HT40_MSK)
-               rx_status.enc_flags |= RX_ENC_FLAG_40MHZ;
+               rx_status.bw = RATE_INFO_BW_40;
+       else
+               rx_status.bw = RATE_INFO_BW_20;
        if (rate_n_flags & RATE_MCS_SGI_MSK)
                rx_status.enc_flags |= RX_ENC_FLAG_SHORT_GI;
        if (rate_n_flags & RATE_MCS_GF_MSK)
index 87444af20fc5eb183784f9497869a59f8b6100b7..002b25cff5b65e18460a2da08637886274bfdfa5 100644 (file)
@@ -1201,7 +1201,13 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
                        rx_status.encoding = RX_ENC_HT;
        }
        if (info->control.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
-               rx_status.enc_flags |= RX_ENC_FLAG_40MHZ;
+               rx_status.bw = RATE_INFO_BW_40;
+       else if (info->control.rates[0].flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
+               rx_status.bw = RATE_INFO_BW_80;
+       else if (info->control.rates[0].flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
+               rx_status.bw = RATE_INFO_BW_160;
+       else
+               rx_status.bw = RATE_INFO_BW_20;
        if (info->control.rates[0].flags & IEEE80211_TX_RC_SHORT_GI)
                rx_status.enc_flags |= RX_ENC_FLAG_SHORT_GI;
        /* TODO: simulate real signal strength (and optional packet loss) */
index 6ffc482550c1d24f9b795f1ab3951101fd901f1c..7b61adb6270c99f8c70f1efa7575b1bb62d96f45 100644 (file)
@@ -1934,8 +1934,7 @@ abort_transaction_no_dev_fatal:
        xennet_disconnect_backend(info);
        xennet_destroy_queues(info);
  out:
-       unregister_netdev(info->netdev);
-       xennet_free_netdev(info->netdev);
+       device_unregister(&dev->dev);
        return err;
 }
 
index 9faaa9694d8741adb64b5aae8754f44d24a01e13..822198a75e96a599a7c9c55e14f61164bf35ba77 100644 (file)
@@ -218,7 +218,8 @@ static blk_qc_t nd_blk_make_request(struct request_queue *q, struct bio *bio)
 }
 
 static int nsblk_rw_bytes(struct nd_namespace_common *ndns,
-               resource_size_t offset, void *iobuf, size_t n, int rw)
+               resource_size_t offset, void *iobuf, size_t n, int rw,
+               unsigned long flags)
 {
        struct nd_namespace_blk *nsblk = to_nd_namespace_blk(&ndns->dev);
        struct nd_blk_region *ndbr = to_ndbr(nsblk);
index 368795aad5c974dbb59b1a43825b76c3e443acd2..983718b8fd9b44f9ab5af4dff0129fccc085689d 100644 (file)
@@ -32,45 +32,53 @@ enum log_ent_request {
 };
 
 static int arena_read_bytes(struct arena_info *arena, resource_size_t offset,
-               void *buf, size_t n)
+               void *buf, size_t n, unsigned long flags)
 {
        struct nd_btt *nd_btt = arena->nd_btt;
        struct nd_namespace_common *ndns = nd_btt->ndns;
 
        /* arena offsets are 4K from the base of the device */
        offset += SZ_4K;
-       return nvdimm_read_bytes(ndns, offset, buf, n);
+       return nvdimm_read_bytes(ndns, offset, buf, n, flags);
 }
 
 static int arena_write_bytes(struct arena_info *arena, resource_size_t offset,
-               void *buf, size_t n)
+               void *buf, size_t n, unsigned long flags)
 {
        struct nd_btt *nd_btt = arena->nd_btt;
        struct nd_namespace_common *ndns = nd_btt->ndns;
 
        /* arena offsets are 4K from the base of the device */
        offset += SZ_4K;
-       return nvdimm_write_bytes(ndns, offset, buf, n);
+       return nvdimm_write_bytes(ndns, offset, buf, n, flags);
 }
 
 static int btt_info_write(struct arena_info *arena, struct btt_sb *super)
 {
        int ret;
 
+       /*
+        * infooff and info2off should always be at least 512B aligned.
+        * We rely on that to make sure rw_bytes does error clearing
+        * correctly, so make sure that is the case.
+        */
+       WARN_ON_ONCE(!IS_ALIGNED(arena->infooff, 512));
+       WARN_ON_ONCE(!IS_ALIGNED(arena->info2off, 512));
+
        ret = arena_write_bytes(arena, arena->info2off, super,
-                       sizeof(struct btt_sb));
+                       sizeof(struct btt_sb), 0);
        if (ret)
                return ret;
 
        return arena_write_bytes(arena, arena->infooff, super,
-                       sizeof(struct btt_sb));
+                       sizeof(struct btt_sb), 0);
 }
 
 static int btt_info_read(struct arena_info *arena, struct btt_sb *super)
 {
        WARN_ON(!super);
        return arena_read_bytes(arena, arena->infooff, super,
-                       sizeof(struct btt_sb));
+                       sizeof(struct btt_sb), 0);
 }
 
 /*
@@ -79,16 +87,17 @@ static int btt_info_read(struct arena_info *arena, struct btt_sb *super)
  *   mapping is in little-endian
  *   mapping contains 'E' and 'Z' flags as desired
  */
-static int __btt_map_write(struct arena_info *arena, u32 lba, __le32 mapping)
+static int __btt_map_write(struct arena_info *arena, u32 lba, __le32 mapping,
+               unsigned long flags)
 {
        u64 ns_off = arena->mapoff + (lba * MAP_ENT_SIZE);
 
        WARN_ON(lba >= arena->external_nlba);
-       return arena_write_bytes(arena, ns_off, &mapping, MAP_ENT_SIZE);
+       return arena_write_bytes(arena, ns_off, &mapping, MAP_ENT_SIZE, flags);
 }
 
 static int btt_map_write(struct arena_info *arena, u32 lba, u32 mapping,
-                       u32 z_flag, u32 e_flag)
+                       u32 z_flag, u32 e_flag, unsigned long rwb_flags)
 {
        u32 ze;
        __le32 mapping_le;
@@ -127,11 +136,11 @@ static int btt_map_write(struct arena_info *arena, u32 lba, u32 mapping,
        }
 
        mapping_le = cpu_to_le32(mapping);
-       return __btt_map_write(arena, lba, mapping_le);
+       return __btt_map_write(arena, lba, mapping_le, rwb_flags);
 }
 
 static int btt_map_read(struct arena_info *arena, u32 lba, u32 *mapping,
-                       int *trim, int *error)
+                       int *trim, int *error, unsigned long rwb_flags)
 {
        int ret;
        __le32 in;
@@ -140,7 +149,7 @@ static int btt_map_read(struct arena_info *arena, u32 lba, u32 *mapping,
 
        WARN_ON(lba >= arena->external_nlba);
 
-       ret = arena_read_bytes(arena, ns_off, &in, MAP_ENT_SIZE);
+       ret = arena_read_bytes(arena, ns_off, &in, MAP_ENT_SIZE, rwb_flags);
        if (ret)
                return ret;
 
@@ -189,7 +198,7 @@ static int btt_log_read_pair(struct arena_info *arena, u32 lane,
        WARN_ON(!ent);
        return arena_read_bytes(arena,
                        arena->logoff + (2 * lane * LOG_ENT_SIZE), ent,
-                       2 * LOG_ENT_SIZE);
+                       2 * LOG_ENT_SIZE, 0);
 }
 
 static struct dentry *debugfs_root;
@@ -335,7 +344,7 @@ static int btt_log_read(struct arena_info *arena, u32 lane,
  * btt_flog_write is the wrapper for updating the freelist elements
  */
 static int __btt_log_write(struct arena_info *arena, u32 lane,
-                       u32 sub, struct log_entry *ent)
+                       u32 sub, struct log_entry *ent, unsigned long flags)
 {
        int ret;
        /*
@@ -350,13 +359,13 @@ static int __btt_log_write(struct arena_info *arena, u32 lane,
        void *src = ent;
 
        /* split the 16B write into atomic, durable halves */
-       ret = arena_write_bytes(arena, ns_off, src, log_half);
+       ret = arena_write_bytes(arena, ns_off, src, log_half, flags);
        if (ret)
                return ret;
 
        ns_off += log_half;
        src += log_half;
-       return arena_write_bytes(arena, ns_off, src, log_half);
+       return arena_write_bytes(arena, ns_off, src, log_half, flags);
 }
 
 static int btt_flog_write(struct arena_info *arena, u32 lane, u32 sub,
@@ -364,7 +373,7 @@ static int btt_flog_write(struct arena_info *arena, u32 lane, u32 sub,
 {
        int ret;
 
-       ret = __btt_log_write(arena, lane, sub, ent);
+       ret = __btt_log_write(arena, lane, sub, ent, NVDIMM_IO_ATOMIC);
        if (ret)
                return ret;
 
@@ -393,11 +402,19 @@ static int btt_map_init(struct arena_info *arena)
        if (!zerobuf)
                return -ENOMEM;
 
+       /*
+        * mapoff should always be at least 512B  aligned. We rely on that to
+        * make sure rw_bytes does error clearing correctly, so make sure that
+        * is the case.
+        */
+       WARN_ON_ONCE(!IS_ALIGNED(arena->mapoff, 512));
+
        while (mapsize) {
                size_t size = min(mapsize, chunk_size);
 
+               WARN_ON_ONCE(size < 512);
                ret = arena_write_bytes(arena, arena->mapoff + offset, zerobuf,
-                               size);
+                               size, 0);
                if (ret)
                        goto free;
 
@@ -417,26 +434,50 @@ static int btt_map_init(struct arena_info *arena)
  */
 static int btt_log_init(struct arena_info *arena)
 {
+       size_t logsize = arena->info2off - arena->logoff;
+       size_t chunk_size = SZ_4K, offset = 0;
+       struct log_entry log;
+       void *zerobuf;
        int ret;
        u32 i;
-       struct log_entry log, zerolog;
 
-       memset(&zerolog, 0, sizeof(zerolog));
+       zerobuf = kzalloc(chunk_size, GFP_KERNEL);
+       if (!zerobuf)
+               return -ENOMEM;
+       /*
+        * logoff should always be at least 512B  aligned. We rely on that to
+        * make sure rw_bytes does error clearing correctly, so make sure that
+        * is the case.
+        */
+       WARN_ON_ONCE(!IS_ALIGNED(arena->logoff, 512));
+
+       while (logsize) {
+               size_t size = min(logsize, chunk_size);
+
+               WARN_ON_ONCE(size < 512);
+               ret = arena_write_bytes(arena, arena->logoff + offset, zerobuf,
+                               size, 0);
+               if (ret)
+                       goto free;
+
+               offset += size;
+               logsize -= size;
+               cond_resched();
+       }
 
        for (i = 0; i < arena->nfree; i++) {
                log.lba = cpu_to_le32(i);
                log.old_map = cpu_to_le32(arena->external_nlba + i);
                log.new_map = cpu_to_le32(arena->external_nlba + i);
                log.seq = cpu_to_le32(LOG_SEQ_INIT);
-               ret = __btt_log_write(arena, i, 0, &log);
-               if (ret)
-                       return ret;
-               ret = __btt_log_write(arena, i, 1, &zerolog);
+               ret = __btt_log_write(arena, i, 0, &log, 0);
                if (ret)
-                       return ret;
+                       goto free;
        }
 
-       return 0;
+ free:
+       kfree(zerobuf);
+       return ret;
 }
 
 static int btt_freelist_init(struct arena_info *arena)
@@ -470,7 +511,7 @@ static int btt_freelist_init(struct arena_info *arena)
 
                /* Check if map recovery is needed */
                ret = btt_map_read(arena, le32_to_cpu(log_new.lba), &map_entry,
-                               NULL, NULL);
+                               NULL, NULL, 0);
                if (ret)
                        return ret;
                if ((le32_to_cpu(log_new.new_map) != map_entry) &&
@@ -480,7 +521,7 @@ static int btt_freelist_init(struct arena_info *arena)
                         * to complete the map write. So fix up the map.
                         */
                        ret = btt_map_write(arena, le32_to_cpu(log_new.lba),
-                                       le32_to_cpu(log_new.new_map), 0, 0);
+                                       le32_to_cpu(log_new.new_map), 0, 0, 0);
                        if (ret)
                                return ret;
                }
@@ -875,7 +916,7 @@ static int btt_data_read(struct arena_info *arena, struct page *page,
        u64 nsoff = to_namespace_offset(arena, lba);
        void *mem = kmap_atomic(page);
 
-       ret = arena_read_bytes(arena, nsoff, mem + off, len);
+       ret = arena_read_bytes(arena, nsoff, mem + off, len, NVDIMM_IO_ATOMIC);
        kunmap_atomic(mem);
 
        return ret;
@@ -888,7 +929,7 @@ static int btt_data_write(struct arena_info *arena, u32 lba,
        u64 nsoff = to_namespace_offset(arena, lba);
        void *mem = kmap_atomic(page);
 
-       ret = arena_write_bytes(arena, nsoff, mem + off, len);
+       ret = arena_write_bytes(arena, nsoff, mem + off, len, NVDIMM_IO_ATOMIC);
        kunmap_atomic(mem);
 
        return ret;
@@ -931,10 +972,12 @@ static int btt_rw_integrity(struct btt *btt, struct bio_integrity_payload *bip,
                mem = kmap_atomic(bv.bv_page);
                if (rw)
                        ret = arena_write_bytes(arena, meta_nsoff,
-                                       mem + bv.bv_offset, cur_len);
+                                       mem + bv.bv_offset, cur_len,
+                                       NVDIMM_IO_ATOMIC);
                else
                        ret = arena_read_bytes(arena, meta_nsoff,
-                                       mem + bv.bv_offset, cur_len);
+                                       mem + bv.bv_offset, cur_len,
+                                       NVDIMM_IO_ATOMIC);
 
                kunmap_atomic(mem);
                if (ret)
@@ -976,7 +1019,8 @@ static int btt_read_pg(struct btt *btt, struct bio_integrity_payload *bip,
 
                cur_len = min(btt->sector_size, len);
 
-               ret = btt_map_read(arena, premap, &postmap, &t_flag, &e_flag);
+               ret = btt_map_read(arena, premap, &postmap, &t_flag, &e_flag,
+                               NVDIMM_IO_ATOMIC);
                if (ret)
                        goto out_lane;
 
@@ -1006,7 +1050,7 @@ static int btt_read_pg(struct btt *btt, struct bio_integrity_payload *bip,
                        barrier();
 
                        ret = btt_map_read(arena, premap, &new_map, &t_flag,
-                                               &e_flag);
+                                               &e_flag, NVDIMM_IO_ATOMIC);
                        if (ret)
                                goto out_rtt;
 
@@ -1093,7 +1137,8 @@ static int btt_write_pg(struct btt *btt, struct bio_integrity_payload *bip,
                }
 
                lock_map(arena, premap);
-               ret = btt_map_read(arena, premap, &old_postmap, NULL, NULL);
+               ret = btt_map_read(arena, premap, &old_postmap, NULL, NULL,
+                               NVDIMM_IO_ATOMIC);
                if (ret)
                        goto out_map;
                if (old_postmap >= arena->internal_nlba) {
@@ -1110,7 +1155,7 @@ static int btt_write_pg(struct btt *btt, struct bio_integrity_payload *bip,
                if (ret)
                        goto out_map;
 
-               ret = btt_map_write(arena, premap, new_postmap, 0, 0);
+               ret = btt_map_write(arena, premap, new_postmap, 0, 0, 0);
                if (ret)
                        goto out_map;
 
index 4b76af2b8715993a25ba8e8899a3ad9ab1c64cfd..ae00dc0d97917392cd3f447d1e3bb937a1a67253 100644 (file)
@@ -273,7 +273,7 @@ static int __nd_btt_probe(struct nd_btt *nd_btt,
        if (!btt_sb || !ndns || !nd_btt)
                return -ENODEV;
 
-       if (nvdimm_read_bytes(ndns, SZ_4K, btt_sb, sizeof(*btt_sb)))
+       if (nvdimm_read_bytes(ndns, SZ_4K, btt_sb, sizeof(*btt_sb), 0))
                return -ENXIO;
 
        if (nvdimm_namespace_capacity(ndns) < SZ_16M)
index 93d128da1c922e1740b9891d1454afeef0899201..7ceb5fa4f2a1343c0136cb56cdf887b4aeabac65 100644 (file)
@@ -228,7 +228,8 @@ u64 nd_sb_checksum(struct nd_gen_sb *nd_gen_sb)
 EXPORT_SYMBOL(nd_sb_checksum);
 
 static int nsio_rw_bytes(struct nd_namespace_common *ndns,
-               resource_size_t offset, void *buf, size_t size, int rw)
+               resource_size_t offset, void *buf, size_t size, int rw,
+               unsigned long flags)
 {
        struct nd_namespace_io *nsio = to_nd_namespace_io(&ndns->dev);
        unsigned int sz_align = ALIGN(size + (offset & (512 - 1)), 512);
@@ -259,7 +260,8 @@ static int nsio_rw_bytes(struct nd_namespace_common *ndns,
                 * work around this collision.
                 */
                if (IS_ALIGNED(offset, 512) && IS_ALIGNED(size, 512)
-                               && (!ndns->claim || !is_nd_btt(ndns->claim))) {
+                               && !(flags & NVDIMM_IO_ATOMIC)
+                               && !ndns->claim) {
                        long cleared;
 
                        cleared = nvdimm_clear_poison(&ndns->dev,
index fac1e9fbd11d8dbcfbb1ca2d0ca868f83b1073e7..9852a335550958c8f47c7c027089133fbde9e5cb 100644 (file)
@@ -106,10 +106,7 @@ int nvdimm_init_config_data(struct nvdimm_drvdata *ndd)
                return -ENXIO;
        }
 
-       ndd->data = kmalloc(ndd->nsarea.config_size, GFP_KERNEL);
-       if (!ndd->data)
-               ndd->data = vmalloc(ndd->nsarea.config_size);
-
+       ndd->data = kvmalloc(ndd->nsarea.config_size, GFP_KERNEL);
        if (!ndd->data)
                return -ENOMEM;
 
index 77d032192bf7d6c11e97b9afb345272b1f3f50ff..03852d738eec14a39b5826472db732e11b791743 100644 (file)
@@ -31,6 +31,7 @@ enum {
        ND_MAX_LANES = 256,
        SECTOR_SHIFT = 9,
        INT_LBASIZE_ALIGNMENT = 64,
+       NVDIMM_IO_ATOMIC = 1,
 };
 
 struct nd_poison {
index 335c8175410bae4f95321c94906bdedb7b709944..a6c403600d19c9b51edcb6a44639c278aa640dfe 100644 (file)
@@ -357,7 +357,7 @@ int nd_pfn_validate(struct nd_pfn *nd_pfn, const char *sig)
        if (!is_nd_pmem(nd_pfn->dev.parent))
                return -ENODEV;
 
-       if (nvdimm_read_bytes(ndns, SZ_4K, pfn_sb, sizeof(*pfn_sb)))
+       if (nvdimm_read_bytes(ndns, SZ_4K, pfn_sb, sizeof(*pfn_sb), 0))
                return -ENXIO;
 
        if (memcmp(pfn_sb->signature, sig, PFN_SIG_LEN) != 0)
@@ -662,7 +662,7 @@ static int nd_pfn_init(struct nd_pfn *nd_pfn)
        checksum = nd_sb_checksum((struct nd_gen_sb *) pfn_sb);
        pfn_sb->checksum = cpu_to_le64(checksum);
 
-       return nvdimm_write_bytes(ndns, SZ_4K, pfn_sb, sizeof(*pfn_sb));
+       return nvdimm_write_bytes(ndns, SZ_4K, pfn_sb, sizeof(*pfn_sb), 0);
 }
 
 /*
index 8c4adac6fafcc56dfe37d05a51f45798e5194652..f5df78ed1e10974ffb9e239b57ce260f0bb5bae9 100644 (file)
@@ -367,7 +367,8 @@ static int nvme_nvm_get_l2p_tbl(struct nvm_dev *nvmdev, u64 slba, u32 nlb,
 
                if (unlikely(elba > nvmdev->total_secs)) {
                        pr_err("nvm: L2P data from device is out of bounds!\n");
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       goto out;
                }
 
                /* Transform physical address to target address space */
@@ -464,8 +465,8 @@ static int nvme_nvm_set_bb_tbl(struct nvm_dev *nvmdev, struct ppa_addr *ppas,
        return ret;
 }
 
-static inline void nvme_nvm_rqtocmd(struct request *rq, struct nvm_rq *rqd,
-                               struct nvme_ns *ns, struct nvme_nvm_command *c)
+static inline void nvme_nvm_rqtocmd(struct nvm_rq *rqd, struct nvme_ns *ns,
+                                   struct nvme_nvm_command *c)
 {
        c->ph_rw.opcode = rqd->opcode;
        c->ph_rw.nsid = cpu_to_le32(ns->ns_id);
@@ -503,7 +504,7 @@ static int nvme_nvm_submit_io(struct nvm_dev *dev, struct nvm_rq *rqd)
        if (!cmd)
                return -ENOMEM;
 
-       nvme_nvm_rqtocmd(rq, rqd, ns, cmd);
+       nvme_nvm_rqtocmd(rqd, ns, cmd);
 
        rq = nvme_alloc_request(q, (struct nvme_command *)cmd, 0, NVME_QID_ANY);
        if (IS_ERR(rq)) {
index 56a315bd4d9627213e8a49a13ade68da74007a88..fed803232edccbdf63139d89028c694efff52409 100644 (file)
@@ -132,7 +132,6 @@ static inline struct nvme_dev *to_nvme_dev(struct nvme_ctrl *ctrl)
 struct nvme_queue {
        struct device *q_dmadev;
        struct nvme_dev *dev;
-       char irqname[24];       /* nvme4294967295-65535\0 */
        spinlock_t q_lock;
        struct nvme_command *sq_cmds;
        struct nvme_command __iomem *sq_cmds_io;
@@ -329,11 +328,6 @@ static unsigned int nvme_cmd_size(struct nvme_dev *dev)
                nvme_iod_alloc_size(dev, NVME_INT_BYTES(dev), NVME_INT_PAGES);
 }
 
-static int nvmeq_irq(struct nvme_queue *nvmeq)
-{
-       return pci_irq_vector(to_pci_dev(nvmeq->dev->dev), nvmeq->cq_vector);
-}
-
 static int nvme_admin_init_hctx(struct blk_mq_hw_ctx *hctx, void *data,
                                unsigned int hctx_idx)
 {
@@ -1078,7 +1072,7 @@ static int nvme_suspend_queue(struct nvme_queue *nvmeq)
                spin_unlock_irq(&nvmeq->q_lock);
                return 1;
        }
-       vector = nvmeq_irq(nvmeq);
+       vector = nvmeq->cq_vector;
        nvmeq->dev->online_queues--;
        nvmeq->cq_vector = -1;
        spin_unlock_irq(&nvmeq->q_lock);
@@ -1086,7 +1080,7 @@ static int nvme_suspend_queue(struct nvme_queue *nvmeq)
        if (!nvmeq->qid && nvmeq->dev->ctrl.admin_q)
                blk_mq_stop_hw_queues(nvmeq->dev->ctrl.admin_q);
 
-       free_irq(vector, nvmeq);
+       pci_free_irq(to_pci_dev(nvmeq->dev->dev), vector, nvmeq);
 
        return 0;
 }
@@ -1171,8 +1165,6 @@ static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev, int qid,
 
        nvmeq->q_dmadev = dev->dev;
        nvmeq->dev = dev;
-       snprintf(nvmeq->irqname, sizeof(nvmeq->irqname), "nvme%dq%d",
-                       dev->ctrl.instance, qid);
        spin_lock_init(&nvmeq->q_lock);
        nvmeq->cq_head = 0;
        nvmeq->cq_phase = 1;
@@ -1195,12 +1187,16 @@ static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev, int qid,
 
 static int queue_request_irq(struct nvme_queue *nvmeq)
 {
-       if (use_threaded_interrupts)
-               return request_threaded_irq(nvmeq_irq(nvmeq), nvme_irq_check,
-                               nvme_irq, IRQF_SHARED, nvmeq->irqname, nvmeq);
-       else
-               return request_irq(nvmeq_irq(nvmeq), nvme_irq, IRQF_SHARED,
-                               nvmeq->irqname, nvmeq);
+       struct pci_dev *pdev = to_pci_dev(nvmeq->dev->dev);
+       int nr = nvmeq->dev->ctrl.instance;
+
+       if (use_threaded_interrupts) {
+               return pci_request_irq(pdev, nvmeq->cq_vector, nvme_irq_check,
+                               nvme_irq, nvmeq, "nvme%dq%d", nr, nvmeq->qid);
+       } else {
+               return pci_request_irq(pdev, nvmeq->cq_vector, nvme_irq,
+                               NULL, nvmeq, "nvme%dq%d", nr, nvmeq->qid);
+       }
 }
 
 static void nvme_init_queue(struct nvme_queue *nvmeq, u16 qid)
@@ -1557,7 +1553,7 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
        }
 
        /* Deregister the admin queue's interrupt */
-       free_irq(pci_irq_vector(pdev, 0), adminq);
+       pci_free_irq(pdev, 0, adminq);
 
        /*
         * If we enable msix early due to not intx, disable it again before
index f207c3b1048200d6a37586de7acaf5071a9bf2c0..70bfc9839bb2fede6ec424f23d933805ba3f4812 100644 (file)
@@ -27,7 +27,7 @@ static int meson_efuse_read(void *context, unsigned int offset,
        u8 *buf = val;
        int ret;
 
-       ret = meson_sm_call_read(buf, SM_EFUSE_READ, offset,
+       ret = meson_sm_call_read(buf, bytes, SM_EFUSE_READ, offset,
                                 bytes, 0, 0, 0);
        if (ret < 0)
                return ret;
index 6e2f9113b1b7ab18706b1b763699669e883533c2..9416d052cb89474e811d8c4e8ca5ca3a81732fbb 100644 (file)
@@ -82,7 +82,7 @@ int of_device_add(struct platform_device *ofdev)
  * can use a platform bus notifier and handle BUS_NOTIFY_ADD_DEVICE events
  * to fix up DMA configuration.
  */
-void of_dma_configure(struct device *dev, struct device_node *np)
+int of_dma_configure(struct device *dev, struct device_node *np)
 {
        u64 dma_addr, paddr, size;
        int ret;
@@ -107,7 +107,7 @@ void of_dma_configure(struct device *dev, struct device_node *np)
        ret = of_dma_get_range(np, &dma_addr, &paddr, &size);
        if (ret < 0) {
                dma_addr = offset = 0;
-               size = dev->coherent_dma_mask + 1;
+               size = max(dev->coherent_dma_mask, dev->coherent_dma_mask + 1);
        } else {
                offset = PFN_DOWN(paddr - dma_addr);
 
@@ -123,7 +123,7 @@ void of_dma_configure(struct device *dev, struct device_node *np)
 
                if (!size) {
                        dev_err(dev, "Adjusted size 0x%llx invalid\n", size);
-                       return;
+                       return -EINVAL;
                }
                dev_dbg(dev, "dma_pfn_offset(%#08lx)\n", offset);
        }
@@ -144,13 +144,30 @@ void of_dma_configure(struct device *dev, struct device_node *np)
                coherent ? " " : " not ");
 
        iommu = of_iommu_configure(dev, np);
+       if (IS_ERR(iommu))
+               return PTR_ERR(iommu);
+
        dev_dbg(dev, "device is%sbehind an iommu\n",
                iommu ? " " : " not ");
 
        arch_setup_dma_ops(dev, dma_addr, size, iommu, coherent);
+
+       return 0;
 }
 EXPORT_SYMBOL_GPL(of_dma_configure);
 
+/**
+ * of_dma_deconfigure - Clean up DMA configuration
+ * @dev:       Device for which to clean up DMA configuration
+ *
+ * Clean up all configuration performed by of_dma_configure_ops() and free all
+ * resources that have been allocated.
+ */
+void of_dma_deconfigure(struct device *dev)
+{
+       arch_teardown_dma_ops(dev);
+}
+
 int of_device_register(struct platform_device *pdev)
 {
        device_initialize(&pdev->dev);
index a0972219ccfc5fccee139c46d9f4fd97445973e2..43bd69dceabfd36b43368366b8afdc9fa2b30106 100644 (file)
@@ -507,6 +507,9 @@ void *__unflatten_device_tree(const void *blob,
 
        /* Allocate memory for the expanded device tree */
        mem = dt_alloc(size + 4, __alignof__(struct device_node));
+       if (!mem)
+               return NULL;
+
        memset(mem, 0, size);
 
        *(__be32 *)(mem + size) = cpu_to_be32(0xdeadbeef);
@@ -755,6 +758,36 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node,
        return rc;
 }
 
+/**
+ * of_scan_flat_dt_subnodes - scan sub-nodes of a node call callback on each.
+ * @it: callback function
+ * @data: context data pointer
+ *
+ * This function is used to scan sub-nodes of a node.
+ */
+int __init of_scan_flat_dt_subnodes(unsigned long parent,
+                                   int (*it)(unsigned long node,
+                                             const char *uname,
+                                             void *data),
+                                   void *data)
+{
+       const void *blob = initial_boot_params;
+       int node;
+
+       fdt_for_each_subnode(node, blob, parent) {
+               const char *pathp;
+               int rc;
+
+               pathp = fdt_get_name(blob, node, NULL);
+               if (*pathp == '/')
+                       pathp = kbasename(pathp);
+               rc = it(node, pathp, data);
+               if (rc)
+                       return rc;
+       }
+       return 0;
+}
+
 /**
  * of_get_flat_dt_subnode_by_name - get the subnode by given name
  *
@@ -814,6 +847,14 @@ int __init of_flat_dt_match(unsigned long node, const char *const *compat)
        return of_fdt_match(initial_boot_params, node, compat);
 }
 
+/**
+ * of_get_flat_dt_prop - Given a node in the flat blob, return the phandle
+ */
+uint32_t __init of_get_flat_dt_phandle(unsigned long node)
+{
+       return fdt_get_phandle(initial_boot_params, node);
+}
+
 struct fdt_scan_status {
        const char *name;
        int namelen;
index 0ee42c3e66a1900db49408577c8ae69e698e7223..c9d4d3a7b0fecba0d73cb5642b7be789b6f035ad 100644 (file)
@@ -285,51 +285,6 @@ parse_failed:
 EXPORT_SYMBOL_GPL(of_pci_get_host_bridge_resources);
 #endif /* CONFIG_OF_ADDRESS */
 
-#ifdef CONFIG_PCI_MSI
-
-static LIST_HEAD(of_pci_msi_chip_list);
-static DEFINE_MUTEX(of_pci_msi_chip_mutex);
-
-int of_pci_msi_chip_add(struct msi_controller *chip)
-{
-       if (!of_property_read_bool(chip->of_node, "msi-controller"))
-               return -EINVAL;
-
-       mutex_lock(&of_pci_msi_chip_mutex);
-       list_add(&chip->list, &of_pci_msi_chip_list);
-       mutex_unlock(&of_pci_msi_chip_mutex);
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(of_pci_msi_chip_add);
-
-void of_pci_msi_chip_remove(struct msi_controller *chip)
-{
-       mutex_lock(&of_pci_msi_chip_mutex);
-       list_del(&chip->list);
-       mutex_unlock(&of_pci_msi_chip_mutex);
-}
-EXPORT_SYMBOL_GPL(of_pci_msi_chip_remove);
-
-struct msi_controller *of_pci_find_msi_chip_by_node(struct device_node *of_node)
-{
-       struct msi_controller *c;
-
-       mutex_lock(&of_pci_msi_chip_mutex);
-       list_for_each_entry(c, &of_pci_msi_chip_list, list) {
-               if (c->of_node == of_node) {
-                       mutex_unlock(&of_pci_msi_chip_mutex);
-                       return c;
-               }
-       }
-       mutex_unlock(&of_pci_msi_chip_mutex);
-
-       return NULL;
-}
-EXPORT_SYMBOL_GPL(of_pci_find_msi_chip_by_node);
-
-#endif /* CONFIG_PCI_MSI */
-
 /**
  * of_pci_map_rid - Translate a requester ID through a downstream mapping.
  * @np: root complex device node.
index 4dec07ea510f5fd67f38fa798727bdffef6c3168..d507c3569a88acac9e796f1f172f412e5386347f 100644 (file)
@@ -197,7 +197,7 @@ static int __init __reserved_mem_init_node(struct reserved_mem *rmem)
        const struct of_device_id *i;
 
        for (i = __reservedmem_of_table; i < &__rmem_of_table_sentinel; i++) {
-               int const (*initfn)(struct reserved_mem *rmem) = i->data;
+               reservedmem_of_init_fn initfn = i->data;
                const char *compat = i->compatible;
 
                if (!of_flat_dt_is_compatible(rmem->fdt_node, compat))
index 45b413e5a4447fea8c5e2355f438ba6ba8de9ca7..71fecc2debfc940affba38afc6c912f3a4aa8b4b 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/slab.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
+#include <linux/of_iommu.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/platform_device.h>
@@ -158,11 +159,6 @@ struct platform_device *of_device_alloc(struct device_node *np,
 }
 EXPORT_SYMBOL(of_device_alloc);
 
-static void of_dma_deconfigure(struct device *dev)
-{
-       arch_teardown_dma_ops(dev);
-}
-
 /**
  * of_platform_device_create_pdata - Alloc, initialize and register an of_device
  * @np: pointer to node to create device for
@@ -191,11 +187,9 @@ static struct platform_device *of_platform_device_create_pdata(
 
        dev->dev.bus = &platform_bus_type;
        dev->dev.platform_data = platform_data;
-       of_dma_configure(&dev->dev, dev->dev.of_node);
        of_msi_configure(&dev->dev, dev->dev.of_node);
 
        if (of_device_add(dev) != 0) {
-               of_dma_deconfigure(&dev->dev);
                platform_device_put(dev);
                goto err_clear_flag;
        }
@@ -253,7 +247,6 @@ static struct amba_device *of_amba_device_create(struct device_node *node,
                dev_set_name(&dev->dev, "%s", bus_id);
        else
                of_device_make_bus_id(&dev->dev);
-       of_dma_configure(&dev->dev, dev->dev.of_node);
 
        /* Allow the HW Peripheral ID to be overridden */
        prop = of_get_property(node, "arm,primecell-periphid", NULL);
@@ -547,7 +540,6 @@ static int of_platform_device_destroy(struct device *dev, void *data)
                amba_device_unregister(to_amba_device(dev));
 #endif
 
-       of_dma_deconfigure(dev);
        of_node_clear_flag(dev->of_node, OF_POPULATED);
        of_node_clear_flag(dev->of_node, OF_POPULATED_BUS);
        return 0;
index 9d42dfe65d448aa8e85c8737fae6ba4065e5a421..5548193a28a651272f6f6eedda7a1085caab4219 100644 (file)
@@ -3150,13 +3150,13 @@ static char *irq[PARPORT_PC_MAX_PORTS];
 static char *dma[PARPORT_PC_MAX_PORTS];
 
 MODULE_PARM_DESC(io, "Base I/O address (SPP regs)");
-module_param_array(io, int, NULL, 0);
+module_param_hw_array(io, int, ioport, NULL, 0);
 MODULE_PARM_DESC(io_hi, "Base I/O address (ECR)");
-module_param_array(io_hi, int, NULL, 0);
+module_param_hw_array(io_hi, int, ioport, NULL, 0);
 MODULE_PARM_DESC(irq, "IRQ line");
-module_param_array(irq, charp, NULL, 0);
+module_param_hw_array(irq, charp, irq, NULL, 0);
 MODULE_PARM_DESC(dma, "DMA channel");
-module_param_array(dma, charp, NULL, 0);
+module_param_hw_array(dma, charp, dma, NULL, 0);
 #if defined(CONFIG_PARPORT_PC_SUPERIO) || \
        (defined(CONFIG_PARPORT_1284) && defined(CONFIG_PARPORT_PC_FIFO))
 MODULE_PARM_DESC(verbose_probing, "Log chit-chat during initialisation");
index df141420c902ae5ea45972021a121ac6917cd119..e0cacb7b8563468fe9ce98ed603e176f267c7ac7 100644 (file)
@@ -134,3 +134,5 @@ config PCI_HYPERV
 source "drivers/pci/hotplug/Kconfig"
 source "drivers/pci/dwc/Kconfig"
 source "drivers/pci/host/Kconfig"
+source "drivers/pci/endpoint/Kconfig"
+source "drivers/pci/switch/Kconfig"
index 8db5079f09a7826bdf66dc94f02c19e902f99e6e..462c1f5f554689188791edb9461b27174fb56f72 100644 (file)
@@ -4,7 +4,7 @@
 
 obj-y          += access.o bus.o probe.o host-bridge.o remove.o pci.o \
                        pci-driver.o search.o pci-sysfs.o rom.o setup-res.o \
-                       irq.o vpd.o setup-bus.o vc.o
+                       irq.o vpd.o setup-bus.o vc.o mmap.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_SYSFS) += slot.o
 
@@ -68,3 +68,4 @@ ccflags-$(CONFIG_PCI_DEBUG) := -DDEBUG
 
 # PCI host controller drivers
 obj-y += host/
+obj-y += switch/
index 8b7382705bf27e3e8e315bbbd539ae6222f56318..74cf5fffb1e1b93fdb1a6d44002d7727544195e7 100644 (file)
@@ -629,7 +629,7 @@ void pci_vpd_release(struct pci_dev *dev)
  *
  * When access is locked, any userspace reads or writes to config
  * space and concurrent lock requests will sleep until access is
- * allowed via pci_cfg_access_unlocked again.
+ * allowed via pci_cfg_access_unlock() again.
  */
 void pci_cfg_access_lock(struct pci_dev *dev)
 {
@@ -700,7 +700,8 @@ static bool pcie_downstream_port(const struct pci_dev *dev)
        int type = pci_pcie_type(dev);
 
        return type == PCI_EXP_TYPE_ROOT_PORT ||
-              type == PCI_EXP_TYPE_DOWNSTREAM;
+              type == PCI_EXP_TYPE_DOWNSTREAM ||
+              type == PCI_EXP_TYPE_PCIE_BRIDGE;
 }
 
 bool pcie_cap_has_lnkctl(const struct pci_dev *dev)
@@ -890,3 +891,59 @@ int pcie_capability_clear_and_set_dword(struct pci_dev *dev, int pos,
        return ret;
 }
 EXPORT_SYMBOL(pcie_capability_clear_and_set_dword);
+
+int pci_read_config_byte(const struct pci_dev *dev, int where, u8 *val)
+{
+       if (pci_dev_is_disconnected(dev)) {
+               *val = ~0;
+               return -ENODEV;
+       }
+       return pci_bus_read_config_byte(dev->bus, dev->devfn, where, val);
+}
+EXPORT_SYMBOL(pci_read_config_byte);
+
+int pci_read_config_word(const struct pci_dev *dev, int where, u16 *val)
+{
+       if (pci_dev_is_disconnected(dev)) {
+               *val = ~0;
+               return -ENODEV;
+       }
+       return pci_bus_read_config_word(dev->bus, dev->devfn, where, val);
+}
+EXPORT_SYMBOL(pci_read_config_word);
+
+int pci_read_config_dword(const struct pci_dev *dev, int where,
+                                       u32 *val)
+{
+       if (pci_dev_is_disconnected(dev)) {
+               *val = ~0;
+               return -ENODEV;
+       }
+       return pci_bus_read_config_dword(dev->bus, dev->devfn, where, val);
+}
+EXPORT_SYMBOL(pci_read_config_dword);
+
+int pci_write_config_byte(const struct pci_dev *dev, int where, u8 val)
+{
+       if (pci_dev_is_disconnected(dev))
+               return -ENODEV;
+       return pci_bus_write_config_byte(dev->bus, dev->devfn, where, val);
+}
+EXPORT_SYMBOL(pci_write_config_byte);
+
+int pci_write_config_word(const struct pci_dev *dev, int where, u16 val)
+{
+       if (pci_dev_is_disconnected(dev))
+               return -ENODEV;
+       return pci_bus_write_config_word(dev->bus, dev->devfn, where, val);
+}
+EXPORT_SYMBOL(pci_write_config_word);
+
+int pci_write_config_dword(const struct pci_dev *dev, int where,
+                                        u32 val)
+{
+       if (pci_dev_is_disconnected(dev))
+               return -ENODEV;
+       return pci_bus_write_config_dword(dev->bus, dev->devfn, where, val);
+}
+EXPORT_SYMBOL(pci_write_config_dword);
index d2d2ba5b8a68e4eabcf9afe5c28f3fe1b29f3d5b..b7e15526d676504f61f4baa160e431171f19b0fd 100644 (file)
@@ -9,16 +9,44 @@ config PCIE_DW_HOST
        depends on PCI_MSI_IRQ_DOMAIN
         select PCIE_DW
 
+config PCIE_DW_EP
+       bool
+       depends on PCI_ENDPOINT
+       select PCIE_DW
+
 config PCI_DRA7XX
        bool "TI DRA7xx PCIe controller"
-       depends on PCI
+       depends on (PCI && PCI_MSI_IRQ_DOMAIN) || PCI_ENDPOINT
        depends on OF && HAS_IOMEM && TI_PIPE3
+       help
+        Enables support for the PCIe controller in the DRA7xx SoC. There
+        are two instances of PCIe controller in DRA7xx. This controller can
+        work either as EP or RC. In order to enable host-specific features
+        PCI_DRA7XX_HOST must be selected and in order to enable device-
+        specific features PCI_DRA7XX_EP must be selected. This uses
+        the Designware core.
+
+if PCI_DRA7XX
+
+config PCI_DRA7XX_HOST
+       bool "PCI DRA7xx Host Mode"
+       depends on PCI
        depends on PCI_MSI_IRQ_DOMAIN
        select PCIE_DW_HOST
+       default y
        help
-        Enables support for the PCIe controller in the DRA7xx SoC.  There
-        are two instances of PCIe controller in DRA7xx.  This controller can
-        act both as EP and RC.  This reuses the Designware core.
+        Enables support for the PCIe controller in the DRA7xx SoC to work in
+        host mode.
+
+config PCI_DRA7XX_EP
+       bool "PCI DRA7xx Endpoint Mode"
+       depends on PCI_ENDPOINT
+       select PCIE_DW_EP
+       help
+        Enables support for the PCIe controller in the DRA7xx SoC to work in
+        endpoint mode.
+
+endif
 
 config PCIE_DW_PLAT
        bool "Platform bus based DesignWare PCIe Controller"
index a2df13c287989fa4d4b71a2283798ee7e052ba18..f31a8596442ae19d164cf02ca10c97b64715fc76 100644 (file)
@@ -1,7 +1,10 @@
 obj-$(CONFIG_PCIE_DW) += pcie-designware.o
 obj-$(CONFIG_PCIE_DW_HOST) += pcie-designware-host.o
+obj-$(CONFIG_PCIE_DW_EP) += pcie-designware-ep.o
 obj-$(CONFIG_PCIE_DW_PLAT) += pcie-designware-plat.o
-obj-$(CONFIG_PCI_DRA7XX) += pci-dra7xx.o
+ifneq ($(filter y,$(CONFIG_PCI_DRA7XX_HOST) $(CONFIG_PCI_DRA7XX_EP)),)
+        obj-$(CONFIG_PCI_DRA7XX) += pci-dra7xx.o
+endif
 obj-$(CONFIG_PCI_EXYNOS) += pci-exynos.o
 obj-$(CONFIG_PCI_IMX6) += pci-imx6.o
 obj-$(CONFIG_PCIE_SPEAR13XX) += pcie-spear13xx.o
index 0984baff07e3490c3139e32ac29a0929cead52f0..8decf46cf5257228985ae722ec3ddaa3ca9b2184 100644 (file)
  * published by the Free Software Foundation.
  */
 
+#include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/of_device.h>
 #include <linux/of_gpio.h>
 #include <linux/of_pci.h>
 #include <linux/pci.h>
@@ -24,6 +26,8 @@
 #include <linux/pm_runtime.h>
 #include <linux/resource.h>
 #include <linux/types.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
 
 #include "pcie-designware.h"
 
 #define        MSI                                             BIT(4)
 #define        LEG_EP_INTERRUPTS (INTA | INTB | INTC | INTD)
 
+#define        PCIECTRL_TI_CONF_DEVICE_TYPE                    0x0100
+#define        DEVICE_TYPE_EP                                  0x0
+#define        DEVICE_TYPE_LEG_EP                              0x1
+#define        DEVICE_TYPE_RC                                  0x4
+
 #define        PCIECTRL_DRA7XX_CONF_DEVICE_CMD                 0x0104
 #define        LTSSM_EN                                        0x1
 
 
 #define EXP_CAP_ID_OFFSET                              0x70
 
+#define        PCIECTRL_TI_CONF_INTX_ASSERT                    0x0124
+#define        PCIECTRL_TI_CONF_INTX_DEASSERT                  0x0128
+
+#define        PCIECTRL_TI_CONF_MSI_XMT                        0x012c
+#define MSI_REQ_GRANT                                  BIT(0)
+#define MSI_VECTOR_SHIFT                               7
+
 struct dra7xx_pcie {
        struct dw_pcie          *pci;
        void __iomem            *base;          /* DT ti_conf */
@@ -73,6 +89,11 @@ struct dra7xx_pcie {
        struct phy              **phy;
        int                     link_gen;
        struct irq_domain       *irq_domain;
+       enum dw_pcie_device_mode mode;
+};
+
+struct dra7xx_pcie_of_data {
+       enum dw_pcie_device_mode mode;
 };
 
 #define to_dra7xx_pcie(x)      dev_get_drvdata((x)->dev)
@@ -88,6 +109,11 @@ static inline void dra7xx_pcie_writel(struct dra7xx_pcie *pcie, u32 offset,
        writel(value, pcie->base + offset);
 }
 
+static u64 dra7xx_pcie_cpu_addr_fixup(u64 pci_addr)
+{
+       return pci_addr & DRA7XX_CPU_TO_BUS_ADDR;
+}
+
 static int dra7xx_pcie_link_up(struct dw_pcie *pci)
 {
        struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pci);
@@ -96,9 +122,19 @@ static int dra7xx_pcie_link_up(struct dw_pcie *pci)
        return !!(reg & LINK_UP);
 }
 
-static int dra7xx_pcie_establish_link(struct dra7xx_pcie *dra7xx)
+static void dra7xx_pcie_stop_link(struct dw_pcie *pci)
 {
-       struct dw_pcie *pci = dra7xx->pci;
+       struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pci);
+       u32 reg;
+
+       reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD);
+       reg &= ~LTSSM_EN;
+       dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD, reg);
+}
+
+static int dra7xx_pcie_establish_link(struct dw_pcie *pci)
+{
+       struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pci);
        struct device *dev = pci->dev;
        u32 reg;
        u32 exp_cap_off = EXP_CAP_ID_OFFSET;
@@ -132,34 +168,42 @@ static int dra7xx_pcie_establish_link(struct dra7xx_pcie *dra7xx)
        reg |= LTSSM_EN;
        dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_DEVICE_CMD, reg);
 
-       return dw_pcie_wait_for_link(pci);
+       return 0;
 }
 
-static void dra7xx_pcie_enable_interrupts(struct dra7xx_pcie *dra7xx)
+static void dra7xx_pcie_enable_msi_interrupts(struct dra7xx_pcie *dra7xx)
 {
-       dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MAIN,
-                          ~INTERRUPTS);
-       dra7xx_pcie_writel(dra7xx,
-                          PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MAIN, INTERRUPTS);
        dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MSI,
                           ~LEG_EP_INTERRUPTS & ~MSI);
-       dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MSI,
+
+       dra7xx_pcie_writel(dra7xx,
+                          PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MSI,
                           MSI | LEG_EP_INTERRUPTS);
 }
 
+static void dra7xx_pcie_enable_wrapper_interrupts(struct dra7xx_pcie *dra7xx)
+{
+       dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MAIN,
+                          ~INTERRUPTS);
+       dra7xx_pcie_writel(dra7xx, PCIECTRL_DRA7XX_CONF_IRQENABLE_SET_MAIN,
+                          INTERRUPTS);
+}
+
+static void dra7xx_pcie_enable_interrupts(struct dra7xx_pcie *dra7xx)
+{
+       dra7xx_pcie_enable_wrapper_interrupts(dra7xx);
+       dra7xx_pcie_enable_msi_interrupts(dra7xx);
+}
+
 static void dra7xx_pcie_host_init(struct pcie_port *pp)
 {
        struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
        struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pci);
 
-       pp->io_base &= DRA7XX_CPU_TO_BUS_ADDR;
-       pp->mem_base &= DRA7XX_CPU_TO_BUS_ADDR;
-       pp->cfg0_base &= DRA7XX_CPU_TO_BUS_ADDR;
-       pp->cfg1_base &= DRA7XX_CPU_TO_BUS_ADDR;
-
        dw_pcie_setup_rc(pp);
 
-       dra7xx_pcie_establish_link(dra7xx);
+       dra7xx_pcie_establish_link(pci);
+       dw_pcie_wait_for_link(pci);
        dw_pcie_msi_init(pp);
        dra7xx_pcie_enable_interrupts(dra7xx);
 }
@@ -237,6 +281,7 @@ static irqreturn_t dra7xx_pcie_irq_handler(int irq, void *arg)
        struct dra7xx_pcie *dra7xx = arg;
        struct dw_pcie *pci = dra7xx->pci;
        struct device *dev = pci->dev;
+       struct dw_pcie_ep *ep = &pci->ep;
        u32 reg;
 
        reg = dra7xx_pcie_readl(dra7xx, PCIECTRL_DRA7XX_CONF_IRQSTATUS_MAIN);
@@ -273,8 +318,11 @@ static irqreturn_t dra7xx_pcie_irq_handler(int irq, void *arg)
        if (reg & LINK_REQ_RST)
                dev_dbg(dev, "Link Request Reset\n");
 
-       if (reg & LINK_UP_EVT)
+       if (reg & LINK_UP_EVT) {
+               if (dra7xx->mode == DW_PCIE_EP_TYPE)
+                       dw_pcie_ep_linkup(ep);
                dev_dbg(dev, "Link-up state change\n");
+       }
 
        if (reg & CFG_BME_EVT)
                dev_dbg(dev, "CFG 'Bus Master Enable' change\n");
@@ -287,6 +335,94 @@ static irqreturn_t dra7xx_pcie_irq_handler(int irq, void *arg)
        return IRQ_HANDLED;
 }
 
+static void dra7xx_pcie_ep_init(struct dw_pcie_ep *ep)
+{
+       struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+       struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pci);
+
+       dra7xx_pcie_enable_wrapper_interrupts(dra7xx);
+}
+
+static void dra7xx_pcie_raise_legacy_irq(struct dra7xx_pcie *dra7xx)
+{
+       dra7xx_pcie_writel(dra7xx, PCIECTRL_TI_CONF_INTX_ASSERT, 0x1);
+       mdelay(1);
+       dra7xx_pcie_writel(dra7xx, PCIECTRL_TI_CONF_INTX_DEASSERT, 0x1);
+}
+
+static void dra7xx_pcie_raise_msi_irq(struct dra7xx_pcie *dra7xx,
+                                     u8 interrupt_num)
+{
+       u32 reg;
+
+       reg = (interrupt_num - 1) << MSI_VECTOR_SHIFT;
+       reg |= MSI_REQ_GRANT;
+       dra7xx_pcie_writel(dra7xx, PCIECTRL_TI_CONF_MSI_XMT, reg);
+}
+
+static int dra7xx_pcie_raise_irq(struct dw_pcie_ep *ep,
+                                enum pci_epc_irq_type type, u8 interrupt_num)
+{
+       struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+       struct dra7xx_pcie *dra7xx = to_dra7xx_pcie(pci);
+
+       switch (type) {
+       case PCI_EPC_IRQ_LEGACY:
+               dra7xx_pcie_raise_legacy_irq(dra7xx);
+               break;
+       case PCI_EPC_IRQ_MSI:
+               dra7xx_pcie_raise_msi_irq(dra7xx, interrupt_num);
+               break;
+       default:
+               dev_err(pci->dev, "UNKNOWN IRQ type\n");
+       }
+
+       return 0;
+}
+
+static struct dw_pcie_ep_ops pcie_ep_ops = {
+       .ep_init = dra7xx_pcie_ep_init,
+       .raise_irq = dra7xx_pcie_raise_irq,
+};
+
+static int __init dra7xx_add_pcie_ep(struct dra7xx_pcie *dra7xx,
+                                    struct platform_device *pdev)
+{
+       int ret;
+       struct dw_pcie_ep *ep;
+       struct resource *res;
+       struct device *dev = &pdev->dev;
+       struct dw_pcie *pci = dra7xx->pci;
+
+       ep = &pci->ep;
+       ep->ops = &pcie_ep_ops;
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ep_dbics");
+       pci->dbi_base = devm_ioremap(dev, res->start, resource_size(res));
+       if (!pci->dbi_base)
+               return -ENOMEM;
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ep_dbics2");
+       pci->dbi_base2 = devm_ioremap(dev, res->start, resource_size(res));
+       if (!pci->dbi_base2)
+               return -ENOMEM;
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "addr_space");
+       if (!res)
+               return -EINVAL;
+
+       ep->phys_base = res->start;
+       ep->addr_size = resource_size(res);
+
+       ret = dw_pcie_ep_init(ep);
+       if (ret) {
+               dev_err(dev, "failed to initialize endpoint\n");
+               return ret;
+       }
+
+       return 0;
+}
+
 static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
                                       struct platform_device *pdev)
 {
@@ -329,6 +465,9 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
 }
 
 static const struct dw_pcie_ops dw_pcie_ops = {
+       .cpu_addr_fixup = dra7xx_pcie_cpu_addr_fixup,
+       .start_link = dra7xx_pcie_establish_link,
+       .stop_link = dra7xx_pcie_stop_link,
        .link_up = dra7xx_pcie_link_up,
 };
 
@@ -371,6 +510,68 @@ err_phy:
        return ret;
 }
 
+static const struct dra7xx_pcie_of_data dra7xx_pcie_rc_of_data = {
+       .mode = DW_PCIE_RC_TYPE,
+};
+
+static const struct dra7xx_pcie_of_data dra7xx_pcie_ep_of_data = {
+       .mode = DW_PCIE_EP_TYPE,
+};
+
+static const struct of_device_id of_dra7xx_pcie_match[] = {
+       {
+               .compatible = "ti,dra7-pcie",
+               .data = &dra7xx_pcie_rc_of_data,
+       },
+       {
+               .compatible = "ti,dra7-pcie-ep",
+               .data = &dra7xx_pcie_ep_of_data,
+       },
+       {},
+};
+
+/*
+ * dra7xx_pcie_ep_unaligned_memaccess: workaround for AM572x/AM571x Errata i870
+ * @dra7xx: the dra7xx device where the workaround should be applied
+ *
+ * Access to the PCIe slave port that are not 32-bit aligned will result
+ * in incorrect mapping to TLP Address and Byte enable fields. Therefore,
+ * byte and half-word accesses are not possible to byte offset 0x1, 0x2, or
+ * 0x3.
+ *
+ * To avoid this issue set PCIE_SS1_AXI2OCP_LEGACY_MODE_ENABLE to 1.
+ */
+static int dra7xx_pcie_ep_unaligned_memaccess(struct device *dev)
+{
+       int ret;
+       struct device_node *np = dev->of_node;
+       struct of_phandle_args args;
+       struct regmap *regmap;
+
+       regmap = syscon_regmap_lookup_by_phandle(np,
+                                                "ti,syscon-unaligned-access");
+       if (IS_ERR(regmap)) {
+               dev_dbg(dev, "can't get ti,syscon-unaligned-access\n");
+               return -EINVAL;
+       }
+
+       ret = of_parse_phandle_with_fixed_args(np, "ti,syscon-unaligned-access",
+                                              2, 0, &args);
+       if (ret) {
+               dev_err(dev, "failed to parse ti,syscon-unaligned-access\n");
+               return ret;
+       }
+
+       ret = regmap_update_bits(regmap, args.args[0], args.args[1],
+                                args.args[1]);
+       if (ret)
+               dev_err(dev, "failed to enable unaligned access\n");
+
+       of_node_put(args.np);
+
+       return ret;
+}
+
 static int __init dra7xx_pcie_probe(struct platform_device *pdev)
 {
        u32 reg;
@@ -388,6 +589,16 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev)
        struct device_node *np = dev->of_node;
        char name[10];
        struct gpio_desc *reset;
+       const struct of_device_id *match;
+       const struct dra7xx_pcie_of_data *data;
+       enum dw_pcie_device_mode mode;
+
+       match = of_match_device(of_match_ptr(of_dra7xx_pcie_match), dev);
+       if (!match)
+               return -EINVAL;
+
+       data = (struct dra7xx_pcie_of_data *)match->data;
+       mode = (enum dw_pcie_device_mode)data->mode;
 
        dra7xx = devm_kzalloc(dev, sizeof(*dra7xx), GFP_KERNEL);
        if (!dra7xx)
@@ -409,13 +620,6 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev)
                return -EINVAL;
        }
 
-       ret = devm_request_irq(dev, irq, dra7xx_pcie_irq_handler,
-                              IRQF_SHARED, "dra7xx-pcie-main", dra7xx);
-       if (ret) {
-               dev_err(dev, "failed to request irq\n");
-               return ret;
-       }
-
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ti_conf");
        base = devm_ioremap_nocache(dev, res->start, resource_size(res));
        if (!base)
@@ -473,9 +677,37 @@ static int __init dra7xx_pcie_probe(struct platform_device *pdev)
        if (dra7xx->link_gen < 0 || dra7xx->link_gen > 2)
                dra7xx->link_gen = 2;
 
-       ret = dra7xx_add_pcie_port(dra7xx, pdev);
-       if (ret < 0)
+       switch (mode) {
+       case DW_PCIE_RC_TYPE:
+               dra7xx_pcie_writel(dra7xx, PCIECTRL_TI_CONF_DEVICE_TYPE,
+                                  DEVICE_TYPE_RC);
+               ret = dra7xx_add_pcie_port(dra7xx, pdev);
+               if (ret < 0)
+                       goto err_gpio;
+               break;
+       case DW_PCIE_EP_TYPE:
+               dra7xx_pcie_writel(dra7xx, PCIECTRL_TI_CONF_DEVICE_TYPE,
+                                  DEVICE_TYPE_EP);
+
+               ret = dra7xx_pcie_ep_unaligned_memaccess(dev);
+               if (ret)
+                       goto err_gpio;
+
+               ret = dra7xx_add_pcie_ep(dra7xx, pdev);
+               if (ret < 0)
+                       goto err_gpio;
+               break;
+       default:
+               dev_err(dev, "INVALID device type %d\n", mode);
+       }
+       dra7xx->mode = mode;
+
+       ret = devm_request_irq(dev, irq, dra7xx_pcie_irq_handler,
+                              IRQF_SHARED, "dra7xx-pcie-main", dra7xx);
+       if (ret) {
+               dev_err(dev, "failed to request irq\n");
                goto err_gpio;
+       }
 
        return 0;
 
@@ -496,6 +728,9 @@ static int dra7xx_pcie_suspend(struct device *dev)
        struct dw_pcie *pci = dra7xx->pci;
        u32 val;
 
+       if (dra7xx->mode != DW_PCIE_RC_TYPE)
+               return 0;
+
        /* clear MSE */
        val = dw_pcie_readl_dbi(pci, PCI_COMMAND);
        val &= ~PCI_COMMAND_MEMORY;
@@ -510,6 +745,9 @@ static int dra7xx_pcie_resume(struct device *dev)
        struct dw_pcie *pci = dra7xx->pci;
        u32 val;
 
+       if (dra7xx->mode != DW_PCIE_RC_TYPE)
+               return 0;
+
        /* set MSE */
        val = dw_pcie_readl_dbi(pci, PCI_COMMAND);
        val |= PCI_COMMAND_MEMORY;
@@ -548,11 +786,6 @@ static const struct dev_pm_ops dra7xx_pcie_pm_ops = {
                                      dra7xx_pcie_resume_noirq)
 };
 
-static const struct of_device_id of_dra7xx_pcie_match[] = {
-       { .compatible = "ti,dra7-pcie", },
-       {},
-};
-
 static struct platform_driver dra7xx_pcie_driver = {
        .driver = {
                .name   = "dra7-pcie",
index 44f774c12fb25e7ab6f98df5edf8a09638971eca..546082ad5a3f767d97af9d6015023aded654032e 100644 (file)
@@ -521,23 +521,25 @@ static void exynos_pcie_enable_interrupts(struct exynos_pcie *ep)
                exynos_pcie_msi_init(ep);
 }
 
-static u32 exynos_pcie_readl_dbi(struct dw_pcie *pci, u32 reg)
+static u32 exynos_pcie_read_dbi(struct dw_pcie *pci, void __iomem *base,
+                               u32 reg, size_t size)
 {
        struct exynos_pcie *ep = to_exynos_pcie(pci);
        u32 val;
 
        exynos_pcie_sideband_dbi_r_mode(ep, true);
-       val = readl(pci->dbi_base + reg);
+       dw_pcie_read(base + reg, size, &val);
        exynos_pcie_sideband_dbi_r_mode(ep, false);
        return val;
 }
 
-static void exynos_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val)
+static void exynos_pcie_write_dbi(struct dw_pcie *pci, void __iomem *base,
+                                 u32 reg, size_t size, u32 val)
 {
        struct exynos_pcie *ep = to_exynos_pcie(pci);
 
        exynos_pcie_sideband_dbi_w_mode(ep, true);
-       writel(val, pci->dbi_base + reg);
+       dw_pcie_write(base + reg, size, val);
        exynos_pcie_sideband_dbi_w_mode(ep, false);
 }
 
@@ -644,8 +646,8 @@ static int __init exynos_add_pcie_port(struct exynos_pcie *ep,
 }
 
 static const struct dw_pcie_ops dw_pcie_ops = {
-       .readl_dbi = exynos_pcie_readl_dbi,
-       .writel_dbi = exynos_pcie_writel_dbi,
+       .read_dbi = exynos_pcie_read_dbi,
+       .write_dbi = exynos_pcie_write_dbi,
        .link_up = exynos_pcie_link_up,
 };
 
index 801e46cd266d79463e9b1a96fb418769c3414548..a98cba55c7f02e670436787c011a85a8772f5109 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/kernel.h>
 #include <linux/mfd/syscon.h>
 #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
+#include <linux/mfd/syscon/imx7-iomuxc-gpr.h>
 #include <linux/module.h>
 #include <linux/of_gpio.h>
 #include <linux/of_device.h>
@@ -27,6 +28,7 @@
 #include <linux/signal.h>
 #include <linux/types.h>
 #include <linux/interrupt.h>
+#include <linux/reset.h>
 
 #include "pcie-designware.h"
 
@@ -36,6 +38,7 @@ enum imx6_pcie_variants {
        IMX6Q,
        IMX6SX,
        IMX6QP,
+       IMX7D,
 };
 
 struct imx6_pcie {
@@ -47,6 +50,8 @@ struct imx6_pcie {
        struct clk              *pcie_inbound_axi;
        struct clk              *pcie;
        struct regmap           *iomuxc_gpr;
+       struct reset_control    *pciephy_reset;
+       struct reset_control    *apps_reset;
        enum imx6_pcie_variants variant;
        u32                     tx_deemph_gen1;
        u32                     tx_deemph_gen2_3p5db;
@@ -56,6 +61,11 @@ struct imx6_pcie {
        int                     link_gen;
 };
 
+/* Parameters for the waiting for PCIe PHY PLL to lock on i.MX7 */
+#define PHY_PLL_LOCK_WAIT_MAX_RETRIES  2000
+#define PHY_PLL_LOCK_WAIT_USLEEP_MIN   50
+#define PHY_PLL_LOCK_WAIT_USLEEP_MAX   200
+
 /* PCIe Root Complex registers (memory-mapped) */
 #define PCIE_RC_LCR                            0x7c
 #define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1       0x1
@@ -248,6 +258,10 @@ static int imx6q_pcie_abort_handler(unsigned long addr,
 static void imx6_pcie_assert_core_reset(struct imx6_pcie *imx6_pcie)
 {
        switch (imx6_pcie->variant) {
+       case IMX7D:
+               reset_control_assert(imx6_pcie->pciephy_reset);
+               reset_control_assert(imx6_pcie->apps_reset);
+               break;
        case IMX6SX:
                regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
                                   IMX6SX_GPR12_PCIE_TEST_POWERDOWN,
@@ -303,11 +317,32 @@ static int imx6_pcie_enable_ref_clk(struct imx6_pcie *imx6_pcie)
                regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1,
                                   IMX6Q_GPR1_PCIE_REF_CLK_EN, 1 << 16);
                break;
+       case IMX7D:
+               break;
        }
 
        return ret;
 }
 
+static void imx7d_pcie_wait_for_phy_pll_lock(struct imx6_pcie *imx6_pcie)
+{
+       u32 val;
+       unsigned int retries;
+       struct device *dev = imx6_pcie->pci->dev;
+
+       for (retries = 0; retries < PHY_PLL_LOCK_WAIT_MAX_RETRIES; retries++) {
+               regmap_read(imx6_pcie->iomuxc_gpr, IOMUXC_GPR22, &val);
+
+               if (val & IMX7D_GPR22_PCIE_PHY_PLL_LOCKED)
+                       return;
+
+               usleep_range(PHY_PLL_LOCK_WAIT_USLEEP_MIN,
+                            PHY_PLL_LOCK_WAIT_USLEEP_MAX);
+       }
+
+       dev_err(dev, "PCIe PLL lock timeout\n");
+}
+
 static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
 {
        struct dw_pcie *pci = imx6_pcie->pci;
@@ -351,6 +386,10 @@ static void imx6_pcie_deassert_core_reset(struct imx6_pcie *imx6_pcie)
        }
 
        switch (imx6_pcie->variant) {
+       case IMX7D:
+               reset_control_deassert(imx6_pcie->pciephy_reset);
+               imx7d_pcie_wait_for_phy_pll_lock(imx6_pcie);
+               break;
        case IMX6SX:
                regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR5,
                                   IMX6SX_GPR5_PCIE_BTNRST_RESET, 0);
@@ -377,35 +416,44 @@ err_pcie_bus:
 
 static void imx6_pcie_init_phy(struct imx6_pcie *imx6_pcie)
 {
-       if (imx6_pcie->variant == IMX6SX)
+       switch (imx6_pcie->variant) {
+       case IMX7D:
+               regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+                                  IMX7D_GPR12_PCIE_PHY_REFCLK_SEL, 0);
+               break;
+       case IMX6SX:
                regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
                                   IMX6SX_GPR12_PCIE_RX_EQ_MASK,
                                   IMX6SX_GPR12_PCIE_RX_EQ_2);
+               /* FALLTHROUGH */
+       default:
+               regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+                                  IMX6Q_GPR12_PCIE_CTL_2, 0 << 10);
 
-       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
-                       IMX6Q_GPR12_PCIE_CTL_2, 0 << 10);
+               /* configure constant input signal to the pcie ctrl and phy */
+               regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+                                  IMX6Q_GPR12_LOS_LEVEL, 9 << 4);
+
+               regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
+                                  IMX6Q_GPR8_TX_DEEMPH_GEN1,
+                                  imx6_pcie->tx_deemph_gen1 << 0);
+               regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
+                                  IMX6Q_GPR8_TX_DEEMPH_GEN2_3P5DB,
+                                  imx6_pcie->tx_deemph_gen2_3p5db << 6);
+               regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
+                                  IMX6Q_GPR8_TX_DEEMPH_GEN2_6DB,
+                                  imx6_pcie->tx_deemph_gen2_6db << 12);
+               regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
+                                  IMX6Q_GPR8_TX_SWING_FULL,
+                                  imx6_pcie->tx_swing_full << 18);
+               regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
+                                  IMX6Q_GPR8_TX_SWING_LOW,
+                                  imx6_pcie->tx_swing_low << 25);
+               break;
+       }
 
-       /* configure constant input signal to the pcie ctrl and phy */
        regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
                        IMX6Q_GPR12_DEVICE_TYPE, PCI_EXP_TYPE_ROOT_PORT << 12);
-       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
-                       IMX6Q_GPR12_LOS_LEVEL, 9 << 4);
-
-       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
-                          IMX6Q_GPR8_TX_DEEMPH_GEN1,
-                          imx6_pcie->tx_deemph_gen1 << 0);
-       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
-                          IMX6Q_GPR8_TX_DEEMPH_GEN2_3P5DB,
-                          imx6_pcie->tx_deemph_gen2_3p5db << 6);
-       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
-                          IMX6Q_GPR8_TX_DEEMPH_GEN2_6DB,
-                          imx6_pcie->tx_deemph_gen2_6db << 12);
-       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
-                          IMX6Q_GPR8_TX_SWING_FULL,
-                          imx6_pcie->tx_swing_full << 18);
-       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR8,
-                          IMX6Q_GPR8_TX_SWING_LOW,
-                          imx6_pcie->tx_swing_low << 25);
 }
 
 static int imx6_pcie_wait_for_link(struct imx6_pcie *imx6_pcie)
@@ -469,8 +517,11 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie)
        dw_pcie_writel_dbi(pci, PCIE_RC_LCR, tmp);
 
        /* Start LTSSM. */
-       regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
-                       IMX6Q_GPR12_PCIE_CTL_2, 1 << 10);
+       if (imx6_pcie->variant == IMX7D)
+               reset_control_deassert(imx6_pcie->apps_reset);
+       else
+               regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
+                                  IMX6Q_GPR12_PCIE_CTL_2, 1 << 10);
 
        ret = imx6_pcie_wait_for_link(imx6_pcie);
        if (ret)
@@ -482,29 +533,40 @@ static int imx6_pcie_establish_link(struct imx6_pcie *imx6_pcie)
                tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK;
                tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2;
                dw_pcie_writel_dbi(pci, PCIE_RC_LCR, tmp);
-       } else {
-               dev_info(dev, "Link: Gen2 disabled\n");
-       }
-
-       /*
-        * Start Directed Speed Change so the best possible speed both link
-        * partners support can be negotiated.
-        */
-       tmp = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL);
-       tmp |= PORT_LOGIC_SPEED_CHANGE;
-       dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp);
 
-       ret = imx6_pcie_wait_for_speed_change(imx6_pcie);
-       if (ret) {
-               dev_err(dev, "Failed to bring link up!\n");
-               goto err_reset_phy;
-       }
+               /*
+                * Start Directed Speed Change so the best possible
+                * speed both link partners support can be negotiated.
+                */
+               tmp = dw_pcie_readl_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL);
+               tmp |= PORT_LOGIC_SPEED_CHANGE;
+               dw_pcie_writel_dbi(pci, PCIE_LINK_WIDTH_SPEED_CONTROL, tmp);
+
+               if (imx6_pcie->variant != IMX7D) {
+                       /*
+                        * On i.MX7, DIRECT_SPEED_CHANGE behaves differently
+                        * from i.MX6 family when no link speed transition
+                        * occurs and we go Gen1 -> yep, Gen1. The difference
+                        * is that, in such case, it will not be cleared by HW
+                        * which will cause the following code to report false
+                        * failure.
+                        */
+
+                       ret = imx6_pcie_wait_for_speed_change(imx6_pcie);
+                       if (ret) {
+                               dev_err(dev, "Failed to bring link up!\n");
+                               goto err_reset_phy;
+                       }
+               }
 
-       /* Make sure link training is finished as well! */
-       ret = imx6_pcie_wait_for_link(imx6_pcie);
-       if (ret) {
-               dev_err(dev, "Failed to bring link up!\n");
-               goto err_reset_phy;
+               /* Make sure link training is finished as well! */
+               ret = imx6_pcie_wait_for_link(imx6_pcie);
+               if (ret) {
+                       dev_err(dev, "Failed to bring link up!\n");
+                       goto err_reset_phy;
+               }
+       } else {
+               dev_info(dev, "Link: Gen2 disabled\n");
        }
 
        tmp = dw_pcie_readl_dbi(pci, PCIE_RC_LCSR);
@@ -544,8 +606,8 @@ static struct dw_pcie_host_ops imx6_pcie_host_ops = {
        .host_init = imx6_pcie_host_init,
 };
 
-static int __init imx6_add_pcie_port(struct imx6_pcie *imx6_pcie,
-                                    struct platform_device *pdev)
+static int imx6_add_pcie_port(struct imx6_pcie *imx6_pcie,
+                             struct platform_device *pdev)
 {
        struct dw_pcie *pci = imx6_pcie->pci;
        struct pcie_port *pp = &pci->pp;
@@ -585,7 +647,7 @@ static const struct dw_pcie_ops dw_pcie_ops = {
        .link_up = imx6_pcie_link_up,
 };
 
-static int __init imx6_pcie_probe(struct platform_device *pdev)
+static int imx6_pcie_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct dw_pcie *pci;
@@ -609,10 +671,6 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
        imx6_pcie->variant =
                (enum imx6_pcie_variants)of_device_get_match_data(dev);
 
-       /* Added for PCI abort handling */
-       hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0,
-               "imprecise external abort");
-
        dbi_base = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        pci->dbi_base = devm_ioremap_resource(dev, dbi_base);
        if (IS_ERR(pci->dbi_base))
@@ -632,6 +690,8 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
                        dev_err(dev, "unable to get reset gpio\n");
                        return ret;
                }
+       } else if (imx6_pcie->reset_gpio == -EPROBE_DEFER) {
+               return imx6_pcie->reset_gpio;
        }
 
        /* Fetch clocks */
@@ -653,13 +713,31 @@ static int __init imx6_pcie_probe(struct platform_device *pdev)
                return PTR_ERR(imx6_pcie->pcie);
        }
 
-       if (imx6_pcie->variant == IMX6SX) {
+       switch (imx6_pcie->variant) {
+       case IMX6SX:
                imx6_pcie->pcie_inbound_axi = devm_clk_get(dev,
                                                           "pcie_inbound_axi");
                if (IS_ERR(imx6_pcie->pcie_inbound_axi)) {
                        dev_err(dev, "pcie_inbound_axi clock missing or invalid\n");
                        return PTR_ERR(imx6_pcie->pcie_inbound_axi);
                }
+               break;
+       case IMX7D:
+               imx6_pcie->pciephy_reset = devm_reset_control_get(dev,
+                                                                 "pciephy");
+               if (IS_ERR(imx6_pcie->pciephy_reset)) {
+                       dev_err(dev, "Failed to get PCIEPHY reset control\n");
+                       return PTR_ERR(imx6_pcie->pciephy_reset);
+               }
+
+               imx6_pcie->apps_reset = devm_reset_control_get(dev, "apps");
+               if (IS_ERR(imx6_pcie->apps_reset)) {
+                       dev_err(dev, "Failed to get PCIE APPS reset control\n");
+                       return PTR_ERR(imx6_pcie->apps_reset);
+               }
+               break;
+       default:
+               break;
        }
 
        /* Grab GPR config register range */
@@ -718,6 +796,7 @@ static const struct of_device_id imx6_pcie_of_match[] = {
        { .compatible = "fsl,imx6q-pcie",  .data = (void *)IMX6Q,  },
        { .compatible = "fsl,imx6sx-pcie", .data = (void *)IMX6SX, },
        { .compatible = "fsl,imx6qp-pcie", .data = (void *)IMX6QP, },
+       { .compatible = "fsl,imx7d-pcie",  .data = (void *)IMX7D,  },
        {},
 };
 
@@ -725,12 +804,24 @@ static struct platform_driver imx6_pcie_driver = {
        .driver = {
                .name   = "imx6q-pcie",
                .of_match_table = imx6_pcie_of_match,
+               .suppress_bind_attrs = true,
        },
+       .probe    = imx6_pcie_probe,
        .shutdown = imx6_pcie_shutdown,
 };
 
 static int __init imx6_pcie_init(void)
 {
-       return platform_driver_probe(&imx6_pcie_driver, imx6_pcie_probe);
+       /*
+        * Since probe() can be deferred we need to make sure that
+        * hook_fault_code is not called after __init memory is freed
+        * by kernel and since imx6q_pcie_abort_handler() is a no-op,
+        * we can install the handler here without risking it
+        * accessing some uninitialized driver state.
+        */
+       hook_fault_code(16 + 6, imx6q_pcie_abort_handler, SIGBUS, 0,
+                       "imprecise external abort");
+
+       return platform_driver_register(&imx6_pcie_driver);
 }
 device_initcall(imx6_pcie_init);
index 6b396f6b4615ad7275617cb4841faded498e7fc9..8bc626e640c8b2f87b50b1ba664555e875ccb507 100644 (file)
@@ -543,7 +543,7 @@ int __init ks_dw_pcie_host_init(struct keystone_pcie *ks_pcie,
 
        /* Index 0 is the config reg. space address */
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       pci->dbi_base = devm_ioremap_resource(dev, res);
+       pci->dbi_base = devm_pci_remap_cfg_resource(dev, res);
        if (IS_ERR(pci->dbi_base))
                return PTR_ERR(pci->dbi_base);
 
index c32e392a0ae6f89beec5b088ab1da4580b37fa36..27d638c4e134316676f9984a4596b6275c23f133 100644 (file)
@@ -283,7 +283,7 @@ static int __init ls_pcie_probe(struct platform_device *pdev)
        pcie->pci = pci;
 
        dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs");
-       pci->dbi_base = devm_ioremap_resource(dev, dbi_base);
+       pci->dbi_base = devm_pci_remap_cfg_resource(dev, dbi_base);
        if (IS_ERR(pci->dbi_base))
                return PTR_ERR(pci->dbi_base);
 
@@ -305,6 +305,7 @@ static struct platform_driver ls_pcie_driver = {
        .driver = {
                .name = "layerscape-pcie",
                .of_match_table = ls_pcie_of_match,
+               .suppress_bind_attrs = true,
        },
 };
 builtin_platform_driver_probe(ls_pcie_driver, ls_pcie_probe);
index f110e3b24a26dc11459d113d1bcffe9ce80e370f..495b023042b3ac2b861515aea4245be91ecaefeb 100644 (file)
@@ -230,7 +230,7 @@ static int armada8k_pcie_probe(struct platform_device *pdev)
 
        /* Get the dw-pcie unit configuration/control registers base. */
        base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctrl");
-       pci->dbi_base = devm_ioremap_resource(dev, base);
+       pci->dbi_base = devm_pci_remap_cfg_resource(dev, base);
        if (IS_ERR(pci->dbi_base)) {
                dev_err(dev, "couldn't remap regs base %p\n", base);
                ret = PTR_ERR(pci->dbi_base);
@@ -262,6 +262,7 @@ static struct platform_driver armada8k_pcie_driver = {
        .driver = {
                .name   = "armada8k-pcie",
                .of_match_table = of_match_ptr(armada8k_pcie_of_match),
+               .suppress_bind_attrs = true,
        },
 };
 builtin_platform_driver(armada8k_pcie_driver);
index 6d23683c0892f59646b4142242fa80bf0e85be98..82a04acc42fdc228e8e500efd4fa082494b7930c 100644 (file)
@@ -78,6 +78,11 @@ static void artpec6_pcie_writel(struct artpec6_pcie *artpec6_pcie, u32 offset, u
        regmap_write(artpec6_pcie->regmap, offset, val);
 }
 
+static u64 artpec6_pcie_cpu_addr_fixup(u64 pci_addr)
+{
+       return pci_addr & ARTPEC6_CPU_TO_BUS_ADDR;
+}
+
 static int artpec6_pcie_establish_link(struct artpec6_pcie *artpec6_pcie)
 {
        struct dw_pcie *pci = artpec6_pcie->pci;
@@ -142,11 +147,6 @@ static int artpec6_pcie_establish_link(struct artpec6_pcie *artpec6_pcie)
         */
        dw_pcie_writel_dbi(pci, MISC_CONTROL_1_OFF, DBI_RO_WR_EN);
 
-       pp->io_base &= ARTPEC6_CPU_TO_BUS_ADDR;
-       pp->mem_base &= ARTPEC6_CPU_TO_BUS_ADDR;
-       pp->cfg0_base &= ARTPEC6_CPU_TO_BUS_ADDR;
-       pp->cfg1_base &= ARTPEC6_CPU_TO_BUS_ADDR;
-
        /* setup root complex */
        dw_pcie_setup_rc(pp);
 
@@ -235,6 +235,7 @@ static int artpec6_add_pcie_port(struct artpec6_pcie *artpec6_pcie,
 }
 
 static const struct dw_pcie_ops dw_pcie_ops = {
+       .cpu_addr_fixup = artpec6_pcie_cpu_addr_fixup,
 };
 
 static int artpec6_pcie_probe(struct platform_device *pdev)
@@ -294,6 +295,7 @@ static struct platform_driver artpec6_pcie_driver = {
        .driver = {
                .name   = "artpec6-pcie",
                .of_match_table = artpec6_pcie_of_match,
+               .suppress_bind_attrs = true,
        },
 };
 builtin_platform_driver(artpec6_pcie_driver);
diff --git a/drivers/pci/dwc/pcie-designware-ep.c b/drivers/pci/dwc/pcie-designware-ep.c
new file mode 100644 (file)
index 0000000..3984063
--- /dev/null
@@ -0,0 +1,342 @@
+/**
+ * Synopsys Designware PCIe Endpoint controller driver
+ *
+ * Copyright (C) 2017 Texas Instruments
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 of
+ * the License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/of.h>
+
+#include "pcie-designware.h"
+#include <linux/pci-epc.h>
+#include <linux/pci-epf.h>
+
+void dw_pcie_ep_linkup(struct dw_pcie_ep *ep)
+{
+       struct pci_epc *epc = ep->epc;
+
+       pci_epc_linkup(epc);
+}
+
+static void dw_pcie_ep_reset_bar(struct dw_pcie *pci, enum pci_barno bar)
+{
+       u32 reg;
+
+       reg = PCI_BASE_ADDRESS_0 + (4 * bar);
+       dw_pcie_writel_dbi2(pci, reg, 0x0);
+       dw_pcie_writel_dbi(pci, reg, 0x0);
+}
+
+static int dw_pcie_ep_write_header(struct pci_epc *epc,
+                                  struct pci_epf_header *hdr)
+{
+       struct dw_pcie_ep *ep = epc_get_drvdata(epc);
+       struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+
+       dw_pcie_writew_dbi(pci, PCI_VENDOR_ID, hdr->vendorid);
+       dw_pcie_writew_dbi(pci, PCI_DEVICE_ID, hdr->deviceid);
+       dw_pcie_writeb_dbi(pci, PCI_REVISION_ID, hdr->revid);
+       dw_pcie_writeb_dbi(pci, PCI_CLASS_PROG, hdr->progif_code);
+       dw_pcie_writew_dbi(pci, PCI_CLASS_DEVICE,
+                          hdr->subclass_code | hdr->baseclass_code << 8);
+       dw_pcie_writeb_dbi(pci, PCI_CACHE_LINE_SIZE,
+                          hdr->cache_line_size);
+       dw_pcie_writew_dbi(pci, PCI_SUBSYSTEM_VENDOR_ID,
+                          hdr->subsys_vendor_id);
+       dw_pcie_writew_dbi(pci, PCI_SUBSYSTEM_ID, hdr->subsys_id);
+       dw_pcie_writeb_dbi(pci, PCI_INTERRUPT_PIN,
+                          hdr->interrupt_pin);
+
+       return 0;
+}
+
+static int dw_pcie_ep_inbound_atu(struct dw_pcie_ep *ep, enum pci_barno bar,
+                                 dma_addr_t cpu_addr,
+                                 enum dw_pcie_as_type as_type)
+{
+       int ret;
+       u32 free_win;
+       struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+
+       free_win = find_first_zero_bit(&ep->ib_window_map,
+                                      sizeof(ep->ib_window_map));
+       if (free_win >= ep->num_ib_windows) {
+               dev_err(pci->dev, "no free inbound window\n");
+               return -EINVAL;
+       }
+
+       ret = dw_pcie_prog_inbound_atu(pci, free_win, bar, cpu_addr,
+                                      as_type);
+       if (ret < 0) {
+               dev_err(pci->dev, "Failed to program IB window\n");
+               return ret;
+       }
+
+       ep->bar_to_atu[bar] = free_win;
+       set_bit(free_win, &ep->ib_window_map);
+
+       return 0;
+}
+
+static int dw_pcie_ep_outbound_atu(struct dw_pcie_ep *ep, phys_addr_t phys_addr,
+                                  u64 pci_addr, size_t size)
+{
+       u32 free_win;
+       struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+
+       free_win = find_first_zero_bit(&ep->ob_window_map,
+                                      sizeof(ep->ob_window_map));
+       if (free_win >= ep->num_ob_windows) {
+               dev_err(pci->dev, "no free outbound window\n");
+               return -EINVAL;
+       }
+
+       dw_pcie_prog_outbound_atu(pci, free_win, PCIE_ATU_TYPE_MEM,
+                                 phys_addr, pci_addr, size);
+
+       set_bit(free_win, &ep->ob_window_map);
+       ep->outbound_addr[free_win] = phys_addr;
+
+       return 0;
+}
+
+static void dw_pcie_ep_clear_bar(struct pci_epc *epc, enum pci_barno bar)
+{
+       struct dw_pcie_ep *ep = epc_get_drvdata(epc);
+       struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+       u32 atu_index = ep->bar_to_atu[bar];
+
+       dw_pcie_ep_reset_bar(pci, bar);
+
+       dw_pcie_disable_atu(pci, atu_index, DW_PCIE_REGION_INBOUND);
+       clear_bit(atu_index, &ep->ib_window_map);
+}
+
+static int dw_pcie_ep_set_bar(struct pci_epc *epc, enum pci_barno bar,
+                             dma_addr_t bar_phys, size_t size, int flags)
+{
+       int ret;
+       struct dw_pcie_ep *ep = epc_get_drvdata(epc);
+       struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+       enum dw_pcie_as_type as_type;
+       u32 reg = PCI_BASE_ADDRESS_0 + (4 * bar);
+
+       if (!(flags & PCI_BASE_ADDRESS_SPACE))
+               as_type = DW_PCIE_AS_MEM;
+       else
+               as_type = DW_PCIE_AS_IO;
+
+       ret = dw_pcie_ep_inbound_atu(ep, bar, bar_phys, as_type);
+       if (ret)
+               return ret;
+
+       dw_pcie_writel_dbi2(pci, reg, size - 1);
+       dw_pcie_writel_dbi(pci, reg, flags);
+
+       return 0;
+}
+
+static int dw_pcie_find_index(struct dw_pcie_ep *ep, phys_addr_t addr,
+                             u32 *atu_index)
+{
+       u32 index;
+
+       for (index = 0; index < ep->num_ob_windows; index++) {
+               if (ep->outbound_addr[index] != addr)
+                       continue;
+               *atu_index = index;
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static void dw_pcie_ep_unmap_addr(struct pci_epc *epc, phys_addr_t addr)
+{
+       int ret;
+       u32 atu_index;
+       struct dw_pcie_ep *ep = epc_get_drvdata(epc);
+       struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+
+       ret = dw_pcie_find_index(ep, addr, &atu_index);
+       if (ret < 0)
+               return;
+
+       dw_pcie_disable_atu(pci, atu_index, DW_PCIE_REGION_OUTBOUND);
+       clear_bit(atu_index, &ep->ob_window_map);
+}
+
+static int dw_pcie_ep_map_addr(struct pci_epc *epc, phys_addr_t addr,
+                              u64 pci_addr, size_t size)
+{
+       int ret;
+       struct dw_pcie_ep *ep = epc_get_drvdata(epc);
+       struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+
+       ret = dw_pcie_ep_outbound_atu(ep, addr, pci_addr, size);
+       if (ret) {
+               dev_err(pci->dev, "failed to enable address\n");
+               return ret;
+       }
+
+       return 0;
+}
+
+static int dw_pcie_ep_get_msi(struct pci_epc *epc)
+{
+       int val;
+       u32 lower_addr;
+       u32 upper_addr;
+       struct dw_pcie_ep *ep = epc_get_drvdata(epc);
+       struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+
+       val = dw_pcie_readb_dbi(pci, MSI_MESSAGE_CONTROL);
+       val = (val & MSI_CAP_MME_MASK) >> MSI_CAP_MME_SHIFT;
+
+       lower_addr = dw_pcie_readl_dbi(pci, MSI_MESSAGE_ADDR_L32);
+       upper_addr = dw_pcie_readl_dbi(pci, MSI_MESSAGE_ADDR_U32);
+
+       if (!(lower_addr || upper_addr))
+               return -EINVAL;
+
+       return val;
+}
+
+static int dw_pcie_ep_set_msi(struct pci_epc *epc, u8 encode_int)
+{
+       int val;
+       struct dw_pcie_ep *ep = epc_get_drvdata(epc);
+       struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+
+       val = (encode_int << MSI_CAP_MMC_SHIFT);
+       dw_pcie_writew_dbi(pci, MSI_MESSAGE_CONTROL, val);
+
+       return 0;
+}
+
+static int dw_pcie_ep_raise_irq(struct pci_epc *epc,
+                               enum pci_epc_irq_type type, u8 interrupt_num)
+{
+       struct dw_pcie_ep *ep = epc_get_drvdata(epc);
+
+       if (!ep->ops->raise_irq)
+               return -EINVAL;
+
+       return ep->ops->raise_irq(ep, type, interrupt_num);
+}
+
+static void dw_pcie_ep_stop(struct pci_epc *epc)
+{
+       struct dw_pcie_ep *ep = epc_get_drvdata(epc);
+       struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+
+       if (!pci->ops->stop_link)
+               return;
+
+       pci->ops->stop_link(pci);
+}
+
+static int dw_pcie_ep_start(struct pci_epc *epc)
+{
+       struct dw_pcie_ep *ep = epc_get_drvdata(epc);
+       struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+
+       if (!pci->ops->start_link)
+               return -EINVAL;
+
+       return pci->ops->start_link(pci);
+}
+
+static const struct pci_epc_ops epc_ops = {
+       .write_header           = dw_pcie_ep_write_header,
+       .set_bar                = dw_pcie_ep_set_bar,
+       .clear_bar              = dw_pcie_ep_clear_bar,
+       .map_addr               = dw_pcie_ep_map_addr,
+       .unmap_addr             = dw_pcie_ep_unmap_addr,
+       .set_msi                = dw_pcie_ep_set_msi,
+       .get_msi                = dw_pcie_ep_get_msi,
+       .raise_irq              = dw_pcie_ep_raise_irq,
+       .start                  = dw_pcie_ep_start,
+       .stop                   = dw_pcie_ep_stop,
+};
+
+void dw_pcie_ep_exit(struct dw_pcie_ep *ep)
+{
+       struct pci_epc *epc = ep->epc;
+
+       pci_epc_mem_exit(epc);
+}
+
+int dw_pcie_ep_init(struct dw_pcie_ep *ep)
+{
+       int ret;
+       void *addr;
+       enum pci_barno bar;
+       struct pci_epc *epc;
+       struct dw_pcie *pci = to_dw_pcie_from_ep(ep);
+       struct device *dev = pci->dev;
+       struct device_node *np = dev->of_node;
+
+       if (!pci->dbi_base || !pci->dbi_base2) {
+               dev_err(dev, "dbi_base/deb_base2 is not populated\n");
+               return -EINVAL;
+       }
+
+       ret = of_property_read_u32(np, "num-ib-windows", &ep->num_ib_windows);
+       if (ret < 0) {
+               dev_err(dev, "unable to read *num-ib-windows* property\n");
+               return ret;
+       }
+
+       ret = of_property_read_u32(np, "num-ob-windows", &ep->num_ob_windows);
+       if (ret < 0) {
+               dev_err(dev, "unable to read *num-ob-windows* property\n");
+               return ret;
+       }
+
+       addr = devm_kzalloc(dev, sizeof(phys_addr_t) * ep->num_ob_windows,
+                           GFP_KERNEL);
+       if (!addr)
+               return -ENOMEM;
+       ep->outbound_addr = addr;
+
+       for (bar = BAR_0; bar <= BAR_5; bar++)
+               dw_pcie_ep_reset_bar(pci, bar);
+
+       if (ep->ops->ep_init)
+               ep->ops->ep_init(ep);
+
+       epc = devm_pci_epc_create(dev, &epc_ops);
+       if (IS_ERR(epc)) {
+               dev_err(dev, "failed to create epc device\n");
+               return PTR_ERR(epc);
+       }
+
+       ret = of_property_read_u8(np, "max-functions", &epc->max_functions);
+       if (ret < 0)
+               epc->max_functions = 1;
+
+       ret = pci_epc_mem_init(epc, ep->phys_base, ep->addr_size);
+       if (ret < 0) {
+               dev_err(dev, "Failed to initialize address space\n");
+               return ret;
+       }
+
+       ep->epc = epc;
+       epc_set_drvdata(epc, ep);
+       dw_pcie_setup(pci);
+
+       return 0;
+}
index 5ba334938b52273917c160c829aae9baca267ebf..28ed32ba4f1bf400fa384b9880593db7f16793cc 100644 (file)
@@ -56,24 +56,25 @@ static struct irq_chip dw_msi_irq_chip = {
 /* MSI int handler */
 irqreturn_t dw_handle_msi_irq(struct pcie_port *pp)
 {
-       unsigned long val;
+       u32 val;
        int i, pos, irq;
        irqreturn_t ret = IRQ_NONE;
 
        for (i = 0; i < MAX_MSI_CTRLS; i++) {
                dw_pcie_rd_own_conf(pp, PCIE_MSI_INTR0_STATUS + i * 12, 4,
-                                   (u32 *)&val);
-               if (val) {
-                       ret = IRQ_HANDLED;
-                       pos = 0;
-                       while ((pos = find_next_bit(&val, 32, pos)) != 32) {
-                               irq = irq_find_mapping(pp->irq_domain,
-                                                      i * 32 + pos);
-                               dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_STATUS +
-                                                   i * 12, 4, 1 << pos);
-                               generic_handle_irq(irq);
-                               pos++;
-                       }
+                                   &val);
+               if (!val)
+                       continue;
+
+               ret = IRQ_HANDLED;
+               pos = 0;
+               while ((pos = find_next_bit((unsigned long *) &val, 32,
+                                           pos)) != 32) {
+                       irq = irq_find_mapping(pp->irq_domain, i * 32 + pos);
+                       dw_pcie_wr_own_conf(pp, PCIE_MSI_INTR0_STATUS + i * 12,
+                                           4, 1 << pos);
+                       generic_handle_irq(irq);
+                       pos++;
                }
        }
 
@@ -338,8 +339,9 @@ int dw_pcie_host_init(struct pcie_port *pp)
        }
 
        if (!pci->dbi_base) {
-               pci->dbi_base = devm_ioremap(dev, pp->cfg->start,
-                                       resource_size(pp->cfg));
+               pci->dbi_base = devm_pci_remap_cfgspace(dev,
+                                               pp->cfg->start,
+                                               resource_size(pp->cfg));
                if (!pci->dbi_base) {
                        dev_err(dev, "error with ioremap\n");
                        ret = -ENOMEM;
@@ -350,8 +352,8 @@ int dw_pcie_host_init(struct pcie_port *pp)
        pp->mem_base = pp->mem->start;
 
        if (!pp->va_cfg0_base) {
-               pp->va_cfg0_base = devm_ioremap(dev, pp->cfg0_base,
-                                               pp->cfg0_size);
+               pp->va_cfg0_base = devm_pci_remap_cfgspace(dev,
+                                       pp->cfg0_base, pp->cfg0_size);
                if (!pp->va_cfg0_base) {
                        dev_err(dev, "error with ioremap in function\n");
                        ret = -ENOMEM;
@@ -360,7 +362,8 @@ int dw_pcie_host_init(struct pcie_port *pp)
        }
 
        if (!pp->va_cfg1_base) {
-               pp->va_cfg1_base = devm_ioremap(dev, pp->cfg1_base,
+               pp->va_cfg1_base = devm_pci_remap_cfgspace(dev,
+                                               pp->cfg1_base,
                                                pp->cfg1_size);
                if (!pp->va_cfg1_base) {
                        dev_err(dev, "error with ioremap\n");
index f20d494922ab890badd99dd96af9bcad866f2ca2..32091b32f6e1e43b52ecec7f40a4d5e26105e891 100644 (file)
@@ -133,6 +133,7 @@ static struct platform_driver dw_plat_pcie_driver = {
        .driver = {
                .name   = "dw-pcie",
                .of_match_table = dw_plat_pcie_of_match,
+               .suppress_bind_attrs = true,
        },
        .probe = dw_plat_pcie_probe,
 };
index 7e1fb7d6643cfe4c01e294220e4f8284f1b356e2..0e03af279259b735ade878bf96be3963270c1b15 100644 (file)
@@ -61,91 +61,253 @@ int dw_pcie_write(void __iomem *addr, int size, u32 val)
        return PCIBIOS_SUCCESSFUL;
 }
 
-u32 dw_pcie_readl_dbi(struct dw_pcie *pci, u32 reg)
+u32 __dw_pcie_read_dbi(struct dw_pcie *pci, void __iomem *base, u32 reg,
+                      size_t size)
 {
-       if (pci->ops->readl_dbi)
-               return pci->ops->readl_dbi(pci, reg);
+       int ret;
+       u32 val;
 
-       return readl(pci->dbi_base + reg);
+       if (pci->ops->read_dbi)
+               return pci->ops->read_dbi(pci, base, reg, size);
+
+       ret = dw_pcie_read(base + reg, size, &val);
+       if (ret)
+               dev_err(pci->dev, "read DBI address failed\n");
+
+       return val;
 }
 
-void dw_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val)
+void __dw_pcie_write_dbi(struct dw_pcie *pci, void __iomem *base, u32 reg,
+                        size_t size, u32 val)
 {
-       if (pci->ops->writel_dbi)
-               pci->ops->writel_dbi(pci, reg, val);
-       else
-               writel(val, pci->dbi_base + reg);
+       int ret;
+
+       if (pci->ops->write_dbi) {
+               pci->ops->write_dbi(pci, base, reg, size, val);
+               return;
+       }
+
+       ret = dw_pcie_write(base + reg, size, val);
+       if (ret)
+               dev_err(pci->dev, "write DBI address failed\n");
 }
 
-static u32 dw_pcie_readl_unroll(struct dw_pcie *pci, u32 index, u32 reg)
+static u32 dw_pcie_readl_ob_unroll(struct dw_pcie *pci, u32 index, u32 reg)
 {
        u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
 
        return dw_pcie_readl_dbi(pci, offset + reg);
 }
 
-static void dw_pcie_writel_unroll(struct dw_pcie *pci, u32 index, u32 reg,
-                                 u32 val)
+static void dw_pcie_writel_ob_unroll(struct dw_pcie *pci, u32 index, u32 reg,
+                                    u32 val)
 {
        u32 offset = PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(index);
 
        dw_pcie_writel_dbi(pci, offset + reg, val);
 }
 
+void dw_pcie_prog_outbound_atu_unroll(struct dw_pcie *pci, int index, int type,
+                                     u64 cpu_addr, u64 pci_addr, u32 size)
+{
+       u32 retries, val;
+
+       dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LOWER_BASE,
+                                lower_32_bits(cpu_addr));
+       dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_BASE,
+                                upper_32_bits(cpu_addr));
+       dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LIMIT,
+                                lower_32_bits(cpu_addr + size - 1));
+       dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_LOWER_TARGET,
+                                lower_32_bits(pci_addr));
+       dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_UPPER_TARGET,
+                                upper_32_bits(pci_addr));
+       dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL1,
+                                type);
+       dw_pcie_writel_ob_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL2,
+                                PCIE_ATU_ENABLE);
+
+       /*
+        * Make sure ATU enable takes effect before any subsequent config
+        * and I/O accesses.
+        */
+       for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) {
+               val = dw_pcie_readl_ob_unroll(pci, index,
+                                             PCIE_ATU_UNR_REGION_CTRL2);
+               if (val & PCIE_ATU_ENABLE)
+                       return;
+
+               usleep_range(LINK_WAIT_IATU_MIN, LINK_WAIT_IATU_MAX);
+       }
+       dev_err(pci->dev, "outbound iATU is not being enabled\n");
+}
+
 void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index, int type,
                               u64 cpu_addr, u64 pci_addr, u32 size)
 {
        u32 retries, val;
 
+       if (pci->ops->cpu_addr_fixup)
+               cpu_addr = pci->ops->cpu_addr_fixup(cpu_addr);
+
        if (pci->iatu_unroll_enabled) {
-               dw_pcie_writel_unroll(pci, index, PCIE_ATU_UNR_LOWER_BASE,
-                                     lower_32_bits(cpu_addr));
-               dw_pcie_writel_unroll(pci, index, PCIE_ATU_UNR_UPPER_BASE,
-                                     upper_32_bits(cpu_addr));
-               dw_pcie_writel_unroll(pci, index, PCIE_ATU_UNR_LIMIT,
-                                     lower_32_bits(cpu_addr + size - 1));
-               dw_pcie_writel_unroll(pci, index, PCIE_ATU_UNR_LOWER_TARGET,
-                                     lower_32_bits(pci_addr));
-               dw_pcie_writel_unroll(pci, index, PCIE_ATU_UNR_UPPER_TARGET,
-                                     upper_32_bits(pci_addr));
-               dw_pcie_writel_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL1,
-                                     type);
-               dw_pcie_writel_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL2,
-                                     PCIE_ATU_ENABLE);
-       } else {
-               dw_pcie_writel_dbi(pci, PCIE_ATU_VIEWPORT,
-                                  PCIE_ATU_REGION_OUTBOUND | index);
-               dw_pcie_writel_dbi(pci, PCIE_ATU_LOWER_BASE,
-                                  lower_32_bits(cpu_addr));
-               dw_pcie_writel_dbi(pci, PCIE_ATU_UPPER_BASE,
-                                  upper_32_bits(cpu_addr));
-               dw_pcie_writel_dbi(pci, PCIE_ATU_LIMIT,
-                                  lower_32_bits(cpu_addr + size - 1));
-               dw_pcie_writel_dbi(pci, PCIE_ATU_LOWER_TARGET,
-                                  lower_32_bits(pci_addr));
-               dw_pcie_writel_dbi(pci, PCIE_ATU_UPPER_TARGET,
-                                  upper_32_bits(pci_addr));
-               dw_pcie_writel_dbi(pci, PCIE_ATU_CR1, type);
-               dw_pcie_writel_dbi(pci, PCIE_ATU_CR2, PCIE_ATU_ENABLE);
+               dw_pcie_prog_outbound_atu_unroll(pci, index, type, cpu_addr,
+                                                pci_addr, size);
+               return;
        }
 
+       dw_pcie_writel_dbi(pci, PCIE_ATU_VIEWPORT,
+                          PCIE_ATU_REGION_OUTBOUND | index);
+       dw_pcie_writel_dbi(pci, PCIE_ATU_LOWER_BASE,
+                          lower_32_bits(cpu_addr));
+       dw_pcie_writel_dbi(pci, PCIE_ATU_UPPER_BASE,
+                          upper_32_bits(cpu_addr));
+       dw_pcie_writel_dbi(pci, PCIE_ATU_LIMIT,
+                          lower_32_bits(cpu_addr + size - 1));
+       dw_pcie_writel_dbi(pci, PCIE_ATU_LOWER_TARGET,
+                          lower_32_bits(pci_addr));
+       dw_pcie_writel_dbi(pci, PCIE_ATU_UPPER_TARGET,
+                          upper_32_bits(pci_addr));
+       dw_pcie_writel_dbi(pci, PCIE_ATU_CR1, type);
+       dw_pcie_writel_dbi(pci, PCIE_ATU_CR2, PCIE_ATU_ENABLE);
+
        /*
         * Make sure ATU enable takes effect before any subsequent config
         * and I/O accesses.
         */
        for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) {
-               if (pci->iatu_unroll_enabled)
-                       val = dw_pcie_readl_unroll(pci, index,
-                                                  PCIE_ATU_UNR_REGION_CTRL2);
-               else
-                       val = dw_pcie_readl_dbi(pci, PCIE_ATU_CR2);
-
+               val = dw_pcie_readl_dbi(pci, PCIE_ATU_CR2);
                if (val == PCIE_ATU_ENABLE)
                        return;
 
                usleep_range(LINK_WAIT_IATU_MIN, LINK_WAIT_IATU_MAX);
        }
-       dev_err(pci->dev, "iATU is not being enabled\n");
+       dev_err(pci->dev, "outbound iATU is not being enabled\n");
+}
+
+static u32 dw_pcie_readl_ib_unroll(struct dw_pcie *pci, u32 index, u32 reg)
+{
+       u32 offset = PCIE_GET_ATU_INB_UNR_REG_OFFSET(index);
+
+       return dw_pcie_readl_dbi(pci, offset + reg);
+}
+
+static void dw_pcie_writel_ib_unroll(struct dw_pcie *pci, u32 index, u32 reg,
+                                    u32 val)
+{
+       u32 offset = PCIE_GET_ATU_INB_UNR_REG_OFFSET(index);
+
+       dw_pcie_writel_dbi(pci, offset + reg, val);
+}
+
+int dw_pcie_prog_inbound_atu_unroll(struct dw_pcie *pci, int index, int bar,
+                                   u64 cpu_addr, enum dw_pcie_as_type as_type)
+{
+       int type;
+       u32 retries, val;
+
+       dw_pcie_writel_ib_unroll(pci, index, PCIE_ATU_UNR_LOWER_TARGET,
+                                lower_32_bits(cpu_addr));
+       dw_pcie_writel_ib_unroll(pci, index, PCIE_ATU_UNR_UPPER_TARGET,
+                                upper_32_bits(cpu_addr));
+
+       switch (as_type) {
+       case DW_PCIE_AS_MEM:
+               type = PCIE_ATU_TYPE_MEM;
+               break;
+       case DW_PCIE_AS_IO:
+               type = PCIE_ATU_TYPE_IO;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       dw_pcie_writel_ib_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL1, type);
+       dw_pcie_writel_ib_unroll(pci, index, PCIE_ATU_UNR_REGION_CTRL2,
+                                PCIE_ATU_ENABLE |
+                                PCIE_ATU_BAR_MODE_ENABLE | (bar << 8));
+
+       /*
+        * Make sure ATU enable takes effect before any subsequent config
+        * and I/O accesses.
+        */
+       for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) {
+               val = dw_pcie_readl_ib_unroll(pci, index,
+                                             PCIE_ATU_UNR_REGION_CTRL2);
+               if (val & PCIE_ATU_ENABLE)
+                       return 0;
+
+               usleep_range(LINK_WAIT_IATU_MIN, LINK_WAIT_IATU_MAX);
+       }
+       dev_err(pci->dev, "inbound iATU is not being enabled\n");
+
+       return -EBUSY;
+}
+
+int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int bar,
+                            u64 cpu_addr, enum dw_pcie_as_type as_type)
+{
+       int type;
+       u32 retries, val;
+
+       if (pci->iatu_unroll_enabled)
+               return dw_pcie_prog_inbound_atu_unroll(pci, index, bar,
+                                                      cpu_addr, as_type);
+
+       dw_pcie_writel_dbi(pci, PCIE_ATU_VIEWPORT, PCIE_ATU_REGION_INBOUND |
+                          index);
+       dw_pcie_writel_dbi(pci, PCIE_ATU_LOWER_TARGET, lower_32_bits(cpu_addr));
+       dw_pcie_writel_dbi(pci, PCIE_ATU_UPPER_TARGET, upper_32_bits(cpu_addr));
+
+       switch (as_type) {
+       case DW_PCIE_AS_MEM:
+               type = PCIE_ATU_TYPE_MEM;
+               break;
+       case DW_PCIE_AS_IO:
+               type = PCIE_ATU_TYPE_IO;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       dw_pcie_writel_dbi(pci, PCIE_ATU_CR1, type);
+       dw_pcie_writel_dbi(pci, PCIE_ATU_CR2, PCIE_ATU_ENABLE
+                          | PCIE_ATU_BAR_MODE_ENABLE | (bar << 8));
+
+       /*
+        * Make sure ATU enable takes effect before any subsequent config
+        * and I/O accesses.
+        */
+       for (retries = 0; retries < LINK_WAIT_MAX_IATU_RETRIES; retries++) {
+               val = dw_pcie_readl_dbi(pci, PCIE_ATU_CR2);
+               if (val & PCIE_ATU_ENABLE)
+                       return 0;
+
+               usleep_range(LINK_WAIT_IATU_MIN, LINK_WAIT_IATU_MAX);
+       }
+       dev_err(pci->dev, "inbound iATU is not being enabled\n");
+
+       return -EBUSY;
+}
+
+void dw_pcie_disable_atu(struct dw_pcie *pci, int index,
+                        enum dw_pcie_region_type type)
+{
+       int region;
+
+       switch (type) {
+       case DW_PCIE_REGION_INBOUND:
+               region = PCIE_ATU_REGION_INBOUND;
+               break;
+       case DW_PCIE_REGION_OUTBOUND:
+               region = PCIE_ATU_REGION_OUTBOUND;
+               break;
+       default:
+               return;
+       }
+
+       dw_pcie_writel_dbi(pci, PCIE_ATU_VIEWPORT, region | index);
+       dw_pcie_writel_dbi(pci, PCIE_ATU_CR2, ~PCIE_ATU_ENABLE);
 }
 
 int dw_pcie_wait_for_link(struct dw_pcie *pci)
index cd3b8713fe5044a7d3e4366f201972759ce3fcab..c6a840575796ff1bcc2617c4eb40f003668a3a4e 100644 (file)
@@ -18,6 +18,9 @@
 #include <linux/msi.h>
 #include <linux/pci.h>
 
+#include <linux/pci-epc.h>
+#include <linux/pci-epf.h>
+
 /* Parameters for the waiting for link up routine */
 #define LINK_WAIT_MAX_RETRIES          10
 #define LINK_WAIT_USLEEP_MIN           90000
 #define PCIE_GET_ATU_OUTB_UNR_REG_OFFSET(region)       \
                        ((0x3 << 20) | ((region) << 9))
 
+#define PCIE_GET_ATU_INB_UNR_REG_OFFSET(region)                                \
+                       ((0x3 << 20) | ((region) << 9) | (0x1 << 8))
+
+#define MSI_MESSAGE_CONTROL            0x52
+#define MSI_CAP_MMC_SHIFT              1
+#define MSI_CAP_MME_SHIFT              4
+#define MSI_CAP_MME_MASK               (7 << MSI_CAP_MME_SHIFT)
+#define MSI_MESSAGE_ADDR_L32           0x54
+#define MSI_MESSAGE_ADDR_U32           0x58
+
 /*
  * Maximum number of MSI IRQs can be 256 per controller. But keep
  * it 32 as of now. Probably we will never need more than 32. If needed,
 
 struct pcie_port;
 struct dw_pcie;
+struct dw_pcie_ep;
+
+enum dw_pcie_region_type {
+       DW_PCIE_REGION_UNKNOWN,
+       DW_PCIE_REGION_INBOUND,
+       DW_PCIE_REGION_OUTBOUND,
+};
+
+enum dw_pcie_device_mode {
+       DW_PCIE_UNKNOWN_TYPE,
+       DW_PCIE_EP_TYPE,
+       DW_PCIE_LEG_EP_TYPE,
+       DW_PCIE_RC_TYPE,
+};
 
 struct dw_pcie_host_ops {
        int (*rd_own_conf)(struct pcie_port *pp, int where, int size, u32 *val);
@@ -142,35 +169,116 @@ struct pcie_port {
        DECLARE_BITMAP(msi_irq_in_use, MAX_MSI_IRQS);
 };
 
+enum dw_pcie_as_type {
+       DW_PCIE_AS_UNKNOWN,
+       DW_PCIE_AS_MEM,
+       DW_PCIE_AS_IO,
+};
+
+struct dw_pcie_ep_ops {
+       void    (*ep_init)(struct dw_pcie_ep *ep);
+       int     (*raise_irq)(struct dw_pcie_ep *ep, enum pci_epc_irq_type type,
+                            u8 interrupt_num);
+};
+
+struct dw_pcie_ep {
+       struct pci_epc          *epc;
+       struct dw_pcie_ep_ops   *ops;
+       phys_addr_t             phys_base;
+       size_t                  addr_size;
+       u8                      bar_to_atu[6];
+       phys_addr_t             *outbound_addr;
+       unsigned long           ib_window_map;
+       unsigned long           ob_window_map;
+       u32                     num_ib_windows;
+       u32                     num_ob_windows;
+};
+
 struct dw_pcie_ops {
-       u32     (*readl_dbi)(struct dw_pcie *pcie, u32 reg);
-       void    (*writel_dbi)(struct dw_pcie *pcie, u32 reg, u32 val);
+       u64     (*cpu_addr_fixup)(u64 cpu_addr);
+       u32     (*read_dbi)(struct dw_pcie *pcie, void __iomem *base, u32 reg,
+                           size_t size);
+       void    (*write_dbi)(struct dw_pcie *pcie, void __iomem *base, u32 reg,
+                            size_t size, u32 val);
        int     (*link_up)(struct dw_pcie *pcie);
+       int     (*start_link)(struct dw_pcie *pcie);
+       void    (*stop_link)(struct dw_pcie *pcie);
 };
 
 struct dw_pcie {
        struct device           *dev;
        void __iomem            *dbi_base;
+       void __iomem            *dbi_base2;
        u32                     num_viewport;
        u8                      iatu_unroll_enabled;
        struct pcie_port        pp;
+       struct dw_pcie_ep       ep;
        const struct dw_pcie_ops *ops;
 };
 
 #define to_dw_pcie_from_pp(port) container_of((port), struct dw_pcie, pp)
 
+#define to_dw_pcie_from_ep(endpoint)   \
+               container_of((endpoint), struct dw_pcie, ep)
+
 int dw_pcie_read(void __iomem *addr, int size, u32 *val);
 int dw_pcie_write(void __iomem *addr, int size, u32 val);
 
-u32 dw_pcie_readl_dbi(struct dw_pcie *pci, u32 reg);
-void dw_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val);
+u32 __dw_pcie_read_dbi(struct dw_pcie *pci, void __iomem *base, u32 reg,
+                      size_t size);
+void __dw_pcie_write_dbi(struct dw_pcie *pci, void __iomem *base, u32 reg,
+                        size_t size, u32 val);
 int dw_pcie_link_up(struct dw_pcie *pci);
 int dw_pcie_wait_for_link(struct dw_pcie *pci);
 void dw_pcie_prog_outbound_atu(struct dw_pcie *pci, int index,
                               int type, u64 cpu_addr, u64 pci_addr,
                               u32 size);
+int dw_pcie_prog_inbound_atu(struct dw_pcie *pci, int index, int bar,
+                            u64 cpu_addr, enum dw_pcie_as_type as_type);
+void dw_pcie_disable_atu(struct dw_pcie *pci, int index,
+                        enum dw_pcie_region_type type);
 void dw_pcie_setup(struct dw_pcie *pci);
 
+static inline void dw_pcie_writel_dbi(struct dw_pcie *pci, u32 reg, u32 val)
+{
+       __dw_pcie_write_dbi(pci, pci->dbi_base, reg, 0x4, val);
+}
+
+static inline u32 dw_pcie_readl_dbi(struct dw_pcie *pci, u32 reg)
+{
+       return __dw_pcie_read_dbi(pci, pci->dbi_base, reg, 0x4);
+}
+
+static inline void dw_pcie_writew_dbi(struct dw_pcie *pci, u32 reg, u16 val)
+{
+       __dw_pcie_write_dbi(pci, pci->dbi_base, reg, 0x2, val);
+}
+
+static inline u16 dw_pcie_readw_dbi(struct dw_pcie *pci, u32 reg)
+{
+       return __dw_pcie_read_dbi(pci, pci->dbi_base, reg, 0x2);
+}
+
+static inline void dw_pcie_writeb_dbi(struct dw_pcie *pci, u32 reg, u8 val)
+{
+       __dw_pcie_write_dbi(pci, pci->dbi_base, reg, 0x1, val);
+}
+
+static inline u8 dw_pcie_readb_dbi(struct dw_pcie *pci, u32 reg)
+{
+       return __dw_pcie_read_dbi(pci, pci->dbi_base, reg, 0x1);
+}
+
+static inline void dw_pcie_writel_dbi2(struct dw_pcie *pci, u32 reg, u32 val)
+{
+       __dw_pcie_write_dbi(pci, pci->dbi_base2, reg, 0x4, val);
+}
+
+static inline u32 dw_pcie_readl_dbi2(struct dw_pcie *pci, u32 reg)
+{
+       return __dw_pcie_read_dbi(pci, pci->dbi_base2, reg, 0x4);
+}
+
 #ifdef CONFIG_PCIE_DW_HOST
 irqreturn_t dw_handle_msi_irq(struct pcie_port *pp);
 void dw_pcie_msi_init(struct pcie_port *pp);
@@ -195,4 +303,23 @@ static inline int dw_pcie_host_init(struct pcie_port *pp)
        return 0;
 }
 #endif
+
+#ifdef CONFIG_PCIE_DW_EP
+void dw_pcie_ep_linkup(struct dw_pcie_ep *ep);
+int dw_pcie_ep_init(struct dw_pcie_ep *ep);
+void dw_pcie_ep_exit(struct dw_pcie_ep *ep);
+#else
+static inline void dw_pcie_ep_linkup(struct dw_pcie_ep *ep)
+{
+}
+
+static inline int dw_pcie_ep_init(struct dw_pcie_ep *ep)
+{
+       return 0;
+}
+
+static inline void dw_pcie_ep_exit(struct dw_pcie_ep *ep)
+{
+}
+#endif
 #endif /* _PCIE_DESIGNWARE_H */
index cf9d6a9d9fd4fc17afd19d0e659f5e7cff0a3ca8..e51acee0ddf3b8598bf2044f50e94fc50b1fd513 100644 (file)
@@ -99,7 +99,7 @@ static int hisi_pcie_init(struct pci_config_window *cfg)
                return -ENOMEM;
        }
 
-       reg_base = devm_ioremap(dev, res->start, resource_size(res));
+       reg_base = devm_pci_remap_cfgspace(dev, res->start, resource_size(res));
        if (!reg_base)
                return -ENOMEM;
 
@@ -296,10 +296,9 @@ static int hisi_pcie_probe(struct platform_device *pdev)
        }
 
        reg = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rc_dbi");
-       pci->dbi_base = devm_ioremap_resource(dev, reg);
+       pci->dbi_base = devm_pci_remap_cfg_resource(dev, reg);
        if (IS_ERR(pci->dbi_base))
                return PTR_ERR(pci->dbi_base);
-
        platform_set_drvdata(pdev, hisi_pcie);
 
        ret = hisi_add_pcie_port(hisi_pcie, pdev);
@@ -334,6 +333,7 @@ static struct platform_driver hisi_pcie_driver = {
        .driver = {
                   .name = "hisi-pcie",
                   .of_match_table = hisi_pcie_of_match,
+                  .suppress_bind_attrs = true,
        },
 };
 builtin_platform_driver(hisi_pcie_driver);
@@ -360,7 +360,7 @@ static int hisi_pcie_platform_init(struct pci_config_window *cfg)
                return -EINVAL;
        }
 
-       reg_base = devm_ioremap(dev, res->start, resource_size(res));
+       reg_base = devm_pci_remap_cfgspace(dev, res->start, resource_size(res));
        if (!reg_base)
                return -ENOMEM;
 
@@ -395,6 +395,7 @@ static struct platform_driver hisi_pcie_almost_ecam_driver = {
        .driver = {
                   .name = "hisi-pcie-almost-ecam",
                   .of_match_table = hisi_pcie_almost_ecam_of_match,
+                  .suppress_bind_attrs = true,
        },
 };
 builtin_platform_driver(hisi_pcie_almost_ecam_driver);
index 67eb7f5926ddd2248c53ba3668a0b939e6be1099..5bf23d432fdbf9f23de926273b9d79d154027d93 100644 (file)
@@ -700,7 +700,7 @@ static int qcom_pcie_probe(struct platform_device *pdev)
                return PTR_ERR(pcie->parf);
 
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi");
-       pci->dbi_base = devm_ioremap_resource(dev, res);
+       pci->dbi_base = devm_pci_remap_cfg_resource(dev, res);
        if (IS_ERR(pci->dbi_base))
                return PTR_ERR(pci->dbi_base);
 
index eaa4ea8e2ea4eacec48788bf86a32b8600a4beb5..8ff36b3dbbdf7ebdb8f06fdaea334033467bf31d 100644 (file)
@@ -273,7 +273,7 @@ static int spear13xx_pcie_probe(struct platform_device *pdev)
        }
 
        dbi_base = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dbi");
-       pci->dbi_base = devm_ioremap_resource(dev, dbi_base);
+       pci->dbi_base = devm_pci_remap_cfg_resource(dev, dbi_base);
        if (IS_ERR(pci->dbi_base)) {
                dev_err(dev, "couldn't remap dbi base %p\n", dbi_base);
                ret = PTR_ERR(pci->dbi_base);
@@ -308,6 +308,7 @@ static struct platform_driver spear13xx_pcie_driver = {
        .driver = {
                .name   = "spear-pcie",
                .of_match_table = of_match_ptr(spear13xx_pcie_of_match),
+               .suppress_bind_attrs = true,
        },
 };
 
index 2fee61bb6559408469c795554b87a320695fff24..c228a2eb7faa85ba8b0b0d57da23572c433df0e9 100644 (file)
@@ -84,12 +84,14 @@ struct pci_config_window *pci_ecam_create(struct device *dev,
                if (!cfg->winp)
                        goto err_exit_malloc;
                for (i = 0; i < bus_range; i++) {
-                       cfg->winp[i] = ioremap(cfgres->start + i * bsz, bsz);
+                       cfg->winp[i] =
+                               pci_remap_cfgspace(cfgres->start + i * bsz,
+                                                  bsz);
                        if (!cfg->winp[i])
                                goto err_exit_iomap;
                }
        } else {
-               cfg->win = ioremap(cfgres->start, bus_range * bsz);
+               cfg->win = pci_remap_cfgspace(cfgres->start, bus_range * bsz);
                if (!cfg->win)
                        goto err_exit_iomap;
        }
diff --git a/drivers/pci/endpoint/Kconfig b/drivers/pci/endpoint/Kconfig
new file mode 100644 (file)
index 0000000..c23f146
--- /dev/null
@@ -0,0 +1,31 @@
+#
+# PCI Endpoint Support
+#
+
+menu "PCI Endpoint"
+
+config PCI_ENDPOINT
+       bool "PCI Endpoint Support"
+       help
+          Enable this configuration option to support configurable PCI
+          endpoint. This should be enabled if the platform has a PCI
+          controller that can operate in endpoint mode.
+
+          Enabling this option will build the endpoint library, which
+          includes endpoint controller library and endpoint function
+          library.
+
+          If in doubt, say "N" to disable Endpoint support.
+
+config PCI_ENDPOINT_CONFIGFS
+       bool "PCI Endpoint Configfs Support"
+       depends on PCI_ENDPOINT
+       select CONFIGFS_FS
+       help
+          This will enable the configfs entry that can be used to
+          configure the endpoint function and used to bind the
+          function with a endpoint controller.
+
+source "drivers/pci/endpoint/functions/Kconfig"
+
+endmenu
diff --git a/drivers/pci/endpoint/Makefile b/drivers/pci/endpoint/Makefile
new file mode 100644 (file)
index 0000000..1041f80
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# Makefile for PCI Endpoint Support
+#
+
+obj-$(CONFIG_PCI_ENDPOINT_CONFIGFS)    += pci-ep-cfs.o
+obj-$(CONFIG_PCI_ENDPOINT)             += pci-epc-core.o pci-epf-core.o\
+                                          pci-epc-mem.o functions/
diff --git a/drivers/pci/endpoint/functions/Kconfig b/drivers/pci/endpoint/functions/Kconfig
new file mode 100644 (file)
index 0000000..175edad
--- /dev/null
@@ -0,0 +1,12 @@
+#
+# PCI Endpoint Functions
+#
+
+config PCI_EPF_TEST
+       tristate "PCI Endpoint Test driver"
+       depends on PCI_ENDPOINT
+       help
+          Enable this configuration option to enable the test driver
+          for PCI Endpoint.
+
+          If in doubt, say "N" to disable Endpoint test driver.
diff --git a/drivers/pci/endpoint/functions/Makefile b/drivers/pci/endpoint/functions/Makefile
new file mode 100644 (file)
index 0000000..6d94a48
--- /dev/null
@@ -0,0 +1,5 @@
+#
+# Makefile for PCI Endpoint Functions
+#
+
+obj-$(CONFIG_PCI_EPF_TEST)             += pci-epf-test.o
diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c
new file mode 100644 (file)
index 0000000..53fff80
--- /dev/null
@@ -0,0 +1,510 @@
+/**
+ * Test driver to test endpoint functionality
+ *
+ * Copyright (C) 2017 Texas Instruments
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 of
+ * the License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/crc32.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/pci_ids.h>
+#include <linux/random.h>
+
+#include <linux/pci-epc.h>
+#include <linux/pci-epf.h>
+#include <linux/pci_regs.h>
+
+#define COMMAND_RAISE_LEGACY_IRQ       BIT(0)
+#define COMMAND_RAISE_MSI_IRQ          BIT(1)
+#define MSI_NUMBER_SHIFT               2
+#define MSI_NUMBER_MASK                        (0x3f << MSI_NUMBER_SHIFT)
+#define COMMAND_READ                   BIT(8)
+#define COMMAND_WRITE                  BIT(9)
+#define COMMAND_COPY                   BIT(10)
+
+#define STATUS_READ_SUCCESS            BIT(0)
+#define STATUS_READ_FAIL               BIT(1)
+#define STATUS_WRITE_SUCCESS           BIT(2)
+#define STATUS_WRITE_FAIL              BIT(3)
+#define STATUS_COPY_SUCCESS            BIT(4)
+#define STATUS_COPY_FAIL               BIT(5)
+#define STATUS_IRQ_RAISED              BIT(6)
+#define STATUS_SRC_ADDR_INVALID                BIT(7)
+#define STATUS_DST_ADDR_INVALID                BIT(8)
+
+#define TIMER_RESOLUTION               1
+
+static struct workqueue_struct *kpcitest_workqueue;
+
+struct pci_epf_test {
+       void                    *reg[6];
+       struct pci_epf          *epf;
+       struct delayed_work     cmd_handler;
+};
+
+struct pci_epf_test_reg {
+       u32     magic;
+       u32     command;
+       u32     status;
+       u64     src_addr;
+       u64     dst_addr;
+       u32     size;
+       u32     checksum;
+} __packed;
+
+static struct pci_epf_header test_header = {
+       .vendorid       = PCI_ANY_ID,
+       .deviceid       = PCI_ANY_ID,
+       .baseclass_code = PCI_CLASS_OTHERS,
+       .interrupt_pin  = PCI_INTERRUPT_INTA,
+};
+
+static int bar_size[] = { 512, 1024, 16384, 131072, 1048576 };
+
+static int pci_epf_test_copy(struct pci_epf_test *epf_test)
+{
+       int ret;
+       void __iomem *src_addr;
+       void __iomem *dst_addr;
+       phys_addr_t src_phys_addr;
+       phys_addr_t dst_phys_addr;
+       struct pci_epf *epf = epf_test->epf;
+       struct device *dev = &epf->dev;
+       struct pci_epc *epc = epf->epc;
+       struct pci_epf_test_reg *reg = epf_test->reg[0];
+
+       src_addr = pci_epc_mem_alloc_addr(epc, &src_phys_addr, reg->size);
+       if (!src_addr) {
+               dev_err(dev, "failed to allocate source address\n");
+               reg->status = STATUS_SRC_ADDR_INVALID;
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       ret = pci_epc_map_addr(epc, src_phys_addr, reg->src_addr, reg->size);
+       if (ret) {
+               dev_err(dev, "failed to map source address\n");
+               reg->status = STATUS_SRC_ADDR_INVALID;
+               goto err_src_addr;
+       }
+
+       dst_addr = pci_epc_mem_alloc_addr(epc, &dst_phys_addr, reg->size);
+       if (!dst_addr) {
+               dev_err(dev, "failed to allocate destination address\n");
+               reg->status = STATUS_DST_ADDR_INVALID;
+               ret = -ENOMEM;
+               goto err_src_map_addr;
+       }
+
+       ret = pci_epc_map_addr(epc, dst_phys_addr, reg->dst_addr, reg->size);
+       if (ret) {
+               dev_err(dev, "failed to map destination address\n");
+               reg->status = STATUS_DST_ADDR_INVALID;
+               goto err_dst_addr;
+       }
+
+       memcpy(dst_addr, src_addr, reg->size);
+
+       pci_epc_unmap_addr(epc, dst_phys_addr);
+
+err_dst_addr:
+       pci_epc_mem_free_addr(epc, dst_phys_addr, dst_addr, reg->size);
+
+err_src_map_addr:
+       pci_epc_unmap_addr(epc, src_phys_addr);
+
+err_src_addr:
+       pci_epc_mem_free_addr(epc, src_phys_addr, src_addr, reg->size);
+
+err:
+       return ret;
+}
+
+static int pci_epf_test_read(struct pci_epf_test *epf_test)
+{
+       int ret;
+       void __iomem *src_addr;
+       void *buf;
+       u32 crc32;
+       phys_addr_t phys_addr;
+       struct pci_epf *epf = epf_test->epf;
+       struct device *dev = &epf->dev;
+       struct pci_epc *epc = epf->epc;
+       struct pci_epf_test_reg *reg = epf_test->reg[0];
+
+       src_addr = pci_epc_mem_alloc_addr(epc, &phys_addr, reg->size);
+       if (!src_addr) {
+               dev_err(dev, "failed to allocate address\n");
+               reg->status = STATUS_SRC_ADDR_INVALID;
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       ret = pci_epc_map_addr(epc, phys_addr, reg->src_addr, reg->size);
+       if (ret) {
+               dev_err(dev, "failed to map address\n");
+               reg->status = STATUS_SRC_ADDR_INVALID;
+               goto err_addr;
+       }
+
+       buf = kzalloc(reg->size, GFP_KERNEL);
+       if (!buf) {
+               ret = -ENOMEM;
+               goto err_map_addr;
+       }
+
+       memcpy(buf, src_addr, reg->size);
+
+       crc32 = crc32_le(~0, buf, reg->size);
+       if (crc32 != reg->checksum)
+               ret = -EIO;
+
+       kfree(buf);
+
+err_map_addr:
+       pci_epc_unmap_addr(epc, phys_addr);
+
+err_addr:
+       pci_epc_mem_free_addr(epc, phys_addr, src_addr, reg->size);
+
+err:
+       return ret;
+}
+
+static int pci_epf_test_write(struct pci_epf_test *epf_test)
+{
+       int ret;
+       void __iomem *dst_addr;
+       void *buf;
+       phys_addr_t phys_addr;
+       struct pci_epf *epf = epf_test->epf;
+       struct device *dev = &epf->dev;
+       struct pci_epc *epc = epf->epc;
+       struct pci_epf_test_reg *reg = epf_test->reg[0];
+
+       dst_addr = pci_epc_mem_alloc_addr(epc, &phys_addr, reg->size);
+       if (!dst_addr) {
+               dev_err(dev, "failed to allocate address\n");
+               reg->status = STATUS_DST_ADDR_INVALID;
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       ret = pci_epc_map_addr(epc, phys_addr, reg->dst_addr, reg->size);
+       if (ret) {
+               dev_err(dev, "failed to map address\n");
+               reg->status = STATUS_DST_ADDR_INVALID;
+               goto err_addr;
+       }
+
+       buf = kzalloc(reg->size, GFP_KERNEL);
+       if (!buf) {
+               ret = -ENOMEM;
+               goto err_map_addr;
+       }
+
+       get_random_bytes(buf, reg->size);
+       reg->checksum = crc32_le(~0, buf, reg->size);
+
+       memcpy(dst_addr, buf, reg->size);
+
+       /*
+        * wait 1ms inorder for the write to complete. Without this delay L3
+        * error in observed in the host system.
+        */
+       mdelay(1);
+
+       kfree(buf);
+
+err_map_addr:
+       pci_epc_unmap_addr(epc, phys_addr);
+
+err_addr:
+       pci_epc_mem_free_addr(epc, phys_addr, dst_addr, reg->size);
+
+err:
+       return ret;
+}
+
+static void pci_epf_test_raise_irq(struct pci_epf_test *epf_test)
+{
+       u8 irq;
+       u8 msi_count;
+       struct pci_epf *epf = epf_test->epf;
+       struct pci_epc *epc = epf->epc;
+       struct pci_epf_test_reg *reg = epf_test->reg[0];
+
+       reg->status |= STATUS_IRQ_RAISED;
+       msi_count = pci_epc_get_msi(epc);
+       irq = (reg->command & MSI_NUMBER_MASK) >> MSI_NUMBER_SHIFT;
+       if (irq > msi_count || msi_count <= 0)
+               pci_epc_raise_irq(epc, PCI_EPC_IRQ_LEGACY, 0);
+       else
+               pci_epc_raise_irq(epc, PCI_EPC_IRQ_MSI, irq);
+}
+
+static void pci_epf_test_cmd_handler(struct work_struct *work)
+{
+       int ret;
+       u8 irq;
+       u8 msi_count;
+       struct pci_epf_test *epf_test = container_of(work, struct pci_epf_test,
+                                                    cmd_handler.work);
+       struct pci_epf *epf = epf_test->epf;
+       struct pci_epc *epc = epf->epc;
+       struct pci_epf_test_reg *reg = epf_test->reg[0];
+
+       if (!reg->command)
+               goto reset_handler;
+
+       if (reg->command & COMMAND_RAISE_LEGACY_IRQ) {
+               reg->status = STATUS_IRQ_RAISED;
+               pci_epc_raise_irq(epc, PCI_EPC_IRQ_LEGACY, 0);
+               goto reset_handler;
+       }
+
+       if (reg->command & COMMAND_WRITE) {
+               ret = pci_epf_test_write(epf_test);
+               if (ret)
+                       reg->status |= STATUS_WRITE_FAIL;
+               else
+                       reg->status |= STATUS_WRITE_SUCCESS;
+               pci_epf_test_raise_irq(epf_test);
+               goto reset_handler;
+       }
+
+       if (reg->command & COMMAND_READ) {
+               ret = pci_epf_test_read(epf_test);
+               if (!ret)
+                       reg->status |= STATUS_READ_SUCCESS;
+               else
+                       reg->status |= STATUS_READ_FAIL;
+               pci_epf_test_raise_irq(epf_test);
+               goto reset_handler;
+       }
+
+       if (reg->command & COMMAND_COPY) {
+               ret = pci_epf_test_copy(epf_test);
+               if (!ret)
+                       reg->status |= STATUS_COPY_SUCCESS;
+               else
+                       reg->status |= STATUS_COPY_FAIL;
+               pci_epf_test_raise_irq(epf_test);
+               goto reset_handler;
+       }
+
+       if (reg->command & COMMAND_RAISE_MSI_IRQ) {
+               msi_count = pci_epc_get_msi(epc);
+               irq = (reg->command & MSI_NUMBER_MASK) >> MSI_NUMBER_SHIFT;
+               if (irq > msi_count || msi_count <= 0)
+                       goto reset_handler;
+               reg->status = STATUS_IRQ_RAISED;
+               pci_epc_raise_irq(epc, PCI_EPC_IRQ_MSI, irq);
+               goto reset_handler;
+       }
+
+reset_handler:
+       reg->command = 0;
+
+       queue_delayed_work(kpcitest_workqueue, &epf_test->cmd_handler,
+                          msecs_to_jiffies(1));
+}
+
+static void pci_epf_test_linkup(struct pci_epf *epf)
+{
+       struct pci_epf_test *epf_test = epf_get_drvdata(epf);
+
+       queue_delayed_work(kpcitest_workqueue, &epf_test->cmd_handler,
+                          msecs_to_jiffies(1));
+}
+
+static void pci_epf_test_unbind(struct pci_epf *epf)
+{
+       struct pci_epf_test *epf_test = epf_get_drvdata(epf);
+       struct pci_epc *epc = epf->epc;
+       int bar;
+
+       cancel_delayed_work(&epf_test->cmd_handler);
+       pci_epc_stop(epc);
+       for (bar = BAR_0; bar <= BAR_5; bar++) {
+               if (epf_test->reg[bar]) {
+                       pci_epf_free_space(epf, epf_test->reg[bar], bar);
+                       pci_epc_clear_bar(epc, bar);
+               }
+       }
+}
+
+static int pci_epf_test_set_bar(struct pci_epf *epf)
+{
+       int flags;
+       int bar;
+       int ret;
+       struct pci_epf_bar *epf_bar;
+       struct pci_epc *epc = epf->epc;
+       struct device *dev = &epf->dev;
+       struct pci_epf_test *epf_test = epf_get_drvdata(epf);
+
+       flags = PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_32;
+       if (sizeof(dma_addr_t) == 0x8)
+               flags |= PCI_BASE_ADDRESS_MEM_TYPE_64;
+
+       for (bar = BAR_0; bar <= BAR_5; bar++) {
+               epf_bar = &epf->bar[bar];
+               ret = pci_epc_set_bar(epc, bar, epf_bar->phys_addr,
+                                     epf_bar->size, flags);
+               if (ret) {
+                       pci_epf_free_space(epf, epf_test->reg[bar], bar);
+                       dev_err(dev, "failed to set BAR%d\n", bar);
+                       if (bar == BAR_0)
+                               return ret;
+               }
+       }
+
+       return 0;
+}
+
+static int pci_epf_test_alloc_space(struct pci_epf *epf)
+{
+       struct pci_epf_test *epf_test = epf_get_drvdata(epf);
+       struct device *dev = &epf->dev;
+       void *base;
+       int bar;
+
+       base = pci_epf_alloc_space(epf, sizeof(struct pci_epf_test_reg),
+                                  BAR_0);
+       if (!base) {
+               dev_err(dev, "failed to allocated register space\n");
+               return -ENOMEM;
+       }
+       epf_test->reg[0] = base;
+
+       for (bar = BAR_1; bar <= BAR_5; bar++) {
+               base = pci_epf_alloc_space(epf, bar_size[bar - 1], bar);
+               if (!base)
+                       dev_err(dev, "failed to allocate space for BAR%d\n",
+                               bar);
+               epf_test->reg[bar] = base;
+       }
+
+       return 0;
+}
+
+static int pci_epf_test_bind(struct pci_epf *epf)
+{
+       int ret;
+       struct pci_epf_header *header = epf->header;
+       struct pci_epc *epc = epf->epc;
+       struct device *dev = &epf->dev;
+
+       if (WARN_ON_ONCE(!epc))
+               return -EINVAL;
+
+       ret = pci_epc_write_header(epc, header);
+       if (ret) {
+               dev_err(dev, "configuration header write failed\n");
+               return ret;
+       }
+
+       ret = pci_epf_test_alloc_space(epf);
+       if (ret)
+               return ret;
+
+       ret = pci_epf_test_set_bar(epf);
+       if (ret)
+               return ret;
+
+       ret = pci_epc_set_msi(epc, epf->msi_interrupts);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+static int pci_epf_test_probe(struct pci_epf *epf)
+{
+       struct pci_epf_test *epf_test;
+       struct device *dev = &epf->dev;
+
+       epf_test = devm_kzalloc(dev, sizeof(*epf_test), GFP_KERNEL);
+       if (!epf_test)
+               return -ENOMEM;
+
+       epf->header = &test_header;
+       epf_test->epf = epf;
+
+       INIT_DELAYED_WORK(&epf_test->cmd_handler, pci_epf_test_cmd_handler);
+
+       epf_set_drvdata(epf, epf_test);
+       return 0;
+}
+
+static int pci_epf_test_remove(struct pci_epf *epf)
+{
+       struct pci_epf_test *epf_test = epf_get_drvdata(epf);
+
+       kfree(epf_test);
+       return 0;
+}
+
+static struct pci_epf_ops ops = {
+       .unbind = pci_epf_test_unbind,
+       .bind   = pci_epf_test_bind,
+       .linkup = pci_epf_test_linkup,
+};
+
+static const struct pci_epf_device_id pci_epf_test_ids[] = {
+       {
+               .name = "pci_epf_test",
+       },
+       {},
+};
+
+static struct pci_epf_driver test_driver = {
+       .driver.name    = "pci_epf_test",
+       .probe          = pci_epf_test_probe,
+       .remove         = pci_epf_test_remove,
+       .id_table       = pci_epf_test_ids,
+       .ops            = &ops,
+       .owner          = THIS_MODULE,
+};
+
+static int __init pci_epf_test_init(void)
+{
+       int ret;
+
+       kpcitest_workqueue = alloc_workqueue("kpcitest",
+                                            WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
+       ret = pci_epf_register_driver(&test_driver);
+       if (ret) {
+               pr_err("failed to register pci epf test driver --> %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+module_init(pci_epf_test_init);
+
+static void __exit pci_epf_test_exit(void)
+{
+       pci_epf_unregister_driver(&test_driver);
+}
+module_exit(pci_epf_test_exit);
+
+MODULE_DESCRIPTION("PCI EPF TEST DRIVER");
+MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pci/endpoint/pci-ep-cfs.c b/drivers/pci/endpoint/pci-ep-cfs.c
new file mode 100644 (file)
index 0000000..424fdd6
--- /dev/null
@@ -0,0 +1,509 @@
+/**
+ * configfs to configure the PCI endpoint
+ *
+ * Copyright (C) 2017 Texas Instruments
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 of
+ * the License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include <linux/pci-epc.h>
+#include <linux/pci-epf.h>
+#include <linux/pci-ep-cfs.h>
+
+static struct config_group *functions_group;
+static struct config_group *controllers_group;
+
+struct pci_epf_group {
+       struct config_group group;
+       struct pci_epf *epf;
+};
+
+struct pci_epc_group {
+       struct config_group group;
+       struct pci_epc *epc;
+       bool start;
+       unsigned long function_num_map;
+};
+
+static inline struct pci_epf_group *to_pci_epf_group(struct config_item *item)
+{
+       return container_of(to_config_group(item), struct pci_epf_group, group);
+}
+
+static inline struct pci_epc_group *to_pci_epc_group(struct config_item *item)
+{
+       return container_of(to_config_group(item), struct pci_epc_group, group);
+}
+
+static ssize_t pci_epc_start_store(struct config_item *item, const char *page,
+                                  size_t len)
+{
+       int ret;
+       bool start;
+       struct pci_epc *epc;
+       struct pci_epc_group *epc_group = to_pci_epc_group(item);
+
+       epc = epc_group->epc;
+
+       ret = kstrtobool(page, &start);
+       if (ret)
+               return ret;
+
+       if (!start) {
+               pci_epc_stop(epc);
+               return len;
+       }
+
+       ret = pci_epc_start(epc);
+       if (ret) {
+               dev_err(&epc->dev, "failed to start endpoint controller\n");
+               return -EINVAL;
+       }
+
+       epc_group->start = start;
+
+       return len;
+}
+
+static ssize_t pci_epc_start_show(struct config_item *item, char *page)
+{
+       return sprintf(page, "%d\n",
+                      to_pci_epc_group(item)->start);
+}
+
+CONFIGFS_ATTR(pci_epc_, start);
+
+static struct configfs_attribute *pci_epc_attrs[] = {
+       &pci_epc_attr_start,
+       NULL,
+};
+
+static int pci_epc_epf_link(struct config_item *epc_item,
+                           struct config_item *epf_item)
+{
+       int ret;
+       u32 func_no = 0;
+       struct pci_epc *epc;
+       struct pci_epf *epf;
+       struct pci_epf_group *epf_group = to_pci_epf_group(epf_item);
+       struct pci_epc_group *epc_group = to_pci_epc_group(epc_item);
+
+       epc = epc_group->epc;
+       epf = epf_group->epf;
+       ret = pci_epc_add_epf(epc, epf);
+       if (ret)
+               goto err_add_epf;
+
+       func_no = find_first_zero_bit(&epc_group->function_num_map,
+                                     sizeof(epc_group->function_num_map));
+       set_bit(func_no, &epc_group->function_num_map);
+       epf->func_no = func_no;
+
+       ret = pci_epf_bind(epf);
+       if (ret)
+               goto err_epf_bind;
+
+       return 0;
+
+err_epf_bind:
+       pci_epc_remove_epf(epc, epf);
+
+err_add_epf:
+       clear_bit(func_no, &epc_group->function_num_map);
+
+       return ret;
+}
+
+static void pci_epc_epf_unlink(struct config_item *epc_item,
+                              struct config_item *epf_item)
+{
+       struct pci_epc *epc;
+       struct pci_epf *epf;
+       struct pci_epf_group *epf_group = to_pci_epf_group(epf_item);
+       struct pci_epc_group *epc_group = to_pci_epc_group(epc_item);
+
+       WARN_ON_ONCE(epc_group->start);
+
+       epc = epc_group->epc;
+       epf = epf_group->epf;
+       clear_bit(epf->func_no, &epc_group->function_num_map);
+       pci_epf_unbind(epf);
+       pci_epc_remove_epf(epc, epf);
+}
+
+static struct configfs_item_operations pci_epc_item_ops = {
+       .allow_link     = pci_epc_epf_link,
+       .drop_link      = pci_epc_epf_unlink,
+};
+
+static struct config_item_type pci_epc_type = {
+       .ct_item_ops    = &pci_epc_item_ops,
+       .ct_attrs       = pci_epc_attrs,
+       .ct_owner       = THIS_MODULE,
+};
+
+struct config_group *pci_ep_cfs_add_epc_group(const char *name)
+{
+       int ret;
+       struct pci_epc *epc;
+       struct config_group *group;
+       struct pci_epc_group *epc_group;
+
+       epc_group = kzalloc(sizeof(*epc_group), GFP_KERNEL);
+       if (!epc_group) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       group = &epc_group->group;
+
+       config_group_init_type_name(group, name, &pci_epc_type);
+       ret = configfs_register_group(controllers_group, group);
+       if (ret) {
+               pr_err("failed to register configfs group for %s\n", name);
+               goto err_register_group;
+       }
+
+       epc = pci_epc_get(name);
+       if (IS_ERR(epc)) {
+               ret = PTR_ERR(epc);
+               goto err_epc_get;
+       }
+
+       epc_group->epc = epc;
+
+       return group;
+
+err_epc_get:
+       configfs_unregister_group(group);
+
+err_register_group:
+       kfree(epc_group);
+
+err:
+       return ERR_PTR(ret);
+}
+EXPORT_SYMBOL(pci_ep_cfs_add_epc_group);
+
+void pci_ep_cfs_remove_epc_group(struct config_group *group)
+{
+       struct pci_epc_group *epc_group;
+
+       if (!group)
+               return;
+
+       epc_group = container_of(group, struct pci_epc_group, group);
+       pci_epc_put(epc_group->epc);
+       configfs_unregister_group(&epc_group->group);
+       kfree(epc_group);
+}
+EXPORT_SYMBOL(pci_ep_cfs_remove_epc_group);
+
+#define PCI_EPF_HEADER_R(_name)                                                       \
+static ssize_t pci_epf_##_name##_show(struct config_item *item,        char *page)    \
+{                                                                             \
+       struct pci_epf *epf = to_pci_epf_group(item)->epf;                     \
+       if (WARN_ON_ONCE(!epf->header))                                        \
+               return -EINVAL;                                                \
+       return sprintf(page, "0x%04x\n", epf->header->_name);                  \
+}
+
+#define PCI_EPF_HEADER_W_u32(_name)                                           \
+static ssize_t pci_epf_##_name##_store(struct config_item *item,              \
+                                      const char *page, size_t len)           \
+{                                                                             \
+       u32 val;                                                               \
+       int ret;                                                               \
+       struct pci_epf *epf = to_pci_epf_group(item)->epf;                     \
+       if (WARN_ON_ONCE(!epf->header))                                        \
+               return -EINVAL;                                                \
+       ret = kstrtou32(page, 0, &val);                                        \
+       if (ret)                                                               \
+               return ret;                                                    \
+       epf->header->_name = val;                                              \
+       return len;                                                            \
+}
+
+#define PCI_EPF_HEADER_W_u16(_name)                                           \
+static ssize_t pci_epf_##_name##_store(struct config_item *item,              \
+                                      const char *page, size_t len)           \
+{                                                                             \
+       u16 val;                                                               \
+       int ret;                                                               \
+       struct pci_epf *epf = to_pci_epf_group(item)->epf;                     \
+       if (WARN_ON_ONCE(!epf->header))                                        \
+               return -EINVAL;                                                \
+       ret = kstrtou16(page, 0, &val);                                        \
+       if (ret)                                                               \
+               return ret;                                                    \
+       epf->header->_name = val;                                              \
+       return len;                                                            \
+}
+
+#define PCI_EPF_HEADER_W_u8(_name)                                            \
+static ssize_t pci_epf_##_name##_store(struct config_item *item,              \
+                                      const char *page, size_t len)           \
+{                                                                             \
+       u8 val;                                                                \
+       int ret;                                                               \
+       struct pci_epf *epf = to_pci_epf_group(item)->epf;                     \
+       if (WARN_ON_ONCE(!epf->header))                                        \
+               return -EINVAL;                                                \
+       ret = kstrtou8(page, 0, &val);                                         \
+       if (ret)                                                               \
+               return ret;                                                    \
+       epf->header->_name = val;                                              \
+       return len;                                                            \
+}
+
+static ssize_t pci_epf_msi_interrupts_store(struct config_item *item,
+                                           const char *page, size_t len)
+{
+       u8 val;
+       int ret;
+
+       ret = kstrtou8(page, 0, &val);
+       if (ret)
+               return ret;
+
+       to_pci_epf_group(item)->epf->msi_interrupts = val;
+
+       return len;
+}
+
+static ssize_t pci_epf_msi_interrupts_show(struct config_item *item,
+                                          char *page)
+{
+       return sprintf(page, "%d\n",
+                      to_pci_epf_group(item)->epf->msi_interrupts);
+}
+
+PCI_EPF_HEADER_R(vendorid)
+PCI_EPF_HEADER_W_u16(vendorid)
+
+PCI_EPF_HEADER_R(deviceid)
+PCI_EPF_HEADER_W_u16(deviceid)
+
+PCI_EPF_HEADER_R(revid)
+PCI_EPF_HEADER_W_u8(revid)
+
+PCI_EPF_HEADER_R(progif_code)
+PCI_EPF_HEADER_W_u8(progif_code)
+
+PCI_EPF_HEADER_R(subclass_code)
+PCI_EPF_HEADER_W_u8(subclass_code)
+
+PCI_EPF_HEADER_R(baseclass_code)
+PCI_EPF_HEADER_W_u8(baseclass_code)
+
+PCI_EPF_HEADER_R(cache_line_size)
+PCI_EPF_HEADER_W_u8(cache_line_size)
+
+PCI_EPF_HEADER_R(subsys_vendor_id)
+PCI_EPF_HEADER_W_u16(subsys_vendor_id)
+
+PCI_EPF_HEADER_R(subsys_id)
+PCI_EPF_HEADER_W_u16(subsys_id)
+
+PCI_EPF_HEADER_R(interrupt_pin)
+PCI_EPF_HEADER_W_u8(interrupt_pin)
+
+CONFIGFS_ATTR(pci_epf_, vendorid);
+CONFIGFS_ATTR(pci_epf_, deviceid);
+CONFIGFS_ATTR(pci_epf_, revid);
+CONFIGFS_ATTR(pci_epf_, progif_code);
+CONFIGFS_ATTR(pci_epf_, subclass_code);
+CONFIGFS_ATTR(pci_epf_, baseclass_code);
+CONFIGFS_ATTR(pci_epf_, cache_line_size);
+CONFIGFS_ATTR(pci_epf_, subsys_vendor_id);
+CONFIGFS_ATTR(pci_epf_, subsys_id);
+CONFIGFS_ATTR(pci_epf_, interrupt_pin);
+CONFIGFS_ATTR(pci_epf_, msi_interrupts);
+
+static struct configfs_attribute *pci_epf_attrs[] = {
+       &pci_epf_attr_vendorid,
+       &pci_epf_attr_deviceid,
+       &pci_epf_attr_revid,
+       &pci_epf_attr_progif_code,
+       &pci_epf_attr_subclass_code,
+       &pci_epf_attr_baseclass_code,
+       &pci_epf_attr_cache_line_size,
+       &pci_epf_attr_subsys_vendor_id,
+       &pci_epf_attr_subsys_id,
+       &pci_epf_attr_interrupt_pin,
+       &pci_epf_attr_msi_interrupts,
+       NULL,
+};
+
+static void pci_epf_release(struct config_item *item)
+{
+       struct pci_epf_group *epf_group = to_pci_epf_group(item);
+
+       pci_epf_destroy(epf_group->epf);
+       kfree(epf_group);
+}
+
+static struct configfs_item_operations pci_epf_ops = {
+       .release                = pci_epf_release,
+};
+
+static struct config_item_type pci_epf_type = {
+       .ct_item_ops    = &pci_epf_ops,
+       .ct_attrs       = pci_epf_attrs,
+       .ct_owner       = THIS_MODULE,
+};
+
+static struct config_group *pci_epf_make(struct config_group *group,
+                                        const char *name)
+{
+       struct pci_epf_group *epf_group;
+       struct pci_epf *epf;
+
+       epf_group = kzalloc(sizeof(*epf_group), GFP_KERNEL);
+       if (!epf_group)
+               return ERR_PTR(-ENOMEM);
+
+       config_group_init_type_name(&epf_group->group, name, &pci_epf_type);
+
+       epf = pci_epf_create(group->cg_item.ci_name);
+       if (IS_ERR(epf)) {
+               pr_err("failed to create endpoint function device\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       epf_group->epf = epf;
+
+       return &epf_group->group;
+}
+
+static void pci_epf_drop(struct config_group *group, struct config_item *item)
+{
+       config_item_put(item);
+}
+
+static struct configfs_group_operations pci_epf_group_ops = {
+       .make_group     = &pci_epf_make,
+       .drop_item      = &pci_epf_drop,
+};
+
+static struct config_item_type pci_epf_group_type = {
+       .ct_group_ops   = &pci_epf_group_ops,
+       .ct_owner       = THIS_MODULE,
+};
+
+struct config_group *pci_ep_cfs_add_epf_group(const char *name)
+{
+       struct config_group *group;
+
+       group = configfs_register_default_group(functions_group, name,
+                                               &pci_epf_group_type);
+       if (IS_ERR(group))
+               pr_err("failed to register configfs group for %s function\n",
+                      name);
+
+       return group;
+}
+EXPORT_SYMBOL(pci_ep_cfs_add_epf_group);
+
+void pci_ep_cfs_remove_epf_group(struct config_group *group)
+{
+       if (IS_ERR_OR_NULL(group))
+               return;
+
+       configfs_unregister_default_group(group);
+}
+EXPORT_SYMBOL(pci_ep_cfs_remove_epf_group);
+
+static struct config_item_type pci_functions_type = {
+       .ct_owner       = THIS_MODULE,
+};
+
+static struct config_item_type pci_controllers_type = {
+       .ct_owner       = THIS_MODULE,
+};
+
+static struct config_item_type pci_ep_type = {
+       .ct_owner       = THIS_MODULE,
+};
+
+static struct configfs_subsystem pci_ep_cfs_subsys = {
+       .su_group = {
+               .cg_item = {
+                       .ci_namebuf = "pci_ep",
+                       .ci_type = &pci_ep_type,
+               },
+       },
+       .su_mutex = __MUTEX_INITIALIZER(pci_ep_cfs_subsys.su_mutex),
+};
+
+static int __init pci_ep_cfs_init(void)
+{
+       int ret;
+       struct config_group *root = &pci_ep_cfs_subsys.su_group;
+
+       config_group_init(root);
+
+       ret = configfs_register_subsystem(&pci_ep_cfs_subsys);
+       if (ret) {
+               pr_err("Error %d while registering subsystem %s\n",
+                      ret, root->cg_item.ci_namebuf);
+               goto err;
+       }
+
+       functions_group = configfs_register_default_group(root, "functions",
+                                                         &pci_functions_type);
+       if (IS_ERR(functions_group)) {
+               ret = PTR_ERR(functions_group);
+               pr_err("Error %d while registering functions group\n",
+                      ret);
+               goto err_functions_group;
+       }
+
+       controllers_group =
+               configfs_register_default_group(root, "controllers",
+                                               &pci_controllers_type);
+       if (IS_ERR(controllers_group)) {
+               ret = PTR_ERR(controllers_group);
+               pr_err("Error %d while registering controllers group\n",
+                      ret);
+               goto err_controllers_group;
+       }
+
+       return 0;
+
+err_controllers_group:
+       configfs_unregister_default_group(functions_group);
+
+err_functions_group:
+       configfs_unregister_subsystem(&pci_ep_cfs_subsys);
+
+err:
+       return ret;
+}
+module_init(pci_ep_cfs_init);
+
+static void __exit pci_ep_cfs_exit(void)
+{
+       configfs_unregister_default_group(controllers_group);
+       configfs_unregister_default_group(functions_group);
+       configfs_unregister_subsystem(&pci_ep_cfs_subsys);
+}
+module_exit(pci_ep_cfs_exit);
+
+MODULE_DESCRIPTION("PCI EP CONFIGFS");
+MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pci/endpoint/pci-epc-core.c b/drivers/pci/endpoint/pci-epc-core.c
new file mode 100644 (file)
index 0000000..caa7be1
--- /dev/null
@@ -0,0 +1,580 @@
+/**
+ * PCI Endpoint *Controller* (EPC) library
+ *
+ * Copyright (C) 2017 Texas Instruments
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 of
+ * the License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+
+#include <linux/pci-epc.h>
+#include <linux/pci-epf.h>
+#include <linux/pci-ep-cfs.h>
+
+static struct class *pci_epc_class;
+
+static void devm_pci_epc_release(struct device *dev, void *res)
+{
+       struct pci_epc *epc = *(struct pci_epc **)res;
+
+       pci_epc_destroy(epc);
+}
+
+static int devm_pci_epc_match(struct device *dev, void *res, void *match_data)
+{
+       struct pci_epc **epc = res;
+
+       return *epc == match_data;
+}
+
+/**
+ * pci_epc_put() - release the PCI endpoint controller
+ * @epc: epc returned by pci_epc_get()
+ *
+ * release the refcount the caller obtained by invoking pci_epc_get()
+ */
+void pci_epc_put(struct pci_epc *epc)
+{
+       if (!epc || IS_ERR(epc))
+               return;
+
+       module_put(epc->ops->owner);
+       put_device(&epc->dev);
+}
+EXPORT_SYMBOL_GPL(pci_epc_put);
+
+/**
+ * pci_epc_get() - get the PCI endpoint controller
+ * @epc_name: device name of the endpoint controller
+ *
+ * Invoke to get struct pci_epc * corresponding to the device name of the
+ * endpoint controller
+ */
+struct pci_epc *pci_epc_get(const char *epc_name)
+{
+       int ret = -EINVAL;
+       struct pci_epc *epc;
+       struct device *dev;
+       struct class_dev_iter iter;
+
+       class_dev_iter_init(&iter, pci_epc_class, NULL, NULL);
+       while ((dev = class_dev_iter_next(&iter))) {
+               if (strcmp(epc_name, dev_name(dev)))
+                       continue;
+
+               epc = to_pci_epc(dev);
+               if (!try_module_get(epc->ops->owner)) {
+                       ret = -EINVAL;
+                       goto err;
+               }
+
+               class_dev_iter_exit(&iter);
+               get_device(&epc->dev);
+               return epc;
+       }
+
+err:
+       class_dev_iter_exit(&iter);
+       return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(pci_epc_get);
+
+/**
+ * pci_epc_stop() - stop the PCI link
+ * @epc: the link of the EPC device that has to be stopped
+ *
+ * Invoke to stop the PCI link
+ */
+void pci_epc_stop(struct pci_epc *epc)
+{
+       unsigned long flags;
+
+       if (IS_ERR(epc) || !epc->ops->stop)
+               return;
+
+       spin_lock_irqsave(&epc->lock, flags);
+       epc->ops->stop(epc);
+       spin_unlock_irqrestore(&epc->lock, flags);
+}
+EXPORT_SYMBOL_GPL(pci_epc_stop);
+
+/**
+ * pci_epc_start() - start the PCI link
+ * @epc: the link of *this* EPC device has to be started
+ *
+ * Invoke to start the PCI link
+ */
+int pci_epc_start(struct pci_epc *epc)
+{
+       int ret;
+       unsigned long flags;
+
+       if (IS_ERR(epc))
+               return -EINVAL;
+
+       if (!epc->ops->start)
+               return 0;
+
+       spin_lock_irqsave(&epc->lock, flags);
+       ret = epc->ops->start(epc);
+       spin_unlock_irqrestore(&epc->lock, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(pci_epc_start);
+
+/**
+ * pci_epc_raise_irq() - interrupt the host system
+ * @epc: the EPC device which has to interrupt the host
+ * @type: specify the type of interrupt; legacy or MSI
+ * @interrupt_num: the MSI interrupt number
+ *
+ * Invoke to raise an MSI or legacy interrupt
+ */
+int pci_epc_raise_irq(struct pci_epc *epc, enum pci_epc_irq_type type,
+                     u8 interrupt_num)
+{
+       int ret;
+       unsigned long flags;
+
+       if (IS_ERR(epc))
+               return -EINVAL;
+
+       if (!epc->ops->raise_irq)
+               return 0;
+
+       spin_lock_irqsave(&epc->lock, flags);
+       ret = epc->ops->raise_irq(epc, type, interrupt_num);
+       spin_unlock_irqrestore(&epc->lock, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(pci_epc_raise_irq);
+
+/**
+ * pci_epc_get_msi() - get the number of MSI interrupt numbers allocated
+ * @epc: the EPC device to which MSI interrupts was requested
+ *
+ * Invoke to get the number of MSI interrupts allocated by the RC
+ */
+int pci_epc_get_msi(struct pci_epc *epc)
+{
+       int interrupt;
+       unsigned long flags;
+
+       if (IS_ERR(epc))
+               return 0;
+
+       if (!epc->ops->get_msi)
+               return 0;
+
+       spin_lock_irqsave(&epc->lock, flags);
+       interrupt = epc->ops->get_msi(epc);
+       spin_unlock_irqrestore(&epc->lock, flags);
+
+       if (interrupt < 0)
+               return 0;
+
+       interrupt = 1 << interrupt;
+
+       return interrupt;
+}
+EXPORT_SYMBOL_GPL(pci_epc_get_msi);
+
+/**
+ * pci_epc_set_msi() - set the number of MSI interrupt numbers required
+ * @epc: the EPC device on which MSI has to be configured
+ * @interrupts: number of MSI interrupts required by the EPF
+ *
+ * Invoke to set the required number of MSI interrupts.
+ */
+int pci_epc_set_msi(struct pci_epc *epc, u8 interrupts)
+{
+       int ret;
+       u8 encode_int;
+       unsigned long flags;
+
+       if (IS_ERR(epc))
+               return -EINVAL;
+
+       if (!epc->ops->set_msi)
+               return 0;
+
+       encode_int = order_base_2(interrupts);
+
+       spin_lock_irqsave(&epc->lock, flags);
+       ret = epc->ops->set_msi(epc, encode_int);
+       spin_unlock_irqrestore(&epc->lock, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(pci_epc_set_msi);
+
+/**
+ * pci_epc_unmap_addr() - unmap CPU address from PCI address
+ * @epc: the EPC device on which address is allocated
+ * @phys_addr: physical address of the local system
+ *
+ * Invoke to unmap the CPU address from PCI address.
+ */
+void pci_epc_unmap_addr(struct pci_epc *epc, phys_addr_t phys_addr)
+{
+       unsigned long flags;
+
+       if (IS_ERR(epc))
+               return;
+
+       if (!epc->ops->unmap_addr)
+               return;
+
+       spin_lock_irqsave(&epc->lock, flags);
+       epc->ops->unmap_addr(epc, phys_addr);
+       spin_unlock_irqrestore(&epc->lock, flags);
+}
+EXPORT_SYMBOL_GPL(pci_epc_unmap_addr);
+
+/**
+ * pci_epc_map_addr() - map CPU address to PCI address
+ * @epc: the EPC device on which address is allocated
+ * @phys_addr: physical address of the local system
+ * @pci_addr: PCI address to which the physical address should be mapped
+ * @size: the size of the allocation
+ *
+ * Invoke to map CPU address with PCI address.
+ */
+int pci_epc_map_addr(struct pci_epc *epc, phys_addr_t phys_addr,
+                    u64 pci_addr, size_t size)
+{
+       int ret;
+       unsigned long flags;
+
+       if (IS_ERR(epc))
+               return -EINVAL;
+
+       if (!epc->ops->map_addr)
+               return 0;
+
+       spin_lock_irqsave(&epc->lock, flags);
+       ret = epc->ops->map_addr(epc, phys_addr, pci_addr, size);
+       spin_unlock_irqrestore(&epc->lock, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(pci_epc_map_addr);
+
+/**
+ * pci_epc_clear_bar() - reset the BAR
+ * @epc: the EPC device for which the BAR has to be cleared
+ * @bar: the BAR number that has to be reset
+ *
+ * Invoke to reset the BAR of the endpoint device.
+ */
+void pci_epc_clear_bar(struct pci_epc *epc, int bar)
+{
+       unsigned long flags;
+
+       if (IS_ERR(epc))
+               return;
+
+       if (!epc->ops->clear_bar)
+               return;
+
+       spin_lock_irqsave(&epc->lock, flags);
+       epc->ops->clear_bar(epc, bar);
+       spin_unlock_irqrestore(&epc->lock, flags);
+}
+EXPORT_SYMBOL_GPL(pci_epc_clear_bar);
+
+/**
+ * pci_epc_set_bar() - configure BAR in order for host to assign PCI addr space
+ * @epc: the EPC device on which BAR has to be configured
+ * @bar: the BAR number that has to be configured
+ * @size: the size of the addr space
+ * @flags: specify memory allocation/io allocation/32bit address/64 bit address
+ *
+ * Invoke to configure the BAR of the endpoint device.
+ */
+int pci_epc_set_bar(struct pci_epc *epc, enum pci_barno bar,
+                   dma_addr_t bar_phys, size_t size, int flags)
+{
+       int ret;
+       unsigned long irq_flags;
+
+       if (IS_ERR(epc))
+               return -EINVAL;
+
+       if (!epc->ops->set_bar)
+               return 0;
+
+       spin_lock_irqsave(&epc->lock, irq_flags);
+       ret = epc->ops->set_bar(epc, bar, bar_phys, size, flags);
+       spin_unlock_irqrestore(&epc->lock, irq_flags);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(pci_epc_set_bar);
+
+/**
+ * pci_epc_write_header() - write standard configuration header
+ * @epc: the EPC device to which the configuration header should be written
+ * @header: standard configuration header fields
+ *
+ * Invoke to write the configuration header to the endpoint controller. Every
+ * endpoint controller will have a dedicated location to which the standard
+ * configuration header would be written. The callback function should write
+ * the header fields to this dedicated location.
+ */
+int pci_epc_write_header(struct pci_epc *epc, struct pci_epf_header *header)
+{
+       int ret;
+       unsigned long flags;
+
+       if (IS_ERR(epc))
+               return -EINVAL;
+
+       if (!epc->ops->write_header)
+               return 0;
+
+       spin_lock_irqsave(&epc->lock, flags);
+       ret = epc->ops->write_header(epc, header);
+       spin_unlock_irqrestore(&epc->lock, flags);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(pci_epc_write_header);
+
+/**
+ * pci_epc_add_epf() - bind PCI endpoint function to an endpoint controller
+ * @epc: the EPC device to which the endpoint function should be added
+ * @epf: the endpoint function to be added
+ *
+ * A PCI endpoint device can have one or more functions. In the case of PCIe,
+ * the specification allows up to 8 PCIe endpoint functions. Invoke
+ * pci_epc_add_epf() to add a PCI endpoint function to an endpoint controller.
+ */
+int pci_epc_add_epf(struct pci_epc *epc, struct pci_epf *epf)
+{
+       unsigned long flags;
+
+       if (epf->epc)
+               return -EBUSY;
+
+       if (IS_ERR(epc))
+               return -EINVAL;
+
+       if (epf->func_no > epc->max_functions - 1)
+               return -EINVAL;
+
+       epf->epc = epc;
+       dma_set_coherent_mask(&epf->dev, epc->dev.coherent_dma_mask);
+       epf->dev.dma_mask = epc->dev.dma_mask;
+
+       spin_lock_irqsave(&epc->lock, flags);
+       list_add_tail(&epf->list, &epc->pci_epf);
+       spin_unlock_irqrestore(&epc->lock, flags);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(pci_epc_add_epf);
+
+/**
+ * pci_epc_remove_epf() - remove PCI endpoint function from endpoint controller
+ * @epc: the EPC device from which the endpoint function should be removed
+ * @epf: the endpoint function to be removed
+ *
+ * Invoke to remove PCI endpoint function from the endpoint controller.
+ */
+void pci_epc_remove_epf(struct pci_epc *epc, struct pci_epf *epf)
+{
+       unsigned long flags;
+
+       if (!epc || IS_ERR(epc))
+               return;
+
+       spin_lock_irqsave(&epc->lock, flags);
+       list_del(&epf->list);
+       spin_unlock_irqrestore(&epc->lock, flags);
+}
+EXPORT_SYMBOL_GPL(pci_epc_remove_epf);
+
+/**
+ * pci_epc_linkup() - Notify the EPF device that EPC device has established a
+ *                   connection with the Root Complex.
+ * @epc: the EPC device which has established link with the host
+ *
+ * Invoke to Notify the EPF device that the EPC device has established a
+ * connection with the Root Complex.
+ */
+void pci_epc_linkup(struct pci_epc *epc)
+{
+       unsigned long flags;
+       struct pci_epf *epf;
+
+       if (!epc || IS_ERR(epc))
+               return;
+
+       spin_lock_irqsave(&epc->lock, flags);
+       list_for_each_entry(epf, &epc->pci_epf, list)
+               pci_epf_linkup(epf);
+       spin_unlock_irqrestore(&epc->lock, flags);
+}
+EXPORT_SYMBOL_GPL(pci_epc_linkup);
+
+/**
+ * pci_epc_destroy() - destroy the EPC device
+ * @epc: the EPC device that has to be destroyed
+ *
+ * Invoke to destroy the PCI EPC device
+ */
+void pci_epc_destroy(struct pci_epc *epc)
+{
+       pci_ep_cfs_remove_epc_group(epc->group);
+       device_unregister(&epc->dev);
+       kfree(epc);
+}
+EXPORT_SYMBOL_GPL(pci_epc_destroy);
+
+/**
+ * devm_pci_epc_destroy() - destroy the EPC device
+ * @dev: device that wants to destroy the EPC
+ * @epc: the EPC device that has to be destroyed
+ *
+ * Invoke to destroy the devres associated with this
+ * pci_epc and destroy the EPC device.
+ */
+void devm_pci_epc_destroy(struct device *dev, struct pci_epc *epc)
+{
+       int r;
+
+       r = devres_destroy(dev, devm_pci_epc_release, devm_pci_epc_match,
+                          epc);
+       dev_WARN_ONCE(dev, r, "couldn't find PCI EPC resource\n");
+}
+EXPORT_SYMBOL_GPL(devm_pci_epc_destroy);
+
+/**
+ * __pci_epc_create() - create a new endpoint controller (EPC) device
+ * @dev: device that is creating the new EPC
+ * @ops: function pointers for performing EPC operations
+ * @owner: the owner of the module that creates the EPC device
+ *
+ * Invoke to create a new EPC device and add it to pci_epc class.
+ */
+struct pci_epc *
+__pci_epc_create(struct device *dev, const struct pci_epc_ops *ops,
+                struct module *owner)
+{
+       int ret;
+       struct pci_epc *epc;
+
+       if (WARN_ON(!dev)) {
+               ret = -EINVAL;
+               goto err_ret;
+       }
+
+       epc = kzalloc(sizeof(*epc), GFP_KERNEL);
+       if (!epc) {
+               ret = -ENOMEM;
+               goto err_ret;
+       }
+
+       spin_lock_init(&epc->lock);
+       INIT_LIST_HEAD(&epc->pci_epf);
+
+       device_initialize(&epc->dev);
+       dma_set_coherent_mask(&epc->dev, dev->coherent_dma_mask);
+       epc->dev.class = pci_epc_class;
+       epc->dev.dma_mask = dev->dma_mask;
+       epc->ops = ops;
+
+       ret = dev_set_name(&epc->dev, "%s", dev_name(dev));
+       if (ret)
+               goto put_dev;
+
+       ret = device_add(&epc->dev);
+       if (ret)
+               goto put_dev;
+
+       epc->group = pci_ep_cfs_add_epc_group(dev_name(dev));
+
+       return epc;
+
+put_dev:
+       put_device(&epc->dev);
+       kfree(epc);
+
+err_ret:
+       return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(__pci_epc_create);
+
+/**
+ * __devm_pci_epc_create() - create a new endpoint controller (EPC) device
+ * @dev: device that is creating the new EPC
+ * @ops: function pointers for performing EPC operations
+ * @owner: the owner of the module that creates the EPC device
+ *
+ * Invoke to create a new EPC device and add it to pci_epc class.
+ * While at that, it also associates the device with the pci_epc using devres.
+ * On driver detach, release function is invoked on the devres data,
+ * then, devres data is freed.
+ */
+struct pci_epc *
+__devm_pci_epc_create(struct device *dev, const struct pci_epc_ops *ops,
+                     struct module *owner)
+{
+       struct pci_epc **ptr, *epc;
+
+       ptr = devres_alloc(devm_pci_epc_release, sizeof(*ptr), GFP_KERNEL);
+       if (!ptr)
+               return ERR_PTR(-ENOMEM);
+
+       epc = __pci_epc_create(dev, ops, owner);
+       if (!IS_ERR(epc)) {
+               *ptr = epc;
+               devres_add(dev, ptr);
+       } else {
+               devres_free(ptr);
+       }
+
+       return epc;
+}
+EXPORT_SYMBOL_GPL(__devm_pci_epc_create);
+
+static int __init pci_epc_init(void)
+{
+       pci_epc_class = class_create(THIS_MODULE, "pci_epc");
+       if (IS_ERR(pci_epc_class)) {
+               pr_err("failed to create pci epc class --> %ld\n",
+                      PTR_ERR(pci_epc_class));
+               return PTR_ERR(pci_epc_class);
+       }
+
+       return 0;
+}
+module_init(pci_epc_init);
+
+static void __exit pci_epc_exit(void)
+{
+       class_destroy(pci_epc_class);
+}
+module_exit(pci_epc_exit);
+
+MODULE_DESCRIPTION("PCI EPC Library");
+MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pci/endpoint/pci-epc-mem.c b/drivers/pci/endpoint/pci-epc-mem.c
new file mode 100644 (file)
index 0000000..3a94cc1
--- /dev/null
@@ -0,0 +1,143 @@
+/**
+ * PCI Endpoint *Controller* Address Space Management
+ *
+ * Copyright (C) 2017 Texas Instruments
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 of
+ * the License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include <linux/pci-epc.h>
+
+/**
+ * pci_epc_mem_init() - initialize the pci_epc_mem structure
+ * @epc: the EPC device that invoked pci_epc_mem_init
+ * @phys_base: the physical address of the base
+ * @size: the size of the address space
+ *
+ * Invoke to initialize the pci_epc_mem structure used by the
+ * endpoint functions to allocate mapped PCI address.
+ */
+int pci_epc_mem_init(struct pci_epc *epc, phys_addr_t phys_base, size_t size)
+{
+       int ret;
+       struct pci_epc_mem *mem;
+       unsigned long *bitmap;
+       int pages = size >> PAGE_SHIFT;
+       int bitmap_size = BITS_TO_LONGS(pages) * sizeof(long);
+
+       mem = kzalloc(sizeof(*mem), GFP_KERNEL);
+       if (!mem) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       bitmap = kzalloc(bitmap_size, GFP_KERNEL);
+       if (!bitmap) {
+               ret = -ENOMEM;
+               goto err_mem;
+       }
+
+       mem->bitmap = bitmap;
+       mem->phys_base = phys_base;
+       mem->pages = pages;
+       mem->size = size;
+
+       epc->mem = mem;
+
+       return 0;
+
+err_mem:
+       kfree(mem);
+
+err:
+return ret;
+}
+EXPORT_SYMBOL_GPL(pci_epc_mem_init);
+
+/**
+ * pci_epc_mem_exit() - cleanup the pci_epc_mem structure
+ * @epc: the EPC device that invoked pci_epc_mem_exit
+ *
+ * Invoke to cleanup the pci_epc_mem structure allocated in
+ * pci_epc_mem_init().
+ */
+void pci_epc_mem_exit(struct pci_epc *epc)
+{
+       struct pci_epc_mem *mem = epc->mem;
+
+       epc->mem = NULL;
+       kfree(mem->bitmap);
+       kfree(mem);
+}
+EXPORT_SYMBOL_GPL(pci_epc_mem_exit);
+
+/**
+ * pci_epc_mem_alloc_addr() - allocate memory address from EPC addr space
+ * @epc: the EPC device on which memory has to be allocated
+ * @phys_addr: populate the allocated physical address here
+ * @size: the size of the address space that has to be allocated
+ *
+ * Invoke to allocate memory address from the EPC address space. This
+ * is usually done to map the remote RC address into the local system.
+ */
+void __iomem *pci_epc_mem_alloc_addr(struct pci_epc *epc,
+                                    phys_addr_t *phys_addr, size_t size)
+{
+       int pageno;
+       void __iomem *virt_addr;
+       struct pci_epc_mem *mem = epc->mem;
+       int order = get_order(size);
+
+       pageno = bitmap_find_free_region(mem->bitmap, mem->pages, order);
+       if (pageno < 0)
+               return NULL;
+
+       *phys_addr = mem->phys_base + (pageno << PAGE_SHIFT);
+       virt_addr = ioremap(*phys_addr, size);
+       if (!virt_addr)
+               bitmap_release_region(mem->bitmap, pageno, order);
+
+       return virt_addr;
+}
+EXPORT_SYMBOL_GPL(pci_epc_mem_alloc_addr);
+
+/**
+ * pci_epc_mem_free_addr() - free the allocated memory address
+ * @epc: the EPC device on which memory was allocated
+ * @phys_addr: the allocated physical address
+ * @virt_addr: virtual address of the allocated mem space
+ * @size: the size of the allocated address space
+ *
+ * Invoke to free the memory allocated using pci_epc_mem_alloc_addr.
+ */
+void pci_epc_mem_free_addr(struct pci_epc *epc, phys_addr_t phys_addr,
+                          void __iomem *virt_addr, size_t size)
+{
+       int pageno;
+       int order = get_order(size);
+       struct pci_epc_mem *mem = epc->mem;
+
+       iounmap(virt_addr);
+       pageno = (phys_addr - mem->phys_base) >> PAGE_SHIFT;
+       bitmap_release_region(mem->bitmap, pageno, order);
+}
+EXPORT_SYMBOL_GPL(pci_epc_mem_free_addr);
+
+MODULE_DESCRIPTION("PCI EPC Address Space Management");
+MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/pci/endpoint/pci-epf-core.c b/drivers/pci/endpoint/pci-epf-core.c
new file mode 100644 (file)
index 0000000..6877d6a
--- /dev/null
@@ -0,0 +1,359 @@
+/**
+ * PCI Endpoint *Function* (EPF) library
+ *
+ * Copyright (C) 2017 Texas Instruments
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 of
+ * the License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+
+#include <linux/pci-epc.h>
+#include <linux/pci-epf.h>
+#include <linux/pci-ep-cfs.h>
+
+static struct bus_type pci_epf_bus_type;
+static struct device_type pci_epf_type;
+
+/**
+ * pci_epf_linkup() - Notify the function driver that EPC device has
+ *                   established a connection with the Root Complex.
+ * @epf: the EPF device bound to the EPC device which has established
+ *      the connection with the host
+ *
+ * Invoke to notify the function driver that EPC device has established
+ * a connection with the Root Complex.
+ */
+void pci_epf_linkup(struct pci_epf *epf)
+{
+       if (!epf->driver) {
+               dev_WARN(&epf->dev, "epf device not bound to driver\n");
+               return;
+       }
+
+       epf->driver->ops->linkup(epf);
+}
+EXPORT_SYMBOL_GPL(pci_epf_linkup);
+
+/**
+ * pci_epf_unbind() - Notify the function driver that the binding between the
+ *                   EPF device and EPC device has been lost
+ * @epf: the EPF device which has lost the binding with the EPC device
+ *
+ * Invoke to notify the function driver that the binding between the EPF device
+ * and EPC device has been lost.
+ */
+void pci_epf_unbind(struct pci_epf *epf)
+{
+       if (!epf->driver) {
+               dev_WARN(&epf->dev, "epf device not bound to driver\n");
+               return;
+       }
+
+       epf->driver->ops->unbind(epf);
+       module_put(epf->driver->owner);
+}
+EXPORT_SYMBOL_GPL(pci_epf_unbind);
+
+/**
+ * pci_epf_bind() - Notify the function driver that the EPF device has been
+ *                 bound to a EPC device
+ * @epf: the EPF device which has been bound to the EPC device
+ *
+ * Invoke to notify the function driver that it has been bound to a EPC device
+ */
+int pci_epf_bind(struct pci_epf *epf)
+{
+       if (!epf->driver) {
+               dev_WARN(&epf->dev, "epf device not bound to driver\n");
+               return -EINVAL;
+       }
+
+       if (!try_module_get(epf->driver->owner))
+               return -EAGAIN;
+
+       return epf->driver->ops->bind(epf);
+}
+EXPORT_SYMBOL_GPL(pci_epf_bind);
+
+/**
+ * pci_epf_free_space() - free the allocated PCI EPF register space
+ * @addr: the virtual address of the PCI EPF register space
+ * @bar: the BAR number corresponding to the register space
+ *
+ * Invoke to free the allocated PCI EPF register space.
+ */
+void pci_epf_free_space(struct pci_epf *epf, void *addr, enum pci_barno bar)
+{
+       struct device *dev = &epf->dev;
+
+       if (!addr)
+               return;
+
+       dma_free_coherent(dev, epf->bar[bar].size, addr,
+                         epf->bar[bar].phys_addr);
+
+       epf->bar[bar].phys_addr = 0;
+       epf->bar[bar].size = 0;
+}
+EXPORT_SYMBOL_GPL(pci_epf_free_space);
+
+/**
+ * pci_epf_alloc_space() - allocate memory for the PCI EPF register space
+ * @size: the size of the memory that has to be allocated
+ * @bar: the BAR number corresponding to the allocated register space
+ *
+ * Invoke to allocate memory for the PCI EPF register space.
+ */
+void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar)
+{
+       void *space;
+       struct device *dev = &epf->dev;
+       dma_addr_t phys_addr;
+
+       if (size < 128)
+               size = 128;
+       size = roundup_pow_of_two(size);
+
+       space = dma_alloc_coherent(dev, size, &phys_addr, GFP_KERNEL);
+       if (!space) {
+               dev_err(dev, "failed to allocate mem space\n");
+               return NULL;
+       }
+
+       epf->bar[bar].phys_addr = phys_addr;
+       epf->bar[bar].size = size;
+
+       return space;
+}
+EXPORT_SYMBOL_GPL(pci_epf_alloc_space);
+
+/**
+ * pci_epf_unregister_driver() - unregister the PCI EPF driver
+ * @driver: the PCI EPF driver that has to be unregistered
+ *
+ * Invoke to unregister the PCI EPF driver.
+ */
+void pci_epf_unregister_driver(struct pci_epf_driver *driver)
+{
+       pci_ep_cfs_remove_epf_group(driver->group);
+       driver_unregister(&driver->driver);
+}
+EXPORT_SYMBOL_GPL(pci_epf_unregister_driver);
+
+/**
+ * __pci_epf_register_driver() - register a new PCI EPF driver
+ * @driver: structure representing PCI EPF driver
+ * @owner: the owner of the module that registers the PCI EPF driver
+ *
+ * Invoke to register a new PCI EPF driver.
+ */
+int __pci_epf_register_driver(struct pci_epf_driver *driver,
+                             struct module *owner)
+{
+       int ret;
+
+       if (!driver->ops)
+               return -EINVAL;
+
+       if (!driver->ops->bind || !driver->ops->unbind || !driver->ops->linkup)
+               return -EINVAL;
+
+       driver->driver.bus = &pci_epf_bus_type;
+       driver->driver.owner = owner;
+
+       ret = driver_register(&driver->driver);
+       if (ret)
+               return ret;
+
+       driver->group = pci_ep_cfs_add_epf_group(driver->driver.name);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(__pci_epf_register_driver);
+
+/**
+ * pci_epf_destroy() - destroy the created PCI EPF device
+ * @epf: the PCI EPF device that has to be destroyed.
+ *
+ * Invoke to destroy the PCI EPF device created by invoking pci_epf_create().
+ */
+void pci_epf_destroy(struct pci_epf *epf)
+{
+       device_unregister(&epf->dev);
+}
+EXPORT_SYMBOL_GPL(pci_epf_destroy);
+
+/**
+ * pci_epf_create() - create a new PCI EPF device
+ * @name: the name of the PCI EPF device. This name will be used to bind the
+ *       the EPF device to a EPF driver
+ *
+ * Invoke to create a new PCI EPF device by providing the name of the function
+ * device.
+ */
+struct pci_epf *pci_epf_create(const char *name)
+{
+       int ret;
+       struct pci_epf *epf;
+       struct device *dev;
+       char *func_name;
+       char *buf;
+
+       epf = kzalloc(sizeof(*epf), GFP_KERNEL);
+       if (!epf) {
+               ret = -ENOMEM;
+               goto err_ret;
+       }
+
+       buf = kstrdup(name, GFP_KERNEL);
+       if (!buf) {
+               ret = -ENOMEM;
+               goto free_epf;
+       }
+
+       func_name = buf;
+       buf = strchrnul(buf, '.');
+       *buf = '\0';
+
+       epf->name = kstrdup(func_name, GFP_KERNEL);
+       if (!epf->name) {
+               ret = -ENOMEM;
+               goto free_func_name;
+       }
+
+       dev = &epf->dev;
+       device_initialize(dev);
+       dev->bus = &pci_epf_bus_type;
+       dev->type = &pci_epf_type;
+
+       ret = dev_set_name(dev, "%s", name);
+       if (ret)
+               goto put_dev;
+
+       ret = device_add(dev);
+       if (ret)
+               goto put_dev;
+
+       kfree(func_name);
+       return epf;
+
+put_dev:
+       put_device(dev);
+       kfree(epf->name);
+
+free_func_name:
+       kfree(func_name);
+
+free_epf:
+       kfree(epf);
+
+err_ret:
+       return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(pci_epf_create);
+
+static void pci_epf_dev_release(struct device *dev)
+{
+       struct pci_epf *epf = to_pci_epf(dev);
+
+       kfree(epf->name);
+       kfree(epf);
+}
+
+static struct device_type pci_epf_type = {
+       .release        = pci_epf_dev_release,
+};
+
+static int
+pci_epf_match_id(const struct pci_epf_device_id *id, const struct pci_epf *epf)
+{
+       while (id->name[0]) {
+               if (strcmp(epf->name, id->name) == 0)
+                       return true;
+               id++;
+       }
+
+       return false;
+}
+
+static int pci_epf_device_match(struct device *dev, struct device_driver *drv)
+{
+       struct pci_epf *epf = to_pci_epf(dev);
+       struct pci_epf_driver *driver = to_pci_epf_driver(drv);
+
+       if (driver->id_table)
+               return pci_epf_match_id(driver->id_table, epf);
+
+       return !strcmp(epf->name, drv->name);
+}
+
+static int pci_epf_device_probe(struct device *dev)
+{
+       struct pci_epf *epf = to_pci_epf(dev);
+       struct pci_epf_driver *driver = to_pci_epf_driver(dev->driver);
+
+       if (!driver->probe)
+               return -ENODEV;
+
+       epf->driver = driver;
+
+       return driver->probe(epf);
+}
+
+static int pci_epf_device_remove(struct device *dev)
+{
+       int ret;
+       struct pci_epf *epf = to_pci_epf(dev);
+       struct pci_epf_driver *driver = to_pci_epf_driver(dev->driver);
+
+       ret = driver->remove(epf);
+       epf->driver = NULL;
+
+       return ret;
+}
+
+static struct bus_type pci_epf_bus_type = {
+       .name           = "pci-epf",
+       .match          = pci_epf_device_match,
+       .probe          = pci_epf_device_probe,
+       .remove         = pci_epf_device_remove,
+};
+
+static int __init pci_epf_init(void)
+{
+       int ret;
+
+       ret = bus_register(&pci_epf_bus_type);
+       if (ret) {
+               pr_err("failed to register pci epf bus --> %d\n", ret);
+               return ret;
+       }
+
+       return 0;
+}
+module_init(pci_epf_init);
+
+static void __exit pci_epf_exit(void)
+{
+       bus_unregister(&pci_epf_bus_type);
+}
+module_exit(pci_epf_exit);
+
+MODULE_DESCRIPTION("PCI EPF Library");
+MODULE_AUTHOR("Kishon Vijay Abraham I <kishon@ti.com>");
+MODULE_LICENSE("GPL v2");
index f7c1d4d5c665b5c2df520d2dfeabd4e80c6e224d..7f47cd5e10a57c4f7de8f175b3034fe375d6785f 100644 (file)
@@ -27,6 +27,12 @@ config PCIE_XILINX_NWL
         or End Point. The current option selection will only
         support root port enabling.
 
+config PCI_FTPCI100
+       bool "Faraday Technology FTPCI100 PCI controller"
+       depends on OF
+       depends on ARM
+       default ARCH_GEMINI
+
 config PCI_TEGRA
        bool "NVIDIA Tegra PCIe controller"
        depends on ARCH_TEGRA
@@ -95,6 +101,7 @@ config PCI_VERSATILE
 
 config PCIE_IPROC
        tristate
+       select PCI_DOMAINS
        help
          This enables the iProc PCIe core controller support for Broadcom's
          iProc family of SoCs. An appropriate bus interface driver needs
@@ -115,7 +122,6 @@ config PCIE_IPROC_BCMA
        depends on ARM && (ARCH_BCM_IPROC || COMPILE_TEST)
        select PCIE_IPROC
        select BCMA
-       select PCI_DOMAINS
        default ARCH_BCM_5301X
        help
          Say Y here if you want to use the Broadcom iProc PCIe controller
@@ -164,7 +170,7 @@ config PCI_HOST_THUNDER_ECAM
          Say Y here if you want ECAM support for CN88XX-Pass-1.x Cavium Thunder SoCs.
 
 config PCIE_ROCKCHIP
-       bool "Rockchip PCIe controller"
+       tristate "Rockchip PCIe controller"
        depends on ARCH_ROCKCHIP || COMPILE_TEST
        depends on OF
        depends on PCI_MSI_IRQ_DOMAIN
index 4d3686676cc3c9ea21ae2e9933f4208631fc09d7..cab879578003f6c287adbbb058d00aab5d90ff99 100644 (file)
@@ -1,3 +1,4 @@
+obj-$(CONFIG_PCI_FTPCI100) += pci-ftpci100.o
 obj-$(CONFIG_PCI_HYPERV) += pci-hyperv.o
 obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o
 obj-$(CONFIG_PCI_AARDVARK) += pci-aardvark.o
index 4fce494271cc60387c08d5675caa474047727854..37d0bcd31f8a77912e0479b390077f67fbee7938 100644 (file)
@@ -200,10 +200,12 @@ struct advk_pcie {
        struct list_head resources;
        struct irq_domain *irq_domain;
        struct irq_chip irq_chip;
-       struct msi_controller msi;
        struct irq_domain *msi_domain;
+       struct irq_domain *msi_inner_domain;
+       struct irq_chip msi_bottom_irq_chip;
        struct irq_chip msi_irq_chip;
-       DECLARE_BITMAP(msi_irq_in_use, MSI_IRQ_NUM);
+       struct msi_domain_info msi_domain_info;
+       DECLARE_BITMAP(msi_used, MSI_IRQ_NUM);
        struct mutex msi_used_lock;
        u16 msi_msg;
        int root_bus_nr;
@@ -545,94 +547,64 @@ static struct pci_ops advk_pcie_ops = {
        .write = advk_pcie_wr_conf,
 };
 
-static int advk_pcie_alloc_msi(struct advk_pcie *pcie)
+static void advk_msi_irq_compose_msi_msg(struct irq_data *data,
+                                        struct msi_msg *msg)
 {
-       int hwirq;
+       struct advk_pcie *pcie = irq_data_get_irq_chip_data(data);
+       phys_addr_t msi_msg = virt_to_phys(&pcie->msi_msg);
 
-       mutex_lock(&pcie->msi_used_lock);
-       hwirq = find_first_zero_bit(pcie->msi_irq_in_use, MSI_IRQ_NUM);
-       if (hwirq >= MSI_IRQ_NUM)
-               hwirq = -ENOSPC;
-       else
-               set_bit(hwirq, pcie->msi_irq_in_use);
-       mutex_unlock(&pcie->msi_used_lock);
-
-       return hwirq;
+       msg->address_lo = lower_32_bits(msi_msg);
+       msg->address_hi = upper_32_bits(msi_msg);
+       msg->data = data->irq;
 }
 
-static void advk_pcie_free_msi(struct advk_pcie *pcie, int hwirq)
+static int advk_msi_set_affinity(struct irq_data *irq_data,
+                                const struct cpumask *mask, bool force)
 {
-       struct device *dev = &pcie->pdev->dev;
-
-       mutex_lock(&pcie->msi_used_lock);
-       if (!test_bit(hwirq, pcie->msi_irq_in_use))
-               dev_err(dev, "trying to free unused MSI#%d\n", hwirq);
-       else
-               clear_bit(hwirq, pcie->msi_irq_in_use);
-       mutex_unlock(&pcie->msi_used_lock);
+       return -EINVAL;
 }
 
-static int advk_pcie_setup_msi_irq(struct msi_controller *chip,
-                                  struct pci_dev *pdev,
-                                  struct msi_desc *desc)
+static int advk_msi_irq_domain_alloc(struct irq_domain *domain,
+                                    unsigned int virq,
+                                    unsigned int nr_irqs, void *args)
 {
-       struct advk_pcie *pcie = pdev->bus->sysdata;
-       struct msi_msg msg;
-       int virq, hwirq;
-       phys_addr_t msi_msg_phys;
-
-       /* We support MSI, but not MSI-X */
-       if (desc->msi_attrib.is_msix)
-               return -EINVAL;
-
-       hwirq = advk_pcie_alloc_msi(pcie);
-       if (hwirq < 0)
-               return hwirq;
+       struct advk_pcie *pcie = domain->host_data;
+       int hwirq, i;
 
-       virq = irq_create_mapping(pcie->msi_domain, hwirq);
-       if (!virq) {
-               advk_pcie_free_msi(pcie, hwirq);
-               return -EINVAL;
+       mutex_lock(&pcie->msi_used_lock);
+       hwirq = bitmap_find_next_zero_area(pcie->msi_used, MSI_IRQ_NUM,
+                                          0, nr_irqs, 0);
+       if (hwirq >= MSI_IRQ_NUM) {
+               mutex_unlock(&pcie->msi_used_lock);
+               return -ENOSPC;
        }
 
-       irq_set_msi_desc(virq, desc);
-
-       msi_msg_phys = virt_to_phys(&pcie->msi_msg);
-
-       msg.address_lo = lower_32_bits(msi_msg_phys);
-       msg.address_hi = upper_32_bits(msi_msg_phys);
-       msg.data = virq;
-
-       pci_write_msi_msg(virq, &msg);
-
-       return 0;
-}
+       bitmap_set(pcie->msi_used, hwirq, nr_irqs);
+       mutex_unlock(&pcie->msi_used_lock);
 
-static void advk_pcie_teardown_msi_irq(struct msi_controller *chip,
-                                      unsigned int irq)
-{
-       struct irq_data *d = irq_get_irq_data(irq);
-       struct msi_desc *msi = irq_data_get_msi_desc(d);
-       struct advk_pcie *pcie = msi_desc_to_pci_sysdata(msi);
-       unsigned long hwirq = d->hwirq;
+       for (i = 0; i < nr_irqs; i++)
+               irq_domain_set_info(domain, virq + i, hwirq + i,
+                                   &pcie->msi_bottom_irq_chip,
+                                   domain->host_data, handle_simple_irq,
+                                   NULL, NULL);
 
-       irq_dispose_mapping(irq);
-       advk_pcie_free_msi(pcie, hwirq);
+       return hwirq;
 }
 
-static int advk_pcie_msi_map(struct irq_domain *domain,
-                            unsigned int virq, irq_hw_number_t hw)
+static void advk_msi_irq_domain_free(struct irq_domain *domain,
+                                    unsigned int virq, unsigned int nr_irqs)
 {
+       struct irq_data *d = irq_domain_get_irq_data(domain, virq);
        struct advk_pcie *pcie = domain->host_data;
 
-       irq_set_chip_and_handler(virq, &pcie->msi_irq_chip,
-                                handle_simple_irq);
-
-       return 0;
+       mutex_lock(&pcie->msi_used_lock);
+       bitmap_clear(pcie->msi_used, d->hwirq, nr_irqs);
+       mutex_unlock(&pcie->msi_used_lock);
 }
 
-static const struct irq_domain_ops advk_pcie_msi_irq_ops = {
-       .map = advk_pcie_msi_map,
+static const struct irq_domain_ops advk_msi_domain_ops = {
+       .alloc = advk_msi_irq_domain_alloc,
+       .free = advk_msi_irq_domain_free,
 };
 
 static void advk_pcie_irq_mask(struct irq_data *d)
@@ -680,30 +652,25 @@ static int advk_pcie_init_msi_irq_domain(struct advk_pcie *pcie)
 {
        struct device *dev = &pcie->pdev->dev;
        struct device_node *node = dev->of_node;
-       struct irq_chip *msi_irq_chip;
-       struct msi_controller *msi;
+       struct irq_chip *bottom_ic, *msi_ic;
+       struct msi_domain_info *msi_di;
        phys_addr_t msi_msg_phys;
-       int ret;
 
-       msi_irq_chip = &pcie->msi_irq_chip;
+       mutex_init(&pcie->msi_used_lock);
 
-       msi_irq_chip->name = devm_kasprintf(dev, GFP_KERNEL, "%s-msi",
-                                           dev_name(dev));
-       if (!msi_irq_chip->name)
-               return -ENOMEM;
+       bottom_ic = &pcie->msi_bottom_irq_chip;
 
-       msi_irq_chip->irq_enable = pci_msi_unmask_irq;
-       msi_irq_chip->irq_disable = pci_msi_mask_irq;
-       msi_irq_chip->irq_mask = pci_msi_mask_irq;
-       msi_irq_chip->irq_unmask = pci_msi_unmask_irq;
+       bottom_ic->name = "MSI";
+       bottom_ic->irq_compose_msi_msg = advk_msi_irq_compose_msi_msg;
+       bottom_ic->irq_set_affinity = advk_msi_set_affinity;
 
-       msi = &pcie->msi;
+       msi_ic = &pcie->msi_irq_chip;
+       msi_ic->name = "advk-MSI";
 
-       msi->setup_irq = advk_pcie_setup_msi_irq;
-       msi->teardown_irq = advk_pcie_teardown_msi_irq;
-       msi->of_node = node;
-
-       mutex_init(&pcie->msi_used_lock);
+       msi_di = &pcie->msi_domain_info;
+       msi_di->flags = MSI_FLAG_USE_DEF_DOM_OPS | MSI_FLAG_USE_DEF_CHIP_OPS |
+               MSI_FLAG_MULTI_PCI_MSI;
+       msi_di->chip = msi_ic;
 
        msi_msg_phys = virt_to_phys(&pcie->msi_msg);
 
@@ -712,16 +679,18 @@ static int advk_pcie_init_msi_irq_domain(struct advk_pcie *pcie)
        advk_writel(pcie, upper_32_bits(msi_msg_phys),
                    PCIE_MSI_ADDR_HIGH_REG);
 
-       pcie->msi_domain =
+       pcie->msi_inner_domain =
                irq_domain_add_linear(NULL, MSI_IRQ_NUM,
-                                     &advk_pcie_msi_irq_ops, pcie);
-       if (!pcie->msi_domain)
+                                     &advk_msi_domain_ops, pcie);
+       if (!pcie->msi_inner_domain)
                return -ENOMEM;
 
-       ret = of_pci_msi_chip_add(msi);
-       if (ret < 0) {
-               irq_domain_remove(pcie->msi_domain);
-               return ret;
+       pcie->msi_domain =
+               pci_msi_create_irq_domain(of_node_to_fwnode(node),
+                                         msi_di, pcie->msi_inner_domain);
+       if (!pcie->msi_domain) {
+               irq_domain_remove(pcie->msi_inner_domain);
+               return -ENOMEM;
        }
 
        return 0;
@@ -729,8 +698,8 @@ static int advk_pcie_init_msi_irq_domain(struct advk_pcie *pcie)
 
 static void advk_pcie_remove_msi_irq_domain(struct advk_pcie *pcie)
 {
-       of_pci_msi_chip_remove(&pcie->msi);
        irq_domain_remove(pcie->msi_domain);
+       irq_domain_remove(pcie->msi_inner_domain);
 }
 
 static int advk_pcie_init_irq_domain(struct advk_pcie *pcie)
@@ -917,8 +886,6 @@ static int advk_pcie_probe(struct platform_device *pdev)
        struct advk_pcie *pcie;
        struct resource *res;
        struct pci_bus *bus, *child;
-       struct msi_controller *msi;
-       struct device_node *msi_node;
        int ret, irq;
 
        pcie = devm_kzalloc(dev, sizeof(struct advk_pcie), GFP_KERNEL);
@@ -962,14 +929,8 @@ static int advk_pcie_probe(struct platform_device *pdev)
                return ret;
        }
 
-       msi_node = of_parse_phandle(dev->of_node, "msi-parent", 0);
-       if (msi_node)
-               msi = of_pci_find_msi_chip_by_node(msi_node);
-       else
-               msi = NULL;
-
-       bus = pci_scan_root_bus_msi(dev, 0, &advk_pcie_ops,
-                                   pcie, &pcie->resources, &pcie->msi);
+       bus = pci_scan_root_bus(dev, 0, &advk_pcie_ops,
+                               pcie, &pcie->resources);
        if (!bus) {
                advk_pcie_remove_msi_irq_domain(pcie);
                advk_pcie_remove_irq_domain(pcie);
diff --git a/drivers/pci/host/pci-ftpci100.c b/drivers/pci/host/pci-ftpci100.c
new file mode 100644 (file)
index 0000000..d26501c
--- /dev/null
@@ -0,0 +1,563 @@
+/*
+ * Support for Faraday Technology FTPC100 PCI Controller
+ *
+ * Copyright (C) 2017 Linus Walleij <linus.walleij@linaro.org>
+ *
+ * Based on the out-of-tree OpenWRT patch for Cortina Gemini:
+ * Copyright (C) 2009 Janos Laube <janos.dev@gmail.com>
+ * Copyright (C) 2009 Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
+ * Based on SL2312 PCI controller code
+ * Storlink (C) 2003
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/of_pci.h>
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/irqdomain.h>
+#include <linux/irqchip/chained_irq.h>
+#include <linux/bitops.h>
+#include <linux/irq.h>
+
+/*
+ * Special configuration registers directly in the first few words
+ * in I/O space.
+ */
+#define PCI_IOSIZE     0x00
+#define PCI_PROT       0x04 /* AHB protection */
+#define PCI_CTRL       0x08 /* PCI control signal */
+#define PCI_SOFTRST    0x10 /* Soft reset counter and response error enable */
+#define PCI_CONFIG     0x28 /* PCI configuration command register */
+#define PCI_DATA       0x2C
+
+#define FARADAY_PCI_PMC                        0x40 /* Power management control */
+#define FARADAY_PCI_PMCSR              0x44 /* Power management status */
+#define FARADAY_PCI_CTRL1              0x48 /* Control register 1 */
+#define FARADAY_PCI_CTRL2              0x4C /* Control register 2 */
+#define FARADAY_PCI_MEM1_BASE_SIZE     0x50 /* Memory base and size #1 */
+#define FARADAY_PCI_MEM2_BASE_SIZE     0x54 /* Memory base and size #2 */
+#define FARADAY_PCI_MEM3_BASE_SIZE     0x58 /* Memory base and size #3 */
+
+/* Bits 31..28 gives INTD..INTA status */
+#define PCI_CTRL2_INTSTS_SHIFT         28
+#define PCI_CTRL2_INTMASK_CMDERR       BIT(27)
+#define PCI_CTRL2_INTMASK_PARERR       BIT(26)
+/* Bits 25..22 masks INTD..INTA */
+#define PCI_CTRL2_INTMASK_SHIFT                22
+#define PCI_CTRL2_INTMASK_MABRT_RX     BIT(21)
+#define PCI_CTRL2_INTMASK_TABRT_RX     BIT(20)
+#define PCI_CTRL2_INTMASK_TABRT_TX     BIT(19)
+#define PCI_CTRL2_INTMASK_RETRY4       BIT(18)
+#define PCI_CTRL2_INTMASK_SERR_RX      BIT(17)
+#define PCI_CTRL2_INTMASK_PERR_RX      BIT(16)
+/* Bit 15 reserved */
+#define PCI_CTRL2_MSTPRI_REQ6          BIT(14)
+#define PCI_CTRL2_MSTPRI_REQ5          BIT(13)
+#define PCI_CTRL2_MSTPRI_REQ4          BIT(12)
+#define PCI_CTRL2_MSTPRI_REQ3          BIT(11)
+#define PCI_CTRL2_MSTPRI_REQ2          BIT(10)
+#define PCI_CTRL2_MSTPRI_REQ1          BIT(9)
+#define PCI_CTRL2_MSTPRI_REQ0          BIT(8)
+/* Bits 7..4 reserved */
+/* Bits 3..0 TRDYW */
+
+/*
+ * Memory configs:
+ * Bit 31..20 defines the PCI side memory base
+ * Bit 19..16 (4 bits) defines the size per below
+ */
+#define FARADAY_PCI_MEMBASE_MASK       0xfff00000
+#define FARADAY_PCI_MEMSIZE_1MB                0x0
+#define FARADAY_PCI_MEMSIZE_2MB                0x1
+#define FARADAY_PCI_MEMSIZE_4MB                0x2
+#define FARADAY_PCI_MEMSIZE_8MB                0x3
+#define FARADAY_PCI_MEMSIZE_16MB       0x4
+#define FARADAY_PCI_MEMSIZE_32MB       0x5
+#define FARADAY_PCI_MEMSIZE_64MB       0x6
+#define FARADAY_PCI_MEMSIZE_128MB      0x7
+#define FARADAY_PCI_MEMSIZE_256MB      0x8
+#define FARADAY_PCI_MEMSIZE_512MB      0x9
+#define FARADAY_PCI_MEMSIZE_1GB                0xa
+#define FARADAY_PCI_MEMSIZE_2GB                0xb
+#define FARADAY_PCI_MEMSIZE_SHIFT      16
+
+/*
+ * The DMA base is set to 0x0 for all memory segments, it reflects the
+ * fact that the memory of the host system starts at 0x0.
+ */
+#define FARADAY_PCI_DMA_MEM1_BASE      0x00000000
+#define FARADAY_PCI_DMA_MEM2_BASE      0x00000000
+#define FARADAY_PCI_DMA_MEM3_BASE      0x00000000
+
+/* Defines for PCI configuration command register */
+#define PCI_CONF_ENABLE                BIT(31)
+#define PCI_CONF_WHERE(r)      ((r) & 0xFC)
+#define PCI_CONF_BUS(b)                (((b) & 0xFF) << 16)
+#define PCI_CONF_DEVICE(d)     (((d) & 0x1F) << 11)
+#define PCI_CONF_FUNCTION(f)   (((f) & 0x07) << 8)
+
+/**
+ * struct faraday_pci_variant - encodes IP block differences
+ * @cascaded_irq: this host has cascaded IRQs from an interrupt controller
+ *     embedded in the host bridge.
+ */
+struct faraday_pci_variant {
+       bool cascaded_irq;
+};
+
+struct faraday_pci {
+       struct device *dev;
+       void __iomem *base;
+       struct irq_domain *irqdomain;
+       struct pci_bus *bus;
+};
+
+static int faraday_res_to_memcfg(resource_size_t mem_base,
+                                resource_size_t mem_size, u32 *val)
+{
+       u32 outval;
+
+       switch (mem_size) {
+       case SZ_1M:
+               outval = FARADAY_PCI_MEMSIZE_1MB;
+               break;
+       case SZ_2M:
+               outval = FARADAY_PCI_MEMSIZE_2MB;
+               break;
+       case SZ_4M:
+               outval = FARADAY_PCI_MEMSIZE_4MB;
+               break;
+       case SZ_8M:
+               outval = FARADAY_PCI_MEMSIZE_8MB;
+               break;
+       case SZ_16M:
+               outval = FARADAY_PCI_MEMSIZE_16MB;
+               break;
+       case SZ_32M:
+               outval = FARADAY_PCI_MEMSIZE_32MB;
+               break;
+       case SZ_64M:
+               outval = FARADAY_PCI_MEMSIZE_64MB;
+               break;
+       case SZ_128M:
+               outval = FARADAY_PCI_MEMSIZE_128MB;
+               break;
+       case SZ_256M:
+               outval = FARADAY_PCI_MEMSIZE_256MB;
+               break;
+       case SZ_512M:
+               outval = FARADAY_PCI_MEMSIZE_512MB;
+               break;
+       case SZ_1G:
+               outval = FARADAY_PCI_MEMSIZE_1GB;
+               break;
+       case SZ_2G:
+               outval = FARADAY_PCI_MEMSIZE_2GB;
+               break;
+       default:
+               return -EINVAL;
+       }
+       outval <<= FARADAY_PCI_MEMSIZE_SHIFT;
+
+       /* This is probably not good */
+       if (mem_base & ~(FARADAY_PCI_MEMBASE_MASK))
+               pr_warn("truncated PCI memory base\n");
+       /* Translate to bridge side address space */
+       outval |= (mem_base & FARADAY_PCI_MEMBASE_MASK);
+       pr_debug("Translated pci base @%pap, size %pap to config %08x\n",
+                &mem_base, &mem_size, outval);
+
+       *val = outval;
+       return 0;
+}
+
+static int faraday_pci_read_config(struct pci_bus *bus, unsigned int fn,
+                                  int config, int size, u32 *value)
+{
+       struct faraday_pci *p = bus->sysdata;
+
+       writel(PCI_CONF_BUS(bus->number) |
+                       PCI_CONF_DEVICE(PCI_SLOT(fn)) |
+                       PCI_CONF_FUNCTION(PCI_FUNC(fn)) |
+                       PCI_CONF_WHERE(config) |
+                       PCI_CONF_ENABLE,
+                       p->base + PCI_CONFIG);
+
+       *value = readl(p->base + PCI_DATA);
+
+       if (size == 1)
+               *value = (*value >> (8 * (config & 3))) & 0xFF;
+       else if (size == 2)
+               *value = (*value >> (8 * (config & 3))) & 0xFFFF;
+
+       dev_dbg(&bus->dev,
+               "[read]  slt: %.2d, fnc: %d, cnf: 0x%.2X, val (%d bytes): 0x%.8X\n",
+               PCI_SLOT(fn), PCI_FUNC(fn), config, size, *value);
+
+       return PCIBIOS_SUCCESSFUL;
+}
+
+static int faraday_pci_write_config(struct pci_bus *bus, unsigned int fn,
+                                   int config, int size, u32 value)
+{
+       struct faraday_pci *p = bus->sysdata;
+       int ret = PCIBIOS_SUCCESSFUL;
+
+       dev_dbg(&bus->dev,
+               "[write] slt: %.2d, fnc: %d, cnf: 0x%.2X, val (%d bytes): 0x%.8X\n",
+               PCI_SLOT(fn), PCI_FUNC(fn), config, size, value);
+
+       writel(PCI_CONF_BUS(bus->number) |
+                       PCI_CONF_DEVICE(PCI_SLOT(fn)) |
+                       PCI_CONF_FUNCTION(PCI_FUNC(fn)) |
+                       PCI_CONF_WHERE(config) |
+                       PCI_CONF_ENABLE,
+                       p->base + PCI_CONFIG);
+
+       switch (size) {
+       case 4:
+               writel(value, p->base + PCI_DATA);
+               break;
+       case 2:
+               writew(value, p->base + PCI_DATA + (config & 3));
+               break;
+       case 1:
+               writeb(value, p->base + PCI_DATA + (config & 3));
+               break;
+       default:
+               ret = PCIBIOS_BAD_REGISTER_NUMBER;
+       }
+
+       return ret;
+}
+
+static struct pci_ops faraday_pci_ops = {
+       .read   = faraday_pci_read_config,
+       .write  = faraday_pci_write_config,
+};
+
+static void faraday_pci_ack_irq(struct irq_data *d)
+{
+       struct faraday_pci *p = irq_data_get_irq_chip_data(d);
+       unsigned int reg;
+
+       faraday_pci_read_config(p->bus, 0, FARADAY_PCI_CTRL2, 4, &reg);
+       reg &= ~(0xF << PCI_CTRL2_INTSTS_SHIFT);
+       reg |= BIT(irqd_to_hwirq(d) + PCI_CTRL2_INTSTS_SHIFT);
+       faraday_pci_write_config(p->bus, 0, FARADAY_PCI_CTRL2, 4, reg);
+}
+
+static void faraday_pci_mask_irq(struct irq_data *d)
+{
+       struct faraday_pci *p = irq_data_get_irq_chip_data(d);
+       unsigned int reg;
+
+       faraday_pci_read_config(p->bus, 0, FARADAY_PCI_CTRL2, 4, &reg);
+       reg &= ~((0xF << PCI_CTRL2_INTSTS_SHIFT)
+                | BIT(irqd_to_hwirq(d) + PCI_CTRL2_INTMASK_SHIFT));
+       faraday_pci_write_config(p->bus, 0, FARADAY_PCI_CTRL2, 4, reg);
+}
+
+static void faraday_pci_unmask_irq(struct irq_data *d)
+{
+       struct faraday_pci *p = irq_data_get_irq_chip_data(d);
+       unsigned int reg;
+
+       faraday_pci_read_config(p->bus, 0, FARADAY_PCI_CTRL2, 4, &reg);
+       reg &= ~(0xF << PCI_CTRL2_INTSTS_SHIFT);
+       reg |= BIT(irqd_to_hwirq(d) + PCI_CTRL2_INTMASK_SHIFT);
+       faraday_pci_write_config(p->bus, 0, FARADAY_PCI_CTRL2, 4, reg);
+}
+
+static void faraday_pci_irq_handler(struct irq_desc *desc)
+{
+       struct faraday_pci *p = irq_desc_get_handler_data(desc);
+       struct irq_chip *irqchip = irq_desc_get_chip(desc);
+       unsigned int irq_stat, reg, i;
+
+       faraday_pci_read_config(p->bus, 0, FARADAY_PCI_CTRL2, 4, &reg);
+       irq_stat = reg >> PCI_CTRL2_INTSTS_SHIFT;
+
+       chained_irq_enter(irqchip, desc);
+
+       for (i = 0; i < 4; i++) {
+               if ((irq_stat & BIT(i)) == 0)
+                       continue;
+               generic_handle_irq(irq_find_mapping(p->irqdomain, i));
+       }
+
+       chained_irq_exit(irqchip, desc);
+}
+
+static struct irq_chip faraday_pci_irq_chip = {
+       .name = "PCI",
+       .irq_ack = faraday_pci_ack_irq,
+       .irq_mask = faraday_pci_mask_irq,
+       .irq_unmask = faraday_pci_unmask_irq,
+};
+
+static int faraday_pci_irq_map(struct irq_domain *domain, unsigned int irq,
+                              irq_hw_number_t hwirq)
+{
+       irq_set_chip_and_handler(irq, &faraday_pci_irq_chip, handle_level_irq);
+       irq_set_chip_data(irq, domain->host_data);
+
+       return 0;
+}
+
+static const struct irq_domain_ops faraday_pci_irqdomain_ops = {
+       .map = faraday_pci_irq_map,
+};
+
+static int faraday_pci_setup_cascaded_irq(struct faraday_pci *p)
+{
+       struct device_node *intc = of_get_next_child(p->dev->of_node, NULL);
+       int irq;
+       int i;
+
+       if (!intc) {
+               dev_err(p->dev, "missing child interrupt-controller node\n");
+               return -EINVAL;
+       }
+
+       /* All PCI IRQs cascade off this one */
+       irq = of_irq_get(intc, 0);
+       if (!irq) {
+               dev_err(p->dev, "failed to get parent IRQ\n");
+               return -EINVAL;
+       }
+
+       p->irqdomain = irq_domain_add_linear(intc, 4,
+                                            &faraday_pci_irqdomain_ops, p);
+       if (!p->irqdomain) {
+               dev_err(p->dev, "failed to create Gemini PCI IRQ domain\n");
+               return -EINVAL;
+       }
+
+       irq_set_chained_handler_and_data(irq, faraday_pci_irq_handler, p);
+
+       for (i = 0; i < 4; i++)
+               irq_create_mapping(p->irqdomain, i);
+
+       return 0;
+}
+
+static int pci_dma_range_parser_init(struct of_pci_range_parser *parser,
+                                    struct device_node *node)
+{
+       const int na = 3, ns = 2;
+       int rlen;
+
+       parser->node = node;
+       parser->pna = of_n_addr_cells(node);
+       parser->np = parser->pna + na + ns;
+
+       parser->range = of_get_property(node, "dma-ranges", &rlen);
+       if (!parser->range)
+               return -ENOENT;
+       parser->end = parser->range + rlen / sizeof(__be32);
+
+       return 0;
+}
+
+static int faraday_pci_parse_map_dma_ranges(struct faraday_pci *p,
+                                           struct device_node *np)
+{
+       struct of_pci_range range;
+       struct of_pci_range_parser parser;
+       struct device *dev = p->dev;
+       u32 confreg[3] = {
+               FARADAY_PCI_MEM1_BASE_SIZE,
+               FARADAY_PCI_MEM2_BASE_SIZE,
+               FARADAY_PCI_MEM3_BASE_SIZE,
+       };
+       int i = 0;
+       u32 val;
+
+       if (pci_dma_range_parser_init(&parser, np)) {
+               dev_err(dev, "missing dma-ranges property\n");
+               return -EINVAL;
+       }
+
+       /*
+        * Get the dma-ranges from the device tree
+        */
+       for_each_of_pci_range(&parser, &range) {
+               u64 end = range.pci_addr + range.size - 1;
+               int ret;
+
+               ret = faraday_res_to_memcfg(range.pci_addr, range.size, &val);
+               if (ret) {
+                       dev_err(dev,
+                               "DMA range %d: illegal MEM resource size\n", i);
+                       return -EINVAL;
+               }
+
+               dev_info(dev, "DMA MEM%d BASE: 0x%016llx -> 0x%016llx config %08x\n",
+                        i + 1, range.pci_addr, end, val);
+               if (i <= 2) {
+                       faraday_pci_write_config(p->bus, 0, confreg[i],
+                                                4, val);
+               } else {
+                       dev_err(dev, "ignore extraneous dma-range %d\n", i);
+                       break;
+               }
+
+               i++;
+       }
+
+       return 0;
+}
+
+static int faraday_pci_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       const struct faraday_pci_variant *variant =
+               of_device_get_match_data(dev);
+       struct resource *regs;
+       resource_size_t io_base;
+       struct resource_entry *win;
+       struct faraday_pci *p;
+       struct resource *mem;
+       struct resource *io;
+       struct pci_host_bridge *host;
+       int ret;
+       u32 val;
+       LIST_HEAD(res);
+
+       host = pci_alloc_host_bridge(sizeof(*p));
+       if (!host)
+               return -ENOMEM;
+
+       host->dev.parent = dev;
+       host->ops = &faraday_pci_ops;
+       host->busnr = 0;
+       host->msi = NULL;
+       p = pci_host_bridge_priv(host);
+       host->sysdata = p;
+       p->dev = dev;
+
+       regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       p->base = devm_ioremap_resource(dev, regs);
+       if (IS_ERR(p->base))
+               return PTR_ERR(p->base);
+
+       ret = of_pci_get_host_bridge_resources(dev->of_node, 0, 0xff,
+                                              &res, &io_base);
+       if (ret)
+               return ret;
+
+       ret = devm_request_pci_bus_resources(dev, &res);
+       if (ret)
+               return ret;
+
+       /* Get the I/O and memory ranges from DT */
+       resource_list_for_each_entry(win, &res) {
+               switch (resource_type(win->res)) {
+               case IORESOURCE_IO:
+                       io = win->res;
+                       io->name = "Gemini PCI I/O";
+                       if (!faraday_res_to_memcfg(io->start - win->offset,
+                                                  resource_size(io), &val)) {
+                               /* setup I/O space size */
+                               writel(val, p->base + PCI_IOSIZE);
+                       } else {
+                               dev_err(dev, "illegal IO mem size\n");
+                               return -EINVAL;
+                       }
+                       ret = pci_remap_iospace(io, io_base);
+                       if (ret) {
+                               dev_warn(dev, "error %d: failed to map resource %pR\n",
+                                        ret, io);
+                               continue;
+                       }
+                       break;
+               case IORESOURCE_MEM:
+                       mem = win->res;
+                       mem->name = "Gemini PCI MEM";
+                       break;
+               case IORESOURCE_BUS:
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       /* Setup hostbridge */
+       val = readl(p->base + PCI_CTRL);
+       val |= PCI_COMMAND_IO;
+       val |= PCI_COMMAND_MEMORY;
+       val |= PCI_COMMAND_MASTER;
+       writel(val, p->base + PCI_CTRL);
+
+       list_splice_init(&res, &host->windows);
+       ret = pci_register_host_bridge(host);
+       if (ret) {
+               dev_err(dev, "failed to register host: %d\n", ret);
+               return ret;
+       }
+       p->bus = host->bus;
+
+       /* Mask and clear all interrupts */
+       faraday_pci_write_config(p->bus, 0, FARADAY_PCI_CTRL2 + 2, 2, 0xF000);
+       if (variant->cascaded_irq) {
+               ret = faraday_pci_setup_cascaded_irq(p);
+               if (ret) {
+                       dev_err(dev, "failed to setup cascaded IRQ\n");
+                       return ret;
+               }
+       }
+
+       ret = faraday_pci_parse_map_dma_ranges(p, dev->of_node);
+       if (ret)
+               return ret;
+
+       pci_scan_child_bus(p->bus);
+       pci_fixup_irqs(pci_common_swizzle, of_irq_parse_and_map_pci);
+       pci_bus_assign_resources(p->bus);
+       pci_bus_add_devices(p->bus);
+       pci_free_resource_list(&res);
+
+       return 0;
+}
+
+/*
+ * We encode bridge variants here, we have at least two so it doesn't
+ * hurt to have infrastructure to encompass future variants as well.
+ */
+const struct faraday_pci_variant faraday_regular = {
+       .cascaded_irq = true,
+};
+
+const struct faraday_pci_variant faraday_dual = {
+       .cascaded_irq = false,
+};
+
+static const struct of_device_id faraday_pci_of_match[] = {
+       {
+               .compatible = "faraday,ftpci100",
+               .data = &faraday_regular,
+       },
+       {
+               .compatible = "faraday,ftpci100-dual",
+               .data = &faraday_dual,
+       },
+       {},
+};
+
+static struct platform_driver faraday_pci_driver = {
+       .driver = {
+               .name = "ftpci100",
+               .of_match_table = of_match_ptr(faraday_pci_of_match),
+               .suppress_bind_attrs = true,
+       },
+       .probe  = faraday_pci_probe,
+};
+builtin_platform_driver(faraday_pci_driver);
index c05ea9d72f693f38203e98ae92c4c95df4dab661..7d709a7e0aa8a7cf2e0bc55de059f1731d8adb27 100644 (file)
@@ -60,6 +60,7 @@ static struct platform_driver gen_pci_driver = {
        .driver = {
                .name = "pci-host-generic",
                .of_match_table = gen_pci_of_match,
+               .suppress_bind_attrs = true,
        },
        .probe = gen_pci_probe,
 };
index ada98569b78ed65561d5fb4479f1eeee62cd00c3..84936383e26911ea7c634698b8f53c053d236a1e 100644 (file)
@@ -56,6 +56,7 @@
 #include <asm/apic.h>
 #include <linux/msi.h>
 #include <linux/hyperv.h>
+#include <linux/refcount.h>
 #include <asm/mshyperv.h>
 
 /*
@@ -72,6 +73,7 @@ enum {
        PCI_PROTOCOL_VERSION_CURRENT = PCI_PROTOCOL_VERSION_1_1
 };
 
+#define CPU_AFFINITY_ALL       -1ULL
 #define PCI_CONFIG_MMIO_LENGTH 0x2000
 #define CFG_PAGE_OFFSET 0x1000
 #define CFG_PAGE_SIZE (PCI_CONFIG_MMIO_LENGTH - CFG_PAGE_OFFSET)
@@ -350,6 +352,7 @@ enum hv_pcibus_state {
        hv_pcibus_init = 0,
        hv_pcibus_probed,
        hv_pcibus_installed,
+       hv_pcibus_removed,
        hv_pcibus_maximum
 };
 
@@ -421,7 +424,7 @@ enum hv_pcidev_ref_reason {
 struct hv_pci_dev {
        /* List protected by pci_rescan_remove_lock */
        struct list_head list_entry;
-       atomic_t refs;
+       refcount_t refs;
        enum hv_pcichild_state state;
        struct pci_function_description desc;
        bool reported_missing;
@@ -876,7 +879,7 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
                hv_int_desc_free(hpdev, int_desc);
        }
 
-       int_desc = kzalloc(sizeof(*int_desc), GFP_KERNEL);
+       int_desc = kzalloc(sizeof(*int_desc), GFP_ATOMIC);
        if (!int_desc)
                goto drop_reference;
 
@@ -897,9 +900,13 @@ static void hv_compose_msi_msg(struct irq_data *data, struct msi_msg *msg)
         * processors because Hyper-V only supports 64 in a guest.
         */
        affinity = irq_data_get_affinity_mask(data);
-       for_each_cpu_and(cpu, affinity, cpu_online_mask) {
-               int_pkt->int_desc.cpu_mask |=
-                       (1ULL << vmbus_cpu_number_to_vp_number(cpu));
+       if (cpumask_weight(affinity) >= 32) {
+               int_pkt->int_desc.cpu_mask = CPU_AFFINITY_ALL;
+       } else {
+               for_each_cpu_and(cpu, affinity, cpu_online_mask) {
+                       int_pkt->int_desc.cpu_mask |=
+                               (1ULL << vmbus_cpu_number_to_vp_number(cpu));
+               }
        }
 
        ret = vmbus_sendpacket(hpdev->hbus->hdev->channel, int_pkt,
@@ -1208,9 +1215,11 @@ static int create_root_hv_pci_bus(struct hv_pcibus_device *hbus)
        hbus->pci_bus->msi = &hbus->msi_chip;
        hbus->pci_bus->msi->dev = &hbus->hdev->device;
 
+       pci_lock_rescan_remove();
        pci_scan_child_bus(hbus->pci_bus);
        pci_bus_assign_resources(hbus->pci_bus);
        pci_bus_add_devices(hbus->pci_bus);
+       pci_unlock_rescan_remove();
        hbus->state = hv_pcibus_installed;
        return 0;
 }
@@ -1254,13 +1263,13 @@ static void q_resource_requirements(void *context, struct pci_response *resp,
 static void get_pcichild(struct hv_pci_dev *hpdev,
                            enum hv_pcidev_ref_reason reason)
 {
-       atomic_inc(&hpdev->refs);
+       refcount_inc(&hpdev->refs);
 }
 
 static void put_pcichild(struct hv_pci_dev *hpdev,
                            enum hv_pcidev_ref_reason reason)
 {
-       if (atomic_dec_and_test(&hpdev->refs))
+       if (refcount_dec_and_test(&hpdev->refs))
                kfree(hpdev);
 }
 
@@ -1314,7 +1323,7 @@ static struct hv_pci_dev *new_pcichild_device(struct hv_pcibus_device *hbus,
        wait_for_completion(&comp_pkt.host_event);
 
        hpdev->desc = *desc;
-       get_pcichild(hpdev, hv_pcidev_ref_initial);
+       refcount_set(&hpdev->refs, 1);
        get_pcichild(hpdev, hv_pcidev_ref_childlist);
        spin_lock_irqsave(&hbus->device_list_lock, flags);
 
@@ -1504,13 +1513,24 @@ static void pci_devices_present_work(struct work_struct *work)
                put_pcichild(hpdev, hv_pcidev_ref_initial);
        }
 
-       /* Tell the core to rescan bus because there may have been changes. */
-       if (hbus->state == hv_pcibus_installed) {
+       switch(hbus->state) {
+       case hv_pcibus_installed:
+               /*
+               * Tell the core to rescan bus
+               * because there may have been changes.
+               */
                pci_lock_rescan_remove();
                pci_scan_child_bus(hbus->pci_bus);
                pci_unlock_rescan_remove();
-       } else {
+               break;
+
+       case hv_pcibus_init:
+       case hv_pcibus_probed:
                survey_child_resources(hbus);
+               break;
+
+       default:
+               break;
        }
 
        up(&hbus->enum_sem);
@@ -1600,8 +1620,10 @@ static void hv_eject_device_work(struct work_struct *work)
        pdev = pci_get_domain_bus_and_slot(hpdev->hbus->sysdata.domain, 0,
                                           wslot);
        if (pdev) {
+               pci_lock_rescan_remove();
                pci_stop_and_remove_bus_device(pdev);
                pci_dev_put(pdev);
+               pci_unlock_rescan_remove();
        }
 
        spin_lock_irqsave(&hpdev->hbus->device_list_lock, flags);
@@ -2185,6 +2207,7 @@ static int hv_pci_probe(struct hv_device *hdev,
        hbus = kzalloc(sizeof(*hbus), GFP_KERNEL);
        if (!hbus)
                return -ENOMEM;
+       hbus->state = hv_pcibus_init;
 
        /*
         * The PCI bus "domain" is what is called "segment" in ACPI and
@@ -2348,6 +2371,7 @@ static int hv_pci_remove(struct hv_device *hdev)
                pci_stop_root_bus(hbus->pci_bus);
                pci_remove_root_bus(hbus->pci_bus);
                pci_unlock_rescan_remove();
+               hbus->state = hv_pcibus_removed;
        }
 
        hv_pci_bus_exit(hdev);
index cd7d51988738e288e8269f0c016ec0d31aa99c13..f353a6eb2f010aa622c7bf440a6e1312f9748734 100644 (file)
@@ -752,10 +752,11 @@ static int mvebu_sw_pci_bridge_write(struct mvebu_pcie_port *port,
                 * If the mask is 0xffff0000, then we only want to write
                 * the link control register, rather than clearing the
                 * RW1C bits in the link status register.  Mask out the
-                * status register bits.
+                * RW1C status register bits.
                 */
                if (mask == 0xffff0000)
-                       value &= 0xffff;
+                       value &= ~((PCI_EXP_LNKSTA_LABS |
+                                   PCI_EXP_LNKSTA_LBMS) << 16);
 
                mvebu_writel(port, value, PCIE_CAP_PCIEXP + PCI_EXP_LNKCTL);
                break;
@@ -1005,22 +1006,6 @@ static int mvebu_get_tgt_attr(struct device_node *np, int devfn,
        return -ENOENT;
 }
 
-static void mvebu_pcie_msi_enable(struct mvebu_pcie *pcie)
-{
-       struct device_node *msi_node;
-
-       msi_node = of_parse_phandle(pcie->pdev->dev.of_node,
-                                   "msi-parent", 0);
-       if (!msi_node)
-               return;
-
-       pcie->msi = of_pci_find_msi_chip_by_node(msi_node);
-       of_node_put(msi_node);
-
-       if (pcie->msi)
-               pcie->msi->dev = &pcie->pdev->dev;
-}
-
 #ifdef CONFIG_PM_SLEEP
 static int mvebu_pcie_suspend(struct device *dev)
 {
@@ -1298,7 +1283,6 @@ static int mvebu_pcie_probe(struct platform_device *pdev)
        for (i = 0; i < (IO_SPACE_LIMIT - SZ_64K); i += SZ_64K)
                pci_ioremap_io(i, pcie->io.start + i);
 
-       mvebu_pcie_msi_enable(pcie);
        mvebu_pcie_enable(pcie);
 
        platform_set_drvdata(pdev, pcie);
index ed8a93f2bfb5fd4167f7362cddbc6eabe6dd85c8..2618f875a600d63aea25aebbee2a145587d540f9 100644 (file)
@@ -380,7 +380,7 @@ static struct tegra_pcie_bus *tegra_pcie_bus_alloc(struct tegra_pcie *pcie,
                                                   unsigned int busnr)
 {
        struct device *dev = pcie->dev;
-       pgprot_t prot = pgprot_device(PAGE_KERNEL);
+       pgprot_t prot = pgprot_noncached(PAGE_KERNEL);
        phys_addr_t cs = pcie->cs->start;
        struct tegra_pcie_bus *bus;
        unsigned int i;
@@ -1962,7 +1962,7 @@ static int tegra_pcie_parse_dt(struct tegra_pcie *pcie)
                rp->pcie = pcie;
                rp->np = port;
 
-               rp->base = devm_ioremap_resource(dev, &rp->regs);
+               rp->base = devm_pci_remap_cfg_resource(dev, &rp->regs);
                if (IS_ERR(rp->base))
                        return PTR_ERR(rp->base);
 
index 3f54a43bbbea50740045592790377d4b009e5d76..fc0ca03f280ead292d26d67d15ece79bd8e0f558 100644 (file)
@@ -373,6 +373,7 @@ static struct platform_driver thunder_ecam_driver = {
        .driver = {
                .name = KBUILD_MODNAME,
                .of_match_table = thunder_ecam_of_match,
+               .suppress_bind_attrs = true,
        },
        .probe = thunder_ecam_probe,
 };
index 6e031b522529daec0240022cf5221e92be3ea29b..6e066f8b74dfda865a6b9b4ad5c145861d255415 100644 (file)
@@ -474,6 +474,7 @@ static struct platform_driver thunder_pem_driver = {
        .driver = {
                .name = KBUILD_MODNAME,
                .of_match_table = thunder_pem_of_match,
+               .suppress_bind_attrs = true,
        },
        .probe = thunder_pem_probe,
 };
index 5ebee7d37ff5f0d59e5c032ab0dc9af4b5e3dbbe..9281eee2d00088eaea0a74adeed4bd9430f55f92 100644 (file)
@@ -138,7 +138,8 @@ static int versatile_pci_probe(struct platform_device *pdev)
                return PTR_ERR(versatile_cfg_base[0]);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
-       versatile_cfg_base[1] = devm_ioremap_resource(&pdev->dev, res);
+       versatile_cfg_base[1] = devm_pci_remap_cfg_resource(&pdev->dev,
+                                                           res);
        if (IS_ERR(versatile_cfg_base[1]))
                return PTR_ERR(versatile_cfg_base[1]);
 
@@ -221,6 +222,7 @@ static struct platform_driver versatile_pci_driver = {
        .driver = {
                .name = "versatile-pci",
                .of_match_table = versatile_pci_of_match,
+               .suppress_bind_attrs = true,
        },
        .probe = versatile_pci_probe,
 };
index 1a6108788f6f07fa1e361f34d6e8963f995c1466..8cae013e7188dfcf1c6d78a8316c4dcc7d21663b 100644 (file)
@@ -248,7 +248,7 @@ static int xgene_pcie_ecam_init(struct pci_config_window *cfg, u32 ipversion)
                dev_err(dev, "can't get CSR resource\n");
                return ret;
        }
-       port->csr_base = devm_ioremap_resource(dev, &csr);
+       port->csr_base = devm_pci_remap_cfg_resource(dev, &csr);
        if (IS_ERR(port->csr_base))
                return PTR_ERR(port->csr_base);
 
@@ -359,7 +359,7 @@ static int xgene_pcie_map_reg(struct xgene_pcie_port *port,
        struct resource *res;
 
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "csr");
-       port->csr_base = devm_ioremap_resource(dev, res);
+       port->csr_base = devm_pci_remap_cfg_resource(dev, res);
        if (IS_ERR(port->csr_base))
                return PTR_ERR(port->csr_base);
 
@@ -697,6 +697,7 @@ static struct platform_driver xgene_pcie_driver = {
        .driver = {
                   .name = "xgene-pcie",
                   .of_match_table = of_match_ptr(xgene_pcie_match_table),
+                  .suppress_bind_attrs = true,
        },
        .probe = xgene_pcie_probe_bridge,
 };
index 8c6a327ca6cdf883f32ea9a6fa0e7e1e28ab0e98..90d2bdd94e416243a99b38598c68d7eed160810f 100644 (file)
@@ -67,7 +67,8 @@ static int iproc_pcie_pltfm_probe(struct platform_device *pdev)
                return ret;
        }
 
-       pcie->base = devm_ioremap(dev, reg.start, resource_size(&reg));
+       pcie->base = devm_pci_remap_cfgspace(dev, reg.start,
+                                            resource_size(&reg));
        if (!pcie->base) {
                dev_err(dev, "unable to map controller registers\n");
                return -ENOMEM;
index 26ddd3535272e89b9dcb9b1da48ee6acb6211666..0e020b6e0943148a1981a9ad3fab4b03060213b3 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/irqdomain.h>
 #include <linux/kernel.h>
 #include <linux/mfd/syscon.h>
+#include <linux/module.h>
 #include <linux/of_address.h>
 #include <linux/of_device.h>
 #include <linux/of_pci.h>
@@ -223,9 +224,11 @@ struct rockchip_pcie {
        int     link_gen;
        struct  device *dev;
        struct  irq_domain *irq_domain;
-       u32     io_size;
        int     offset;
+       struct pci_bus *root_bus;
+       struct resource *io;
        phys_addr_t io_bus_addr;
+       u32     io_size;
        void    __iomem *msg_region;
        u32     mem_size;
        phys_addr_t msg_bus_addr;
@@ -425,7 +428,8 @@ static struct pci_ops rockchip_pcie_ops = {
 
 static void rockchip_pcie_set_power_limit(struct rockchip_pcie *rockchip)
 {
-       u32 status, curr, scale, power;
+       int curr;
+       u32 status, scale, power;
 
        if (IS_ERR(rockchip->vpcie3v3))
                return;
@@ -437,24 +441,25 @@ static void rockchip_pcie_set_power_limit(struct rockchip_pcie *rockchip)
         * to the actual power supply.
         */
        curr = regulator_get_current_limit(rockchip->vpcie3v3);
-       if (curr > 0) {
-               scale = 3; /* 0.001x */
-               curr = curr / 1000; /* convert to mA */
-               power = (curr * 3300) / 1000; /* milliwatt */
-               while (power > PCIE_RC_CONFIG_DCR_CSPL_LIMIT) {
-                       if (!scale) {
-                               dev_warn(rockchip->dev, "invalid power supply\n");
-                               return;
-                       }
-                       scale--;
-                       power = power / 10;
-               }
+       if (curr <= 0)
+               return;
 
-               status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_DCR);
-               status |= (power << PCIE_RC_CONFIG_DCR_CSPL_SHIFT) |
-                         (scale << PCIE_RC_CONFIG_DCR_CPLS_SHIFT);
-               rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_DCR);
+       scale = 3; /* 0.001x */
+       curr = curr / 1000; /* convert to mA */
+       power = (curr * 3300) / 1000; /* milliwatt */
+       while (power > PCIE_RC_CONFIG_DCR_CSPL_LIMIT) {
+               if (!scale) {
+                       dev_warn(rockchip->dev, "invalid power supply\n");
+                       return;
+               }
+               scale--;
+               power = power / 10;
        }
+
+       status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_DCR);
+       status |= (power << PCIE_RC_CONFIG_DCR_CSPL_SHIFT) |
+                 (scale << PCIE_RC_CONFIG_DCR_CPLS_SHIFT);
+       rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_DCR);
 }
 
 /**
@@ -596,7 +601,12 @@ static int rockchip_pcie_init_port(struct rockchip_pcie *rockchip)
 
        /* Set RC's clock architecture as common clock */
        status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LCS);
-       status |= PCI_EXP_LNKCTL_CCC;
+       status |= PCI_EXP_LNKSTA_SLC << 16;
+       rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS);
+
+       /* Set RC's RCB to 128 */
+       status = rockchip_pcie_read(rockchip, PCIE_RC_CONFIG_LCS);
+       status |= PCI_EXP_LNKCTL_RCB;
        rockchip_pcie_write(rockchip, status, PCIE_RC_CONFIG_LCS);
 
        /* Enable Gen1 training */
@@ -822,7 +832,7 @@ static int rockchip_pcie_parse_dt(struct rockchip_pcie *rockchip)
        regs = platform_get_resource_byname(pdev,
                                            IORESOURCE_MEM,
                                            "axi-base");
-       rockchip->reg_base = devm_ioremap_resource(dev, regs);
+       rockchip->reg_base = devm_pci_remap_cfg_resource(dev, regs);
        if (IS_ERR(rockchip->reg_base))
                return PTR_ERR(rockchip->reg_base);
 
@@ -1359,6 +1369,7 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
                                         err, io);
                                continue;
                        }
+                       rockchip->io = io;
                        break;
                case IORESOURCE_MEM:
                        mem = win->res;
@@ -1390,6 +1401,7 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
                err = -ENOMEM;
                goto err_free_res;
        }
+       rockchip->root_bus = bus;
 
        pci_bus_size_bridges(bus);
        pci_bus_assign_resources(bus);
@@ -1397,7 +1409,7 @@ static int rockchip_pcie_probe(struct platform_device *pdev)
                pcie_bus_configure_settings(child);
 
        pci_bus_add_devices(bus);
-       return err;
+       return 0;
 
 err_free_res:
        pci_free_resource_list(&res);
@@ -1420,6 +1432,34 @@ err_aclk_pcie:
        return err;
 }
 
+static int rockchip_pcie_remove(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct rockchip_pcie *rockchip = dev_get_drvdata(dev);
+
+       pci_stop_root_bus(rockchip->root_bus);
+       pci_remove_root_bus(rockchip->root_bus);
+       pci_unmap_iospace(rockchip->io);
+       irq_domain_remove(rockchip->irq_domain);
+
+       phy_power_off(rockchip->phy);
+       phy_exit(rockchip->phy);
+
+       clk_disable_unprepare(rockchip->clk_pcie_pm);
+       clk_disable_unprepare(rockchip->hclk_pcie);
+       clk_disable_unprepare(rockchip->aclk_perf_pcie);
+       clk_disable_unprepare(rockchip->aclk_pcie);
+
+       if (!IS_ERR(rockchip->vpcie3v3))
+               regulator_disable(rockchip->vpcie3v3);
+       if (!IS_ERR(rockchip->vpcie1v8))
+               regulator_disable(rockchip->vpcie1v8);
+       if (!IS_ERR(rockchip->vpcie0v9))
+               regulator_disable(rockchip->vpcie0v9);
+
+       return 0;
+}
+
 static const struct dev_pm_ops rockchip_pcie_pm_ops = {
        SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(rockchip_pcie_suspend_noirq,
                                      rockchip_pcie_resume_noirq)
@@ -1429,6 +1469,7 @@ static const struct of_device_id rockchip_pcie_of_match[] = {
        { .compatible = "rockchip,rk3399-pcie", },
        {}
 };
+MODULE_DEVICE_TABLE(of, rockchip_pcie_of_match);
 
 static struct platform_driver rockchip_pcie_driver = {
        .driver = {
@@ -1437,6 +1478,10 @@ static struct platform_driver rockchip_pcie_driver = {
                .pm = &rockchip_pcie_pm_ops,
        },
        .probe = rockchip_pcie_probe,
-
+       .remove = rockchip_pcie_remove,
 };
-builtin_platform_driver(rockchip_pcie_driver);
+module_platform_driver(rockchip_pcie_driver);
+
+MODULE_AUTHOR("Rockchip Inc");
+MODULE_DESCRIPTION("Rockchip AXI PCIe driver");
+MODULE_LICENSE("GPL v2");
index 4c3e0ab354963322679a2a88af7ba9670a24b5ab..4b16b26ae9090cdf2042e4b8a7a32bdfbc8f4f4b 100644 (file)
@@ -761,7 +761,7 @@ static int nwl_pcie_parse_dt(struct nwl_pcie *pcie,
        pcie->phys_pcie_reg_base = res->start;
 
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cfg");
-       pcie->ecam_base = devm_ioremap_resource(dev, res);
+       pcie->ecam_base = devm_pci_remap_cfg_resource(dev, res);
        if (IS_ERR(pcie->ecam_base))
                return PTR_ERR(pcie->ecam_base);
        pcie->phys_ecam_base = res->start;
index 7f030f5d750bbb52e88d611b80555e852b497a6d..2fe2df51f9f8334774bc0affc7fed90fc03cfd29 100644 (file)
@@ -606,7 +606,7 @@ static int xilinx_pcie_parse_dt(struct xilinx_pcie_port *port)
                return err;
        }
 
-       port->reg_base = devm_ioremap_resource(dev, &regs);
+       port->reg_base = devm_pci_remap_cfg_resource(dev, &regs);
        if (IS_ERR(port->reg_base))
                return PTR_ERR(port->reg_base);
 
index 88a44a707b96ffe224c374167fff9ff0bbf537c6..bbf9cf8aeaad997b1b7157af60e27d0210e42a92 100644 (file)
@@ -220,7 +220,7 @@ module_param(first_slot, byte, 0);
 MODULE_PARM_DESC(first_slot, "Hotswap bus first slot number");
 module_param(last_slot, byte, 0);
 MODULE_PARM_DESC(last_slot, "Hotswap bus last slot number");
-module_param(port, ushort, 0);
+module_param_hw(port, ushort, ioport, 0);
 MODULE_PARM_DESC(port, "#ENUM signal I/O port");
 module_param(enum_bit, uint, 0);
 MODULE_PARM_DESC(enum_bit, "#ENUM signal bit (0-7)");
index 9e69403be6327156c0a7a95fa8ce5b422aa60cb9..19f30a9f461d50b3ec12847b67ed2eea251f16f5 100644 (file)
@@ -109,6 +109,12 @@ int pciehp_unconfigure_device(struct slot *p_slot)
                                break;
                        }
                }
+               if (!presence) {
+                       pci_dev_set_disconnected(dev, NULL);
+                       if (pci_has_subordinate(dev))
+                               pci_walk_bus(dev->subordinate,
+                                            pci_dev_set_disconnected, NULL);
+               }
                pci_stop_and_remove_bus_device(dev);
                /*
                 * Ensure that no new Requests will be generated from
index 2479ae8764826575825ded382b48d96491296ecf..d9dc7363ac77def7cd81f06646ae76774d92f743 100644 (file)
@@ -450,6 +450,7 @@ found:
        iov->total_VFs = total;
        iov->pgsz = pgsz;
        iov->self = dev;
+       iov->drivers_autoprobe = true;
        pci_read_config_dword(dev, pos + PCI_SRIOV_CAP, &iov->cap);
        pci_read_config_byte(dev, pos + PCI_SRIOV_FUNC_LINK, &iov->link);
        if (pci_pcie_type(dev) == PCI_EXP_TYPE_RC_END)
index f9f2a0324ecc31097e4e0785933f92da37feba9f..83d30953ce195d46ad4e5f11f740084593b23a88 100644 (file)
@@ -1,7 +1,8 @@
 /*
- * PCI IRQ failure handing code
+ * PCI IRQ handling code
  *
  * Copyright (c) 2008 James Bottomley <James.Bottomley@HansenPartnership.com>
+ * Copyright (C) 2017 Christoph Hellwig.
  */
 
 #include <linux/acpi.h>
@@ -59,3 +60,61 @@ enum pci_lost_interrupt_reason pci_lost_interrupt(struct pci_dev *pdev)
        return PCI_LOST_IRQ_NO_INFORMATION;
 }
 EXPORT_SYMBOL(pci_lost_interrupt);
+
+/**
+ * pci_request_irq - allocate an interrupt line for a PCI device
+ * @dev:       PCI device to operate on
+ * @nr:                device-relative interrupt vector index (0-based).
+ * @handler:   Function to be called when the IRQ occurs.
+ *             Primary handler for threaded interrupts.
+ *             If NULL and thread_fn != NULL the default primary handler is
+ *             installed.
+ * @thread_fn: Function called from the IRQ handler thread
+ *             If NULL, no IRQ thread is created
+ * @dev_id:    Cookie passed back to the handler function
+ * @fmt:       Printf-like format string naming the handler
+ *
+ * This call allocates interrupt resources and enables the interrupt line and
+ * IRQ handling. From the point this call is made @handler and @thread_fn may
+ * be invoked.  All interrupts requested using this function might be shared.
+ *
+ * @dev_id must not be NULL and must be globally unique.
+ */
+int pci_request_irq(struct pci_dev *dev, unsigned int nr, irq_handler_t handler,
+               irq_handler_t thread_fn, void *dev_id, const char *fmt, ...)
+{
+       va_list ap;
+       int ret;
+       char *devname;
+
+       va_start(ap, fmt);
+       devname = kvasprintf(GFP_KERNEL, fmt, ap);
+       va_end(ap);
+
+       ret = request_threaded_irq(pci_irq_vector(dev, nr), handler, thread_fn,
+                       IRQF_SHARED, devname, dev_id);
+       if (ret)
+               kfree(devname);
+       return ret;
+}
+EXPORT_SYMBOL(pci_request_irq);
+
+/**
+ * pci_free_irq - free an interrupt allocated with pci_request_irq
+ * @dev:       PCI device to operate on
+ * @nr:                device-relative interrupt vector index (0-based).
+ * @dev_id:    Device identity to free
+ *
+ * Remove an interrupt handler. The handler is removed and if the interrupt
+ * line is no longer in use by any driver it is disabled.  The caller must
+ * ensure the interrupt is disabled on the device before calling this function.
+ * The function does not return until any executing interrupts for this IRQ
+ * have completed.
+ *
+ * This function must not be called from interrupt context.
+ */
+void pci_free_irq(struct pci_dev *dev, unsigned int nr, void *dev_id)
+{
+       kfree(free_irq(pci_irq_vector(dev, nr), dev_id));
+}
+EXPORT_SYMBOL(pci_free_irq);
diff --git a/drivers/pci/mmap.c b/drivers/pci/mmap.c
new file mode 100644 (file)
index 0000000..9a5e5a9
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * mmap.c — generic PCI resource mmap helper
+ *
+ * Copyright © 2017 Amazon.com, Inc. or its affiliates.
+ *
+ * Author: David Woodhouse <dwmw2@infradead.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/pci.h>
+
+#ifdef ARCH_GENERIC_PCI_MMAP_RESOURCE
+
+/*
+ * Modern setup: generic pci_mmap_resource_range(), and implement the legacy
+ * pci_mmap_page_range() (if needed) as a wrapper round it.
+ */
+
+#ifdef HAVE_PCI_MMAP
+int pci_mmap_page_range(struct pci_dev *pdev, int bar,
+                       struct vm_area_struct *vma,
+                       enum pci_mmap_state mmap_state, int write_combine)
+{
+       resource_size_t start, end;
+
+       pci_resource_to_user(pdev, bar, &pdev->resource[bar], &start, &end);
+
+       /* Adjust vm_pgoff to be the offset within the resource */
+       vma->vm_pgoff -= start >> PAGE_SHIFT;
+       return pci_mmap_resource_range(pdev, bar, vma, mmap_state,
+                                      write_combine);
+}
+#endif
+
+static const struct vm_operations_struct pci_phys_vm_ops = {
+#ifdef CONFIG_HAVE_IOREMAP_PROT
+       .access = generic_access_phys,
+#endif
+};
+
+int pci_mmap_resource_range(struct pci_dev *pdev, int bar,
+                           struct vm_area_struct *vma,
+                           enum pci_mmap_state mmap_state, int write_combine)
+{
+       unsigned long size;
+       int ret;
+
+       size = ((pci_resource_len(pdev, bar) - 1) >> PAGE_SHIFT) + 1;
+       if (vma->vm_pgoff + vma_pages(vma) > size)
+               return -EINVAL;
+
+       if (write_combine)
+               vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+       else
+               vma->vm_page_prot = pgprot_device(vma->vm_page_prot);
+
+       if (mmap_state == pci_mmap_io) {
+               ret = pci_iobar_pfn(pdev, bar, vma);
+               if (ret)
+                       return ret;
+       } else
+               vma->vm_pgoff += (pci_resource_start(pdev, bar) >> PAGE_SHIFT);
+
+       vma->vm_ops = &pci_phys_vm_ops;
+
+       return io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+                                 vma->vm_end - vma->vm_start,
+                                 vma->vm_page_prot);
+}
+
+#elif defined(HAVE_PCI_MMAP) /* && !ARCH_GENERIC_PCI_MMAP_RESOURCE */
+
+/*
+ * Legacy setup: Impement pci_mmap_resource_range() as a wrapper around
+ * the architecture's pci_mmap_page_range(), converting to "user visible"
+ * addresses as necessary.
+ */
+
+int pci_mmap_resource_range(struct pci_dev *pdev, int bar,
+                           struct vm_area_struct *vma,
+                           enum pci_mmap_state mmap_state, int write_combine)
+{
+       resource_size_t start, end;
+
+       /*
+        * pci_mmap_page_range() expects the same kind of entry as coming
+        * from /proc/bus/pci/ which is a "user visible" value. If this is
+        * different from the resource itself, arch will do necessary fixup.
+        */
+       pci_resource_to_user(pdev, bar, &pdev->resource[bar], &start, &end);
+       vma->vm_pgoff += start >> PAGE_SHIFT;
+       return pci_mmap_page_range(pdev, bar, vma, mmap_state, write_combine);
+}
+#endif
index 0042c365b29b9b94c791ca99d00dc7263354bb71..ba44fdfda66bb5caba6c74d9ad056b34a2d01068 100644 (file)
@@ -298,7 +298,7 @@ void __pci_write_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
 {
        struct pci_dev *dev = msi_desc_to_pci_dev(entry);
 
-       if (dev->current_state != PCI_D0) {
+       if (dev->current_state != PCI_D0 || pci_dev_is_disconnected(dev)) {
                /* Don't touch the hardware now */
        } else if (entry->msi_attrib.is_msix) {
                void __iomem *base = pci_msix_desc_addr(entry);
@@ -541,7 +541,8 @@ msi_setup_entry(struct pci_dev *dev, int nvec, const struct irq_affinity *affd)
        if (affd) {
                masks = irq_create_affinity_masks(nvec, affd);
                if (!masks)
-                       pr_err("Unable to allocate affinity masks, ignoring\n");
+                       dev_err(&dev->dev, "can't allocate MSI affinity masks for %d vectors\n",
+                               nvec);
        }
 
        /* MSI Entry Initialization */
@@ -681,7 +682,8 @@ static int msix_setup_entries(struct pci_dev *dev, void __iomem *base,
        if (affd) {
                masks = irq_create_affinity_masks(nvec, affd);
                if (!masks)
-                       pr_err("Unable to allocate affinity masks, ignoring\n");
+                       dev_err(&dev->dev, "can't allocate MSI-X affinity masks for %d vectors\n",
+                               nvec);
        }
 
        for (i = 0, curmsk = masks; i < nvec; i++) {
@@ -882,7 +884,7 @@ int pci_msi_vec_count(struct pci_dev *dev)
 }
 EXPORT_SYMBOL(pci_msi_vec_count);
 
-void pci_msi_shutdown(struct pci_dev *dev)
+static void pci_msi_shutdown(struct pci_dev *dev)
 {
        struct msi_desc *desc;
        u32 mask;
@@ -973,13 +975,18 @@ static int __pci_enable_msix(struct pci_dev *dev, struct msix_entry *entries,
        return msix_capability_init(dev, entries, nvec, affd);
 }
 
-void pci_msix_shutdown(struct pci_dev *dev)
+static void pci_msix_shutdown(struct pci_dev *dev)
 {
        struct msi_desc *entry;
 
        if (!pci_msi_enable || !dev || !dev->msix_enabled)
                return;
 
+       if (pci_dev_is_disconnected(dev)) {
+               dev->msix_enabled = 0;
+               return;
+       }
+
        /* Return the device with MSI-X masked as initial states */
        for_each_pci_msi_entry(entry, dev) {
                /* Keep cached states to be restored */
index afa72717a97937cdb5d222dbb292a993fdf5d436..192e7b681b96ad82be54625e70252ca859adfb5e 100644 (file)
@@ -394,6 +394,18 @@ void __weak pcibios_free_irq(struct pci_dev *dev)
 {
 }
 
+#ifdef CONFIG_PCI_IOV
+static inline bool pci_device_can_probe(struct pci_dev *pdev)
+{
+       return (!pdev->is_virtfn || pdev->physfn->sriov->drivers_autoprobe);
+}
+#else
+static inline bool pci_device_can_probe(struct pci_dev *pdev)
+{
+       return true;
+}
+#endif
+
 static int pci_device_probe(struct device *dev)
 {
        int error;
@@ -405,10 +417,12 @@ static int pci_device_probe(struct device *dev)
                return error;
 
        pci_dev_get(pci_dev);
-       error = __pci_device_probe(drv, pci_dev);
-       if (error) {
-               pcibios_free_irq(pci_dev);
-               pci_dev_put(pci_dev);
+       if (pci_device_can_probe(pci_dev)) {
+               error = __pci_device_probe(drv, pci_dev);
+               if (error) {
+                       pcibios_free_irq(pci_dev);
+                       pci_dev_put(pci_dev);
+               }
        }
 
        return error;
@@ -461,8 +475,6 @@ static void pci_device_shutdown(struct device *dev)
 
        if (drv && drv->shutdown)
                drv->shutdown(pci_dev);
-       pci_msi_shutdown(pci_dev);
-       pci_msix_shutdown(pci_dev);
 
        /*
         * If this is a kexec reboot, turn off Bus Master bit on the
index 25d010d449a31408fe3058783eec32f0be92e3e4..31e99613a12e4d9737d082ac0c5f3be19bbdae7d 100644 (file)
@@ -526,10 +526,37 @@ exit:
        return count;
 }
 
+static ssize_t sriov_drivers_autoprobe_show(struct device *dev,
+                                           struct device_attribute *attr,
+                                           char *buf)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+
+       return sprintf(buf, "%u\n", pdev->sriov->drivers_autoprobe);
+}
+
+static ssize_t sriov_drivers_autoprobe_store(struct device *dev,
+                                            struct device_attribute *attr,
+                                            const char *buf, size_t count)
+{
+       struct pci_dev *pdev = to_pci_dev(dev);
+       bool drivers_autoprobe;
+
+       if (kstrtobool(buf, &drivers_autoprobe) < 0)
+               return -EINVAL;
+
+       pdev->sriov->drivers_autoprobe = drivers_autoprobe;
+
+       return count;
+}
+
 static struct device_attribute sriov_totalvfs_attr = __ATTR_RO(sriov_totalvfs);
 static struct device_attribute sriov_numvfs_attr =
                __ATTR(sriov_numvfs, (S_IRUGO|S_IWUSR|S_IWGRP),
                       sriov_numvfs_show, sriov_numvfs_store);
+static struct device_attribute sriov_drivers_autoprobe_attr =
+               __ATTR(sriov_drivers_autoprobe, (S_IRUGO|S_IWUSR|S_IWGRP),
+                      sriov_drivers_autoprobe_show, sriov_drivers_autoprobe_store);
 #endif /* CONFIG_PCI_IOV */
 
 static ssize_t driver_override_store(struct device *dev,
@@ -980,20 +1007,24 @@ void pci_remove_legacy_files(struct pci_bus *b)
 }
 #endif /* HAVE_PCI_LEGACY */
 
-#ifdef HAVE_PCI_MMAP
+#if defined(HAVE_PCI_MMAP) || defined(ARCH_GENERIC_PCI_MMAP_RESOURCE)
 
 int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vma,
                  enum pci_mmap_api mmap_api)
 {
-       unsigned long nr, start, size, pci_start;
+       unsigned long nr, start, size;
+       resource_size_t pci_start = 0, pci_end;
 
        if (pci_resource_len(pdev, resno) == 0)
                return 0;
        nr = vma_pages(vma);
        start = vma->vm_pgoff;
        size = ((pci_resource_len(pdev, resno) - 1) >> PAGE_SHIFT) + 1;
-       pci_start = (mmap_api == PCI_MMAP_PROCFS) ?
-                       pci_resource_start(pdev, resno) >> PAGE_SHIFT : 0;
+       if (mmap_api == PCI_MMAP_PROCFS) {
+               pci_resource_to_user(pdev, resno, &pdev->resource[resno],
+                                    &pci_start, &pci_end);
+               pci_start >>= PAGE_SHIFT;
+       }
        if (start >= pci_start && start < pci_start + size &&
                        start + nr <= pci_start + size)
                return 1;
@@ -1013,37 +1044,24 @@ static int pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
                             struct vm_area_struct *vma, int write_combine)
 {
        struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
-       struct resource *res = attr->private;
+       int bar = (unsigned long)attr->private;
        enum pci_mmap_state mmap_type;
-       resource_size_t start, end;
-       int i;
-
-       for (i = 0; i < PCI_ROM_RESOURCE; i++)
-               if (res == &pdev->resource[i])
-                       break;
-       if (i >= PCI_ROM_RESOURCE)
-               return -ENODEV;
+       struct resource *res = &pdev->resource[bar];
 
        if (res->flags & IORESOURCE_MEM && iomem_is_exclusive(res->start))
                return -EINVAL;
 
-       if (!pci_mmap_fits(pdev, i, vma, PCI_MMAP_SYSFS)) {
+       if (!pci_mmap_fits(pdev, bar, vma, PCI_MMAP_SYSFS)) {
                WARN(1, "process \"%s\" tried to map 0x%08lx bytes at page 0x%08lx on %s BAR %d (start 0x%16Lx, size 0x%16Lx)\n",
                        current->comm, vma->vm_end-vma->vm_start, vma->vm_pgoff,
-                       pci_name(pdev), i,
-                       (u64)pci_resource_start(pdev, i),
-                       (u64)pci_resource_len(pdev, i));
+                       pci_name(pdev), bar,
+                       (u64)pci_resource_start(pdev, bar),
+                       (u64)pci_resource_len(pdev, bar));
                return -EINVAL;
        }
-
-       /* pci_mmap_page_range() expects the same kind of entry as coming
-        * from /proc/bus/pci/ which is a "user visible" value. If this is
-        * different from the resource itself, arch will do necessary fixup.
-        */
-       pci_resource_to_user(pdev, i, res, &start, &end);
-       vma->vm_pgoff += start >> PAGE_SHIFT;
        mmap_type = res->flags & IORESOURCE_MEM ? pci_mmap_mem : pci_mmap_io;
-       return pci_mmap_page_range(pdev, vma, mmap_type, write_combine);
+
+       return pci_mmap_resource_range(pdev, bar, vma, mmap_type, write_combine);
 }
 
 static int pci_mmap_resource_uc(struct file *filp, struct kobject *kobj,
@@ -1065,22 +1083,18 @@ static ssize_t pci_resource_io(struct file *filp, struct kobject *kobj,
                               loff_t off, size_t count, bool write)
 {
        struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
-       struct resource *res = attr->private;
+       int bar = (unsigned long)attr->private;
+       struct resource *res;
        unsigned long port = off;
-       int i;
 
-       for (i = 0; i < PCI_ROM_RESOURCE; i++)
-               if (res == &pdev->resource[i])
-                       break;
-       if (i >= PCI_ROM_RESOURCE)
-               return -ENODEV;
+       res = &pdev->resource[bar];
 
-       port += pci_resource_start(pdev, i);
+       port += pci_resource_start(pdev, bar);
 
-       if (port > pci_resource_end(pdev, i))
+       if (port > pci_resource_end(pdev, bar))
                return 0;
 
-       if (port + count - 1 > pci_resource_end(pdev, i))
+       if (port + count - 1 > pci_resource_end(pdev, bar))
                return -EINVAL;
 
        switch (count) {
@@ -1170,16 +1184,19 @@ static int pci_create_attr(struct pci_dev *pdev, int num, int write_combine)
        } else {
                pdev->res_attr[num] = res_attr;
                sprintf(res_attr_name, "resource%d", num);
-               res_attr->mmap = pci_mmap_resource_uc;
-       }
-       if (pci_resource_flags(pdev, num) & IORESOURCE_IO) {
-               res_attr->read = pci_read_resource_io;
-               res_attr->write = pci_write_resource_io;
+               if (pci_resource_flags(pdev, num) & IORESOURCE_IO) {
+                       res_attr->read = pci_read_resource_io;
+                       res_attr->write = pci_write_resource_io;
+                       if (arch_can_pci_mmap_io())
+                               res_attr->mmap = pci_mmap_resource_uc;
+               } else {
+                       res_attr->mmap = pci_mmap_resource_uc;
+               }
        }
        res_attr->attr.name = res_attr_name;
        res_attr->attr.mode = S_IRUSR | S_IWUSR;
        res_attr->size = pci_resource_len(pdev, num);
-       res_attr->private = &pdev->resource[num];
+       res_attr->private = (void *)(unsigned long)num;
        retval = sysfs_create_bin_file(&pdev->dev.kobj, res_attr);
        if (retval)
                kfree(res_attr);
@@ -1207,9 +1224,9 @@ static int pci_create_resource_files(struct pci_dev *pdev)
 
                retval = pci_create_attr(pdev, i, 0);
                /* for prefetchable resources, create a WC mappable file */
-               if (!retval && pdev->resource[i].flags & IORESOURCE_PREFETCH)
+               if (!retval && arch_can_pci_mmap_wc() &&
+                   pdev->resource[i].flags & IORESOURCE_PREFETCH)
                        retval = pci_create_attr(pdev, i, 1);
-
                if (retval) {
                        pci_remove_resource_files(pdev);
                        return retval;
@@ -1549,6 +1566,7 @@ static struct attribute_group pci_dev_hp_attr_group = {
 static struct attribute *sriov_dev_attrs[] = {
        &sriov_totalvfs_attr.attr,
        &sriov_numvfs_attr.attr,
+       &sriov_drivers_autoprobe_attr.attr,
        NULL,
 };
 
index 7904d02ffdb97e5f23d915e9c83edbf599ddf58b..b01bd5bba8e604709c3b51f14f9fbdb796a2c4fb 100644 (file)
@@ -66,7 +66,8 @@ static void pci_dev_d3_sleep(struct pci_dev *dev)
        if (delay < pci_pm_d3_delay)
                delay = pci_pm_d3_delay;
 
-       msleep(delay);
+       if (delay)
+               msleep(delay);
 }
 
 #ifdef CONFIG_PCI_DOMAINS
@@ -827,7 +828,8 @@ static void __pci_start_power_transition(struct pci_dev *dev, pci_power_t state)
                 * because have already delayed for the bridge.
                 */
                if (dev->runtime_d3cold) {
-                       msleep(dev->d3cold_delay);
+                       if (dev->d3cold_delay)
+                               msleep(dev->d3cold_delay);
                        /*
                         * When powering on a bridge from D3cold, the
                         * whole hierarchy may be powered on into
@@ -1782,8 +1784,8 @@ static void pci_pme_list_scan(struct work_struct *work)
                }
        }
        if (!list_empty(&pci_pme_list))
-               schedule_delayed_work(&pci_pme_work,
-                                     msecs_to_jiffies(PME_TIMEOUT));
+               queue_delayed_work(system_freezable_wq, &pci_pme_work,
+                                  msecs_to_jiffies(PME_TIMEOUT));
        mutex_unlock(&pci_pme_list_mutex);
 }
 
@@ -1848,8 +1850,9 @@ void pci_pme_active(struct pci_dev *dev, bool enable)
                        mutex_lock(&pci_pme_list_mutex);
                        list_add(&pme_dev->list, &pci_pme_list);
                        if (list_is_singular(&pci_pme_list))
-                               schedule_delayed_work(&pci_pme_work,
-                                                     msecs_to_jiffies(PME_TIMEOUT));
+                               queue_delayed_work(system_freezable_wq,
+                                                  &pci_pme_work,
+                                                  msecs_to_jiffies(PME_TIMEOUT));
                        mutex_unlock(&pci_pme_list_mutex);
                } else {
                        mutex_lock(&pci_pme_list_mutex);
@@ -3363,7 +3366,7 @@ unsigned long __weak pci_address_to_pio(phys_addr_t address)
  *     Only architectures that have memory mapped IO functions defined
  *     (and the PCI_IOBASE value defined) should call this function.
  */
-int __weak pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr)
+int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr)
 {
 #if defined(PCI_IOBASE) && defined(CONFIG_MMU)
        unsigned long vaddr = (unsigned long)PCI_IOBASE + res->start;
@@ -3383,6 +3386,7 @@ int __weak pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr)
        return -ENODEV;
 #endif
 }
+EXPORT_SYMBOL(pci_remap_iospace);
 
 /**
  *     pci_unmap_iospace - Unmap the memory mapped I/O space
@@ -3400,6 +3404,89 @@ void pci_unmap_iospace(struct resource *res)
        unmap_kernel_range(vaddr, resource_size(res));
 #endif
 }
+EXPORT_SYMBOL(pci_unmap_iospace);
+
+/**
+ * devm_pci_remap_cfgspace - Managed pci_remap_cfgspace()
+ * @dev: Generic device to remap IO address for
+ * @offset: Resource address to map
+ * @size: Size of map
+ *
+ * Managed pci_remap_cfgspace().  Map is automatically unmapped on driver
+ * detach.
+ */
+void __iomem *devm_pci_remap_cfgspace(struct device *dev,
+                                     resource_size_t offset,
+                                     resource_size_t size)
+{
+       void __iomem **ptr, *addr;
+
+       ptr = devres_alloc(devm_ioremap_release, sizeof(*ptr), GFP_KERNEL);
+       if (!ptr)
+               return NULL;
+
+       addr = pci_remap_cfgspace(offset, size);
+       if (addr) {
+               *ptr = addr;
+               devres_add(dev, ptr);
+       } else
+               devres_free(ptr);
+
+       return addr;
+}
+EXPORT_SYMBOL(devm_pci_remap_cfgspace);
+
+/**
+ * devm_pci_remap_cfg_resource - check, request region and ioremap cfg resource
+ * @dev: generic device to handle the resource for
+ * @res: configuration space resource to be handled
+ *
+ * Checks that a resource is a valid memory region, requests the memory
+ * region and ioremaps with pci_remap_cfgspace() API that ensures the
+ * proper PCI configuration space memory attributes are guaranteed.
+ *
+ * All operations are managed and will be undone on driver detach.
+ *
+ * Returns a pointer to the remapped memory or an ERR_PTR() encoded error code
+ * on failure. Usage example:
+ *
+ *     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ *     base = devm_pci_remap_cfg_resource(&pdev->dev, res);
+ *     if (IS_ERR(base))
+ *             return PTR_ERR(base);
+ */
+void __iomem *devm_pci_remap_cfg_resource(struct device *dev,
+                                         struct resource *res)
+{
+       resource_size_t size;
+       const char *name;
+       void __iomem *dest_ptr;
+
+       BUG_ON(!dev);
+
+       if (!res || resource_type(res) != IORESOURCE_MEM) {
+               dev_err(dev, "invalid resource\n");
+               return IOMEM_ERR_PTR(-EINVAL);
+       }
+
+       size = resource_size(res);
+       name = res->name ?: dev_name(dev);
+
+       if (!devm_request_mem_region(dev, res->start, size, name)) {
+               dev_err(dev, "can't request region for resource %pR\n", res);
+               return IOMEM_ERR_PTR(-EBUSY);
+       }
+
+       dest_ptr = devm_pci_remap_cfgspace(dev, res->start, size);
+       if (!dest_ptr) {
+               dev_err(dev, "ioremap failed for resource %pR\n", res);
+               devm_release_mem_region(dev, res->start, size);
+               dest_ptr = IOMEM_ERR_PTR(-ENOMEM);
+       }
+
+       return dest_ptr;
+}
+EXPORT_SYMBOL(devm_pci_remap_cfg_resource);
 
 static void __pci_set_master(struct pci_dev *dev, bool enable)
 {
@@ -3773,24 +3860,41 @@ static void pci_flr_wait(struct pci_dev *dev)
                         (i - 1) * 100);
 }
 
-static int pcie_flr(struct pci_dev *dev, int probe)
+/**
+ * pcie_has_flr - check if a device supports function level resets
+ * @dev:       device to check
+ *
+ * Returns true if the device advertises support for PCIe function level
+ * resets.
+ */
+static bool pcie_has_flr(struct pci_dev *dev)
 {
        u32 cap;
 
-       pcie_capability_read_dword(dev, PCI_EXP_DEVCAP, &cap);
-       if (!(cap & PCI_EXP_DEVCAP_FLR))
-               return -ENOTTY;
+       if (dev->dev_flags & PCI_DEV_FLAGS_NO_FLR_RESET)
+               return false;
 
-       if (probe)
-               return 0;
+       pcie_capability_read_dword(dev, PCI_EXP_DEVCAP, &cap);
+       return cap & PCI_EXP_DEVCAP_FLR;
+}
 
+/**
+ * pcie_flr - initiate a PCIe function level reset
+ * @dev:       device to reset
+ *
+ * Initiate a function level reset on @dev.  The caller should ensure the
+ * device supports FLR before calling this function, e.g. by using the
+ * pcie_has_flr() helper.
+ */
+void pcie_flr(struct pci_dev *dev)
+{
        if (!pci_wait_for_pending_transaction(dev))
                dev_err(&dev->dev, "timed out waiting for pending transaction; performing function level reset anyway\n");
 
        pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR);
        pci_flr_wait(dev);
-       return 0;
 }
+EXPORT_SYMBOL_GPL(pcie_flr);
 
 static int pci_af_flr(struct pci_dev *dev, int probe)
 {
@@ -3801,6 +3905,9 @@ static int pci_af_flr(struct pci_dev *dev, int probe)
        if (!pos)
                return -ENOTTY;
 
+       if (dev->dev_flags & PCI_DEV_FLAGS_NO_FLR_RESET)
+               return -ENOTTY;
+
        pci_read_config_byte(dev, pos + PCI_AF_CAP, &cap);
        if (!(cap & PCI_AF_CAP_TP) || !(cap & PCI_AF_CAP_FLR))
                return -ENOTTY;
@@ -3971,9 +4078,12 @@ static int __pci_dev_reset(struct pci_dev *dev, int probe)
        if (rc != -ENOTTY)
                goto done;
 
-       rc = pcie_flr(dev, probe);
-       if (rc != -ENOTTY)
+       if (pcie_has_flr(dev)) {
+               if (!probe)
+                       pcie_flr(dev);
+               rc = 0;
                goto done;
+       }
 
        rc = pci_af_flr(dev, probe);
        if (rc != -ENOTTY)
@@ -4932,6 +5042,8 @@ bool pci_device_is_present(struct pci_dev *pdev)
 {
        u32 v;
 
+       if (pci_dev_is_disconnected(pdev))
+               return false;
        return pci_bus_read_dev_vendor_id(pdev->bus, pdev->devfn, &v, 0);
 }
 EXPORT_SYMBOL_GPL(pci_device_is_present);
@@ -4947,6 +5059,11 @@ void pci_ignore_hotplug(struct pci_dev *dev)
 }
 EXPORT_SYMBOL_GPL(pci_ignore_hotplug);
 
+resource_size_t __weak pcibios_default_alignment(void)
+{
+       return 0;
+}
+
 #define RESOURCE_ALIGNMENT_PARAM_SIZE COMMAND_LINE_SIZE
 static char resource_alignment_param[RESOURCE_ALIGNMENT_PARAM_SIZE] = {0};
 static DEFINE_SPINLOCK(resource_alignment_lock);
@@ -4954,22 +5071,25 @@ static DEFINE_SPINLOCK(resource_alignment_lock);
 /**
  * pci_specified_resource_alignment - get resource alignment specified by user.
  * @dev: the PCI device to get
+ * @resize: whether or not to change resources' size when reassigning alignment
  *
  * RETURNS: Resource alignment if it is specified.
  *          Zero if it is not specified.
  */
-static resource_size_t pci_specified_resource_alignment(struct pci_dev *dev)
+static resource_size_t pci_specified_resource_alignment(struct pci_dev *dev,
+                                                       bool *resize)
 {
        int seg, bus, slot, func, align_order, count;
        unsigned short vendor, device, subsystem_vendor, subsystem_device;
-       resource_size_t align = 0;
+       resource_size_t align = pcibios_default_alignment();
        char *p;
 
        spin_lock(&resource_alignment_lock);
        p = resource_alignment_param;
-       if (!*p)
+       if (!*p && !align)
                goto out;
        if (pci_has_flag(PCI_PROBE_ONLY)) {
+               align = 0;
                pr_info_once("PCI: Ignoring requested alignments (PCI_PROBE_ONLY)\n");
                goto out;
        }
@@ -4999,6 +5119,7 @@ static resource_size_t pci_specified_resource_alignment(struct pci_dev *dev)
                                (!device || (device == dev->device)) &&
                                (!subsystem_vendor || (subsystem_vendor == dev->subsystem_vendor)) &&
                                (!subsystem_device || (subsystem_device == dev->subsystem_device))) {
+                               *resize = true;
                                if (align_order == -1)
                                        align = PAGE_SIZE;
                                else
@@ -5024,6 +5145,7 @@ static resource_size_t pci_specified_resource_alignment(struct pci_dev *dev)
                                bus == dev->bus->number &&
                                slot == PCI_SLOT(dev->devfn) &&
                                func == PCI_FUNC(dev->devfn)) {
+                               *resize = true;
                                if (align_order == -1)
                                        align = PAGE_SIZE;
                                else
@@ -5043,6 +5165,68 @@ out:
        return align;
 }
 
+static void pci_request_resource_alignment(struct pci_dev *dev, int bar,
+                                          resource_size_t align, bool resize)
+{
+       struct resource *r = &dev->resource[bar];
+       resource_size_t size;
+
+       if (!(r->flags & IORESOURCE_MEM))
+               return;
+
+       if (r->flags & IORESOURCE_PCI_FIXED) {
+               dev_info(&dev->dev, "BAR%d %pR: ignoring requested alignment %#llx\n",
+                        bar, r, (unsigned long long)align);
+               return;
+       }
+
+       size = resource_size(r);
+       if (size >= align)
+               return;
+
+       /*
+        * Increase the alignment of the resource.  There are two ways we
+        * can do this:
+        *
+        * 1) Increase the size of the resource.  BARs are aligned on their
+        *    size, so when we reallocate space for this resource, we'll
+        *    allocate it with the larger alignment.  This also prevents
+        *    assignment of any other BARs inside the alignment region, so
+        *    if we're requesting page alignment, this means no other BARs
+        *    will share the page.
+        *
+        *    The disadvantage is that this makes the resource larger than
+        *    the hardware BAR, which may break drivers that compute things
+        *    based on the resource size, e.g., to find registers at a
+        *    fixed offset before the end of the BAR.
+        *
+        * 2) Retain the resource size, but use IORESOURCE_STARTALIGN and
+        *    set r->start to the desired alignment.  By itself this
+        *    doesn't prevent other BARs being put inside the alignment
+        *    region, but if we realign *every* resource of every device in
+        *    the system, none of them will share an alignment region.
+        *
+        * When the user has requested alignment for only some devices via
+        * the "pci=resource_alignment" argument, "resize" is true and we
+        * use the first method.  Otherwise we assume we're aligning all
+        * devices and we use the second.
+        */
+
+       dev_info(&dev->dev, "BAR%d %pR: requesting alignment to %#llx\n",
+                bar, r, (unsigned long long)align);
+
+       if (resize) {
+               r->start = 0;
+               r->end = align - 1;
+       } else {
+               r->flags &= ~IORESOURCE_SIZEALIGN;
+               r->flags |= IORESOURCE_STARTALIGN;
+               r->start = align;
+               r->end = r->start + size - 1;
+       }
+       r->flags |= IORESOURCE_UNSET;
+}
+
 /*
  * This function disables memory decoding and releases memory resources
  * of the device specified by kernel's boot parameter 'pci=resource_alignment='.
@@ -5054,8 +5238,9 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev)
 {
        int i;
        struct resource *r;
-       resource_size_t align, size;
+       resource_size_t align;
        u16 command;
+       bool resize = false;
 
        /*
         * VF BARs are read-only zero according to SR-IOV spec r1.1, sec
@@ -5067,7 +5252,7 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev)
                return;
 
        /* check if specified PCI is target device to reassign */
-       align = pci_specified_resource_alignment(dev);
+       align = pci_specified_resource_alignment(dev, &resize);
        if (!align)
                return;
 
@@ -5084,28 +5269,11 @@ void pci_reassigndev_resource_alignment(struct pci_dev *dev)
        command &= ~PCI_COMMAND_MEMORY;
        pci_write_config_word(dev, PCI_COMMAND, command);
 
-       for (i = 0; i < PCI_BRIDGE_RESOURCES; i++) {
-               r = &dev->resource[i];
-               if (!(r->flags & IORESOURCE_MEM))
-                       continue;
-               if (r->flags & IORESOURCE_PCI_FIXED) {
-                       dev_info(&dev->dev, "Ignoring requested alignment for BAR%d: %pR\n",
-                               i, r);
-                       continue;
-               }
+       for (i = 0; i <= PCI_ROM_RESOURCE; i++)
+               pci_request_resource_alignment(dev, i, align, resize);
 
-               size = resource_size(r);
-               if (size < align) {
-                       size = align;
-                       dev_info(&dev->dev,
-                               "Rounding up size of resource #%d to %#llx.\n",
-                               i, (unsigned long long)size);
-               }
-               r->flags |= IORESOURCE_UNSET;
-               r->end = size - 1;
-               r->start = 0;
-       }
-       /* Need to disable bridge's resource window,
+       /*
+        * Need to disable bridge's resource window,
         * to enable the kernel to reassign new resource
         * window later on.
         */
index 4dbf9f96ae5ba31d761b30ee43c11d2f053140fe..f8113e5b98129026e6c100b7b8f803a74507a442 100644 (file)
@@ -23,14 +23,14 @@ void pci_create_firmware_label_files(struct pci_dev *pdev);
 void pci_remove_firmware_label_files(struct pci_dev *pdev);
 #endif
 void pci_cleanup_rom(struct pci_dev *dev);
-#ifdef HAVE_PCI_MMAP
+
 enum pci_mmap_api {
        PCI_MMAP_SYSFS, /* mmap on /sys/bus/pci/devices/<BDF>/resource<N> */
        PCI_MMAP_PROCFS /* mmap on /proc/bus/pci/<BDF> */
 };
 int pci_mmap_fits(struct pci_dev *pdev, int resno, struct vm_area_struct *vmai,
                  enum pci_mmap_api mmap_api);
-#endif
+
 int pci_probe_reset_function(struct pci_dev *dev);
 
 /**
@@ -274,8 +274,23 @@ struct pci_sriov {
        struct pci_dev *self;   /* this PF */
        struct mutex lock;      /* lock for setting sriov_numvfs in sysfs */
        resource_size_t barsz[PCI_SRIOV_NUM_BARS];      /* VF BAR size */
+       bool drivers_autoprobe; /* auto probing of VFs by driver */
 };
 
+/* pci_dev priv_flags */
+#define PCI_DEV_DISCONNECTED 0
+
+static inline int pci_dev_set_disconnected(struct pci_dev *dev, void *unused)
+{
+       set_bit(PCI_DEV_DISCONNECTED, &dev->priv_flags);
+       return 0;
+}
+
+static inline bool pci_dev_is_disconnected(const struct pci_dev *dev)
+{
+       return test_bit(PCI_DEV_DISCONNECTED, &dev->priv_flags);
+}
+
 #ifdef CONFIG_PCI_ATS
 void pci_restore_ats_state(struct pci_dev *dev);
 #else
index d4d70ef4a2d7a9f844a0e7e72e5a532c116d5137..77d2ca99d2ec20bb0cf2b6b07d9add8cca845e1f 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/init.h>
 #include <linux/pci.h>
 #include <linux/pcieport_if.h>
+#include "../pci.h"
 
 struct dpc_dev {
        struct pcie_device      *dev;
@@ -66,6 +67,10 @@ static void interrupt_event_handler(struct work_struct *work)
        list_for_each_entry_safe_reverse(dev, temp, &parent->devices,
                                         bus_list) {
                pci_dev_get(dev);
+               pci_dev_set_disconnected(dev, NULL);
+               if (pci_has_subordinate(dev))
+                       pci_walk_bus(dev->subordinate,
+                                    pci_dev_set_disconnected, NULL);
                pci_stop_and_remove_bus_device(dev);
                pci_dev_put(dev);
        }
index 90592d424e9b67458ad740ddb3b09d50f5ec30ff..19c8950c6c382f3c56c9337565483fd2a74419b4 100644 (file)
@@ -175,7 +175,7 @@ static inline unsigned long decode_bar(struct pci_dev *dev, u32 bar)
 int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
                    struct resource *res, unsigned int pos)
 {
-       u32 l, sz, mask;
+       u32 l = 0, sz = 0, mask;
        u64 l64, sz64, mask64;
        u16 orig_cmd;
        struct pci_bus_region region, inverted_region;
@@ -231,7 +231,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
                        res->flags |= IORESOURCE_ROM_ENABLE;
                l64 = l & PCI_ROM_ADDRESS_MASK;
                sz64 = sz & PCI_ROM_ADDRESS_MASK;
-               mask64 = (u32)PCI_ROM_ADDRESS_MASK;
+               mask64 = PCI_ROM_ADDRESS_MASK;
        }
 
        if (res->flags & IORESOURCE_MEM_64) {
@@ -1914,33 +1914,6 @@ static void pci_set_msi_domain(struct pci_dev *dev)
        dev_set_msi_domain(&dev->dev, d);
 }
 
-/**
- * pci_dma_configure - Setup DMA configuration
- * @dev: ptr to pci_dev struct of the PCI device
- *
- * Function to update PCI devices's DMA configuration using the same
- * info from the OF node or ACPI node of host bridge's parent (if any).
- */
-static void pci_dma_configure(struct pci_dev *dev)
-{
-       struct device *bridge = pci_get_host_bridge_device(dev);
-
-       if (IS_ENABLED(CONFIG_OF) &&
-               bridge->parent && bridge->parent->of_node) {
-                       of_dma_configure(&dev->dev, bridge->parent->of_node);
-       } else if (has_acpi_companion(bridge)) {
-               struct acpi_device *adev = to_acpi_device_node(bridge->fwnode);
-               enum dev_dma_attr attr = acpi_get_dma_attr(adev);
-
-               if (attr == DEV_DMA_NOT_SUPPORTED)
-                       dev_warn(&dev->dev, "DMA not supported.\n");
-               else
-                       acpi_dma_configure(&dev->dev, attr);
-       }
-
-       pci_put_host_bridge_device(bridge);
-}
-
 void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
 {
        int ret;
@@ -1954,7 +1927,6 @@ void pci_device_add(struct pci_dev *dev, struct pci_bus *bus)
        dev->dev.dma_mask = &dev->dma_mask;
        dev->dev.dma_parms = &dev->dma_parms;
        dev->dev.coherent_dma_mask = 0xffffffffull;
-       pci_dma_configure(dev);
 
        pci_set_dma_max_seg_size(dev, 65536);
        pci_set_dma_seg_boundary(dev, 0xffffffff);
index f82710a8694ddd48925a8ba92ef196e033e06dc8..098360d7ff81639c90e6ec9bcc0fe56a2a01fd7d 100644 (file)
@@ -202,6 +202,8 @@ static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd,
 
 #ifdef HAVE_PCI_MMAP
        case PCIIOC_MMAP_IS_IO:
+               if (!arch_can_pci_mmap_io())
+                       return -EINVAL;
                fpriv->mmap_state = pci_mmap_io;
                break;
 
@@ -210,14 +212,15 @@ static long proc_bus_pci_ioctl(struct file *file, unsigned int cmd,
                break;
 
        case PCIIOC_WRITE_COMBINE:
-               if (arg)
-                       fpriv->write_combine = 1;
-               else
-                       fpriv->write_combine = 0;
-               break;
-
+               if (arch_can_pci_mmap_wc()) {
+                       if (arg)
+                               fpriv->write_combine = 1;
+                       else
+                               fpriv->write_combine = 0;
+                       break;
+               }
+               /* If arch decided it can't, fall through... */
 #endif /* HAVE_PCI_MMAP */
-
        default:
                ret = -EINVAL;
                break;
@@ -231,25 +234,35 @@ static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma)
 {
        struct pci_dev *dev = PDE_DATA(file_inode(file));
        struct pci_filp_private *fpriv = file->private_data;
-       int i, ret, write_combine;
+       int i, ret, write_combine = 0, res_bit = IORESOURCE_MEM;
 
        if (!capable(CAP_SYS_RAWIO))
                return -EPERM;
 
+       if (fpriv->mmap_state == pci_mmap_io) {
+               if (!arch_can_pci_mmap_io())
+                       return -EINVAL;
+               res_bit = IORESOURCE_IO;
+       }
+
        /* Make sure the caller is mapping a real resource for this device */
        for (i = 0; i < PCI_ROM_RESOURCE; i++) {
-               if (pci_mmap_fits(dev, i, vma,  PCI_MMAP_PROCFS))
+               if (dev->resource[i].flags & res_bit &&
+                   pci_mmap_fits(dev, i, vma,  PCI_MMAP_PROCFS))
                        break;
        }
 
        if (i >= PCI_ROM_RESOURCE)
                return -ENODEV;
 
-       if (fpriv->mmap_state == pci_mmap_mem)
-               write_combine = fpriv->write_combine;
-       else
-               write_combine = 0;
-       ret = pci_mmap_page_range(dev, vma,
+       if (fpriv->mmap_state == pci_mmap_mem &&
+           fpriv->write_combine) {
+               if (dev->resource[i].flags & IORESOURCE_PREFETCH)
+                       write_combine = 1;
+               else
+                       return -EINVAL;
+       }
+       ret = pci_mmap_page_range(dev, i, vma,
                                  fpriv->mmap_state, write_combine);
        if (ret < 0)
                return ret;
index 673683660b5c70567d7c49cd091c5c8ecf088655..085fb787aa9e03b88b505ec9365ecd7a275a3f79 100644 (file)
@@ -1685,6 +1685,29 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,     0x260a, quirk_intel_pcie_pm);
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,   0x260b, quirk_intel_pcie_pm);
 
 #ifdef CONFIG_X86_IO_APIC
+static int dmi_disable_ioapicreroute(const struct dmi_system_id *d)
+{
+       noioapicreroute = 1;
+       pr_info("%s detected: disable boot interrupt reroute\n", d->ident);
+
+       return 0;
+}
+
+static struct dmi_system_id boot_interrupt_dmi_table[] = {
+       /*
+        * Systems to exclude from boot interrupt reroute quirks
+        */
+       {
+               .callback = dmi_disable_ioapicreroute,
+               .ident = "ASUSTek Computer INC. M2N-LR",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "ASUSTek Computer INC."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "M2N-LR"),
+               },
+       },
+       {}
+};
+
 /*
  * Boot interrupts on some chipsets cannot be turned off. For these chipsets,
  * remap the original interrupt in the linux kernel to the boot interrupt, so
@@ -1693,6 +1716,7 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL,      0x260b, quirk_intel_pcie_pm);
  */
 static void quirk_reroute_to_boot_interrupts_intel(struct pci_dev *dev)
 {
+       dmi_check_system(boot_interrupt_dmi_table);
        if (noioapicquirk || noioapicreroute)
                return;
 
@@ -3642,19 +3666,11 @@ static int reset_intel_82599_sfp_virtfn(struct pci_dev *dev, int probe)
         *
         * The 82599 supports FLR on VFs, but FLR support is reported only
         * in the PF DEVCAP (sec 9.3.10.4), not in the VF DEVCAP (sec 9.5).
-        * Therefore, we can't use pcie_flr(), which checks the VF DEVCAP.
+        * Thus we must call pcie_flr() directly without first checking if it is
+        * supported.
         */
-
-       if (probe)
-               return 0;
-
-       if (!pci_wait_for_pending_transaction(dev))
-               dev_err(&dev->dev, "transaction is not cleared; proceeding with reset anyway\n");
-
-       pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR);
-
-       msleep(100);
-
+       if (!probe)
+               pcie_flr(dev);
        return 0;
 }
 
@@ -3759,20 +3775,7 @@ static int reset_chelsio_generic_dev(struct pci_dev *dev, int probe)
                                      PCI_MSIX_FLAGS_ENABLE |
                                      PCI_MSIX_FLAGS_MASKALL);
 
-       /*
-        * Start of pcie_flr() code sequence.  This reset code is a copy of
-        * the guts of pcie_flr() because that's not an exported function.
-        */
-
-       if (!pci_wait_for_pending_transaction(dev))
-               dev_err(&dev->dev, "transaction is not cleared; proceeding with reset anyway\n");
-
-       pcie_capability_set_word(dev, PCI_EXP_DEVCTL, PCI_EXP_DEVCTL_BCR_FLR);
-       msleep(100);
-
-       /*
-        * End of pcie_flr() code sequence.
-        */
+       pcie_flr(dev);
 
        /*
         * Restore the configuration information (BAR values, etc.) including
@@ -3939,6 +3942,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ASMEDIA, 0x1080,
 DECLARE_PCI_FIXUP_HEADER(0x10e3, 0x8113, quirk_use_pcie_bridge_dma_alias);
 /* ITE 8892, https://bugzilla.kernel.org/show_bug.cgi?id=73551 */
 DECLARE_PCI_FIXUP_HEADER(0x1283, 0x8892, quirk_use_pcie_bridge_dma_alias);
+/* ITE 8893 has the same problem as the 8892 */
+DECLARE_PCI_FIXUP_HEADER(0x1283, 0x8893, quirk_use_pcie_bridge_dma_alias);
 /* Intel 82801, https://bugzilla.kernel.org/show_bug.cgi?id=44881#c49 */
 DECLARE_PCI_FIXUP_HEADER(0x8086, 0x244e, quirk_use_pcie_bridge_dma_alias);
 
@@ -3957,6 +3962,20 @@ static void quirk_mic_x200_dma_alias(struct pci_dev *pdev)
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2260, quirk_mic_x200_dma_alias);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2264, quirk_mic_x200_dma_alias);
 
+/*
+ * The IOMMU and interrupt controller on Broadcom Vulcan/Cavium ThunderX2 are
+ * associated not at the root bus, but at a bridge below. This quirk avoids
+ * generating invalid DMA aliases.
+ */
+static void quirk_bridge_cavm_thrx2_pcie_root(struct pci_dev *pdev)
+{
+       pdev->dev_flags |= PCI_DEV_FLAGS_BRIDGE_XLATE_ROOT;
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM, 0x9000,
+                               quirk_bridge_cavm_thrx2_pcie_root);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_BROADCOM, 0x9084,
+                               quirk_bridge_cavm_thrx2_pcie_root);
+
 /*
  * Intersil/Techwell TW686[4589]-based video capture cards have an empty (zero)
  * class code.  Fix it.
@@ -4095,6 +4114,9 @@ static int pci_quirk_cavium_acs(struct pci_dev *dev, u16 acs_flags)
        acs_flags &= ~(PCI_ACS_SV | PCI_ACS_TB | PCI_ACS_RR |
                       PCI_ACS_CR | PCI_ACS_UF | PCI_ACS_DT);
 
+       if (!((dev->device >= 0xa000) && (dev->device <= 0xa0ff)))
+               return -ENOTTY;
+
        return acs_flags ? 0 : 1;
 }
 
@@ -4634,3 +4656,11 @@ DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2030, quirk_no_aersid);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2031, quirk_no_aersid);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2032, quirk_no_aersid);
 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x2033, quirk_no_aersid);
+
+/* FLR may cause some 82579 devices to hang. */
+static void quirk_intel_no_flr(struct pci_dev *dev)
+{
+       dev->dev_flags |= PCI_DEV_FLAGS_NO_FLR_RESET;
+}
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1502, quirk_intel_no_flr);
+DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_INTEL, 0x1503, quirk_intel_no_flr);
index 33e0f033a48e7e2f6097b13d4425d8d17b1cabb7..4c6044ad7368acbe617fbd6bd90bfb359f29032a 100644 (file)
@@ -60,6 +60,10 @@ int pci_for_each_dma_alias(struct pci_dev *pdev,
 
                tmp = bus->self;
 
+               /* stop at bridge where translation unit is associated */
+               if (tmp->dev_flags & PCI_DEV_FLAGS_BRIDGE_XLATE_ROOT)
+                       return ret;
+
                /*
                 * PCIe-to-PCI/X bridges alias transactions from downstream
                 * devices using the subordinate bus number (PCI Express to
index cb389277df413915e5784f1c18bea599dc90fca8..958da7db90331c44315f95ab90553c586d918c46 100644 (file)
@@ -1066,10 +1066,10 @@ static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
                                r->flags = 0;
                                continue;
                        }
-                       size += r_size;
+                       size += max(r_size, align);
                        /* Exclude ranges with size > align from
                           calculation of the alignment. */
-                       if (r_size == align)
+                       if (r_size <= align)
                                aligns[order] += align;
                        if (order > max_order)
                                max_order = order;
index 4bc589ee78d03716c708fa18d56844049e7ac433..85774b7a316aac4b8b2d49f8a448d9539cb333b1 100644 (file)
@@ -63,7 +63,7 @@ static void pci_std_update_resource(struct pci_dev *dev, int resno)
                mask = (u32)PCI_BASE_ADDRESS_IO_MASK;
                new |= res->flags & ~PCI_BASE_ADDRESS_IO_MASK;
        } else if (resno == PCI_ROM_RESOURCE) {
-               mask = (u32)PCI_ROM_ADDRESS_MASK;
+               mask = PCI_ROM_ADDRESS_MASK;
        } else {
                mask = (u32)PCI_BASE_ADDRESS_MEM_MASK;
                new |= res->flags & ~PCI_BASE_ADDRESS_MEM_MASK;
diff --git a/drivers/pci/switch/Kconfig b/drivers/pci/switch/Kconfig
new file mode 100644 (file)
index 0000000..4c49648
--- /dev/null
@@ -0,0 +1,13 @@
+menu "PCI switch controller drivers"
+       depends on PCI
+
+config PCI_SW_SWITCHTEC
+       tristate "MicroSemi Switchtec PCIe Switch Management Driver"
+       help
+        Enables support for the management interface for the MicroSemi
+        Switchtec series of PCIe switches. Supports userspace access
+        to submit MRPC commands to the switch via /dev/switchtecX
+        devices. See <file:Documentation/switchtec.txt> for more
+        information.
+
+endmenu
diff --git a/drivers/pci/switch/Makefile b/drivers/pci/switch/Makefile
new file mode 100644 (file)
index 0000000..37d8cfb
--- /dev/null
@@ -0,0 +1 @@
+obj-$(CONFIG_PCI_SW_SWITCHTEC) += switchtec.o
diff --git a/drivers/pci/switch/switchtec.c b/drivers/pci/switch/switchtec.c
new file mode 100644 (file)
index 0000000..cc6e085
--- /dev/null
@@ -0,0 +1,1600 @@
+/*
+ * Microsemi Switchtec(tm) PCIe Management Driver
+ * Copyright (c) 2017, Microsemi Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#include <linux/switchtec_ioctl.h>
+
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/poll.h>
+#include <linux/pci.h>
+#include <linux/cdev.h>
+#include <linux/wait.h>
+
+MODULE_DESCRIPTION("Microsemi Switchtec(tm) PCIe Management Driver");
+MODULE_VERSION("0.1");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Microsemi Corporation");
+
+static int max_devices = 16;
+module_param(max_devices, int, 0644);
+MODULE_PARM_DESC(max_devices, "max number of switchtec device instances");
+
+static dev_t switchtec_devt;
+static struct class *switchtec_class;
+static DEFINE_IDA(switchtec_minor_ida);
+
+#define MICROSEMI_VENDOR_ID         0x11f8
+#define MICROSEMI_NTB_CLASSCODE     0x068000
+#define MICROSEMI_MGMT_CLASSCODE    0x058000
+
+#define SWITCHTEC_MRPC_PAYLOAD_SIZE 1024
+#define SWITCHTEC_MAX_PFF_CSR 48
+
+#define SWITCHTEC_EVENT_OCCURRED BIT(0)
+#define SWITCHTEC_EVENT_CLEAR    BIT(0)
+#define SWITCHTEC_EVENT_EN_LOG   BIT(1)
+#define SWITCHTEC_EVENT_EN_CLI   BIT(2)
+#define SWITCHTEC_EVENT_EN_IRQ   BIT(3)
+#define SWITCHTEC_EVENT_FATAL    BIT(4)
+
+enum {
+       SWITCHTEC_GAS_MRPC_OFFSET       = 0x0000,
+       SWITCHTEC_GAS_TOP_CFG_OFFSET    = 0x1000,
+       SWITCHTEC_GAS_SW_EVENT_OFFSET   = 0x1800,
+       SWITCHTEC_GAS_SYS_INFO_OFFSET   = 0x2000,
+       SWITCHTEC_GAS_FLASH_INFO_OFFSET = 0x2200,
+       SWITCHTEC_GAS_PART_CFG_OFFSET   = 0x4000,
+       SWITCHTEC_GAS_NTB_OFFSET        = 0x10000,
+       SWITCHTEC_GAS_PFF_CSR_OFFSET    = 0x134000,
+};
+
+struct mrpc_regs {
+       u8 input_data[SWITCHTEC_MRPC_PAYLOAD_SIZE];
+       u8 output_data[SWITCHTEC_MRPC_PAYLOAD_SIZE];
+       u32 cmd;
+       u32 status;
+       u32 ret_value;
+} __packed;
+
+enum mrpc_status {
+       SWITCHTEC_MRPC_STATUS_INPROGRESS = 1,
+       SWITCHTEC_MRPC_STATUS_DONE = 2,
+       SWITCHTEC_MRPC_STATUS_ERROR = 0xFF,
+       SWITCHTEC_MRPC_STATUS_INTERRUPTED = 0x100,
+};
+
+struct sw_event_regs {
+       u64 event_report_ctrl;
+       u64 reserved1;
+       u64 part_event_bitmap;
+       u64 reserved2;
+       u32 global_summary;
+       u32 reserved3[3];
+       u32 stack_error_event_hdr;
+       u32 stack_error_event_data;
+       u32 reserved4[4];
+       u32 ppu_error_event_hdr;
+       u32 ppu_error_event_data;
+       u32 reserved5[4];
+       u32 isp_error_event_hdr;
+       u32 isp_error_event_data;
+       u32 reserved6[4];
+       u32 sys_reset_event_hdr;
+       u32 reserved7[5];
+       u32 fw_exception_hdr;
+       u32 reserved8[5];
+       u32 fw_nmi_hdr;
+       u32 reserved9[5];
+       u32 fw_non_fatal_hdr;
+       u32 reserved10[5];
+       u32 fw_fatal_hdr;
+       u32 reserved11[5];
+       u32 twi_mrpc_comp_hdr;
+       u32 twi_mrpc_comp_data;
+       u32 reserved12[4];
+       u32 twi_mrpc_comp_async_hdr;
+       u32 twi_mrpc_comp_async_data;
+       u32 reserved13[4];
+       u32 cli_mrpc_comp_hdr;
+       u32 cli_mrpc_comp_data;
+       u32 reserved14[4];
+       u32 cli_mrpc_comp_async_hdr;
+       u32 cli_mrpc_comp_async_data;
+       u32 reserved15[4];
+       u32 gpio_interrupt_hdr;
+       u32 gpio_interrupt_data;
+       u32 reserved16[4];
+} __packed;
+
+struct sys_info_regs {
+       u32 device_id;
+       u32 device_version;
+       u32 firmware_version;
+       u32 reserved1;
+       u32 vendor_table_revision;
+       u32 table_format_version;
+       u32 partition_id;
+       u32 cfg_file_fmt_version;
+       u32 reserved2[58];
+       char vendor_id[8];
+       char product_id[16];
+       char product_revision[4];
+       char component_vendor[8];
+       u16 component_id;
+       u8 component_revision;
+} __packed;
+
+struct flash_info_regs {
+       u32 flash_part_map_upd_idx;
+
+       struct active_partition_info {
+               u32 address;
+               u32 build_version;
+               u32 build_string;
+       } active_img;
+
+       struct active_partition_info active_cfg;
+       struct active_partition_info inactive_img;
+       struct active_partition_info inactive_cfg;
+
+       u32 flash_length;
+
+       struct partition_info {
+               u32 address;
+               u32 length;
+       } cfg0;
+
+       struct partition_info cfg1;
+       struct partition_info img0;
+       struct partition_info img1;
+       struct partition_info nvlog;
+       struct partition_info vendor[8];
+};
+
+struct ntb_info_regs {
+       u8  partition_count;
+       u8  partition_id;
+       u16 reserved1;
+       u64 ep_map;
+       u16 requester_id;
+} __packed;
+
+struct part_cfg_regs {
+       u32 status;
+       u32 state;
+       u32 port_cnt;
+       u32 usp_port_mode;
+       u32 usp_pff_inst_id;
+       u32 vep_pff_inst_id;
+       u32 dsp_pff_inst_id[47];
+       u32 reserved1[11];
+       u16 vep_vector_number;
+       u16 usp_vector_number;
+       u32 port_event_bitmap;
+       u32 reserved2[3];
+       u32 part_event_summary;
+       u32 reserved3[3];
+       u32 part_reset_hdr;
+       u32 part_reset_data[5];
+       u32 mrpc_comp_hdr;
+       u32 mrpc_comp_data[5];
+       u32 mrpc_comp_async_hdr;
+       u32 mrpc_comp_async_data[5];
+       u32 dyn_binding_hdr;
+       u32 dyn_binding_data[5];
+       u32 reserved4[159];
+} __packed;
+
+enum {
+       SWITCHTEC_PART_CFG_EVENT_RESET = 1 << 0,
+       SWITCHTEC_PART_CFG_EVENT_MRPC_CMP = 1 << 1,
+       SWITCHTEC_PART_CFG_EVENT_MRPC_ASYNC_CMP = 1 << 2,
+       SWITCHTEC_PART_CFG_EVENT_DYN_PART_CMP = 1 << 3,
+};
+
+struct pff_csr_regs {
+       u16 vendor_id;
+       u16 device_id;
+       u32 pci_cfg_header[15];
+       u32 pci_cap_region[48];
+       u32 pcie_cap_region[448];
+       u32 indirect_gas_window[128];
+       u32 indirect_gas_window_off;
+       u32 reserved[127];
+       u32 pff_event_summary;
+       u32 reserved2[3];
+       u32 aer_in_p2p_hdr;
+       u32 aer_in_p2p_data[5];
+       u32 aer_in_vep_hdr;
+       u32 aer_in_vep_data[5];
+       u32 dpc_hdr;
+       u32 dpc_data[5];
+       u32 cts_hdr;
+       u32 cts_data[5];
+       u32 reserved3[6];
+       u32 hotplug_hdr;
+       u32 hotplug_data[5];
+       u32 ier_hdr;
+       u32 ier_data[5];
+       u32 threshold_hdr;
+       u32 threshold_data[5];
+       u32 power_mgmt_hdr;
+       u32 power_mgmt_data[5];
+       u32 tlp_throttling_hdr;
+       u32 tlp_throttling_data[5];
+       u32 force_speed_hdr;
+       u32 force_speed_data[5];
+       u32 credit_timeout_hdr;
+       u32 credit_timeout_data[5];
+       u32 link_state_hdr;
+       u32 link_state_data[5];
+       u32 reserved4[174];
+} __packed;
+
+struct switchtec_dev {
+       struct pci_dev *pdev;
+       struct device dev;
+       struct cdev cdev;
+
+       int partition;
+       int partition_count;
+       int pff_csr_count;
+       char pff_local[SWITCHTEC_MAX_PFF_CSR];
+
+       void __iomem *mmio;
+       struct mrpc_regs __iomem *mmio_mrpc;
+       struct sw_event_regs __iomem *mmio_sw_event;
+       struct sys_info_regs __iomem *mmio_sys_info;
+       struct flash_info_regs __iomem *mmio_flash_info;
+       struct ntb_info_regs __iomem *mmio_ntb;
+       struct part_cfg_regs __iomem *mmio_part_cfg;
+       struct part_cfg_regs __iomem *mmio_part_cfg_all;
+       struct pff_csr_regs __iomem *mmio_pff_csr;
+
+       /*
+        * The mrpc mutex must be held when accessing the other
+        * mrpc_ fields, alive flag and stuser->state field
+        */
+       struct mutex mrpc_mutex;
+       struct list_head mrpc_queue;
+       int mrpc_busy;
+       struct work_struct mrpc_work;
+       struct delayed_work mrpc_timeout;
+       bool alive;
+
+       wait_queue_head_t event_wq;
+       atomic_t event_cnt;
+};
+
+static struct switchtec_dev *to_stdev(struct device *dev)
+{
+       return container_of(dev, struct switchtec_dev, dev);
+}
+
+enum mrpc_state {
+       MRPC_IDLE = 0,
+       MRPC_QUEUED,
+       MRPC_RUNNING,
+       MRPC_DONE,
+};
+
+struct switchtec_user {
+       struct switchtec_dev *stdev;
+
+       enum mrpc_state state;
+
+       struct completion comp;
+       struct kref kref;
+       struct list_head list;
+
+       u32 cmd;
+       u32 status;
+       u32 return_code;
+       size_t data_len;
+       size_t read_len;
+       unsigned char data[SWITCHTEC_MRPC_PAYLOAD_SIZE];
+       int event_cnt;
+};
+
+static struct switchtec_user *stuser_create(struct switchtec_dev *stdev)
+{
+       struct switchtec_user *stuser;
+
+       stuser = kzalloc(sizeof(*stuser), GFP_KERNEL);
+       if (!stuser)
+               return ERR_PTR(-ENOMEM);
+
+       get_device(&stdev->dev);
+       stuser->stdev = stdev;
+       kref_init(&stuser->kref);
+       INIT_LIST_HEAD(&stuser->list);
+       init_completion(&stuser->comp);
+       stuser->event_cnt = atomic_read(&stdev->event_cnt);
+
+       dev_dbg(&stdev->dev, "%s: %p\n", __func__, stuser);
+
+       return stuser;
+}
+
+static void stuser_free(struct kref *kref)
+{
+       struct switchtec_user *stuser;
+
+       stuser = container_of(kref, struct switchtec_user, kref);
+
+       dev_dbg(&stuser->stdev->dev, "%s: %p\n", __func__, stuser);
+
+       put_device(&stuser->stdev->dev);
+       kfree(stuser);
+}
+
+static void stuser_put(struct switchtec_user *stuser)
+{
+       kref_put(&stuser->kref, stuser_free);
+}
+
+static void stuser_set_state(struct switchtec_user *stuser,
+                            enum mrpc_state state)
+{
+       /* requires the mrpc_mutex to already be held when called */
+
+       const char * const state_names[] = {
+               [MRPC_IDLE] = "IDLE",
+               [MRPC_QUEUED] = "QUEUED",
+               [MRPC_RUNNING] = "RUNNING",
+               [MRPC_DONE] = "DONE",
+       };
+
+       stuser->state = state;
+
+       dev_dbg(&stuser->stdev->dev, "stuser state %p -> %s",
+               stuser, state_names[state]);
+}
+
+static void mrpc_complete_cmd(struct switchtec_dev *stdev);
+
+static void mrpc_cmd_submit(struct switchtec_dev *stdev)
+{
+       /* requires the mrpc_mutex to already be held when called */
+
+       struct switchtec_user *stuser;
+
+       if (stdev->mrpc_busy)
+               return;
+
+       if (list_empty(&stdev->mrpc_queue))
+               return;
+
+       stuser = list_entry(stdev->mrpc_queue.next, struct switchtec_user,
+                           list);
+
+       stuser_set_state(stuser, MRPC_RUNNING);
+       stdev->mrpc_busy = 1;
+       memcpy_toio(&stdev->mmio_mrpc->input_data,
+                   stuser->data, stuser->data_len);
+       iowrite32(stuser->cmd, &stdev->mmio_mrpc->cmd);
+
+       stuser->status = ioread32(&stdev->mmio_mrpc->status);
+       if (stuser->status != SWITCHTEC_MRPC_STATUS_INPROGRESS)
+               mrpc_complete_cmd(stdev);
+
+       schedule_delayed_work(&stdev->mrpc_timeout,
+                             msecs_to_jiffies(500));
+}
+
+static int mrpc_queue_cmd(struct switchtec_user *stuser)
+{
+       /* requires the mrpc_mutex to already be held when called */
+
+       struct switchtec_dev *stdev = stuser->stdev;
+
+       kref_get(&stuser->kref);
+       stuser->read_len = sizeof(stuser->data);
+       stuser_set_state(stuser, MRPC_QUEUED);
+       init_completion(&stuser->comp);
+       list_add_tail(&stuser->list, &stdev->mrpc_queue);
+
+       mrpc_cmd_submit(stdev);
+
+       return 0;
+}
+
+static void mrpc_complete_cmd(struct switchtec_dev *stdev)
+{
+       /* requires the mrpc_mutex to already be held when called */
+       struct switchtec_user *stuser;
+
+       if (list_empty(&stdev->mrpc_queue))
+               return;
+
+       stuser = list_entry(stdev->mrpc_queue.next, struct switchtec_user,
+                           list);
+
+       stuser->status = ioread32(&stdev->mmio_mrpc->status);
+       if (stuser->status == SWITCHTEC_MRPC_STATUS_INPROGRESS)
+               return;
+
+       stuser_set_state(stuser, MRPC_DONE);
+       stuser->return_code = 0;
+
+       if (stuser->status != SWITCHTEC_MRPC_STATUS_DONE)
+               goto out;
+
+       stuser->return_code = ioread32(&stdev->mmio_mrpc->ret_value);
+       if (stuser->return_code != 0)
+               goto out;
+
+       memcpy_fromio(stuser->data, &stdev->mmio_mrpc->output_data,
+                     stuser->read_len);
+
+out:
+       complete_all(&stuser->comp);
+       list_del_init(&stuser->list);
+       stuser_put(stuser);
+       stdev->mrpc_busy = 0;
+
+       mrpc_cmd_submit(stdev);
+}
+
+static void mrpc_event_work(struct work_struct *work)
+{
+       struct switchtec_dev *stdev;
+
+       stdev = container_of(work, struct switchtec_dev, mrpc_work);
+
+       dev_dbg(&stdev->dev, "%s\n", __func__);
+
+       mutex_lock(&stdev->mrpc_mutex);
+       cancel_delayed_work(&stdev->mrpc_timeout);
+       mrpc_complete_cmd(stdev);
+       mutex_unlock(&stdev->mrpc_mutex);
+}
+
+static void mrpc_timeout_work(struct work_struct *work)
+{
+       struct switchtec_dev *stdev;
+       u32 status;
+
+       stdev = container_of(work, struct switchtec_dev, mrpc_timeout.work);
+
+       dev_dbg(&stdev->dev, "%s\n", __func__);
+
+       mutex_lock(&stdev->mrpc_mutex);
+
+       status = ioread32(&stdev->mmio_mrpc->status);
+       if (status == SWITCHTEC_MRPC_STATUS_INPROGRESS) {
+               schedule_delayed_work(&stdev->mrpc_timeout,
+                                     msecs_to_jiffies(500));
+               goto out;
+       }
+
+       mrpc_complete_cmd(stdev);
+
+out:
+       mutex_unlock(&stdev->mrpc_mutex);
+}
+
+static ssize_t device_version_show(struct device *dev,
+       struct device_attribute *attr, char *buf)
+{
+       struct switchtec_dev *stdev = to_stdev(dev);
+       u32 ver;
+
+       ver = ioread32(&stdev->mmio_sys_info->device_version);
+
+       return sprintf(buf, "%x\n", ver);
+}
+static DEVICE_ATTR_RO(device_version);
+
+static ssize_t fw_version_show(struct device *dev,
+       struct device_attribute *attr, char *buf)
+{
+       struct switchtec_dev *stdev = to_stdev(dev);
+       u32 ver;
+
+       ver = ioread32(&stdev->mmio_sys_info->firmware_version);
+
+       return sprintf(buf, "%08x\n", ver);
+}
+static DEVICE_ATTR_RO(fw_version);
+
+static ssize_t io_string_show(char *buf, void __iomem *attr, size_t len)
+{
+       int i;
+
+       memcpy_fromio(buf, attr, len);
+       buf[len] = '\n';
+       buf[len + 1] = 0;
+
+       for (i = len - 1; i > 0; i--) {
+               if (buf[i] != ' ')
+                       break;
+               buf[i] = '\n';
+               buf[i + 1] = 0;
+       }
+
+       return strlen(buf);
+}
+
+#define DEVICE_ATTR_SYS_INFO_STR(field) \
+static ssize_t field ## _show(struct device *dev, \
+       struct device_attribute *attr, char *buf) \
+{ \
+       struct switchtec_dev *stdev = to_stdev(dev); \
+       return io_string_show(buf, &stdev->mmio_sys_info->field, \
+                           sizeof(stdev->mmio_sys_info->field)); \
+} \
+\
+static DEVICE_ATTR_RO(field)
+
+DEVICE_ATTR_SYS_INFO_STR(vendor_id);
+DEVICE_ATTR_SYS_INFO_STR(product_id);
+DEVICE_ATTR_SYS_INFO_STR(product_revision);
+DEVICE_ATTR_SYS_INFO_STR(component_vendor);
+
+static ssize_t component_id_show(struct device *dev,
+       struct device_attribute *attr, char *buf)
+{
+       struct switchtec_dev *stdev = to_stdev(dev);
+       int id = ioread16(&stdev->mmio_sys_info->component_id);
+
+       return sprintf(buf, "PM%04X\n", id);
+}
+static DEVICE_ATTR_RO(component_id);
+
+static ssize_t component_revision_show(struct device *dev,
+       struct device_attribute *attr, char *buf)
+{
+       struct switchtec_dev *stdev = to_stdev(dev);
+       int rev = ioread8(&stdev->mmio_sys_info->component_revision);
+
+       return sprintf(buf, "%d\n", rev);
+}
+static DEVICE_ATTR_RO(component_revision);
+
+static ssize_t partition_show(struct device *dev,
+       struct device_attribute *attr, char *buf)
+{
+       struct switchtec_dev *stdev = to_stdev(dev);
+
+       return sprintf(buf, "%d\n", stdev->partition);
+}
+static DEVICE_ATTR_RO(partition);
+
+static ssize_t partition_count_show(struct device *dev,
+       struct device_attribute *attr, char *buf)
+{
+       struct switchtec_dev *stdev = to_stdev(dev);
+
+       return sprintf(buf, "%d\n", stdev->partition_count);
+}
+static DEVICE_ATTR_RO(partition_count);
+
+static struct attribute *switchtec_device_attrs[] = {
+       &dev_attr_device_version.attr,
+       &dev_attr_fw_version.attr,
+       &dev_attr_vendor_id.attr,
+       &dev_attr_product_id.attr,
+       &dev_attr_product_revision.attr,
+       &dev_attr_component_vendor.attr,
+       &dev_attr_component_id.attr,
+       &dev_attr_component_revision.attr,
+       &dev_attr_partition.attr,
+       &dev_attr_partition_count.attr,
+       NULL,
+};
+
+ATTRIBUTE_GROUPS(switchtec_device);
+
+static int switchtec_dev_open(struct inode *inode, struct file *filp)
+{
+       struct switchtec_dev *stdev;
+       struct switchtec_user *stuser;
+
+       stdev = container_of(inode->i_cdev, struct switchtec_dev, cdev);
+
+       stuser = stuser_create(stdev);
+       if (IS_ERR(stuser))
+               return PTR_ERR(stuser);
+
+       filp->private_data = stuser;
+       nonseekable_open(inode, filp);
+
+       dev_dbg(&stdev->dev, "%s: %p\n", __func__, stuser);
+
+       return 0;
+}
+
+static int switchtec_dev_release(struct inode *inode, struct file *filp)
+{
+       struct switchtec_user *stuser = filp->private_data;
+
+       stuser_put(stuser);
+
+       return 0;
+}
+
+static int lock_mutex_and_test_alive(struct switchtec_dev *stdev)
+{
+       if (mutex_lock_interruptible(&stdev->mrpc_mutex))
+               return -EINTR;
+
+       if (!stdev->alive) {
+               mutex_unlock(&stdev->mrpc_mutex);
+               return -ENODEV;
+       }
+
+       return 0;
+}
+
+static ssize_t switchtec_dev_write(struct file *filp, const char __user *data,
+                                  size_t size, loff_t *off)
+{
+       struct switchtec_user *stuser = filp->private_data;
+       struct switchtec_dev *stdev = stuser->stdev;
+       int rc;
+
+       if (size < sizeof(stuser->cmd) ||
+           size > sizeof(stuser->cmd) + sizeof(stuser->data))
+               return -EINVAL;
+
+       stuser->data_len = size - sizeof(stuser->cmd);
+
+       rc = lock_mutex_and_test_alive(stdev);
+       if (rc)
+               return rc;
+
+       if (stuser->state != MRPC_IDLE) {
+               rc = -EBADE;
+               goto out;
+       }
+
+       rc = copy_from_user(&stuser->cmd, data, sizeof(stuser->cmd));
+       if (rc) {
+               rc = -EFAULT;
+               goto out;
+       }
+
+       data += sizeof(stuser->cmd);
+       rc = copy_from_user(&stuser->data, data, size - sizeof(stuser->cmd));
+       if (rc) {
+               rc = -EFAULT;
+               goto out;
+       }
+
+       rc = mrpc_queue_cmd(stuser);
+
+out:
+       mutex_unlock(&stdev->mrpc_mutex);
+
+       if (rc)
+               return rc;
+
+       return size;
+}
+
+static ssize_t switchtec_dev_read(struct file *filp, char __user *data,
+                                 size_t size, loff_t *off)
+{
+       struct switchtec_user *stuser = filp->private_data;
+       struct switchtec_dev *stdev = stuser->stdev;
+       int rc;
+
+       if (size < sizeof(stuser->cmd) ||
+           size > sizeof(stuser->cmd) + sizeof(stuser->data))
+               return -EINVAL;
+
+       rc = lock_mutex_and_test_alive(stdev);
+       if (rc)
+               return rc;
+
+       if (stuser->state == MRPC_IDLE) {
+               mutex_unlock(&stdev->mrpc_mutex);
+               return -EBADE;
+       }
+
+       stuser->read_len = size - sizeof(stuser->return_code);
+
+       mutex_unlock(&stdev->mrpc_mutex);
+
+       if (filp->f_flags & O_NONBLOCK) {
+               if (!try_wait_for_completion(&stuser->comp))
+                       return -EAGAIN;
+       } else {
+               rc = wait_for_completion_interruptible(&stuser->comp);
+               if (rc < 0)
+                       return rc;
+       }
+
+       rc = lock_mutex_and_test_alive(stdev);
+       if (rc)
+               return rc;
+
+       if (stuser->state != MRPC_DONE) {
+               mutex_unlock(&stdev->mrpc_mutex);
+               return -EBADE;
+       }
+
+       rc = copy_to_user(data, &stuser->return_code,
+                         sizeof(stuser->return_code));
+       if (rc) {
+               rc = -EFAULT;
+               goto out;
+       }
+
+       data += sizeof(stuser->return_code);
+       rc = copy_to_user(data, &stuser->data,
+                         size - sizeof(stuser->return_code));
+       if (rc) {
+               rc = -EFAULT;
+               goto out;
+       }
+
+       stuser_set_state(stuser, MRPC_IDLE);
+
+out:
+       mutex_unlock(&stdev->mrpc_mutex);
+
+       if (stuser->status == SWITCHTEC_MRPC_STATUS_DONE)
+               return size;
+       else if (stuser->status == SWITCHTEC_MRPC_STATUS_INTERRUPTED)
+               return -ENXIO;
+       else
+               return -EBADMSG;
+}
+
+static unsigned int switchtec_dev_poll(struct file *filp, poll_table *wait)
+{
+       struct switchtec_user *stuser = filp->private_data;
+       struct switchtec_dev *stdev = stuser->stdev;
+       int ret = 0;
+
+       poll_wait(filp, &stuser->comp.wait, wait);
+       poll_wait(filp, &stdev->event_wq, wait);
+
+       if (lock_mutex_and_test_alive(stdev))
+               return POLLIN | POLLRDHUP | POLLOUT | POLLERR | POLLHUP;
+
+       mutex_unlock(&stdev->mrpc_mutex);
+
+       if (try_wait_for_completion(&stuser->comp))
+               ret |= POLLIN | POLLRDNORM;
+
+       if (stuser->event_cnt != atomic_read(&stdev->event_cnt))
+               ret |= POLLPRI | POLLRDBAND;
+
+       return ret;
+}
+
+static int ioctl_flash_info(struct switchtec_dev *stdev,
+                           struct switchtec_ioctl_flash_info __user *uinfo)
+{
+       struct switchtec_ioctl_flash_info info = {0};
+       struct flash_info_regs __iomem *fi = stdev->mmio_flash_info;
+
+       info.flash_length = ioread32(&fi->flash_length);
+       info.num_partitions = SWITCHTEC_IOCTL_NUM_PARTITIONS;
+
+       if (copy_to_user(uinfo, &info, sizeof(info)))
+               return -EFAULT;
+
+       return 0;
+}
+
+static void set_fw_info_part(struct switchtec_ioctl_flash_part_info *info,
+                            struct partition_info __iomem *pi)
+{
+       info->address = ioread32(&pi->address);
+       info->length = ioread32(&pi->length);
+}
+
+static int ioctl_flash_part_info(struct switchtec_dev *stdev,
+       struct switchtec_ioctl_flash_part_info __user *uinfo)
+{
+       struct switchtec_ioctl_flash_part_info info = {0};
+       struct flash_info_regs __iomem *fi = stdev->mmio_flash_info;
+       u32 active_addr = -1;
+
+       if (copy_from_user(&info, uinfo, sizeof(info)))
+               return -EFAULT;
+
+       switch (info.flash_partition) {
+       case SWITCHTEC_IOCTL_PART_CFG0:
+               active_addr = ioread32(&fi->active_cfg);
+               set_fw_info_part(&info, &fi->cfg0);
+               break;
+       case SWITCHTEC_IOCTL_PART_CFG1:
+               active_addr = ioread32(&fi->active_cfg);
+               set_fw_info_part(&info, &fi->cfg1);
+               break;
+       case SWITCHTEC_IOCTL_PART_IMG0:
+               active_addr = ioread32(&fi->active_img);
+               set_fw_info_part(&info, &fi->img0);
+               break;
+       case SWITCHTEC_IOCTL_PART_IMG1:
+               active_addr = ioread32(&fi->active_img);
+               set_fw_info_part(&info, &fi->img1);
+               break;
+       case SWITCHTEC_IOCTL_PART_NVLOG:
+               set_fw_info_part(&info, &fi->nvlog);
+               break;
+       case SWITCHTEC_IOCTL_PART_VENDOR0:
+               set_fw_info_part(&info, &fi->vendor[0]);
+               break;
+       case SWITCHTEC_IOCTL_PART_VENDOR1:
+               set_fw_info_part(&info, &fi->vendor[1]);
+               break;
+       case SWITCHTEC_IOCTL_PART_VENDOR2:
+               set_fw_info_part(&info, &fi->vendor[2]);
+               break;
+       case SWITCHTEC_IOCTL_PART_VENDOR3:
+               set_fw_info_part(&info, &fi->vendor[3]);
+               break;
+       case SWITCHTEC_IOCTL_PART_VENDOR4:
+               set_fw_info_part(&info, &fi->vendor[4]);
+               break;
+       case SWITCHTEC_IOCTL_PART_VENDOR5:
+               set_fw_info_part(&info, &fi->vendor[5]);
+               break;
+       case SWITCHTEC_IOCTL_PART_VENDOR6:
+               set_fw_info_part(&info, &fi->vendor[6]);
+               break;
+       case SWITCHTEC_IOCTL_PART_VENDOR7:
+               set_fw_info_part(&info, &fi->vendor[7]);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       if (info.address == active_addr)
+               info.active = 1;
+
+       if (copy_to_user(uinfo, &info, sizeof(info)))
+               return -EFAULT;
+
+       return 0;
+}
+
+static int ioctl_event_summary(struct switchtec_dev *stdev,
+       struct switchtec_user *stuser,
+       struct switchtec_ioctl_event_summary __user *usum)
+{
+       struct switchtec_ioctl_event_summary s = {0};
+       int i;
+       u32 reg;
+
+       s.global = ioread32(&stdev->mmio_sw_event->global_summary);
+       s.part_bitmap = ioread32(&stdev->mmio_sw_event->part_event_bitmap);
+       s.local_part = ioread32(&stdev->mmio_part_cfg->part_event_summary);
+
+       for (i = 0; i < stdev->partition_count; i++) {
+               reg = ioread32(&stdev->mmio_part_cfg_all[i].part_event_summary);
+               s.part[i] = reg;
+       }
+
+       for (i = 0; i < SWITCHTEC_MAX_PFF_CSR; i++) {
+               reg = ioread16(&stdev->mmio_pff_csr[i].vendor_id);
+               if (reg != MICROSEMI_VENDOR_ID)
+                       break;
+
+               reg = ioread32(&stdev->mmio_pff_csr[i].pff_event_summary);
+               s.pff[i] = reg;
+       }
+
+       if (copy_to_user(usum, &s, sizeof(s)))
+               return -EFAULT;
+
+       stuser->event_cnt = atomic_read(&stdev->event_cnt);
+
+       return 0;
+}
+
+static u32 __iomem *global_ev_reg(struct switchtec_dev *stdev,
+                                 size_t offset, int index)
+{
+       return (void __iomem *)stdev->mmio_sw_event + offset;
+}
+
+static u32 __iomem *part_ev_reg(struct switchtec_dev *stdev,
+                               size_t offset, int index)
+{
+       return (void __iomem *)&stdev->mmio_part_cfg_all[index] + offset;
+}
+
+static u32 __iomem *pff_ev_reg(struct switchtec_dev *stdev,
+                              size_t offset, int index)
+{
+       return (void __iomem *)&stdev->mmio_pff_csr[index] + offset;
+}
+
+#define EV_GLB(i, r)[i] = {offsetof(struct sw_event_regs, r), global_ev_reg}
+#define EV_PAR(i, r)[i] = {offsetof(struct part_cfg_regs, r), part_ev_reg}
+#define EV_PFF(i, r)[i] = {offsetof(struct pff_csr_regs, r), pff_ev_reg}
+
+const struct event_reg {
+       size_t offset;
+       u32 __iomem *(*map_reg)(struct switchtec_dev *stdev,
+                               size_t offset, int index);
+} event_regs[] = {
+       EV_GLB(SWITCHTEC_IOCTL_EVENT_STACK_ERROR, stack_error_event_hdr),
+       EV_GLB(SWITCHTEC_IOCTL_EVENT_PPU_ERROR, ppu_error_event_hdr),
+       EV_GLB(SWITCHTEC_IOCTL_EVENT_ISP_ERROR, isp_error_event_hdr),
+       EV_GLB(SWITCHTEC_IOCTL_EVENT_SYS_RESET, sys_reset_event_hdr),
+       EV_GLB(SWITCHTEC_IOCTL_EVENT_FW_EXC, fw_exception_hdr),
+       EV_GLB(SWITCHTEC_IOCTL_EVENT_FW_NMI, fw_nmi_hdr),
+       EV_GLB(SWITCHTEC_IOCTL_EVENT_FW_NON_FATAL, fw_non_fatal_hdr),
+       EV_GLB(SWITCHTEC_IOCTL_EVENT_FW_FATAL, fw_fatal_hdr),
+       EV_GLB(SWITCHTEC_IOCTL_EVENT_TWI_MRPC_COMP, twi_mrpc_comp_hdr),
+       EV_GLB(SWITCHTEC_IOCTL_EVENT_TWI_MRPC_COMP_ASYNC,
+              twi_mrpc_comp_async_hdr),
+       EV_GLB(SWITCHTEC_IOCTL_EVENT_CLI_MRPC_COMP, cli_mrpc_comp_hdr),
+       EV_GLB(SWITCHTEC_IOCTL_EVENT_CLI_MRPC_COMP_ASYNC,
+              cli_mrpc_comp_async_hdr),
+       EV_GLB(SWITCHTEC_IOCTL_EVENT_GPIO_INT, gpio_interrupt_hdr),
+       EV_PAR(SWITCHTEC_IOCTL_EVENT_PART_RESET, part_reset_hdr),
+       EV_PAR(SWITCHTEC_IOCTL_EVENT_MRPC_COMP, mrpc_comp_hdr),
+       EV_PAR(SWITCHTEC_IOCTL_EVENT_MRPC_COMP_ASYNC, mrpc_comp_async_hdr),
+       EV_PAR(SWITCHTEC_IOCTL_EVENT_DYN_PART_BIND_COMP, dyn_binding_hdr),
+       EV_PFF(SWITCHTEC_IOCTL_EVENT_AER_IN_P2P, aer_in_p2p_hdr),
+       EV_PFF(SWITCHTEC_IOCTL_EVENT_AER_IN_VEP, aer_in_vep_hdr),
+       EV_PFF(SWITCHTEC_IOCTL_EVENT_DPC, dpc_hdr),
+       EV_PFF(SWITCHTEC_IOCTL_EVENT_CTS, cts_hdr),
+       EV_PFF(SWITCHTEC_IOCTL_EVENT_HOTPLUG, hotplug_hdr),
+       EV_PFF(SWITCHTEC_IOCTL_EVENT_IER, ier_hdr),
+       EV_PFF(SWITCHTEC_IOCTL_EVENT_THRESH, threshold_hdr),
+       EV_PFF(SWITCHTEC_IOCTL_EVENT_POWER_MGMT, power_mgmt_hdr),
+       EV_PFF(SWITCHTEC_IOCTL_EVENT_TLP_THROTTLING, tlp_throttling_hdr),
+       EV_PFF(SWITCHTEC_IOCTL_EVENT_FORCE_SPEED, force_speed_hdr),
+       EV_PFF(SWITCHTEC_IOCTL_EVENT_CREDIT_TIMEOUT, credit_timeout_hdr),
+       EV_PFF(SWITCHTEC_IOCTL_EVENT_LINK_STATE, link_state_hdr),
+};
+
+static u32 __iomem *event_hdr_addr(struct switchtec_dev *stdev,
+                                  int event_id, int index)
+{
+       size_t off;
+
+       if (event_id < 0 || event_id >= SWITCHTEC_IOCTL_MAX_EVENTS)
+               return ERR_PTR(-EINVAL);
+
+       off = event_regs[event_id].offset;
+
+       if (event_regs[event_id].map_reg == part_ev_reg) {
+               if (index == SWITCHTEC_IOCTL_EVENT_LOCAL_PART_IDX)
+                       index = stdev->partition;
+               else if (index < 0 || index >= stdev->partition_count)
+                       return ERR_PTR(-EINVAL);
+       } else if (event_regs[event_id].map_reg == pff_ev_reg) {
+               if (index < 0 || index >= stdev->pff_csr_count)
+                       return ERR_PTR(-EINVAL);
+       }
+
+       return event_regs[event_id].map_reg(stdev, off, index);
+}
+
+static int event_ctl(struct switchtec_dev *stdev,
+                    struct switchtec_ioctl_event_ctl *ctl)
+{
+       int i;
+       u32 __iomem *reg;
+       u32 hdr;
+
+       reg = event_hdr_addr(stdev, ctl->event_id, ctl->index);
+       if (IS_ERR(reg))
+               return PTR_ERR(reg);
+
+       hdr = ioread32(reg);
+       for (i = 0; i < ARRAY_SIZE(ctl->data); i++)
+               ctl->data[i] = ioread32(&reg[i + 1]);
+
+       ctl->occurred = hdr & SWITCHTEC_EVENT_OCCURRED;
+       ctl->count = (hdr >> 5) & 0xFF;
+
+       if (!(ctl->flags & SWITCHTEC_IOCTL_EVENT_FLAG_CLEAR))
+               hdr &= ~SWITCHTEC_EVENT_CLEAR;
+       if (ctl->flags & SWITCHTEC_IOCTL_EVENT_FLAG_EN_POLL)
+               hdr |= SWITCHTEC_EVENT_EN_IRQ;
+       if (ctl->flags & SWITCHTEC_IOCTL_EVENT_FLAG_DIS_POLL)
+               hdr &= ~SWITCHTEC_EVENT_EN_IRQ;
+       if (ctl->flags & SWITCHTEC_IOCTL_EVENT_FLAG_EN_LOG)
+               hdr |= SWITCHTEC_EVENT_EN_LOG;
+       if (ctl->flags & SWITCHTEC_IOCTL_EVENT_FLAG_DIS_LOG)
+               hdr &= ~SWITCHTEC_EVENT_EN_LOG;
+       if (ctl->flags & SWITCHTEC_IOCTL_EVENT_FLAG_EN_CLI)
+               hdr |= SWITCHTEC_EVENT_EN_CLI;
+       if (ctl->flags & SWITCHTEC_IOCTL_EVENT_FLAG_DIS_CLI)
+               hdr &= ~SWITCHTEC_EVENT_EN_CLI;
+       if (ctl->flags & SWITCHTEC_IOCTL_EVENT_FLAG_EN_FATAL)
+               hdr |= SWITCHTEC_EVENT_FATAL;
+       if (ctl->flags & SWITCHTEC_IOCTL_EVENT_FLAG_DIS_FATAL)
+               hdr &= ~SWITCHTEC_EVENT_FATAL;
+
+       if (ctl->flags)
+               iowrite32(hdr, reg);
+
+       ctl->flags = 0;
+       if (hdr & SWITCHTEC_EVENT_EN_IRQ)
+               ctl->flags |= SWITCHTEC_IOCTL_EVENT_FLAG_EN_POLL;
+       if (hdr & SWITCHTEC_EVENT_EN_LOG)
+               ctl->flags |= SWITCHTEC_IOCTL_EVENT_FLAG_EN_LOG;
+       if (hdr & SWITCHTEC_EVENT_EN_CLI)
+               ctl->flags |= SWITCHTEC_IOCTL_EVENT_FLAG_EN_CLI;
+       if (hdr & SWITCHTEC_EVENT_FATAL)
+               ctl->flags |= SWITCHTEC_IOCTL_EVENT_FLAG_EN_FATAL;
+
+       return 0;
+}
+
+static int ioctl_event_ctl(struct switchtec_dev *stdev,
+       struct switchtec_ioctl_event_ctl __user *uctl)
+{
+       int ret;
+       int nr_idxs;
+       struct switchtec_ioctl_event_ctl ctl;
+
+       if (copy_from_user(&ctl, uctl, sizeof(ctl)))
+               return -EFAULT;
+
+       if (ctl.event_id >= SWITCHTEC_IOCTL_MAX_EVENTS)
+               return -EINVAL;
+
+       if (ctl.flags & SWITCHTEC_IOCTL_EVENT_FLAG_UNUSED)
+               return -EINVAL;
+
+       if (ctl.index == SWITCHTEC_IOCTL_EVENT_IDX_ALL) {
+               if (event_regs[ctl.event_id].map_reg == global_ev_reg)
+                       nr_idxs = 1;
+               else if (event_regs[ctl.event_id].map_reg == part_ev_reg)
+                       nr_idxs = stdev->partition_count;
+               else if (event_regs[ctl.event_id].map_reg == pff_ev_reg)
+                       nr_idxs = stdev->pff_csr_count;
+               else
+                       return -EINVAL;
+
+               for (ctl.index = 0; ctl.index < nr_idxs; ctl.index++) {
+                       ret = event_ctl(stdev, &ctl);
+                       if (ret < 0)
+                               return ret;
+               }
+       } else {
+               ret = event_ctl(stdev, &ctl);
+               if (ret < 0)
+                       return ret;
+       }
+
+       if (copy_to_user(uctl, &ctl, sizeof(ctl)))
+               return -EFAULT;
+
+       return 0;
+}
+
+static int ioctl_pff_to_port(struct switchtec_dev *stdev,
+                            struct switchtec_ioctl_pff_port *up)
+{
+       int i, part;
+       u32 reg;
+       struct part_cfg_regs *pcfg;
+       struct switchtec_ioctl_pff_port p;
+
+       if (copy_from_user(&p, up, sizeof(p)))
+               return -EFAULT;
+
+       p.port = -1;
+       for (part = 0; part < stdev->partition_count; part++) {
+               pcfg = &stdev->mmio_part_cfg_all[part];
+               p.partition = part;
+
+               reg = ioread32(&pcfg->usp_pff_inst_id);
+               if (reg == p.pff) {
+                       p.port = 0;
+                       break;
+               }
+
+               reg = ioread32(&pcfg->vep_pff_inst_id);
+               if (reg == p.pff) {
+                       p.port = SWITCHTEC_IOCTL_PFF_VEP;
+                       break;
+               }
+
+               for (i = 0; i < ARRAY_SIZE(pcfg->dsp_pff_inst_id); i++) {
+                       reg = ioread32(&pcfg->dsp_pff_inst_id[i]);
+                       if (reg != p.pff)
+                               continue;
+
+                       p.port = i + 1;
+                       break;
+               }
+
+               if (p.port != -1)
+                       break;
+       }
+
+       if (copy_to_user(up, &p, sizeof(p)))
+               return -EFAULT;
+
+       return 0;
+}
+
+static int ioctl_port_to_pff(struct switchtec_dev *stdev,
+                            struct switchtec_ioctl_pff_port *up)
+{
+       struct switchtec_ioctl_pff_port p;
+       struct part_cfg_regs *pcfg;
+
+       if (copy_from_user(&p, up, sizeof(p)))
+               return -EFAULT;
+
+       if (p.partition == SWITCHTEC_IOCTL_EVENT_LOCAL_PART_IDX)
+               pcfg = stdev->mmio_part_cfg;
+       else if (p.partition < stdev->partition_count)
+               pcfg = &stdev->mmio_part_cfg_all[p.partition];
+       else
+               return -EINVAL;
+
+       switch (p.port) {
+       case 0:
+               p.pff = ioread32(&pcfg->usp_pff_inst_id);
+               break;
+       case SWITCHTEC_IOCTL_PFF_VEP:
+               p.pff = ioread32(&pcfg->vep_pff_inst_id);
+               break;
+       default:
+               if (p.port > ARRAY_SIZE(pcfg->dsp_pff_inst_id))
+                       return -EINVAL;
+               p.pff = ioread32(&pcfg->dsp_pff_inst_id[p.port - 1]);
+               break;
+       }
+
+       if (copy_to_user(up, &p, sizeof(p)))
+               return -EFAULT;
+
+       return 0;
+}
+
+static long switchtec_dev_ioctl(struct file *filp, unsigned int cmd,
+                               unsigned long arg)
+{
+       struct switchtec_user *stuser = filp->private_data;
+       struct switchtec_dev *stdev = stuser->stdev;
+       int rc;
+       void __user *argp = (void __user *)arg;
+
+       rc = lock_mutex_and_test_alive(stdev);
+       if (rc)
+               return rc;
+
+       switch (cmd) {
+       case SWITCHTEC_IOCTL_FLASH_INFO:
+               rc = ioctl_flash_info(stdev, argp);
+               break;
+       case SWITCHTEC_IOCTL_FLASH_PART_INFO:
+               rc = ioctl_flash_part_info(stdev, argp);
+               break;
+       case SWITCHTEC_IOCTL_EVENT_SUMMARY:
+               rc = ioctl_event_summary(stdev, stuser, argp);
+               break;
+       case SWITCHTEC_IOCTL_EVENT_CTL:
+               rc = ioctl_event_ctl(stdev, argp);
+               break;
+       case SWITCHTEC_IOCTL_PFF_TO_PORT:
+               rc = ioctl_pff_to_port(stdev, argp);
+               break;
+       case SWITCHTEC_IOCTL_PORT_TO_PFF:
+               rc = ioctl_port_to_pff(stdev, argp);
+               break;
+       default:
+               rc = -ENOTTY;
+               break;
+       }
+
+       mutex_unlock(&stdev->mrpc_mutex);
+       return rc;
+}
+
+static const struct file_operations switchtec_fops = {
+       .owner = THIS_MODULE,
+       .open = switchtec_dev_open,
+       .release = switchtec_dev_release,
+       .write = switchtec_dev_write,
+       .read = switchtec_dev_read,
+       .poll = switchtec_dev_poll,
+       .unlocked_ioctl = switchtec_dev_ioctl,
+       .compat_ioctl = switchtec_dev_ioctl,
+};
+
+static void stdev_release(struct device *dev)
+{
+       struct switchtec_dev *stdev = to_stdev(dev);
+
+       kfree(stdev);
+}
+
+static void stdev_kill(struct switchtec_dev *stdev)
+{
+       struct switchtec_user *stuser, *tmpuser;
+
+       pci_clear_master(stdev->pdev);
+
+       cancel_delayed_work_sync(&stdev->mrpc_timeout);
+
+       /* Mark the hardware as unavailable and complete all completions */
+       mutex_lock(&stdev->mrpc_mutex);
+       stdev->alive = false;
+
+       /* Wake up and kill any users waiting on an MRPC request */
+       list_for_each_entry_safe(stuser, tmpuser, &stdev->mrpc_queue, list) {
+               complete_all(&stuser->comp);
+               list_del_init(&stuser->list);
+               stuser_put(stuser);
+       }
+
+       mutex_unlock(&stdev->mrpc_mutex);
+
+       /* Wake up any users waiting on event_wq */
+       wake_up_interruptible(&stdev->event_wq);
+}
+
+static struct switchtec_dev *stdev_create(struct pci_dev *pdev)
+{
+       struct switchtec_dev *stdev;
+       int minor;
+       struct device *dev;
+       struct cdev *cdev;
+       int rc;
+
+       stdev = kzalloc_node(sizeof(*stdev), GFP_KERNEL,
+                            dev_to_node(&pdev->dev));
+       if (!stdev)
+               return ERR_PTR(-ENOMEM);
+
+       stdev->alive = true;
+       stdev->pdev = pdev;
+       INIT_LIST_HEAD(&stdev->mrpc_queue);
+       mutex_init(&stdev->mrpc_mutex);
+       stdev->mrpc_busy = 0;
+       INIT_WORK(&stdev->mrpc_work, mrpc_event_work);
+       INIT_DELAYED_WORK(&stdev->mrpc_timeout, mrpc_timeout_work);
+       init_waitqueue_head(&stdev->event_wq);
+       atomic_set(&stdev->event_cnt, 0);
+
+       dev = &stdev->dev;
+       device_initialize(dev);
+       dev->class = switchtec_class;
+       dev->parent = &pdev->dev;
+       dev->groups = switchtec_device_groups;
+       dev->release = stdev_release;
+
+       minor = ida_simple_get(&switchtec_minor_ida, 0, 0,
+                              GFP_KERNEL);
+       if (minor < 0) {
+               rc = minor;
+               goto err_put;
+       }
+
+       dev->devt = MKDEV(MAJOR(switchtec_devt), minor);
+       dev_set_name(dev, "switchtec%d", minor);
+
+       cdev = &stdev->cdev;
+       cdev_init(cdev, &switchtec_fops);
+       cdev->owner = THIS_MODULE;
+       cdev->kobj.parent = &dev->kobj;
+
+       return stdev;
+
+err_put:
+       put_device(&stdev->dev);
+       return ERR_PTR(rc);
+}
+
+static int mask_event(struct switchtec_dev *stdev, int eid, int idx)
+{
+       size_t off = event_regs[eid].offset;
+       u32 __iomem *hdr_reg;
+       u32 hdr;
+
+       hdr_reg = event_regs[eid].map_reg(stdev, off, idx);
+       hdr = ioread32(hdr_reg);
+
+       if (!(hdr & SWITCHTEC_EVENT_OCCURRED && hdr & SWITCHTEC_EVENT_EN_IRQ))
+               return 0;
+
+       dev_dbg(&stdev->dev, "%s: %d %d %x\n", __func__, eid, idx, hdr);
+       hdr &= ~(SWITCHTEC_EVENT_EN_IRQ | SWITCHTEC_EVENT_OCCURRED);
+       iowrite32(hdr, hdr_reg);
+
+       return 1;
+}
+
+static int mask_all_events(struct switchtec_dev *stdev, int eid)
+{
+       int idx;
+       int count = 0;
+
+       if (event_regs[eid].map_reg == part_ev_reg) {
+               for (idx = 0; idx < stdev->partition_count; idx++)
+                       count += mask_event(stdev, eid, idx);
+       } else if (event_regs[eid].map_reg == pff_ev_reg) {
+               for (idx = 0; idx < stdev->pff_csr_count; idx++) {
+                       if (!stdev->pff_local[idx])
+                               continue;
+                       count += mask_event(stdev, eid, idx);
+               }
+       } else {
+               count += mask_event(stdev, eid, 0);
+       }
+
+       return count;
+}
+
+static irqreturn_t switchtec_event_isr(int irq, void *dev)
+{
+       struct switchtec_dev *stdev = dev;
+       u32 reg;
+       irqreturn_t ret = IRQ_NONE;
+       int eid, event_count = 0;
+
+       reg = ioread32(&stdev->mmio_part_cfg->mrpc_comp_hdr);
+       if (reg & SWITCHTEC_EVENT_OCCURRED) {
+               dev_dbg(&stdev->dev, "%s: mrpc comp\n", __func__);
+               ret = IRQ_HANDLED;
+               schedule_work(&stdev->mrpc_work);
+               iowrite32(reg, &stdev->mmio_part_cfg->mrpc_comp_hdr);
+       }
+
+       for (eid = 0; eid < SWITCHTEC_IOCTL_MAX_EVENTS; eid++)
+               event_count += mask_all_events(stdev, eid);
+
+       if (event_count) {
+               atomic_inc(&stdev->event_cnt);
+               wake_up_interruptible(&stdev->event_wq);
+               dev_dbg(&stdev->dev, "%s: %d events\n", __func__,
+                       event_count);
+               return IRQ_HANDLED;
+       }
+
+       return ret;
+}
+
+static int switchtec_init_isr(struct switchtec_dev *stdev)
+{
+       int nvecs;
+       int event_irq;
+
+       nvecs = pci_alloc_irq_vectors(stdev->pdev, 1, 4,
+                                     PCI_IRQ_MSIX | PCI_IRQ_MSI);
+       if (nvecs < 0)
+               return nvecs;
+
+       event_irq = ioread32(&stdev->mmio_part_cfg->vep_vector_number);
+       if (event_irq < 0 || event_irq >= nvecs)
+               return -EFAULT;
+
+       event_irq = pci_irq_vector(stdev->pdev, event_irq);
+       if (event_irq < 0)
+               return event_irq;
+
+       return devm_request_irq(&stdev->pdev->dev, event_irq,
+                               switchtec_event_isr, 0,
+                               KBUILD_MODNAME, stdev);
+}
+
+static void init_pff(struct switchtec_dev *stdev)
+{
+       int i;
+       u32 reg;
+       struct part_cfg_regs *pcfg = stdev->mmio_part_cfg;
+
+       for (i = 0; i < SWITCHTEC_MAX_PFF_CSR; i++) {
+               reg = ioread16(&stdev->mmio_pff_csr[i].vendor_id);
+               if (reg != MICROSEMI_VENDOR_ID)
+                       break;
+       }
+
+       stdev->pff_csr_count = i;
+
+       reg = ioread32(&pcfg->usp_pff_inst_id);
+       if (reg < SWITCHTEC_MAX_PFF_CSR)
+               stdev->pff_local[reg] = 1;
+
+       reg = ioread32(&pcfg->vep_pff_inst_id);
+       if (reg < SWITCHTEC_MAX_PFF_CSR)
+               stdev->pff_local[reg] = 1;
+
+       for (i = 0; i < ARRAY_SIZE(pcfg->dsp_pff_inst_id); i++) {
+               reg = ioread32(&pcfg->dsp_pff_inst_id[i]);
+               if (reg < SWITCHTEC_MAX_PFF_CSR)
+                       stdev->pff_local[reg] = 1;
+       }
+}
+
+static int switchtec_init_pci(struct switchtec_dev *stdev,
+                             struct pci_dev *pdev)
+{
+       int rc;
+
+       rc = pcim_enable_device(pdev);
+       if (rc)
+               return rc;
+
+       rc = pcim_iomap_regions(pdev, 0x1, KBUILD_MODNAME);
+       if (rc)
+               return rc;
+
+       pci_set_master(pdev);
+
+       stdev->mmio = pcim_iomap_table(pdev)[0];
+       stdev->mmio_mrpc = stdev->mmio + SWITCHTEC_GAS_MRPC_OFFSET;
+       stdev->mmio_sw_event = stdev->mmio + SWITCHTEC_GAS_SW_EVENT_OFFSET;
+       stdev->mmio_sys_info = stdev->mmio + SWITCHTEC_GAS_SYS_INFO_OFFSET;
+       stdev->mmio_flash_info = stdev->mmio + SWITCHTEC_GAS_FLASH_INFO_OFFSET;
+       stdev->mmio_ntb = stdev->mmio + SWITCHTEC_GAS_NTB_OFFSET;
+       stdev->partition = ioread8(&stdev->mmio_ntb->partition_id);
+       stdev->partition_count = ioread8(&stdev->mmio_ntb->partition_count);
+       stdev->mmio_part_cfg_all = stdev->mmio + SWITCHTEC_GAS_PART_CFG_OFFSET;
+       stdev->mmio_part_cfg = &stdev->mmio_part_cfg_all[stdev->partition];
+       stdev->mmio_pff_csr = stdev->mmio + SWITCHTEC_GAS_PFF_CSR_OFFSET;
+
+       init_pff(stdev);
+
+       pci_set_drvdata(pdev, stdev);
+
+       return 0;
+}
+
+static int switchtec_pci_probe(struct pci_dev *pdev,
+                              const struct pci_device_id *id)
+{
+       struct switchtec_dev *stdev;
+       int rc;
+
+       stdev = stdev_create(pdev);
+       if (IS_ERR(stdev))
+               return PTR_ERR(stdev);
+
+       rc = switchtec_init_pci(stdev, pdev);
+       if (rc)
+               goto err_put;
+
+       rc = switchtec_init_isr(stdev);
+       if (rc) {
+               dev_err(&stdev->dev, "failed to init isr.\n");
+               goto err_put;
+       }
+
+       iowrite32(SWITCHTEC_EVENT_CLEAR |
+                 SWITCHTEC_EVENT_EN_IRQ,
+                 &stdev->mmio_part_cfg->mrpc_comp_hdr);
+
+       rc = cdev_add(&stdev->cdev, stdev->dev.devt, 1);
+       if (rc)
+               goto err_put;
+
+       rc = device_add(&stdev->dev);
+       if (rc)
+               goto err_devadd;
+
+       dev_info(&stdev->dev, "Management device registered.\n");
+
+       return 0;
+
+err_devadd:
+       cdev_del(&stdev->cdev);
+       stdev_kill(stdev);
+err_put:
+       ida_simple_remove(&switchtec_minor_ida, MINOR(stdev->dev.devt));
+       put_device(&stdev->dev);
+       return rc;
+}
+
+static void switchtec_pci_remove(struct pci_dev *pdev)
+{
+       struct switchtec_dev *stdev = pci_get_drvdata(pdev);
+
+       pci_set_drvdata(pdev, NULL);
+
+       device_del(&stdev->dev);
+       cdev_del(&stdev->cdev);
+       ida_simple_remove(&switchtec_minor_ida, MINOR(stdev->dev.devt));
+       dev_info(&stdev->dev, "unregistered.\n");
+
+       stdev_kill(stdev);
+       put_device(&stdev->dev);
+}
+
+#define SWITCHTEC_PCI_DEVICE(device_id) \
+       { \
+               .vendor     = MICROSEMI_VENDOR_ID, \
+               .device     = device_id, \
+               .subvendor  = PCI_ANY_ID, \
+               .subdevice  = PCI_ANY_ID, \
+               .class      = MICROSEMI_MGMT_CLASSCODE, \
+               .class_mask = 0xFFFFFFFF, \
+       }, \
+       { \
+               .vendor     = MICROSEMI_VENDOR_ID, \
+               .device     = device_id, \
+               .subvendor  = PCI_ANY_ID, \
+               .subdevice  = PCI_ANY_ID, \
+               .class      = MICROSEMI_NTB_CLASSCODE, \
+               .class_mask = 0xFFFFFFFF, \
+       }
+
+static const struct pci_device_id switchtec_pci_tbl[] = {
+       SWITCHTEC_PCI_DEVICE(0x8531),  //PFX 24xG3
+       SWITCHTEC_PCI_DEVICE(0x8532),  //PFX 32xG3
+       SWITCHTEC_PCI_DEVICE(0x8533),  //PFX 48xG3
+       SWITCHTEC_PCI_DEVICE(0x8534),  //PFX 64xG3
+       SWITCHTEC_PCI_DEVICE(0x8535),  //PFX 80xG3
+       SWITCHTEC_PCI_DEVICE(0x8536),  //PFX 96xG3
+       SWITCHTEC_PCI_DEVICE(0x8543),  //PSX 48xG3
+       SWITCHTEC_PCI_DEVICE(0x8544),  //PSX 64xG3
+       SWITCHTEC_PCI_DEVICE(0x8545),  //PSX 80xG3
+       SWITCHTEC_PCI_DEVICE(0x8546),  //PSX 96xG3
+       {0}
+};
+MODULE_DEVICE_TABLE(pci, switchtec_pci_tbl);
+
+static struct pci_driver switchtec_pci_driver = {
+       .name           = KBUILD_MODNAME,
+       .id_table       = switchtec_pci_tbl,
+       .probe          = switchtec_pci_probe,
+       .remove         = switchtec_pci_remove,
+};
+
+static int __init switchtec_init(void)
+{
+       int rc;
+
+       rc = alloc_chrdev_region(&switchtec_devt, 0, max_devices,
+                                "switchtec");
+       if (rc)
+               return rc;
+
+       switchtec_class = class_create(THIS_MODULE, "switchtec");
+       if (IS_ERR(switchtec_class)) {
+               rc = PTR_ERR(switchtec_class);
+               goto err_create_class;
+       }
+
+       rc = pci_register_driver(&switchtec_pci_driver);
+       if (rc)
+               goto err_pci_register;
+
+       pr_info(KBUILD_MODNAME ": loaded.\n");
+
+       return 0;
+
+err_pci_register:
+       class_destroy(switchtec_class);
+
+err_create_class:
+       unregister_chrdev_region(switchtec_devt, max_devices);
+
+       return rc;
+}
+module_init(switchtec_init);
+
+static void __exit switchtec_exit(void)
+{
+       pci_unregister_driver(&switchtec_pci_driver);
+       class_destroy(switchtec_class);
+       unregister_chrdev_region(switchtec_devt, max_devices);
+       ida_destroy(&switchtec_minor_ida);
+
+       pr_info(KBUILD_MODNAME ": unloaded.\n");
+}
+module_exit(switchtec_exit);
index eb0d80a429e468ce81c7ffd9d4cb481985c08e07..fb38cc01859f15ac3519e8310391bde330033156 100644 (file)
@@ -108,12 +108,12 @@ static int async_clock = -1;
 static int cable_mode = -1;
 static int wakeup = 0;
 
-module_param(i365_base, ulong, 0444);
+module_param_hw(i365_base, ulong, ioport, 0444);
 module_param(ignore, int, 0444);
 module_param(extra_sockets, int, 0444);
-module_param(irq_mask, int, 0444);
-module_param_array(irq_list, int, &irq_list_count, 0444);
-module_param(cs_irq, int, 0444);
+module_param_hw(irq_mask, int, other, 0444);
+module_param_hw_array(irq_list, int, irq, &irq_list_count, 0444);
+module_param_hw(cs_irq, int, irq, 0444);
 module_param(async_clock, int, 0444);
 module_param(cable_mode, int, 0444);
 module_param(wakeup, int, 0444);
index 1ee63e5f0550329e9b8adbd9e34c9c03e0e3a088..a1ac72d51d707d816a15130cccdb45549424e098 100644 (file)
@@ -85,12 +85,12 @@ static int poll_quick = HZ/20;
 /* CCLK external clock time, in nanoseconds.  70 ns = 14.31818 MHz */
 static int cycle_time = 70;
 
-module_param(tcic_base, ulong, 0444);
+module_param_hw(tcic_base, ulong, ioport, 0444);
 module_param(ignore, int, 0444);
 module_param(do_scan, int, 0444);
-module_param(irq_mask, int, 0444);
-module_param_array(irq_list, int, &irq_list_count, 0444);
-module_param(cs_irq, int, 0444);
+module_param_hw(irq_mask, int, other, 0444);
+module_param_hw_array(irq_list, int, irq, &irq_list_count, 0444);
+module_param_hw(cs_irq, int, irq, 0444);
 module_param(poll_interval, int, 0444);
 module_param(poll_quick, int, 0444);
 module_param(cycle_time, int, 0444);
index da922756149fd7e2490f3e786e27f02f6d68dde4..86f40bf37c349d55b4899a4ff0edb9d11bf17542 100644 (file)
@@ -238,6 +238,26 @@ config CHARGER_AXP20X
          This driver can also be built as a module. If so, the module will be
          called axp20x_ac_power.
 
+config BATTERY_AXP20X
+       tristate "X-Powers AXP20X battery driver"
+       depends on MFD_AXP20X
+       depends on AXP20X_ADC
+       depends on IIO
+       help
+         Say Y here to enable support for X-Powers AXP20X PMICs' battery power
+         supply.
+
+         This driver can also be built as a module. If so, the module will be
+         called axp20x_battery.
+
+config AXP20X_POWER
+       tristate "AXP20x power supply driver"
+       depends on MFD_AXP20X
+       depends on IIO
+       help
+         This driver provides support for the power supply features of
+         AXP20x PMIC.
+
 config AXP288_CHARGER
        tristate "X-Powers AXP288 Charger"
        depends on MFD_AXP20X && EXTCON_AXP288
@@ -541,11 +561,4 @@ config CHARGER_RT9455
        help
          Say Y to enable support for Richtek RT9455 battery charger.
 
-config AXP20X_POWER
-       tristate "AXP20x power supply driver"
-       depends on MFD_AXP20X
-       help
-         This driver provides support for the power supply features of
-         AXP20x PMIC.
-
 endif # POWER_SUPPLY
index 39fc733e6cc4dc2dc7fde75f3525ed3c2aebeacd..a39126d7a6ce0364840d625c66d2c0508e7dceaf 100644 (file)
@@ -18,6 +18,7 @@ obj-$(CONFIG_TEST_POWER)      += test_power.o
 
 obj-$(CONFIG_BATTERY_88PM860X) += 88pm860x_battery.o
 obj-$(CONFIG_BATTERY_ACT8945A) += act8945a_charger.o
+obj-$(CONFIG_BATTERY_AXP20X)   += axp20x_battery.o
 obj-$(CONFIG_CHARGER_AXP20X)   += axp20x_ac_power.o
 obj-$(CONFIG_BATTERY_DS2760)   += ds2760_battery.o
 obj-$(CONFIG_BATTERY_DS2780)   += ds2780_battery.o
index 5cee9aa87aa338b3e310c136317850e47e62d9cd..4ebbcce45c48407a69ae10d177a786d7f7d52ec7 100644 (file)
@@ -3238,7 +3238,7 @@ static int ab8500_charger_init_hw_registers(struct ab8500_charger *di)
                        BUS_PP_PRECHG_CURRENT_MASK, 0);
                if (ret) {
                        dev_err(di->dev,
-                               "failed to setup usb power path prechage current\n");
+                               "failed to setup usb power path precharge current\n");
                        goto out;
                }
        }
diff --git a/drivers/power/supply/axp20x_battery.c b/drivers/power/supply/axp20x_battery.c
new file mode 100644 (file)
index 0000000..5d29b2e
--- /dev/null
@@ -0,0 +1,502 @@
+/*
+ * Battery power supply driver for X-Powers AXP20X and AXP22X PMICs
+ *
+ * Copyright 2016 Free Electrons NextThing Co.
+ *     Quentin Schulz <quentin.schulz@free-electrons.com>
+ *
+ * This driver is based on a previous upstreaming attempt by:
+ *     Bruno Prémont <bonbons@linux-vserver.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file "COPYING" in the main directory of this
+ * archive for more details.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/time.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/consumer.h>
+#include <linux/mfd/axp20x.h>
+
+#define AXP20X_PWR_STATUS_BAT_CHARGING BIT(2)
+
+#define AXP20X_PWR_OP_BATT_PRESENT     BIT(5)
+#define AXP20X_PWR_OP_BATT_ACTIVATED   BIT(3)
+
+#define AXP209_FG_PERCENT              GENMASK(6, 0)
+#define AXP22X_FG_VALID                        BIT(7)
+
+#define AXP20X_CHRG_CTRL1_TGT_VOLT     GENMASK(6, 5)
+#define AXP20X_CHRG_CTRL1_TGT_4_1V     (0 << 5)
+#define AXP20X_CHRG_CTRL1_TGT_4_15V    (1 << 5)
+#define AXP20X_CHRG_CTRL1_TGT_4_2V     (2 << 5)
+#define AXP20X_CHRG_CTRL1_TGT_4_36V    (3 << 5)
+
+#define AXP22X_CHRG_CTRL1_TGT_4_22V    (1 << 5)
+#define AXP22X_CHRG_CTRL1_TGT_4_24V    (3 << 5)
+
+#define AXP20X_CHRG_CTRL1_TGT_CURR     GENMASK(3, 0)
+
+#define AXP20X_V_OFF_MASK              GENMASK(2, 0)
+
+struct axp20x_batt_ps {
+       struct regmap *regmap;
+       struct power_supply *batt;
+       struct device *dev;
+       struct iio_channel *batt_chrg_i;
+       struct iio_channel *batt_dischrg_i;
+       struct iio_channel *batt_v;
+       u8 axp_id;
+};
+
+static int axp20x_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt,
+                                         int *val)
+{
+       int ret, reg;
+
+       ret = regmap_read(axp20x_batt->regmap, AXP20X_CHRG_CTRL1, &reg);
+       if (ret)
+               return ret;
+
+       switch (reg & AXP20X_CHRG_CTRL1_TGT_VOLT) {
+       case AXP20X_CHRG_CTRL1_TGT_4_1V:
+               *val = 4100000;
+               break;
+       case AXP20X_CHRG_CTRL1_TGT_4_15V:
+               *val = 4150000;
+               break;
+       case AXP20X_CHRG_CTRL1_TGT_4_2V:
+               *val = 4200000;
+               break;
+       case AXP20X_CHRG_CTRL1_TGT_4_36V:
+               *val = 4360000;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int axp22x_battery_get_max_voltage(struct axp20x_batt_ps *axp20x_batt,
+                                         int *val)
+{
+       int ret, reg;
+
+       ret = regmap_read(axp20x_batt->regmap, AXP20X_CHRG_CTRL1, &reg);
+       if (ret)
+               return ret;
+
+       switch (reg & AXP20X_CHRG_CTRL1_TGT_VOLT) {
+       case AXP20X_CHRG_CTRL1_TGT_4_1V:
+               *val = 4100000;
+               break;
+       case AXP20X_CHRG_CTRL1_TGT_4_2V:
+               *val = 4200000;
+               break;
+       case AXP22X_CHRG_CTRL1_TGT_4_22V:
+               *val = 4220000;
+               break;
+       case AXP22X_CHRG_CTRL1_TGT_4_24V:
+               *val = 4240000;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void raw_to_constant_charge_current(struct axp20x_batt_ps *axp, int *val)
+{
+       if (axp->axp_id == AXP209_ID)
+               *val = *val * 100000 + 300000;
+       else
+               *val = *val * 150000 + 300000;
+}
+
+static int axp20x_get_constant_charge_current(struct axp20x_batt_ps *axp,
+                                             int *val)
+{
+       int ret;
+
+       ret = regmap_read(axp->regmap, AXP20X_CHRG_CTRL1, val);
+       if (ret)
+               return ret;
+
+       *val &= AXP20X_CHRG_CTRL1_TGT_CURR;
+
+       raw_to_constant_charge_current(axp, val);
+
+       return 0;
+}
+
+static int axp20x_battery_get_prop(struct power_supply *psy,
+                                  enum power_supply_property psp,
+                                  union power_supply_propval *val)
+{
+       struct axp20x_batt_ps *axp20x_batt = power_supply_get_drvdata(psy);
+       struct iio_channel *chan;
+       int ret = 0, reg, val1;
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_PRESENT:
+       case POWER_SUPPLY_PROP_ONLINE:
+               ret = regmap_read(axp20x_batt->regmap, AXP20X_PWR_OP_MODE,
+                                 &reg);
+               if (ret)
+                       return ret;
+
+               val->intval = !!(reg & AXP20X_PWR_OP_BATT_PRESENT);
+               break;
+
+       case POWER_SUPPLY_PROP_STATUS:
+               ret = regmap_read(axp20x_batt->regmap, AXP20X_PWR_INPUT_STATUS,
+                                 &reg);
+               if (ret)
+                       return ret;
+
+               if (reg & AXP20X_PWR_STATUS_BAT_CHARGING) {
+                       val->intval = POWER_SUPPLY_STATUS_CHARGING;
+                       return 0;
+               }
+
+               ret = iio_read_channel_processed(axp20x_batt->batt_dischrg_i,
+                                                &val1);
+               if (ret)
+                       return ret;
+
+               if (val1) {
+                       val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+                       return 0;
+               }
+
+               ret = regmap_read(axp20x_batt->regmap, AXP20X_FG_RES, &val1);
+               if (ret)
+                       return ret;
+
+               /*
+                * Fuel Gauge data takes 7 bits but the stored value seems to be
+                * directly the raw percentage without any scaling to 7 bits.
+                */
+               if ((val1 & AXP209_FG_PERCENT) == 100)
+                       val->intval = POWER_SUPPLY_STATUS_FULL;
+               else
+                       val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+               break;
+
+       case POWER_SUPPLY_PROP_HEALTH:
+               ret = regmap_read(axp20x_batt->regmap, AXP20X_PWR_OP_MODE,
+                                 &val1);
+               if (ret)
+                       return ret;
+
+               if (val1 & AXP20X_PWR_OP_BATT_ACTIVATED) {
+                       val->intval = POWER_SUPPLY_HEALTH_DEAD;
+                       return 0;
+               }
+
+               val->intval = POWER_SUPPLY_HEALTH_GOOD;
+               break;
+
+       case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
+               ret = axp20x_get_constant_charge_current(axp20x_batt,
+                                                        &val->intval);
+               if (ret)
+                       return ret;
+               break;
+
+       case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX:
+               val->intval = AXP20X_CHRG_CTRL1_TGT_CURR;
+               raw_to_constant_charge_current(axp20x_batt, &val->intval);
+
+               break;
+
+       case POWER_SUPPLY_PROP_CURRENT_NOW:
+               ret = regmap_read(axp20x_batt->regmap, AXP20X_PWR_INPUT_STATUS,
+                                 &reg);
+               if (ret)
+                       return ret;
+
+               if (reg & AXP20X_PWR_STATUS_BAT_CHARGING)
+                       chan = axp20x_batt->batt_chrg_i;
+               else
+                       chan = axp20x_batt->batt_dischrg_i;
+
+               ret = iio_read_channel_processed(chan, &val->intval);
+               if (ret)
+                       return ret;
+
+               /* IIO framework gives mA but Power Supply framework gives uA */
+               val->intval *= 1000;
+               break;
+
+       case POWER_SUPPLY_PROP_CAPACITY:
+               /* When no battery is present, return capacity is 100% */
+               ret = regmap_read(axp20x_batt->regmap, AXP20X_PWR_OP_MODE,
+                                 &reg);
+               if (ret)
+                       return ret;
+
+               if (!(reg & AXP20X_PWR_OP_BATT_PRESENT)) {
+                       val->intval = 100;
+                       return 0;
+               }
+
+               ret = regmap_read(axp20x_batt->regmap, AXP20X_FG_RES, &reg);
+               if (ret)
+                       return ret;
+
+               if (axp20x_batt->axp_id == AXP221_ID &&
+                   !(reg & AXP22X_FG_VALID))
+                       return -EINVAL;
+
+               /*
+                * Fuel Gauge data takes 7 bits but the stored value seems to be
+                * directly the raw percentage without any scaling to 7 bits.
+                */
+               val->intval = reg & AXP209_FG_PERCENT;
+               break;
+
+       case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+               if (axp20x_batt->axp_id == AXP209_ID)
+                       return axp20x_battery_get_max_voltage(axp20x_batt,
+                                                             &val->intval);
+               return axp22x_battery_get_max_voltage(axp20x_batt,
+                                                     &val->intval);
+
+       case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+               ret = regmap_read(axp20x_batt->regmap, AXP20X_V_OFF, &reg);
+               if (ret)
+                       return ret;
+
+               val->intval = 2600000 + 100000 * (reg & AXP20X_V_OFF_MASK);
+               break;
+
+       case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+               ret = iio_read_channel_processed(axp20x_batt->batt_v,
+                                                &val->intval);
+               if (ret)
+                       return ret;
+
+               /* IIO framework gives mV but Power Supply framework gives uV */
+               val->intval *= 1000;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int axp20x_battery_set_max_voltage(struct axp20x_batt_ps *axp20x_batt,
+                                         int val)
+{
+       switch (val) {
+       case 4100000:
+               val = AXP20X_CHRG_CTRL1_TGT_4_1V;
+               break;
+
+       case 4150000:
+               if (axp20x_batt->axp_id == AXP221_ID)
+                       return -EINVAL;
+
+               val = AXP20X_CHRG_CTRL1_TGT_4_15V;
+               break;
+
+       case 4200000:
+               val = AXP20X_CHRG_CTRL1_TGT_4_2V;
+               break;
+
+       default:
+               /*
+                * AXP20x max voltage can be set to 4.36V and AXP22X max voltage
+                * can be set to 4.22V and 4.24V, but these voltages are too
+                * high for Lithium based batteries (AXP PMICs are supposed to
+                * be used with these kinds of battery).
+                */
+               return -EINVAL;
+       }
+
+       return regmap_update_bits(axp20x_batt->regmap, AXP20X_CHRG_CTRL1,
+                                 AXP20X_CHRG_CTRL1_TGT_VOLT, val);
+}
+
+static int axp20x_set_constant_charge_current(struct axp20x_batt_ps *axp_batt,
+                                             int charge_current)
+{
+       if (axp_batt->axp_id == AXP209_ID)
+               charge_current = (charge_current - 300000) / 100000;
+       else
+               charge_current = (charge_current - 300000) / 150000;
+
+       if (charge_current > AXP20X_CHRG_CTRL1_TGT_CURR || charge_current < 0)
+               return -EINVAL;
+
+       return regmap_update_bits(axp_batt->regmap, AXP20X_CHRG_CTRL1,
+                                 AXP20X_CHRG_CTRL1_TGT_CURR, charge_current);
+}
+
+static int axp20x_set_voltage_min_design(struct axp20x_batt_ps *axp_batt,
+                                        int min_voltage)
+{
+       int val1 = (min_voltage - 2600000) / 100000;
+
+       if (val1 < 0 || val1 > AXP20X_V_OFF_MASK)
+               return -EINVAL;
+
+       return regmap_update_bits(axp_batt->regmap, AXP20X_V_OFF,
+                                 AXP20X_V_OFF_MASK, val1);
+}
+
+static int axp20x_battery_set_prop(struct power_supply *psy,
+                                  enum power_supply_property psp,
+                                  const union power_supply_propval *val)
+{
+       struct axp20x_batt_ps *axp20x_batt = power_supply_get_drvdata(psy);
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+               return axp20x_set_voltage_min_design(axp20x_batt, val->intval);
+
+       case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
+               return axp20x_battery_set_max_voltage(axp20x_batt, val->intval);
+
+       case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
+               return axp20x_set_constant_charge_current(axp20x_batt,
+                                                         val->intval);
+
+       default:
+               return -EINVAL;
+       }
+}
+
+static enum power_supply_property axp20x_battery_props[] = {
+       POWER_SUPPLY_PROP_PRESENT,
+       POWER_SUPPLY_PROP_ONLINE,
+       POWER_SUPPLY_PROP_STATUS,
+       POWER_SUPPLY_PROP_VOLTAGE_NOW,
+       POWER_SUPPLY_PROP_CURRENT_NOW,
+       POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
+       POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
+       POWER_SUPPLY_PROP_HEALTH,
+       POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN,
+       POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+       POWER_SUPPLY_PROP_CAPACITY,
+};
+
+static int axp20x_battery_prop_writeable(struct power_supply *psy,
+                                        enum power_supply_property psp)
+{
+       return psp == POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN ||
+              psp == POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN ||
+              psp == POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT;
+}
+
+static const struct power_supply_desc axp20x_batt_ps_desc = {
+       .name = "axp20x-battery",
+       .type = POWER_SUPPLY_TYPE_BATTERY,
+       .properties = axp20x_battery_props,
+       .num_properties = ARRAY_SIZE(axp20x_battery_props),
+       .property_is_writeable = axp20x_battery_prop_writeable,
+       .get_property = axp20x_battery_get_prop,
+       .set_property = axp20x_battery_set_prop,
+};
+
+static const struct of_device_id axp20x_battery_ps_id[] = {
+       {
+               .compatible = "x-powers,axp209-battery-power-supply",
+               .data = (void *)AXP209_ID,
+       }, {
+               .compatible = "x-powers,axp221-battery-power-supply",
+               .data = (void *)AXP221_ID,
+       }, { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, axp20x_battery_ps_id);
+
+static int axp20x_power_probe(struct platform_device *pdev)
+{
+       struct axp20x_batt_ps *axp20x_batt;
+       struct power_supply_config psy_cfg = {};
+
+       if (!of_device_is_available(pdev->dev.of_node))
+               return -ENODEV;
+
+       axp20x_batt = devm_kzalloc(&pdev->dev, sizeof(*axp20x_batt),
+                                  GFP_KERNEL);
+       if (!axp20x_batt)
+               return -ENOMEM;
+
+       axp20x_batt->dev = &pdev->dev;
+
+       axp20x_batt->batt_v = devm_iio_channel_get(&pdev->dev, "batt_v");
+       if (IS_ERR(axp20x_batt->batt_v)) {
+               if (PTR_ERR(axp20x_batt->batt_v) == -ENODEV)
+                       return -EPROBE_DEFER;
+               return PTR_ERR(axp20x_batt->batt_v);
+       }
+
+       axp20x_batt->batt_chrg_i = devm_iio_channel_get(&pdev->dev,
+                                                       "batt_chrg_i");
+       if (IS_ERR(axp20x_batt->batt_chrg_i)) {
+               if (PTR_ERR(axp20x_batt->batt_chrg_i) == -ENODEV)
+                       return -EPROBE_DEFER;
+               return PTR_ERR(axp20x_batt->batt_chrg_i);
+       }
+
+       axp20x_batt->batt_dischrg_i = devm_iio_channel_get(&pdev->dev,
+                                                          "batt_dischrg_i");
+       if (IS_ERR(axp20x_batt->batt_dischrg_i)) {
+               if (PTR_ERR(axp20x_batt->batt_dischrg_i) == -ENODEV)
+                       return -EPROBE_DEFER;
+               return PTR_ERR(axp20x_batt->batt_dischrg_i);
+       }
+
+       axp20x_batt->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+       platform_set_drvdata(pdev, axp20x_batt);
+
+       psy_cfg.drv_data = axp20x_batt;
+       psy_cfg.of_node = pdev->dev.of_node;
+
+       axp20x_batt->axp_id = (uintptr_t)of_device_get_match_data(&pdev->dev);
+
+       axp20x_batt->batt = devm_power_supply_register(&pdev->dev,
+                                                      &axp20x_batt_ps_desc,
+                                                      &psy_cfg);
+       if (IS_ERR(axp20x_batt->batt)) {
+               dev_err(&pdev->dev, "failed to register power supply: %ld\n",
+                       PTR_ERR(axp20x_batt->batt));
+               return PTR_ERR(axp20x_batt->batt);
+       }
+
+       return 0;
+}
+
+static struct platform_driver axp20x_batt_driver = {
+       .probe    = axp20x_power_probe,
+       .driver   = {
+               .name  = "axp20x-battery-power-supply",
+               .of_match_table = axp20x_battery_ps_id,
+       },
+};
+
+module_platform_driver(axp20x_batt_driver);
+
+MODULE_DESCRIPTION("Battery power supply driver for AXP20X and AXP22X PMICs");
+MODULE_AUTHOR("Quentin Schulz <quentin.schulz@free-electrons.com>");
+MODULE_LICENSE("GPL");
index bd9e5c3d8cc2880678f366fa0ec10c130f5c4e43..d5a707e14526ac9b47716b5452cccc8b233ef68b 100644 (file)
@@ -533,6 +533,9 @@ static int bq24190_register_reset(struct bq24190_dev_info *bdi)
        int ret, limit = 100;
        u8 v;
 
+       if (device_property_read_bool(bdi->dev, "disable-reset"))
+               return 0;
+
        /* Reset the registers */
        ret = bq24190_write_mask(bdi, BQ24190_REG_POC,
                        BQ24190_REG_POC_RESET_MASK,
@@ -659,22 +662,25 @@ static int bq24190_charger_get_health(struct bq24190_dev_info *bdi,
        v = bdi->f_reg;
        mutex_unlock(&bdi->f_reg_lock);
 
-       if (v & BQ24190_REG_F_BOOST_FAULT_MASK) {
-               /*
-                * This could be over-current or over-voltage but there's
-                * no way to tell which.  Return 'OVERVOLTAGE' since there
-                * isn't an 'OVERCURRENT' value defined that we can return
-                * even if it was over-current.
-                */
-               health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
-       } else {
-               v &= BQ24190_REG_F_CHRG_FAULT_MASK;
-               v >>= BQ24190_REG_F_CHRG_FAULT_SHIFT;
-
-               switch (v) {
-               case 0x0: /* Normal */
-                       health = POWER_SUPPLY_HEALTH_GOOD;
+       if (v & BQ24190_REG_F_NTC_FAULT_MASK) {
+               switch (v >> BQ24190_REG_F_NTC_FAULT_SHIFT & 0x7) {
+               case 0x1: /* TS1  Cold */
+               case 0x3: /* TS2  Cold */
+               case 0x5: /* Both Cold */
+                       health = POWER_SUPPLY_HEALTH_COLD;
+                       break;
+               case 0x2: /* TS1  Hot */
+               case 0x4: /* TS2  Hot */
+               case 0x6: /* Both Hot */
+                       health = POWER_SUPPLY_HEALTH_OVERHEAT;
                        break;
+               default:
+                       health = POWER_SUPPLY_HEALTH_UNKNOWN;
+               }
+       } else if (v & BQ24190_REG_F_BAT_FAULT_MASK) {
+               health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
+       } else if (v & BQ24190_REG_F_CHRG_FAULT_MASK) {
+               switch (v >> BQ24190_REG_F_CHRG_FAULT_SHIFT & 0x3) {
                case 0x1: /* Input Fault (VBUS OVP or VBAT<VBUS<3.8V) */
                        /*
                         * This could be over-voltage or under-voltage
@@ -691,9 +697,19 @@ static int bq24190_charger_get_health(struct bq24190_dev_info *bdi,
                case 0x3: /* Charge Safety Timer Expiration */
                        health = POWER_SUPPLY_HEALTH_SAFETY_TIMER_EXPIRE;
                        break;
-               default:
-                       health = POWER_SUPPLY_HEALTH_UNKNOWN;
+               default:  /* prevent compiler warning */
+                       health = -1;
                }
+       } else if (v & BQ24190_REG_F_BOOST_FAULT_MASK) {
+               /*
+                * This could be over-current or over-voltage but there's
+                * no way to tell which.  Return 'OVERVOLTAGE' since there
+                * isn't an 'OVERCURRENT' value defined that we can return
+                * even if it was over-current.
+                */
+               health = POWER_SUPPLY_HEALTH_OVERVOLTAGE;
+       } else {
+               health = POWER_SUPPLY_HEALTH_GOOD;
        }
 
        val->intval = health;
@@ -704,19 +720,59 @@ static int bq24190_charger_get_health(struct bq24190_dev_info *bdi,
 static int bq24190_charger_get_online(struct bq24190_dev_info *bdi,
                union power_supply_propval *val)
 {
-       u8 v;
+       u8 pg_stat, batfet_disable;
        int ret;
 
        ret = bq24190_read_mask(bdi, BQ24190_REG_SS,
                        BQ24190_REG_SS_PG_STAT_MASK,
-                       BQ24190_REG_SS_PG_STAT_SHIFT, &v);
+                       BQ24190_REG_SS_PG_STAT_SHIFT, &pg_stat);
        if (ret < 0)
                return ret;
 
-       val->intval = v;
+       ret = bq24190_read_mask(bdi, BQ24190_REG_MOC,
+                       BQ24190_REG_MOC_BATFET_DISABLE_MASK,
+                       BQ24190_REG_MOC_BATFET_DISABLE_SHIFT, &batfet_disable);
+       if (ret < 0)
+               return ret;
+
+       val->intval = pg_stat && !batfet_disable;
+
        return 0;
 }
 
+static int bq24190_battery_set_online(struct bq24190_dev_info *bdi,
+                                     const union power_supply_propval *val);
+static int bq24190_battery_get_status(struct bq24190_dev_info *bdi,
+                                     union power_supply_propval *val);
+static int bq24190_battery_get_temp_alert_max(struct bq24190_dev_info *bdi,
+                                             union power_supply_propval *val);
+static int bq24190_battery_set_temp_alert_max(struct bq24190_dev_info *bdi,
+                                             const union power_supply_propval *val);
+
+static int bq24190_charger_set_online(struct bq24190_dev_info *bdi,
+                                     const union power_supply_propval *val)
+{
+       return bq24190_battery_set_online(bdi, val);
+}
+
+static int bq24190_charger_get_status(struct bq24190_dev_info *bdi,
+                                     union power_supply_propval *val)
+{
+       return bq24190_battery_get_status(bdi, val);
+}
+
+static int bq24190_charger_get_temp_alert_max(struct bq24190_dev_info *bdi,
+                                             union power_supply_propval *val)
+{
+       return bq24190_battery_get_temp_alert_max(bdi, val);
+}
+
+static int bq24190_charger_set_temp_alert_max(struct bq24190_dev_info *bdi,
+                                             const union power_supply_propval *val)
+{
+       return bq24190_battery_set_temp_alert_max(bdi, val);
+}
+
 static int bq24190_charger_get_current(struct bq24190_dev_info *bdi,
                union power_supply_propval *val)
 {
@@ -831,6 +887,12 @@ static int bq24190_charger_get_property(struct power_supply *psy,
        case POWER_SUPPLY_PROP_ONLINE:
                ret = bq24190_charger_get_online(bdi, val);
                break;
+       case POWER_SUPPLY_PROP_STATUS:
+               ret = bq24190_charger_get_status(bdi, val);
+               break;
+       case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
+               ret =  bq24190_charger_get_temp_alert_max(bdi, val);
+               break;
        case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
                ret = bq24190_charger_get_current(bdi, val);
                break;
@@ -879,6 +941,12 @@ static int bq24190_charger_set_property(struct power_supply *psy,
                return ret;
 
        switch (psp) {
+       case POWER_SUPPLY_PROP_ONLINE:
+               ret = bq24190_charger_set_online(bdi, val);
+               break;
+       case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
+               ret = bq24190_charger_set_temp_alert_max(bdi, val);
+               break;
        case POWER_SUPPLY_PROP_CHARGE_TYPE:
                ret = bq24190_charger_set_charge_type(bdi, val);
                break;
@@ -904,6 +972,8 @@ static int bq24190_charger_property_is_writeable(struct power_supply *psy,
        int ret;
 
        switch (psp) {
+       case POWER_SUPPLY_PROP_ONLINE:
+       case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
        case POWER_SUPPLY_PROP_CHARGE_TYPE:
        case POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT:
        case POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE:
@@ -920,6 +990,8 @@ static enum power_supply_property bq24190_charger_properties[] = {
        POWER_SUPPLY_PROP_CHARGE_TYPE,
        POWER_SUPPLY_PROP_HEALTH,
        POWER_SUPPLY_PROP_ONLINE,
+       POWER_SUPPLY_PROP_STATUS,
+       POWER_SUPPLY_PROP_TEMP_ALERT_MAX,
        POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT,
        POWER_SUPPLY_PROP_CONSTANT_CHARGE_CURRENT_MAX,
        POWER_SUPPLY_PROP_CONSTANT_CHARGE_VOLTAGE,
@@ -1093,6 +1165,7 @@ static int bq24190_battery_get_property(struct power_supply *psy,
        struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);
        int ret;
 
+       dev_warn(bdi->dev, "warning: /sys/class/power_supply/bq24190-battery is deprecated\n");
        dev_dbg(bdi->dev, "prop: %d\n", psp);
 
        ret = pm_runtime_get_sync(bdi->dev);
@@ -1138,6 +1211,7 @@ static int bq24190_battery_set_property(struct power_supply *psy,
        struct bq24190_dev_info *bdi = power_supply_get_drvdata(psy);
        int ret;
 
+       dev_warn(bdi->dev, "warning: /sys/class/power_supply/bq24190-battery is deprecated\n");
        dev_dbg(bdi->dev, "prop: %d\n", psp);
 
        ret = pm_runtime_get_sync(bdi->dev);
@@ -1266,9 +1340,9 @@ static void bq24190_check_status(struct bq24190_dev_info *bdi)
                bdi->ss_reg = ss_reg;
        }
 
-       if (alert_charger)
+       if (alert_charger || alert_battery)
                power_supply_changed(bdi->charger);
-       if (alert_battery)
+       if (alert_battery && bdi->battery)
                power_supply_changed(bdi->battery);
 
        dev_dbg(bdi->dev, "ss_reg: 0x%02x, f_reg: 0x%02x\n", ss_reg, f_reg);
@@ -1473,19 +1547,23 @@ static int bq24190_probe(struct i2c_client *client,
                goto out_pmrt;
        }
 
-       battery_cfg.drv_data = bdi;
-       bdi->battery = power_supply_register(dev, &bq24190_battery_desc,
-                                               &battery_cfg);
-       if (IS_ERR(bdi->battery)) {
-               dev_err(dev, "Can't register battery\n");
-               ret = PTR_ERR(bdi->battery);
-               goto out_charger;
+       /* the battery class is deprecated and will be removed. */
+       /* in the interim, this property hides it.              */
+       if (!device_property_read_bool(dev, "omit-battery-class")) {
+               battery_cfg.drv_data = bdi;
+               bdi->battery = power_supply_register(dev, &bq24190_battery_desc,
+                                                    &battery_cfg);
+               if (IS_ERR(bdi->battery)) {
+                       dev_err(dev, "Can't register battery\n");
+                       ret = PTR_ERR(bdi->battery);
+                       goto out_charger;
+               }
        }
 
        ret = bq24190_sysfs_create_group(bdi);
        if (ret) {
                dev_err(dev, "Can't create sysfs entries\n");
-               goto out_battery;
+               goto out_charger;
        }
 
        bdi->initialized = true;
@@ -1523,10 +1601,9 @@ static int bq24190_probe(struct i2c_client *client,
 out_sysfs:
        bq24190_sysfs_remove_group(bdi);
 
-out_battery:
-       power_supply_unregister(bdi->battery);
-
 out_charger:
+       if (!IS_ERR_OR_NULL(bdi->battery))
+               power_supply_unregister(bdi->battery);
        power_supply_unregister(bdi->charger);
 
 out_pmrt:
@@ -1549,7 +1626,8 @@ static int bq24190_remove(struct i2c_client *client)
 
        bq24190_register_reset(bdi);
        bq24190_sysfs_remove_group(bdi);
-       power_supply_unregister(bdi->battery);
+       if (bdi->battery)
+               power_supply_unregister(bdi->battery);
        power_supply_unregister(bdi->charger);
        if (error >= 0)
                pm_runtime_put_sync(bdi->dev);
@@ -1636,7 +1714,8 @@ static __maybe_unused int bq24190_pm_resume(struct device *dev)
 
        /* Things may have changed while suspended so alert upper layer */
        power_supply_changed(bdi->charger);
-       power_supply_changed(bdi->battery);
+       if (bdi->battery)
+               power_supply_changed(bdi->battery);
 
        return 0;
 }
index 543a1bd21ab9c74ab15a2a16898fa477ed021818..26a2dc7ac9a2777643ec2b3abda2e19af0b7ea50 100644 (file)
@@ -76,7 +76,7 @@
 #define CPCAP_REG_CRM_VCHRG_4V30       CPCAP_REG_CRM_VCHRG(0x8)
 #define CPCAP_REG_CRM_VCHRG_4V32       CPCAP_REG_CRM_VCHRG(0x9)
 #define CPCAP_REG_CRM_VCHRG_4V34       CPCAP_REG_CRM_VCHRG(0xa)
-#define CPCAP_REG_CRM_VCHRG_4V36       CPCAP_REG_CRM_VCHRG(0xb)
+#define CPCAP_REG_CRM_VCHRG_4V35       CPCAP_REG_CRM_VCHRG(0xb)
 #define CPCAP_REG_CRM_VCHRG_4V38       CPCAP_REG_CRM_VCHRG(0xc)
 #define CPCAP_REG_CRM_VCHRG_4V40       CPCAP_REG_CRM_VCHRG(0xd)
 #define CPCAP_REG_CRM_VCHRG_4V42       CPCAP_REG_CRM_VCHRG(0xe)
@@ -262,7 +262,7 @@ static int cpcap_charger_set_state(struct cpcap_charger_ddata *ddata,
        bool enable;
        int error;
 
-       enable = max_voltage && (charge_current || trickle_current);
+       enable = (charge_current || trickle_current);
        dev_dbg(ddata->dev, "%s enable: %i\n", __func__, enable);
 
        if (!enable) {
@@ -433,9 +433,8 @@ static void cpcap_usb_detect(struct work_struct *work)
                        max_current = CPCAP_REG_CRM_ICHRG_0A528;
 
                error = cpcap_charger_set_state(ddata,
-                                               CPCAP_REG_CRM_VCHRG_4V20,
-                                               max_current,
-                                               CPCAP_REG_CRM_TR_0A72);
+                                               CPCAP_REG_CRM_VCHRG_4V35,
+                                               max_current, 0);
                if (error)
                        goto out_err;
        } else {
@@ -566,7 +565,7 @@ out_err:
 }
 
 static const struct power_supply_desc cpcap_charger_usb_desc = {
-       .name           = "cpcap_usb",
+       .name           = "usb",
        .type           = POWER_SUPPLY_TYPE_USB,
        .properties     = cpcap_charger_props,
        .num_properties = ARRAY_SIZE(cpcap_charger_props),
index edb36bf781b0cb0bb0856b72ab91b2aa8e33aaa4..37e523374fe00ebe44de3f20ae12a1b8674641b5 100644 (file)
@@ -383,8 +383,7 @@ static int gab_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM
-static int gab_suspend(struct device *dev)
+static int __maybe_unused gab_suspend(struct device *dev)
 {
        struct gab *adc_bat = dev_get_drvdata(dev);
 
@@ -393,7 +392,7 @@ static int gab_suspend(struct device *dev)
        return 0;
 }
 
-static int gab_resume(struct device *dev)
+static int __maybe_unused gab_resume(struct device *dev)
 {
        struct gab *adc_bat = dev_get_drvdata(dev);
        struct gab_platform_data *pdata = adc_bat->pdata;
@@ -407,20 +406,12 @@ static int gab_resume(struct device *dev)
        return 0;
 }
 
-static const struct dev_pm_ops gab_pm_ops = {
-       .suspend        = gab_suspend,
-       .resume         = gab_resume,
-};
-
-#define GAB_PM_OPS       (&gab_pm_ops)
-#else
-#define GAB_PM_OPS       (NULL)
-#endif
+static SIMPLE_DEV_PM_OPS(gab_pm_ops, gab_suspend, gab_resume);
 
 static struct platform_driver gab_driver = {
        .driver         = {
                .name   = "generic-adc-battery",
-               .pm     = GAB_PM_OPS
+               .pm     = &gab_pm_ops,
        },
        .probe          = gab_probe,
        .remove         = gab_remove,
index 4cd6899b961e780e0623e81951ecc12e1fcd3557..95af5f305838a6508bf1b95988a28854d829a6dc 100644 (file)
@@ -418,6 +418,10 @@ static int isp1704_charger_probe(struct platform_device *pdev)
 
                pdata = devm_kzalloc(&pdev->dev,
                        sizeof(struct isp1704_charger_data), GFP_KERNEL);
+               if (!pdata) {
+                       ret = -ENOMEM;
+                       goto fail0;
+               }
                pdata->enable_gpio = gpio;
 
                dev_info(&pdev->dev, "init gpio %d\n", pdata->enable_gpio);
index da7a75f824891200f9db4c9dd4d274c5125d3dd8..aecaaa2b0586027036f467805358697e979b4538 100644 (file)
@@ -76,15 +76,20 @@ struct max17042_chip {
 };
 
 static enum power_supply_property max17042_battery_props[] = {
+       POWER_SUPPLY_PROP_STATUS,
        POWER_SUPPLY_PROP_PRESENT,
+       POWER_SUPPLY_PROP_TECHNOLOGY,
        POWER_SUPPLY_PROP_CYCLE_COUNT,
        POWER_SUPPLY_PROP_VOLTAGE_MAX,
+       POWER_SUPPLY_PROP_VOLTAGE_MIN,
        POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
        POWER_SUPPLY_PROP_VOLTAGE_NOW,
        POWER_SUPPLY_PROP_VOLTAGE_AVG,
        POWER_SUPPLY_PROP_VOLTAGE_OCV,
        POWER_SUPPLY_PROP_CAPACITY,
+       POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
        POWER_SUPPLY_PROP_CHARGE_FULL,
+       POWER_SUPPLY_PROP_CHARGE_NOW,
        POWER_SUPPLY_PROP_CHARGE_COUNTER,
        POWER_SUPPLY_PROP_TEMP,
        POWER_SUPPLY_PROP_TEMP_ALERT_MIN,
@@ -92,6 +97,7 @@ static enum power_supply_property max17042_battery_props[] = {
        POWER_SUPPLY_PROP_TEMP_MIN,
        POWER_SUPPLY_PROP_TEMP_MAX,
        POWER_SUPPLY_PROP_HEALTH,
+       POWER_SUPPLY_PROP_SCOPE,
        POWER_SUPPLY_PROP_CURRENT_NOW,
        POWER_SUPPLY_PROP_CURRENT_AVG,
 };
@@ -106,19 +112,53 @@ static int max17042_get_temperature(struct max17042_chip *chip, int *temp)
        if (ret < 0)
                return ret;
 
-       *temp = data;
-       /* The value is signed. */
-       if (*temp & 0x8000) {
-               *temp = (0x7fff & ~*temp) + 1;
-               *temp *= -1;
-       }
-
+       *temp = sign_extend32(data, 15);
        /* The value is converted into deci-centigrade scale */
        /* Units of LSB = 1 / 256 degree Celsius */
        *temp = *temp * 10 / 256;
        return 0;
 }
 
+static int max17042_get_status(struct max17042_chip *chip, int *status)
+{
+       int ret, charge_full, charge_now;
+
+       ret = power_supply_am_i_supplied(chip->battery);
+       if (ret < 0) {
+               *status = POWER_SUPPLY_STATUS_UNKNOWN;
+               return 0;
+       }
+       if (ret == 0) {
+               *status = POWER_SUPPLY_STATUS_DISCHARGING;
+               return 0;
+       }
+
+       /*
+        * The MAX170xx has builtin end-of-charge detection and will update
+        * FullCAP to match RepCap when it detects end of charging.
+        *
+        * When this cycle the battery gets charged to a higher (calculated)
+        * capacity then the previous cycle then FullCAP will get updated
+        * contineously once end-of-charge detection kicks in, so allow the
+        * 2 to differ a bit.
+        */
+
+       ret = regmap_read(chip->regmap, MAX17042_FullCAP, &charge_full);
+       if (ret < 0)
+               return ret;
+
+       ret = regmap_read(chip->regmap, MAX17042_RepCap, &charge_now);
+       if (ret < 0)
+               return ret;
+
+       if ((charge_full - charge_now) <= MAX17042_FULL_THRESHOLD)
+               *status = POWER_SUPPLY_STATUS_FULL;
+       else
+               *status = POWER_SUPPLY_STATUS_CHARGING;
+
+       return 0;
+}
+
 static int max17042_get_battery_health(struct max17042_chip *chip, int *health)
 {
        int temp, vavg, vbatt, ret;
@@ -156,12 +196,12 @@ static int max17042_get_battery_health(struct max17042_chip *chip, int *health)
        if (ret < 0)
                goto health_error;
 
-       if (temp <= chip->pdata->temp_min) {
+       if (temp < chip->pdata->temp_min) {
                *health = POWER_SUPPLY_HEALTH_COLD;
                goto out;
        }
 
-       if (temp >= chip->pdata->temp_max) {
+       if (temp > chip->pdata->temp_max) {
                *health = POWER_SUPPLY_HEALTH_OVERHEAT;
                goto out;
        }
@@ -183,11 +223,17 @@ static int max17042_get_property(struct power_supply *psy,
        struct regmap *map = chip->regmap;
        int ret;
        u32 data;
+       u64 data64;
 
        if (!chip->init_complete)
                return -EAGAIN;
 
        switch (psp) {
+       case POWER_SUPPLY_PROP_STATUS:
+               ret = max17042_get_status(chip, &val->intval);
+               if (ret < 0)
+                       return ret;
+               break;
        case POWER_SUPPLY_PROP_PRESENT:
                ret = regmap_read(map, MAX17042_STATUS, &data);
                if (ret < 0)
@@ -198,6 +244,9 @@ static int max17042_get_property(struct power_supply *psy,
                else
                        val->intval = 1;
                break;
+       case POWER_SUPPLY_PROP_TECHNOLOGY:
+               val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
+               break;
        case POWER_SUPPLY_PROP_CYCLE_COUNT:
                ret = regmap_read(map, MAX17042_Cycles, &data);
                if (ret < 0)
@@ -213,6 +262,13 @@ static int max17042_get_property(struct power_supply *psy,
                val->intval = data >> 8;
                val->intval *= 20000; /* Units of LSB = 20mV */
                break;
+       case POWER_SUPPLY_PROP_VOLTAGE_MIN:
+               ret = regmap_read(map, MAX17042_MinMaxVolt, &data);
+               if (ret < 0)
+                       return ret;
+
+               val->intval = (data & 0xff) * 20000; /* Units of 20mV */
+               break;
        case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
                if (chip->chip_type == MAXIM_DEVICE_TYPE_MAX17042)
                        ret = regmap_read(map, MAX17042_V_empty, &data);
@@ -252,12 +308,32 @@ static int max17042_get_property(struct power_supply *psy,
 
                val->intval = data >> 8;
                break;
+       case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+               ret = regmap_read(map, MAX17042_DesignCap, &data);
+               if (ret < 0)
+                       return ret;
+
+               data64 = data * 5000000ll;
+               do_div(data64, chip->pdata->r_sns);
+               val->intval = data64;
+               break;
        case POWER_SUPPLY_PROP_CHARGE_FULL:
                ret = regmap_read(map, MAX17042_FullCAP, &data);
                if (ret < 0)
                        return ret;
 
-               val->intval = data * 1000 / 2;
+               data64 = data * 5000000ll;
+               do_div(data64, chip->pdata->r_sns);
+               val->intval = data64;
+               break;
+       case POWER_SUPPLY_PROP_CHARGE_NOW:
+               ret = regmap_read(map, MAX17042_RepCap, &data);
+               if (ret < 0)
+                       return ret;
+
+               data64 = data * 5000000ll;
+               do_div(data64, chip->pdata->r_sns);
+               val->intval = data64;
                break;
        case POWER_SUPPLY_PROP_CHARGE_COUNTER:
                ret = regmap_read(map, MAX17042_QH, &data);
@@ -276,14 +352,14 @@ static int max17042_get_property(struct power_supply *psy,
                if (ret < 0)
                        return ret;
                /* LSB is Alert Minimum. In deci-centigrade */
-               val->intval = (data & 0xff) * 10;
+               val->intval = sign_extend32(data & 0xff, 7) * 10;
                break;
        case POWER_SUPPLY_PROP_TEMP_ALERT_MAX:
                ret = regmap_read(map, MAX17042_TALRT_Th, &data);
                if (ret < 0)
                        return ret;
                /* MSB is Alert Maximum. In deci-centigrade */
-               val->intval = (data >> 8) * 10;
+               val->intval = sign_extend32(data >> 8, 7) * 10;
                break;
        case POWER_SUPPLY_PROP_TEMP_MIN:
                val->intval = chip->pdata->temp_min;
@@ -296,19 +372,16 @@ static int max17042_get_property(struct power_supply *psy,
                if (ret < 0)
                        return ret;
                break;
+       case POWER_SUPPLY_PROP_SCOPE:
+               val->intval = POWER_SUPPLY_SCOPE_SYSTEM;
+               break;
        case POWER_SUPPLY_PROP_CURRENT_NOW:
                if (chip->pdata->enable_current_sense) {
                        ret = regmap_read(map, MAX17042_Current, &data);
                        if (ret < 0)
                                return ret;
 
-                       val->intval = data;
-                       if (val->intval & 0x8000) {
-                               /* Negative */
-                               val->intval = ~val->intval & 0x7fff;
-                               val->intval++;
-                               val->intval *= -1;
-                       }
+                       val->intval = sign_extend32(data, 15);
                        val->intval *= 1562500 / chip->pdata->r_sns;
                } else {
                        return -EINVAL;
@@ -320,13 +393,7 @@ static int max17042_get_property(struct power_supply *psy,
                        if (ret < 0)
                                return ret;
 
-                       val->intval = data;
-                       if (val->intval & 0x8000) {
-                               /* Negative */
-                               val->intval = ~val->intval & 0x7fff;
-                               val->intval++;
-                               val->intval *= -1;
-                       }
+                       val->intval = sign_extend32(data, 15);
                        val->intval *= 1562500 / chip->pdata->r_sns;
                } else {
                        return -EINVAL;
@@ -401,6 +468,11 @@ static int max17042_property_is_writeable(struct power_supply *psy,
        return ret;
 }
 
+static void max17042_external_power_changed(struct power_supply *psy)
+{
+       power_supply_changed(psy);
+}
+
 static int max17042_write_verify_reg(struct regmap *map, u8 reg, u32 value)
 {
        int retries = 8;
@@ -790,8 +862,9 @@ static void max17042_init_worker(struct work_struct *work)
 
 #ifdef CONFIG_OF
 static struct max17042_platform_data *
-max17042_get_pdata(struct device *dev)
+max17042_get_pdata(struct max17042_chip *chip)
 {
+       struct device *dev = &chip->client->dev;
        struct device_node *np = dev->of_node;
        u32 prop;
        struct max17042_platform_data *pdata;
@@ -824,10 +897,55 @@ max17042_get_pdata(struct device *dev)
        return pdata;
 }
 #else
+static struct max17042_reg_data max17047_default_pdata_init_regs[] = {
+       /*
+        * Some firmwares do not set FullSOCThr, Enable End-of-Charge Detection
+        * when the voltage FG reports 95%, as recommended in the datasheet.
+        */
+       { MAX17047_FullSOCThr, MAX17042_BATTERY_FULL << 8 },
+};
+
 static struct max17042_platform_data *
-max17042_get_pdata(struct device *dev)
+max17042_get_pdata(struct max17042_chip *chip)
 {
-       return dev->platform_data;
+       struct device *dev = &chip->client->dev;
+       struct max17042_platform_data *pdata;
+       int ret, misc_cfg;
+
+       if (dev->platform_data)
+               return dev->platform_data;
+
+       /*
+        * The MAX17047 gets used on x86 where we might not have pdata, assume
+        * the firmware will already have initialized the fuel-gauge and provide
+        * default values for the non init bits to make things work.
+        */
+       pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return pdata;
+
+       if (chip->chip_type != MAXIM_DEVICE_TYPE_MAX17042) {
+               pdata->init_data = max17047_default_pdata_init_regs;
+               pdata->num_init_data =
+                       ARRAY_SIZE(max17047_default_pdata_init_regs);
+       }
+
+       ret = regmap_read(chip->regmap, MAX17042_MiscCFG, &misc_cfg);
+       if (ret < 0)
+               return NULL;
+
+       /* If bits 0-1 are set to 3 then only Voltage readings are used */
+       if ((misc_cfg & 0x3) == 0x3)
+               pdata->enable_current_sense = false;
+       else
+               pdata->enable_current_sense = true;
+
+       pdata->vmin = MAX17042_DEFAULT_VMIN;
+       pdata->vmax = MAX17042_DEFAULT_VMAX;
+       pdata->temp_min = MAX17042_DEFAULT_TEMP_MIN;
+       pdata->temp_max = MAX17042_DEFAULT_TEMP_MAX;
+
+       return pdata;
 }
 #endif
 
@@ -843,6 +961,7 @@ static const struct power_supply_desc max17042_psy_desc = {
        .get_property   = max17042_get_property,
        .set_property   = max17042_set_property,
        .property_is_writeable  = max17042_property_is_writeable,
+       .external_power_changed = max17042_external_power_changed,
        .properties     = max17042_battery_props,
        .num_properties = ARRAY_SIZE(max17042_battery_props),
 };
@@ -876,20 +995,20 @@ static int max17042_probe(struct i2c_client *client,
                return -ENOMEM;
 
        chip->client = client;
+       chip->chip_type = id->driver_data;
        chip->regmap = devm_regmap_init_i2c(client, &max17042_regmap_config);
        if (IS_ERR(chip->regmap)) {
                dev_err(&client->dev, "Failed to initialize regmap\n");
                return -EINVAL;
        }
 
-       chip->pdata = max17042_get_pdata(&client->dev);
+       chip->pdata = max17042_get_pdata(chip);
        if (!chip->pdata) {
                dev_err(&client->dev, "no platform data provided\n");
                return -EINVAL;
        }
 
        i2c_set_clientdata(client, chip);
-       chip->chip_type = id->driver_data;
        psy_cfg.drv_data = chip;
 
        /* When current is not measured,
index dfe1ee89f7c7ad06fc014b3986c240904329e6ba..922a86787c5c4c69901bf2f48933e29653e29bf1 100644 (file)
@@ -30,9 +30,9 @@ static inline unsigned int get_irq_flags(struct resource *res)
 static struct device *dev;
 static struct pda_power_pdata *pdata;
 static struct resource *ac_irq, *usb_irq;
-static struct timer_list charger_timer;
-static struct timer_list supply_timer;
-static struct timer_list polling_timer;
+static struct delayed_work charger_work;
+static struct delayed_work polling_work;
+static struct delayed_work supply_work;
 static int polling;
 static struct power_supply *pda_psy_ac, *pda_psy_usb;
 
@@ -140,7 +140,7 @@ static void update_charger(void)
        }
 }
 
-static void supply_timer_func(unsigned long unused)
+static void supply_work_func(struct work_struct *work)
 {
        if (ac_status == PDA_PSY_TO_CHANGE) {
                ac_status = new_ac_status;
@@ -161,11 +161,12 @@ static void psy_changed(void)
         * Okay, charger set. Now wait a bit before notifying supplicants,
         * charge power should stabilize.
         */
-       mod_timer(&supply_timer,
-                 jiffies + msecs_to_jiffies(pdata->wait_for_charger));
+       cancel_delayed_work(&supply_work);
+       schedule_delayed_work(&supply_work,
+                             msecs_to_jiffies(pdata->wait_for_charger));
 }
 
-static void charger_timer_func(unsigned long unused)
+static void charger_work_func(struct work_struct *work)
 {
        update_status();
        psy_changed();
@@ -184,13 +185,14 @@ static irqreturn_t power_changed_isr(int irq, void *power_supply)
         * Wait a bit before reading ac/usb line status and setting charger,
         * because ac/usb status readings may lag from irq.
         */
-       mod_timer(&charger_timer,
-                 jiffies + msecs_to_jiffies(pdata->wait_for_status));
+       cancel_delayed_work(&charger_work);
+       schedule_delayed_work(&charger_work,
+                             msecs_to_jiffies(pdata->wait_for_status));
 
        return IRQ_HANDLED;
 }
 
-static void polling_timer_func(unsigned long unused)
+static void polling_work_func(struct work_struct *work)
 {
        int changed = 0;
 
@@ -211,8 +213,9 @@ static void polling_timer_func(unsigned long unused)
        if (changed)
                psy_changed();
 
-       mod_timer(&polling_timer,
-                 jiffies + msecs_to_jiffies(pdata->polling_interval));
+       cancel_delayed_work(&polling_work);
+       schedule_delayed_work(&polling_work,
+                             msecs_to_jiffies(pdata->polling_interval));
 }
 
 #if IS_ENABLED(CONFIG_USB_PHY)
@@ -250,8 +253,9 @@ static int otg_handle_notification(struct notifier_block *nb,
         * Wait a bit before reading ac/usb line status and setting charger,
         * because ac/usb status readings may lag from irq.
         */
-       mod_timer(&charger_timer,
-                 jiffies + msecs_to_jiffies(pdata->wait_for_status));
+       cancel_delayed_work(&charger_work);
+       schedule_delayed_work(&charger_work,
+                             msecs_to_jiffies(pdata->wait_for_status));
 
        return NOTIFY_OK;
 }
@@ -300,8 +304,8 @@ static int pda_power_probe(struct platform_device *pdev)
        if (!pdata->ac_max_uA)
                pdata->ac_max_uA = 500000;
 
-       setup_timer(&charger_timer, charger_timer_func, 0);
-       setup_timer(&supply_timer, supply_timer_func, 0);
+       INIT_DELAYED_WORK(&charger_work, charger_work_func);
+       INIT_DELAYED_WORK(&supply_work, supply_work_func);
 
        ac_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "ac");
        usb_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "usb");
@@ -385,9 +389,10 @@ static int pda_power_probe(struct platform_device *pdev)
 
        if (polling) {
                dev_dbg(dev, "will poll for status\n");
-               setup_timer(&polling_timer, polling_timer_func, 0);
-               mod_timer(&polling_timer,
-                         jiffies + msecs_to_jiffies(pdata->polling_interval));
+               INIT_DELAYED_WORK(&polling_work, polling_work_func);
+               cancel_delayed_work(&polling_work);
+               schedule_delayed_work(&polling_work,
+                                     msecs_to_jiffies(pdata->polling_interval));
        }
 
        if (ac_irq || usb_irq)
@@ -433,9 +438,9 @@ static int pda_power_remove(struct platform_device *pdev)
                free_irq(ac_irq->start, pda_psy_ac);
 
        if (polling)
-               del_timer_sync(&polling_timer);
-       del_timer_sync(&charger_timer);
-       del_timer_sync(&supply_timer);
+               cancel_delayed_work_sync(&polling_work);
+       cancel_delayed_work_sync(&charger_work);
+       cancel_delayed_work_sync(&supply_work);
 
        if (pdata->is_usb_online)
                power_supply_unregister(pda_psy_usb);
index 1e0960b646e823caeb82bf9f10bd72ee36a687d4..7ec7c7c202bd1e95e3cff0c940f1a5b103dae326 100644 (file)
@@ -280,13 +280,19 @@ static inline int power_supply_check_supplies(struct power_supply *psy)
 }
 #endif
 
-static int __power_supply_am_i_supplied(struct device *dev, void *data)
+struct psy_am_i_supplied_data {
+       struct power_supply *psy;
+       unsigned int count;
+};
+
+static int __power_supply_am_i_supplied(struct device *dev, void *_data)
 {
        union power_supply_propval ret = {0,};
-       struct power_supply *psy = data;
        struct power_supply *epsy = dev_get_drvdata(dev);
+       struct psy_am_i_supplied_data *data = _data;
 
-       if (__power_supply_is_supplied_by(epsy, psy))
+       data->count++;
+       if (__power_supply_is_supplied_by(epsy, data->psy))
                if (!epsy->desc->get_property(epsy, POWER_SUPPLY_PROP_ONLINE,
                                        &ret))
                        return ret.intval;
@@ -296,12 +302,16 @@ static int __power_supply_am_i_supplied(struct device *dev, void *data)
 
 int power_supply_am_i_supplied(struct power_supply *psy)
 {
+       struct psy_am_i_supplied_data data = { psy, 0 };
        int error;
 
-       error = class_for_each_device(power_supply_class, NULL, psy,
+       error = class_for_each_device(power_supply_class, NULL, &data,
                                      __power_supply_am_i_supplied);
 
-       dev_dbg(&psy->dev, "%s %d\n", __func__, error);
+       dev_dbg(&psy->dev, "%s count %u err %d\n", __func__, data.count, error);
+
+       if (data.count == 0)
+               return -ENODEV;
 
        return error;
 }
index af9383d23d122e36b99efb8868f9c84790f17267..5654708b12790c1b608dae27cf4ed1e5ef392df1 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/platform_device.h>
 #include <linux/power_supply.h>
 #include <linux/slab.h>
-#include <linux/i2c/twl4030-madc.h>
 #include <linux/iio/consumer.h>
 #include <linux/of.h>
 
index 8bb2eb38eb1c872e7a50f7aa765c9c4c712c79f1..e3a114e60f1a3cac1c72bf72800cb859cae12254 100644 (file)
@@ -171,7 +171,6 @@ struct sbs_info {
        u32                             i2c_retry_count;
        u32                             poll_retry_count;
        struct delayed_work             work;
-       int                             ignore_changes;
 };
 
 static char model_name[I2C_SMBUS_BLOCK_MAX + 1];
@@ -296,6 +295,31 @@ static int sbs_write_word_data(struct i2c_client *client, u8 address,
        return 0;
 }
 
+static int sbs_status_correct(struct i2c_client *client, int *intval)
+{
+       int ret;
+
+       ret = sbs_read_word_data(client, sbs_data[REG_CURRENT].addr);
+       if (ret < 0)
+               return ret;
+
+       ret = (s16)ret;
+
+       /* Not drawing current means full (cannot be not charging) */
+       if (ret == 0)
+               *intval = POWER_SUPPLY_STATUS_FULL;
+
+       if (*intval == POWER_SUPPLY_STATUS_FULL) {
+               /* Drawing or providing current when full */
+               if (ret > 0)
+                       *intval = POWER_SUPPLY_STATUS_CHARGING;
+               else if (ret < 0)
+                       *intval = POWER_SUPPLY_STATUS_DISCHARGING;
+       }
+
+       return 0;
+}
+
 static int sbs_get_battery_presence_and_health(
        struct i2c_client *client, enum power_supply_property psp,
        union power_supply_propval *val)
@@ -402,6 +426,8 @@ static int sbs_get_battery_property(struct i2c_client *client,
                else
                        val->intval = POWER_SUPPLY_STATUS_CHARGING;
 
+               sbs_status_correct(client, &val->intval);
+
                if (chip->poll_time == 0)
                        chip->last_state = val->intval;
                else if (chip->last_state != val->intval) {
@@ -675,30 +701,34 @@ done:
        return 0;
 }
 
-static irqreturn_t sbs_irq(int irq, void *devid)
+static void sbs_supply_changed(struct sbs_info *chip)
 {
-       struct sbs_info *chip = devid;
        struct power_supply *battery = chip->power_supply;
        int ret;
 
        ret = gpiod_get_value_cansleep(chip->gpio_detect);
        if (ret < 0)
-               return ret;
+               return;
        chip->is_present = ret;
        power_supply_changed(battery);
+}
 
+static irqreturn_t sbs_irq(int irq, void *devid)
+{
+       sbs_supply_changed(devid);
        return IRQ_HANDLED;
 }
 
+static void sbs_alert(struct i2c_client *client, enum i2c_alert_protocol prot,
+       unsigned int data)
+{
+       sbs_supply_changed(i2c_get_clientdata(client));
+}
+
 static void sbs_external_power_changed(struct power_supply *psy)
 {
        struct sbs_info *chip = power_supply_get_drvdata(psy);
 
-       if (chip->ignore_changes > 0) {
-               chip->ignore_changes--;
-               return;
-       }
-
        /* cancel outstanding work */
        cancel_delayed_work_sync(&chip->work);
 
@@ -727,6 +757,8 @@ static void sbs_delayed_work(struct work_struct *work)
        else
                ret = POWER_SUPPLY_STATUS_CHARGING;
 
+       sbs_status_correct(chip->client, &ret);
+
        if (chip->last_state != ret) {
                chip->poll_time = 0;
                power_supply_changed(chip->power_supply);
@@ -775,10 +807,6 @@ static int sbs_probe(struct i2c_client *client,
        chip->enable_detection = false;
        psy_cfg.of_node = client->dev.of_node;
        psy_cfg.drv_data = chip;
-       /* ignore first notification of external change, it is generated
-        * from the power_supply_register call back
-        */
-       chip->ignore_changes = 1;
        chip->last_state = POWER_SUPPLY_STATUS_UNKNOWN;
 
        /* use pdata if available, fall back to DT properties,
@@ -820,7 +848,7 @@ static int sbs_probe(struct i2c_client *client,
        }
 
        rc = devm_request_threaded_irq(&client->dev, irq, NULL, sbs_irq,
-               IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+               IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
                dev_name(&client->dev), chip);
        if (rc) {
                dev_warn(&client->dev, "Failed to request irq: %d\n", rc);
@@ -917,6 +945,7 @@ MODULE_DEVICE_TABLE(of, sbs_dt_ids);
 static struct i2c_driver sbs_battery_driver = {
        .probe          = sbs_probe,
        .remove         = sbs_remove,
+       .alert          = sbs_alert,
        .id_table       = sbs_id,
        .driver = {
                .name   = "sbs-battery",
index 990ff3d218bcc7572bd1be15da7731fd36894736..2f82d0e9ec1bf7eaf879a57faa3b1da14303d99c 100644 (file)
@@ -205,35 +205,6 @@ static int twl4030bci_read_adc_val(u8 reg)
        return temp | val;
 }
 
-/*
- * Check if Battery Pack was present
- */
-static int twl4030_is_battery_present(struct twl4030_bci *bci)
-{
-       int ret;
-       u8 val = 0;
-
-       /* Battery presence in Main charge? */
-       ret = twl_i2c_read_u8(TWL_MODULE_MAIN_CHARGE, &val, TWL4030_BCIMFSTS3);
-       if (ret)
-               return ret;
-       if (val & TWL4030_BATSTSMCHG)
-               return 0;
-
-       /*
-        * OK, It could be that bootloader did not enable main charger,
-        * pre-charge is h/w auto. So, Battery presence in Pre-charge?
-        */
-       ret = twl_i2c_read_u8(TWL4030_MODULE_PRECHARGE, &val,
-                             TWL4030_BCIMFSTS1);
-       if (ret)
-               return ret;
-       if (val & TWL4030_BATSTSPCHG)
-               return 0;
-
-       return -ENODEV;
-}
-
 /*
  * TI provided formulas:
  * CGAIN == 0: ICHG = (BCIICHG * 1.7) / (2^10 - 1) - 0.85
@@ -922,6 +893,28 @@ static int twl4030_bci_get_property(struct power_supply *psy,
                        twl4030_bci_state_to_status(state) !=
                                POWER_SUPPLY_STATUS_NOT_CHARGING;
                break;
+       case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+               val->intval = -1;
+               if (psy->desc->type != POWER_SUPPLY_TYPE_USB) {
+                       if (!bci->ac_is_active)
+                               val->intval = bci->ac_cur;
+               } else {
+                       if (bci->ac_is_active)
+                               val->intval = bci->usb_cur_target;
+               }
+               if (val->intval < 0) {
+                       u8 bcictl1;
+
+                       val->intval = twl4030bci_read_adc_val(TWL4030_BCIIREF1);
+                       if (val->intval < 0)
+                               return val->intval;
+                       ret = twl4030_bci_read(TWL4030_BCICTL1, &bcictl1);
+                       if (ret < 0)
+                               return ret;
+                       val->intval = regval2ua(val->intval, bcictl1 &
+                                                       TWL4030_CGAIN);
+               }
+               break;
        default:
                return -EINVAL;
        }
@@ -929,11 +922,44 @@ static int twl4030_bci_get_property(struct power_supply *psy,
        return 0;
 }
 
+static int twl4030_bci_set_property(struct power_supply *psy,
+                                   enum power_supply_property psp,
+                                   const union power_supply_propval *val)
+{
+       struct twl4030_bci *bci = dev_get_drvdata(psy->dev.parent);
+
+       switch (psp) {
+       case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+               if (psy->desc->type == POWER_SUPPLY_TYPE_USB)
+                       bci->usb_cur_target = val->intval;
+               else
+                       bci->ac_cur = val->intval;
+               twl4030_charger_update_current(bci);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int twl4030_bci_property_is_writeable(struct power_supply *psy,
+                                     enum power_supply_property psp)
+{
+       switch (psp) {
+       case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT:
+               return true;
+       default:
+               return false;
+       }
+}
+
 static enum power_supply_property twl4030_charger_props[] = {
        POWER_SUPPLY_PROP_STATUS,
        POWER_SUPPLY_PROP_ONLINE,
        POWER_SUPPLY_PROP_VOLTAGE_NOW,
        POWER_SUPPLY_PROP_CURRENT_NOW,
+       POWER_SUPPLY_PROP_INPUT_CURRENT_LIMIT,
 };
 
 #ifdef CONFIG_OF
@@ -970,6 +996,8 @@ static const struct power_supply_desc twl4030_bci_ac_desc = {
        .properties     = twl4030_charger_props,
        .num_properties = ARRAY_SIZE(twl4030_charger_props),
        .get_property   = twl4030_bci_get_property,
+       .set_property   = twl4030_bci_set_property,
+       .property_is_writeable  = twl4030_bci_property_is_writeable,
 };
 
 static const struct power_supply_desc twl4030_bci_usb_desc = {
@@ -978,6 +1006,8 @@ static const struct power_supply_desc twl4030_bci_usb_desc = {
        .properties     = twl4030_charger_props,
        .num_properties = ARRAY_SIZE(twl4030_charger_props),
        .get_property   = twl4030_bci_get_property,
+       .set_property   = twl4030_bci_set_property,
+       .property_is_writeable  = twl4030_bci_property_is_writeable,
 };
 
 static int twl4030_bci_probe(struct platform_device *pdev)
@@ -1009,13 +1039,6 @@ static int twl4030_bci_probe(struct platform_device *pdev)
        bci->irq_chg = platform_get_irq(pdev, 0);
        bci->irq_bci = platform_get_irq(pdev, 1);
 
-       /* Only proceed further *IF* battery is physically present */
-       ret = twl4030_is_battery_present(bci);
-       if  (ret) {
-               dev_crit(&pdev->dev, "Battery was not detected:%d\n", ret);
-               return ret;
-       }
-
        platform_set_drvdata(pdev, bci);
 
        bci->ac = devm_power_supply_register(&pdev->dev, &twl4030_bci_ac_desc,
index f5817e422d6499aafc097791301092ce7d763751..4d41acb985761ad976f9de2b2cdc265a50fc9dea 100644 (file)
@@ -17,7 +17,6 @@
 #include <linux/power_supply.h>
 #include <linux/slab.h>
 #include <linux/sort.h>
-#include <linux/i2c/twl4030-madc.h>
 #include <linux/power/twl4030_madc_battery.h>
 #include <linux/iio/consumer.h>
 
index 9a25110c4a46bd3ac504d2bb6db65ac3bee156c5..9ddad0815ba909a7c77de8f93db06e7bc712d246 100644 (file)
@@ -1164,6 +1164,7 @@ static const struct x86_cpu_id rapl_ids[] __initconst = {
        RAPL_CPU(INTEL_FAM6_ATOM_MERRIFIELD,    rapl_defaults_tng),
        RAPL_CPU(INTEL_FAM6_ATOM_MOOREFIELD,    rapl_defaults_ann),
        RAPL_CPU(INTEL_FAM6_ATOM_GOLDMONT,      rapl_defaults_core),
+       RAPL_CPU(INTEL_FAM6_ATOM_GEMINI_LAKE,   rapl_defaults_core),
        RAPL_CPU(INTEL_FAM6_ATOM_DENVERTON,     rapl_defaults_core),
 
        RAPL_CPU(INTEL_FAM6_XEON_PHI_KNL,       rapl_defaults_hsw_server),
index 42e37c20b36178fc47c1e141f5658fe9ee249dfe..313c10789ca2e69b10f645a4399df290dc40920b 100644 (file)
@@ -293,6 +293,15 @@ config PWM_MTK_DISP
          To compile this driver as a module, choose M here: the module
          will be called pwm-mtk-disp.
 
+config PWM_MEDIATEK
+       tristate "MediaTek PWM support"
+       depends on ARCH_MEDIATEK || COMPILE_TEST
+       help
+         Generic PWM framework driver for Mediatek ARM SoC.
+
+         To compile this driver as a module, choose M here: the module
+         will be called pwm-mxs.
+
 config PWM_MXS
        tristate "Freescale MXS PWM support"
        depends on ARCH_MXS && OF
index 346a83b00f28f81124990c87d464b07f08af7844..93da1f79a3b8f818faee55d0221f4d34b3537797 100644 (file)
@@ -26,6 +26,7 @@ obj-$(CONFIG_PWM_LPSS)                += pwm-lpss.o
 obj-$(CONFIG_PWM_LPSS_PCI)     += pwm-lpss-pci.o
 obj-$(CONFIG_PWM_LPSS_PLATFORM)        += pwm-lpss-platform.o
 obj-$(CONFIG_PWM_MESON)                += pwm-meson.o
+obj-$(CONFIG_PWM_MEDIATEK)     += pwm-mediatek.o
 obj-$(CONFIG_PWM_MTK_DISP)     += pwm-mtk-disp.o
 obj-$(CONFIG_PWM_MXS)          += pwm-mxs.o
 obj-$(CONFIG_PWM_OMAP_DMTIMER) += pwm-omap-dmtimer.o
index 999187277ea56fd603993680a8c7f8ecb9effd15..54c6633d9b5d0576f09ee8be54a1b72324171e73 100644 (file)
@@ -49,172 +49,181 @@ static inline struct atmel_hlcdc_pwm *to_atmel_hlcdc_pwm(struct pwm_chip *chip)
        return container_of(chip, struct atmel_hlcdc_pwm, chip);
 }
 
-static int atmel_hlcdc_pwm_config(struct pwm_chip *c,
-                                 struct pwm_device *pwm,
-                                 int duty_ns, int period_ns)
+static int atmel_hlcdc_pwm_apply(struct pwm_chip *c, struct pwm_device *pwm,
+                                struct pwm_state *state)
 {
        struct atmel_hlcdc_pwm *chip = to_atmel_hlcdc_pwm(c);
        struct atmel_hlcdc *hlcdc = chip->hlcdc;
-       struct clk *new_clk = hlcdc->slow_clk;
-       u64 pwmcval = duty_ns * 256;
-       unsigned long clk_freq;
-       u64 clk_period_ns;
-       u32 pwmcfg;
-       int pres;
-
-       if (!chip->errata || !chip->errata->slow_clk_erratum) {
-               clk_freq = clk_get_rate(new_clk);
-               if (!clk_freq)
-                       return -EINVAL;
+       unsigned int status;
+       int ret;
 
-               clk_period_ns = (u64)NSEC_PER_SEC * 256;
-               do_div(clk_period_ns, clk_freq);
-       }
+       if (state->enabled) {
+               struct clk *new_clk = hlcdc->slow_clk;
+               u64 pwmcval = state->duty_cycle * 256;
+               unsigned long clk_freq;
+               u64 clk_period_ns;
+               u32 pwmcfg;
+               int pres;
+
+               if (!chip->errata || !chip->errata->slow_clk_erratum) {
+                       clk_freq = clk_get_rate(new_clk);
+                       if (!clk_freq)
+                               return -EINVAL;
+
+                       clk_period_ns = (u64)NSEC_PER_SEC * 256;
+                       do_div(clk_period_ns, clk_freq);
+               }
+
+               /* Errata: cannot use slow clk on some IP revisions */
+               if ((chip->errata && chip->errata->slow_clk_erratum) ||
+                   clk_period_ns > state->period) {
+                       new_clk = hlcdc->sys_clk;
+                       clk_freq = clk_get_rate(new_clk);
+                       if (!clk_freq)
+                               return -EINVAL;
+
+                       clk_period_ns = (u64)NSEC_PER_SEC * 256;
+                       do_div(clk_period_ns, clk_freq);
+               }
+
+               for (pres = 0; pres <= ATMEL_HLCDC_PWMPS_MAX; pres++) {
+               /* Errata: cannot divide by 1 on some IP revisions */
+                       if (!pres && chip->errata &&
+                           chip->errata->div1_clk_erratum)
+                               continue;
+
+                       if ((clk_period_ns << pres) >= state->period)
+                               break;
+               }
 
-       /* Errata: cannot use slow clk on some IP revisions */
-       if ((chip->errata && chip->errata->slow_clk_erratum) ||
-           clk_period_ns > period_ns) {
-               new_clk = hlcdc->sys_clk;
-               clk_freq = clk_get_rate(new_clk);
-               if (!clk_freq)
+               if (pres > ATMEL_HLCDC_PWMPS_MAX)
                        return -EINVAL;
 
-               clk_period_ns = (u64)NSEC_PER_SEC * 256;
-               do_div(clk_period_ns, clk_freq);
-       }
+               pwmcfg = ATMEL_HLCDC_PWMPS(pres);
 
-       for (pres = 0; pres <= ATMEL_HLCDC_PWMPS_MAX; pres++) {
-               /* Errata: cannot divide by 1 on some IP revisions */
-               if (!pres && chip->errata && chip->errata->div1_clk_erratum)
-                       continue;
+               if (new_clk != chip->cur_clk) {
+                       u32 gencfg = 0;
+                       int ret;
 
-               if ((clk_period_ns << pres) >= period_ns)
-                       break;
-       }
+                       ret = clk_prepare_enable(new_clk);
+                       if (ret)
+                               return ret;
 
-       if (pres > ATMEL_HLCDC_PWMPS_MAX)
-               return -EINVAL;
+                       clk_disable_unprepare(chip->cur_clk);
+                       chip->cur_clk = new_clk;
 
-       pwmcfg = ATMEL_HLCDC_PWMPS(pres);
+                       if (new_clk == hlcdc->sys_clk)
+                               gencfg = ATMEL_HLCDC_CLKPWMSEL;
 
-       if (new_clk != chip->cur_clk) {
-               u32 gencfg = 0;
-               int ret;
+                       ret = regmap_update_bits(hlcdc->regmap,
+                                                ATMEL_HLCDC_CFG(0),
+                                                ATMEL_HLCDC_CLKPWMSEL,
+                                                gencfg);
+                       if (ret)
+                               return ret;
+               }
 
-               ret = clk_prepare_enable(new_clk);
-               if (ret)
-                       return ret;
+               do_div(pwmcval, state->period);
 
-               clk_disable_unprepare(chip->cur_clk);
-               chip->cur_clk = new_clk;
+               /*
+                * The PWM duty cycle is configurable from 0/256 to 255/256 of
+                * the period cycle. Hence we can't set a duty cycle occupying
+                * the whole period cycle if we're asked to.
+                * Set it to 255 if pwmcval is greater than 256.
+                */
+               if (pwmcval > 255)
+                       pwmcval = 255;
 
-               if (new_clk == hlcdc->sys_clk)
-                       gencfg = ATMEL_HLCDC_CLKPWMSEL;
+               pwmcfg |= ATMEL_HLCDC_PWMCVAL(pwmcval);
 
-               ret = regmap_update_bits(hlcdc->regmap, ATMEL_HLCDC_CFG(0),
-                                        ATMEL_HLCDC_CLKPWMSEL, gencfg);
+               if (state->polarity == PWM_POLARITY_NORMAL)
+                       pwmcfg |= ATMEL_HLCDC_PWMPOL;
+
+               ret = regmap_update_bits(hlcdc->regmap, ATMEL_HLCDC_CFG(6),
+                                        ATMEL_HLCDC_PWMCVAL_MASK |
+                                        ATMEL_HLCDC_PWMPS_MASK |
+                                        ATMEL_HLCDC_PWMPOL,
+                                        pwmcfg);
                if (ret)
                        return ret;
-       }
 
-       do_div(pwmcval, period_ns);
-
-       /*
-        * The PWM duty cycle is configurable from 0/256 to 255/256 of the
-        * period cycle. Hence we can't set a duty cycle occupying the
-        * whole period cycle if we're asked to.
-        * Set it to 255 if pwmcval is greater than 256.
-        */
-       if (pwmcval > 255)
-               pwmcval = 255;
-
-       pwmcfg |= ATMEL_HLCDC_PWMCVAL(pwmcval);
+               ret = regmap_write(hlcdc->regmap, ATMEL_HLCDC_EN,
+                                  ATMEL_HLCDC_PWM);
+               if (ret)
+                       return ret;
 
-       return regmap_update_bits(hlcdc->regmap, ATMEL_HLCDC_CFG(6),
-                                 ATMEL_HLCDC_PWMCVAL_MASK |
-                                 ATMEL_HLCDC_PWMPS_MASK,
-                                 pwmcfg);
-}
+               ret = regmap_read_poll_timeout(hlcdc->regmap, ATMEL_HLCDC_SR,
+                                              status,
+                                              status & ATMEL_HLCDC_PWM,
+                                              10, 0);
+               if (ret)
+                       return ret;
+       } else {
+               ret = regmap_write(hlcdc->regmap, ATMEL_HLCDC_DIS,
+                                  ATMEL_HLCDC_PWM);
+               if (ret)
+                       return ret;
 
-static int atmel_hlcdc_pwm_set_polarity(struct pwm_chip *c,
-                                       struct pwm_device *pwm,
-                                       enum pwm_polarity polarity)
-{
-       struct atmel_hlcdc_pwm *chip = to_atmel_hlcdc_pwm(c);
-       struct atmel_hlcdc *hlcdc = chip->hlcdc;
-       u32 cfg = 0;
+               ret = regmap_read_poll_timeout(hlcdc->regmap, ATMEL_HLCDC_SR,
+                                              status,
+                                              !(status & ATMEL_HLCDC_PWM),
+                                              10, 0);
+               if (ret)
+                       return ret;
 
-       if (polarity == PWM_POLARITY_NORMAL)
-               cfg = ATMEL_HLCDC_PWMPOL;
+               clk_disable_unprepare(chip->cur_clk);
+               chip->cur_clk = NULL;
+       }
 
-       return regmap_update_bits(hlcdc->regmap, ATMEL_HLCDC_CFG(6),
-                                 ATMEL_HLCDC_PWMPOL, cfg);
+       return 0;
 }
 
-static int atmel_hlcdc_pwm_enable(struct pwm_chip *c, struct pwm_device *pwm)
-{
-       struct atmel_hlcdc_pwm *chip = to_atmel_hlcdc_pwm(c);
-       struct atmel_hlcdc *hlcdc = chip->hlcdc;
-       u32 status;
-       int ret;
+static const struct pwm_ops atmel_hlcdc_pwm_ops = {
+       .apply = atmel_hlcdc_pwm_apply,
+       .owner = THIS_MODULE,
+};
 
-       ret = regmap_write(hlcdc->regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_PWM);
-       if (ret)
-               return ret;
+static const struct atmel_hlcdc_pwm_errata atmel_hlcdc_pwm_at91sam9x5_errata = {
+       .slow_clk_erratum = true,
+};
 
-       while (true) {
-               ret = regmap_read(hlcdc->regmap, ATMEL_HLCDC_SR, &status);
-               if (ret)
-                       return ret;
+static const struct atmel_hlcdc_pwm_errata atmel_hlcdc_pwm_sama5d3_errata = {
+       .div1_clk_erratum = true,
+};
 
-               if ((status & ATMEL_HLCDC_PWM) != 0)
-                       break;
+#ifdef CONFIG_PM_SLEEP
+static int atmel_hlcdc_pwm_suspend(struct device *dev)
+{
+       struct atmel_hlcdc_pwm *chip = dev_get_drvdata(dev);
 
-               usleep_range(1, 10);
-       }
+       /* Keep the periph clock enabled if the PWM is still running. */
+       if (pwm_is_enabled(&chip->chip.pwms[0]))
+               clk_disable_unprepare(chip->hlcdc->periph_clk);
 
        return 0;
 }
 
-static void atmel_hlcdc_pwm_disable(struct pwm_chip *c,
-                                   struct pwm_device *pwm)
+static int atmel_hlcdc_pwm_resume(struct device *dev)
 {
-       struct atmel_hlcdc_pwm *chip = to_atmel_hlcdc_pwm(c);
-       struct atmel_hlcdc *hlcdc = chip->hlcdc;
-       u32 status;
+       struct atmel_hlcdc_pwm *chip = dev_get_drvdata(dev);
+       struct pwm_state state;
        int ret;
 
-       ret = regmap_write(hlcdc->regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_PWM);
-       if (ret)
-               return;
+       pwm_get_state(&chip->chip.pwms[0], &state);
 
-       while (true) {
-               ret = regmap_read(hlcdc->regmap, ATMEL_HLCDC_SR, &status);
+       /* Re-enable the periph clock it was stopped during suspend. */
+       if (!state.enabled) {
+               ret = clk_prepare_enable(chip->hlcdc->periph_clk);
                if (ret)
-                       return;
-
-               if ((status & ATMEL_HLCDC_PWM) == 0)
-                       break;
-
-               usleep_range(1, 10);
+                       return ret;
        }
-}
-
-static const struct pwm_ops atmel_hlcdc_pwm_ops = {
-       .config = atmel_hlcdc_pwm_config,
-       .set_polarity = atmel_hlcdc_pwm_set_polarity,
-       .enable = atmel_hlcdc_pwm_enable,
-       .disable = atmel_hlcdc_pwm_disable,
-       .owner = THIS_MODULE,
-};
 
-static const struct atmel_hlcdc_pwm_errata atmel_hlcdc_pwm_at91sam9x5_errata = {
-       .slow_clk_erratum = true,
-};
+       return atmel_hlcdc_pwm_apply(&chip->chip, &chip->chip.pwms[0], &state);
+}
+#endif
 
-static const struct atmel_hlcdc_pwm_errata atmel_hlcdc_pwm_sama5d3_errata = {
-       .div1_clk_erratum = true,
-};
+static SIMPLE_DEV_PM_OPS(atmel_hlcdc_pwm_pm_ops,
+                        atmel_hlcdc_pwm_suspend, atmel_hlcdc_pwm_resume);
 
 static const struct of_device_id atmel_hlcdc_dt_ids[] = {
        {
@@ -305,6 +314,7 @@ static struct platform_driver atmel_hlcdc_pwm_driver = {
        .driver = {
                .name = "atmel-hlcdc-pwm",
                .of_match_table = atmel_hlcdc_pwm_dt_ids,
+               .pm = &atmel_hlcdc_pwm_pm_ops,
        },
        .probe = atmel_hlcdc_pwm_probe,
        .remove = atmel_hlcdc_pwm_remove,
index 67a7023be5c2b54bb35eb70eb94be07aaa471432..530d7dc5f1b5cdad7d10d6c9c675ffc3e1430b3a 100644 (file)
 #define PWM_MAX_PRD            0xFFFF
 #define PRD_MAX_PRES           10
 
+struct atmel_pwm_registers {
+       u8 period;
+       u8 period_upd;
+       u8 duty;
+       u8 duty_upd;
+};
+
 struct atmel_pwm_chip {
        struct pwm_chip chip;
        struct clk *clk;
        void __iomem *base;
+       const struct atmel_pwm_registers *regs;
 
        unsigned int updated_pwms;
        /* ISR is cleared when read, ensure only one thread does that */
        struct mutex isr_lock;
-
-       void (*config)(struct pwm_chip *chip, struct pwm_device *pwm,
-                      unsigned long dty, unsigned long prd);
 };
 
 static inline struct atmel_pwm_chip *to_atmel_pwm_chip(struct pwm_chip *chip)
@@ -105,153 +110,71 @@ static inline void atmel_pwm_ch_writel(struct atmel_pwm_chip *chip,
        writel_relaxed(val, chip->base + base + offset);
 }
 
-static int atmel_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
-                           int duty_ns, int period_ns)
+static int atmel_pwm_calculate_cprd_and_pres(struct pwm_chip *chip,
+                                            const struct pwm_state *state,
+                                            unsigned long *cprd, u32 *pres)
 {
        struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
-       unsigned long prd, dty;
-       unsigned long long div;
-       unsigned int pres = 0;
-       u32 val;
-       int ret;
-
-       if (pwm_is_enabled(pwm) && (period_ns != pwm_get_period(pwm))) {
-               dev_err(chip->dev, "cannot change PWM period while enabled\n");
-               return -EBUSY;
-       }
+       unsigned long long cycles = state->period;
 
        /* Calculate the period cycles and prescale value */
-       div = (unsigned long long)clk_get_rate(atmel_pwm->clk) * period_ns;
-       do_div(div, NSEC_PER_SEC);
+       cycles *= clk_get_rate(atmel_pwm->clk);
+       do_div(cycles, NSEC_PER_SEC);
 
-       while (div > PWM_MAX_PRD) {
-               div >>= 1;
-               pres++;
-       }
+       for (*pres = 0; cycles > PWM_MAX_PRD; cycles >>= 1)
+               (*pres)++;
 
-       if (pres > PRD_MAX_PRES) {
+       if (*pres > PRD_MAX_PRES) {
                dev_err(chip->dev, "pres exceeds the maximum value\n");
                return -EINVAL;
        }
 
-       /* Calculate the duty cycles */
-       prd = div;
-       div *= duty_ns;
-       do_div(div, period_ns);
-       dty = prd - div;
-
-       ret = clk_enable(atmel_pwm->clk);
-       if (ret) {
-               dev_err(chip->dev, "failed to enable PWM clock\n");
-               return ret;
-       }
-
-       /* It is necessary to preserve CPOL, inside CMR */
-       val = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, PWM_CMR);
-       val = (val & ~PWM_CMR_CPRE_MSK) | (pres & PWM_CMR_CPRE_MSK);
-       atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWM_CMR, val);
-       atmel_pwm->config(chip, pwm, dty, prd);
-       mutex_lock(&atmel_pwm->isr_lock);
-       atmel_pwm->updated_pwms |= atmel_pwm_readl(atmel_pwm, PWM_ISR);
-       atmel_pwm->updated_pwms &= ~(1 << pwm->hwpwm);
-       mutex_unlock(&atmel_pwm->isr_lock);
-
-       clk_disable(atmel_pwm->clk);
-       return ret;
-}
-
-static void atmel_pwm_config_v1(struct pwm_chip *chip, struct pwm_device *pwm,
-                               unsigned long dty, unsigned long prd)
-{
-       struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
-       unsigned int val;
-
+       *cprd = cycles;
 
-       atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV1_CUPD, dty);
-
-       val = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, PWM_CMR);
-       val &= ~PWM_CMR_UPD_CDTY;
-       atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWM_CMR, val);
-
-       /*
-        * If the PWM channel is enabled, only update CDTY by using the update
-        * register, it needs to set bit 10 of CMR to 0
-        */
-       if (pwm_is_enabled(pwm))
-               return;
-       /*
-        * If the PWM channel is disabled, write value to duty and period
-        * registers directly.
-        */
-       atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV1_CDTY, dty);
-       atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV1_CPRD, prd);
+       return 0;
 }
 
-static void atmel_pwm_config_v2(struct pwm_chip *chip, struct pwm_device *pwm,
-                               unsigned long dty, unsigned long prd)
+static void atmel_pwm_calculate_cdty(const struct pwm_state *state,
+                                    unsigned long cprd, unsigned long *cdty)
 {
-       struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
+       unsigned long long cycles = state->duty_cycle;
 
-       if (pwm_is_enabled(pwm)) {
-               /*
-                * If the PWM channel is enabled, using the duty update register
-                * to update the value.
-                */
-               atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV2_CDTYUPD, dty);
-       } else {
-               /*
-                * If the PWM channel is disabled, write value to duty and
-                * period registers directly.
-                */
-               atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV2_CDTY, dty);
-               atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWMV2_CPRD, prd);
-       }
+       cycles *= cprd;
+       do_div(cycles, state->period);
+       *cdty = cprd - cycles;
 }
 
-static int atmel_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm,
-                                 enum pwm_polarity polarity)
+static void atmel_pwm_update_cdty(struct pwm_chip *chip, struct pwm_device *pwm,
+                                 unsigned long cdty)
 {
        struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
        u32 val;
-       int ret;
-
-       val = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, PWM_CMR);
 
-       if (polarity == PWM_POLARITY_NORMAL)
-               val &= ~PWM_CMR_CPOL;
-       else
-               val |= PWM_CMR_CPOL;
-
-       ret = clk_enable(atmel_pwm->clk);
-       if (ret) {
-               dev_err(chip->dev, "failed to enable PWM clock\n");
-               return ret;
+       if (atmel_pwm->regs->duty_upd ==
+           atmel_pwm->regs->period_upd) {
+               val = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, PWM_CMR);
+               val &= ~PWM_CMR_UPD_CDTY;
+               atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWM_CMR, val);
        }
 
-       atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWM_CMR, val);
-
-       clk_disable(atmel_pwm->clk);
-
-       return 0;
+       atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm,
+                           atmel_pwm->regs->duty_upd, cdty);
 }
 
-static int atmel_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+static void atmel_pwm_set_cprd_cdty(struct pwm_chip *chip,
+                                   struct pwm_device *pwm,
+                                   unsigned long cprd, unsigned long cdty)
 {
        struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
-       int ret;
-
-       ret = clk_enable(atmel_pwm->clk);
-       if (ret) {
-               dev_err(chip->dev, "failed to enable PWM clock\n");
-               return ret;
-       }
 
-       atmel_pwm_writel(atmel_pwm, PWM_ENA, 1 << pwm->hwpwm);
-
-       return 0;
+       atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm,
+                           atmel_pwm->regs->duty, cdty);
+       atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm,
+                           atmel_pwm->regs->period, cprd);
 }
 
-static void atmel_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+static void atmel_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm,
+                             bool disable_clk)
 {
        struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
        unsigned long timeout = jiffies + 2 * HZ;
@@ -282,37 +205,99 @@ static void atmel_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
               time_before(jiffies, timeout))
                usleep_range(10, 100);
 
-       clk_disable(atmel_pwm->clk);
+       if (disable_clk)
+               clk_disable(atmel_pwm->clk);
+}
+
+static int atmel_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+                          struct pwm_state *state)
+{
+       struct atmel_pwm_chip *atmel_pwm = to_atmel_pwm_chip(chip);
+       struct pwm_state cstate;
+       unsigned long cprd, cdty;
+       u32 pres, val;
+       int ret;
+
+       pwm_get_state(pwm, &cstate);
+
+       if (state->enabled) {
+               if (cstate.enabled &&
+                   cstate.polarity == state->polarity &&
+                   cstate.period == state->period) {
+                       cprd = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm,
+                                                 atmel_pwm->regs->period);
+                       atmel_pwm_calculate_cdty(state, cprd, &cdty);
+                       atmel_pwm_update_cdty(chip, pwm, cdty);
+                       return 0;
+               }
+
+               ret = atmel_pwm_calculate_cprd_and_pres(chip, state, &cprd,
+                                                       &pres);
+               if (ret) {
+                       dev_err(chip->dev,
+                               "failed to calculate cprd and prescaler\n");
+                       return ret;
+               }
+
+               atmel_pwm_calculate_cdty(state, cprd, &cdty);
+
+               if (cstate.enabled) {
+                       atmel_pwm_disable(chip, pwm, false);
+               } else {
+                       ret = clk_enable(atmel_pwm->clk);
+                       if (ret) {
+                               dev_err(chip->dev, "failed to enable clock\n");
+                               return ret;
+                       }
+               }
+
+               /* It is necessary to preserve CPOL, inside CMR */
+               val = atmel_pwm_ch_readl(atmel_pwm, pwm->hwpwm, PWM_CMR);
+               val = (val & ~PWM_CMR_CPRE_MSK) | (pres & PWM_CMR_CPRE_MSK);
+               if (state->polarity == PWM_POLARITY_NORMAL)
+                       val &= ~PWM_CMR_CPOL;
+               else
+                       val |= PWM_CMR_CPOL;
+               atmel_pwm_ch_writel(atmel_pwm, pwm->hwpwm, PWM_CMR, val);
+               atmel_pwm_set_cprd_cdty(chip, pwm, cprd, cdty);
+               mutex_lock(&atmel_pwm->isr_lock);
+               atmel_pwm->updated_pwms |= atmel_pwm_readl(atmel_pwm, PWM_ISR);
+               atmel_pwm->updated_pwms &= ~(1 << pwm->hwpwm);
+               mutex_unlock(&atmel_pwm->isr_lock);
+               atmel_pwm_writel(atmel_pwm, PWM_ENA, 1 << pwm->hwpwm);
+       } else if (cstate.enabled) {
+               atmel_pwm_disable(chip, pwm, true);
+       }
+
+       return 0;
 }
 
 static const struct pwm_ops atmel_pwm_ops = {
-       .config = atmel_pwm_config,
-       .set_polarity = atmel_pwm_set_polarity,
-       .enable = atmel_pwm_enable,
-       .disable = atmel_pwm_disable,
+       .apply = atmel_pwm_apply,
        .owner = THIS_MODULE,
 };
 
-struct atmel_pwm_data {
-       void (*config)(struct pwm_chip *chip, struct pwm_device *pwm,
-                      unsigned long dty, unsigned long prd);
+static const struct atmel_pwm_registers atmel_pwm_regs_v1 = {
+       .period         = PWMV1_CPRD,
+       .period_upd     = PWMV1_CUPD,
+       .duty           = PWMV1_CDTY,
+       .duty_upd       = PWMV1_CUPD,
 };
 
-static const struct atmel_pwm_data atmel_pwm_data_v1 = {
-       .config = atmel_pwm_config_v1,
-};
-
-static const struct atmel_pwm_data atmel_pwm_data_v2 = {
-       .config = atmel_pwm_config_v2,
+static const struct atmel_pwm_registers atmel_pwm_regs_v2 = {
+       .period         = PWMV2_CPRD,
+       .period_upd     = PWMV2_CPRDUPD,
+       .duty           = PWMV2_CDTY,
+       .duty_upd       = PWMV2_CDTYUPD,
 };
 
 static const struct platform_device_id atmel_pwm_devtypes[] = {
        {
                .name = "at91sam9rl-pwm",
-               .driver_data = (kernel_ulong_t)&atmel_pwm_data_v1,
+               .driver_data = (kernel_ulong_t)&atmel_pwm_regs_v1,
        }, {
                .name = "sama5d3-pwm",
-               .driver_data = (kernel_ulong_t)&atmel_pwm_data_v2,
+               .driver_data = (kernel_ulong_t)&atmel_pwm_regs_v2,
        }, {
                /* sentinel */
        },
@@ -322,17 +307,20 @@ MODULE_DEVICE_TABLE(platform, atmel_pwm_devtypes);
 static const struct of_device_id atmel_pwm_dt_ids[] = {
        {
                .compatible = "atmel,at91sam9rl-pwm",
-               .data = &atmel_pwm_data_v1,
+               .data = &atmel_pwm_regs_v1,
        }, {
                .compatible = "atmel,sama5d3-pwm",
-               .data = &atmel_pwm_data_v2,
+               .data = &atmel_pwm_regs_v2,
+       }, {
+               .compatible = "atmel,sama5d2-pwm",
+               .data = &atmel_pwm_regs_v2,
        }, {
                /* sentinel */
        },
 };
 MODULE_DEVICE_TABLE(of, atmel_pwm_dt_ids);
 
-static inline const struct atmel_pwm_data *
+static inline const struct atmel_pwm_registers *
 atmel_pwm_get_driver_data(struct platform_device *pdev)
 {
        const struct platform_device_id *id;
@@ -342,18 +330,18 @@ atmel_pwm_get_driver_data(struct platform_device *pdev)
 
        id = platform_get_device_id(pdev);
 
-       return (struct atmel_pwm_data *)id->driver_data;
+       return (struct atmel_pwm_registers *)id->driver_data;
 }
 
 static int atmel_pwm_probe(struct platform_device *pdev)
 {
-       const struct atmel_pwm_data *data;
+       const struct atmel_pwm_registers *regs;
        struct atmel_pwm_chip *atmel_pwm;
        struct resource *res;
        int ret;
 
-       data = atmel_pwm_get_driver_data(pdev);
-       if (!data)
+       regs = atmel_pwm_get_driver_data(pdev);
+       if (!regs)
                return -ENODEV;
 
        atmel_pwm = devm_kzalloc(&pdev->dev, sizeof(*atmel_pwm), GFP_KERNEL);
@@ -385,7 +373,7 @@ static int atmel_pwm_probe(struct platform_device *pdev)
 
        atmel_pwm->chip.base = -1;
        atmel_pwm->chip.npwm = 4;
-       atmel_pwm->config = data->config;
+       atmel_pwm->regs = regs;
        atmel_pwm->updated_pwms = 0;
        mutex_init(&atmel_pwm->isr_lock);
 
diff --git a/drivers/pwm/pwm-mediatek.c b/drivers/pwm/pwm-mediatek.c
new file mode 100644 (file)
index 0000000..5c11bc7
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * Mediatek Pulse Width Modulator driver
+ *
+ * Copyright (C) 2015 John Crispin <blogic@openwrt.org>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+/* PWM registers and bits definitions */
+#define PWMCON                 0x00
+#define PWMHDUR                        0x04
+#define PWMLDUR                        0x08
+#define PWMGDUR                        0x0c
+#define PWMWAVENUM             0x28
+#define PWMDWIDTH              0x2c
+#define PWMTHRES               0x30
+
+enum {
+       MTK_CLK_MAIN = 0,
+       MTK_CLK_TOP,
+       MTK_CLK_PWM1,
+       MTK_CLK_PWM2,
+       MTK_CLK_PWM3,
+       MTK_CLK_PWM4,
+       MTK_CLK_PWM5,
+       MTK_CLK_MAX,
+};
+
+static const char * const mtk_pwm_clk_name[] = {
+       "main", "top", "pwm1", "pwm2", "pwm3", "pwm4", "pwm5"
+};
+
+/**
+ * struct mtk_pwm_chip - struct representing PWM chip
+ * @chip: linux PWM chip representation
+ * @regs: base address of PWM chip
+ * @clks: list of clocks
+ */
+struct mtk_pwm_chip {
+       struct pwm_chip chip;
+       void __iomem *regs;
+       struct clk *clks[MTK_CLK_MAX];
+};
+
+static inline struct mtk_pwm_chip *to_mtk_pwm_chip(struct pwm_chip *chip)
+{
+       return container_of(chip, struct mtk_pwm_chip, chip);
+}
+
+static inline u32 mtk_pwm_readl(struct mtk_pwm_chip *chip, unsigned int num,
+                               unsigned int offset)
+{
+       return readl(chip->regs + 0x10 + (num * 0x40) + offset);
+}
+
+static inline void mtk_pwm_writel(struct mtk_pwm_chip *chip,
+                                 unsigned int num, unsigned int offset,
+                                 u32 value)
+{
+       writel(value, chip->regs + 0x10 + (num * 0x40) + offset);
+}
+
+static int mtk_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
+                         int duty_ns, int period_ns)
+{
+       struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip);
+       struct clk *clk = pc->clks[MTK_CLK_PWM1 + pwm->hwpwm];
+       u32 resolution, clkdiv = 0;
+
+       resolution = NSEC_PER_SEC / clk_get_rate(clk);
+
+       while (period_ns / resolution > 8191) {
+               resolution *= 2;
+               clkdiv++;
+       }
+
+       if (clkdiv > 7)
+               return -EINVAL;
+
+       mtk_pwm_writel(pc, pwm->hwpwm, PWMCON, BIT(15) | BIT(3) | clkdiv);
+       mtk_pwm_writel(pc, pwm->hwpwm, PWMDWIDTH, period_ns / resolution);
+       mtk_pwm_writel(pc, pwm->hwpwm, PWMTHRES, duty_ns / resolution);
+
+       return 0;
+}
+
+static int mtk_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+       struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip);
+       u32 value;
+       int ret;
+
+       ret = clk_prepare(pc->clks[MTK_CLK_PWM1 + pwm->hwpwm]);
+       if (ret < 0)
+               return ret;
+
+       value = readl(pc->regs);
+       value |= BIT(pwm->hwpwm);
+       writel(value, pc->regs);
+
+       return 0;
+}
+
+static void mtk_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
+{
+       struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip);
+       u32 value;
+
+       value = readl(pc->regs);
+       value &= ~BIT(pwm->hwpwm);
+       writel(value, pc->regs);
+
+       clk_unprepare(pc->clks[MTK_CLK_PWM1 + pwm->hwpwm]);
+}
+
+static const struct pwm_ops mtk_pwm_ops = {
+       .config = mtk_pwm_config,
+       .enable = mtk_pwm_enable,
+       .disable = mtk_pwm_disable,
+       .owner = THIS_MODULE,
+};
+
+static int mtk_pwm_probe(struct platform_device *pdev)
+{
+       struct mtk_pwm_chip *pc;
+       struct resource *res;
+       unsigned int i;
+       int ret;
+
+       pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL);
+       if (!pc)
+               return -ENOMEM;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       pc->regs = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(pc->regs))
+               return PTR_ERR(pc->regs);
+
+       for (i = 0; i < MTK_CLK_MAX; i++) {
+               pc->clks[i] = devm_clk_get(&pdev->dev, mtk_pwm_clk_name[i]);
+               if (IS_ERR(pc->clks[i]))
+                       return PTR_ERR(pc->clks[i]);
+       }
+
+       ret = clk_prepare(pc->clks[MTK_CLK_TOP]);
+       if (ret < 0)
+               return ret;
+
+       ret = clk_prepare(pc->clks[MTK_CLK_MAIN]);
+       if (ret < 0)
+               goto disable_clk_top;
+
+       platform_set_drvdata(pdev, pc);
+
+       pc->chip.dev = &pdev->dev;
+       pc->chip.ops = &mtk_pwm_ops;
+       pc->chip.base = -1;
+       pc->chip.npwm = 5;
+
+       ret = pwmchip_add(&pc->chip);
+       if (ret < 0) {
+               dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret);
+               goto disable_clk_main;
+       }
+
+       return 0;
+
+disable_clk_main:
+       clk_unprepare(pc->clks[MTK_CLK_MAIN]);
+disable_clk_top:
+       clk_unprepare(pc->clks[MTK_CLK_TOP]);
+
+       return ret;
+}
+
+static int mtk_pwm_remove(struct platform_device *pdev)
+{
+       struct mtk_pwm_chip *pc = platform_get_drvdata(pdev);
+       unsigned int i;
+
+       for (i = 0; i < pc->chip.npwm; i++)
+               pwm_disable(&pc->chip.pwms[i]);
+
+       return pwmchip_remove(&pc->chip);
+}
+
+static const struct of_device_id mtk_pwm_of_match[] = {
+       { .compatible = "mediatek,mt7623-pwm" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, mtk_pwm_of_match);
+
+static struct platform_driver mtk_pwm_driver = {
+       .driver = {
+               .name = "mtk-pwm",
+               .of_match_table = mtk_pwm_of_match,
+       },
+       .probe = mtk_pwm_probe,
+       .remove = mtk_pwm_remove,
+};
+module_platform_driver(mtk_pwm_driver);
+
+MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
+MODULE_ALIAS("platform:mtk-pwm");
+MODULE_LICENSE("GPL");
index 0cfb3571a7325519cb5aec77ce16bf71921b6846..5f55cfab9b1c235ca3b7e63582398ddc2fc53f04 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/regmap.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
+#include <linux/pm_runtime.h>
 
 /*
  * Because the PCA9685 has only one prescaler per chip, changing the period of
@@ -79,7 +80,6 @@
 struct pca9685 {
        struct pwm_chip chip;
        struct regmap *regmap;
-       int active_cnt;
        int duty_ns;
        int period_ns;
 #if IS_ENABLED(CONFIG_GPIOLIB)
@@ -111,20 +111,10 @@ static int pca9685_pwm_gpio_request(struct gpio_chip *gpio, unsigned int offset)
        pwm_set_chip_data(pwm, (void *)1);
 
        mutex_unlock(&pca->lock);
+       pm_runtime_get_sync(pca->chip.dev);
        return 0;
 }
 
-static void pca9685_pwm_gpio_free(struct gpio_chip *gpio, unsigned int offset)
-{
-       struct pca9685 *pca = gpiochip_get_data(gpio);
-       struct pwm_device *pwm;
-
-       mutex_lock(&pca->lock);
-       pwm = &pca->chip.pwms[offset];
-       pwm_set_chip_data(pwm, NULL);
-       mutex_unlock(&pca->lock);
-}
-
 static bool pca9685_pwm_is_gpio(struct pca9685 *pca, struct pwm_device *pwm)
 {
        bool is_gpio = false;
@@ -177,6 +167,19 @@ static void pca9685_pwm_gpio_set(struct gpio_chip *gpio, unsigned int offset,
        regmap_write(pca->regmap, LED_N_ON_H(pwm->hwpwm), on);
 }
 
+static void pca9685_pwm_gpio_free(struct gpio_chip *gpio, unsigned int offset)
+{
+       struct pca9685 *pca = gpiochip_get_data(gpio);
+       struct pwm_device *pwm;
+
+       pca9685_pwm_gpio_set(gpio, offset, 0);
+       pm_runtime_put(pca->chip.dev);
+       mutex_lock(&pca->lock);
+       pwm = &pca->chip.pwms[offset];
+       pwm_set_chip_data(pwm, NULL);
+       mutex_unlock(&pca->lock);
+}
+
 static int pca9685_pwm_gpio_get_direction(struct gpio_chip *chip,
                                          unsigned int offset)
 {
@@ -238,6 +241,16 @@ static inline int pca9685_pwm_gpio_probe(struct pca9685 *pca)
 }
 #endif
 
+static void pca9685_set_sleep_mode(struct pca9685 *pca, int sleep)
+{
+       regmap_update_bits(pca->regmap, PCA9685_MODE1,
+                          MODE1_SLEEP, sleep ? MODE1_SLEEP : 0);
+       if (!sleep) {
+               /* Wait 500us for the oscillator to be back up */
+               udelay(500);
+       }
+}
+
 static int pca9685_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
                              int duty_ns, int period_ns)
 {
@@ -252,19 +265,20 @@ static int pca9685_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
 
                if (prescale >= PCA9685_PRESCALE_MIN &&
                        prescale <= PCA9685_PRESCALE_MAX) {
+                       /*
+                        * putting the chip briefly into SLEEP mode
+                        * at this point won't interfere with the
+                        * pm_runtime framework, because the pm_runtime
+                        * state is guaranteed active here.
+                        */
                        /* Put chip into sleep mode */
-                       regmap_update_bits(pca->regmap, PCA9685_MODE1,
-                                          MODE1_SLEEP, MODE1_SLEEP);
+                       pca9685_set_sleep_mode(pca, 1);
 
                        /* Change the chip-wide output frequency */
                        regmap_write(pca->regmap, PCA9685_PRESCALE, prescale);
 
                        /* Wake the chip up */
-                       regmap_update_bits(pca->regmap, PCA9685_MODE1,
-                                          MODE1_SLEEP, 0x0);
-
-                       /* Wait 500us for the oscillator to be back up */
-                       udelay(500);
+                       pca9685_set_sleep_mode(pca, 0);
 
                        pca->period_ns = period_ns;
                } else {
@@ -406,21 +420,15 @@ static int pca9685_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
 
        if (pca9685_pwm_is_gpio(pca, pwm))
                return -EBUSY;
-
-       if (pca->active_cnt++ == 0)
-               return regmap_update_bits(pca->regmap, PCA9685_MODE1,
-                                         MODE1_SLEEP, 0x0);
+       pm_runtime_get_sync(chip->dev);
 
        return 0;
 }
 
 static void pca9685_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
 {
-       struct pca9685 *pca = to_pca(chip);
-
-       if (--pca->active_cnt == 0)
-               regmap_update_bits(pca->regmap, PCA9685_MODE1, MODE1_SLEEP,
-                                  MODE1_SLEEP);
+       pca9685_pwm_disable(chip, pwm);
+       pm_runtime_put(chip->dev);
 }
 
 static const struct pwm_ops pca9685_pwm_ops = {
@@ -492,22 +500,54 @@ static int pca9685_pwm_probe(struct i2c_client *client,
                return ret;
 
        ret = pca9685_pwm_gpio_probe(pca);
-       if (ret < 0)
+       if (ret < 0) {
                pwmchip_remove(&pca->chip);
+               return ret;
+       }
+
+       /* the chip comes out of power-up in the active state */
+       pm_runtime_set_active(&client->dev);
+       /*
+        * enable will put the chip into suspend, which is what we
+        * want as all outputs are disabled at this point
+        */
+       pm_runtime_enable(&client->dev);
 
-       return ret;
+       return 0;
 }
 
 static int pca9685_pwm_remove(struct i2c_client *client)
 {
        struct pca9685 *pca = i2c_get_clientdata(client);
+       int ret;
 
-       regmap_update_bits(pca->regmap, PCA9685_MODE1, MODE1_SLEEP,
-                          MODE1_SLEEP);
+       ret = pwmchip_remove(&pca->chip);
+       if (ret)
+               return ret;
+       pm_runtime_disable(&client->dev);
+       return 0;
+}
 
-       return pwmchip_remove(&pca->chip);
+#ifdef CONFIG_PM
+static int pca9685_pwm_runtime_suspend(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct pca9685 *pca = i2c_get_clientdata(client);
+
+       pca9685_set_sleep_mode(pca, 1);
+       return 0;
 }
 
+static int pca9685_pwm_runtime_resume(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct pca9685 *pca = i2c_get_clientdata(client);
+
+       pca9685_set_sleep_mode(pca, 0);
+       return 0;
+}
+#endif
+
 static const struct i2c_device_id pca9685_id[] = {
        { "pca9685", 0 },
        { /* sentinel */ },
@@ -530,11 +570,17 @@ static const struct of_device_id pca9685_dt_ids[] = {
 MODULE_DEVICE_TABLE(of, pca9685_dt_ids);
 #endif
 
+static const struct dev_pm_ops pca9685_pwm_pm = {
+       SET_RUNTIME_PM_OPS(pca9685_pwm_runtime_suspend,
+                          pca9685_pwm_runtime_resume, NULL)
+};
+
 static struct i2c_driver pca9685_i2c_driver = {
        .driver = {
                .name = "pca9685-pwm",
                .acpi_match_table = ACPI_PTR(pca9685_acpi_ids),
                .of_match_table = of_match_ptr(pca9685_dt_ids),
+               .pm = &pca9685_pwm_pm,
        },
        .probe = pca9685_pwm_probe,
        .remove = pca9685_pwm_remove,
index e4647840cd6e3129fb94da036e30470714852f14..8c6ed556db28a874c244c1300cae30109e43deb1 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/of_device.h>
 #include <linux/pwm.h>
 #include <linux/platform_device.h>
+#include <linux/pinctrl/consumer.h>
 #include <linux/slab.h>
 #include <linux/reset.h>
 
@@ -49,6 +50,8 @@ struct tegra_pwm_chip {
        struct clk *clk;
        struct reset_control*rst;
 
+       unsigned long clk_rate;
+
        void __iomem *regs;
 
        const struct tegra_pwm_soc *soc;
@@ -74,8 +77,8 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
                            int duty_ns, int period_ns)
 {
        struct tegra_pwm_chip *pc = to_tegra_pwm_chip(chip);
-       unsigned long long c = duty_ns;
-       unsigned long rate, hz;
+       unsigned long long c = duty_ns, hz;
+       unsigned long rate;
        u32 val = 0;
        int err;
 
@@ -85,8 +88,7 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
         * nearest integer during division.
         */
        c *= (1 << PWM_DUTY_WIDTH);
-       c += period_ns / 2;
-       do_div(c, period_ns);
+       c = DIV_ROUND_CLOSEST_ULL(c, period_ns);
 
        val = (u32)c << PWM_DUTY_SHIFT;
 
@@ -94,10 +96,11 @@ static int tegra_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
         * Compute the prescaler value for which (1 << PWM_DUTY_WIDTH)
         * cycles at the PWM clock rate will take period_ns nanoseconds.
         */
-       rate = clk_get_rate(pc->clk) >> PWM_DUTY_WIDTH;
-       hz = NSEC_PER_SEC / period_ns;
+       rate = pc->clk_rate >> PWM_DUTY_WIDTH;
 
-       rate = (rate + (hz / 2)) / hz;
+       /* Consider precision in PWM_SCALE_WIDTH rate calculation */
+       hz = DIV_ROUND_CLOSEST_ULL(100ULL * NSEC_PER_SEC, period_ns);
+       rate = DIV_ROUND_CLOSEST_ULL(100ULL * rate, hz);
 
        /*
         * Since the actual PWM divider is the register's frequency divider
@@ -198,6 +201,9 @@ static int tegra_pwm_probe(struct platform_device *pdev)
        if (IS_ERR(pwm->clk))
                return PTR_ERR(pwm->clk);
 
+       /* Read PWM clock rate from source */
+       pwm->clk_rate = clk_get_rate(pwm->clk);
+
        pwm->rst = devm_reset_control_get(&pdev->dev, "pwm");
        if (IS_ERR(pwm->rst)) {
                ret = PTR_ERR(pwm->rst);
@@ -253,6 +259,18 @@ static int tegra_pwm_remove(struct platform_device *pdev)
        return pwmchip_remove(&pc->chip);
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int tegra_pwm_suspend(struct device *dev)
+{
+       return pinctrl_pm_select_sleep_state(dev);
+}
+
+static int tegra_pwm_resume(struct device *dev)
+{
+       return pinctrl_pm_select_default_state(dev);
+}
+#endif
+
 static const struct tegra_pwm_soc tegra20_pwm_soc = {
        .num_channels = 4,
 };
@@ -269,10 +287,15 @@ static const struct of_device_id tegra_pwm_of_match[] = {
 
 MODULE_DEVICE_TABLE(of, tegra_pwm_of_match);
 
+static const struct dev_pm_ops tegra_pwm_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(tegra_pwm_suspend, tegra_pwm_resume)
+};
+
 static struct platform_driver tegra_pwm_driver = {
        .driver = {
                .name = "tegra-pwm",
                .of_match_table = tegra_pwm_of_match,
+               .pm = &tegra_pwm_pm_ops,
        },
        .probe = tegra_pwm_probe,
        .remove = tegra_pwm_remove,
index 0142cc3f0c91c6fe98fe4222741819692592b25b..294634836b321d01d2adbf5cd2613b488c5eb44f 100644 (file)
@@ -71,7 +71,7 @@ EXPORT_SYMBOL(rproc_vq_interrupt);
 static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
                                    unsigned int id,
                                    void (*callback)(struct virtqueue *vq),
-                                   const char *name)
+                                   const char *name, bool ctx)
 {
        struct rproc_vdev *rvdev = vdev_to_rvdev(vdev);
        struct rproc *rproc = vdev_to_rproc(vdev);
@@ -103,8 +103,8 @@ static struct virtqueue *rp_find_vq(struct virtio_device *vdev,
         * Create the new vq, and tell virtio we're not interested in
         * the 'weak' smp barriers, since we're talking with a real device.
         */
-       vq = vring_new_virtqueue(id, len, rvring->align, vdev, false, addr,
-                                rproc_virtio_notify, callback, name);
+       vq = vring_new_virtqueue(id, len, rvring->align, vdev, false, ctx,
+                                addr, rproc_virtio_notify, callback, name);
        if (!vq) {
                dev_err(dev, "vring_new_virtqueue %s failed\n", name);
                rproc_free_vring(rvring);
@@ -138,12 +138,14 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
                                 struct virtqueue *vqs[],
                                 vq_callback_t *callbacks[],
                                 const char * const names[],
+                                const bool * ctx,
                                 struct irq_affinity *desc)
 {
        int i, ret;
 
        for (i = 0; i < nvqs; ++i) {
-               vqs[i] = rp_find_vq(vdev, i, callbacks[i], names[i]);
+               vqs[i] = rp_find_vq(vdev, i, callbacks[i], names[i],
+                                   ctx ? ctx[i] : false);
                if (IS_ERR(vqs[i])) {
                        ret = PTR_ERR(vqs[i]);
                        goto error;
index f4cdfe94b9ec0b4124b3f9680b23c283d546f867..d21c07ccc94e501ff44206c151a8bc5c48db513e 100644 (file)
@@ -14,6 +14,13 @@ menuconfig RESET_CONTROLLER
 
 if RESET_CONTROLLER
 
+config RESET_A10SR
+       tristate "Altera Arria10 System Resource Reset"
+       depends on MFD_ALTERA_A10SR
+       help
+         This option enables support for the external reset functions for
+         peripheral PHYs on the Altera Arria10 System Resource Chip.
+
 config RESET_ATH79
        bool "AR71xx Reset Driver" if COMPILE_TEST
        default ATH79
@@ -27,6 +34,13 @@ config RESET_BERLIN
        help
          This enables the reset controller driver for Marvell Berlin SoCs.
 
+config RESET_IMX7
+       bool "i.MX7 Reset Driver" if COMPILE_TEST
+       default SOC_IMX7D
+       select MFD_SYSCON
+       help
+         This enables the reset controller driver for i.MX7 SoCs.
+
 config RESET_LPC18XX
        bool "LPC18xx/43xx Reset Driver" if COMPILE_TEST
        default ARCH_LPC18XX
index 2cd3f6c45165a8f4a3a1e5c31c92e7f2fa69a8f8..02a74db94339750d4bb57b2450f24d29caed4128 100644 (file)
@@ -2,8 +2,10 @@ obj-y += core.o
 obj-y += hisilicon/
 obj-$(CONFIG_ARCH_STI) += sti/
 obj-$(CONFIG_ARCH_TEGRA) += tegra/
+obj-$(CONFIG_RESET_A10SR) += reset-a10sr.o
 obj-$(CONFIG_RESET_ATH79) += reset-ath79.o
 obj-$(CONFIG_RESET_BERLIN) += reset-berlin.o
+obj-$(CONFIG_RESET_IMX7) += reset-imx7.o
 obj-$(CONFIG_RESET_LPC18XX) += reset-lpc18xx.o
 obj-$(CONFIG_RESET_MESON) += reset-meson.o
 obj-$(CONFIG_RESET_OXNAS) += reset-oxnas.o
@@ -15,3 +17,4 @@ obj-$(CONFIG_TI_SYSCON_RESET) += reset-ti-syscon.o
 obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
 obj-$(CONFIG_RESET_ZX2967) += reset-zx2967.o
 obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o
+
diff --git a/drivers/reset/reset-a10sr.c b/drivers/reset/reset-a10sr.c
new file mode 100644 (file)
index 0000000..37496bd
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ *  Copyright Intel Corporation (C) 2017. All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Reset driver for Altera Arria10 MAX5 System Resource Chip
+ *
+ * Adapted from reset-socfpga.c
+ */
+
+#include <linux/err.h>
+#include <linux/mfd/altera-a10sr.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+
+#include <dt-bindings/reset/altr,rst-mgr-a10sr.h>
+
+struct a10sr_reset {
+       struct reset_controller_dev     rcdev;
+       struct regmap *regmap;
+};
+
+static inline struct a10sr_reset *to_a10sr_rst(struct reset_controller_dev *rc)
+{
+       return container_of(rc, struct a10sr_reset, rcdev);
+}
+
+static inline int a10sr_reset_shift(unsigned long id)
+{
+       switch (id) {
+       case A10SR_RESET_ENET_HPS:
+               return 1;
+       case A10SR_RESET_PCIE:
+       case A10SR_RESET_FILE:
+       case A10SR_RESET_BQSPI:
+       case A10SR_RESET_USB:
+               return id + 11;
+       default:
+               return -EINVAL;
+       }
+}
+
+static int a10sr_reset_update(struct reset_controller_dev *rcdev,
+                             unsigned long id, bool assert)
+{
+       struct a10sr_reset *a10r = to_a10sr_rst(rcdev);
+       int offset = a10sr_reset_shift(id);
+       u8 mask = ALTR_A10SR_REG_BIT_MASK(offset);
+       int index = ALTR_A10SR_HPS_RST_REG + ALTR_A10SR_REG_OFFSET(offset);
+
+       return regmap_update_bits(a10r->regmap, index, mask, assert ? 0 : mask);
+}
+
+static int a10sr_reset_assert(struct reset_controller_dev *rcdev,
+                             unsigned long id)
+{
+       return a10sr_reset_update(rcdev, id, true);
+}
+
+static int a10sr_reset_deassert(struct reset_controller_dev *rcdev,
+                               unsigned long id)
+{
+       return a10sr_reset_update(rcdev, id, false);
+}
+
+static int a10sr_reset_status(struct reset_controller_dev *rcdev,
+                             unsigned long id)
+{
+       int ret;
+       struct a10sr_reset *a10r = to_a10sr_rst(rcdev);
+       int offset = a10sr_reset_shift(id);
+       u8 mask = ALTR_A10SR_REG_BIT_MASK(offset);
+       int index = ALTR_A10SR_HPS_RST_REG + ALTR_A10SR_REG_OFFSET(offset);
+       unsigned int value;
+
+       ret = regmap_read(a10r->regmap, index, &value);
+       if (ret < 0)
+               return ret;
+
+       return !!(value & mask);
+}
+
+static const struct reset_control_ops a10sr_reset_ops = {
+       .assert         = a10sr_reset_assert,
+       .deassert       = a10sr_reset_deassert,
+       .status         = a10sr_reset_status,
+};
+
+static int a10sr_reset_probe(struct platform_device *pdev)
+{
+       struct altr_a10sr *a10sr = dev_get_drvdata(pdev->dev.parent);
+       struct a10sr_reset *a10r;
+
+       a10r = devm_kzalloc(&pdev->dev, sizeof(struct a10sr_reset),
+                           GFP_KERNEL);
+       if (!a10r)
+               return -ENOMEM;
+
+       a10r->rcdev.owner = THIS_MODULE;
+       a10r->rcdev.nr_resets = A10SR_RESET_NUM;
+       a10r->rcdev.ops = &a10sr_reset_ops;
+       a10r->rcdev.of_node = pdev->dev.of_node;
+       a10r->regmap = a10sr->regmap;
+
+       platform_set_drvdata(pdev, a10r);
+
+       return devm_reset_controller_register(&pdev->dev, &a10r->rcdev);
+}
+
+static const struct of_device_id a10sr_reset_of_match[] = {
+       { .compatible = "altr,a10sr-reset" },
+       { },
+};
+MODULE_DEVICE_TABLE(of, a10sr_reset_of_match);
+
+static struct platform_driver a10sr_reset_driver = {
+       .probe  = a10sr_reset_probe,
+       .driver = {
+               .name           = "altr_a10sr_reset",
+       },
+};
+module_platform_driver(a10sr_reset_driver);
+
+MODULE_AUTHOR("Thor Thayer <thor.thayer@linux.intel.com>");
+MODULE_DESCRIPTION("Altera Arria10 System Resource Reset Controller Driver");
+MODULE_LICENSE("GPL v2");
index 6b97631f548932158e7e84b29fdc5cc63f5e2049..2674880e5492be7be62b7053abe776961ba013ef 100644 (file)
@@ -1,4 +1,7 @@
 /*
+ * AR71xx Reset Controller Driver
+ * Author: Alban Bedel
+ *
  * Copyright (C) 2015 Alban Bedel <albeu@free.fr>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -13,7 +16,7 @@
  */
 
 #include <linux/io.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/reset-controller.h>
 #include <linux/reboot.h>
@@ -127,31 +130,17 @@ static int ath79_reset_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int ath79_reset_remove(struct platform_device *pdev)
-{
-       struct ath79_reset *ath79_reset = platform_get_drvdata(pdev);
-
-       unregister_restart_handler(&ath79_reset->restart_nb);
-
-       return 0;
-}
-
 static const struct of_device_id ath79_reset_dt_ids[] = {
        { .compatible = "qca,ar7100-reset", },
        { },
 };
-MODULE_DEVICE_TABLE(of, ath79_reset_dt_ids);
 
 static struct platform_driver ath79_reset_driver = {
        .probe  = ath79_reset_probe,
-       .remove = ath79_reset_remove,
        .driver = {
-               .name           = "ath79-reset",
-               .of_match_table = ath79_reset_dt_ids,
+               .name                   = "ath79-reset",
+               .of_match_table         = ath79_reset_dt_ids,
+               .suppress_bind_attrs    = true,
        },
 };
-module_platform_driver(ath79_reset_driver);
-
-MODULE_AUTHOR("Alban Bedel <albeu@free.fr>");
-MODULE_DESCRIPTION("AR71xx Reset Controller Driver");
-MODULE_LICENSE("GPL");
+builtin_platform_driver(ath79_reset_driver);
diff --git a/drivers/reset/reset-imx7.c b/drivers/reset/reset-imx7.c
new file mode 100644 (file)
index 0000000..4db177b
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ * Copyright (c) 2017, Impinj, Inc.
+ *
+ * i.MX7 System Reset Controller (SRC) driver
+ *
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/mfd/syscon.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/regmap.h>
+#include <dt-bindings/reset/imx7-reset.h>
+
+struct imx7_src {
+       struct reset_controller_dev rcdev;
+       struct regmap *regmap;
+};
+
+enum imx7_src_registers {
+       SRC_A7RCR0              = 0x0004,
+       SRC_M4RCR               = 0x000c,
+       SRC_ERCR                = 0x0014,
+       SRC_HSICPHY_RCR         = 0x001c,
+       SRC_USBOPHY1_RCR        = 0x0020,
+       SRC_USBOPHY2_RCR        = 0x0024,
+       SRC_MIPIPHY_RCR         = 0x0028,
+       SRC_PCIEPHY_RCR         = 0x002c,
+       SRC_DDRC_RCR            = 0x1000,
+};
+
+struct imx7_src_signal {
+       unsigned int offset, bit;
+};
+
+static const struct imx7_src_signal imx7_src_signals[IMX7_RESET_NUM] = {
+       [IMX7_RESET_A7_CORE_POR_RESET0] = { SRC_A7RCR0, BIT(0) },
+       [IMX7_RESET_A7_CORE_POR_RESET1] = { SRC_A7RCR0, BIT(1) },
+       [IMX7_RESET_A7_CORE_RESET0]     = { SRC_A7RCR0, BIT(4) },
+       [IMX7_RESET_A7_CORE_RESET1]     = { SRC_A7RCR0, BIT(5) },
+       [IMX7_RESET_A7_DBG_RESET0]      = { SRC_A7RCR0, BIT(8) },
+       [IMX7_RESET_A7_DBG_RESET1]      = { SRC_A7RCR0, BIT(9) },
+       [IMX7_RESET_A7_ETM_RESET0]      = { SRC_A7RCR0, BIT(12) },
+       [IMX7_RESET_A7_ETM_RESET1]      = { SRC_A7RCR0, BIT(13) },
+       [IMX7_RESET_A7_SOC_DBG_RESET]   = { SRC_A7RCR0, BIT(20) },
+       [IMX7_RESET_A7_L2RESET]         = { SRC_A7RCR0, BIT(21) },
+       [IMX7_RESET_SW_M4C_RST]         = { SRC_M4RCR, BIT(1) },
+       [IMX7_RESET_SW_M4P_RST]         = { SRC_M4RCR, BIT(2) },
+       [IMX7_RESET_EIM_RST]            = { SRC_ERCR, BIT(0) },
+       [IMX7_RESET_HSICPHY_PORT_RST]   = { SRC_HSICPHY_RCR, BIT(1) },
+       [IMX7_RESET_USBPHY1_POR]        = { SRC_USBOPHY1_RCR, BIT(0) },
+       [IMX7_RESET_USBPHY1_PORT_RST]   = { SRC_USBOPHY1_RCR, BIT(1) },
+       [IMX7_RESET_USBPHY2_POR]        = { SRC_USBOPHY2_RCR, BIT(0) },
+       [IMX7_RESET_USBPHY2_PORT_RST]   = { SRC_USBOPHY2_RCR, BIT(1) },
+       [IMX7_RESET_MIPI_PHY_MRST]      = { SRC_MIPIPHY_RCR, BIT(1) },
+       [IMX7_RESET_MIPI_PHY_SRST]      = { SRC_MIPIPHY_RCR, BIT(2) },
+       [IMX7_RESET_PCIEPHY]            = { SRC_PCIEPHY_RCR, BIT(2) | BIT(1) },
+       [IMX7_RESET_PCIEPHY_PERST]      = { SRC_PCIEPHY_RCR, BIT(3) },
+       [IMX7_RESET_PCIE_CTRL_APPS_EN]  = { SRC_PCIEPHY_RCR, BIT(6) },
+       [IMX7_RESET_DDRC_PRST]          = { SRC_DDRC_RCR, BIT(0) },
+       [IMX7_RESET_DDRC_CORE_RST]      = { SRC_DDRC_RCR, BIT(1) },
+};
+
+static struct imx7_src *to_imx7_src(struct reset_controller_dev *rcdev)
+{
+       return container_of(rcdev, struct imx7_src, rcdev);
+}
+
+static int imx7_reset_set(struct reset_controller_dev *rcdev,
+                         unsigned long id, bool assert)
+{
+       struct imx7_src *imx7src = to_imx7_src(rcdev);
+       const struct imx7_src_signal *signal = &imx7_src_signals[id];
+       unsigned int value = 0;
+
+       switch (id) {
+       case IMX7_RESET_PCIEPHY:
+               /*
+                * wait for more than 10us to release phy g_rst and
+                * btnrst
+                */
+               if (!assert)
+                       udelay(10);
+               break;
+
+       case IMX7_RESET_PCIE_CTRL_APPS_EN:
+               value = (assert) ? 0 : signal->bit;
+               break;
+       }
+
+       return regmap_update_bits(imx7src->regmap,
+                                 signal->offset, signal->bit, value);
+}
+
+static int imx7_reset_assert(struct reset_controller_dev *rcdev,
+                            unsigned long id)
+{
+       return imx7_reset_set(rcdev, id, true);
+}
+
+static int imx7_reset_deassert(struct reset_controller_dev *rcdev,
+                              unsigned long id)
+{
+       return imx7_reset_set(rcdev, id, false);
+}
+
+static const struct reset_control_ops imx7_reset_ops = {
+       .assert         = imx7_reset_assert,
+       .deassert       = imx7_reset_deassert,
+};
+
+static int imx7_reset_probe(struct platform_device *pdev)
+{
+       struct imx7_src *imx7src;
+       struct device *dev = &pdev->dev;
+       struct regmap_config config = { .name = "src" };
+
+       imx7src = devm_kzalloc(dev, sizeof(*imx7src), GFP_KERNEL);
+       if (!imx7src)
+               return -ENOMEM;
+
+       imx7src->regmap = syscon_node_to_regmap(dev->of_node);
+       if (IS_ERR(imx7src->regmap)) {
+               dev_err(dev, "Unable to get imx7-src regmap");
+               return PTR_ERR(imx7src->regmap);
+       }
+       regmap_attach_dev(dev, imx7src->regmap, &config);
+
+       imx7src->rcdev.owner     = THIS_MODULE;
+       imx7src->rcdev.nr_resets = IMX7_RESET_NUM;
+       imx7src->rcdev.ops       = &imx7_reset_ops;
+       imx7src->rcdev.of_node   = dev->of_node;
+
+       return devm_reset_controller_register(dev, &imx7src->rcdev);
+}
+
+static const struct of_device_id imx7_reset_dt_ids[] = {
+       { .compatible = "fsl,imx7d-src", },
+       { /* sentinel */ },
+};
+
+static struct platform_driver imx7_reset_driver = {
+       .probe  = imx7_reset_probe,
+       .driver = {
+               .name           = KBUILD_MODNAME,
+               .of_match_table = imx7_reset_dt_ids,
+       },
+};
+builtin_platform_driver(imx7_reset_driver);
index c32f11a30c5f3f732e2e80d11e88a394cf0fe425..a8b915eb8b581e4e9086d5cb0d2df11ff800b814 100644 (file)
@@ -1,4 +1,6 @@
 /*
+ * Amlogic Meson Reset Controller driver
+ *
  * This file is provided under a dual BSD/GPLv2 license.  When using or
  * redistributing this file, you may do so under either license.
  *
@@ -53,7 +55,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include <linux/err.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
@@ -95,7 +97,6 @@ static const struct of_device_id meson_reset_dt_ids[] = {
         { .compatible = "amlogic,meson-gxbb-reset", },
         { /* sentinel */ },
 };
-MODULE_DEVICE_TABLE(of, meson_reset_dt_ids);
 
 static int meson_reset_probe(struct platform_device *pdev)
 {
@@ -128,9 +129,4 @@ static struct platform_driver meson_reset_driver = {
                .of_match_table = meson_reset_dt_ids,
        },
 };
-
-module_platform_driver(meson_reset_driver);
-
-MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
-MODULE_DESCRIPTION("Amlogic Meson Reset Controller driver");
-MODULE_LICENSE("Dual BSD/GPL");
+builtin_platform_driver(meson_reset_driver);
index 0d9036dea010d1274e4a79b536368adad543f0a0..cf5b9742b86ecf4ebc8aa8f53fd5ffb3f607d6b1 100644 (file)
@@ -18,7 +18,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 #include <linux/err.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/reset-controller.h>
@@ -83,7 +83,6 @@ static const struct of_device_id oxnas_reset_dt_ids[] = {
         { .compatible = "oxsemi,ox820-reset", },
         { /* sentinel */ },
 };
-MODULE_DEVICE_TABLE(of, oxnas_reset_dt_ids);
 
 static int oxnas_reset_probe(struct platform_device *pdev)
 {
@@ -123,5 +122,4 @@ static struct platform_driver oxnas_reset_driver = {
                .of_match_table = oxnas_reset_dt_ids,
        },
 };
-
-module_platform_driver(oxnas_reset_driver);
+builtin_platform_driver(oxnas_reset_driver);
index bbc4c06dd33b7542b1b1478e46201e9024237682..11d651b44e814ba922e1f7151c6214666cf7c057 100644 (file)
@@ -10,7 +10,7 @@
  * version 2, as published by the Free Software Foundation.
  */
 
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
@@ -128,7 +128,6 @@ static const struct of_device_id pistachio_reset_dt_ids[] = {
         { .compatible = "img,pistachio-reset", },
         { /* sentinel */ },
 };
-MODULE_DEVICE_TABLE(of, pistachio_reset_dt_ids);
 
 static struct platform_driver pistachio_reset_driver = {
        .probe  = pistachio_reset_probe,
@@ -137,8 +136,4 @@ static struct platform_driver pistachio_reset_driver = {
                .of_match_table = pistachio_reset_dt_ids,
        },
 };
-module_platform_driver(pistachio_reset_driver);
-
-MODULE_AUTHOR("Damien Horsley <Damien.Horsley@imgtec.com>");
-MODULE_DESCRIPTION("Pistacho Reset Controller Driver");
-MODULE_LICENSE("GPL v2");
+builtin_platform_driver(pistachio_reset_driver);
index 43e4a9f39b9b8f9be75a52695c9adec73a981667..07224c019892006248a98fe58343d2a0f6c4fe36 100644 (file)
@@ -25,7 +25,8 @@
 #include <linux/spinlock.h>
 #include <linux/types.h>
 
-#define NR_BANKS               4
+#define BANK_INCREMENT         4
+#define NR_BANKS               8
 
 struct socfpga_reset_data {
        spinlock_t                      lock;
@@ -46,8 +47,8 @@ static int socfpga_reset_assert(struct reset_controller_dev *rcdev,
 
        spin_lock_irqsave(&data->lock, flags);
 
-       reg = readl(data->membase + (bank * NR_BANKS));
-       writel(reg | BIT(offset), data->membase + (bank * NR_BANKS));
+       reg = readl(data->membase + (bank * BANK_INCREMENT));
+       writel(reg | BIT(offset), data->membase + (bank * BANK_INCREMENT));
        spin_unlock_irqrestore(&data->lock, flags);
 
        return 0;
@@ -67,8 +68,8 @@ static int socfpga_reset_deassert(struct reset_controller_dev *rcdev,
 
        spin_lock_irqsave(&data->lock, flags);
 
-       reg = readl(data->membase + (bank * NR_BANKS));
-       writel(reg & ~BIT(offset), data->membase + (bank * NR_BANKS));
+       reg = readl(data->membase + (bank * BANK_INCREMENT));
+       writel(reg & ~BIT(offset), data->membase + (bank * BANK_INCREMENT));
 
        spin_unlock_irqrestore(&data->lock, flags);
 
@@ -84,7 +85,7 @@ static int socfpga_reset_status(struct reset_controller_dev *rcdev,
        int offset = id % BITS_PER_LONG;
        u32 reg;
 
-       reg = readl(data->membase + (bank * NR_BANKS));
+       reg = readl(data->membase + (bank * BANK_INCREMENT));
 
        return !(reg & BIT(offset));
 }
index b44f6b5f87b6389a7f983ff794c746a77fbe9b7a..cd585cd2f04dd1b2677fa8c2cf5ac95200792b70 100644 (file)
@@ -34,15 +34,16 @@ static int sunxi_reset_assert(struct reset_controller_dev *rcdev,
        struct sunxi_reset_data *data = container_of(rcdev,
                                                     struct sunxi_reset_data,
                                                     rcdev);
-       int bank = id / BITS_PER_LONG;
-       int offset = id % BITS_PER_LONG;
+       int reg_width = sizeof(u32);
+       int bank = id / (reg_width * BITS_PER_BYTE);
+       int offset = id % (reg_width * BITS_PER_BYTE);
        unsigned long flags;
        u32 reg;
 
        spin_lock_irqsave(&data->lock, flags);
 
-       reg = readl(data->membase + (bank * 4));
-       writel(reg & ~BIT(offset), data->membase + (bank * 4));
+       reg = readl(data->membase + (bank * reg_width));
+       writel(reg & ~BIT(offset), data->membase + (bank * reg_width));
 
        spin_unlock_irqrestore(&data->lock, flags);
 
@@ -55,15 +56,16 @@ static int sunxi_reset_deassert(struct reset_controller_dev *rcdev,
        struct sunxi_reset_data *data = container_of(rcdev,
                                                     struct sunxi_reset_data,
                                                     rcdev);
-       int bank = id / BITS_PER_LONG;
-       int offset = id % BITS_PER_LONG;
+       int reg_width = sizeof(u32);
+       int bank = id / (reg_width * BITS_PER_BYTE);
+       int offset = id % (reg_width * BITS_PER_BYTE);
        unsigned long flags;
        u32 reg;
 
        spin_lock_irqsave(&data->lock, flags);
 
-       reg = readl(data->membase + (bank * 4));
-       writel(reg | BIT(offset), data->membase + (bank * 4));
+       reg = readl(data->membase + (bank * reg_width));
+       writel(reg | BIT(offset), data->membase + (bank * reg_width));
 
        spin_unlock_irqrestore(&data->lock, flags);
 
index 9c11be3d3450f804d1ae90470a3950ac79c5bef0..c4ba89832796b767debc204d41513dc563c96c81 100644 (file)
@@ -50,6 +50,15 @@ struct uniphier_reset_data {
        }
 
 /* System reset data */
+#define UNIPHIER_SLD3_SYS_RESET_NAND(id)               \
+       UNIPHIER_RESETX((id), 0x2004, 2)
+
+#define UNIPHIER_LD11_SYS_RESET_NAND(id)               \
+       UNIPHIER_RESETX((id), 0x200c, 0)
+
+#define UNIPHIER_LD11_SYS_RESET_EMMC(id)               \
+       UNIPHIER_RESETX((id), 0x200c, 2)
+
 #define UNIPHIER_SLD3_SYS_RESET_STDMAC(id)             \
        UNIPHIER_RESETX((id), 0x2000, 10)
 
@@ -65,12 +74,14 @@ struct uniphier_reset_data {
 #define UNIPHIER_PRO4_SYS_RESET_USB3(id, ch)           \
        UNIPHIER_RESETX((id), 0x2000 + 0x4 * (ch), 17)
 
-const struct uniphier_reset_data uniphier_sld3_sys_reset_data[] = {
+static const struct uniphier_reset_data uniphier_sld3_sys_reset_data[] = {
+       UNIPHIER_SLD3_SYS_RESET_NAND(2),
        UNIPHIER_SLD3_SYS_RESET_STDMAC(8),      /* Ether, HSC, MIO */
        UNIPHIER_RESET_END,
 };
 
-const struct uniphier_reset_data uniphier_pro4_sys_reset_data[] = {
+static const struct uniphier_reset_data uniphier_pro4_sys_reset_data[] = {
+       UNIPHIER_SLD3_SYS_RESET_NAND(2),
        UNIPHIER_SLD3_SYS_RESET_STDMAC(8),      /* HSC, MIO, RLE */
        UNIPHIER_PRO4_SYS_RESET_GIO(12),        /* Ether, SATA, USB3 */
        UNIPHIER_PRO4_SYS_RESET_USB3(14, 0),
@@ -78,7 +89,8 @@ const struct uniphier_reset_data uniphier_pro4_sys_reset_data[] = {
        UNIPHIER_RESET_END,
 };
 
-const struct uniphier_reset_data uniphier_pro5_sys_reset_data[] = {
+static const struct uniphier_reset_data uniphier_pro5_sys_reset_data[] = {
+       UNIPHIER_SLD3_SYS_RESET_NAND(2),
        UNIPHIER_SLD3_SYS_RESET_STDMAC(8),      /* HSC */
        UNIPHIER_PRO4_SYS_RESET_GIO(12),        /* PCIe, USB3 */
        UNIPHIER_PRO4_SYS_RESET_USB3(14, 0),
@@ -86,7 +98,8 @@ const struct uniphier_reset_data uniphier_pro5_sys_reset_data[] = {
        UNIPHIER_RESET_END,
 };
 
-const struct uniphier_reset_data uniphier_pxs2_sys_reset_data[] = {
+static const struct uniphier_reset_data uniphier_pxs2_sys_reset_data[] = {
+       UNIPHIER_SLD3_SYS_RESET_NAND(2),
        UNIPHIER_SLD3_SYS_RESET_STDMAC(8),      /* HSC, RLE */
        UNIPHIER_PRO4_SYS_RESET_USB3(14, 0),
        UNIPHIER_PRO4_SYS_RESET_USB3(15, 1),
@@ -100,12 +113,16 @@ const struct uniphier_reset_data uniphier_pxs2_sys_reset_data[] = {
        UNIPHIER_RESET_END,
 };
 
-const struct uniphier_reset_data uniphier_ld11_sys_reset_data[] = {
+static const struct uniphier_reset_data uniphier_ld11_sys_reset_data[] = {
+       UNIPHIER_LD11_SYS_RESET_NAND(2),
+       UNIPHIER_LD11_SYS_RESET_EMMC(4),
        UNIPHIER_LD11_SYS_RESET_STDMAC(8),      /* HSC, MIO */
        UNIPHIER_RESET_END,
 };
 
-const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = {
+static const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = {
+       UNIPHIER_LD11_SYS_RESET_NAND(2),
+       UNIPHIER_LD11_SYS_RESET_EMMC(4),
        UNIPHIER_LD11_SYS_RESET_STDMAC(8),      /* HSC */
        UNIPHIER_LD20_SYS_RESET_GIO(12),        /* PCIe, USB3 */
        UNIPHIER_RESETX(16, 0x200c, 12),        /* USB30-PHY0 */
@@ -134,7 +151,7 @@ const struct uniphier_reset_data uniphier_ld20_sys_reset_data[] = {
 #define UNIPHIER_MIO_RESET_DMAC(id)                    \
        UNIPHIER_RESETX((id), 0x110, 17)
 
-const struct uniphier_reset_data uniphier_sld3_mio_reset_data[] = {
+static const struct uniphier_reset_data uniphier_sld3_mio_reset_data[] = {
        UNIPHIER_MIO_RESET_SD(0, 0),
        UNIPHIER_MIO_RESET_SD(1, 1),
        UNIPHIER_MIO_RESET_SD(2, 2),
@@ -154,7 +171,7 @@ const struct uniphier_reset_data uniphier_sld3_mio_reset_data[] = {
        UNIPHIER_RESET_END,
 };
 
-const struct uniphier_reset_data uniphier_pro5_sd_reset_data[] = {
+static const struct uniphier_reset_data uniphier_pro5_sd_reset_data[] = {
        UNIPHIER_MIO_RESET_SD(0, 0),
        UNIPHIER_MIO_RESET_SD(1, 1),
        UNIPHIER_MIO_RESET_EMMC_HW_RESET(6, 1),
@@ -171,7 +188,7 @@ const struct uniphier_reset_data uniphier_pro5_sd_reset_data[] = {
 #define UNIPHIER_PERI_RESET_FI2C(id, ch)               \
        UNIPHIER_RESETX((id), 0x114, 24 + (ch))
 
-const struct uniphier_reset_data uniphier_ld4_peri_reset_data[] = {
+static const struct uniphier_reset_data uniphier_ld4_peri_reset_data[] = {
        UNIPHIER_PERI_RESET_UART(0, 0),
        UNIPHIER_PERI_RESET_UART(1, 1),
        UNIPHIER_PERI_RESET_UART(2, 2),
@@ -184,7 +201,7 @@ const struct uniphier_reset_data uniphier_ld4_peri_reset_data[] = {
        UNIPHIER_RESET_END,
 };
 
-const struct uniphier_reset_data uniphier_pro4_peri_reset_data[] = {
+static const struct uniphier_reset_data uniphier_pro4_peri_reset_data[] = {
        UNIPHIER_PERI_RESET_UART(0, 0),
        UNIPHIER_PERI_RESET_UART(1, 1),
        UNIPHIER_PERI_RESET_UART(2, 2),
index 5e66e081027e56ce00ac9273752a5c2bc34ea7c6..f7cade09d38a3d3476a14dfef67adba84bfad90f 100644 (file)
@@ -869,7 +869,7 @@ static int rpmsg_probe(struct virtio_device *vdev)
        init_waitqueue_head(&vrp->sendq);
 
        /* We expect two virtqueues, rx and tx (and in this order) */
-       err = vdev->config->find_vqs(vdev, 2, vqs, vq_cbs, names, NULL);
+       err = virtio_find_vqs(vdev, 2, vqs, vq_cbs, names, NULL);
        if (err)
                goto free_vrp;
 
index ee1b0e9dde79a9ec4720c516a697fd5de1e72fcf..8d3b9572832666a5bbe5f5be8ea5a5f0b8efa29e 100644 (file)
@@ -1303,10 +1303,10 @@ config RTC_DRV_SA1100
 
 config RTC_DRV_SH
        tristate "SuperH On-Chip RTC"
-       depends on SUPERH && HAVE_CLK
+       depends on SUPERH || ARCH_RENESAS
        help
          Say Y here to enable support for the on-chip RTC found in
-         most SuperH processors.
+         most SuperH processors. This RTC is also found in RZ/A SoCs.
 
          To compile this driver as a module, choose M here: the
          module will be called rtc-sh.
@@ -1731,6 +1731,13 @@ config RTC_DRV_STM32
           This driver can also be built as a module, if so, the module
           will be called "rtc-stm32".
 
+config RTC_DRV_CPCAP
+       depends on MFD_CPCAP
+       tristate "Motorola CPCAP RTC"
+       help
+          Say y here for CPCAP rtc found on some Motorola phones
+          and tablets such as Droid 4.
+
 comment "HID Sensor RTC drivers"
 
 config RTC_DRV_HID_SENSOR_TIME
index f07297b1460a06f2ed33c2b6b2ff11196f6955b0..13857d2fce09b24320db136c4e8deedc2f850259 100644 (file)
@@ -40,6 +40,7 @@ obj-$(CONFIG_RTC_DRV_BQ32K)   += rtc-bq32k.o
 obj-$(CONFIG_RTC_DRV_BQ4802)   += rtc-bq4802.o
 obj-$(CONFIG_RTC_DRV_CMOS)     += rtc-cmos.o
 obj-$(CONFIG_RTC_DRV_COH901331)        += rtc-coh901331.o
+obj-$(CONFIG_RTC_DRV_CPCAP)    += rtc-cpcap.o
 obj-$(CONFIG_RTC_DRV_DA9052)   += rtc-da9052.o
 obj-$(CONFIG_RTC_DRV_DA9055)   += rtc-da9055.o
 obj-$(CONFIG_RTC_DRV_DA9063)   += rtc-da9063.o
index 2b223935001fb57e92abdbbd360b02db70ada47c..98ac8d5c7901a59f438cb2ec83670caa54ce80fe 100644 (file)
@@ -310,9 +310,16 @@ static const struct i2c_device_id bq32k_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, bq32k_id);
 
+static const struct of_device_id bq32k_of_match[] = {
+       { .compatible = "ti,bq32000" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, bq32k_of_match);
+
 static struct i2c_driver bq32k_driver = {
        .driver = {
                .name   = "bq32k",
+               .of_match_table = of_match_ptr(bq32k_of_match),
        },
        .probe          = bq32k_probe,
        .remove         = bq32k_remove,
index f4a96dbdabf21ec4bdf8017e524ea42b9b0ce5c7..b3de973a62607de6812615e81ac1d00bce5c1f1a 100644 (file)
@@ -41,6 +41,9 @@
 #include <linux/pm.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
+#ifdef CONFIG_X86
+#include <asm/i8259.h>
+#endif
 
 /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */
 #include <linux/mc146818rtc.h>
@@ -1193,17 +1196,23 @@ static int cmos_pnp_probe(struct pnp_dev *pnp, const struct pnp_device_id *id)
 {
        cmos_wake_setup(&pnp->dev);
 
-       if (pnp_port_start(pnp, 0) == 0x70 && !pnp_irq_valid(pnp, 0))
+       if (pnp_port_start(pnp, 0) == 0x70 && !pnp_irq_valid(pnp, 0)) {
+               unsigned int irq = 0;
+#ifdef CONFIG_X86
                /* Some machines contain a PNP entry for the RTC, but
                 * don't define the IRQ. It should always be safe to
-                * hardcode it in these cases
+                * hardcode it on systems with a legacy PIC.
                 */
+               if (nr_legacy_irqs())
+                       irq = 8;
+#endif
                return cmos_do_probe(&pnp->dev,
-                               pnp_get_resource(pnp, IORESOURCE_IO, 0), 8);
-       else
+                               pnp_get_resource(pnp, IORESOURCE_IO, 0), irq);
+       } else {
                return cmos_do_probe(&pnp->dev,
                                pnp_get_resource(pnp, IORESOURCE_IO, 0),
                                pnp_irq(pnp, 0));
+       }
 }
 
 static void cmos_pnp_remove(struct pnp_dev *pnp)
diff --git a/drivers/rtc/rtc-cpcap.c b/drivers/rtc/rtc-cpcap.c
new file mode 100644 (file)
index 0000000..3a0333e
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+ * Motorola CPCAP PMIC RTC driver
+ *
+ * Based on cpcap-regulator.c from Motorola Linux kernel tree
+ * Copyright (C) 2009 Motorola, Inc.
+ *
+ * Rewritten for mainline kernel
+ *  - use DT
+ *  - use regmap
+ *  - use standard interrupt framework
+ *  - use managed device resources
+ *  - remove custom "secure clock daemon" helpers
+ *
+ * Copyright (C) 2017 Sebastian Reichel <sre@kernel.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+#include <linux/err.h>
+#include <linux/regmap.h>
+#include <linux/mfd/motorola-cpcap.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+
+#define SECS_PER_DAY 86400
+#define DAY_MASK  0x7FFF
+#define TOD1_MASK 0x00FF
+#define TOD2_MASK 0x01FF
+
+struct cpcap_time {
+       int day;
+       int tod1;
+       int tod2;
+};
+
+struct cpcap_rtc {
+       struct regmap *regmap;
+       struct rtc_device *rtc_dev;
+       u16 vendor;
+       int alarm_irq;
+       bool alarm_enabled;
+       int update_irq;
+       bool update_enabled;
+};
+
+static void cpcap2rtc_time(struct rtc_time *rtc, struct cpcap_time *cpcap)
+{
+       unsigned long int tod;
+       unsigned long int time;
+
+       tod = (cpcap->tod1 & TOD1_MASK) | ((cpcap->tod2 & TOD2_MASK) << 8);
+       time = tod + ((cpcap->day & DAY_MASK) * SECS_PER_DAY);
+
+       rtc_time_to_tm(time, rtc);
+}
+
+static void rtc2cpcap_time(struct cpcap_time *cpcap, struct rtc_time *rtc)
+{
+       unsigned long time;
+
+       rtc_tm_to_time(rtc, &time);
+
+       cpcap->day = time / SECS_PER_DAY;
+       time %= SECS_PER_DAY;
+       cpcap->tod2 = (time >> 8) & TOD2_MASK;
+       cpcap->tod1 = time & TOD1_MASK;
+}
+
+static int cpcap_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+       struct cpcap_rtc *rtc = dev_get_drvdata(dev);
+
+       if (rtc->alarm_enabled == enabled)
+               return 0;
+
+       if (enabled)
+               enable_irq(rtc->alarm_irq);
+       else
+               disable_irq(rtc->alarm_irq);
+
+       rtc->alarm_enabled = !!enabled;
+
+       return 0;
+}
+
+static int cpcap_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+       struct cpcap_rtc *rtc;
+       struct cpcap_time cpcap_tm;
+       int temp_tod2;
+       int ret;
+
+       rtc = dev_get_drvdata(dev);
+
+       ret = regmap_read(rtc->regmap, CPCAP_REG_TOD2, &temp_tod2);
+       ret |= regmap_read(rtc->regmap, CPCAP_REG_DAY, &cpcap_tm.day);
+       ret |= regmap_read(rtc->regmap, CPCAP_REG_TOD1, &cpcap_tm.tod1);
+       ret |= regmap_read(rtc->regmap, CPCAP_REG_TOD2, &cpcap_tm.tod2);
+
+       if (temp_tod2 > cpcap_tm.tod2)
+               ret |= regmap_read(rtc->regmap, CPCAP_REG_DAY, &cpcap_tm.day);
+
+       if (ret) {
+               dev_err(dev, "Failed to read time\n");
+               return -EIO;
+       }
+
+       cpcap2rtc_time(tm, &cpcap_tm);
+
+       return rtc_valid_tm(tm);
+}
+
+static int cpcap_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+       struct cpcap_rtc *rtc;
+       struct cpcap_time cpcap_tm;
+       int ret = 0;
+
+       rtc = dev_get_drvdata(dev);
+
+       rtc2cpcap_time(&cpcap_tm, tm);
+
+       if (rtc->alarm_enabled)
+               disable_irq(rtc->alarm_irq);
+       if (rtc->update_enabled)
+               disable_irq(rtc->update_irq);
+
+       if (rtc->vendor == CPCAP_VENDOR_ST) {
+               /* The TOD1 and TOD2 registers MUST be written in this order
+                * for the change to properly set.
+                */
+               ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_TOD1,
+                                         TOD1_MASK, cpcap_tm.tod1);
+               ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_TOD2,
+                                         TOD2_MASK, cpcap_tm.tod2);
+               ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_DAY,
+                                         DAY_MASK, cpcap_tm.day);
+       } else {
+               /* Clearing the upper lower 8 bits of the TOD guarantees that
+                * the upper half of TOD (TOD2) will not increment for 0xFF RTC
+                * ticks (255 seconds).  During this time we can safely write
+                * to DAY, TOD2, then TOD1 (in that order) and expect RTC to be
+                * synchronized to the exact time requested upon the final write
+                * to TOD1.
+                */
+               ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_TOD1,
+                                         TOD1_MASK, 0);
+               ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_DAY,
+                                         DAY_MASK, cpcap_tm.day);
+               ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_TOD2,
+                                         TOD2_MASK, cpcap_tm.tod2);
+               ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_TOD1,
+                                         TOD1_MASK, cpcap_tm.tod1);
+       }
+
+       if (rtc->update_enabled)
+               enable_irq(rtc->update_irq);
+       if (rtc->alarm_enabled)
+               enable_irq(rtc->alarm_irq);
+
+       return ret;
+}
+
+static int cpcap_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+       struct cpcap_rtc *rtc;
+       struct cpcap_time cpcap_tm;
+       int ret;
+
+       rtc = dev_get_drvdata(dev);
+
+       alrm->enabled = rtc->alarm_enabled;
+
+       ret = regmap_read(rtc->regmap, CPCAP_REG_DAYA, &cpcap_tm.day);
+       ret |= regmap_read(rtc->regmap, CPCAP_REG_TODA2, &cpcap_tm.tod2);
+       ret |= regmap_read(rtc->regmap, CPCAP_REG_TODA1, &cpcap_tm.tod1);
+
+       if (ret) {
+               dev_err(dev, "Failed to read time\n");
+               return -EIO;
+       }
+
+       cpcap2rtc_time(&alrm->time, &cpcap_tm);
+       return rtc_valid_tm(&alrm->time);
+}
+
+static int cpcap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+       struct cpcap_rtc *rtc;
+       struct cpcap_time cpcap_tm;
+       int ret;
+
+       rtc = dev_get_drvdata(dev);
+
+       rtc2cpcap_time(&cpcap_tm, &alrm->time);
+
+       if (rtc->alarm_enabled)
+               disable_irq(rtc->alarm_irq);
+
+       ret = regmap_update_bits(rtc->regmap, CPCAP_REG_DAYA, DAY_MASK,
+                                cpcap_tm.day);
+       ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_TODA2, TOD2_MASK,
+                                 cpcap_tm.tod2);
+       ret |= regmap_update_bits(rtc->regmap, CPCAP_REG_TODA1, TOD1_MASK,
+                                 cpcap_tm.tod1);
+
+       if (!ret) {
+               enable_irq(rtc->alarm_irq);
+               rtc->alarm_enabled = true;
+       }
+
+       return ret;
+}
+
+static const struct rtc_class_ops cpcap_rtc_ops = {
+       .read_time              = cpcap_rtc_read_time,
+       .set_time               = cpcap_rtc_set_time,
+       .read_alarm             = cpcap_rtc_read_alarm,
+       .set_alarm              = cpcap_rtc_set_alarm,
+       .alarm_irq_enable       = cpcap_rtc_alarm_irq_enable,
+};
+
+static irqreturn_t cpcap_rtc_alarm_irq(int irq, void *data)
+{
+       struct cpcap_rtc *rtc = data;
+
+       rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF);
+       return IRQ_HANDLED;
+}
+
+static irqreturn_t cpcap_rtc_update_irq(int irq, void *data)
+{
+       struct cpcap_rtc *rtc = data;
+
+       rtc_update_irq(rtc->rtc_dev, 1, RTC_UF | RTC_IRQF);
+       return IRQ_HANDLED;
+}
+
+static int cpcap_rtc_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct cpcap_rtc *rtc;
+       int err;
+
+       rtc = devm_kzalloc(dev, sizeof(*rtc), GFP_KERNEL);
+       if (!rtc)
+               return -ENOMEM;
+
+       rtc->regmap = dev_get_regmap(dev->parent, NULL);
+       if (!rtc->regmap)
+               return -ENODEV;
+
+       platform_set_drvdata(pdev, rtc);
+       rtc->rtc_dev = devm_rtc_device_register(dev, "cpcap_rtc",
+                                               &cpcap_rtc_ops, THIS_MODULE);
+
+       if (IS_ERR(rtc->rtc_dev))
+               return PTR_ERR(rtc->rtc_dev);
+
+       err = cpcap_get_vendor(dev, rtc->regmap, &rtc->vendor);
+       if (err)
+               return err;
+
+       rtc->alarm_irq = platform_get_irq(pdev, 0);
+       err = devm_request_threaded_irq(dev, rtc->alarm_irq, NULL,
+                                       cpcap_rtc_alarm_irq, IRQF_TRIGGER_NONE,
+                                       "rtc_alarm", rtc);
+       if (err) {
+               dev_err(dev, "Could not request alarm irq: %d\n", err);
+               return err;
+       }
+       disable_irq(rtc->alarm_irq);
+
+       /* Stock Android uses the 1 Hz interrupt for "secure clock daemon",
+        * which is not supported by the mainline kernel. The mainline kernel
+        * does not use the irq at the moment, but we explicitly request and
+        * disable it, so that its masked and does not wake up the processor
+        * every second.
+        */
+       rtc->update_irq = platform_get_irq(pdev, 1);
+       err = devm_request_threaded_irq(dev, rtc->update_irq, NULL,
+                                       cpcap_rtc_update_irq, IRQF_TRIGGER_NONE,
+                                       "rtc_1hz", rtc);
+       if (err) {
+               dev_err(dev, "Could not request update irq: %d\n", err);
+               return err;
+       }
+       disable_irq(rtc->update_irq);
+
+       err = device_init_wakeup(dev, 1);
+       if (err) {
+               dev_err(dev, "wakeup initialization failed (%d)\n", err);
+               /* ignore error and continue without wakeup support */
+       }
+
+       return 0;
+}
+
+static const struct of_device_id cpcap_rtc_of_match[] = {
+       { .compatible = "motorola,cpcap-rtc", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, cpcap_rtc_of_match);
+
+static struct platform_driver cpcap_rtc_driver = {
+       .probe          = cpcap_rtc_probe,
+       .driver         = {
+               .name   = "cpcap-rtc",
+               .of_match_table = cpcap_rtc_of_match,
+       },
+};
+
+module_platform_driver(cpcap_rtc_driver);
+
+MODULE_ALIAS("platform:cpcap-rtc");
+MODULE_DESCRIPTION("CPCAP RTC driver");
+MODULE_AUTHOR("Sebastian Reichel <sre@kernel.org>");
+MODULE_LICENSE("GPL");
index 4ad97be480430babc3321075f2739114eaad8f04..77339b3d50a1e8a9f921afa54340a30373e3d00b 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/i2c.h>
 #include <linux/init.h>
 #include <linux/module.h>
+#include <linux/of_device.h>
 #include <linux/rtc/ds1307.h>
 #include <linux/rtc.h>
 #include <linux/slab.h>
@@ -38,6 +39,7 @@ enum ds_type {
        ds_1340,
        ds_1388,
        ds_3231,
+       m41t0,
        m41t00,
        mcp794xx,
        rx_8025,
@@ -52,6 +54,7 @@ enum ds_type {
 #      define DS1340_BIT_nEOSC         0x80
 #      define MCP794XX_BIT_ST          0x80
 #define DS1307_REG_MIN         0x01    /* 00-59 */
+#      define M41T0_BIT_OF             0x80
 #define DS1307_REG_HOUR                0x02    /* 00-23, or 1-12{am,pm} */
 #      define DS1307_BIT_12HR          0x40    /* in REG_HOUR */
 #      define DS1307_BIT_PM            0x20    /* in REG_HOUR */
@@ -182,6 +185,7 @@ static const struct i2c_device_id ds1307_id[] = {
        { "ds1388", ds_1388 },
        { "ds1340", ds_1340 },
        { "ds3231", ds_3231 },
+       { "m41t0", m41t0 },
        { "m41t00", m41t00 },
        { "mcp7940x", mcp794xx },
        { "mcp7941x", mcp794xx },
@@ -192,6 +196,69 @@ static const struct i2c_device_id ds1307_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, ds1307_id);
 
+#ifdef CONFIG_OF
+static const struct of_device_id ds1307_of_match[] = {
+       {
+               .compatible = "dallas,ds1307",
+               .data = (void *)ds_1307
+       },
+       {
+               .compatible = "dallas,ds1337",
+               .data = (void *)ds_1337
+       },
+       {
+               .compatible = "dallas,ds1338",
+               .data = (void *)ds_1338
+       },
+       {
+               .compatible = "dallas,ds1339",
+               .data = (void *)ds_1339
+       },
+       {
+               .compatible = "dallas,ds1388",
+               .data = (void *)ds_1388
+       },
+       {
+               .compatible = "dallas,ds1340",
+               .data = (void *)ds_1340
+       },
+       {
+               .compatible = "maxim,ds3231",
+               .data = (void *)ds_3231
+       },
+       {
+               .compatible = "st,m41t0",
+               .data = (void *)m41t00
+       },
+       {
+               .compatible = "st,m41t00",
+               .data = (void *)m41t00
+       },
+       {
+               .compatible = "microchip,mcp7940x",
+               .data = (void *)mcp794xx
+       },
+       {
+               .compatible = "microchip,mcp7941x",
+               .data = (void *)mcp794xx
+       },
+       {
+               .compatible = "pericom,pt7c4338",
+               .data = (void *)ds_1307
+       },
+       {
+               .compatible = "epson,rx8025",
+               .data = (void *)rx_8025
+       },
+       {
+               .compatible = "isil,isl12057",
+               .data = (void *)ds_1337
+       },
+       { }
+};
+MODULE_DEVICE_TABLE(of, ds1307_of_match);
+#endif
+
 #ifdef CONFIG_ACPI
 static const struct acpi_device_id ds1307_acpi_ids[] = {
        { .id = "DS1307", .driver_data = ds_1307 },
@@ -201,6 +268,7 @@ static const struct acpi_device_id ds1307_acpi_ids[] = {
        { .id = "DS1388", .driver_data = ds_1388 },
        { .id = "DS1340", .driver_data = ds_1340 },
        { .id = "DS3231", .driver_data = ds_3231 },
+       { .id = "M41T0", .driver_data = m41t0 },
        { .id = "M41T00", .driver_data = m41t00 },
        { .id = "MCP7940X", .driver_data = mcp794xx },
        { .id = "MCP7941X", .driver_data = mcp794xx },
@@ -396,6 +464,13 @@ static int ds1307_get_time(struct device *dev, struct rtc_time *t)
 
        dev_dbg(dev, "%s: %7ph\n", "read", ds1307->regs);
 
+       /* if oscillator fail bit is set, no data can be trusted */
+       if (ds1307->type == m41t0 &&
+           ds1307->regs[DS1307_REG_MIN] & M41T0_BIT_OF) {
+               dev_warn_once(dev, "oscillator failed, set time!\n");
+               return -EINVAL;
+       }
+
        t->tm_sec = bcd2bin(ds1307->regs[DS1307_REG_SECS] & 0x7f);
        t->tm_min = bcd2bin(ds1307->regs[DS1307_REG_MIN] & 0x7f);
        tmp = ds1307->regs[DS1307_REG_HOUR] & 0x3f;
@@ -1318,7 +1393,12 @@ static int ds1307_probe(struct i2c_client *client,
        i2c_set_clientdata(client, ds1307);
 
        ds1307->client  = client;
-       if (id) {
+
+       if (client->dev.of_node) {
+               ds1307->type = (enum ds_type)
+                       of_device_get_match_data(&client->dev);
+               chip = &chips[ds1307->type];
+       } else if (id) {
                chip = &chips[id->driver_data];
                ds1307->type = id->driver_data;
        } else {
@@ -1513,6 +1593,7 @@ read_rtc:
        tmp = ds1307->regs[DS1307_REG_SECS];
        switch (ds1307->type) {
        case ds_1307:
+       case m41t0:
        case m41t00:
                /* clock halted?  turn it on, so clock can tick. */
                if (tmp & DS1307_BIT_CH) {
@@ -1577,6 +1658,7 @@ read_rtc:
        tmp = ds1307->regs[DS1307_REG_HOUR];
        switch (ds1307->type) {
        case ds_1340:
+       case m41t0:
        case m41t00:
                /*
                 * NOTE: ignores century bits; fix before deploying
@@ -1711,6 +1793,7 @@ static int ds1307_remove(struct i2c_client *client)
 static struct i2c_driver ds1307_driver = {
        .driver = {
                .name   = "rtc-ds1307",
+               .of_match_table = of_match_ptr(ds1307_of_match),
                .acpi_match_table = ACPI_PTR(ds1307_acpi_ids),
        },
        .probe          = ds1307_probe,
index 52429f0a57cc2125e428aa88be917a4268f44b35..38a2e9e684df43898086ebaa119cb7752d981794 100644 (file)
@@ -525,6 +525,10 @@ static long ds1374_wdt_ioctl(struct file *file, unsigned int cmd,
                if (get_user(new_margin, (int __user *)arg))
                        return -EFAULT;
 
+               /* the hardware's tick rate is 4096 Hz, so
+                * the counter value needs to be scaled accordingly
+                */
+               new_margin <<= 12;
                if (new_margin < 1 || new_margin > 16777216)
                        return -EINVAL;
 
@@ -533,7 +537,8 @@ static long ds1374_wdt_ioctl(struct file *file, unsigned int cmd,
                ds1374_wdt_ping();
                /* fallthrough */
        case WDIOC_GETTIMEOUT:
-               return put_user(wdt_margin, (int __user *)arg);
+               /* when returning ... inverse is true */
+               return put_user((wdt_margin >> 12), (int __user *)arg);
        case WDIOC_SETOPTIONS:
                if (copy_from_user(&options, (int __user *)arg, sizeof(int)))
                        return -EFAULT;
@@ -541,14 +546,15 @@ static long ds1374_wdt_ioctl(struct file *file, unsigned int cmd,
                if (options & WDIOS_DISABLECARD) {
                        pr_info("disable watchdog\n");
                        ds1374_wdt_disable();
+                       return 0;
                }
 
                if (options & WDIOS_ENABLECARD) {
                        pr_info("enable watchdog\n");
                        ds1374_wdt_settimeout(wdt_margin);
                        ds1374_wdt_ping();
+                       return 0;
                }
-
                return -EINVAL;
        }
        return -ENOTTY;
@@ -704,6 +710,7 @@ static SIMPLE_DEV_PM_OPS(ds1374_pm, ds1374_suspend, ds1374_resume);
 static struct i2c_driver ds1374_driver = {
        .driver = {
                .name = "rtc-ds1374",
+               .of_match_table = of_match_ptr(ds1374_of_match),
                .pm = &ds1374_pm,
        },
        .probe = ds1374_probe,
index 5c18ac7394c42a4cae30046ec30a1240ea66997a..7bf46bfe11a44a71a5d0067843283acad8979c1c 100644 (file)
@@ -196,10 +196,17 @@ static struct i2c_device_id ds1672_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, ds1672_id);
 
+static const struct of_device_id ds1672_of_match[] = {
+       { .compatible = "dallas,ds1672" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, ds1672_of_match);
+
 static struct i2c_driver ds1672_driver = {
        .driver = {
                   .name = "rtc-ds1672",
-                  },
+                  .of_match_table = of_match_ptr(ds1672_of_match),
+       },
        .probe = &ds1672_probe,
        .id_table = ds1672_id,
 };
index 9bb39a06b994ad5990b47870fe53fdaf7436dd7c..deff431a37c446359fb925605494b7e19c717911 100644 (file)
@@ -442,9 +442,16 @@ static const struct i2c_device_id ds3232_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, ds3232_id);
 
+static const struct of_device_id ds3232_of_match[] = {
+       { .compatible = "dallas,ds3232" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, ds3232_of_match);
+
 static struct i2c_driver ds3232_driver = {
        .driver = {
                .name = "rtc-ds3232",
+               .of_match_table = of_match_ptr(ds3232_of_match),
                .pm     = &ds3232_pm_ops,
        },
        .probe = ds3232_i2c_probe,
index ccf0dbadb62d16d7c512fffb9fc37efb7fcac7b8..5279390bb42da84d5f477a3098d7af39c3599e8c 100644 (file)
@@ -139,6 +139,8 @@ static int gemini_rtc_probe(struct platform_device *pdev)
 
        rtc->rtc_base = devm_ioremap(dev, res->start,
                                     resource_size(res));
+       if (!rtc->rtc_base)
+               return -ENOMEM;
 
        ret = devm_request_irq(dev, rtc->rtc_irq, gemini_rtc_interrupt,
                               IRQF_SHARED, pdev->name, dev);
index c398f74234c6914c3ebd4c3a80732f90e2d8b302..2751dba850c614f452d4f297e8bdbb461e9ae15d 100644 (file)
@@ -291,9 +291,9 @@ static int hid_time_probe(struct platform_device *pdev)
                                        "hid-sensor-time", &hid_time_rtc_ops,
                                        THIS_MODULE);
 
-       if (IS_ERR_OR_NULL(time_state->rtc)) {
+       if (IS_ERR(time_state->rtc)) {
                hid_device_io_stop(hsdev->hdev);
-               ret = time_state->rtc ? PTR_ERR(time_state->rtc) : -ENODEV;
+               ret = PTR_ERR(time_state->rtc);
                time_state->rtc = NULL;
                dev_err(&pdev->dev, "rtc device register failed!\n");
                goto err_rtc;
index 2893785f0eba221f4175cc9cd5237306ac9045bf..8dd299c6a1f338b522f524ee519e5892bf90fe46 100644 (file)
@@ -687,10 +687,18 @@ static const struct i2c_device_id isl1208_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, isl1208_id);
 
+static const struct of_device_id isl1208_of_match[] = {
+       { .compatible = "isil,isl1208" },
+       { .compatible = "isil,isl1218" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, isl1208_of_match);
+
 static struct i2c_driver isl1208_driver = {
        .driver = {
-                  .name = "rtc-isl1208",
-                  },
+               .name = "rtc-isl1208",
+               .of_match_table = of_match_ptr(isl1208_of_match),
+       },
        .probe = isl1208_probe,
        .remove = isl1208_remove,
        .id_table = isl1208_id,
index 58698d21c2c3d37878deedf442a34331659a5c7a..5ec4653022fff574ae8d4df2a31531d6963b5ca2 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/of_device.h>
 #include <linux/rtc.h>
 #include <linux/slab.h>
 #include <linux/mutex.h>
@@ -86,8 +87,66 @@ static const struct i2c_device_id m41t80_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, m41t80_id);
 
+static const struct of_device_id m41t80_of_match[] = {
+       {
+               .compatible = "st,m41t62",
+               .data = (void *)(M41T80_FEATURE_SQ | M41T80_FEATURE_SQ_ALT)
+       },
+       {
+               .compatible = "st,m41t65",
+               .data = (void *)(M41T80_FEATURE_HT | M41T80_FEATURE_WD)
+       },
+       {
+               .compatible = "st,m41t80",
+               .data = (void *)(M41T80_FEATURE_SQ)
+       },
+       {
+               .compatible = "st,m41t81",
+               .data = (void *)(M41T80_FEATURE_HT | M41T80_FEATURE_SQ)
+       },
+       {
+               .compatible = "st,m41t81s",
+               .data = (void *)(M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ)
+       },
+       {
+               .compatible = "st,m41t82",
+               .data = (void *)(M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ)
+       },
+       {
+               .compatible = "st,m41t83",
+               .data = (void *)(M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ)
+       },
+       {
+               .compatible = "st,m41t84",
+               .data = (void *)(M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ)
+       },
+       {
+               .compatible = "st,m41t85",
+               .data = (void *)(M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ)
+       },
+       {
+               .compatible = "st,m41t87",
+               .data = (void *)(M41T80_FEATURE_HT | M41T80_FEATURE_BL | M41T80_FEATURE_SQ)
+       },
+       {
+               .compatible = "microcrystal,rv4162",
+               .data = (void *)(M41T80_FEATURE_SQ | M41T80_FEATURE_WD | M41T80_FEATURE_SQ_ALT)
+       },
+       /* DT compatibility only, do not use compatibles below: */
+       {
+               .compatible = "st,rv4162",
+               .data = (void *)(M41T80_FEATURE_SQ | M41T80_FEATURE_WD | M41T80_FEATURE_SQ_ALT)
+       },
+       {
+               .compatible = "rv4162",
+               .data = (void *)(M41T80_FEATURE_SQ | M41T80_FEATURE_WD | M41T80_FEATURE_SQ_ALT)
+       },
+       { }
+};
+MODULE_DEVICE_TABLE(of, m41t80_of_match);
+
 struct m41t80_data {
-       u8 features;
+       unsigned long features;
        struct rtc_device *rtc;
 };
 
@@ -786,7 +845,11 @@ static int m41t80_probe(struct i2c_client *client,
        if (!m41t80_data)
                return -ENOMEM;
 
-       m41t80_data->features = id->driver_data;
+       if (client->dev.of_node)
+               m41t80_data->features = (unsigned long)
+                       of_device_get_match_data(&client->dev);
+       else
+               m41t80_data->features = id->driver_data;
        i2c_set_clientdata(client, m41t80_data);
 
        if (client->irq > 0) {
@@ -894,6 +957,7 @@ static int m41t80_remove(struct i2c_client *client)
 static struct i2c_driver m41t80_driver = {
        .driver = {
                .name = "rtc-m41t80",
+               .of_match_table = of_match_ptr(m41t80_of_match),
                .pm = &m41t80_pm,
        },
        .probe = m41t80_probe,
index 73594f38c453e3cbfe4d301b4a18404520a7d8ef..13f7cd11c07eb52948121225242b57f8ab2c8e2c 100644 (file)
@@ -844,7 +844,7 @@ err:
        return ret;
 }
 
-static int __exit omap_rtc_remove(struct platform_device *pdev)
+static int omap_rtc_remove(struct platform_device *pdev)
 {
        struct omap_rtc *rtc = platform_get_drvdata(pdev);
        u8 reg;
@@ -882,8 +882,7 @@ static int __exit omap_rtc_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int omap_rtc_suspend(struct device *dev)
+static int __maybe_unused omap_rtc_suspend(struct device *dev)
 {
        struct omap_rtc *rtc = dev_get_drvdata(dev);
 
@@ -906,7 +905,7 @@ static int omap_rtc_suspend(struct device *dev)
        return 0;
 }
 
-static int omap_rtc_resume(struct device *dev)
+static int __maybe_unused omap_rtc_resume(struct device *dev)
 {
        struct omap_rtc *rtc = dev_get_drvdata(dev);
 
@@ -921,10 +920,8 @@ static int omap_rtc_resume(struct device *dev)
 
        return 0;
 }
-#endif
 
-#ifdef CONFIG_PM
-static int omap_rtc_runtime_suspend(struct device *dev)
+static int __maybe_unused omap_rtc_runtime_suspend(struct device *dev)
 {
        struct omap_rtc *rtc = dev_get_drvdata(dev);
 
@@ -934,16 +931,9 @@ static int omap_rtc_runtime_suspend(struct device *dev)
        return 0;
 }
 
-static int omap_rtc_runtime_resume(struct device *dev)
-{
-       return 0;
-}
-#endif
-
 static const struct dev_pm_ops omap_rtc_pm_ops = {
        SET_SYSTEM_SLEEP_PM_OPS(omap_rtc_suspend, omap_rtc_resume)
-       SET_RUNTIME_PM_OPS(omap_rtc_runtime_suspend,
-                          omap_rtc_runtime_resume, NULL)
+       SET_RUNTIME_PM_OPS(omap_rtc_runtime_suspend, NULL, NULL)
 };
 
 static void omap_rtc_shutdown(struct platform_device *pdev)
@@ -964,7 +954,7 @@ static void omap_rtc_shutdown(struct platform_device *pdev)
 
 static struct platform_driver omap_rtc_driver = {
        .probe          = omap_rtc_probe,
-       .remove         = __exit_p(omap_rtc_remove),
+       .remove         = omap_rtc_remove,
        .shutdown       = omap_rtc_shutdown,
        .driver         = {
                .name   = "omap_rtc",
index c8c7574667837522ae4863f743ba978229116fc5..d4eff8d7131fd171769cc4238e8f550758e30b53 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/bcd.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/of_device.h>
 
 /*
  * Ricoh has a family of I2C based RTCs, which differ only slightly from
@@ -83,6 +84,35 @@ static const struct i2c_device_id rs5c372_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, rs5c372_id);
 
+static const struct of_device_id rs5c372_of_match[] = {
+       {
+               .compatible = "ricoh,r2025sd",
+               .data = (void *)rtc_r2025sd
+       },
+       {
+               .compatible = "ricoh,r2221tl",
+               .data = (void *)rtc_r2221tl
+       },
+       {
+               .compatible = "ricoh,rs5c372a",
+               .data = (void *)rtc_rs5c372a
+       },
+       {
+               .compatible = "ricoh,rs5c372b",
+               .data = (void *)rtc_rs5c372b
+       },
+       {
+               .compatible = "ricoh,rv5c386",
+               .data = (void *)rtc_rv5c386
+       },
+       {
+               .compatible = "ricoh,rv5c387a",
+               .data = (void *)rtc_rv5c387a
+       },
+       { }
+};
+MODULE_DEVICE_TABLE(of, rs5c372_of_match);
+
 /* REVISIT:  this assumes that:
  *  - we're in the 21st century, so it's safe to ignore the century
  *    bit for rv5c38[67] (REG_MONTH bit 7);
@@ -581,7 +611,11 @@ static int rs5c372_probe(struct i2c_client *client,
 
        rs5c372->client = client;
        i2c_set_clientdata(client, rs5c372);
-       rs5c372->type = id->driver_data;
+       if (client->dev.of_node)
+               rs5c372->type = (enum rtc_type)
+                       of_device_get_match_data(&client->dev);
+       else
+               rs5c372->type = id->driver_data;
 
        /* we read registers 0x0f then 0x00-0x0f; skip the first one */
        rs5c372->regs = &rs5c372->buf[1];
@@ -673,6 +707,7 @@ static int rs5c372_remove(struct i2c_client *client)
 static struct i2c_driver rs5c372_driver = {
        .driver         = {
                .name   = "rtc-rs5c372",
+               .of_match_table = of_match_ptr(rs5c372_of_match),
        },
        .probe          = rs5c372_probe,
        .remove         = rs5c372_remove,
index 1f9f7b4bf3fb2d4c94d430dcb34d4fa7cd1f9139..85fa1da03762cafd4991bfbf6e2aab421532a475 100644 (file)
@@ -875,9 +875,18 @@ static struct i2c_device_id rv3029_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, rv3029_id);
 
+static const struct of_device_id rv3029_of_match[] = {
+       { .compatible = "rv3029" },
+       { .compatible = "rv3029c2" },
+       { .compatible = "mc,rv3029c2" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, rv3029_of_match);
+
 static struct i2c_driver rv3029_driver = {
        .driver = {
                .name = "rtc-rv3029c2",
+               .of_match_table = of_match_ptr(rv3029_of_match),
        },
        .probe          = rv3029_i2c_probe,
        .id_table       = rv3029_id,
index f9277e536f7e8754120da35b17581b9f1492c632..9ad97ab298664c9bda5bc221aa94f9cef97173b1 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/interrupt.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/of_device.h>
 #include <linux/rtc.h>
 
 #define RV8803_I2C_TRY_COUNT           4
@@ -556,7 +557,11 @@ static int rv8803_probe(struct i2c_client *client,
 
        mutex_init(&rv8803->flags_lock);
        rv8803->client = client;
-       rv8803->type = id->driver_data;
+       if (client->dev.of_node)
+               rv8803->type = (enum rv8803_type)
+                       of_device_get_match_data(&client->dev);
+       else
+               rv8803->type = id->driver_data;
        i2c_set_clientdata(client, rv8803);
 
        flags = rv8803_read_reg(client, RV8803_FLAG);
@@ -627,9 +632,23 @@ static const struct i2c_device_id rv8803_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, rv8803_id);
 
+static const struct of_device_id rv8803_of_match[] = {
+       {
+               .compatible = "microcrystal,rv8803",
+               .data = (void *)rx_8900
+       },
+       {
+               .compatible = "epson,rx8900",
+               .data = (void *)rx_8900
+       },
+       { }
+};
+MODULE_DEVICE_TABLE(of, rv8803_of_match);
+
 static struct i2c_driver rv8803_driver = {
        .driver = {
                .name = "rtc-rv8803",
+               .of_match_table = of_match_ptr(rv8803_of_match),
        },
        .probe          = rv8803_probe,
        .remove         = rv8803_remove,
index d08da371912cd868e496cbfd417d59067d04ce3a..1ed3403ff8ac23ae1c9c2923b76f3f8aff1c9c11 100644 (file)
@@ -59,6 +59,12 @@ static const struct i2c_device_id rx8010_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, rx8010_id);
 
+static const struct of_device_id rx8010_of_match[] = {
+       { .compatible = "epson,rx8010" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, rx8010_of_match);
+
 struct rx8010_data {
        struct i2c_client *client;
        struct rtc_device *rtc;
@@ -487,6 +493,7 @@ static int rx8010_probe(struct i2c_client *client,
 static struct i2c_driver rx8010_driver = {
        .driver = {
                .name = "rtc-rx8010",
+               .of_match_table = of_match_ptr(rx8010_of_match),
        },
        .probe          = rx8010_probe,
        .id_table       = rx8010_id,
index 0c362a3d1f178d6f19e12c1b051f5a2eef53666e..9998d7937688c6e27d351c846cdfe16b978b48ef 100644 (file)
@@ -308,9 +308,16 @@ static const struct i2c_device_id rx8581_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, rx8581_id);
 
+static const struct of_device_id rx8581_of_match[] = {
+       { .compatible = "epson,rx8581" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, rx8581_of_match);
+
 static struct i2c_driver rx8581_driver = {
        .driver         = {
                .name   = "rtc-rx8581",
+               .of_match_table = of_match_ptr(rx8581_of_match),
        },
        .probe          = rx8581_probe,
        .id_table       = rx8581_id,
index 5dab4665ca3bd2c488fd4548f15fce3945bb6fad..449820eeefe813f993348a1f018fd7fd41868c6f 100644 (file)
@@ -58,6 +58,13 @@ static const struct i2c_device_id s35390a_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, s35390a_id);
 
+static const struct of_device_id s35390a_of_match[] = {
+       { .compatible = "s35390a" },
+       { .compatible = "sii,s35390a" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, s35390a_of_match);
+
 struct s35390a {
        struct i2c_client *client[8];
        struct rtc_device *rtc;
@@ -502,6 +509,7 @@ static int s35390a_remove(struct i2c_client *client)
 static struct i2c_driver s35390a_driver = {
        .driver         = {
                .name   = "rtc-s35390a",
+               .of_match_table = of_match_ptr(s35390a_of_match),
        },
        .probe          = s35390a_probe,
        .remove         = s35390a_remove,
index c626e43a9cbb48f6c254517dc858dd1451c550d3..6c2d3989f967baff96625ab39d0d19336b002def 100644 (file)
 #include <linux/log2.h>
 #include <linux/clk.h>
 #include <linux/slab.h>
+#ifdef CONFIG_SUPERH
 #include <asm/rtc.h>
+#else
+/* Default values for RZ/A RTC */
+#define rtc_reg_size           sizeof(u16)
+#define RTC_BIT_INVERTED        0      /* no chip bugs */
+#define RTC_CAP_4_DIGIT_YEAR    (1 << 0)
+#define RTC_DEF_CAPABILITIES    RTC_CAP_4_DIGIT_YEAR
+#endif
 
 #define DRV_NAME       "sh-rtc"
 
@@ -570,6 +578,8 @@ static int __init sh_rtc_probe(struct platform_device *pdev)
        rtc->alarm_irq = platform_get_irq(pdev, 2);
 
        res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+       if (!res)
+               res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (unlikely(res == NULL)) {
                dev_err(&pdev->dev, "No IO resource\n");
                return -ENOENT;
@@ -587,12 +597,15 @@ static int __init sh_rtc_probe(struct platform_device *pdev)
        if (unlikely(!rtc->regbase))
                return -EINVAL;
 
-       clk_id = pdev->id;
-       /* With a single device, the clock id is still "rtc0" */
-       if (clk_id < 0)
-               clk_id = 0;
+       if (!pdev->dev.of_node) {
+               clk_id = pdev->id;
+               /* With a single device, the clock id is still "rtc0" */
+               if (clk_id < 0)
+                       clk_id = 0;
 
-       snprintf(clk_name, sizeof(clk_name), "rtc%d", clk_id);
+               snprintf(clk_name, sizeof(clk_name), "rtc%d", clk_id);
+       } else
+               snprintf(clk_name, sizeof(clk_name), "fck");
 
        rtc->clk = devm_clk_get(&pdev->dev, clk_name);
        if (IS_ERR(rtc->clk)) {
@@ -608,6 +621,8 @@ static int __init sh_rtc_probe(struct platform_device *pdev)
        clk_enable(rtc->clk);
 
        rtc->capabilities = RTC_DEF_CAPABILITIES;
+
+#ifdef CONFIG_SUPERH
        if (dev_get_platdata(&pdev->dev)) {
                struct sh_rtc_platform_info *pinfo =
                        dev_get_platdata(&pdev->dev);
@@ -618,6 +633,7 @@ static int __init sh_rtc_probe(struct platform_device *pdev)
                 */
                rtc->capabilities |= pinfo->capabilities;
        }
+#endif
 
        if (rtc->carry_irq <= 0) {
                /* register shared periodic/carry/alarm irq */
@@ -718,8 +734,7 @@ static void sh_rtc_set_irq_wake(struct device *dev, int enabled)
        }
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int sh_rtc_suspend(struct device *dev)
+static int __maybe_unused sh_rtc_suspend(struct device *dev)
 {
        if (device_may_wakeup(dev))
                sh_rtc_set_irq_wake(dev, 1);
@@ -727,21 +742,27 @@ static int sh_rtc_suspend(struct device *dev)
        return 0;
 }
 
-static int sh_rtc_resume(struct device *dev)
+static int __maybe_unused sh_rtc_resume(struct device *dev)
 {
        if (device_may_wakeup(dev))
                sh_rtc_set_irq_wake(dev, 0);
 
        return 0;
 }
-#endif
 
 static SIMPLE_DEV_PM_OPS(sh_rtc_pm_ops, sh_rtc_suspend, sh_rtc_resume);
 
+static const struct of_device_id sh_rtc_of_match[] = {
+       { .compatible = "renesas,sh-rtc", },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, sh_rtc_of_match);
+
 static struct platform_driver sh_rtc_platform_driver = {
        .driver         = {
                .name   = DRV_NAME,
                .pm     = &sh_rtc_pm_ops,
+               .of_match_table = sh_rtc_of_match,
        },
        .remove         = __exit_p(sh_rtc_remove),
 };
index d51b07d620f7bd6fadbbf66f666870d8e50516f0..d8ef9e052c4fc71f38a871a8293271cb469d495b 100644 (file)
@@ -258,7 +258,7 @@ static int snvs_rtc_probe(struct platform_device *pdev)
                of_property_read_u32(pdev->dev.of_node, "offset", &data->offset);
        }
 
-       if (!data->regmap) {
+       if (IS_ERR(data->regmap)) {
                dev_err(&pdev->dev, "Can't find snvs syscon\n");
                return -ENODEV;
        }
index fa247deb9cf40df95fb7f4e8dc238f1c4291a112..483c7993516bb1f3326f54bb595b5144de6c694b 100644 (file)
@@ -30,8 +30,6 @@
 #define WM8350_SET_TIME_RETRIES        5
 #define WM8350_GET_TIME_RETRIES        5
 
-#define to_wm8350_from_rtc_dev(d) container_of(d, struct wm8350, rtc.pdev.dev)
-
 /*
  * Read current time and date in RTC
  */
index e443b0d0b23612efec3800a5468e36e58ef7f8d3..34b9ad6b31438fb8864a9068d7f72294722da169 100644 (file)
@@ -35,7 +35,7 @@ static struct bus_type ccwgroup_bus_type;
 static void __ccwgroup_remove_symlinks(struct ccwgroup_device *gdev)
 {
        int i;
-       char str[8];
+       char str[16];
 
        for (i = 0; i < gdev->count; i++) {
                sprintf(str, "cdev%d", i);
@@ -238,7 +238,7 @@ static void ccwgroup_release(struct device *dev)
 
 static int __ccwgroup_create_symlinks(struct ccwgroup_device *gdev)
 {
-       char str[8];
+       char str[16];
        int i, rc;
 
        for (i = 0; i < gdev->count; i++) {
index f33ce85776190ab938548dccbc84fb311d3703fd..1d595d17bf11f6b529eca2caafc494721130b32c 100644 (file)
@@ -11,7 +11,7 @@
 #include "qdio.h"
 
 /* that gives us 15 characters in the text event views */
-#define QDIO_DBF_LEN   16
+#define QDIO_DBF_LEN   32
 
 extern debug_info_t *qdio_dbf_setup;
 extern debug_info_t *qdio_dbf_error;
index f6aa21176d89780e9e745f9045255ff37f1cf788..30bc6105aac3731f2bfad5ffd0d4f14f07f9d291 100644 (file)
@@ -701,6 +701,7 @@ enum qeth_discipline_id {
 };
 
 struct qeth_discipline {
+       const struct device_type *devtype;
        void (*start_poll)(struct ccw_device *, int, unsigned long);
        qdio_handler_t *input_handler;
        qdio_handler_t *output_handler;
@@ -875,6 +876,9 @@ extern struct qeth_discipline qeth_l2_discipline;
 extern struct qeth_discipline qeth_l3_discipline;
 extern const struct attribute_group *qeth_generic_attr_groups[];
 extern const struct attribute_group *qeth_osn_attr_groups[];
+extern const struct attribute_group qeth_device_attr_group;
+extern const struct attribute_group qeth_device_blkt_group;
+extern const struct device_type qeth_generic_devtype;
 extern struct workqueue_struct *qeth_wq;
 
 int qeth_card_hw_is_reachable(struct qeth_card *);
index 38114a8d56e00f471360ab400767dcb8ba8a1a7b..fc6d85f2b38d60d4c1b62bd169776d5cfcabcc52 100644 (file)
@@ -5530,10 +5530,12 @@ void qeth_core_free_discipline(struct qeth_card *card)
        card->discipline = NULL;
 }
 
-static const struct device_type qeth_generic_devtype = {
+const struct device_type qeth_generic_devtype = {
        .name = "qeth_generic",
        .groups = qeth_generic_attr_groups,
 };
+EXPORT_SYMBOL_GPL(qeth_generic_devtype);
+
 static const struct device_type qeth_osn_devtype = {
        .name = "qeth_osn",
        .groups = qeth_osn_attr_groups,
@@ -5659,23 +5661,22 @@ static int qeth_core_probe_device(struct ccwgroup_device *gdev)
                goto err_card;
        }
 
-       if (card->info.type == QETH_CARD_TYPE_OSN)
-               gdev->dev.type = &qeth_osn_devtype;
-       else
-               gdev->dev.type = &qeth_generic_devtype;
-
        switch (card->info.type) {
        case QETH_CARD_TYPE_OSN:
        case QETH_CARD_TYPE_OSM:
                rc = qeth_core_load_discipline(card, QETH_DISCIPLINE_LAYER2);
                if (rc)
                        goto err_card;
+
+               gdev->dev.type = (card->info.type != QETH_CARD_TYPE_OSN)
+                                       ? card->discipline->devtype
+                                       : &qeth_osn_devtype;
                rc = card->discipline->setup(card->gdev);
                if (rc)
                        goto err_disc;
-       case QETH_CARD_TYPE_OSD:
-       case QETH_CARD_TYPE_OSX:
+               break;
        default:
+               gdev->dev.type = &qeth_generic_devtype;
                break;
        }
 
@@ -5731,8 +5732,10 @@ static int qeth_core_set_online(struct ccwgroup_device *gdev)
                if (rc)
                        goto err;
                rc = card->discipline->setup(card->gdev);
-               if (rc)
+               if (rc) {
+                       qeth_core_free_discipline(card);
                        goto err;
+               }
        }
        rc = card->discipline->set_online(gdev);
 err:
index 75b29fd2fcf4eab64e82b23b1183fe88211d97ba..db6a285d41e033674706543c2353c0312046e331 100644 (file)
@@ -413,12 +413,16 @@ static ssize_t qeth_dev_layer2_store(struct device *dev,
 
        if (card->options.layer2 == newdis)
                goto out;
-       else {
-               card->info.mac_bits  = 0;
-               if (card->discipline) {
-                       card->discipline->remove(card->gdev);
-                       qeth_core_free_discipline(card);
-               }
+       if (card->info.type == QETH_CARD_TYPE_OSM) {
+               /* fixed layer, can't switch */
+               rc = -EOPNOTSUPP;
+               goto out;
+       }
+
+       card->info.mac_bits = 0;
+       if (card->discipline) {
+               card->discipline->remove(card->gdev);
+               qeth_core_free_discipline(card);
        }
 
        rc = qeth_core_load_discipline(card, newdis);
@@ -426,6 +430,8 @@ static ssize_t qeth_dev_layer2_store(struct device *dev,
                goto out;
 
        rc = card->discipline->setup(card->gdev);
+       if (rc)
+               qeth_core_free_discipline(card);
 out:
        mutex_unlock(&card->discipline_mutex);
        return rc ? rc : count;
@@ -703,10 +709,11 @@ static struct attribute *qeth_blkt_device_attrs[] = {
        &dev_attr_inter_jumbo.attr,
        NULL,
 };
-static struct attribute_group qeth_device_blkt_group = {
+const struct attribute_group qeth_device_blkt_group = {
        .name = "blkt",
        .attrs = qeth_blkt_device_attrs,
 };
+EXPORT_SYMBOL_GPL(qeth_device_blkt_group);
 
 static struct attribute *qeth_device_attrs[] = {
        &dev_attr_state.attr,
@@ -726,9 +733,10 @@ static struct attribute *qeth_device_attrs[] = {
        &dev_attr_switch_attrs.attr,
        NULL,
 };
-static struct attribute_group qeth_device_attr_group = {
+const struct attribute_group qeth_device_attr_group = {
        .attrs = qeth_device_attrs,
 };
+EXPORT_SYMBOL_GPL(qeth_device_attr_group);
 
 const struct attribute_group *qeth_generic_attr_groups[] = {
        &qeth_device_attr_group,
index 29d9fb3890ad570826db6d54b1396c149f83fcb5..0d59f9a45ea9e3c52ba4eee9cbc7b37b433dd449 100644 (file)
@@ -8,6 +8,8 @@
 
 #include "qeth_core.h"
 
+extern const struct attribute_group *qeth_l2_attr_groups[];
+
 int qeth_l2_create_device_attributes(struct device *);
 void qeth_l2_remove_device_attributes(struct device *);
 void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card);
index 1b07f382d74c955974d138271bdce2bbbf594f63..bd2df62a5cdf50a85243a878ed98d4d1784b9106 100644 (file)
@@ -880,11 +880,21 @@ static int qeth_l2_stop(struct net_device *dev)
        return 0;
 }
 
+static const struct device_type qeth_l2_devtype = {
+       .name = "qeth_layer2",
+       .groups = qeth_l2_attr_groups,
+};
+
 static int qeth_l2_probe_device(struct ccwgroup_device *gdev)
 {
        struct qeth_card *card = dev_get_drvdata(&gdev->dev);
+       int rc;
 
-       qeth_l2_create_device_attributes(&gdev->dev);
+       if (gdev->dev.type == &qeth_generic_devtype) {
+               rc = qeth_l2_create_device_attributes(&gdev->dev);
+               if (rc)
+                       return rc;
+       }
        INIT_LIST_HEAD(&card->vid_list);
        hash_init(card->mac_htable);
        card->options.layer2 = 1;
@@ -896,7 +906,8 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev)
 {
        struct qeth_card *card = dev_get_drvdata(&cgdev->dev);
 
-       qeth_l2_remove_device_attributes(&cgdev->dev);
+       if (cgdev->dev.type == &qeth_generic_devtype)
+               qeth_l2_remove_device_attributes(&cgdev->dev);
        qeth_set_allowed_threads(card, 0, 1);
        wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
 
@@ -954,7 +965,6 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
        case QETH_CARD_TYPE_OSN:
                card->dev = alloc_netdev(0, "osn%d", NET_NAME_UNKNOWN,
                                         ether_setup);
-               card->dev->flags |= IFF_NOARP;
                break;
        default:
                card->dev = alloc_etherdev(0);
@@ -969,9 +979,12 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)
        card->dev->min_mtu = 64;
        card->dev->max_mtu = ETH_MAX_MTU;
        card->dev->netdev_ops = &qeth_l2_netdev_ops;
-       card->dev->ethtool_ops =
-               (card->info.type != QETH_CARD_TYPE_OSN) ?
-               &qeth_l2_ethtool_ops : &qeth_l2_osn_ops;
+       if (card->info.type == QETH_CARD_TYPE_OSN) {
+               card->dev->ethtool_ops = &qeth_l2_osn_ops;
+               card->dev->flags |= IFF_NOARP;
+       } else {
+               card->dev->ethtool_ops = &qeth_l2_ethtool_ops;
+       }
        card->dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER;
        if (card->info.type == QETH_CARD_TYPE_OSD && !card->info.guestlan) {
                card->dev->hw_features = NETIF_F_SG;
@@ -1269,6 +1282,7 @@ static int qeth_l2_control_event(struct qeth_card *card,
 }
 
 struct qeth_discipline qeth_l2_discipline = {
+       .devtype = &qeth_l2_devtype,
        .start_poll = qeth_qdio_start_poll,
        .input_handler = (qdio_handler_t *) qeth_qdio_input_handler,
        .output_handler = (qdio_handler_t *) qeth_qdio_output_handler,
index 687972356d6b00f8776cb332e31b1ae0063183a5..9696baa49e2d4409062be4338ea383472a7d4ab0 100644 (file)
@@ -269,3 +269,11 @@ void qeth_l2_setup_bridgeport_attrs(struct qeth_card *card)
        } else
                qeth_bridgeport_an_set(card, 0);
 }
+
+const struct attribute_group *qeth_l2_attr_groups[] = {
+       &qeth_device_attr_group,
+       &qeth_device_blkt_group,
+       /* l2 specific, see l2_{create,remove}_device_attributes(): */
+       &qeth_l2_bridgeport_attr_group,
+       NULL,
+};
index 6e0354ef4b8629827e4c8ef40b9d569bc11e354b..d8df1e6351636250ea534cf17527c8fb198435f2 100644 (file)
@@ -3039,8 +3039,13 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)
 static int qeth_l3_probe_device(struct ccwgroup_device *gdev)
 {
        struct qeth_card *card = dev_get_drvdata(&gdev->dev);
+       int rc;
 
-       qeth_l3_create_device_attributes(&gdev->dev);
+       rc = qeth_l3_create_device_attributes(&gdev->dev);
+       if (rc)
+               return rc;
+       hash_init(card->ip_htable);
+       hash_init(card->ip_mc_htable);
        card->options.layer2 = 0;
        card->info.hwtrap = 0;
        return 0;
@@ -3306,6 +3311,7 @@ static int qeth_l3_control_event(struct qeth_card *card,
 }
 
 struct qeth_discipline qeth_l3_discipline = {
+       .devtype = &qeth_generic_devtype,
        .start_poll = qeth_qdio_start_poll,
        .input_handler = (qdio_handler_t *) qeth_qdio_input_handler,
        .output_handler = (qdio_handler_t *) qeth_qdio_output_handler,
index 2ce0b3eb2efebc89121b8cd938d3677e936bffa4..a99d09a11f05eed1e317de5e8f06c549ab760b8b 100644 (file)
@@ -189,7 +189,7 @@ static bool kvm_notify(struct virtqueue *vq)
 static struct virtqueue *kvm_find_vq(struct virtio_device *vdev,
                                     unsigned index,
                                     void (*callback)(struct virtqueue *vq),
-                                    const char *name)
+                                    const char *name, bool ctx)
 {
        struct kvm_device *kdev = to_kvmdev(vdev);
        struct kvm_vqconfig *config;
@@ -211,7 +211,7 @@ static struct virtqueue *kvm_find_vq(struct virtio_device *vdev,
                goto out;
 
        vq = vring_new_virtqueue(index, config->num, KVM_S390_VIRTIO_RING_ALIGN,
-                                vdev, true, (void *) config->address,
+                                vdev, true, ctx, (void *) config->address,
                                 kvm_notify, callback, name);
        if (!vq) {
                err = -ENOMEM;
@@ -256,6 +256,7 @@ static int kvm_find_vqs(struct virtio_device *vdev, unsigned nvqs,
                        struct virtqueue *vqs[],
                        vq_callback_t *callbacks[],
                        const char * const names[],
+                       const bool *ctx,
                        struct irq_affinity *desc)
 {
        struct kvm_device *kdev = to_kvmdev(vdev);
@@ -266,7 +267,8 @@ static int kvm_find_vqs(struct virtio_device *vdev, unsigned nvqs,
                return -ENOENT;
 
        for (i = 0; i < nvqs; ++i) {
-               vqs[i] = kvm_find_vq(vdev, i, callbacks[i], names[i]);
+               vqs[i] = kvm_find_vq(vdev, i, callbacks[i], names[i],
+                                    ctx ? ctx[i] : false);
                if (IS_ERR(vqs[i]))
                        goto error;
        }
index 0ed209f3d8b0c5d572a712e5943b358ec19f3bb0..b18fe2014cf2195a193186c08c956dc8e5cfe7e3 100644 (file)
@@ -87,7 +87,7 @@ struct vq_info_block {
 } __packed;
 
 struct virtio_feature_desc {
-       __u32 features;
+       __le32 features;
        __u8 index;
 } __packed;
 
@@ -484,7 +484,7 @@ static void virtio_ccw_del_vqs(struct virtio_device *vdev)
 
 static struct virtqueue *virtio_ccw_setup_vq(struct virtio_device *vdev,
                                             int i, vq_callback_t *callback,
-                                            const char *name,
+                                            const char *name, bool ctx,
                                             struct ccw1 *ccw)
 {
        struct virtio_ccw_device *vcdev = to_vc_device(vdev);
@@ -522,7 +522,7 @@ static struct virtqueue *virtio_ccw_setup_vq(struct virtio_device *vdev,
        }
 
        vq = vring_new_virtqueue(i, info->num, KVM_VIRTIO_CCW_RING_ALIGN, vdev,
-                                true, info->queue, virtio_ccw_kvm_notify,
+                                true, ctx, info->queue, virtio_ccw_kvm_notify,
                                 callback, name);
        if (!vq) {
                /* For now, we fail if we can't get the requested size. */
@@ -629,6 +629,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
                               struct virtqueue *vqs[],
                               vq_callback_t *callbacks[],
                               const char * const names[],
+                              const bool *ctx,
                               struct irq_affinity *desc)
 {
        struct virtio_ccw_device *vcdev = to_vc_device(vdev);
@@ -642,7 +643,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 
        for (i = 0; i < nvqs; ++i) {
                vqs[i] = virtio_ccw_setup_vq(vdev, i, callbacks[i], names[i],
-                                            ccw);
+                                            ctx ? ctx[i] : false, ccw);
                if (IS_ERR(vqs[i])) {
                        ret = PTR_ERR(vqs[i]);
                        vqs[i] = NULL;
index f44d0487236e34d20622ff9840af68f5170b537c..ce5dc73d85bb1a467388cad7d86b3a5075e0f041 100644 (file)
@@ -331,11 +331,11 @@ MODULE_LICENSE("GPL");
 #if !defined(PCMCIA)
 #if defined(MODULE)
 static int io[] = {0, 0};
-module_param_array(io, int, NULL, 0);
+module_param_hw_array(io, int, ioport, NULL, 0);
 MODULE_PARM_DESC(io,"base io address of controller");
 
 static int irq[] = {0, 0};
-module_param_array(irq, int, NULL, 0);
+module_param_hw_array(irq, int, irq, NULL, 0);
 MODULE_PARM_DESC(irq,"interrupt for controller");
 
 static int scsiid[] = {7, 7};
index 7db448ec8bebe7a97c7edfbf1249d092c50d6e5b..a23cc9ac5acdad15b3d3a95a2227b969f10ba791 100644 (file)
@@ -31,7 +31,7 @@ module_param(isapnp, bool, 0);
 MODULE_PARM_DESC(isapnp, "enable PnP support (default=1)");
 
 static int io[MAXBOARDS] = { 0x330, 0x334, 0, 0 };
-module_param_array(io, int, NULL, 0);
+module_param_hw_array(io, int, ioport, NULL, 0);
 MODULE_PARM_DESC(io, "base IO address of controller (0x130,0x134,0x230,0x234,0x330,0x334, default=0x330,0x334)");
 
 /* time AHA spends on the AT-bus during data transfer */
index 67c8dac321ad217895f7ef877e1439748d5456e1..c34fc91ba48668c09970c5a83a6bd38fa90ccd12 100644 (file)
@@ -85,8 +85,8 @@ static int ncr_53c400;
 static int ncr_53c400a;
 static int dtc_3181e;
 static int hp_c2502;
-module_param(ncr_irq, int, 0);
-module_param(ncr_addr, int, 0);
+module_param_hw(ncr_irq, int, irq, 0);
+module_param_hw(ncr_addr, int, ioport, 0);
 module_param(ncr_5380, int, 0);
 module_param(ncr_53c400, int, 0);
 module_param(ncr_53c400a, int, 0);
@@ -94,11 +94,11 @@ module_param(dtc_3181e, int, 0);
 module_param(hp_c2502, int, 0);
 
 static int irq[] = { -1, -1, -1, -1, -1, -1, -1, -1 };
-module_param_array(irq, int, NULL, 0);
+module_param_hw_array(irq, int, irq, NULL, 0);
 MODULE_PARM_DESC(irq, "IRQ number(s) (0=none, 254=auto [default])");
 
 static int base[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
-module_param_array(base, int, NULL, 0);
+module_param_hw_array(base, int, ioport, NULL, 0);
 MODULE_PARM_DESC(base, "base address(es)");
 
 static int card[] = { -1, -1, -1, -1, -1, -1, -1, -1 };
index d020a13646ae648914ae65e2438e2d474d023662..facc7271f9326549c6009a6da6d33f69e2ecab87 100644 (file)
@@ -353,7 +353,7 @@ static int probe_eisa_isa = 0;
 static int force_dma32 = 0;
 
 /* parameters for modprobe/insmod */
-module_param_array(irq, int, NULL, 0);
+module_param_hw_array(irq, int, irq, NULL, 0);
 module_param(disable, int, 0);
 module_param(reserve_mode, int, 0);
 module_param_array(reserve_list, int, NULL, 0);
index 0f807798c6245f8ba64b5ec3cced694d6a821c31..d390325c99ecf9487c9b4441fd0e25aec05378c7 100644 (file)
@@ -1170,6 +1170,7 @@ static struct ibmvscsis_cmd *ibmvscsis_get_free_cmd(struct scsi_info *vscsi)
                cmd = list_first_entry_or_null(&vscsi->free_cmd,
                                               struct ibmvscsis_cmd, list);
                if (cmd) {
+                       cmd->flags &= ~(DELAY_SEND);
                        list_del(&cmd->list);
                        cmd->iue = iue;
                        cmd->type = UNSET_TYPE;
@@ -1749,45 +1750,79 @@ static void srp_snd_msg_failed(struct scsi_info *vscsi, long rc)
 static void ibmvscsis_send_messages(struct scsi_info *vscsi)
 {
        u64 msg_hi = 0;
-       /* note do not attmempt to access the IU_data_ptr with this pointer
+       /* note do not attempt to access the IU_data_ptr with this pointer
         * it is not valid
         */
        struct viosrp_crq *crq = (struct viosrp_crq *)&msg_hi;
        struct ibmvscsis_cmd *cmd, *nxt;
        struct iu_entry *iue;
        long rc = ADAPT_SUCCESS;
+       bool retry = false;
 
        if (!(vscsi->flags & RESPONSE_Q_DOWN)) {
-               list_for_each_entry_safe(cmd, nxt, &vscsi->waiting_rsp, list) {
-                       iue = cmd->iue;
+               do {
+                       retry = false;
+                       list_for_each_entry_safe(cmd, nxt, &vscsi->waiting_rsp,
+                                                list) {
+                               /*
+                                * Check to make sure abort cmd gets processed
+                                * prior to the abort tmr cmd
+                                */
+                               if (cmd->flags & DELAY_SEND)
+                                       continue;
 
-                       crq->valid = VALID_CMD_RESP_EL;
-                       crq->format = cmd->rsp.format;
+                               if (cmd->abort_cmd) {
+                                       retry = true;
+                                       cmd->abort_cmd->flags &= ~(DELAY_SEND);
+                               }
 
-                       if (cmd->flags & CMD_FAST_FAIL)
-                               crq->status = VIOSRP_ADAPTER_FAIL;
+                               /*
+                                * If CMD_T_ABORTED w/o CMD_T_TAS scenarios and
+                                * the case where LIO issued a
+                                * ABORT_TASK: Sending TMR_TASK_DOES_NOT_EXIST
+                                * case then we dont send a response, since it
+                                * was already done.
+                                */
+                               if (cmd->se_cmd.transport_state & CMD_T_ABORTED &&
+                                   !(cmd->se_cmd.transport_state & CMD_T_TAS)) {
+                                       list_del(&cmd->list);
+                                       ibmvscsis_free_cmd_resources(vscsi,
+                                                                    cmd);
+                               } else {
+                                       iue = cmd->iue;
 
-                       crq->IU_length = cpu_to_be16(cmd->rsp.len);
+                                       crq->valid = VALID_CMD_RESP_EL;
+                                       crq->format = cmd->rsp.format;
 
-                       rc = h_send_crq(vscsi->dma_dev->unit_address,
-                                       be64_to_cpu(msg_hi),
-                                       be64_to_cpu(cmd->rsp.tag));
+                                       if (cmd->flags & CMD_FAST_FAIL)
+                                               crq->status = VIOSRP_ADAPTER_FAIL;
 
-                       pr_debug("send_messages: cmd %p, tag 0x%llx, rc %ld\n",
-                                cmd, be64_to_cpu(cmd->rsp.tag), rc);
+                                       crq->IU_length = cpu_to_be16(cmd->rsp.len);
 
-                       /* if all ok free up the command element resources */
-                       if (rc == H_SUCCESS) {
-                               /* some movement has occurred */
-                               vscsi->rsp_q_timer.timer_pops = 0;
-                               list_del(&cmd->list);
+                                       rc = h_send_crq(vscsi->dma_dev->unit_address,
+                                                       be64_to_cpu(msg_hi),
+                                                       be64_to_cpu(cmd->rsp.tag));
 
-                               ibmvscsis_free_cmd_resources(vscsi, cmd);
-                       } else {
-                               srp_snd_msg_failed(vscsi, rc);
-                               break;
+                                       pr_debug("send_messages: cmd %p, tag 0x%llx, rc %ld\n",
+                                                cmd, be64_to_cpu(cmd->rsp.tag), rc);
+
+                                       /* if all ok free up the command
+                                        * element resources
+                                        */
+                                       if (rc == H_SUCCESS) {
+                                               /* some movement has occurred */
+                                               vscsi->rsp_q_timer.timer_pops = 0;
+                                               list_del(&cmd->list);
+
+                                               ibmvscsis_free_cmd_resources(vscsi,
+                                                                            cmd);
+                                       } else {
+                                               srp_snd_msg_failed(vscsi, rc);
+                                               break;
+                                       }
+                               }
                        }
-               }
+               } while (retry);
 
                if (!rc) {
                        /*
@@ -2708,6 +2743,7 @@ static int ibmvscsis_alloc_cmds(struct scsi_info *vscsi, int num)
 
        for (i = 0, cmd = (struct ibmvscsis_cmd *)vscsi->cmd_pool; i < num;
             i++, cmd++) {
+               cmd->abort_cmd = NULL;
                cmd->adapter = vscsi;
                INIT_WORK(&cmd->work, ibmvscsis_scheduler);
                list_add_tail(&cmd->list, &vscsi->free_cmd);
@@ -3579,9 +3615,20 @@ static int ibmvscsis_write_pending(struct se_cmd *se_cmd)
 {
        struct ibmvscsis_cmd *cmd = container_of(se_cmd, struct ibmvscsis_cmd,
                                                 se_cmd);
+       struct scsi_info *vscsi = cmd->adapter;
        struct iu_entry *iue = cmd->iue;
        int rc;
 
+       /*
+        * If CLIENT_FAILED OR RESPONSE_Q_DOWN, then just return success
+        * since LIO can't do anything about it, and we dont want to
+        * attempt an srp_transfer_data.
+        */
+       if ((vscsi->flags & (CLIENT_FAILED | RESPONSE_Q_DOWN))) {
+               pr_err("write_pending failed since: %d\n", vscsi->flags);
+               return 0;
+       }
+
        rc = srp_transfer_data(cmd, &vio_iu(iue)->srp.cmd, ibmvscsis_rdma,
                               1, 1);
        if (rc) {
@@ -3660,11 +3707,28 @@ static void ibmvscsis_queue_tm_rsp(struct se_cmd *se_cmd)
        struct ibmvscsis_cmd *cmd = container_of(se_cmd, struct ibmvscsis_cmd,
                                                 se_cmd);
        struct scsi_info *vscsi = cmd->adapter;
+       struct ibmvscsis_cmd *cmd_itr;
+       struct iu_entry *iue = iue = cmd->iue;
+       struct srp_tsk_mgmt *srp_tsk = &vio_iu(iue)->srp.tsk_mgmt;
+       u64 tag_to_abort = be64_to_cpu(srp_tsk->task_tag);
        uint len;
 
        pr_debug("queue_tm_rsp %p, status %d\n",
                 se_cmd, (int)se_cmd->se_tmr_req->response);
 
+       if (srp_tsk->tsk_mgmt_func == SRP_TSK_ABORT_TASK &&
+           cmd->se_cmd.se_tmr_req->response == TMR_TASK_DOES_NOT_EXIST) {
+               spin_lock_bh(&vscsi->intr_lock);
+               list_for_each_entry(cmd_itr, &vscsi->active_q, list) {
+                       if (tag_to_abort == cmd_itr->se_cmd.tag) {
+                               cmd_itr->abort_cmd = cmd;
+                               cmd->flags |= DELAY_SEND;
+                               break;
+                       }
+               }
+               spin_unlock_bh(&vscsi->intr_lock);
+       }
+
        srp_build_response(vscsi, cmd, &len);
        cmd->rsp.format = SRP_FORMAT;
        cmd->rsp.len = len;
@@ -3672,8 +3736,8 @@ static void ibmvscsis_queue_tm_rsp(struct se_cmd *se_cmd)
 
 static void ibmvscsis_aborted_task(struct se_cmd *se_cmd)
 {
-       /* TBD: What (if anything) should we do here? */
-       pr_debug("ibmvscsis_aborted_task %p\n", se_cmd);
+       pr_debug("ibmvscsis_aborted_task %p task_tag: %llu\n",
+                se_cmd, se_cmd->tag);
 }
 
 static struct se_wwn *ibmvscsis_make_tport(struct target_fabric_configfs *tf,
index 65c6189885ab08f24212bce5f008c1973539a0f7..b4391a8de4569751d654b3d3f44d722c4a74a7f5 100644 (file)
@@ -168,10 +168,12 @@ struct ibmvscsis_cmd {
        struct iu_rsp rsp;
        struct work_struct work;
        struct scsi_info *adapter;
+       struct ibmvscsis_cmd *abort_cmd;
        /* Sense buffer that will be mapped into outgoing status */
        unsigned char sense_buf[TRANSPORT_SENSE_BUFFER];
        u64 init_time;
 #define CMD_FAST_FAIL  BIT(0)
+#define DELAY_SEND     BIT(1)
        u32 flags;
        char type;
 };
index 97f3ceb8d7245c40fb2784bbcf43e6774c3795c4..63468cfe3e4a333f317e715985f31dc692f9ddb0 100644 (file)
@@ -652,7 +652,7 @@ struct scu_iit_entry {
 
 
 /*
- * TODO: Where is the SAS_LNKTOV regsiter?
+ * TODO: Where is the SAS_LNKTOV register?
  * TODO: Where is the SAS_PHYTOV register? */
 
 #define SCU_SAS_TRANSMIT_IDENTIFICATION_SMP_TARGET_SHIFT            (1)
@@ -1827,7 +1827,7 @@ struct scu_peg_registers {
 };
 
 /**
- * struct scu_registers - SCU regsiters including both PEG registers if we turn
+ * struct scu_registers - SCU registers including both PEG registers if we turn
  *    on that compile option. All of these registers are in the memory mapped
  *    space returned from BAR1.
  *
index bbea8eac9abb737b7be67366ab9cdcde89830609..4842fc0e809d1cf6846ba531165953f1dd11f993 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/types.h>
 #include <linux/inet.h>
 #include <linux/slab.h>
+#include <linux/sched/mm.h>
 #include <linux/file.h>
 #include <linux/blkdev.h>
 #include <linux/delay.h>
@@ -371,10 +372,10 @@ static inline int iscsi_sw_tcp_xmit_qlen(struct iscsi_conn *conn)
 static int iscsi_sw_tcp_pdu_xmit(struct iscsi_task *task)
 {
        struct iscsi_conn *conn = task->conn;
-       unsigned long pflags = current->flags;
+       unsigned int noreclaim_flag;
        int rc = 0;
 
-       current->flags |= PF_MEMALLOC;
+       noreclaim_flag = memalloc_noreclaim_save();
 
        while (iscsi_sw_tcp_xmit_qlen(conn)) {
                rc = iscsi_sw_tcp_xmit(conn);
@@ -387,7 +388,7 @@ static int iscsi_sw_tcp_pdu_xmit(struct iscsi_task *task)
                rc = 0;
        }
 
-       current_restore_flags(pflags, PF_MEMALLOC);
+       memalloc_noreclaim_restore(noreclaim_flag);
        return rc;
 }
 
index 0016f12cc563e7c6e1eb3c2a87685f60c83b9747..316c3df0c3fd80f9689499f0351082703772707f 100644 (file)
@@ -244,7 +244,7 @@ struct megasas_cmd *megasas_get_cmd(struct megasas_instance
  * @instance:          Adapter soft state
  * @cmd:               Command packet to be returned to free command pool
  */
-inline void
+void
 megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd)
 {
        unsigned long flags;
index 8981806fb13fa7792e2b8d45f4fc6880b362da25..099ab4ca7edfdb8eca1f976273b01562c0298ebc 100644 (file)
@@ -1421,7 +1421,7 @@ void mpt3sas_ctl_add_to_event_log(struct MPT3SAS_ADAPTER *ioc,
        Mpi2EventNotificationReply_t *mpi_reply);
 
 void mpt3sas_enable_diag_buffer(struct MPT3SAS_ADAPTER *ioc,
-       u8 bits_to_regsiter);
+       u8 bits_to_register);
 int mpt3sas_send_diag_release(struct MPT3SAS_ADAPTER *ioc, u8 buffer_type,
        u8 *issue_reset);
 
index 61cac87fb86fd4323033834f6c2836ed05b9c0bf..840823b99e51a37505f4fce35fad9877153f10cd 100644 (file)
@@ -137,8 +137,8 @@ err:
 static struct qlogicfas408_priv *cards;
 static int iobase[MAX_QLOGICFAS];
 static int irq[MAX_QLOGICFAS] = { [0 ... MAX_QLOGICFAS-1] = -1 };
-module_param_array(iobase, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
+module_param_hw_array(iobase, int, ioport, NULL, 0);
+module_param_hw_array(irq, int, irq, NULL, 0);
 MODULE_PARM_DESC(iobase, "I/O address");
 MODULE_PARM_DESC(irq, "IRQ");
 
index a29d068b76962df07b67f4885e0c67d4c3342f64..f8dbfeee6c63f24d26f810d39b36405e03cdbbef 100644 (file)
@@ -894,8 +894,7 @@ static int virtscsi_init(struct virtio_device *vdev,
        }
 
        /* Discover virtqueues and write information to configuration.  */
-       err = vdev->config->find_vqs(vdev, num_vqs, vqs, callbacks, names,
-                       &desc);
+       err = virtio_find_vqs(vdev, num_vqs, vqs, callbacks, names, &desc);
        if (err)
                goto out;
 
index f09023f7ab11902523563541615e91077b2d1f4a..309643fe35f9e68eb8e542d5ef48c5d81b904fad 100644 (file)
@@ -1,7 +1,9 @@
 menu "SOC (System On Chip) specific Drivers"
 
+source "drivers/soc/atmel/Kconfig"
 source "drivers/soc/bcm/Kconfig"
 source "drivers/soc/fsl/Kconfig"
+source "drivers/soc/imx/Kconfig"
 source "drivers/soc/mediatek/Kconfig"
 source "drivers/soc/qcom/Kconfig"
 source "drivers/soc/rockchip/Kconfig"
index 05eae52a30b45133ed78da635118976327d9de78..824b44281efa5e115b829b345ed0ea5c73af569b 100644 (file)
@@ -2,10 +2,12 @@
 # Makefile for the Linux Kernel SOC specific device drivers.
 #
 
+obj-$(CONFIG_ARCH_AT91)                += atmel/
 obj-y                          += bcm/
 obj-$(CONFIG_ARCH_DOVE)                += dove/
 obj-$(CONFIG_MACH_DOVE)                += dove/
 obj-y                          += fsl/
+obj-$(CONFIG_ARCH_MXC)         += imx/
 obj-$(CONFIG_ARCH_MEDIATEK)    += mediatek/
 obj-$(CONFIG_ARCH_QCOM)                += qcom/
 obj-$(CONFIG_ARCH_RENESAS)     += renesas/
diff --git a/drivers/soc/atmel/Kconfig b/drivers/soc/atmel/Kconfig
new file mode 100644 (file)
index 0000000..6242ebb
--- /dev/null
@@ -0,0 +1,6 @@
+config AT91_SOC_ID
+       bool "SoC bus for Atmel ARM SoCs"
+       depends on ARCH_AT91 || COMPILE_TEST
+       default ARCH_AT91
+       help
+         Include support for the SoC bus on the Atmel ARM SoCs.
diff --git a/drivers/soc/atmel/Makefile b/drivers/soc/atmel/Makefile
new file mode 100644 (file)
index 0000000..2d92f32
--- /dev/null
@@ -0,0 +1 @@
+obj-$(CONFIG_AT91_SOC_ID) += soc.o
diff --git a/drivers/soc/atmel/soc.c b/drivers/soc/atmel/soc.c
new file mode 100644 (file)
index 0000000..4790094
--- /dev/null
@@ -0,0 +1,231 @@
+/*
+ * Copyright (C) 2015 Atmel
+ *
+ * Alexandre Belloni <alexandre.belloni@free-electrons.com
+ * Boris Brezillon <boris.brezillon@free-electrons.com
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ *
+ */
+
+#define pr_fmt(fmt)    "AT91: " fmt
+
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/slab.h>
+#include <linux/sys_soc.h>
+
+#include "soc.h"
+
+#define AT91_DBGU_CIDR                 0x40
+#define AT91_DBGU_EXID                 0x44
+#define AT91_CHIPID_CIDR               0x00
+#define AT91_CHIPID_EXID               0x04
+#define AT91_CIDR_VERSION(x)           ((x) & 0x1f)
+#define AT91_CIDR_EXT                  BIT(31)
+#define AT91_CIDR_MATCH_MASK           0x7fffffe0
+
+static const struct at91_soc __initconst socs[] = {
+#ifdef CONFIG_SOC_AT91RM9200
+       AT91_SOC(AT91RM9200_CIDR_MATCH, 0, "at91rm9200 BGA", "at91rm9200"),
+#endif
+#ifdef CONFIG_SOC_AT91SAM9
+       AT91_SOC(AT91SAM9260_CIDR_MATCH, 0, "at91sam9260", NULL),
+       AT91_SOC(AT91SAM9261_CIDR_MATCH, 0, "at91sam9261", NULL),
+       AT91_SOC(AT91SAM9263_CIDR_MATCH, 0, "at91sam9263", NULL),
+       AT91_SOC(AT91SAM9G20_CIDR_MATCH, 0, "at91sam9g20", NULL),
+       AT91_SOC(AT91SAM9RL64_CIDR_MATCH, 0, "at91sam9rl64", NULL),
+       AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9M11_EXID_MATCH,
+                "at91sam9m11", "at91sam9g45"),
+       AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9M10_EXID_MATCH,
+                "at91sam9m10", "at91sam9g45"),
+       AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9G46_EXID_MATCH,
+                "at91sam9g46", "at91sam9g45"),
+       AT91_SOC(AT91SAM9G45_CIDR_MATCH, AT91SAM9G45_EXID_MATCH,
+                "at91sam9g45", "at91sam9g45"),
+       AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9G15_EXID_MATCH,
+                "at91sam9g15", "at91sam9x5"),
+       AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9G35_EXID_MATCH,
+                "at91sam9g35", "at91sam9x5"),
+       AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9X35_EXID_MATCH,
+                "at91sam9x35", "at91sam9x5"),
+       AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9G25_EXID_MATCH,
+                "at91sam9g25", "at91sam9x5"),
+       AT91_SOC(AT91SAM9X5_CIDR_MATCH, AT91SAM9X25_EXID_MATCH,
+                "at91sam9x25", "at91sam9x5"),
+       AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91SAM9CN12_EXID_MATCH,
+                "at91sam9cn12", "at91sam9n12"),
+       AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91SAM9N12_EXID_MATCH,
+                "at91sam9n12", "at91sam9n12"),
+       AT91_SOC(AT91SAM9N12_CIDR_MATCH, AT91SAM9CN11_EXID_MATCH,
+                "at91sam9cn11", "at91sam9n12"),
+       AT91_SOC(AT91SAM9XE128_CIDR_MATCH, 0, "at91sam9xe128", "at91sam9xe128"),
+       AT91_SOC(AT91SAM9XE256_CIDR_MATCH, 0, "at91sam9xe256", "at91sam9xe256"),
+       AT91_SOC(AT91SAM9XE512_CIDR_MATCH, 0, "at91sam9xe512", "at91sam9xe512"),
+#endif
+#ifdef CONFIG_SOC_SAMA5
+       AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D21CU_EXID_MATCH,
+                "sama5d21", "sama5d2"),
+       AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D22CU_EXID_MATCH,
+                "sama5d22", "sama5d2"),
+       AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D23CU_EXID_MATCH,
+                "sama5d23", "sama5d2"),
+       AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D24CX_EXID_MATCH,
+                "sama5d24", "sama5d2"),
+       AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D24CU_EXID_MATCH,
+                "sama5d24", "sama5d2"),
+       AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D26CU_EXID_MATCH,
+                "sama5d26", "sama5d2"),
+       AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27CU_EXID_MATCH,
+                "sama5d27", "sama5d2"),
+       AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D27CN_EXID_MATCH,
+                "sama5d27", "sama5d2"),
+       AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28CU_EXID_MATCH,
+                "sama5d28", "sama5d2"),
+       AT91_SOC(SAMA5D2_CIDR_MATCH, SAMA5D28CN_EXID_MATCH,
+                "sama5d28", "sama5d2"),
+       AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D31_EXID_MATCH,
+                "sama5d31", "sama5d3"),
+       AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D33_EXID_MATCH,
+                "sama5d33", "sama5d3"),
+       AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D34_EXID_MATCH,
+                "sama5d34", "sama5d3"),
+       AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D35_EXID_MATCH,
+                "sama5d35", "sama5d3"),
+       AT91_SOC(SAMA5D3_CIDR_MATCH, SAMA5D36_EXID_MATCH,
+                "sama5d36", "sama5d3"),
+       AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D41_EXID_MATCH,
+                "sama5d41", "sama5d4"),
+       AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D42_EXID_MATCH,
+                "sama5d42", "sama5d4"),
+       AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D43_EXID_MATCH,
+                "sama5d43", "sama5d4"),
+       AT91_SOC(SAMA5D4_CIDR_MATCH, SAMA5D44_EXID_MATCH,
+                "sama5d44", "sama5d4"),
+#endif
+       { /* sentinel */ },
+};
+
+static int __init at91_get_cidr_exid_from_dbgu(u32 *cidr, u32 *exid)
+{
+       struct device_node *np;
+       void __iomem *regs;
+
+       np = of_find_compatible_node(NULL, NULL, "atmel,at91rm9200-dbgu");
+       if (!np)
+               np = of_find_compatible_node(NULL, NULL,
+                                            "atmel,at91sam9260-dbgu");
+       if (!np)
+               return -ENODEV;
+
+       regs = of_iomap(np, 0);
+       of_node_put(np);
+
+       if (!regs) {
+               pr_warn("Could not map DBGU iomem range");
+               return -ENXIO;
+       }
+
+       *cidr = readl(regs + AT91_DBGU_CIDR);
+       *exid = readl(regs + AT91_DBGU_EXID);
+
+       iounmap(regs);
+
+       return 0;
+}
+
+static int __init at91_get_cidr_exid_from_chipid(u32 *cidr, u32 *exid)
+{
+       struct device_node *np;
+       void __iomem *regs;
+
+       np = of_find_compatible_node(NULL, NULL, "atmel,sama5d2-chipid");
+       if (!np)
+               return -ENODEV;
+
+       regs = of_iomap(np, 0);
+       of_node_put(np);
+
+       if (!regs) {
+               pr_warn("Could not map DBGU iomem range");
+               return -ENXIO;
+       }
+
+       *cidr = readl(regs + AT91_CHIPID_CIDR);
+       *exid = readl(regs + AT91_CHIPID_EXID);
+
+       iounmap(regs);
+
+       return 0;
+}
+
+struct soc_device * __init at91_soc_init(const struct at91_soc *socs)
+{
+       struct soc_device_attribute *soc_dev_attr;
+       const struct at91_soc *soc;
+       struct soc_device *soc_dev;
+       u32 cidr, exid;
+       int ret;
+
+       /*
+        * With SAMA5D2 and later SoCs, CIDR and EXID registers are no more
+        * in the dbgu device but in the chipid device whose purpose is only
+        * to expose these two registers.
+        */
+       ret = at91_get_cidr_exid_from_dbgu(&cidr, &exid);
+       if (ret)
+               ret = at91_get_cidr_exid_from_chipid(&cidr, &exid);
+       if (ret) {
+               if (ret == -ENODEV)
+                       pr_warn("Could not find identification node");
+               return NULL;
+       }
+
+       for (soc = socs; soc->name; soc++) {
+               if (soc->cidr_match != (cidr & AT91_CIDR_MATCH_MASK))
+                       continue;
+
+               if (!(cidr & AT91_CIDR_EXT) || soc->exid_match == exid)
+                       break;
+       }
+
+       if (!soc->name) {
+               pr_warn("Could not find matching SoC description\n");
+               return NULL;
+       }
+
+       soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+       if (!soc_dev_attr)
+               return NULL;
+
+       soc_dev_attr->family = soc->family;
+       soc_dev_attr->soc_id = soc->name;
+       soc_dev_attr->revision = kasprintf(GFP_KERNEL, "%X",
+                                          AT91_CIDR_VERSION(cidr));
+       soc_dev = soc_device_register(soc_dev_attr);
+       if (IS_ERR(soc_dev)) {
+               kfree(soc_dev_attr->revision);
+               kfree(soc_dev_attr);
+               pr_warn("Could not register SoC device\n");
+               return NULL;
+       }
+
+       if (soc->family)
+               pr_info("Detected SoC family: %s\n", soc->family);
+       pr_info("Detected SoC: %s, revision %X\n", soc->name,
+               AT91_CIDR_VERSION(cidr));
+
+       return soc_dev;
+}
+
+static int __init atmel_soc_device_init(void)
+{
+       at91_soc_init(socs);
+
+       return 0;
+}
+subsys_initcall(atmel_soc_device_init);
index 94e7335553f437f43d614a50e2bf2381c1fae330..22e98a90468c8e35d50e0a1f0da0f73c177084f5 100644 (file)
@@ -41,6 +41,15 @@ bool soc_is_brcmstb(void)
 }
 
 static const struct of_device_id sun_top_ctrl_match[] = {
+       { .compatible = "brcm,bcm7125-sun-top-ctrl", },
+       { .compatible = "brcm,bcm7346-sun-top-ctrl", },
+       { .compatible = "brcm,bcm7358-sun-top-ctrl", },
+       { .compatible = "brcm,bcm7360-sun-top-ctrl", },
+       { .compatible = "brcm,bcm7362-sun-top-ctrl", },
+       { .compatible = "brcm,bcm7420-sun-top-ctrl", },
+       { .compatible = "brcm,bcm7425-sun-top-ctrl", },
+       { .compatible = "brcm,bcm7429-sun-top-ctrl", },
+       { .compatible = "brcm,bcm7435-sun-top-ctrl", },
        { .compatible = "brcm,brcmstb-sun-top-ctrl", },
        { }
 };
index 3d891db57ee6af14d586bfde2ca63fb71e0c3d63..18eefc3f1abea587f63e9a693ea2cbf7bd9ec119 100644 (file)
@@ -1344,6 +1344,7 @@ static void qm_congestion_task(struct work_struct *work)
        if (!qm_mc_result_timeout(&p->p, &mcr)) {
                spin_unlock(&p->cgr_lock);
                dev_crit(p->config->dev, "QUERYCONGESTION timeout\n");
+               qman_p_irqsource_add(p, QM_PIRQ_CSCI);
                return;
        }
        /* mask out the ones I'm not interested in */
@@ -1358,6 +1359,7 @@ static void qm_congestion_task(struct work_struct *work)
                if (cgr->cb && qman_cgrs_get(&c, cgr->cgrid))
                        cgr->cb(p, cgr, qman_cgrs_get(&rr, cgr->cgrid));
        spin_unlock(&p->cgr_lock);
+       qman_p_irqsource_add(p, QM_PIRQ_CSCI);
 }
 
 static void qm_mr_process_task(struct work_struct *work)
@@ -1417,12 +1419,14 @@ static void qm_mr_process_task(struct work_struct *work)
        }
 
        qm_mr_cci_consume(&p->p, num);
+       qman_p_irqsource_add(p, QM_PIRQ_MRI);
        preempt_enable();
 }
 
 static u32 __poll_portal_slow(struct qman_portal *p, u32 is)
 {
        if (is & QM_PIRQ_CSCI) {
+               qman_p_irqsource_remove(p, QM_PIRQ_CSCI);
                queue_work_on(smp_processor_id(), qm_portal_wq,
                              &p->congestion_work);
        }
@@ -1434,6 +1438,7 @@ static u32 __poll_portal_slow(struct qman_portal *p, u32 is)
        }
 
        if (is & QM_PIRQ_MRI) {
+               qman_p_irqsource_remove(p, QM_PIRQ_MRI);
                queue_work_on(smp_processor_id(), qm_portal_wq,
                              &p->mr_work);
        }
index 22725bdc6f15e0a549b88605f7bf310112ea4769..5fe9faf6232e2567324710fcbc0c18f0c67ade98 100644 (file)
@@ -33,6 +33,7 @@
 #include "dpaa_sys.h"
 
 #include <soc/fsl/qman.h>
+#include <linux/dma-mapping.h>
 #include <linux/iommu.h>
 
 #if defined(CONFIG_FSL_PAMU)
index ade168f5328e7fac1e68c4d55004cf94ac842f72..2ef6fc6487c113f8cb33aade2fa4f3d1d30f5454 100644 (file)
@@ -66,7 +66,7 @@ static unsigned int qe_num_of_snum;
 
 static phys_addr_t qebase = -1;
 
-phys_addr_t get_qe_base(void)
+static phys_addr_t get_qe_base(void)
 {
        struct device_node *qe;
        int ret;
@@ -90,8 +90,6 @@ phys_addr_t get_qe_base(void)
        return qebase;
 }
 
-EXPORT_SYMBOL(get_qe_base);
-
 void qe_reset(void)
 {
        if (qe_immr == NULL)
@@ -163,11 +161,15 @@ EXPORT_SYMBOL(qe_issue_cmd);
  */
 static unsigned int brg_clk = 0;
 
+#define CLK_GRAN       (1000)
+#define CLK_GRAN_LIMIT (5)
+
 unsigned int qe_get_brg_clk(void)
 {
        struct device_node *qe;
        int size;
        const u32 *prop;
+       unsigned int mod;
 
        if (brg_clk)
                return brg_clk;
@@ -185,10 +187,22 @@ unsigned int qe_get_brg_clk(void)
 
        of_node_put(qe);
 
+       /* round this if near to a multiple of CLK_GRAN */
+       mod = brg_clk % CLK_GRAN;
+       if (mod) {
+               if (mod < CLK_GRAN_LIMIT)
+                       brg_clk -= mod;
+               else if (mod > (CLK_GRAN - CLK_GRAN_LIMIT))
+                       brg_clk += CLK_GRAN - mod;
+       }
+
        return brg_clk;
 }
 EXPORT_SYMBOL(qe_get_brg_clk);
 
+#define PVR_VER_836x   0x8083
+#define PVR_VER_832x   0x8084
+
 /* Program the BRG to the given sampling rate and multiplier
  *
  * @brg: the BRG, QE_BRG1 - QE_BRG16
@@ -215,8 +229,9 @@ int qe_setbrg(enum qe_clock brg, unsigned int rate, unsigned int multiplier)
        /* Errata QE_General4, which affects some MPC832x and MPC836x SOCs, says
           that the BRG divisor must be even if you're not using divide-by-16
           mode. */
-       if (!div16 && (divisor & 1) && (divisor > 3))
-               divisor++;
+       if (pvr_version_is(PVR_VER_836x) || pvr_version_is(PVR_VER_832x))
+               if (!div16 && (divisor & 1) && (divisor > 3))
+                       divisor++;
 
        tempval = ((divisor - 1) << QE_BRGC_DIVISOR_SHIFT) |
                QE_BRGC_ENABLE | div16;
index a1048b44e6b93309499ddaac4bdb77d8b747c773..f744c214f680bf7343d7b8c8335573bcfc9bdd1b 100644 (file)
@@ -177,6 +177,7 @@ err_miss_siram_property:
        devm_iounmap(&pdev->dev, utdm->si_regs);
        return ret;
 }
+EXPORT_SYMBOL(ucc_of_parse_tdm);
 
 void ucc_tdm_init(struct ucc_tdm *utdm, struct ucc_tdm_info *ut_info)
 {
@@ -274,3 +275,4 @@ void ucc_tdm_init(struct ucc_tdm *utdm, struct ucc_tdm_info *ut_info)
                break;
        }
 }
+EXPORT_SYMBOL(ucc_tdm_init);
diff --git a/drivers/soc/imx/Kconfig b/drivers/soc/imx/Kconfig
new file mode 100644 (file)
index 0000000..a5b86a2
--- /dev/null
@@ -0,0 +1,10 @@
+menu "i.MX SoC drivers"
+
+config IMX7_PM_DOMAINS
+       bool "i.MX7 PM domains"
+       depends on SOC_IMX7D || (COMPILE_TEST && OF)
+       depends on PM
+       select PM_GENERIC_DOMAINS
+       default y if SOC_IMX7D
+
+endmenu
diff --git a/drivers/soc/imx/Makefile b/drivers/soc/imx/Makefile
new file mode 100644 (file)
index 0000000..5b6e396
--- /dev/null
@@ -0,0 +1,2 @@
+obj-y += gpc.o
+obj-$(CONFIG_IMX7_PM_DOMAINS) += gpcv2.o
diff --git a/drivers/soc/imx/gpc.c b/drivers/soc/imx/gpc.c
new file mode 100644 (file)
index 0000000..47e7aa9
--- /dev/null
@@ -0,0 +1,489 @@
+/*
+ * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de>
+ * Copyright 2011-2013 Freescale Semiconductor, Inc.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+
+#define GPC_CNTR               0x000
+
+#define GPC_PGC_CTRL_OFFS      0x0
+#define GPC_PGC_PUPSCR_OFFS    0x4
+#define GPC_PGC_PDNSCR_OFFS    0x8
+#define GPC_PGC_SW2ISO_SHIFT   0x8
+#define GPC_PGC_SW_SHIFT       0x0
+
+#define GPC_PGC_GPU_PDN                0x260
+#define GPC_PGC_GPU_PUPSCR     0x264
+#define GPC_PGC_GPU_PDNSCR     0x268
+
+#define GPU_VPU_PUP_REQ                BIT(1)
+#define GPU_VPU_PDN_REQ                BIT(0)
+
+#define GPC_CLK_MAX            6
+
+#define PGC_DOMAIN_FLAG_NO_PD          BIT(0)
+
+struct imx_pm_domain {
+       struct generic_pm_domain base;
+       struct regmap *regmap;
+       struct regulator *supply;
+       struct clk *clk[GPC_CLK_MAX];
+       int num_clks;
+       unsigned int reg_offs;
+       signed char cntr_pdn_bit;
+       unsigned int ipg_rate_mhz;
+       unsigned int flags;
+};
+
+static inline struct imx_pm_domain *
+to_imx_pm_domain(struct generic_pm_domain *genpd)
+{
+       return container_of(genpd, struct imx_pm_domain, base);
+}
+
+static int imx6_pm_domain_power_off(struct generic_pm_domain *genpd)
+{
+       struct imx_pm_domain *pd = to_imx_pm_domain(genpd);
+       int iso, iso2sw;
+       u32 val;
+
+       if (pd->flags & PGC_DOMAIN_FLAG_NO_PD)
+               return -EBUSY;
+
+       /* Read ISO and ISO2SW power down delays */
+       regmap_read(pd->regmap, pd->reg_offs + GPC_PGC_PUPSCR_OFFS, &val);
+       iso = val & 0x3f;
+       iso2sw = (val >> 8) & 0x3f;
+
+       /* Gate off domain when powered down */
+       regmap_update_bits(pd->regmap, pd->reg_offs + GPC_PGC_CTRL_OFFS,
+                          0x1, 0x1);
+
+       /* Request GPC to power down domain */
+       val = BIT(pd->cntr_pdn_bit);
+       regmap_update_bits(pd->regmap, GPC_CNTR, val, val);
+
+       /* Wait ISO + ISO2SW IPG clock cycles */
+       udelay(DIV_ROUND_UP(iso + iso2sw, pd->ipg_rate_mhz));
+
+       if (pd->supply)
+               regulator_disable(pd->supply);
+
+       return 0;
+}
+
+static int imx6_pm_domain_power_on(struct generic_pm_domain *genpd)
+{
+       struct imx_pm_domain *pd = to_imx_pm_domain(genpd);
+       int i, ret, sw, sw2iso;
+       u32 val;
+
+       if (pd->supply) {
+               ret = regulator_enable(pd->supply);
+               if (ret) {
+                       pr_err("%s: failed to enable regulator: %d\n",
+                              __func__, ret);
+                       return ret;
+               }
+       }
+
+       /* Enable reset clocks for all devices in the domain */
+       for (i = 0; i < pd->num_clks; i++)
+               clk_prepare_enable(pd->clk[i]);
+
+       /* Gate off domain when powered down */
+       regmap_update_bits(pd->regmap, pd->reg_offs + GPC_PGC_CTRL_OFFS,
+                          0x1, 0x1);
+
+       /* Read ISO and ISO2SW power up delays */
+       regmap_read(pd->regmap, pd->reg_offs + GPC_PGC_PUPSCR_OFFS, &val);
+       sw = val & 0x3f;
+       sw2iso = (val >> 8) & 0x3f;
+
+       /* Request GPC to power up domain */
+       val = BIT(pd->cntr_pdn_bit + 1);
+       regmap_update_bits(pd->regmap, GPC_CNTR, val, val);
+
+       /* Wait ISO + ISO2SW IPG clock cycles */
+       udelay(DIV_ROUND_UP(sw + sw2iso, pd->ipg_rate_mhz));
+
+       /* Disable reset clocks for all devices in the domain */
+       for (i = 0; i < pd->num_clks; i++)
+               clk_disable_unprepare(pd->clk[i]);
+
+       return 0;
+}
+
+static int imx_pgc_get_clocks(struct device *dev, struct imx_pm_domain *domain)
+{
+       int i, ret;
+
+       for (i = 0; ; i++) {
+               struct clk *clk = of_clk_get(dev->of_node, i);
+               if (IS_ERR(clk))
+                       break;
+               if (i >= GPC_CLK_MAX) {
+                       dev_err(dev, "more than %d clocks\n", GPC_CLK_MAX);
+                       ret = -EINVAL;
+                       goto clk_err;
+               }
+               domain->clk[i] = clk;
+       }
+       domain->num_clks = i;
+
+       return 0;
+
+clk_err:
+       while (i--)
+               clk_put(domain->clk[i]);
+
+       return ret;
+}
+
+static void imx_pgc_put_clocks(struct imx_pm_domain *domain)
+{
+       int i;
+
+       for (i = domain->num_clks - 1; i >= 0; i--)
+               clk_put(domain->clk[i]);
+}
+
+static int imx_pgc_parse_dt(struct device *dev, struct imx_pm_domain *domain)
+{
+       /* try to get the domain supply regulator */
+       domain->supply = devm_regulator_get_optional(dev, "power");
+       if (IS_ERR(domain->supply)) {
+               if (PTR_ERR(domain->supply) == -ENODEV)
+                       domain->supply = NULL;
+               else
+                       return PTR_ERR(domain->supply);
+       }
+
+       /* try to get all clocks needed for reset propagation */
+       return imx_pgc_get_clocks(dev, domain);
+}
+
+static int imx_pgc_power_domain_probe(struct platform_device *pdev)
+{
+       struct imx_pm_domain *domain = pdev->dev.platform_data;
+       struct device *dev = &pdev->dev;
+       int ret;
+
+       /* if this PD is associated with a DT node try to parse it */
+       if (dev->of_node) {
+               ret = imx_pgc_parse_dt(dev, domain);
+               if (ret)
+                       return ret;
+       }
+
+       /* initially power on the domain */
+       if (domain->base.power_on)
+               domain->base.power_on(&domain->base);
+
+       if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) {
+               pm_genpd_init(&domain->base, NULL, false);
+               ret = of_genpd_add_provider_simple(dev->of_node, &domain->base);
+               if (ret)
+                       goto genpd_err;
+       }
+
+       device_link_add(dev, dev->parent, DL_FLAG_AUTOREMOVE);
+
+       return 0;
+
+genpd_err:
+       pm_genpd_remove(&domain->base);
+       imx_pgc_put_clocks(domain);
+
+       return ret;
+}
+
+static int imx_pgc_power_domain_remove(struct platform_device *pdev)
+{
+       struct imx_pm_domain *domain = pdev->dev.platform_data;
+
+       if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) {
+               of_genpd_del_provider(pdev->dev.of_node);
+               pm_genpd_remove(&domain->base);
+               imx_pgc_put_clocks(domain);
+       }
+
+       return 0;
+}
+
+static const struct platform_device_id imx_pgc_power_domain_id[] = {
+       { "imx-pgc-power-domain"},
+       { },
+};
+
+static struct platform_driver imx_pgc_power_domain_driver = {
+       .driver = {
+               .name = "imx-pgc-pd",
+       },
+       .probe = imx_pgc_power_domain_probe,
+       .remove = imx_pgc_power_domain_remove,
+       .id_table = imx_pgc_power_domain_id,
+};
+builtin_platform_driver(imx_pgc_power_domain_driver)
+
+#define GPC_PGC_DOMAIN_ARM     0
+#define GPC_PGC_DOMAIN_PU      1
+#define GPC_PGC_DOMAIN_DISPLAY 2
+
+static struct genpd_power_state imx6_pm_domain_pu_state = {
+       .power_off_latency_ns = 25000,
+       .power_on_latency_ns = 2000000,
+};
+
+static struct imx_pm_domain imx_gpc_domains[] = {
+       {
+               .base = {
+                       .name = "ARM",
+               },
+       }, {
+               .base = {
+                       .name = "PU",
+                       .power_off = imx6_pm_domain_power_off,
+                       .power_on = imx6_pm_domain_power_on,
+                       .states = &imx6_pm_domain_pu_state,
+                       .state_count = 1,
+               },
+               .reg_offs = 0x260,
+               .cntr_pdn_bit = 0,
+       }, {
+               .base = {
+                       .name = "DISPLAY",
+                       .power_off = imx6_pm_domain_power_off,
+                       .power_on = imx6_pm_domain_power_on,
+               },
+               .reg_offs = 0x240,
+               .cntr_pdn_bit = 4,
+       }
+};
+
+struct imx_gpc_dt_data {
+       int num_domains;
+       bool err009619_present;
+};
+
+static const struct imx_gpc_dt_data imx6q_dt_data = {
+       .num_domains = 2,
+       .err009619_present = false,
+};
+
+static const struct imx_gpc_dt_data imx6qp_dt_data = {
+       .num_domains = 2,
+       .err009619_present = true,
+};
+
+static const struct imx_gpc_dt_data imx6sl_dt_data = {
+       .num_domains = 3,
+       .err009619_present = false,
+};
+
+static const struct of_device_id imx_gpc_dt_ids[] = {
+       { .compatible = "fsl,imx6q-gpc", .data = &imx6q_dt_data },
+       { .compatible = "fsl,imx6qp-gpc", .data = &imx6qp_dt_data },
+       { .compatible = "fsl,imx6sl-gpc", .data = &imx6sl_dt_data },
+       { }
+};
+
+static const struct regmap_config imx_gpc_regmap_config = {
+       .reg_bits = 32,
+       .val_bits = 32,
+       .reg_stride = 4,
+       .max_register = 0x2ac,
+};
+
+static struct generic_pm_domain *imx_gpc_onecell_domains[] = {
+       &imx_gpc_domains[0].base,
+       &imx_gpc_domains[1].base,
+};
+
+static struct genpd_onecell_data imx_gpc_onecell_data = {
+       .domains = imx_gpc_onecell_domains,
+       .num_domains = 2,
+};
+
+static int imx_gpc_old_dt_init(struct device *dev, struct regmap *regmap,
+                              unsigned int num_domains)
+{
+       struct imx_pm_domain *domain;
+       int i, ret;
+
+       for (i = 0; i < num_domains; i++) {
+               domain = &imx_gpc_domains[i];
+               domain->regmap = regmap;
+               domain->ipg_rate_mhz = 66;
+
+               if (i == 1) {
+                       domain->supply = devm_regulator_get(dev, "pu");
+                       if (IS_ERR(domain->supply))
+                               return PTR_ERR(domain->supply);;
+
+                       ret = imx_pgc_get_clocks(dev, domain);
+                       if (ret)
+                               goto clk_err;
+
+                       domain->base.power_on(&domain->base);
+               }
+       }
+
+       for (i = 0; i < num_domains; i++)
+               pm_genpd_init(&imx_gpc_domains[i].base, NULL, false);
+
+       if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) {
+               ret = of_genpd_add_provider_onecell(dev->of_node,
+                                                   &imx_gpc_onecell_data);
+               if (ret)
+                       goto genpd_err;
+       }
+
+       return 0;
+
+genpd_err:
+       for (i = 0; i < num_domains; i++)
+               pm_genpd_remove(&imx_gpc_domains[i].base);
+       imx_pgc_put_clocks(&imx_gpc_domains[GPC_PGC_DOMAIN_PU]);
+clk_err:
+       return ret;
+}
+
+static int imx_gpc_probe(struct platform_device *pdev)
+{
+       const struct of_device_id *of_id =
+                       of_match_device(imx_gpc_dt_ids, &pdev->dev);
+       const struct imx_gpc_dt_data *of_id_data = of_id->data;
+       struct device_node *pgc_node;
+       struct regmap *regmap;
+       struct resource *res;
+       void __iomem *base;
+       int ret;
+
+       pgc_node = of_get_child_by_name(pdev->dev.of_node, "pgc");
+
+       /* bail out if DT too old and doesn't provide the necessary info */
+       if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells") &&
+           !pgc_node)
+               return 0;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       regmap = devm_regmap_init_mmio_clk(&pdev->dev, NULL, base,
+                                          &imx_gpc_regmap_config);
+       if (IS_ERR(regmap)) {
+               ret = PTR_ERR(regmap);
+               dev_err(&pdev->dev, "failed to init regmap: %d\n",
+                       ret);
+               return ret;
+       }
+
+       /* Disable PU power down in normal operation if ERR009619 is present */
+       if (of_id_data->err009619_present)
+               imx_gpc_domains[GPC_PGC_DOMAIN_PU].flags |=
+                               PGC_DOMAIN_FLAG_NO_PD;
+
+       if (!pgc_node) {
+               ret = imx_gpc_old_dt_init(&pdev->dev, regmap,
+                                         of_id_data->num_domains);
+               if (ret)
+                       return ret;
+       } else {
+               struct imx_pm_domain *domain;
+               struct platform_device *pd_pdev;
+               struct device_node *np;
+               struct clk *ipg_clk;
+               unsigned int ipg_rate_mhz;
+               int domain_index;
+
+               ipg_clk = devm_clk_get(&pdev->dev, "ipg");
+               if (IS_ERR(ipg_clk))
+                       return PTR_ERR(ipg_clk);
+               ipg_rate_mhz = clk_get_rate(ipg_clk) / 1000000;
+
+               for_each_child_of_node(pgc_node, np) {
+                       ret = of_property_read_u32(np, "reg", &domain_index);
+                       if (ret) {
+                               of_node_put(np);
+                               return ret;
+                       }
+                       if (domain_index >= of_id_data->num_domains)
+                               continue;
+
+                       domain = &imx_gpc_domains[domain_index];
+                       domain->regmap = regmap;
+                       domain->ipg_rate_mhz = ipg_rate_mhz;
+
+                       pd_pdev = platform_device_alloc("imx-pgc-power-domain",
+                                                       domain_index);
+                       if (!pd_pdev) {
+                               of_node_put(np);
+                               return -ENOMEM;
+                       }
+                       pd_pdev->dev.platform_data = domain;
+                       pd_pdev->dev.parent = &pdev->dev;
+                       pd_pdev->dev.of_node = np;
+
+                       ret = platform_device_add(pd_pdev);
+                       if (ret) {
+                               platform_device_put(pd_pdev);
+                               of_node_put(np);
+                               return ret;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static int imx_gpc_remove(struct platform_device *pdev)
+{
+       int ret;
+
+       /*
+        * If the old DT binding is used the toplevel driver needs to
+        * de-register the power domains
+        */
+       if (!of_get_child_by_name(pdev->dev.of_node, "pgc")) {
+               of_genpd_del_provider(pdev->dev.of_node);
+
+               ret = pm_genpd_remove(&imx_gpc_domains[GPC_PGC_DOMAIN_PU].base);
+               if (ret)
+                       return ret;
+               imx_pgc_put_clocks(&imx_gpc_domains[GPC_PGC_DOMAIN_PU]);
+
+               ret = pm_genpd_remove(&imx_gpc_domains[GPC_PGC_DOMAIN_ARM].base);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
+static struct platform_driver imx_gpc_driver = {
+       .driver = {
+               .name = "imx-gpc",
+               .of_match_table = imx_gpc_dt_ids,
+       },
+       .probe = imx_gpc_probe,
+       .remove = imx_gpc_remove,
+};
+builtin_platform_driver(imx_gpc_driver)
diff --git a/drivers/soc/imx/gpcv2.c b/drivers/soc/imx/gpcv2.c
new file mode 100644 (file)
index 0000000..3039072
--- /dev/null
@@ -0,0 +1,363 @@
+/*
+ * Copyright 2017 Impinj, Inc
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
+ *
+ * Based on the code of analogus driver:
+ *
+ * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de>
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <dt-bindings/power/imx7-power.h>
+
+#define GPC_LPCR_A7_BSC                        0x000
+
+#define GPC_PGC_CPU_MAPPING            0x0ec
+#define USB_HSIC_PHY_A7_DOMAIN         BIT(6)
+#define USB_OTG2_PHY_A7_DOMAIN         BIT(5)
+#define USB_OTG1_PHY_A7_DOMAIN         BIT(4)
+#define PCIE_PHY_A7_DOMAIN             BIT(3)
+#define MIPI_PHY_A7_DOMAIN             BIT(2)
+
+#define GPC_PU_PGC_SW_PUP_REQ          0x0f8
+#define GPC_PU_PGC_SW_PDN_REQ          0x104
+#define USB_HSIC_PHY_SW_Pxx_REQ                BIT(4)
+#define USB_OTG2_PHY_SW_Pxx_REQ                BIT(3)
+#define USB_OTG1_PHY_SW_Pxx_REQ                BIT(2)
+#define PCIE_PHY_SW_Pxx_REQ            BIT(1)
+#define MIPI_PHY_SW_Pxx_REQ            BIT(0)
+
+#define GPC_M4_PU_PDN_FLG              0x1bc
+
+
+#define PGC_MIPI                       4
+#define PGC_PCIE                       5
+#define PGC_USB_HSIC                   8
+#define GPC_PGC_CTRL(n)                        (0x800 + (n) * 0x40)
+#define GPC_PGC_SR(n)                  (GPC_PGC_CTRL(n) + 0xc)
+
+#define GPC_PGC_CTRL_PCR               BIT(0)
+
+struct imx7_pgc_domain {
+       struct generic_pm_domain genpd;
+       struct regmap *regmap;
+       struct regulator *regulator;
+
+       unsigned int pgc;
+
+       const struct {
+               u32 pxx;
+               u32 map;
+       } bits;
+
+       const int voltage;
+       struct device *dev;
+};
+
+static int imx7_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd,
+                                     bool on)
+{
+       struct imx7_pgc_domain *domain = container_of(genpd,
+                                                     struct imx7_pgc_domain,
+                                                     genpd);
+       unsigned int offset = on ?
+               GPC_PU_PGC_SW_PUP_REQ : GPC_PU_PGC_SW_PDN_REQ;
+       const bool enable_power_control = !on;
+       const bool has_regulator = !IS_ERR(domain->regulator);
+       unsigned long deadline;
+       int ret = 0;
+
+       regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
+                          domain->bits.map, domain->bits.map);
+
+       if (has_regulator && on) {
+               ret = regulator_enable(domain->regulator);
+               if (ret) {
+                       dev_err(domain->dev, "failed to enable regulator\n");
+                       goto unmap;
+               }
+       }
+
+       if (enable_power_control)
+               regmap_update_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc),
+                                  GPC_PGC_CTRL_PCR, GPC_PGC_CTRL_PCR);
+
+       regmap_update_bits(domain->regmap, offset,
+                          domain->bits.pxx, domain->bits.pxx);
+
+       /*
+        * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait
+        * for PUP_REQ/PDN_REQ bit to be cleared
+        */
+       deadline = jiffies + msecs_to_jiffies(1);
+       while (true) {
+               u32 pxx_req;
+
+               regmap_read(domain->regmap, offset, &pxx_req);
+
+               if (!(pxx_req & domain->bits.pxx))
+                       break;
+
+               if (time_after(jiffies, deadline)) {
+                       dev_err(domain->dev, "falied to command PGC\n");
+                       ret = -ETIMEDOUT;
+                       /*
+                        * If we were in a process of enabling a
+                        * domain and failed we might as well disable
+                        * the regulator we just enabled. And if it
+                        * was the opposite situation and we failed to
+                        * power down -- keep the regulator on
+                        */
+                       on = !on;
+                       break;
+               }
+
+               cpu_relax();
+       }
+
+       if (enable_power_control)
+               regmap_update_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc),
+                                  GPC_PGC_CTRL_PCR, 0);
+
+       if (has_regulator && !on) {
+               int err;
+
+               err = regulator_disable(domain->regulator);
+               if (err)
+                       dev_err(domain->dev,
+                               "failed to disable regulator: %d\n", ret);
+               /* Preserve earlier error code */
+               ret = ret ?: err;
+       }
+unmap:
+       regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
+                          domain->bits.map, 0);
+       return ret;
+}
+
+static int imx7_gpc_pu_pgc_sw_pup_req(struct generic_pm_domain *genpd)
+{
+       return imx7_gpc_pu_pgc_sw_pxx_req(genpd, true);
+}
+
+static int imx7_gpc_pu_pgc_sw_pdn_req(struct generic_pm_domain *genpd)
+{
+       return imx7_gpc_pu_pgc_sw_pxx_req(genpd, false);
+}
+
+static struct imx7_pgc_domain imx7_pgc_domains[] = {
+       [IMX7_POWER_DOMAIN_MIPI_PHY] = {
+               .genpd = {
+                       .name      = "mipi-phy",
+               },
+               .bits  = {
+                       .pxx = MIPI_PHY_SW_Pxx_REQ,
+                       .map = MIPI_PHY_A7_DOMAIN,
+               },
+               .voltage   = 1000000,
+               .pgc       = PGC_MIPI,
+       },
+
+       [IMX7_POWER_DOMAIN_PCIE_PHY] = {
+               .genpd = {
+                       .name      = "pcie-phy",
+               },
+               .bits  = {
+                       .pxx = PCIE_PHY_SW_Pxx_REQ,
+                       .map = PCIE_PHY_A7_DOMAIN,
+               },
+               .voltage   = 1000000,
+               .pgc       = PGC_PCIE,
+       },
+
+       [IMX7_POWER_DOMAIN_USB_HSIC_PHY] = {
+               .genpd = {
+                       .name      = "usb-hsic-phy",
+               },
+               .bits  = {
+                       .pxx = USB_HSIC_PHY_SW_Pxx_REQ,
+                       .map = USB_HSIC_PHY_A7_DOMAIN,
+               },
+               .voltage   = 1200000,
+               .pgc       = PGC_USB_HSIC,
+       },
+};
+
+static int imx7_pgc_domain_probe(struct platform_device *pdev)
+{
+       struct imx7_pgc_domain *domain = pdev->dev.platform_data;
+       int ret;
+
+       domain->dev = &pdev->dev;
+
+       ret = pm_genpd_init(&domain->genpd, NULL, true);
+       if (ret) {
+               dev_err(domain->dev, "Failed to init power domain\n");
+               return ret;
+       }
+
+       domain->regulator = devm_regulator_get_optional(domain->dev, "power");
+       if (IS_ERR(domain->regulator)) {
+               if (PTR_ERR(domain->regulator) != -ENODEV) {
+                       dev_err(domain->dev, "Failed to get domain's regulator\n");
+                       return PTR_ERR(domain->regulator);
+               }
+       } else {
+               regulator_set_voltage(domain->regulator,
+                                     domain->voltage, domain->voltage);
+       }
+
+       ret = of_genpd_add_provider_simple(domain->dev->of_node,
+                                          &domain->genpd);
+       if (ret) {
+               dev_err(domain->dev, "Failed to add genpd provider\n");
+               pm_genpd_remove(&domain->genpd);
+       }
+
+       return ret;
+}
+
+static int imx7_pgc_domain_remove(struct platform_device *pdev)
+{
+       struct imx7_pgc_domain *domain = pdev->dev.platform_data;
+
+       of_genpd_del_provider(domain->dev->of_node);
+       pm_genpd_remove(&domain->genpd);
+
+       return 0;
+}
+
+static const struct platform_device_id imx7_pgc_domain_id[] = {
+       { "imx7-pgc-domain", },
+       { },
+};
+
+static struct platform_driver imx7_pgc_domain_driver = {
+       .driver = {
+               .name = "imx7-pgc",
+       },
+       .probe    = imx7_pgc_domain_probe,
+       .remove   = imx7_pgc_domain_remove,
+       .id_table = imx7_pgc_domain_id,
+};
+builtin_platform_driver(imx7_pgc_domain_driver)
+
+static int imx_gpcv2_probe(struct platform_device *pdev)
+{
+       static const struct regmap_range yes_ranges[] = {
+               regmap_reg_range(GPC_LPCR_A7_BSC,
+                                GPC_M4_PU_PDN_FLG),
+               regmap_reg_range(GPC_PGC_CTRL(PGC_MIPI),
+                                GPC_PGC_SR(PGC_MIPI)),
+               regmap_reg_range(GPC_PGC_CTRL(PGC_PCIE),
+                                GPC_PGC_SR(PGC_PCIE)),
+               regmap_reg_range(GPC_PGC_CTRL(PGC_USB_HSIC),
+                                GPC_PGC_SR(PGC_USB_HSIC)),
+       };
+       static const struct regmap_access_table access_table = {
+               .yes_ranges     = yes_ranges,
+               .n_yes_ranges   = ARRAY_SIZE(yes_ranges),
+       };
+       static const struct regmap_config regmap_config = {
+               .reg_bits       = 32,
+               .val_bits       = 32,
+               .reg_stride     = 4,
+               .rd_table       = &access_table,
+               .wr_table       = &access_table,
+               .max_register   = SZ_4K,
+       };
+       struct device *dev = &pdev->dev;
+       struct device_node *pgc_np, *np;
+       struct regmap *regmap;
+       struct resource *res;
+       void __iomem *base;
+       int ret;
+
+       pgc_np = of_get_child_by_name(dev->of_node, "pgc");
+       if (!pgc_np) {
+               dev_err(dev, "No power domains specified in DT\n");
+               return -EINVAL;
+       }
+
+       res  = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+
+       regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
+       if (IS_ERR(regmap)) {
+               ret = PTR_ERR(regmap);
+               dev_err(dev, "failed to init regmap (%d)\n", ret);
+               return ret;
+       }
+
+       for_each_child_of_node(pgc_np, np) {
+               struct platform_device *pd_pdev;
+               struct imx7_pgc_domain *domain;
+               u32 domain_index;
+
+               ret = of_property_read_u32(np, "reg", &domain_index);
+               if (ret) {
+                       dev_err(dev, "Failed to read 'reg' property\n");
+                       of_node_put(np);
+                       return ret;
+               }
+
+               if (domain_index >= ARRAY_SIZE(imx7_pgc_domains)) {
+                       dev_warn(dev,
+                                "Domain index %d is out of bounds\n",
+                                domain_index);
+                       continue;
+               }
+
+               domain = &imx7_pgc_domains[domain_index];
+               domain->regmap = regmap;
+               domain->genpd.power_on  = imx7_gpc_pu_pgc_sw_pup_req;
+               domain->genpd.power_off = imx7_gpc_pu_pgc_sw_pdn_req;
+
+               pd_pdev = platform_device_alloc("imx7-pgc-domain",
+                                               domain_index);
+               if (!pd_pdev) {
+                       dev_err(dev, "Failed to allocate platform device\n");
+                       of_node_put(np);
+                       return -ENOMEM;
+               }
+
+               pd_pdev->dev.platform_data = domain;
+               pd_pdev->dev.parent = dev;
+               pd_pdev->dev.of_node = np;
+
+               ret = platform_device_add(pd_pdev);
+               if (ret) {
+                       platform_device_put(pd_pdev);
+                       of_node_put(np);
+                       return ret;
+               }
+       }
+
+       return 0;
+}
+
+static const struct of_device_id imx_gpcv2_dt_ids[] = {
+       { .compatible = "fsl,imx7d-gpc" },
+       { }
+};
+
+static struct platform_driver imx_gpc_driver = {
+       .driver = {
+               .name = "imx-gpcv2",
+               .of_match_table = imx_gpcv2_dt_ids,
+       },
+       .probe = imx_gpcv2_probe,
+};
+builtin_platform_driver(imx_gpc_driver)
index 5e7537c96f7bbbcd2470a15ff1bdaaa13d8a6a13..7412666187b30420235e1ef10d64ce7926c5e7f7 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Renesas R-Car H3 System Controller
  *
- * Copyright (C) 2016 Glider bvba
+ * Copyright (C) 2016-2017 Glider bvba
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 
 #include <linux/bug.h>
 #include <linux/kernel.h>
+#include <linux/sys_soc.h>
 
 #include <dt-bindings/power/r8a7795-sysc.h>
 
 #include "rcar-sysc.h"
 
-static const struct rcar_sysc_area r8a7795_areas[] __initconst = {
+static struct rcar_sysc_area r8a7795_areas[] __initdata = {
        { "always-on",      0, 0, R8A7795_PD_ALWAYS_ON, -1, PD_ALWAYS_ON },
        { "ca57-scu",   0x1c0, 0, R8A7795_PD_CA57_SCU,  R8A7795_PD_ALWAYS_ON,
          PD_SCU },
@@ -40,6 +41,7 @@ static const struct rcar_sysc_area r8a7795_areas[] __initconst = {
        { "a3vp",       0x340, 0, R8A7795_PD_A3VP,      R8A7795_PD_ALWAYS_ON },
        { "cr7",        0x240, 0, R8A7795_PD_CR7,       R8A7795_PD_ALWAYS_ON },
        { "a3vc",       0x380, 0, R8A7795_PD_A3VC,      R8A7795_PD_ALWAYS_ON },
+       /* A2VC0 exists on ES1.x only */
        { "a2vc0",      0x3c0, 0, R8A7795_PD_A2VC0,     R8A7795_PD_A3VC },
        { "a2vc1",      0x3c0, 1, R8A7795_PD_A2VC1,     R8A7795_PD_A3VC },
        { "3dg-a",      0x100, 0, R8A7795_PD_3DG_A,     R8A7795_PD_ALWAYS_ON },
@@ -50,7 +52,27 @@ static const struct rcar_sysc_area r8a7795_areas[] __initconst = {
        { "a3ir",       0x180, 0, R8A7795_PD_A3IR,      R8A7795_PD_ALWAYS_ON },
 };
 
+
+       /*
+        * Fixups for R-Car H3 revisions after ES1.x
+        */
+
+static const struct soc_device_attribute r8a7795es1[] __initconst = {
+       { .soc_id = "r8a7795", .revision = "ES1.*" },
+       { /* sentinel */ }
+};
+
+static int __init r8a7795_sysc_init(void)
+{
+       if (!soc_device_match(r8a7795es1))
+               rcar_sysc_nullify(r8a7795_areas, ARRAY_SIZE(r8a7795_areas),
+                                 R8A7795_PD_A2VC0);
+
+       return 0;
+}
+
 const struct rcar_sysc_info r8a7795_sysc_info __initconst = {
+       .init = r8a7795_sysc_init,
        .areas = r8a7795_areas,
        .num_areas = ARRAY_SIZE(r8a7795_areas),
 };
index 225c35c79d9abad07308d2226f99448ba0d93531..528a13742aeb98d8035c7a998e5e2a037ccffe2c 100644 (file)
@@ -2,7 +2,7 @@
  * R-Car SYSC Power management support
  *
  * Copyright (C) 2014  Magnus Damm
- * Copyright (C) 2015-2016 Glider bvba
+ * Copyright (C) 2015-2017 Glider bvba
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
@@ -334,6 +334,12 @@ static int __init rcar_sysc_pd_init(void)
 
        info = match->data;
 
+       if (info->init) {
+               error = info->init();
+               if (error)
+                       return error;
+       }
+
        has_cpg_mstp = of_find_compatible_node(NULL, NULL,
                                               "renesas,cpg-mstp-clocks");
 
@@ -377,6 +383,11 @@ static int __init rcar_sysc_pd_init(void)
                const struct rcar_sysc_area *area = &info->areas[i];
                struct rcar_sysc_pd *pd;
 
+               if (!area->name) {
+                       /* Skip NULLified area */
+                       continue;
+               }
+
                pd = kzalloc(sizeof(*pd) + strlen(area->name) + 1, GFP_KERNEL);
                if (!pd) {
                        error = -ENOMEM;
@@ -406,6 +417,18 @@ out_put:
 }
 early_initcall(rcar_sysc_pd_init);
 
+void __init rcar_sysc_nullify(struct rcar_sysc_area *areas,
+                             unsigned int num_areas, u8 id)
+{
+       unsigned int i;
+
+       for (i = 0; i < num_areas; i++)
+               if (areas[i].isr_bit == id) {
+                       areas[i].name = NULL;
+                       return;
+               }
+}
+
 void __init rcar_sysc_init(phys_addr_t base, u32 syscier)
 {
        u32 syscimr;
index f6e842e2976ebe326ca2439dfb58a4b14f6464bc..07edb049a401196c7a6cd8903d37d310a96d09c0 100644 (file)
@@ -46,6 +46,7 @@ struct rcar_sysc_area {
  */
 
 struct rcar_sysc_info {
+       int (*init)(void);      /* Optional */
        const struct rcar_sysc_area *areas;
        unsigned int num_areas;
 };
@@ -59,4 +60,13 @@ extern const struct rcar_sysc_info r8a7792_sysc_info;
 extern const struct rcar_sysc_info r8a7794_sysc_info;
 extern const struct rcar_sysc_info r8a7795_sysc_info;
 extern const struct rcar_sysc_info r8a7796_sysc_info;
+
+
+    /*
+     * Helpers for fixing up power area tables depending on SoC revision
+     */
+
+extern void rcar_sysc_nullify(struct rcar_sysc_area *areas,
+                             unsigned int num_areas, u8 id);
+
 #endif /* __SOC_RENESAS_RCAR_SYSC_H__ */
index 330960312296f603075fbcd0296f2693df8889aa..ca26f13d399cf4c12bb2a8e92b2ab526cdee049c 100644 (file)
@@ -80,11 +80,21 @@ static const struct renesas_soc soc_rmobile_a1 __initconst __maybe_unused = {
        .id     = 0x40,
 };
 
+static const struct renesas_soc soc_rz_g1h __initconst __maybe_unused = {
+       .family = &fam_rzg,
+       .id     = 0x45,
+};
+
 static const struct renesas_soc soc_rz_g1m __initconst __maybe_unused = {
        .family = &fam_rzg,
        .id     = 0x47,
 };
 
+static const struct renesas_soc soc_rz_g1n __initconst __maybe_unused = {
+       .family = &fam_rzg,
+       .id     = 0x4b,
+};
+
 static const struct renesas_soc soc_rz_g1e __initconst __maybe_unused = {
        .family = &fam_rzg,
        .id     = 0x4c,
@@ -150,9 +160,15 @@ static const struct of_device_id renesas_socs[] __initconst = {
 #ifdef CONFIG_ARCH_R8A7740
        { .compatible = "renesas,r8a7740",      .data = &soc_rmobile_a1 },
 #endif
+#ifdef CONFIG_ARCH_R8A7742
+       { .compatible = "renesas,r8a7742",      .data = &soc_rz_g1h },
+#endif
 #ifdef CONFIG_ARCH_R8A7743
        { .compatible = "renesas,r8a7743",      .data = &soc_rz_g1m },
 #endif
+#ifdef CONFIG_ARCH_R8A7744
+       { .compatible = "renesas,r8a7744",      .data = &soc_rz_g1n },
+#endif
 #ifdef CONFIG_ARCH_R8A7745
        { .compatible = "renesas,r8a7745",      .data = &soc_rz_g1e },
 #endif
@@ -254,4 +270,4 @@ static int __init renesas_soc_init(void)
 
        return 0;
 }
-core_initcall(renesas_soc_init);
+early_initcall(renesas_soc_init);
index 245533907d1ba51d59e784d644303db88076e582..8b25bd55e64803aa528aa97dabf6090641d619ab 100644 (file)
@@ -8,7 +8,13 @@ if SOC_SAMSUNG
 
 config EXYNOS_PMU
        bool "Exynos PMU controller driver" if COMPILE_TEST
-       depends on (ARM && ARCH_EXYNOS) || ((ARM || ARM64) && COMPILE_TEST)
+       depends on ARCH_EXYNOS || ((ARM || ARM64) && COMPILE_TEST)
+       select EXYNOS_PMU_ARM_DRIVERS if ARM && ARCH_EXYNOS
+
+# There is no need to enable these drivers for ARMv8
+config EXYNOS_PMU_ARM_DRIVERS
+       bool "Exynos PMU ARMv7-specific driver extensions" if COMPILE_TEST
+       depends on EXYNOS_PMU
 
 config EXYNOS_PM_DOMAINS
        bool "Exynos PM domains" if COMPILE_TEST
index 3619f2ecddaa787da3bd19f86c3cc35b0a39c50e..4d7694a4e7a4916db6892cf036fbf872ef31d58b 100644 (file)
@@ -1,3 +1,5 @@
-obj-$(CONFIG_EXYNOS_PMU)       += exynos-pmu.o exynos3250-pmu.o exynos4-pmu.o \
+obj-$(CONFIG_EXYNOS_PMU)       += exynos-pmu.o
+
+obj-$(CONFIG_EXYNOS_PMU_ARM_DRIVERS)   += exynos3250-pmu.o exynos4-pmu.o \
                                        exynos5250-pmu.o exynos5420-pmu.o
 obj-$(CONFIG_EXYNOS_PM_DOMAINS) += pm_domains.o
index 56d9244ff98147d056fc094fb6dcee6ad7f6830e..bd4a76f27bc20521a214c26888f1e7a27b8cc9ff 100644 (file)
@@ -68,28 +68,38 @@ void exynos_sys_powerdown_conf(enum sys_powerdown mode)
        }
 }
 
+/*
+ * Split the data between ARM architectures because it is relatively big
+ * and useless on other arch.
+ */
+#ifdef CONFIG_EXYNOS_PMU_ARM_DRIVERS
+#define exynos_pmu_data_arm_ptr(data)  (&data)
+#else
+#define exynos_pmu_data_arm_ptr(data)  NULL
+#endif
+
 /*
  * PMU platform driver and devicetree bindings.
  */
 static const struct of_device_id exynos_pmu_of_device_ids[] = {
        {
                .compatible = "samsung,exynos3250-pmu",
-               .data = &exynos3250_pmu_data,
+               .data = exynos_pmu_data_arm_ptr(exynos3250_pmu_data),
        }, {
                .compatible = "samsung,exynos4210-pmu",
-               .data = &exynos4210_pmu_data,
+               .data = exynos_pmu_data_arm_ptr(exynos4210_pmu_data),
        }, {
                .compatible = "samsung,exynos4212-pmu",
-               .data = &exynos4212_pmu_data,
+               .data = exynos_pmu_data_arm_ptr(exynos4212_pmu_data),
        }, {
                .compatible = "samsung,exynos4412-pmu",
-               .data = &exynos4412_pmu_data,
+               .data = exynos_pmu_data_arm_ptr(exynos4412_pmu_data),
        }, {
                .compatible = "samsung,exynos5250-pmu",
-               .data = &exynos5250_pmu_data,
+               .data = exynos_pmu_data_arm_ptr(exynos5250_pmu_data),
        }, {
                .compatible = "samsung,exynos5420-pmu",
-               .data = &exynos5420_pmu_data,
+               .data = exynos_pmu_data_arm_ptr(exynos5420_pmu_data),
        }, {
                .compatible = "samsung,exynos5433-pmu",
        },
index a469e366fead456671b53bc7f1512751fe03c5c6..40d4229abfb5670b3da22df5e3a9d2e5baa5cbd1 100644 (file)
@@ -31,6 +31,8 @@ struct exynos_pmu_data {
 };
 
 extern void __iomem *pmu_base_addr;
+
+#ifdef CONFIG_EXYNOS_PMU_ARM_DRIVERS
 /* list of all exported SoC specific data */
 extern const struct exynos_pmu_data exynos3250_pmu_data;
 extern const struct exynos_pmu_data exynos4210_pmu_data;
@@ -38,6 +40,7 @@ extern const struct exynos_pmu_data exynos4212_pmu_data;
 extern const struct exynos_pmu_data exynos4412_pmu_data;
 extern const struct exynos_pmu_data exynos5250_pmu_data;
 extern const struct exynos_pmu_data exynos5420_pmu_data;
+#endif
 
 extern void pmu_raw_writel(u32 val, u32 offset);
 extern u32 pmu_raw_readl(u32 offset);
index e5e124c07066b8a0e202cfe2fd17fb71f979e71e..dcf088db40b664502e9c4dacba81e5487a811f46 100644 (file)
@@ -12,6 +12,8 @@ config ARCH_TEGRA_2x_SOC
        select PINCTRL_TEGRA20
        select PL310_ERRATA_727915 if CACHE_L2X0
        select PL310_ERRATA_769419 if CACHE_L2X0
+       select SOC_TEGRA_FLOWCTRL
+       select SOC_TEGRA_PMC
        select TEGRA_TIMER
        help
          Support for NVIDIA Tegra AP20 and T20 processors, based on the
@@ -23,6 +25,8 @@ config ARCH_TEGRA_3x_SOC
        select ARM_ERRATA_764369 if SMP
        select PINCTRL_TEGRA30
        select PL310_ERRATA_769419 if CACHE_L2X0
+       select SOC_TEGRA_FLOWCTRL
+       select SOC_TEGRA_PMC
        select TEGRA_TIMER
        help
          Support for NVIDIA Tegra T30 processor family, based on the
@@ -33,6 +37,8 @@ config ARCH_TEGRA_114_SOC
        select ARM_ERRATA_798181 if SMP
        select HAVE_ARM_ARCH_TIMER
        select PINCTRL_TEGRA114
+       select SOC_TEGRA_FLOWCTRL
+       select SOC_TEGRA_PMC
        select TEGRA_TIMER
        help
          Support for NVIDIA Tegra T114 processor family, based on the
@@ -42,6 +48,8 @@ config ARCH_TEGRA_124_SOC
        bool "Enable support for Tegra124 family"
        select HAVE_ARM_ARCH_TIMER
        select PINCTRL_TEGRA124
+       select SOC_TEGRA_FLOWCTRL
+       select SOC_TEGRA_PMC
        select TEGRA_TIMER
        help
          Support for NVIDIA Tegra T124 processor family, based on the
@@ -55,6 +63,8 @@ if ARM64
 config ARCH_TEGRA_132_SOC
        bool "NVIDIA Tegra132 SoC"
        select PINCTRL_TEGRA124
+       select SOC_TEGRA_FLOWCTRL
+       select SOC_TEGRA_PMC
        help
          Enable support for NVIDIA Tegra132 SoC, based on the Denver
          ARMv8 CPU.  The Tegra132 SoC is similar to the Tegra124 SoC,
@@ -64,6 +74,8 @@ config ARCH_TEGRA_132_SOC
 config ARCH_TEGRA_210_SOC
        bool "NVIDIA Tegra210 SoC"
        select PINCTRL_TEGRA210
+       select SOC_TEGRA_FLOWCTRL
+       select SOC_TEGRA_PMC
        help
          Enable support for the NVIDIA Tegra210 SoC. Also known as Tegra X1,
          the Tegra210 has four Cortex-A57 cores paired with four Cortex-A53
@@ -83,6 +95,7 @@ config ARCH_TEGRA_186_SOC
        select TEGRA_BPMP
        select TEGRA_HSP_MBOX
        select TEGRA_IVC
+       select SOC_TEGRA_PMC_TEGRA186
        help
          Enable support for the NVIDIA Tegar186 SoC. The Tegra186 features a
          combination of Denver and Cortex-A57 CPU cores and a GPU based on
@@ -93,3 +106,12 @@ config ARCH_TEGRA_186_SOC
 
 endif
 endif
+
+config SOC_TEGRA_FLOWCTRL
+       bool
+
+config SOC_TEGRA_PMC
+       bool
+
+config SOC_TEGRA_PMC_TEGRA186
+       bool
index ae857ff7d53d99c772d3a4c5809b618a17957fdb..4f81dd55e5d1c46443724ef34e90d03e9d15796c 100644 (file)
@@ -1,4 +1,6 @@
 obj-y += fuse/
 
 obj-y += common.o
-obj-y += pmc.o
+obj-$(CONFIG_SOC_TEGRA_FLOWCTRL) += flowctrl.o
+obj-$(CONFIG_SOC_TEGRA_PMC) += pmc.o
+obj-$(CONFIG_SOC_TEGRA_PMC_TEGRA186) += pmc-tegra186.o
similarity index 67%
rename from arch/arm/mach-tegra/flowctrl.c
rename to drivers/soc/tegra/flowctrl.c
index 475e783992fd284dbeb613ba8928262811c1809a..0e345c05fc6529faefe7f991c5f98845e6db07a5 100644 (file)
@@ -1,7 +1,7 @@
 /*
- * arch/arm/mach-tegra/flowctrl.c
+ * drivers/soc/tegra/flowctrl.c
  *
- * functions and macros to control the flowcontroller
+ * Functions and macros to control the flowcontroller
  *
  * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
  *
 #include <linux/kernel.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/platform_device.h>
 
+#include <soc/tegra/common.h>
+#include <soc/tegra/flowctrl.h>
 #include <soc/tegra/fuse.h>
 
-#include "flowctrl.h"
-
 static u8 flowctrl_offset_halt_cpu[] = {
        FLOW_CTRL_HALT_CPU0_EVENTS,
        FLOW_CTRL_HALT_CPU1_EVENTS,
@@ -47,6 +48,10 @@ static void __iomem *tegra_flowctrl_base;
 
 static void flowctrl_update(u8 offset, u32 value)
 {
+       if (WARN_ONCE(IS_ERR_OR_NULL(tegra_flowctrl_base),
+                     "Tegra flowctrl not initialised!\n"))
+               return;
+
        writel(value, tegra_flowctrl_base + offset);
 
        /* ensure the update has reached the flow controller */
@@ -58,6 +63,10 @@ u32 flowctrl_read_cpu_csr(unsigned int cpuid)
 {
        u8 offset = flowctrl_offset_cpu_csr[cpuid];
 
+       if (WARN_ONCE(IS_ERR_OR_NULL(tegra_flowctrl_base),
+                     "Tegra flowctrl not initialised!\n"))
+               return 0;
+
        return readl(tegra_flowctrl_base + offset);
 }
 
@@ -140,7 +149,23 @@ void flowctrl_cpu_suspend_exit(unsigned int cpuid)
        flowctrl_write_cpu_csr(cpuid, reg);
 }
 
-static const struct of_device_id matches[] __initconst = {
+static int tegra_flowctrl_probe(struct platform_device *pdev)
+{
+       void __iomem *base = tegra_flowctrl_base;
+       struct resource *res;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       tegra_flowctrl_base = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(tegra_flowctrl_base))
+               return PTR_ERR(base);
+
+       iounmap(base);
+
+       return 0;
+}
+
+static const struct of_device_id tegra_flowctrl_match[] = {
+       { .compatible = "nvidia,tegra210-flowctrl" },
        { .compatible = "nvidia,tegra124-flowctrl" },
        { .compatible = "nvidia,tegra114-flowctrl" },
        { .compatible = "nvidia,tegra30-flowctrl" },
@@ -148,24 +173,52 @@ static const struct of_device_id matches[] __initconst = {
        { }
 };
 
-void __init tegra_flowctrl_init(void)
+static struct platform_driver tegra_flowctrl_driver = {
+       .driver = {
+               .name = "tegra-flowctrl",
+               .suppress_bind_attrs = true,
+               .of_match_table = tegra_flowctrl_match,
+       },
+       .probe = tegra_flowctrl_probe,
+};
+builtin_platform_driver(tegra_flowctrl_driver);
+
+static int __init tegra_flowctrl_init(void)
 {
-       /* hardcoded fallback if device tree node is missing */
-       unsigned long base = 0x60007000;
-       unsigned long size = SZ_4K;
+       struct resource res;
        struct device_node *np;
 
-       np = of_find_matching_node(NULL, matches);
-       if (np) {
-               struct resource res;
+       if (!soc_is_tegra())
+               return 0;
 
-               if (of_address_to_resource(np, 0, &res) == 0) {
-                       size = resource_size(&res);
-                       base = res.start;
+       np = of_find_matching_node(NULL, tegra_flowctrl_match);
+       if (np) {
+               if (of_address_to_resource(np, 0, &res) < 0) {
+                       pr_err("failed to get flowctrl register\n");
+                       return -ENXIO;
                }
-
                of_node_put(np);
+       } else if (IS_ENABLED(CONFIG_ARM)) {
+               /*
+                * Hardcoded fallback for 32-bit Tegra
+                * devices if device tree node is missing.
+                */
+               res.start = 0x60007000;
+               res.end = 0x60007fff;
+               res.flags = IORESOURCE_MEM;
+       } else {
+               /*
+                * At this point we're running on a Tegra,
+                * that doesn't support the flow controller
+                * (eg. Tegra186), so just return.
+                */
+               return 0;
        }
 
-       tegra_flowctrl_base = ioremap_nocache(base, size);
+       tegra_flowctrl_base = ioremap_nocache(res.start, resource_size(&res));
+       if (!tegra_flowctrl_base)
+               return -ENXIO;
+
+       return 0;
 }
+early_initcall(tegra_flowctrl_init);
index de2c1bfe28b5f6297f6c51dc570951556d064f34..7413f60fa855d7f128efe604a972ee361fdfea4b 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/clk.h>
 #include <linux/device.h>
 #include <linux/kobject.h>
-#include <linux/module.h>
+#include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
@@ -168,7 +168,7 @@ static struct platform_driver tegra_fuse_driver = {
        },
        .probe = tegra_fuse_probe,
 };
-module_platform_driver(tegra_fuse_driver);
+builtin_platform_driver(tegra_fuse_driver);
 
 bool __init tegra_fuse_read_spare(unsigned int spare)
 {
diff --git a/drivers/soc/tegra/pmc-tegra186.c b/drivers/soc/tegra/pmc-tegra186.c
new file mode 100644 (file)
index 0000000..6f5c6f9
--- /dev/null
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ */
+
+#define pr_fmt(fmt) "tegra-pmc: " fmt
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/reboot.h>
+
+#include <asm/system_misc.h>
+
+#define PMC_CNTRL 0x000
+#define  PMC_CNTRL_MAIN_RST BIT(4)
+
+#define PMC_RST_STATUS 0x070
+
+#define WAKE_AOWAKE_CTRL 0x4f4
+#define  WAKE_AOWAKE_CTRL_INTR_POLARITY BIT(0)
+
+#define SCRATCH_SCRATCH0 0x2000
+#define  SCRATCH_SCRATCH0_MODE_RECOVERY BIT(31)
+#define  SCRATCH_SCRATCH0_MODE_BOOTLOADER BIT(30)
+#define  SCRATCH_SCRATCH0_MODE_RCM BIT(1)
+#define  SCRATCH_SCRATCH0_MODE_MASK (SCRATCH_SCRATCH0_MODE_RECOVERY | \
+                                    SCRATCH_SCRATCH0_MODE_BOOTLOADER | \
+                                    SCRATCH_SCRATCH0_MODE_RCM)
+
+struct tegra_pmc {
+       struct device *dev;
+       void __iomem *regs;
+       void __iomem *wake;
+       void __iomem *aotag;
+       void __iomem *scratch;
+
+       void (*system_restart)(enum reboot_mode mode, const char *cmd);
+       struct notifier_block restart;
+};
+
+static int tegra186_pmc_restart_notify(struct notifier_block *nb,
+                                      unsigned long action,
+                                      void *data)
+{
+       struct tegra_pmc *pmc = container_of(nb, struct tegra_pmc, restart);
+       const char *cmd = data;
+       u32 value;
+
+       value = readl(pmc->scratch + SCRATCH_SCRATCH0);
+       value &= ~SCRATCH_SCRATCH0_MODE_MASK;
+
+       if (cmd) {
+               if (strcmp(cmd, "recovery") == 0)
+                       value |= SCRATCH_SCRATCH0_MODE_RECOVERY;
+
+               if (strcmp(cmd, "bootloader") == 0)
+                       value |= SCRATCH_SCRATCH0_MODE_BOOTLOADER;
+
+               if (strcmp(cmd, "forced-recovery") == 0)
+                       value |= SCRATCH_SCRATCH0_MODE_RCM;
+       }
+
+       writel(value, pmc->scratch + SCRATCH_SCRATCH0);
+
+       /*
+        * If available, call the system restart implementation that was
+        * registered earlier (typically PSCI).
+        */
+       if (pmc->system_restart) {
+               pmc->system_restart(reboot_mode, cmd);
+               return NOTIFY_DONE;
+       }
+
+       /* reset everything but SCRATCH0_SCRATCH0 and PMC_RST_STATUS */
+       value = readl(pmc->regs + PMC_CNTRL);
+       value |= PMC_CNTRL_MAIN_RST;
+       writel(value, pmc->regs + PMC_CNTRL);
+
+       return NOTIFY_DONE;
+}
+
+static int tegra186_pmc_setup(struct tegra_pmc *pmc)
+{
+       struct device_node *np = pmc->dev->of_node;
+       bool invert;
+       u32 value;
+
+       invert = of_property_read_bool(np, "nvidia,invert-interrupt");
+
+       value = readl(pmc->wake + WAKE_AOWAKE_CTRL);
+
+       if (invert)
+               value |= WAKE_AOWAKE_CTRL_INTR_POLARITY;
+       else
+               value &= ~WAKE_AOWAKE_CTRL_INTR_POLARITY;
+
+       writel(value, pmc->wake + WAKE_AOWAKE_CTRL);
+
+       /*
+        * We need to hook any system restart implementation registered
+        * previously so we can write SCRATCH_SCRATCH0 before reset.
+        */
+       pmc->system_restart = arm_pm_restart;
+       arm_pm_restart = NULL;
+
+       pmc->restart.notifier_call = tegra186_pmc_restart_notify;
+       pmc->restart.priority = 128;
+
+       return register_restart_handler(&pmc->restart);
+}
+
+static int tegra186_pmc_probe(struct platform_device *pdev)
+{
+       struct tegra_pmc *pmc;
+       struct resource *res;
+
+       pmc = devm_kzalloc(&pdev->dev, sizeof(*pmc), GFP_KERNEL);
+       if (!pmc)
+               return -ENOMEM;
+
+       pmc->dev = &pdev->dev;
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pmc");
+       pmc->regs = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(pmc->regs))
+               return PTR_ERR(pmc->regs);
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "wake");
+       pmc->wake = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(pmc->wake))
+               return PTR_ERR(pmc->wake);
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "aotag");
+       pmc->aotag = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(pmc->aotag))
+               return PTR_ERR(pmc->aotag);
+
+       res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "scratch");
+       pmc->scratch = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(pmc->scratch))
+               return PTR_ERR(pmc->scratch);
+
+       return tegra186_pmc_setup(pmc);
+}
+
+static const struct of_device_id tegra186_pmc_of_match[] = {
+       { .compatible = "nvidia,tegra186-pmc" },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, tegra186_pmc_of_match);
+
+static struct platform_driver tegra186_pmc_driver = {
+       .driver = {
+               .name = "tegra186-pmc",
+               .of_match_table = tegra186_pmc_of_match,
+       },
+       .probe = tegra186_pmc_probe,
+};
+builtin_platform_driver(tegra186_pmc_driver);
index 3557c5e32a931098e9386e97db82da6efeeb2632..39e152abe6b901cfb6fabd0e1f379740a86de2ab 100644 (file)
@@ -38,4 +38,16 @@ config WKUP_M3_IPC
          to communicate and use the Wakeup M3 for PM features like suspend
          resume and boots it using wkup_m3_rproc driver.
 
+config TI_SCI_PM_DOMAINS
+       tristate "TI SCI PM Domains Driver"
+       depends on TI_SCI_PROTOCOL
+       depends on PM_GENERIC_DOMAINS
+       help
+         Generic power domain implementation for TI device implementing
+         the TI SCI protocol.
+
+         To compile this as a module, choose M here. The module will be
+         called ti_sci_pm_domains. Note this is needed early in boot before
+         rootfs may be available.
+
 endif # SOC_TI
index 48ff3a79634fb2d7bbeca91f6a638e417e5557bb..7d572736c86ec8507f1d80d45479d99001446202 100644 (file)
@@ -5,3 +5,4 @@ obj-$(CONFIG_KEYSTONE_NAVIGATOR_QMSS)   += knav_qmss.o
 knav_qmss-y := knav_qmss_queue.o knav_qmss_acc.o
 obj-$(CONFIG_KEYSTONE_NAVIGATOR_DMA)   += knav_dma.o
 obj-$(CONFIG_WKUP_M3_IPC)              += wkup_m3_ipc.o
+obj-$(CONFIG_TI_SCI_PM_DOMAINS)                += ti_sci_pm_domains.o
index ecebe2eecc3aac5058de888817b719f42934d526..026182d3b27c1405a9b875d529795a2e8295a0aa 100644 (file)
@@ -413,7 +413,7 @@ static int of_channel_match_helper(struct device_node *np, const char *name,
  * @name:      slave channel name
  * @config:    dma configuration parameters
  *
- * Returns pointer to appropriate DMA channel on success or NULL.
+ * Returns pointer to appropriate DMA channel on success or error.
  */
 void *knav_dma_open_channel(struct device *dev, const char *name,
                                        struct knav_dma_cfg *config)
diff --git a/drivers/soc/ti/ti_sci_pm_domains.c b/drivers/soc/ti/ti_sci_pm_domains.c
new file mode 100644 (file)
index 0000000..b0b2838
--- /dev/null
@@ -0,0 +1,202 @@
+/*
+ * TI SCI Generic Power Domain Driver
+ *
+ * Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com/
+ *     J Keerthy <j-keerthy@ti.com>
+ *     Dave Gerlach <d-gerlach@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
+#include <linux/slab.h>
+#include <linux/soc/ti/ti_sci_protocol.h>
+
+/**
+ * struct ti_sci_genpd_dev_data: holds data needed for every device attached
+ *                              to this genpd
+ * @idx: index of the device that identifies it with the system
+ *      control processor.
+ */
+struct ti_sci_genpd_dev_data {
+       int idx;
+};
+
+/**
+ * struct ti_sci_pm_domain: TI specific data needed for power domain
+ * @ti_sci: handle to TI SCI protocol driver that provides ops to
+ *         communicate with system control processor.
+ * @dev: pointer to dev for the driver for devm allocs
+ * @pd: generic_pm_domain for use with the genpd framework
+ */
+struct ti_sci_pm_domain {
+       const struct ti_sci_handle *ti_sci;
+       struct device *dev;
+       struct generic_pm_domain pd;
+};
+
+#define genpd_to_ti_sci_pd(gpd) container_of(gpd, struct ti_sci_pm_domain, pd)
+
+/**
+ * ti_sci_dev_id(): get prepopulated ti_sci id from struct dev
+ * @dev: pointer to device associated with this genpd
+ *
+ * Returns device_id stored from ti,sci_id property
+ */
+static int ti_sci_dev_id(struct device *dev)
+{
+       struct generic_pm_domain_data *genpd_data = dev_gpd_data(dev);
+       struct ti_sci_genpd_dev_data *sci_dev_data = genpd_data->data;
+
+       return sci_dev_data->idx;
+}
+
+/**
+ * ti_sci_dev_to_sci_handle(): get pointer to ti_sci_handle
+ * @dev: pointer to device associated with this genpd
+ *
+ * Returns ti_sci_handle to be used to communicate with system
+ *        control processor.
+ */
+static const struct ti_sci_handle *ti_sci_dev_to_sci_handle(struct device *dev)
+{
+       struct generic_pm_domain *pd = pd_to_genpd(dev->pm_domain);
+       struct ti_sci_pm_domain *ti_sci_genpd = genpd_to_ti_sci_pd(pd);
+
+       return ti_sci_genpd->ti_sci;
+}
+
+/**
+ * ti_sci_dev_start(): genpd device start hook called to turn device on
+ * @dev: pointer to device associated with this genpd to be powered on
+ */
+static int ti_sci_dev_start(struct device *dev)
+{
+       const struct ti_sci_handle *ti_sci = ti_sci_dev_to_sci_handle(dev);
+       int idx = ti_sci_dev_id(dev);
+
+       return ti_sci->ops.dev_ops.get_device(ti_sci, idx);
+}
+
+/**
+ * ti_sci_dev_stop(): genpd device stop hook called to turn device off
+ * @dev: pointer to device associated with this genpd to be powered off
+ */
+static int ti_sci_dev_stop(struct device *dev)
+{
+       const struct ti_sci_handle *ti_sci = ti_sci_dev_to_sci_handle(dev);
+       int idx = ti_sci_dev_id(dev);
+
+       return ti_sci->ops.dev_ops.put_device(ti_sci, idx);
+}
+
+static int ti_sci_pd_attach_dev(struct generic_pm_domain *domain,
+                               struct device *dev)
+{
+       struct device_node *np = dev->of_node;
+       struct of_phandle_args pd_args;
+       struct ti_sci_pm_domain *ti_sci_genpd = genpd_to_ti_sci_pd(domain);
+       const struct ti_sci_handle *ti_sci = ti_sci_genpd->ti_sci;
+       struct ti_sci_genpd_dev_data *sci_dev_data;
+       struct generic_pm_domain_data *genpd_data;
+       int idx, ret = 0;
+
+       ret = of_parse_phandle_with_args(np, "power-domains",
+                                        "#power-domain-cells", 0, &pd_args);
+       if (ret < 0)
+               return ret;
+
+       if (pd_args.args_count != 1)
+               return -EINVAL;
+
+       idx = pd_args.args[0];
+
+       /*
+        * Check the validity of the requested idx, if the index is not valid
+        * the PMMC will return a NAK here and we will not allocate it.
+        */
+       ret = ti_sci->ops.dev_ops.is_valid(ti_sci, idx);
+       if (ret)
+               return -EINVAL;
+
+       sci_dev_data = kzalloc(sizeof(*sci_dev_data), GFP_KERNEL);
+       if (!sci_dev_data)
+               return -ENOMEM;
+
+       sci_dev_data->idx = idx;
+
+       genpd_data = dev_gpd_data(dev);
+       genpd_data->data = sci_dev_data;
+
+       return 0;
+}
+
+static void ti_sci_pd_detach_dev(struct generic_pm_domain *domain,
+                                struct device *dev)
+{
+       struct generic_pm_domain_data *genpd_data = dev_gpd_data(dev);
+       struct ti_sci_genpd_dev_data *sci_dev_data = genpd_data->data;
+
+       kfree(sci_dev_data);
+       genpd_data->data = NULL;
+}
+
+static const struct of_device_id ti_sci_pm_domain_matches[] = {
+       { .compatible = "ti,sci-pm-domain", },
+       { },
+};
+MODULE_DEVICE_TABLE(of, ti_sci_pm_domain_matches);
+
+static int ti_sci_pm_domain_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device_node *np = dev->of_node;
+       struct ti_sci_pm_domain *ti_sci_pd;
+       int ret;
+
+       ti_sci_pd = devm_kzalloc(dev, sizeof(*ti_sci_pd), GFP_KERNEL);
+       if (!ti_sci_pd)
+               return -ENOMEM;
+
+       ti_sci_pd->ti_sci = devm_ti_sci_get_handle(dev);
+       if (IS_ERR(ti_sci_pd->ti_sci))
+               return PTR_ERR(ti_sci_pd->ti_sci);
+
+       ti_sci_pd->dev = dev;
+
+       ti_sci_pd->pd.attach_dev = ti_sci_pd_attach_dev;
+       ti_sci_pd->pd.detach_dev = ti_sci_pd_detach_dev;
+
+       ti_sci_pd->pd.dev_ops.start = ti_sci_dev_start;
+       ti_sci_pd->pd.dev_ops.stop = ti_sci_dev_stop;
+
+       pm_genpd_init(&ti_sci_pd->pd, NULL, true);
+
+       ret = of_genpd_add_provider_simple(np, &ti_sci_pd->pd);
+
+       return ret;
+}
+
+static struct platform_driver ti_sci_pm_domains_driver = {
+       .probe = ti_sci_pm_domain_probe,
+       .driver = {
+               .name = "ti_sci_pm_domains",
+               .of_match_table = ti_sci_pm_domain_matches,
+       },
+};
+module_platform_driver(ti_sci_pm_domains_driver);
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("TI System Control Interface (SCI) Power Domain driver");
+MODULE_AUTHOR("Dave Gerlach");
index 5ed924fee855c8b21b82c5dc26844604ff639d34..4dc5d62ee81b1674088a8df2da3600310c0cd7a0 100644 (file)
@@ -169,7 +169,6 @@ static const struct of_device_id zx296718_pm_domain_matches[] = {
 static struct platform_driver zx296718_pd_driver = {
        .driver = {
                .name = "zx296718-powerdomain",
-               .owner = THIS_MODULE,
                .of_match_table = zx296718_pm_domain_matches,
        },
        .probe = zx296718_pd_probe,
index 61c8d84bf31560725439904c0d4e1fc8dbe8775f..c42aeaaa34bab184e1e64008abd2c58ae0bce45e 100644 (file)
@@ -125,10 +125,8 @@ int zx2967_pd_probe(struct platform_device *pdev,
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        pcubase = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(pcubase)) {
-               dev_err(&pdev->dev, "ioremap fail.\n");
+       if (IS_ERR(pcubase))
                return PTR_ERR(pcubase);
-       }
 
        for (i = 0; i < domain_num; ++i) {
                zx_pm_domains[i]->power_on = zx2967_power_on;
index 8ff5d4ec9e5c00d25a81e5a3f2ec47a20b1c5804..f99d4219b01eaf1894b6ccc8a1892971b2e96fc1 100644 (file)
@@ -1987,22 +1987,24 @@ static struct ssi_hash_template driver_hash[] = {
                .hmac_driver_name = "hmac-sha1-dx",
                .blocksize = SHA1_BLOCK_SIZE,
                .synchronize = false,
-               .template_ahash = {
-                       .init = ssi_ahash_init,
-                       .update = ssi_ahash_update,
-                       .final = ssi_ahash_final,
-                       .finup = ssi_ahash_finup,
-                       .digest = ssi_ahash_digest,
+               {
+                       .template_ahash = {
+                               .init = ssi_ahash_init,
+                               .update = ssi_ahash_update,
+                               .final = ssi_ahash_final,
+                               .finup = ssi_ahash_finup,
+                               .digest = ssi_ahash_digest,
 #ifdef EXPORT_FIXED
-                       .export = ssi_ahash_export,
-                       .import = ssi_ahash_import,
+                               .export = ssi_ahash_export,
+                               .import = ssi_ahash_import,
 #endif
-                       .setkey = ssi_ahash_setkey,
-                       .halg = {
-                               .digestsize = SHA1_DIGEST_SIZE,
-                               .statesize = sizeof(struct sha1_state),
+                               .setkey = ssi_ahash_setkey,
+                               .halg = {
+                                       .digestsize = SHA1_DIGEST_SIZE,
+                                       .statesize = sizeof(struct sha1_state),
+                                       },
                                },
-                       },
+               },
                .hash_mode = DRV_HASH_SHA1,
                .hw_mode = DRV_HASH_HW_SHA1,
                .inter_digestsize = SHA1_DIGEST_SIZE,
@@ -2014,22 +2016,24 @@ static struct ssi_hash_template driver_hash[] = {
                .hmac_driver_name = "hmac-sha256-dx",
                .blocksize = SHA256_BLOCK_SIZE,
                .synchronize = false,
-               .template_ahash = {
-                       .init = ssi_ahash_init,
-                       .update = ssi_ahash_update,
-                       .final = ssi_ahash_final,
-                       .finup = ssi_ahash_finup,
-                       .digest = ssi_ahash_digest,
+               {
+                       .template_ahash = {
+                               .init = ssi_ahash_init,
+                               .update = ssi_ahash_update,
+                               .final = ssi_ahash_final,
+                               .finup = ssi_ahash_finup,
+                               .digest = ssi_ahash_digest,
 #ifdef EXPORT_FIXED
-                       .export = ssi_ahash_export,
-                       .import = ssi_ahash_import,
+                               .export = ssi_ahash_export,
+                               .import = ssi_ahash_import,
 #endif
-                       .setkey = ssi_ahash_setkey,
-                       .halg = {
-                               .digestsize = SHA256_DIGEST_SIZE,
-                               .statesize = sizeof(struct sha256_state),
+                               .setkey = ssi_ahash_setkey,
+                               .halg = {
+                                       .digestsize = SHA256_DIGEST_SIZE,
+                                       .statesize = sizeof(struct sha256_state),
+                                       },
                                },
-                       },
+               },
                .hash_mode = DRV_HASH_SHA256,
                .hw_mode = DRV_HASH_HW_SHA256,
                .inter_digestsize = SHA256_DIGEST_SIZE,
@@ -2041,22 +2045,24 @@ static struct ssi_hash_template driver_hash[] = {
                .hmac_driver_name = "hmac-sha224-dx",
                .blocksize = SHA224_BLOCK_SIZE,
                .synchronize = false,
-               .template_ahash = {
-                       .init = ssi_ahash_init,
-                       .update = ssi_ahash_update,
-                       .final = ssi_ahash_final,
-                       .finup = ssi_ahash_finup,
-                       .digest = ssi_ahash_digest,
+               {
+                       .template_ahash = {
+                               .init = ssi_ahash_init,
+                               .update = ssi_ahash_update,
+                               .final = ssi_ahash_final,
+                               .finup = ssi_ahash_finup,
+                               .digest = ssi_ahash_digest,
 #ifdef EXPORT_FIXED
-                       .export = ssi_ahash_export,
-                       .import = ssi_ahash_import,
+                               .export = ssi_ahash_export,
+                               .import = ssi_ahash_import,
 #endif
-                       .setkey = ssi_ahash_setkey,
-                       .halg = {
-                               .digestsize = SHA224_DIGEST_SIZE,
-                               .statesize = sizeof(struct sha256_state),
+                               .setkey = ssi_ahash_setkey,
+                               .halg = {
+                                       .digestsize = SHA224_DIGEST_SIZE,
+                                       .statesize = sizeof(struct sha256_state),
+                                       },
                                },
-                       },
+               },
                .hash_mode = DRV_HASH_SHA224,
                .hw_mode = DRV_HASH_HW_SHA256,
                .inter_digestsize = SHA256_DIGEST_SIZE,
@@ -2069,22 +2075,24 @@ static struct ssi_hash_template driver_hash[] = {
                .hmac_driver_name = "hmac-sha384-dx",
                .blocksize = SHA384_BLOCK_SIZE,
                .synchronize = false,
-               .template_ahash = {
-                       .init = ssi_ahash_init,
-                       .update = ssi_ahash_update,
-                       .final = ssi_ahash_final,
-                       .finup = ssi_ahash_finup,
-                       .digest = ssi_ahash_digest,
+               {
+                       .template_ahash = {
+                               .init = ssi_ahash_init,
+                               .update = ssi_ahash_update,
+                               .final = ssi_ahash_final,
+                               .finup = ssi_ahash_finup,
+                               .digest = ssi_ahash_digest,
 #ifdef EXPORT_FIXED
-                       .export = ssi_ahash_export,
-                       .import = ssi_ahash_import,
+                               .export = ssi_ahash_export,
+                               .import = ssi_ahash_import,
 #endif
-                       .setkey = ssi_ahash_setkey,
-                       .halg = {
-                               .digestsize = SHA384_DIGEST_SIZE,
-                               .statesize = sizeof(struct sha512_state),
+                               .setkey = ssi_ahash_setkey,
+                               .halg = {
+                                       .digestsize = SHA384_DIGEST_SIZE,
+                                       .statesize = sizeof(struct sha512_state),
+                                       },
                                },
-                       },
+               },
                .hash_mode = DRV_HASH_SHA384,
                .hw_mode = DRV_HASH_HW_SHA512,
                .inter_digestsize = SHA512_DIGEST_SIZE,
@@ -2096,22 +2104,24 @@ static struct ssi_hash_template driver_hash[] = {
                .hmac_driver_name = "hmac-sha512-dx",
                .blocksize = SHA512_BLOCK_SIZE,
                .synchronize = false,
-               .template_ahash = {
-                       .init = ssi_ahash_init,
-                       .update = ssi_ahash_update,
-                       .final = ssi_ahash_final,
-                       .finup = ssi_ahash_finup,
-                       .digest = ssi_ahash_digest,
+               {
+                       .template_ahash = {
+                               .init = ssi_ahash_init,
+                               .update = ssi_ahash_update,
+                               .final = ssi_ahash_final,
+                               .finup = ssi_ahash_finup,
+                               .digest = ssi_ahash_digest,
 #ifdef EXPORT_FIXED
-                       .export = ssi_ahash_export,
-                       .import = ssi_ahash_import,
+                               .export = ssi_ahash_export,
+                               .import = ssi_ahash_import,
 #endif
-                       .setkey = ssi_ahash_setkey,
-                       .halg = {
-                               .digestsize = SHA512_DIGEST_SIZE,
-                               .statesize = sizeof(struct sha512_state),
+                               .setkey = ssi_ahash_setkey,
+                               .halg = {
+                                       .digestsize = SHA512_DIGEST_SIZE,
+                                       .statesize = sizeof(struct sha512_state),
+                                       },
                                },
-                       },
+               },
                .hash_mode = DRV_HASH_SHA512,
                .hw_mode = DRV_HASH_HW_SHA512,
                .inter_digestsize = SHA512_DIGEST_SIZE,
@@ -2124,22 +2134,24 @@ static struct ssi_hash_template driver_hash[] = {
                .hmac_driver_name = "hmac-md5-dx",
                .blocksize = MD5_HMAC_BLOCK_SIZE,
                .synchronize = false,
-               .template_ahash = {
-                       .init = ssi_ahash_init,
-                       .update = ssi_ahash_update,
-                       .final = ssi_ahash_final,
-                       .finup = ssi_ahash_finup,
-                       .digest = ssi_ahash_digest,
+               {
+                       .template_ahash = {
+                               .init = ssi_ahash_init,
+                               .update = ssi_ahash_update,
+                               .final = ssi_ahash_final,
+                               .finup = ssi_ahash_finup,
+                               .digest = ssi_ahash_digest,
 #ifdef EXPORT_FIXED
-                       .export = ssi_ahash_export,
-                       .import = ssi_ahash_import,
+                               .export = ssi_ahash_export,
+                               .import = ssi_ahash_import,
 #endif
-                       .setkey = ssi_ahash_setkey,
-                       .halg = {
-                               .digestsize = MD5_DIGEST_SIZE,
-                               .statesize = sizeof(struct md5_state),
+                               .setkey = ssi_ahash_setkey,
+                               .halg = {
+                                       .digestsize = MD5_DIGEST_SIZE,
+                                       .statesize = sizeof(struct md5_state),
+                                       },
                                },
-                       },
+               },
                .hash_mode = DRV_HASH_MD5,
                .hw_mode = DRV_HASH_HW_MD5,
                .inter_digestsize = MD5_DIGEST_SIZE,
@@ -2149,52 +2161,56 @@ static struct ssi_hash_template driver_hash[] = {
                .driver_name = "xcbc-aes-dx",
                .blocksize = AES_BLOCK_SIZE,
                .synchronize = false,
-               .template_ahash = {
-                       .init = ssi_ahash_init,
-                       .update = ssi_mac_update,
-                       .final = ssi_mac_final,
-                       .finup = ssi_mac_finup,
-                       .digest = ssi_mac_digest,
-                       .setkey = ssi_xcbc_setkey,
+               {
+                       .template_ahash = {
+                               .init = ssi_ahash_init,
+                               .update = ssi_mac_update,
+                               .final = ssi_mac_final,
+                               .finup = ssi_mac_finup,
+                               .digest = ssi_mac_digest,
+                               .setkey = ssi_xcbc_setkey,
 #ifdef EXPORT_FIXED
-                       .export = ssi_ahash_export,
-                       .import = ssi_ahash_import,
+                               .export = ssi_ahash_export,
+                               .import = ssi_ahash_import,
 #endif
-                       .halg = {
-                               .digestsize = AES_BLOCK_SIZE,
-                               .statesize = sizeof(struct aeshash_state),
+                               .halg = {
+                                       .digestsize = AES_BLOCK_SIZE,
+                                       .statesize = sizeof(struct aeshash_state),
+                                       },
                                },
-                       },
-                       .hash_mode = DRV_HASH_NULL,
-                       .hw_mode = DRV_CIPHER_XCBC_MAC,
-                       .inter_digestsize = AES_BLOCK_SIZE,
                },
+               .hash_mode = DRV_HASH_NULL,
+               .hw_mode = DRV_CIPHER_XCBC_MAC,
+               .inter_digestsize = AES_BLOCK_SIZE,
+       },
 #if SSI_CC_HAS_CMAC
        {
                .name = "cmac(aes)",
                .driver_name = "cmac-aes-dx",
                .blocksize = AES_BLOCK_SIZE,
                .synchronize = false,
-               .template_ahash = {
-                       .init = ssi_ahash_init,
-                       .update = ssi_mac_update,
-                       .final = ssi_mac_final,
-                       .finup = ssi_mac_finup,
-                       .digest = ssi_mac_digest,
-                       .setkey = ssi_cmac_setkey,
+               {
+                       .template_ahash = {
+                               .init = ssi_ahash_init,
+                               .update = ssi_mac_update,
+                               .final = ssi_mac_final,
+                               .finup = ssi_mac_finup,
+                               .digest = ssi_mac_digest,
+                               .setkey = ssi_cmac_setkey,
 #ifdef EXPORT_FIXED
-                       .export = ssi_ahash_export,
-                       .import = ssi_ahash_import,
+                               .export = ssi_ahash_export,
+                               .import = ssi_ahash_import,
 #endif
-                       .halg = {
-                               .digestsize = AES_BLOCK_SIZE,
-                               .statesize = sizeof(struct aeshash_state),
+                               .halg = {
+                                       .digestsize = AES_BLOCK_SIZE,
+                                       .statesize = sizeof(struct aeshash_state),
+                                       },
                                },
-                       },
-                       .hash_mode = DRV_HASH_NULL,
-                       .hw_mode = DRV_CIPHER_CMAC,
-                       .inter_digestsize = AES_BLOCK_SIZE,
                },
+               .hash_mode = DRV_HASH_NULL,
+               .hw_mode = DRV_CIPHER_CMAC,
+               .inter_digestsize = AES_BLOCK_SIZE,
+       },
 #endif
        
 };
index a6a76a681ea9af0e03709fcacbe50dbbc369e636..8f638267e7048dda61a023c6b126cda74ac25214 100644 (file)
@@ -45,15 +45,6 @@ EXPORT_SYMBOL(libcfs_kvzalloc);
 void *libcfs_kvzalloc_cpt(struct cfs_cpt_table *cptab, int cpt, size_t size,
                          gfp_t flags)
 {
-       void *ret;
-
-       ret = kzalloc_node(size, flags | __GFP_NOWARN,
-                          cfs_cpt_spread_node(cptab, cpt));
-       if (!ret) {
-               WARN_ON(!(flags & (__GFP_FS | __GFP_HIGH)));
-               ret = vmalloc_node(size, cfs_cpt_spread_node(cptab, cpt));
-       }
-
-       return ret;
+       return kvzalloc_node(size, flags, cfs_cpt_spread_node(cptab, cpt));
 }
 EXPORT_SYMBOL(libcfs_kvzalloc_cpt);
index 6f9d540a97ceb6f30fae35b39977c74bd71567b9..fff930fc3cff2f5002ebd41f5a2ce88df615083e 100644 (file)
@@ -1115,7 +1115,7 @@ int ldlm_init(void)
        ldlm_lock_slab = kmem_cache_create("ldlm_locks",
                                           sizeof(struct ldlm_lock), 0,
                                           SLAB_HWCACHE_ALIGN |
-                                          SLAB_DESTROY_BY_RCU, NULL);
+                                          SLAB_TYPESAFE_BY_RCU, NULL);
        if (!ldlm_lock_slab) {
                kmem_cache_destroy(ldlm_resource_slab);
                return -ENOMEM;
index 11b5a8d36415362f7d41c8fe00043f08baa6d5bc..ca5040c69217ea9ac50fea77cdfdf690dedfdbb3 100644 (file)
@@ -1454,17 +1454,17 @@ int ll_setattr_raw(struct dentry *dentry, struct iattr *attr, bool hsm_import)
 
        /* We mark all of the fields "set" so MDS/OST does not re-set them */
        if (attr->ia_valid & ATTR_CTIME) {
-               attr->ia_ctime = CURRENT_TIME;
+               attr->ia_ctime = current_time(inode);
                attr->ia_valid |= ATTR_CTIME_SET;
        }
        if (!(attr->ia_valid & ATTR_ATIME_SET) &&
            (attr->ia_valid & ATTR_ATIME)) {
-               attr->ia_atime = CURRENT_TIME;
+               attr->ia_atime = current_time(inode);
                attr->ia_valid |= ATTR_ATIME_SET;
        }
        if (!(attr->ia_valid & ATTR_MTIME_SET) &&
            (attr->ia_valid & ATTR_MTIME)) {
-               attr->ia_mtime = CURRENT_TIME;
+               attr->ia_mtime = current_time(inode);
                attr->ia_valid |= ATTR_MTIME_SET;
        }
 
index f991bee81b375a4b45ca808969fc4dd3eb5d260f..cbab80092442a18f37900dac6a2029dafbc5b744 100644 (file)
@@ -216,7 +216,7 @@ static int osc_io_submit(const struct lu_env *env,
                struct cl_object *obj = ios->cis_obj;
 
                cl_object_attr_lock(obj);
-               attr->cat_mtime = LTIME_S(CURRENT_TIME);
+               attr->cat_mtime = ktime_get_real_seconds();
                attr->cat_ctime = attr->cat_mtime;
                cl_object_attr_update(env, obj, attr, CAT_MTIME | CAT_CTIME);
                cl_object_attr_unlock(obj);
@@ -256,7 +256,7 @@ static void osc_page_touch_at(const struct lu_env *env,
               kms > loi->loi_kms ? "" : "not ", loi->loi_kms, kms,
               loi->loi_lvb.lvb_size);
 
-       attr->cat_ctime = LTIME_S(CURRENT_TIME);
+       attr->cat_ctime = ktime_get_real_seconds();
        attr->cat_mtime = attr->cat_ctime;
        valid = CAT_MTIME | CAT_CTIME;
        if (kms > loi->loi_kms) {
index 40ac3582fb7aba8ee9b58c8b8805626af20a1f4c..11162f595fc745846a11dd56d275e6b631ab249a 100644 (file)
 #include <linux/string.h>
 #include <linux/list.h>
 #include <linux/errno.h>
-#include <asm/cacheflush.h>
 #include <linux/io.h>
 #include <asm/current.h>
 #include <linux/sched/signal.h>
 #include <linux/file.h>
 
+#include <asm/set_memory.h>
+
 #include "atomisp_internal.h"
 #include "hmm/hmm_common.h"
 #include "hmm/hmm_pool.h"
index 639b8cdf7a5e79f2bd7bb223d01d07193306cbab..19e0e9ee37de2bbde025f21a71baea1fe75a4b54 100644 (file)
@@ -27,7 +27,7 @@
 #include <linux/types.h>
 #include <linux/mm.h>
 
-#include "asm/cacheflush.h"
+#include <asm/set_memory.h>
 
 #include "atomisp_internal.h"
 
index 4000c05652e1f7d24e947bc6dee82aafe96d837f..bf6586805f7fa4f75f289384f2e85ed5eabdd4fc 100644 (file)
@@ -27,7 +27,8 @@
 #include <linux/types.h>
 #include <linux/mm.h>
 
-#include "asm/cacheflush.h"
+#include <asm/set_memory.h>
+
 #include "atomisp_internal.h"
 #include "hmm/hmm_pool.h"
 
index 2009e3a11b860728326087fda36d400ff005e8dd..706bd43e8b1b7b863f88a7f2850bc03bbc8bca21 100644 (file)
 #include <linux/slab.h>                /* for kmalloc */
 #include <linux/list.h>
 #include <linux/io.h>
-#include <asm/cacheflush.h>
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/string.h>
 #include <linux/errno.h>
 #include <linux/sizes.h>
 
+#ifdef CONFIG_X86
+#include <asm/set_memory.h>
+#endif
+
 #include "atomisp_internal.h"
 #include "mmu/isp_mmu.h"
 
index 675b2a9e66c1725ba081c9753ff17dd4e234d53b..069269db394ce5104bc7ba263b7181bca9265a71 100644 (file)
@@ -82,7 +82,7 @@ struct most_inst_obj {
 
 static const struct {
        int most_ch_data_type;
-       char *name;
+       const char *name;
 } ch_data_type[] = {
        { MOST_CH_CONTROL, "control\n" },
        { MOST_CH_ASYNC, "async\n" },
index ad72f8e883fc4a5425c0b23f0f91e049b43295f2..a041441766aa4df2f1943d681140c30379ddd9b3 100644 (file)
@@ -310,7 +310,7 @@ static void accent_release(void)
        speakup_info.port_tts = 0;
 }
 
-module_param_named(port, port_forced, int, 0444);
+module_param_hw_named(port, port_forced, int, ioport, 0444);
 module_param_named(start, synth_acntpc.startup, short, 0444);
 
 MODULE_PARM_DESC(port, "Set the port for the synthesizer (override probing).");
index 5973acc0a00654806afdb6345069b69d426a389c..33180937222d1a930eba0d79a4a4197606aca548 100644 (file)
@@ -382,7 +382,7 @@ static void dtlk_release(void)
        speakup_info.port_tts = 0;
 }
 
-module_param_named(port, port_forced, int, 0444);
+module_param_hw_named(port, port_forced, int, ioport, 0444);
 module_param_named(start, synth_dtlk.startup, short, 0444);
 
 MODULE_PARM_DESC(port, "Set the port for the synthesizer (override probing).");
index ba7901178e0b5eaaed04dd546874614ca974da31..d3203f8fc3d04ca8666a65fb5e44e956b86f31aa 100644 (file)
@@ -312,7 +312,7 @@ static void keynote_release(void)
        synth_port = 0;
 }
 
-module_param_named(port, port_forced, int, 0444);
+module_param_hw_named(port, port_forced, int, ioport, 0444);
 module_param_named(start, synth_keypc.startup, short, 0444);
 
 MODULE_PARM_DESC(port, "Set the port for the synthesizer (override probing).");
index 20a2d835fdaa37e02ffd3e9ede670154bd7595fd..367535b4b77fc7c1ce24a54ca22cac87f8be6f49 100644 (file)
@@ -466,16 +466,16 @@ static void __exit pio2_exit(void)
 
 /* These are required for each board */
 MODULE_PARM_DESC(bus, "Enumeration of VMEbus to which the board is connected");
-module_param_array(bus, int, &bus_num, 0444);
+module_param_hw_array(bus, int, other, &bus_num, 0444);
 
 MODULE_PARM_DESC(base, "Base VME address for PIO2 Registers");
-module_param_array(base, long, &base_num, 0444);
+module_param_hw_array(base, long, other, &base_num, 0444);
 
 MODULE_PARM_DESC(vector, "VME IRQ Vector (Lower 4 bits masked)");
-module_param_array(vector, int, &vector_num, 0444);
+module_param_hw_array(vector, int, other, &vector_num, 0444);
 
 MODULE_PARM_DESC(level, "VME IRQ Level");
-module_param_array(level, int, &level_num, 0444);
+module_param_hw_array(level, int, other, &level_num, 0444);
 
 MODULE_PARM_DESC(variant, "Last 4 characters of PIO2 board variant");
 module_param_array(variant, charp, &variant_num, 0444);
index e3f9ed3690b7a86103472de987c03fd76becd59b..26a9bcd5ee6a40c391195ef13e205d8d936c8a54 100644 (file)
@@ -128,11 +128,9 @@ struct iscsi_tiqn *iscsit_add_tiqn(unsigned char *buf)
                return ERR_PTR(-EINVAL);
        }
 
-       tiqn = kzalloc(sizeof(struct iscsi_tiqn), GFP_KERNEL);
-       if (!tiqn) {
-               pr_err("Unable to allocate struct iscsi_tiqn\n");
+       tiqn = kzalloc(sizeof(*tiqn), GFP_KERNEL);
+       if (!tiqn)
                return ERR_PTR(-ENOMEM);
-       }
 
        sprintf(tiqn->tiqn, "%s", buf);
        INIT_LIST_HEAD(&tiqn->tiqn_list);
@@ -362,9 +360,8 @@ struct iscsi_np *iscsit_add_np(
                return np;
        }
 
-       np = kzalloc(sizeof(struct iscsi_np), GFP_KERNEL);
+       np = kzalloc(sizeof(*np), GFP_KERNEL);
        if (!np) {
-               pr_err("Unable to allocate memory for struct iscsi_np\n");
                mutex_unlock(&np_lock);
                return ERR_PTR(-ENOMEM);
        }
@@ -696,12 +693,10 @@ static int __init iscsi_target_init_module(void)
        int ret = 0, size;
 
        pr_debug("iSCSI-Target "ISCSIT_VERSION"\n");
-
-       iscsit_global = kzalloc(sizeof(struct iscsit_global), GFP_KERNEL);
-       if (!iscsit_global) {
-               pr_err("Unable to allocate memory for iscsit_global\n");
+       iscsit_global = kzalloc(sizeof(*iscsit_global), GFP_KERNEL);
+       if (!iscsit_global)
                return -1;
-       }
+
        spin_lock_init(&iscsit_global->ts_bitmap_lock);
        mutex_init(&auth_id_lock);
        spin_lock_init(&sess_idr_lock);
@@ -714,10 +709,8 @@ static int __init iscsi_target_init_module(void)
 
        size = BITS_TO_LONGS(ISCSIT_BITMAP_BITS) * sizeof(long);
        iscsit_global->ts_bitmap = vzalloc(size);
-       if (!iscsit_global->ts_bitmap) {
-               pr_err("Unable to allocate iscsit_global->ts_bitmap\n");
+       if (!iscsit_global->ts_bitmap)
                goto configfs_out;
-       }
 
        lio_qr_cache = kmem_cache_create("lio_qr_cache",
                        sizeof(struct iscsi_queue_req),
@@ -984,12 +977,9 @@ static int iscsit_allocate_iovecs(struct iscsi_cmd *cmd)
        u32 iov_count = max(1UL, DIV_ROUND_UP(cmd->se_cmd.data_length, PAGE_SIZE));
 
        iov_count += ISCSI_IOV_DATA_BUFFER;
-
-       cmd->iov_data = kzalloc(iov_count * sizeof(struct kvec), GFP_KERNEL);
-       if (!cmd->iov_data) {
-               pr_err("Unable to allocate cmd->iov_data\n");
+       cmd->iov_data = kcalloc(iov_count, sizeof(*cmd->iov_data), GFP_KERNEL);
+       if (!cmd->iov_data)
                return -ENOMEM;
-       }
 
        cmd->orig_iov_data_count = iov_count;
        return 0;
@@ -1850,8 +1840,6 @@ static int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
 
                ping_data = kzalloc(payload_length + 1, GFP_KERNEL);
                if (!ping_data) {
-                       pr_err("Unable to allocate memory for"
-                               " NOPOUT ping data.\n");
                        ret = -1;
                        goto out;
                }
@@ -1997,15 +1985,11 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
                hdr->refcmdsn = cpu_to_be32(ISCSI_RESERVED_TAG);
 
        cmd->data_direction = DMA_NONE;
-
-       cmd->tmr_req = kzalloc(sizeof(struct iscsi_tmr_req), GFP_KERNEL);
-       if (!cmd->tmr_req) {
-               pr_err("Unable to allocate memory for"
-                       " Task Management command!\n");
+       cmd->tmr_req = kzalloc(sizeof(*cmd->tmr_req), GFP_KERNEL);
+       if (!cmd->tmr_req)
                return iscsit_add_reject_cmd(cmd,
                                             ISCSI_REASON_BOOKMARK_NO_RESOURCES,
                                             buf);
-       }
 
        /*
         * TASK_REASSIGN for ERL=2 / connection stays inside of
@@ -2265,11 +2249,9 @@ iscsit_handle_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
                struct kvec iov[3];
 
                text_in = kzalloc(payload_length, GFP_KERNEL);
-               if (!text_in) {
-                       pr_err("Unable to allocate memory for"
-                               " incoming text parameters\n");
+               if (!text_in)
                        goto reject;
-               }
+
                cmd->text_in_ptr = text_in;
 
                memset(iov, 0, 3 * sizeof(struct kvec));
@@ -3353,11 +3335,9 @@ iscsit_build_sendtargets_response(struct iscsi_cmd *cmd,
                         SENDTARGETS_BUF_LIMIT);
 
        payload = kzalloc(buffer_len, GFP_KERNEL);
-       if (!payload) {
-               pr_err("Unable to allocate memory for sendtargets"
-                               " response.\n");
+       if (!payload)
                return -ENOMEM;
-       }
+
        /*
         * Locate pointer to iqn./eui. string for ICF_SENDTARGETS_SINGLE
         * explicit case..
@@ -4683,6 +4663,7 @@ int iscsit_release_sessions_for_tpg(struct iscsi_portal_group *tpg, int force)
                        continue;
                }
                atomic_set(&sess->session_reinstatement, 1);
+               atomic_set(&sess->session_fall_back_to_erl0, 1);
                spin_unlock(&sess->conn_lock);
 
                list_move_tail(&se_sess->sess_list, &free_list);
index 5798810197ecf6f5fcf6f5d219de0f45e607b20c..535a8e06a4010f63a2744c1e1d0152d965d6630b 100644 (file)
@@ -1506,6 +1506,7 @@ static void lio_tpg_close_session(struct se_session *se_sess)
                return;
        }
        atomic_set(&sess->session_reinstatement, 1);
+       atomic_set(&sess->session_fall_back_to_erl0, 1);
        spin_unlock(&sess->conn_lock);
 
        iscsit_stop_time2retain_timer(sess);
index ad8f3011bdc2f1ba901395fbd40abe8353cc753f..66238477137bc46d35cade3167451e19f2d401ce 100644 (file)
@@ -208,6 +208,7 @@ int iscsi_check_for_session_reinstatement(struct iscsi_conn *conn)
                            initiatorname_param->value) &&
                   (sess_p->sess_ops->SessionType == sessiontype))) {
                        atomic_set(&sess_p->session_reinstatement, 1);
+                       atomic_set(&sess_p->session_fall_back_to_erl0, 1);
                        spin_unlock(&sess_p->conn_lock);
                        iscsit_inc_session_usage_count(sess_p);
                        iscsit_stop_time2retain_timer(sess_p);
index 70657fd564406b3c137b02c3f61824f387f554aa..0326607e5ab82fc2208ad4e416f426d92ee89c4a 100644 (file)
@@ -533,6 +533,7 @@ DEF_CONFIGFS_ATTRIB_SHOW(emulate_3pc);
 DEF_CONFIGFS_ATTRIB_SHOW(pi_prot_type);
 DEF_CONFIGFS_ATTRIB_SHOW(hw_pi_prot_type);
 DEF_CONFIGFS_ATTRIB_SHOW(pi_prot_format);
+DEF_CONFIGFS_ATTRIB_SHOW(pi_prot_verify);
 DEF_CONFIGFS_ATTRIB_SHOW(enforce_pr_isids);
 DEF_CONFIGFS_ATTRIB_SHOW(is_nonrot);
 DEF_CONFIGFS_ATTRIB_SHOW(emulate_rest_reord);
@@ -823,6 +824,7 @@ static ssize_t pi_prot_type_store(struct config_item *item,
                ret = dev->transport->init_prot(dev);
                if (ret) {
                        da->pi_prot_type = old_prot;
+                       da->pi_prot_verify = (bool) da->pi_prot_type;
                        return ret;
                }
 
@@ -830,6 +832,7 @@ static ssize_t pi_prot_type_store(struct config_item *item,
                dev->transport->free_prot(dev);
        }
 
+       da->pi_prot_verify = (bool) da->pi_prot_type;
        pr_debug("dev[%p]: SE Device Protection Type: %d\n", dev, flag);
        return count;
 }
@@ -872,6 +875,35 @@ static ssize_t pi_prot_format_store(struct config_item *item,
        return count;
 }
 
+static ssize_t pi_prot_verify_store(struct config_item *item,
+               const char *page, size_t count)
+{
+       struct se_dev_attrib *da = to_attrib(item);
+       bool flag;
+       int ret;
+
+       ret = strtobool(page, &flag);
+       if (ret < 0)
+               return ret;
+
+       if (!flag) {
+               da->pi_prot_verify = flag;
+               return count;
+       }
+       if (da->hw_pi_prot_type) {
+               pr_warn("DIF protection enabled on underlying hardware,"
+                       " ignoring\n");
+               return count;
+       }
+       if (!da->pi_prot_type) {
+               pr_warn("DIF protection not supported by backend, ignoring\n");
+               return count;
+       }
+       da->pi_prot_verify = flag;
+
+       return count;
+}
+
 static ssize_t force_pr_aptpl_store(struct config_item *item,
                const char *page, size_t count)
 {
@@ -1067,6 +1099,7 @@ CONFIGFS_ATTR(, emulate_3pc);
 CONFIGFS_ATTR(, pi_prot_type);
 CONFIGFS_ATTR_RO(, hw_pi_prot_type);
 CONFIGFS_ATTR(, pi_prot_format);
+CONFIGFS_ATTR(, pi_prot_verify);
 CONFIGFS_ATTR(, enforce_pr_isids);
 CONFIGFS_ATTR(, is_nonrot);
 CONFIGFS_ATTR(, emulate_rest_reord);
@@ -1104,6 +1137,7 @@ struct configfs_attribute *sbc_attrib_attrs[] = {
        &attr_pi_prot_type,
        &attr_hw_pi_prot_type,
        &attr_pi_prot_format,
+       &attr_pi_prot_verify,
        &attr_enforce_pr_isids,
        &attr_is_nonrot,
        &attr_emulate_rest_reord,
@@ -1366,7 +1400,7 @@ static ssize_t target_pr_res_holder_show(struct config_item *item, char *page)
        struct se_device *dev = pr_to_dev(item);
        int ret;
 
-       if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
+       if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR)
                return sprintf(page, "Passthrough\n");
 
        spin_lock(&dev->dev_reservation_lock);
@@ -1506,7 +1540,7 @@ static ssize_t target_pr_res_type_show(struct config_item *item, char *page)
 {
        struct se_device *dev = pr_to_dev(item);
 
-       if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
+       if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR)
                return sprintf(page, "SPC_PASSTHROUGH\n");
        else if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
                return sprintf(page, "SPC2_RESERVATIONS\n");
@@ -1519,7 +1553,7 @@ static ssize_t target_pr_res_aptpl_active_show(struct config_item *item,
 {
        struct se_device *dev = pr_to_dev(item);
 
-       if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
+       if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR)
                return 0;
 
        return sprintf(page, "APTPL Bit Status: %s\n",
@@ -1531,7 +1565,7 @@ static ssize_t target_pr_res_aptpl_metadata_show(struct config_item *item,
 {
        struct se_device *dev = pr_to_dev(item);
 
-       if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
+       if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR)
                return 0;
 
        return sprintf(page, "Ready to process PR APTPL metadata..\n");
@@ -1577,7 +1611,7 @@ static ssize_t target_pr_res_aptpl_metadata_store(struct config_item *item,
        u16 tpgt = 0;
        u8 type = 0;
 
-       if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
+       if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR)
                return count;
        if (dev->dev_reservation_flags & DRF_SPC2_RESERVATIONS)
                return count;
@@ -2511,7 +2545,7 @@ static ssize_t target_tg_pt_gp_alua_support_##_name##_store(              \
        int ret;                                                        \
                                                                        \
        if (!t->tg_pt_gp_valid_id) {                                    \
-               pr_err("Unable to do set ##_name ALUA state on non"     \
+               pr_err("Unable to do set " #_name " ALUA state on non"  \
                       " valid tg_pt_gp ID: %hu\n",                     \
                       t->tg_pt_gp_valid_id);                           \
                return -EINVAL;                                         \
@@ -2643,13 +2677,13 @@ static ssize_t target_tg_pt_gp_tg_pt_gp_id_store(struct config_item *item,
 
        ret = kstrtoul(page, 0, &tg_pt_gp_id);
        if (ret < 0) {
-               pr_err("kstrtoul() returned %d for"
-                       " tg_pt_gp_id\n", ret);
+               pr_err("ALUA tg_pt_gp_id: invalid value '%s' for tg_pt_gp_id\n",
+                      page);
                return ret;
        }
        if (tg_pt_gp_id > 0x0000ffff) {
-               pr_err("ALUA tg_pt_gp_id: %lu exceeds maximum:"
-                       " 0x0000ffff\n", tg_pt_gp_id);
+               pr_err("ALUA tg_pt_gp_id: %lu exceeds maximum: 0x0000ffff\n",
+                      tg_pt_gp_id);
                return -EINVAL;
        }
 
index d2f089cfa9aedcd63f204aa898d775c16330d150..8add07f387f9dbf38a1effc84a2a846b95fbd8f3 100644 (file)
@@ -1045,6 +1045,8 @@ passthrough_parse_cdb(struct se_cmd *cmd,
        sense_reason_t (*exec_cmd)(struct se_cmd *cmd))
 {
        unsigned char *cdb = cmd->t_task_cdb;
+       struct se_device *dev = cmd->se_dev;
+       unsigned int size;
 
        /*
         * Clear a lun set in the cdb if the initiator talking to use spoke
@@ -1076,6 +1078,42 @@ passthrough_parse_cdb(struct se_cmd *cmd,
                return TCM_NO_SENSE;
        }
 
+       /*
+        * For PERSISTENT RESERVE IN/OUT, RELEASE, and RESERVE we need to
+        * emulate the response, since tcmu does not have the information
+        * required to process these commands.
+        */
+       if (!(dev->transport->transport_flags &
+             TRANSPORT_FLAG_PASSTHROUGH_PGR)) {
+               if (cdb[0] == PERSISTENT_RESERVE_IN) {
+                       cmd->execute_cmd = target_scsi3_emulate_pr_in;
+                       size = (cdb[7] << 8) + cdb[8];
+                       return target_cmd_size_check(cmd, size);
+               }
+               if (cdb[0] == PERSISTENT_RESERVE_OUT) {
+                       cmd->execute_cmd = target_scsi3_emulate_pr_out;
+                       size = (cdb[7] << 8) + cdb[8];
+                       return target_cmd_size_check(cmd, size);
+               }
+
+               if (cdb[0] == RELEASE || cdb[0] == RELEASE_10) {
+                       cmd->execute_cmd = target_scsi2_reservation_release;
+                       if (cdb[0] == RELEASE_10)
+                               size = (cdb[7] << 8) | cdb[8];
+                       else
+                               size = cmd->data_length;
+                       return target_cmd_size_check(cmd, size);
+               }
+               if (cdb[0] == RESERVE || cdb[0] == RESERVE_10) {
+                       cmd->execute_cmd = target_scsi2_reservation_reserve;
+                       if (cdb[0] == RESERVE_10)
+                               size = (cdb[7] << 8) | cdb[8];
+                       else
+                               size = cmd->data_length;
+                       return target_cmd_size_check(cmd, size);
+               }
+       }
+
        /* Set DATA_CDB flag for ops that should have it */
        switch (cdb[0]) {
        case READ_6:
index 87aa376a1a1ae9f9119369725199d7bd5ba22a1e..73b8f93a5fefbf18dfe06f763ffc07ceaca059a3 100644 (file)
@@ -277,12 +277,11 @@ static int fd_do_rw(struct se_cmd *cmd, struct file *fd,
        else
                ret = vfs_iter_read(fd, &iter, &pos);
 
-       kfree(bvec);
-
        if (is_write) {
                if (ret < 0 || ret != data_length) {
                        pr_err("%s() write returned %d\n", __func__, ret);
-                       return (ret < 0 ? ret : -EINVAL);
+                       if (ret >= 0)
+                               ret = -EINVAL;
                }
        } else {
                /*
@@ -295,17 +294,29 @@ static int fd_do_rw(struct se_cmd *cmd, struct file *fd,
                                pr_err("%s() returned %d, expecting %u for "
                                                "S_ISBLK\n", __func__, ret,
                                                data_length);
-                               return (ret < 0 ? ret : -EINVAL);
+                               if (ret >= 0)
+                                       ret = -EINVAL;
                        }
                } else {
                        if (ret < 0) {
                                pr_err("%s() returned %d for non S_ISBLK\n",
                                                __func__, ret);
-                               return ret;
+                       } else if (ret != data_length) {
+                               /*
+                                * Short read case:
+                                * Probably some one truncate file under us.
+                                * We must explicitly zero sg-pages to prevent
+                                * expose uninizialized pages to userspace.
+                                */
+                               if (ret < data_length)
+                                       ret += iov_iter_zero(data_length - ret, &iter);
+                               else
+                                       ret = -EINVAL;
                        }
                }
        }
-       return 1;
+       kfree(bvec);
+       return ret;
 }
 
 static sense_reason_t
@@ -543,7 +554,8 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
                ret = fd_do_rw(cmd, file, dev->dev_attrib.block_size,
                               sgl, sgl_nents, cmd->data_length, 0);
 
-               if (ret > 0 && cmd->prot_type && dev->dev_attrib.pi_prot_type) {
+               if (ret > 0 && cmd->prot_type && dev->dev_attrib.pi_prot_type &&
+                   dev->dev_attrib.pi_prot_verify) {
                        u32 sectors = cmd->data_length >>
                                        ilog2(dev->dev_attrib.block_size);
 
@@ -553,7 +565,8 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
                                return rc;
                }
        } else {
-               if (cmd->prot_type && dev->dev_attrib.pi_prot_type) {
+               if (cmd->prot_type && dev->dev_attrib.pi_prot_type &&
+                   dev->dev_attrib.pi_prot_verify) {
                        u32 sectors = cmd->data_length >>
                                        ilog2(dev->dev_attrib.block_size);
 
@@ -595,8 +608,7 @@ fd_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
        if (ret < 0)
                return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 
-       if (ret)
-               target_complete_cmd(cmd, SAM_STAT_GOOD);
+       target_complete_cmd(cmd, SAM_STAT_GOOD);
        return 0;
 }
 
index d316ed537d59132a3fde2dfd11eba3194d899bec..bb069ebe4aa6c1abcce203c7133a446493abc7eb 100644 (file)
@@ -279,7 +279,7 @@ static void iblock_complete_cmd(struct se_cmd *cmd)
        struct iblock_req *ibr = cmd->priv;
        u8 status;
 
-       if (!atomic_dec_and_test(&ibr->pending))
+       if (!refcount_dec_and_test(&ibr->pending))
                return;
 
        if (atomic_read(&ibr->ib_bio_err_cnt))
@@ -487,7 +487,7 @@ iblock_execute_write_same(struct se_cmd *cmd)
        bio_list_init(&list);
        bio_list_add(&list, bio);
 
-       atomic_set(&ibr->pending, 1);
+       refcount_set(&ibr->pending, 1);
 
        while (sectors) {
                while (bio_add_page(bio, sg_page(sg), sg->length, sg->offset)
@@ -498,7 +498,7 @@ iblock_execute_write_same(struct se_cmd *cmd)
                        if (!bio)
                                goto fail_put_bios;
 
-                       atomic_inc(&ibr->pending);
+                       refcount_inc(&ibr->pending);
                        bio_list_add(&list, bio);
                }
 
@@ -706,7 +706,7 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
        cmd->priv = ibr;
 
        if (!sgl_nents) {
-               atomic_set(&ibr->pending, 1);
+               refcount_set(&ibr->pending, 1);
                iblock_complete_cmd(cmd);
                return 0;
        }
@@ -719,7 +719,7 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
        bio_list_init(&list);
        bio_list_add(&list, bio);
 
-       atomic_set(&ibr->pending, 2);
+       refcount_set(&ibr->pending, 2);
        bio_cnt = 1;
 
        for_each_sg(sgl, sg, sgl_nents, i) {
@@ -740,7 +740,7 @@ iblock_execute_rw(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
                        if (!bio)
                                goto fail_put_bios;
 
-                       atomic_inc(&ibr->pending);
+                       refcount_inc(&ibr->pending);
                        bio_list_add(&list, bio);
                        bio_cnt++;
                }
index 718d3fcd3e7cd8d8cacd7057ff85119a836725ca..f2a5797217d43e233a5cb1229f7e5977e0a564b8 100644 (file)
@@ -2,6 +2,7 @@
 #define TARGET_CORE_IBLOCK_H
 
 #include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <target/target_core_base.h>
 
 #define IBLOCK_VERSION         "4.0"
@@ -10,7 +11,7 @@
 #define IBLOCK_LBA_SHIFT       9
 
 struct iblock_req {
-       atomic_t pending;
+       refcount_t pending;
        atomic_t ib_bio_err_cnt;
 } ____cacheline_aligned;
 
index e18051185846ad2824ed7aef82ea66ca2898d83c..129ca572673ceaed2aa6f4ca55d10bfcd6b1620a 100644 (file)
@@ -4147,7 +4147,7 @@ target_check_reservation(struct se_cmd *cmd)
                return 0;
        if (dev->se_hba->hba_flags & HBA_FLAGS_INTERNAL_USE)
                return 0;
-       if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH)
+       if (dev->transport->transport_flags & TRANSPORT_FLAG_PASSTHROUGH_PGR)
                return 0;
 
        spin_lock(&dev->dev_reservation_lock);
index 847bd470339c7ab1e1d498a6ddf37be37c526d57..772f9148e75ca36e8395e4e50525d7b07278b6f2 100644 (file)
@@ -7,7 +7,7 @@
 /*
  * PERSISTENT_RESERVE_OUT service action codes
  *
- * spc4r17 section 6.14.2 Table 171
+ * spc5r04b section 6.15.2 Table 174
  */
 #define PRO_REGISTER                           0x00
 #define PRO_RESERVE                            0x01
 #define PRO_PREEMPT_AND_ABORT                  0x05
 #define PRO_REGISTER_AND_IGNORE_EXISTING_KEY   0x06
 #define PRO_REGISTER_AND_MOVE                  0x07
+#define PRO_REPLACE_LOST_RESERVATION   0x08
 /*
  * PERSISTENT_RESERVE_IN service action codes
  *
- * spc4r17 section 6.13.1 Table 159
+ * spc5r04b section 6.14.1 Table 162
  */
 #define PRI_READ_KEYS                          0x00
 #define PRI_READ_RESERVATION                   0x01
 /*
  * PERSISTENT_RESERVE_ SCOPE field
  *
- * spc4r17 section 6.13.3.3 Table 163
+ * spc5r04b section 6.14.3.2 Table 166
  */
 #define PR_SCOPE_LU_SCOPE                      0x00
 /*
  * PERSISTENT_RESERVE_* TYPE field
  *
- * spc4r17 section 6.13.3.4 Table 164
+ * spc5r04b section 6.14.3.3 Table 167
  */
 #define PR_TYPE_WRITE_EXCLUSIVE                        0x01
 #define PR_TYPE_EXCLUSIVE_ACCESS               0x03
index a93d94e68ab5faf5eea22d88ea8d9fe1b26aa897..3e4abb13f8ea4b46ad78de13eae74fd17ccda67a 100644 (file)
@@ -1081,7 +1081,8 @@ static const struct target_backend_ops pscsi_ops = {
        .name                   = "pscsi",
        .owner                  = THIS_MODULE,
        .transport_flags        = TRANSPORT_FLAG_PASSTHROUGH |
-                                 TRANSPORT_FLAG_PASSTHROUGH_ALUA,
+                                 TRANSPORT_FLAG_PASSTHROUGH_ALUA |
+                                 TRANSPORT_FLAG_PASSTHROUGH_PGR,
        .attach_hba             = pscsi_attach_hba,
        .detach_hba             = pscsi_detach_hba,
        .pmode_enable_hba       = pscsi_pmode_enable_hba,
index ddc216c9f1f63dcdea780b5be5edbf34d9cc93d4..20253d04103f6442e4aa5932b67dd88a7251520c 100644 (file)
@@ -47,11 +47,9 @@ static int rd_attach_hba(struct se_hba *hba, u32 host_id)
 {
        struct rd_host *rd_host;
 
-       rd_host = kzalloc(sizeof(struct rd_host), GFP_KERNEL);
-       if (!rd_host) {
-               pr_err("Unable to allocate memory for struct rd_host\n");
+       rd_host = kzalloc(sizeof(*rd_host), GFP_KERNEL);
+       if (!rd_host)
                return -ENOMEM;
-       }
 
        rd_host->rd_host_id = host_id;
 
@@ -148,11 +146,8 @@ static int rd_allocate_sgl_table(struct rd_dev *rd_dev, struct rd_dev_sg_table *
 
                sg = kcalloc(sg_per_table + chain_entry, sizeof(*sg),
                                GFP_KERNEL);
-               if (!sg) {
-                       pr_err("Unable to allocate scatterlist array"
-                               " for struct rd_dev\n");
+               if (!sg)
                        return -ENOMEM;
-               }
 
                sg_init_table(sg, sg_per_table + chain_entry);
 
@@ -210,13 +205,9 @@ static int rd_build_device_space(struct rd_dev *rd_dev)
        total_sg_needed = rd_dev->rd_page_count;
 
        sg_tables = (total_sg_needed / max_sg_per_table) + 1;
-
-       sg_table = kzalloc(sg_tables * sizeof(struct rd_dev_sg_table), GFP_KERNEL);
-       if (!sg_table) {
-               pr_err("Unable to allocate memory for Ramdisk"
-                      " scatterlist tables\n");
+       sg_table = kcalloc(sg_tables, sizeof(*sg_table), GFP_KERNEL);
+       if (!sg_table)
                return -ENOMEM;
-       }
 
        rd_dev->sg_table_array = sg_table;
        rd_dev->sg_table_count = sg_tables;
@@ -271,13 +262,9 @@ static int rd_build_prot_space(struct rd_dev *rd_dev, int prot_length, int block
        total_sg_needed = (rd_dev->rd_page_count * prot_length / block_size) + 1;
 
        sg_tables = (total_sg_needed / max_sg_per_table) + 1;
-
-       sg_table = kzalloc(sg_tables * sizeof(struct rd_dev_sg_table), GFP_KERNEL);
-       if (!sg_table) {
-               pr_err("Unable to allocate memory for Ramdisk protection"
-                      " scatterlist tables\n");
+       sg_table = kcalloc(sg_tables, sizeof(*sg_table), GFP_KERNEL);
+       if (!sg_table)
                return -ENOMEM;
-       }
 
        rd_dev->sg_prot_array = sg_table;
        rd_dev->sg_prot_count = sg_tables;
@@ -298,11 +285,9 @@ static struct se_device *rd_alloc_device(struct se_hba *hba, const char *name)
        struct rd_dev *rd_dev;
        struct rd_host *rd_host = hba->hba_ptr;
 
-       rd_dev = kzalloc(sizeof(struct rd_dev), GFP_KERNEL);
-       if (!rd_dev) {
-               pr_err("Unable to allocate memory for struct rd_dev\n");
+       rd_dev = kzalloc(sizeof(*rd_dev), GFP_KERNEL);
+       if (!rd_dev)
                return NULL;
-       }
 
        rd_dev->rd_host = rd_host;
 
@@ -410,7 +395,7 @@ static sense_reason_t rd_do_prot_rw(struct se_cmd *cmd, bool is_read)
        u32 prot_offset, prot_page;
        u32 prot_npages __maybe_unused;
        u64 tmp;
-       sense_reason_t rc = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+       sense_reason_t rc = 0;
 
        tmp = cmd->t_task_lba * se_dev->prot_length;
        prot_offset = do_div(tmp, PAGE_SIZE);
@@ -423,13 +408,14 @@ static sense_reason_t rd_do_prot_rw(struct se_cmd *cmd, bool is_read)
        prot_sg = &prot_table->sg_table[prot_page -
                                        prot_table->page_start_offset];
 
-       if (is_read)
-               rc = sbc_dif_verify(cmd, cmd->t_task_lba, sectors, 0,
-                                   prot_sg, prot_offset);
-       else
-               rc = sbc_dif_verify(cmd, cmd->t_task_lba, sectors, 0,
-                                   cmd->t_prot_sg, 0);
-
+       if (se_dev->dev_attrib.pi_prot_verify) {
+               if (is_read)
+                       rc = sbc_dif_verify(cmd, cmd->t_task_lba, sectors, 0,
+                                           prot_sg, prot_offset);
+               else
+                       rc = sbc_dif_verify(cmd, cmd->t_task_lba, sectors, 0,
+                                           cmd->t_prot_sg, 0);
+       }
        if (!rc)
                sbc_dif_copy_prot(cmd, sectors, is_read, prot_sg, prot_offset);
 
index c194063f169b13ce44bf014894960693530e25d7..4316f7b65fb7691fa38e81ce7ed4d4d62b9520df 100644 (file)
@@ -507,8 +507,11 @@ static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool succes
         * been failed with a non-zero SCSI status.
         */
        if (cmd->scsi_status) {
-               pr_err("compare_and_write_callback: non zero scsi_status:"
+               pr_debug("compare_and_write_callback: non zero scsi_status:"
                        " 0x%02x\n", cmd->scsi_status);
+               *post_ret = 1;
+               if (cmd->scsi_status == SAM_STAT_CHECK_CONDITION)
+                       ret = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
                goto out;
        }
 
@@ -519,8 +522,8 @@ static sense_reason_t compare_and_write_callback(struct se_cmd *cmd, bool succes
                goto out;
        }
 
-       write_sg = kmalloc(sizeof(struct scatterlist) * cmd->t_data_nents,
-                          GFP_KERNEL);
+       write_sg = kmalloc_array(cmd->t_data_nents, sizeof(*write_sg),
+                                GFP_KERNEL);
        if (!write_sg) {
                pr_err("Unable to allocate compare_and_write sg\n");
                ret = TCM_OUT_OF_RESOURCES;
@@ -924,6 +927,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
                cmd->execute_cmd = sbc_execute_rw;
                break;
        case WRITE_16:
+       case WRITE_VERIFY_16:
                sectors = transport_get_sectors_16(cdb);
                cmd->t_task_lba = transport_lba_64(cdb);
 
index dfaef4d3b2d2698088754c08f1846bc893815237..310d9e55c6eb76994879ebf0d23b1c4bbee0e8db 100644 (file)
@@ -397,6 +397,13 @@ int core_tpg_set_initiator_node_queue_depth(
 {
        struct se_portal_group *tpg = acl->se_tpg;
 
+       /*
+        * Allow the setting of se_node_acl queue_depth to be idempotent,
+        * and not force a session shutdown event if the value is not
+        * changing.
+        */
+       if (acl->queue_depth == queue_depth)
+               return 0;
        /*
         * User has requested to change the queue depth for a Initiator Node.
         * Change the value in the Node's struct se_node_acl, and call
index a0cd56ee5fe984f7ddf27c41157f7314343d23c1..37f57357d4a0827f5669cb89d1619c4651192547 100644 (file)
@@ -2311,7 +2311,7 @@ void *transport_kmap_data_sg(struct se_cmd *cmd)
                return kmap(sg_page(sg)) + sg->offset;
 
        /* >1 page. use vmap */
-       pages = kmalloc(sizeof(*pages) * cmd->t_data_nents, GFP_KERNEL);
+       pages = kmalloc_array(cmd->t_data_nents, sizeof(*pages), GFP_KERNEL);
        if (!pages)
                return NULL;
 
index f615c3bbb73e8b7a2a7bf3f5039efd84c724cdf2..9045837f748bd3b602256cfa9e83058ae92b8b33 100644 (file)
@@ -2,6 +2,7 @@
  * Copyright (C) 2013 Shaohua Li <shli@kernel.org>
  * Copyright (C) 2014 Red Hat, Inc.
  * Copyright (C) 2015 Arrikto, Inc.
+ * Copyright (C) 2017 Chinamobile, Inc.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
 #include <linux/parser.h>
 #include <linux/vmalloc.h>
 #include <linux/uio_driver.h>
+#include <linux/radix-tree.h>
 #include <linux/stringify.h>
 #include <linux/bitops.h>
 #include <linux/highmem.h>
 #include <linux/configfs.h>
+#include <linux/mutex.h>
+#include <linux/kthread.h>
 #include <net/genetlink.h>
 #include <scsi/scsi_common.h>
 #include <scsi/scsi_proto.h>
  * this may have a 'UAM' comment.
  */
 
-
 #define TCMU_TIME_OUT (30 * MSEC_PER_SEC)
 
-#define DATA_BLOCK_BITS 256
-#define DATA_BLOCK_SIZE 4096
+/* For cmd area, the size is fixed 8MB */
+#define CMDR_SIZE (8 * 1024 * 1024)
 
-#define CMDR_SIZE (16 * 4096)
+/*
+ * For data area, the block size is PAGE_SIZE and
+ * the total size is 256K * PAGE_SIZE.
+ */
+#define DATA_BLOCK_SIZE PAGE_SIZE
+#define DATA_BLOCK_BITS (256 * 1024)
 #define DATA_SIZE (DATA_BLOCK_BITS * DATA_BLOCK_SIZE)
+#define DATA_BLOCK_INIT_BITS 128
 
+/* The total size of the ring is 8M + 256K * PAGE_SIZE */
 #define TCMU_RING_SIZE (CMDR_SIZE + DATA_SIZE)
 
+/* Default maximum of the global data blocks(512K * PAGE_SIZE) */
+#define TCMU_GLOBAL_MAX_BLOCKS (512 * 1024)
+
 static struct device *tcmu_root_device;
 
 struct tcmu_hba {
@@ -83,6 +96,8 @@ struct tcmu_hba {
 #define TCMU_CONFIG_LEN 256
 
 struct tcmu_dev {
+       struct list_head node;
+
        struct se_device se_dev;
 
        char *name;
@@ -94,6 +109,8 @@ struct tcmu_dev {
 
        struct uio_info uio_info;
 
+       struct inode *inode;
+
        struct tcmu_mailbox *mb_addr;
        size_t dev_size;
        u32 cmdr_size;
@@ -103,11 +120,14 @@ struct tcmu_dev {
        size_t data_off;
        size_t data_size;
 
-       DECLARE_BITMAP(data_bitmap, DATA_BLOCK_BITS);
-
        wait_queue_head_t wait_cmdr;
-       /* TODO should this be a mutex? */
-       spinlock_t cmdr_lock;
+       struct mutex cmdr_lock;
+
+       bool waiting_global;
+       uint32_t dbi_max;
+       uint32_t dbi_thresh;
+       DECLARE_BITMAP(data_bitmap, DATA_BLOCK_BITS);
+       struct radix_tree_root data_blocks;
 
        struct idr commands;
        spinlock_t commands_lock;
@@ -130,7 +150,9 @@ struct tcmu_cmd {
 
        /* Can't use se_cmd when cleaning up expired cmds, because if
           cmd has been completed then accessing se_cmd is off limits */
-       DECLARE_BITMAP(data_bitmap, DATA_BLOCK_BITS);
+       uint32_t dbi_cnt;
+       uint32_t dbi_cur;
+       uint32_t *dbi;
 
        unsigned long deadline;
 
@@ -138,6 +160,13 @@ struct tcmu_cmd {
        unsigned long flags;
 };
 
+static struct task_struct *unmap_thread;
+static wait_queue_head_t unmap_wait;
+static DEFINE_MUTEX(root_udev_mutex);
+static LIST_HEAD(root_udev);
+
+static atomic_t global_db_count = ATOMIC_INIT(0);
+
 static struct kmem_cache *tcmu_cmd_cache;
 
 /* multicast group */
@@ -161,6 +190,114 @@ static struct genl_family tcmu_genl_family __ro_after_init = {
        .netnsok = true,
 };
 
+#define tcmu_cmd_set_dbi_cur(cmd, index) ((cmd)->dbi_cur = (index))
+#define tcmu_cmd_reset_dbi_cur(cmd) tcmu_cmd_set_dbi_cur(cmd, 0)
+#define tcmu_cmd_set_dbi(cmd, index) ((cmd)->dbi[(cmd)->dbi_cur++] = (index))
+#define tcmu_cmd_get_dbi(cmd) ((cmd)->dbi[(cmd)->dbi_cur++])
+
+static void tcmu_cmd_free_data(struct tcmu_cmd *tcmu_cmd, uint32_t len)
+{
+       struct tcmu_dev *udev = tcmu_cmd->tcmu_dev;
+       uint32_t i;
+
+       for (i = 0; i < len; i++)
+               clear_bit(tcmu_cmd->dbi[i], udev->data_bitmap);
+}
+
+static inline bool tcmu_get_empty_block(struct tcmu_dev *udev,
+                                       struct tcmu_cmd *tcmu_cmd)
+{
+       struct page *page;
+       int ret, dbi;
+
+       dbi = find_first_zero_bit(udev->data_bitmap, udev->dbi_thresh);
+       if (dbi == udev->dbi_thresh)
+               return false;
+
+       page = radix_tree_lookup(&udev->data_blocks, dbi);
+       if (!page) {
+
+               if (atomic_add_return(1, &global_db_count) >
+                                       TCMU_GLOBAL_MAX_BLOCKS) {
+                       atomic_dec(&global_db_count);
+                       return false;
+               }
+
+               /* try to get new page from the mm */
+               page = alloc_page(GFP_KERNEL);
+               if (!page)
+                       return false;
+
+               ret = radix_tree_insert(&udev->data_blocks, dbi, page);
+               if (ret) {
+                       __free_page(page);
+                       return false;
+               }
+
+       }
+
+       if (dbi > udev->dbi_max)
+               udev->dbi_max = dbi;
+
+       set_bit(dbi, udev->data_bitmap);
+       tcmu_cmd_set_dbi(tcmu_cmd, dbi);
+
+       return true;
+}
+
+static bool tcmu_get_empty_blocks(struct tcmu_dev *udev,
+                                 struct tcmu_cmd *tcmu_cmd)
+{
+       int i;
+
+       udev->waiting_global = false;
+
+       for (i = tcmu_cmd->dbi_cur; i < tcmu_cmd->dbi_cnt; i++) {
+               if (!tcmu_get_empty_block(udev, tcmu_cmd))
+                       goto err;
+       }
+       return true;
+
+err:
+       udev->waiting_global = true;
+       /* Try to wake up the unmap thread */
+       wake_up(&unmap_wait);
+       return false;
+}
+
+static inline struct page *
+tcmu_get_block_page(struct tcmu_dev *udev, uint32_t dbi)
+{
+       return radix_tree_lookup(&udev->data_blocks, dbi);
+}
+
+static inline void tcmu_free_cmd(struct tcmu_cmd *tcmu_cmd)
+{
+       kfree(tcmu_cmd->dbi);
+       kmem_cache_free(tcmu_cmd_cache, tcmu_cmd);
+}
+
+static inline size_t tcmu_cmd_get_data_length(struct tcmu_cmd *tcmu_cmd)
+{
+       struct se_cmd *se_cmd = tcmu_cmd->se_cmd;
+       size_t data_length = round_up(se_cmd->data_length, DATA_BLOCK_SIZE);
+
+       if (se_cmd->se_cmd_flags & SCF_BIDI) {
+               BUG_ON(!(se_cmd->t_bidi_data_sg && se_cmd->t_bidi_data_nents));
+               data_length += round_up(se_cmd->t_bidi_data_sg->length,
+                               DATA_BLOCK_SIZE);
+       }
+
+       return data_length;
+}
+
+static inline uint32_t tcmu_cmd_get_block_cnt(struct tcmu_cmd *tcmu_cmd)
+{
+       size_t data_length = tcmu_cmd_get_data_length(tcmu_cmd);
+
+       return data_length / DATA_BLOCK_SIZE;
+}
+
 static struct tcmu_cmd *tcmu_alloc_cmd(struct se_cmd *se_cmd)
 {
        struct se_device *se_dev = se_cmd->se_dev;
@@ -178,6 +315,15 @@ static struct tcmu_cmd *tcmu_alloc_cmd(struct se_cmd *se_cmd)
                tcmu_cmd->deadline = jiffies +
                                        msecs_to_jiffies(udev->cmd_time_out);
 
+       tcmu_cmd_reset_dbi_cur(tcmu_cmd);
+       tcmu_cmd->dbi_cnt = tcmu_cmd_get_block_cnt(tcmu_cmd);
+       tcmu_cmd->dbi = kcalloc(tcmu_cmd->dbi_cnt, sizeof(uint32_t),
+                               GFP_KERNEL);
+       if (!tcmu_cmd->dbi) {
+               kmem_cache_free(tcmu_cmd_cache, tcmu_cmd);
+               return NULL;
+       }
+
        idr_preload(GFP_KERNEL);
        spin_lock_irq(&udev->commands_lock);
        cmd_id = idr_alloc(&udev->commands, tcmu_cmd, 0,
@@ -186,7 +332,7 @@ static struct tcmu_cmd *tcmu_alloc_cmd(struct se_cmd *se_cmd)
        idr_preload_end();
 
        if (cmd_id < 0) {
-               kmem_cache_free(tcmu_cmd_cache, tcmu_cmd);
+               tcmu_free_cmd(tcmu_cmd);
                return NULL;
        }
        tcmu_cmd->cmd_id = cmd_id;
@@ -248,10 +394,10 @@ static inline void new_iov(struct iovec **iov, int *iov_cnt,
 #define UPDATE_HEAD(head, used, size) smp_store_release(&head, ((head % size) + used) % size)
 
 /* offset is relative to mb_addr */
-static inline size_t get_block_offset(struct tcmu_dev *dev,
-               int block, int remaining)
+static inline size_t get_block_offset_user(struct tcmu_dev *dev,
+               int dbi, int remaining)
 {
-       return dev->data_off + block * DATA_BLOCK_SIZE +
+       return dev->data_off + dbi * DATA_BLOCK_SIZE +
                DATA_BLOCK_SIZE - remaining;
 }
 
@@ -260,37 +406,45 @@ static inline size_t iov_tail(struct tcmu_dev *udev, struct iovec *iov)
        return (size_t)iov->iov_base + iov->iov_len;
 }
 
-static void alloc_and_scatter_data_area(struct tcmu_dev *udev,
-       struct scatterlist *data_sg, unsigned int data_nents,
-       struct iovec **iov, int *iov_cnt, bool copy_data)
+static int scatter_data_area(struct tcmu_dev *udev,
+       struct tcmu_cmd *tcmu_cmd, struct scatterlist *data_sg,
+       unsigned int data_nents, struct iovec **iov,
+       int *iov_cnt, bool copy_data)
 {
-       int i, block;
+       int i, dbi;
        int block_remaining = 0;
-       void *from, *to;
-       size_t copy_bytes, to_offset;
+       void *from, *to = NULL;
+       size_t copy_bytes, to_offset, offset;
        struct scatterlist *sg;
+       struct page *page;
 
        for_each_sg(data_sg, sg, data_nents, i) {
                int sg_remaining = sg->length;
                from = kmap_atomic(sg_page(sg)) + sg->offset;
                while (sg_remaining > 0) {
                        if (block_remaining == 0) {
-                               block = find_first_zero_bit(udev->data_bitmap,
-                                               DATA_BLOCK_BITS);
+                               if (to)
+                                       kunmap_atomic(to);
+
                                block_remaining = DATA_BLOCK_SIZE;
-                               set_bit(block, udev->data_bitmap);
+                               dbi = tcmu_cmd_get_dbi(tcmu_cmd);
+                               page = tcmu_get_block_page(udev, dbi);
+                               to = kmap_atomic(page);
                        }
+
                        copy_bytes = min_t(size_t, sg_remaining,
                                        block_remaining);
-                       to_offset = get_block_offset(udev, block,
+                       to_offset = get_block_offset_user(udev, dbi,
                                        block_remaining);
-                       to = (void *)udev->mb_addr + to_offset;
+                       offset = DATA_BLOCK_SIZE - block_remaining;
+                       to = (void *)(unsigned long)to + offset;
+
                        if (*iov_cnt != 0 &&
                            to_offset == iov_tail(udev, *iov)) {
                                (*iov)->iov_len += copy_bytes;
                        } else {
                                new_iov(iov, iov_cnt, udev);
-                               (*iov)->iov_base = (void __user *) to_offset;
+                               (*iov)->iov_base = (void __user *)to_offset;
                                (*iov)->iov_len = copy_bytes;
                        }
                        if (copy_data) {
@@ -303,33 +457,29 @@ static void alloc_and_scatter_data_area(struct tcmu_dev *udev,
                }
                kunmap_atomic(from - sg->offset);
        }
-}
+       if (to)
+               kunmap_atomic(to);
 
-static void free_data_area(struct tcmu_dev *udev, struct tcmu_cmd *cmd)
-{
-       bitmap_xor(udev->data_bitmap, udev->data_bitmap, cmd->data_bitmap,
-                  DATA_BLOCK_BITS);
+       return 0;
 }
 
 static void gather_data_area(struct tcmu_dev *udev, struct tcmu_cmd *cmd,
                             bool bidi)
 {
        struct se_cmd *se_cmd = cmd->se_cmd;
-       int i, block;
+       int i, dbi;
        int block_remaining = 0;
-       void *from, *to;
-       size_t copy_bytes, from_offset;
+       void *from = NULL, *to;
+       size_t copy_bytes, offset;
        struct scatterlist *sg, *data_sg;
+       struct page *page;
        unsigned int data_nents;
-       DECLARE_BITMAP(bitmap, DATA_BLOCK_BITS);
-
-       bitmap_copy(bitmap, cmd->data_bitmap, DATA_BLOCK_BITS);
+       uint32_t count = 0;
 
        if (!bidi) {
                data_sg = se_cmd->t_data_sg;
                data_nents = se_cmd->t_data_nents;
        } else {
-               uint32_t count;
 
                /*
                 * For bidi case, the first count blocks are for Data-Out
@@ -337,30 +487,30 @@ static void gather_data_area(struct tcmu_dev *udev, struct tcmu_cmd *cmd,
                 * the Data-Out buffer blocks should be discarded.
                 */
                count = DIV_ROUND_UP(se_cmd->data_length, DATA_BLOCK_SIZE);
-               while (count--) {
-                       block = find_first_bit(bitmap, DATA_BLOCK_BITS);
-                       clear_bit(block, bitmap);
-               }
 
                data_sg = se_cmd->t_bidi_data_sg;
                data_nents = se_cmd->t_bidi_data_nents;
        }
 
+       tcmu_cmd_set_dbi_cur(cmd, count);
+
        for_each_sg(data_sg, sg, data_nents, i) {
                int sg_remaining = sg->length;
                to = kmap_atomic(sg_page(sg)) + sg->offset;
                while (sg_remaining > 0) {
                        if (block_remaining == 0) {
-                               block = find_first_bit(bitmap,
-                                               DATA_BLOCK_BITS);
+                               if (from)
+                                       kunmap_atomic(from);
+
                                block_remaining = DATA_BLOCK_SIZE;
-                               clear_bit(block, bitmap);
+                               dbi = tcmu_cmd_get_dbi(cmd);
+                               page = tcmu_get_block_page(udev, dbi);
+                               from = kmap_atomic(page);
                        }
                        copy_bytes = min_t(size_t, sg_remaining,
                                        block_remaining);
-                       from_offset = get_block_offset(udev, block,
-                                       block_remaining);
-                       from = (void *) udev->mb_addr + from_offset;
+                       offset = DATA_BLOCK_SIZE - block_remaining;
+                       from = (void *)(unsigned long)from + offset;
                        tcmu_flush_dcache_range(from, copy_bytes);
                        memcpy(to + sg->length - sg_remaining, from,
                                        copy_bytes);
@@ -370,12 +520,13 @@ static void gather_data_area(struct tcmu_dev *udev, struct tcmu_cmd *cmd,
                }
                kunmap_atomic(to - sg->offset);
        }
+       if (from)
+               kunmap_atomic(from);
 }
 
-static inline size_t spc_bitmap_free(unsigned long *bitmap)
+static inline size_t spc_bitmap_free(unsigned long *bitmap, uint32_t thresh)
 {
-       return DATA_BLOCK_SIZE * (DATA_BLOCK_BITS -
-                       bitmap_weight(bitmap, DATA_BLOCK_BITS));
+       return DATA_BLOCK_SIZE * (thresh - bitmap_weight(bitmap, thresh));
 }
 
 /*
@@ -384,9 +535,12 @@ static inline size_t spc_bitmap_free(unsigned long *bitmap)
  *
  * Called with ring lock held.
  */
-static bool is_ring_space_avail(struct tcmu_dev *udev, size_t cmd_size, size_t data_needed)
+static bool is_ring_space_avail(struct tcmu_dev *udev, struct tcmu_cmd *cmd,
+               size_t cmd_size, size_t data_needed)
 {
        struct tcmu_mailbox *mb = udev->mb_addr;
+       uint32_t blocks_needed = (data_needed + DATA_BLOCK_SIZE - 1)
+                               / DATA_BLOCK_SIZE;
        size_t space, cmd_needed;
        u32 cmd_head;
 
@@ -410,35 +564,63 @@ static bool is_ring_space_avail(struct tcmu_dev *udev, size_t cmd_size, size_t d
                return false;
        }
 
-       space = spc_bitmap_free(udev->data_bitmap);
+       /* try to check and get the data blocks as needed */
+       space = spc_bitmap_free(udev->data_bitmap, udev->dbi_thresh);
        if (space < data_needed) {
-               pr_debug("no data space: only %zu available, but ask for %zu\n",
-                               space, data_needed);
-               return false;
+               unsigned long blocks_left = DATA_BLOCK_BITS - udev->dbi_thresh;
+               unsigned long grow;
+
+               if (blocks_left < blocks_needed) {
+                       pr_debug("no data space: only %lu available, but ask for %zu\n",
+                                       blocks_left * DATA_BLOCK_SIZE,
+                                       data_needed);
+                       return false;
+               }
+
+               /* Try to expand the thresh */
+               if (!udev->dbi_thresh) {
+                       /* From idle state */
+                       uint32_t init_thresh = DATA_BLOCK_INIT_BITS;
+
+                       udev->dbi_thresh = max(blocks_needed, init_thresh);
+               } else {
+                       /*
+                        * Grow the data area by max(blocks needed,
+                        * dbi_thresh / 2), but limited to the max
+                        * DATA_BLOCK_BITS size.
+                        */
+                       grow = max(blocks_needed, udev->dbi_thresh / 2);
+                       udev->dbi_thresh += grow;
+                       if (udev->dbi_thresh > DATA_BLOCK_BITS)
+                               udev->dbi_thresh = DATA_BLOCK_BITS;
+               }
        }
 
+       if (!tcmu_get_empty_blocks(udev, cmd))
+               return false;
+
        return true;
 }
 
-static inline size_t tcmu_cmd_get_data_length(struct tcmu_cmd *tcmu_cmd)
+static inline size_t tcmu_cmd_get_base_cmd_size(size_t iov_cnt)
 {
-       struct se_cmd *se_cmd = tcmu_cmd->se_cmd;
-       size_t data_length = round_up(se_cmd->data_length, DATA_BLOCK_SIZE);
-
-       if (se_cmd->se_cmd_flags & SCF_BIDI) {
-               BUG_ON(!(se_cmd->t_bidi_data_sg && se_cmd->t_bidi_data_nents));
-               data_length += round_up(se_cmd->t_bidi_data_sg->length,
-                               DATA_BLOCK_SIZE);
-       }
-
-       return data_length;
+       return max(offsetof(struct tcmu_cmd_entry, req.iov[iov_cnt]),
+                       sizeof(struct tcmu_cmd_entry));
 }
 
-static inline uint32_t tcmu_cmd_get_block_cnt(struct tcmu_cmd *tcmu_cmd)
+static inline size_t tcmu_cmd_get_cmd_size(struct tcmu_cmd *tcmu_cmd,
+                                          size_t base_command_size)
 {
-       size_t data_length = tcmu_cmd_get_data_length(tcmu_cmd);
+       struct se_cmd *se_cmd = tcmu_cmd->se_cmd;
+       size_t command_size;
 
-       return data_length / DATA_BLOCK_SIZE;
+       command_size = base_command_size +
+               round_up(scsi_command_size(se_cmd->t_task_cdb),
+                               TCMU_OP_ALIGN_SIZE);
+
+       WARN_ON(command_size & (TCMU_OP_ALIGN_SIZE-1));
+
+       return command_size;
 }
 
 static sense_reason_t
@@ -450,12 +632,11 @@ tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
        struct tcmu_mailbox *mb;
        struct tcmu_cmd_entry *entry;
        struct iovec *iov;
-       int iov_cnt;
+       int iov_cnt, ret;
        uint32_t cmd_head;
        uint64_t cdb_off;
        bool copy_to_data_area;
        size_t data_length = tcmu_cmd_get_data_length(tcmu_cmd);
-       DECLARE_BITMAP(old_bitmap, DATA_BLOCK_BITS);
 
        if (test_bit(TCMU_DEV_BIT_BROKEN, &udev->flags))
                return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
@@ -464,18 +645,18 @@ tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
         * Must be a certain minimum size for response sense info, but
         * also may be larger if the iov array is large.
         *
-        * We prepare way too many iovs for potential uses here, because it's
-        * expensive to tell how many regions are freed in the bitmap
-       */
-       base_command_size = max(offsetof(struct tcmu_cmd_entry,
-                               req.iov[tcmu_cmd_get_block_cnt(tcmu_cmd)]),
-                               sizeof(struct tcmu_cmd_entry));
-       command_size = base_command_size
-               + round_up(scsi_command_size(se_cmd->t_task_cdb), TCMU_OP_ALIGN_SIZE);
-
-       WARN_ON(command_size & (TCMU_OP_ALIGN_SIZE-1));
+        * We prepare as many iovs as possbile for potential uses here,
+        * because it's expensive to tell how many regions are freed in
+        * the bitmap & global data pool, as the size calculated here
+        * will only be used to do the checks.
+        *
+        * The size will be recalculated later as actually needed to save
+        * cmd area memories.
+        */
+       base_command_size = tcmu_cmd_get_base_cmd_size(tcmu_cmd->dbi_cnt);
+       command_size = tcmu_cmd_get_cmd_size(tcmu_cmd, base_command_size);
 
-       spin_lock_irq(&udev->cmdr_lock);
+       mutex_lock(&udev->cmdr_lock);
 
        mb = udev->mb_addr;
        cmd_head = mb->cmd_head % udev->cmdr_size; /* UAM */
@@ -484,18 +665,18 @@ tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
                pr_warn("TCMU: Request of size %zu/%zu is too big for %u/%zu "
                        "cmd ring/data area\n", command_size, data_length,
                        udev->cmdr_size, udev->data_size);
-               spin_unlock_irq(&udev->cmdr_lock);
+               mutex_unlock(&udev->cmdr_lock);
                return TCM_INVALID_CDB_FIELD;
        }
 
-       while (!is_ring_space_avail(udev, command_size, data_length)) {
+       while (!is_ring_space_avail(udev, tcmu_cmd, command_size, data_length)) {
                int ret;
                DEFINE_WAIT(__wait);
 
                prepare_to_wait(&udev->wait_cmdr, &__wait, TASK_INTERRUPTIBLE);
 
                pr_debug("sleeping for ring space\n");
-               spin_unlock_irq(&udev->cmdr_lock);
+               mutex_unlock(&udev->cmdr_lock);
                if (udev->cmd_time_out)
                        ret = schedule_timeout(
                                        msecs_to_jiffies(udev->cmd_time_out));
@@ -507,7 +688,7 @@ tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
                        return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
                }
 
-               spin_lock_irq(&udev->cmdr_lock);
+               mutex_lock(&udev->cmdr_lock);
 
                /* We dropped cmdr_lock, cmd_head is stale */
                cmd_head = mb->cmd_head % udev->cmdr_size; /* UAM */
@@ -534,20 +715,26 @@ tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
        entry = (void *) mb + CMDR_OFF + cmd_head;
        tcmu_flush_dcache_range(entry, sizeof(*entry));
        tcmu_hdr_set_op(&entry->hdr.len_op, TCMU_OP_CMD);
-       tcmu_hdr_set_len(&entry->hdr.len_op, command_size);
        entry->hdr.cmd_id = tcmu_cmd->cmd_id;
        entry->hdr.kflags = 0;
        entry->hdr.uflags = 0;
 
-       bitmap_copy(old_bitmap, udev->data_bitmap, DATA_BLOCK_BITS);
-
        /* Handle allocating space from the data area */
+       tcmu_cmd_reset_dbi_cur(tcmu_cmd);
        iov = &entry->req.iov[0];
        iov_cnt = 0;
        copy_to_data_area = (se_cmd->data_direction == DMA_TO_DEVICE
                || se_cmd->se_cmd_flags & SCF_BIDI);
-       alloc_and_scatter_data_area(udev, se_cmd->t_data_sg,
-               se_cmd->t_data_nents, &iov, &iov_cnt, copy_to_data_area);
+       ret = scatter_data_area(udev, tcmu_cmd, se_cmd->t_data_sg,
+                               se_cmd->t_data_nents, &iov, &iov_cnt,
+                               copy_to_data_area);
+       if (ret) {
+               tcmu_cmd_free_data(tcmu_cmd, tcmu_cmd->dbi_cnt);
+               mutex_unlock(&udev->cmdr_lock);
+
+               pr_err("tcmu: alloc and scatter data failed\n");
+               return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+       }
        entry->req.iov_cnt = iov_cnt;
        entry->req.iov_dif_cnt = 0;
 
@@ -555,14 +742,29 @@ tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
        if (se_cmd->se_cmd_flags & SCF_BIDI) {
                iov_cnt = 0;
                iov++;
-               alloc_and_scatter_data_area(udev, se_cmd->t_bidi_data_sg,
-                               se_cmd->t_bidi_data_nents, &iov, &iov_cnt,
-                               false);
+               ret = scatter_data_area(udev, tcmu_cmd,
+                                       se_cmd->t_bidi_data_sg,
+                                       se_cmd->t_bidi_data_nents,
+                                       &iov, &iov_cnt, false);
+               if (ret) {
+                       tcmu_cmd_free_data(tcmu_cmd, tcmu_cmd->dbi_cnt);
+                       mutex_unlock(&udev->cmdr_lock);
+
+                       pr_err("tcmu: alloc and scatter bidi data failed\n");
+                       return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+               }
                entry->req.iov_bidi_cnt = iov_cnt;
        }
-       /* cmd's data_bitmap is what changed in process */
-       bitmap_xor(tcmu_cmd->data_bitmap, old_bitmap, udev->data_bitmap,
-                       DATA_BLOCK_BITS);
+
+       /*
+        * Recalaulate the command's base size and size according
+        * to the actual needs
+        */
+       base_command_size = tcmu_cmd_get_base_cmd_size(entry->req.iov_cnt +
+                                                      entry->req.iov_bidi_cnt);
+       command_size = tcmu_cmd_get_cmd_size(tcmu_cmd, base_command_size);
+
+       tcmu_hdr_set_len(&entry->hdr.len_op, command_size);
 
        /* All offsets relative to mb_addr, not start of entry! */
        cdb_off = CMDR_OFF + cmd_head + base_command_size;
@@ -572,8 +774,7 @@ tcmu_queue_cmd_ring(struct tcmu_cmd *tcmu_cmd)
 
        UPDATE_HEAD(mb->cmd_head, command_size, udev->cmdr_size);
        tcmu_flush_dcache_range(mb, sizeof(*mb));
-
-       spin_unlock_irq(&udev->cmdr_lock);
+       mutex_unlock(&udev->cmdr_lock);
 
        /* TODO: only if FLUSH and FUA? */
        uio_event_notify(&udev->uio_info);
@@ -604,7 +805,7 @@ tcmu_queue_cmd(struct se_cmd *se_cmd)
                idr_remove(&udev->commands, tcmu_cmd->cmd_id);
                spin_unlock_irq(&udev->commands_lock);
 
-               kmem_cache_free(tcmu_cmd_cache, tcmu_cmd);
+               tcmu_free_cmd(tcmu_cmd);
        }
 
        return ret;
@@ -615,50 +816,45 @@ static void tcmu_handle_completion(struct tcmu_cmd *cmd, struct tcmu_cmd_entry *
        struct se_cmd *se_cmd = cmd->se_cmd;
        struct tcmu_dev *udev = cmd->tcmu_dev;
 
-       if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags)) {
-               /*
-                * cmd has been completed already from timeout, just reclaim
-                * data area space and free cmd
-                */
-               free_data_area(udev, cmd);
+       /*
+        * cmd has been completed already from timeout, just reclaim
+        * data area space and free cmd
+        */
+       if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags))
+               goto out;
 
-               kmem_cache_free(tcmu_cmd_cache, cmd);
-               return;
-       }
+       tcmu_cmd_reset_dbi_cur(cmd);
 
        if (entry->hdr.uflags & TCMU_UFLAG_UNKNOWN_OP) {
-               free_data_area(udev, cmd);
                pr_warn("TCMU: Userspace set UNKNOWN_OP flag on se_cmd %p\n",
                        cmd->se_cmd);
                entry->rsp.scsi_status = SAM_STAT_CHECK_CONDITION;
        } else if (entry->rsp.scsi_status == SAM_STAT_CHECK_CONDITION) {
                memcpy(se_cmd->sense_buffer, entry->rsp.sense_buffer,
                               se_cmd->scsi_sense_length);
-               free_data_area(udev, cmd);
        } else if (se_cmd->se_cmd_flags & SCF_BIDI) {
                /* Get Data-In buffer before clean up */
                gather_data_area(udev, cmd, true);
-               free_data_area(udev, cmd);
        } else if (se_cmd->data_direction == DMA_FROM_DEVICE) {
                gather_data_area(udev, cmd, false);
-               free_data_area(udev, cmd);
        } else if (se_cmd->data_direction == DMA_TO_DEVICE) {
-               free_data_area(udev, cmd);
+               /* TODO: */
        } else if (se_cmd->data_direction != DMA_NONE) {
                pr_warn("TCMU: data direction was %d!\n",
                        se_cmd->data_direction);
        }
 
        target_complete_cmd(cmd->se_cmd, entry->rsp.scsi_status);
-       cmd->se_cmd = NULL;
 
-       kmem_cache_free(tcmu_cmd_cache, cmd);
+out:
+       cmd->se_cmd = NULL;
+       tcmu_cmd_free_data(cmd, cmd->dbi_cnt);
+       tcmu_free_cmd(cmd);
 }
 
 static unsigned int tcmu_handle_completions(struct tcmu_dev *udev)
 {
        struct tcmu_mailbox *mb;
-       unsigned long flags;
        int handled = 0;
 
        if (test_bit(TCMU_DEV_BIT_BROKEN, &udev->flags)) {
@@ -666,8 +862,6 @@ static unsigned int tcmu_handle_completions(struct tcmu_dev *udev)
                return 0;
        }
 
-       spin_lock_irqsave(&udev->cmdr_lock, flags);
-
        mb = udev->mb_addr;
        tcmu_flush_dcache_range(mb, sizeof(*mb));
 
@@ -708,8 +902,6 @@ static unsigned int tcmu_handle_completions(struct tcmu_dev *udev)
        if (mb->cmd_tail == mb->cmd_head)
                del_timer(&udev->timeout); /* no more pending cmds */
 
-       spin_unlock_irqrestore(&udev->cmdr_lock, flags);
-
        wake_up(&udev->wait_cmdr);
 
        return handled;
@@ -736,16 +928,14 @@ static void tcmu_device_timedout(unsigned long data)
 {
        struct tcmu_dev *udev = (struct tcmu_dev *)data;
        unsigned long flags;
-       int handled;
-
-       handled = tcmu_handle_completions(udev);
-
-       pr_warn("%d completions handled from timeout\n", handled);
 
        spin_lock_irqsave(&udev->commands_lock, flags);
        idr_for_each(&udev->commands, tcmu_check_expired_cmd, NULL);
        spin_unlock_irqrestore(&udev->commands_lock, flags);
 
+       /* Try to wake up the ummap thread */
+       wake_up(&unmap_wait);
+
        /*
         * We don't need to wakeup threads on wait_cmdr since they have their
         * own timeout.
@@ -790,7 +980,7 @@ static struct se_device *tcmu_alloc_device(struct se_hba *hba, const char *name)
        udev->cmd_time_out = TCMU_TIME_OUT;
 
        init_waitqueue_head(&udev->wait_cmdr);
-       spin_lock_init(&udev->cmdr_lock);
+       mutex_init(&udev->cmdr_lock);
 
        idr_init(&udev->commands);
        spin_lock_init(&udev->commands_lock);
@@ -805,7 +995,9 @@ static int tcmu_irqcontrol(struct uio_info *info, s32 irq_on)
 {
        struct tcmu_dev *tcmu_dev = container_of(info, struct tcmu_dev, uio_info);
 
+       mutex_lock(&tcmu_dev->cmdr_lock);
        tcmu_handle_completions(tcmu_dev);
+       mutex_unlock(&tcmu_dev->cmdr_lock);
 
        return 0;
 }
@@ -827,6 +1019,60 @@ static int tcmu_find_mem_index(struct vm_area_struct *vma)
        return -1;
 }
 
+static struct page *tcmu_try_get_block_page(struct tcmu_dev *udev, uint32_t dbi)
+{
+       struct page *page;
+       int ret;
+
+       mutex_lock(&udev->cmdr_lock);
+       page = tcmu_get_block_page(udev, dbi);
+       if (likely(page)) {
+               mutex_unlock(&udev->cmdr_lock);
+               return page;
+       }
+
+       /*
+        * Normally it shouldn't be here:
+        * Only when the userspace has touched the blocks which
+        * are out of the tcmu_cmd's data iov[], and will return
+        * one zeroed page.
+        */
+       pr_warn("Block(%u) out of cmd's iov[] has been touched!\n", dbi);
+       pr_warn("Mostly it will be a bug of userspace, please have a check!\n");
+
+       if (dbi >= udev->dbi_thresh) {
+               /* Extern the udev->dbi_thresh to dbi + 1 */
+               udev->dbi_thresh = dbi + 1;
+               udev->dbi_max = dbi;
+       }
+
+       page = radix_tree_lookup(&udev->data_blocks, dbi);
+       if (!page) {
+               page = alloc_page(GFP_KERNEL | __GFP_ZERO);
+               if (!page) {
+                       mutex_unlock(&udev->cmdr_lock);
+                       return NULL;
+               }
+
+               ret = radix_tree_insert(&udev->data_blocks, dbi, page);
+               if (ret) {
+                       mutex_unlock(&udev->cmdr_lock);
+                       __free_page(page);
+                       return NULL;
+               }
+
+               /*
+                * Since this case is rare in page fault routine, here we
+                * will allow the global_db_count >= TCMU_GLOBAL_MAX_BLOCKS
+                * to reduce possible page fault call trace.
+                */
+               atomic_inc(&global_db_count);
+       }
+       mutex_unlock(&udev->cmdr_lock);
+
+       return page;
+}
+
 static int tcmu_vma_fault(struct vm_fault *vmf)
 {
        struct tcmu_dev *udev = vmf->vma->vm_private_data;
@@ -845,11 +1091,20 @@ static int tcmu_vma_fault(struct vm_fault *vmf)
         */
        offset = (vmf->pgoff - mi) << PAGE_SHIFT;
 
-       addr = (void *)(unsigned long)info->mem[mi].addr + offset;
-       if (info->mem[mi].memtype == UIO_MEM_LOGICAL)
-               page = virt_to_page(addr);
-       else
+       if (offset < udev->data_off) {
+               /* For the vmalloc()ed cmd area pages */
+               addr = (void *)(unsigned long)info->mem[mi].addr + offset;
                page = vmalloc_to_page(addr);
+       } else {
+               uint32_t dbi;
+
+               /* For the dynamically growing data area pages */
+               dbi = (offset - udev->data_off) / DATA_BLOCK_SIZE;
+               page = tcmu_try_get_block_page(udev, dbi);
+               if (!page)
+                       return VM_FAULT_NOPAGE;
+       }
+
        get_page(page);
        vmf->page = page;
        return 0;
@@ -883,6 +1138,8 @@ static int tcmu_open(struct uio_info *info, struct inode *inode)
        if (test_and_set_bit(TCMU_DEV_BIT_OPEN, &udev->flags))
                return -EBUSY;
 
+       udev->inode = inode;
+
        pr_debug("open\n");
 
        return 0;
@@ -963,7 +1220,7 @@ static int tcmu_configure_device(struct se_device *dev)
 
        info->name = str;
 
-       udev->mb_addr = vzalloc(TCMU_RING_SIZE);
+       udev->mb_addr = vzalloc(CMDR_SIZE);
        if (!udev->mb_addr) {
                ret = -ENOMEM;
                goto err_vzalloc;
@@ -972,8 +1229,11 @@ static int tcmu_configure_device(struct se_device *dev)
        /* mailbox fits in first part of CMDR space */
        udev->cmdr_size = CMDR_SIZE - CMDR_OFF;
        udev->data_off = CMDR_SIZE;
-       udev->data_size = TCMU_RING_SIZE - CMDR_SIZE;
+       udev->data_size = DATA_SIZE;
+       udev->dbi_thresh = 0; /* Default in Idle state */
+       udev->waiting_global = false;
 
+       /* Initialise the mailbox of the ring buffer */
        mb = udev->mb_addr;
        mb->version = TCMU_MAILBOX_VERSION;
        mb->flags = TCMU_MAILBOX_FLAG_CAP_OOOC;
@@ -984,12 +1244,14 @@ static int tcmu_configure_device(struct se_device *dev)
        WARN_ON(udev->data_size % PAGE_SIZE);
        WARN_ON(udev->data_size % DATA_BLOCK_SIZE);
 
+       INIT_RADIX_TREE(&udev->data_blocks, GFP_KERNEL);
+
        info->version = __stringify(TCMU_MAILBOX_VERSION);
 
        info->mem[0].name = "tcm-user command & data buffer";
        info->mem[0].addr = (phys_addr_t)(uintptr_t)udev->mb_addr;
        info->mem[0].size = TCMU_RING_SIZE;
-       info->mem[0].memtype = UIO_MEM_VIRTUAL;
+       info->mem[0].memtype = UIO_MEM_NONE;
 
        info->irqcontrol = tcmu_irqcontrol;
        info->irq = UIO_IRQ_CUSTOM;
@@ -1015,6 +1277,10 @@ static int tcmu_configure_device(struct se_device *dev)
        if (ret)
                goto err_netlink;
 
+       mutex_lock(&root_udev_mutex);
+       list_add(&udev->node, &root_udev);
+       mutex_unlock(&root_udev_mutex);
+
        return 0;
 
 err_netlink:
@@ -1049,6 +1315,23 @@ static bool tcmu_dev_configured(struct tcmu_dev *udev)
        return udev->uio_info.uio_dev ? true : false;
 }
 
+static void tcmu_blocks_release(struct tcmu_dev *udev)
+{
+       int i;
+       struct page *page;
+
+       /* Try to release all block pages */
+       mutex_lock(&udev->cmdr_lock);
+       for (i = 0; i <= udev->dbi_max; i++) {
+               page = radix_tree_delete(&udev->data_blocks, i);
+               if (page) {
+                       __free_page(page);
+                       atomic_dec(&global_db_count);
+               }
+       }
+       mutex_unlock(&udev->cmdr_lock);
+}
+
 static void tcmu_free_device(struct se_device *dev)
 {
        struct tcmu_dev *udev = TCMU_DEV(dev);
@@ -1058,6 +1341,10 @@ static void tcmu_free_device(struct se_device *dev)
 
        del_timer_sync(&udev->timeout);
 
+       mutex_lock(&root_udev_mutex);
+       list_del(&udev->node);
+       mutex_unlock(&root_udev_mutex);
+
        vfree(udev->mb_addr);
 
        /* Upper layer should drain all requests before calling this */
@@ -1070,6 +1357,8 @@ static void tcmu_free_device(struct se_device *dev)
        spin_unlock_irq(&udev->commands_lock);
        WARN_ON(!all_expired);
 
+       tcmu_blocks_release(udev);
+
        if (tcmu_dev_configured(udev)) {
                tcmu_netlink_event(TCMU_CMD_REMOVED_DEVICE, udev->uio_info.name,
                                   udev->uio_info.uio_dev->minor);
@@ -1256,6 +1545,84 @@ static struct target_backend_ops tcmu_ops = {
        .tb_dev_attrib_attrs    = NULL,
 };
 
+static int unmap_thread_fn(void *data)
+{
+       struct tcmu_dev *udev;
+       loff_t off;
+       uint32_t start, end, block;
+       struct page *page;
+       int i;
+
+       while (1) {
+               DEFINE_WAIT(__wait);
+
+               prepare_to_wait(&unmap_wait, &__wait, TASK_INTERRUPTIBLE);
+               schedule();
+               finish_wait(&unmap_wait, &__wait);
+
+               if (kthread_should_stop())
+                       break;
+
+               mutex_lock(&root_udev_mutex);
+               list_for_each_entry(udev, &root_udev, node) {
+                       mutex_lock(&udev->cmdr_lock);
+
+                       /* Try to complete the finished commands first */
+                       tcmu_handle_completions(udev);
+
+                       /* Skip the udevs waiting the global pool or in idle */
+                       if (udev->waiting_global || !udev->dbi_thresh) {
+                               mutex_unlock(&udev->cmdr_lock);
+                               continue;
+                       }
+
+                       end = udev->dbi_max + 1;
+                       block = find_last_bit(udev->data_bitmap, end);
+                       if (block == udev->dbi_max) {
+                               /*
+                                * The last bit is dbi_max, so there is
+                                * no need to shrink any blocks.
+                                */
+                               mutex_unlock(&udev->cmdr_lock);
+                               continue;
+                       } else if (block == end) {
+                               /* The current udev will goto idle state */
+                               udev->dbi_thresh = start = 0;
+                               udev->dbi_max = 0;
+                       } else {
+                               udev->dbi_thresh = start = block + 1;
+                               udev->dbi_max = block;
+                       }
+
+                       /* Here will truncate the data area from off */
+                       off = udev->data_off + start * DATA_BLOCK_SIZE;
+                       unmap_mapping_range(udev->inode->i_mapping, off, 0, 1);
+
+                       /* Release the block pages */
+                       for (i = start; i < end; i++) {
+                               page = radix_tree_delete(&udev->data_blocks, i);
+                               if (page) {
+                                       __free_page(page);
+                                       atomic_dec(&global_db_count);
+                               }
+                       }
+                       mutex_unlock(&udev->cmdr_lock);
+               }
+
+               /*
+                * Try to wake up the udevs who are waiting
+                * for the global data pool.
+                */
+               list_for_each_entry(udev, &root_udev, node) {
+                       if (udev->waiting_global)
+                               wake_up(&udev->wait_cmdr);
+               }
+               mutex_unlock(&root_udev_mutex);
+       }
+
+       return 0;
+}
+
 static int __init tcmu_module_init(void)
 {
        int ret, i, len = 0;
@@ -1301,8 +1668,17 @@ static int __init tcmu_module_init(void)
        if (ret)
                goto out_attrs;
 
+       init_waitqueue_head(&unmap_wait);
+       unmap_thread = kthread_run(unmap_thread_fn, NULL, "tcmu_unmap");
+       if (IS_ERR(unmap_thread)) {
+               ret = PTR_ERR(unmap_thread);
+               goto out_unreg_transport;
+       }
+
        return 0;
 
+out_unreg_transport:
+       target_backend_unregister(&tcmu_ops);
 out_attrs:
        kfree(tcmu_attrs);
 out_unreg_genl:
@@ -1317,6 +1693,7 @@ out_free_cache:
 
 static void __exit tcmu_module_exit(void)
 {
+       kthread_stop(unmap_thread);
        target_backend_unregister(&tcmu_ops);
        kfree(tcmu_attrs);
        genl_unregister_family(&tcmu_genl_family);
diff --git a/drivers/tee/Kconfig b/drivers/tee/Kconfig
new file mode 100644 (file)
index 0000000..a6df12d
--- /dev/null
@@ -0,0 +1,19 @@
+# Generic Trusted Execution Environment Configuration
+config TEE
+       tristate "Trusted Execution Environment support"
+       depends on HAVE_ARM_SMCCC || COMPILE_TEST
+       select DMA_SHARED_BUFFER
+       select GENERIC_ALLOCATOR
+       help
+         This implements a generic interface towards a Trusted Execution
+         Environment (TEE).
+
+if TEE
+
+menu "TEE drivers"
+
+source "drivers/tee/optee/Kconfig"
+
+endmenu
+
+endif
diff --git a/drivers/tee/Makefile b/drivers/tee/Makefile
new file mode 100644 (file)
index 0000000..7a4e4a1
--- /dev/null
@@ -0,0 +1,5 @@
+obj-$(CONFIG_TEE) += tee.o
+tee-objs += tee_core.o
+tee-objs += tee_shm.o
+tee-objs += tee_shm_pool.o
+obj-$(CONFIG_OPTEE) += optee/
diff --git a/drivers/tee/optee/Kconfig b/drivers/tee/optee/Kconfig
new file mode 100644 (file)
index 0000000..0126de8
--- /dev/null
@@ -0,0 +1,7 @@
+# OP-TEE Trusted Execution Environment Configuration
+config OPTEE
+       tristate "OP-TEE"
+       depends on HAVE_ARM_SMCCC
+       help
+         This implements the OP-TEE Trusted Execution Environment (TEE)
+         driver.
diff --git a/drivers/tee/optee/Makefile b/drivers/tee/optee/Makefile
new file mode 100644 (file)
index 0000000..92fe578
--- /dev/null
@@ -0,0 +1,5 @@
+obj-$(CONFIG_OPTEE) += optee.o
+optee-objs += core.o
+optee-objs += call.o
+optee-objs += rpc.o
+optee-objs += supp.o
diff --git a/drivers/tee/optee/call.c b/drivers/tee/optee/call.c
new file mode 100644 (file)
index 0000000..f7b7b40
--- /dev/null
@@ -0,0 +1,444 @@
+/*
+ * Copyright (c) 2015, Linaro Limited
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/arm-smccc.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/tee_drv.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include "optee_private.h"
+#include "optee_smc.h"
+
+struct optee_call_waiter {
+       struct list_head list_node;
+       struct completion c;
+};
+
+static void optee_cq_wait_init(struct optee_call_queue *cq,
+                              struct optee_call_waiter *w)
+{
+       /*
+        * We're preparing to make a call to secure world. In case we can't
+        * allocate a thread in secure world we'll end up waiting in
+        * optee_cq_wait_for_completion().
+        *
+        * Normally if there's no contention in secure world the call will
+        * complete and we can cleanup directly with optee_cq_wait_final().
+        */
+       mutex_lock(&cq->mutex);
+
+       /*
+        * We add ourselves to the queue, but we don't wait. This
+        * guarantees that we don't lose a completion if secure world
+        * returns busy and another thread just exited and try to complete
+        * someone.
+        */
+       init_completion(&w->c);
+       list_add_tail(&w->list_node, &cq->waiters);
+
+       mutex_unlock(&cq->mutex);
+}
+
+static void optee_cq_wait_for_completion(struct optee_call_queue *cq,
+                                        struct optee_call_waiter *w)
+{
+       wait_for_completion(&w->c);
+
+       mutex_lock(&cq->mutex);
+
+       /* Move to end of list to get out of the way for other waiters */
+       list_del(&w->list_node);
+       reinit_completion(&w->c);
+       list_add_tail(&w->list_node, &cq->waiters);
+
+       mutex_unlock(&cq->mutex);
+}
+
+static void optee_cq_complete_one(struct optee_call_queue *cq)
+{
+       struct optee_call_waiter *w;
+
+       list_for_each_entry(w, &cq->waiters, list_node) {
+               if (!completion_done(&w->c)) {
+                       complete(&w->c);
+                       break;
+               }
+       }
+}
+
+static void optee_cq_wait_final(struct optee_call_queue *cq,
+                               struct optee_call_waiter *w)
+{
+       /*
+        * We're done with the call to secure world. The thread in secure
+        * world that was used for this call is now available for some
+        * other task to use.
+        */
+       mutex_lock(&cq->mutex);
+
+       /* Get out of the list */
+       list_del(&w->list_node);
+
+       /* Wake up one eventual waiting task */
+       optee_cq_complete_one(cq);
+
+       /*
+        * If we're completed we've got a completion from another task that
+        * was just done with its call to secure world. Since yet another
+        * thread now is available in secure world wake up another eventual
+        * waiting task.
+        */
+       if (completion_done(&w->c))
+               optee_cq_complete_one(cq);
+
+       mutex_unlock(&cq->mutex);
+}
+
+/* Requires the filpstate mutex to be held */
+static struct optee_session *find_session(struct optee_context_data *ctxdata,
+                                         u32 session_id)
+{
+       struct optee_session *sess;
+
+       list_for_each_entry(sess, &ctxdata->sess_list, list_node)
+               if (sess->session_id == session_id)
+                       return sess;
+
+       return NULL;
+}
+
+/**
+ * optee_do_call_with_arg() - Do an SMC to OP-TEE in secure world
+ * @ctx:       calling context
+ * @parg:      physical address of message to pass to secure world
+ *
+ * Does and SMC to OP-TEE in secure world and handles eventual resulting
+ * Remote Procedure Calls (RPC) from OP-TEE.
+ *
+ * Returns return code from secure world, 0 is OK
+ */
+u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg)
+{
+       struct optee *optee = tee_get_drvdata(ctx->teedev);
+       struct optee_call_waiter w;
+       struct optee_rpc_param param = { };
+       u32 ret;
+
+       param.a0 = OPTEE_SMC_CALL_WITH_ARG;
+       reg_pair_from_64(&param.a1, &param.a2, parg);
+       /* Initialize waiter */
+       optee_cq_wait_init(&optee->call_queue, &w);
+       while (true) {
+               struct arm_smccc_res res;
+
+               optee->invoke_fn(param.a0, param.a1, param.a2, param.a3,
+                                param.a4, param.a5, param.a6, param.a7,
+                                &res);
+
+               if (res.a0 == OPTEE_SMC_RETURN_ETHREAD_LIMIT) {
+                       /*
+                        * Out of threads in secure world, wait for a thread
+                        * become available.
+                        */
+                       optee_cq_wait_for_completion(&optee->call_queue, &w);
+               } else if (OPTEE_SMC_RETURN_IS_RPC(res.a0)) {
+                       param.a0 = res.a0;
+                       param.a1 = res.a1;
+                       param.a2 = res.a2;
+                       param.a3 = res.a3;
+                       optee_handle_rpc(ctx, &param);
+               } else {
+                       ret = res.a0;
+                       break;
+               }
+       }
+
+       /*
+        * We're done with our thread in secure world, if there's any
+        * thread waiters wake up one.
+        */
+       optee_cq_wait_final(&optee->call_queue, &w);
+
+       return ret;
+}
+
+static struct tee_shm *get_msg_arg(struct tee_context *ctx, size_t num_params,
+                                  struct optee_msg_arg **msg_arg,
+                                  phys_addr_t *msg_parg)
+{
+       int rc;
+       struct tee_shm *shm;
+       struct optee_msg_arg *ma;
+
+       shm = tee_shm_alloc(ctx, OPTEE_MSG_GET_ARG_SIZE(num_params),
+                           TEE_SHM_MAPPED);
+       if (IS_ERR(shm))
+               return shm;
+
+       ma = tee_shm_get_va(shm, 0);
+       if (IS_ERR(ma)) {
+               rc = PTR_ERR(ma);
+               goto out;
+       }
+
+       rc = tee_shm_get_pa(shm, 0, msg_parg);
+       if (rc)
+               goto out;
+
+       memset(ma, 0, OPTEE_MSG_GET_ARG_SIZE(num_params));
+       ma->num_params = num_params;
+       *msg_arg = ma;
+out:
+       if (rc) {
+               tee_shm_free(shm);
+               return ERR_PTR(rc);
+       }
+
+       return shm;
+}
+
+int optee_open_session(struct tee_context *ctx,
+                      struct tee_ioctl_open_session_arg *arg,
+                      struct tee_param *param)
+{
+       struct optee_context_data *ctxdata = ctx->data;
+       int rc;
+       struct tee_shm *shm;
+       struct optee_msg_arg *msg_arg;
+       phys_addr_t msg_parg;
+       struct optee_session *sess = NULL;
+
+       /* +2 for the meta parameters added below */
+       shm = get_msg_arg(ctx, arg->num_params + 2, &msg_arg, &msg_parg);
+       if (IS_ERR(shm))
+               return PTR_ERR(shm);
+
+       msg_arg->cmd = OPTEE_MSG_CMD_OPEN_SESSION;
+       msg_arg->cancel_id = arg->cancel_id;
+
+       /*
+        * Initialize and add the meta parameters needed when opening a
+        * session.
+        */
+       msg_arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT |
+                                 OPTEE_MSG_ATTR_META;
+       msg_arg->params[1].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT |
+                                 OPTEE_MSG_ATTR_META;
+       memcpy(&msg_arg->params[0].u.value, arg->uuid, sizeof(arg->uuid));
+       memcpy(&msg_arg->params[1].u.value, arg->uuid, sizeof(arg->clnt_uuid));
+       msg_arg->params[1].u.value.c = arg->clnt_login;
+
+       rc = optee_to_msg_param(msg_arg->params + 2, arg->num_params, param);
+       if (rc)
+               goto out;
+
+       sess = kzalloc(sizeof(*sess), GFP_KERNEL);
+       if (!sess) {
+               rc = -ENOMEM;
+               goto out;
+       }
+
+       if (optee_do_call_with_arg(ctx, msg_parg)) {
+               msg_arg->ret = TEEC_ERROR_COMMUNICATION;
+               msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
+       }
+
+       if (msg_arg->ret == TEEC_SUCCESS) {
+               /* A new session has been created, add it to the list. */
+               sess->session_id = msg_arg->session;
+               mutex_lock(&ctxdata->mutex);
+               list_add(&sess->list_node, &ctxdata->sess_list);
+               mutex_unlock(&ctxdata->mutex);
+       } else {
+               kfree(sess);
+       }
+
+       if (optee_from_msg_param(param, arg->num_params, msg_arg->params + 2)) {
+               arg->ret = TEEC_ERROR_COMMUNICATION;
+               arg->ret_origin = TEEC_ORIGIN_COMMS;
+               /* Close session again to avoid leakage */
+               optee_close_session(ctx, msg_arg->session);
+       } else {
+               arg->session = msg_arg->session;
+               arg->ret = msg_arg->ret;
+               arg->ret_origin = msg_arg->ret_origin;
+       }
+out:
+       tee_shm_free(shm);
+
+       return rc;
+}
+
+int optee_close_session(struct tee_context *ctx, u32 session)
+{
+       struct optee_context_data *ctxdata = ctx->data;
+       struct tee_shm *shm;
+       struct optee_msg_arg *msg_arg;
+       phys_addr_t msg_parg;
+       struct optee_session *sess;
+
+       /* Check that the session is valid and remove it from the list */
+       mutex_lock(&ctxdata->mutex);
+       sess = find_session(ctxdata, session);
+       if (sess)
+               list_del(&sess->list_node);
+       mutex_unlock(&ctxdata->mutex);
+       if (!sess)
+               return -EINVAL;
+       kfree(sess);
+
+       shm = get_msg_arg(ctx, 0, &msg_arg, &msg_parg);
+       if (IS_ERR(shm))
+               return PTR_ERR(shm);
+
+       msg_arg->cmd = OPTEE_MSG_CMD_CLOSE_SESSION;
+       msg_arg->session = session;
+       optee_do_call_with_arg(ctx, msg_parg);
+
+       tee_shm_free(shm);
+       return 0;
+}
+
+int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
+                     struct tee_param *param)
+{
+       struct optee_context_data *ctxdata = ctx->data;
+       struct tee_shm *shm;
+       struct optee_msg_arg *msg_arg;
+       phys_addr_t msg_parg;
+       struct optee_session *sess;
+       int rc;
+
+       /* Check that the session is valid */
+       mutex_lock(&ctxdata->mutex);
+       sess = find_session(ctxdata, arg->session);
+       mutex_unlock(&ctxdata->mutex);
+       if (!sess)
+               return -EINVAL;
+
+       shm = get_msg_arg(ctx, arg->num_params, &msg_arg, &msg_parg);
+       if (IS_ERR(shm))
+               return PTR_ERR(shm);
+       msg_arg->cmd = OPTEE_MSG_CMD_INVOKE_COMMAND;
+       msg_arg->func = arg->func;
+       msg_arg->session = arg->session;
+       msg_arg->cancel_id = arg->cancel_id;
+
+       rc = optee_to_msg_param(msg_arg->params, arg->num_params, param);
+       if (rc)
+               goto out;
+
+       if (optee_do_call_with_arg(ctx, msg_parg)) {
+               msg_arg->ret = TEEC_ERROR_COMMUNICATION;
+               msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
+       }
+
+       if (optee_from_msg_param(param, arg->num_params, msg_arg->params)) {
+               msg_arg->ret = TEEC_ERROR_COMMUNICATION;
+               msg_arg->ret_origin = TEEC_ORIGIN_COMMS;
+       }
+
+       arg->ret = msg_arg->ret;
+       arg->ret_origin = msg_arg->ret_origin;
+out:
+       tee_shm_free(shm);
+       return rc;
+}
+
+int optee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session)
+{
+       struct optee_context_data *ctxdata = ctx->data;
+       struct tee_shm *shm;
+       struct optee_msg_arg *msg_arg;
+       phys_addr_t msg_parg;
+       struct optee_session *sess;
+
+       /* Check that the session is valid */
+       mutex_lock(&ctxdata->mutex);
+       sess = find_session(ctxdata, session);
+       mutex_unlock(&ctxdata->mutex);
+       if (!sess)
+               return -EINVAL;
+
+       shm = get_msg_arg(ctx, 0, &msg_arg, &msg_parg);
+       if (IS_ERR(shm))
+               return PTR_ERR(shm);
+
+       msg_arg->cmd = OPTEE_MSG_CMD_CANCEL;
+       msg_arg->session = session;
+       msg_arg->cancel_id = cancel_id;
+       optee_do_call_with_arg(ctx, msg_parg);
+
+       tee_shm_free(shm);
+       return 0;
+}
+
+/**
+ * optee_enable_shm_cache() - Enables caching of some shared memory allocation
+ *                           in OP-TEE
+ * @optee:     main service struct
+ */
+void optee_enable_shm_cache(struct optee *optee)
+{
+       struct optee_call_waiter w;
+
+       /* We need to retry until secure world isn't busy. */
+       optee_cq_wait_init(&optee->call_queue, &w);
+       while (true) {
+               struct arm_smccc_res res;
+
+               optee->invoke_fn(OPTEE_SMC_ENABLE_SHM_CACHE, 0, 0, 0, 0, 0, 0,
+                                0, &res);
+               if (res.a0 == OPTEE_SMC_RETURN_OK)
+                       break;
+               optee_cq_wait_for_completion(&optee->call_queue, &w);
+       }
+       optee_cq_wait_final(&optee->call_queue, &w);
+}
+
+/**
+ * optee_disable_shm_cache() - Disables caching of some shared memory allocation
+ *                           in OP-TEE
+ * @optee:     main service struct
+ */
+void optee_disable_shm_cache(struct optee *optee)
+{
+       struct optee_call_waiter w;
+
+       /* We need to retry until secure world isn't busy. */
+       optee_cq_wait_init(&optee->call_queue, &w);
+       while (true) {
+               union {
+                       struct arm_smccc_res smccc;
+                       struct optee_smc_disable_shm_cache_result result;
+               } res;
+
+               optee->invoke_fn(OPTEE_SMC_DISABLE_SHM_CACHE, 0, 0, 0, 0, 0, 0,
+                                0, &res.smccc);
+               if (res.result.status == OPTEE_SMC_RETURN_ENOTAVAIL)
+                       break; /* All shm's freed */
+               if (res.result.status == OPTEE_SMC_RETURN_OK) {
+                       struct tee_shm *shm;
+
+                       shm = reg_pair_to_ptr(res.result.shm_upper32,
+                                             res.result.shm_lower32);
+                       tee_shm_free(shm);
+               } else {
+                       optee_cq_wait_for_completion(&optee->call_queue, &w);
+               }
+       }
+       optee_cq_wait_final(&optee->call_queue, &w);
+}
diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
new file mode 100644 (file)
index 0000000..58169e5
--- /dev/null
@@ -0,0 +1,622 @@
+/*
+ * Copyright (c) 2015, Linaro Limited
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/arm-smccc.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/tee_drv.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include "optee_private.h"
+#include "optee_smc.h"
+
+#define DRIVER_NAME "optee"
+
+#define OPTEE_SHM_NUM_PRIV_PAGES       1
+
+/**
+ * optee_from_msg_param() - convert from OPTEE_MSG parameters to
+ *                         struct tee_param
+ * @params:    subsystem internal parameter representation
+ * @num_params:        number of elements in the parameter arrays
+ * @msg_params:        OPTEE_MSG parameters
+ * Returns 0 on success or <0 on failure
+ */
+int optee_from_msg_param(struct tee_param *params, size_t num_params,
+                        const struct optee_msg_param *msg_params)
+{
+       int rc;
+       size_t n;
+       struct tee_shm *shm;
+       phys_addr_t pa;
+
+       for (n = 0; n < num_params; n++) {
+               struct tee_param *p = params + n;
+               const struct optee_msg_param *mp = msg_params + n;
+               u32 attr = mp->attr & OPTEE_MSG_ATTR_TYPE_MASK;
+
+               switch (attr) {
+               case OPTEE_MSG_ATTR_TYPE_NONE:
+                       p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
+                       memset(&p->u, 0, sizeof(p->u));
+                       break;
+               case OPTEE_MSG_ATTR_TYPE_VALUE_INPUT:
+               case OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT:
+               case OPTEE_MSG_ATTR_TYPE_VALUE_INOUT:
+                       p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT +
+                                 attr - OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
+                       p->u.value.a = mp->u.value.a;
+                       p->u.value.b = mp->u.value.b;
+                       p->u.value.c = mp->u.value.c;
+                       break;
+               case OPTEE_MSG_ATTR_TYPE_TMEM_INPUT:
+               case OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT:
+               case OPTEE_MSG_ATTR_TYPE_TMEM_INOUT:
+                       p->attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT +
+                                 attr - OPTEE_MSG_ATTR_TYPE_TMEM_INPUT;
+                       p->u.memref.size = mp->u.tmem.size;
+                       shm = (struct tee_shm *)(unsigned long)
+                               mp->u.tmem.shm_ref;
+                       if (!shm) {
+                               p->u.memref.shm_offs = 0;
+                               p->u.memref.shm = NULL;
+                               break;
+                       }
+                       rc = tee_shm_get_pa(shm, 0, &pa);
+                       if (rc)
+                               return rc;
+                       p->u.memref.shm_offs = mp->u.tmem.buf_ptr - pa;
+                       p->u.memref.shm = shm;
+
+                       /* Check that the memref is covered by the shm object */
+                       if (p->u.memref.size) {
+                               size_t o = p->u.memref.shm_offs +
+                                          p->u.memref.size - 1;
+
+                               rc = tee_shm_get_pa(shm, o, NULL);
+                               if (rc)
+                                       return rc;
+                       }
+                       break;
+               default:
+                       return -EINVAL;
+               }
+       }
+       return 0;
+}
+
+/**
+ * optee_to_msg_param() - convert from struct tee_params to OPTEE_MSG parameters
+ * @msg_params:        OPTEE_MSG parameters
+ * @num_params:        number of elements in the parameter arrays
+ * @params:    subsystem itnernal parameter representation
+ * Returns 0 on success or <0 on failure
+ */
+int optee_to_msg_param(struct optee_msg_param *msg_params, size_t num_params,
+                      const struct tee_param *params)
+{
+       int rc;
+       size_t n;
+       phys_addr_t pa;
+
+       for (n = 0; n < num_params; n++) {
+               const struct tee_param *p = params + n;
+               struct optee_msg_param *mp = msg_params + n;
+
+               switch (p->attr) {
+               case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
+                       mp->attr = TEE_IOCTL_PARAM_ATTR_TYPE_NONE;
+                       memset(&mp->u, 0, sizeof(mp->u));
+                       break;
+               case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
+               case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
+               case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
+                       mp->attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT + p->attr -
+                                  TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT;
+                       mp->u.value.a = p->u.value.a;
+                       mp->u.value.b = p->u.value.b;
+                       mp->u.value.c = p->u.value.c;
+                       break;
+               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
+               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
+               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
+                       mp->attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT +
+                                  p->attr -
+                                  TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
+                       mp->u.tmem.shm_ref = (unsigned long)p->u.memref.shm;
+                       mp->u.tmem.size = p->u.memref.size;
+                       if (!p->u.memref.shm) {
+                               mp->u.tmem.buf_ptr = 0;
+                               break;
+                       }
+                       rc = tee_shm_get_pa(p->u.memref.shm,
+                                           p->u.memref.shm_offs, &pa);
+                       if (rc)
+                               return rc;
+                       mp->u.tmem.buf_ptr = pa;
+                       mp->attr |= OPTEE_MSG_ATTR_CACHE_PREDEFINED <<
+                                       OPTEE_MSG_ATTR_CACHE_SHIFT;
+                       break;
+               default:
+                       return -EINVAL;
+               }
+       }
+       return 0;
+}
+
+static void optee_get_version(struct tee_device *teedev,
+                             struct tee_ioctl_version_data *vers)
+{
+       struct tee_ioctl_version_data v = {
+               .impl_id = TEE_IMPL_ID_OPTEE,
+               .impl_caps = TEE_OPTEE_CAP_TZ,
+               .gen_caps = TEE_GEN_CAP_GP,
+       };
+       *vers = v;
+}
+
+static int optee_open(struct tee_context *ctx)
+{
+       struct optee_context_data *ctxdata;
+       struct tee_device *teedev = ctx->teedev;
+       struct optee *optee = tee_get_drvdata(teedev);
+
+       ctxdata = kzalloc(sizeof(*ctxdata), GFP_KERNEL);
+       if (!ctxdata)
+               return -ENOMEM;
+
+       if (teedev == optee->supp_teedev) {
+               bool busy = true;
+
+               mutex_lock(&optee->supp.ctx_mutex);
+               if (!optee->supp.ctx) {
+                       busy = false;
+                       optee->supp.ctx = ctx;
+               }
+               mutex_unlock(&optee->supp.ctx_mutex);
+               if (busy) {
+                       kfree(ctxdata);
+                       return -EBUSY;
+               }
+       }
+
+       mutex_init(&ctxdata->mutex);
+       INIT_LIST_HEAD(&ctxdata->sess_list);
+
+       ctx->data = ctxdata;
+       return 0;
+}
+
+static void optee_release(struct tee_context *ctx)
+{
+       struct optee_context_data *ctxdata = ctx->data;
+       struct tee_device *teedev = ctx->teedev;
+       struct optee *optee = tee_get_drvdata(teedev);
+       struct tee_shm *shm;
+       struct optee_msg_arg *arg = NULL;
+       phys_addr_t parg;
+       struct optee_session *sess;
+       struct optee_session *sess_tmp;
+
+       if (!ctxdata)
+               return;
+
+       shm = tee_shm_alloc(ctx, sizeof(struct optee_msg_arg), TEE_SHM_MAPPED);
+       if (!IS_ERR(shm)) {
+               arg = tee_shm_get_va(shm, 0);
+               /*
+                * If va2pa fails for some reason, we can't call
+                * optee_close_session(), only free the memory. Secure OS
+                * will leak sessions and finally refuse more sessions, but
+                * we will at least let normal world reclaim its memory.
+                */
+               if (!IS_ERR(arg))
+                       tee_shm_va2pa(shm, arg, &parg);
+       }
+
+       list_for_each_entry_safe(sess, sess_tmp, &ctxdata->sess_list,
+                                list_node) {
+               list_del(&sess->list_node);
+               if (!IS_ERR_OR_NULL(arg)) {
+                       memset(arg, 0, sizeof(*arg));
+                       arg->cmd = OPTEE_MSG_CMD_CLOSE_SESSION;
+                       arg->session = sess->session_id;
+                       optee_do_call_with_arg(ctx, parg);
+               }
+               kfree(sess);
+       }
+       kfree(ctxdata);
+
+       if (!IS_ERR(shm))
+               tee_shm_free(shm);
+
+       ctx->data = NULL;
+
+       if (teedev == optee->supp_teedev) {
+               mutex_lock(&optee->supp.ctx_mutex);
+               optee->supp.ctx = NULL;
+               mutex_unlock(&optee->supp.ctx_mutex);
+       }
+}
+
+static struct tee_driver_ops optee_ops = {
+       .get_version = optee_get_version,
+       .open = optee_open,
+       .release = optee_release,
+       .open_session = optee_open_session,
+       .close_session = optee_close_session,
+       .invoke_func = optee_invoke_func,
+       .cancel_req = optee_cancel_req,
+};
+
+static struct tee_desc optee_desc = {
+       .name = DRIVER_NAME "-clnt",
+       .ops = &optee_ops,
+       .owner = THIS_MODULE,
+};
+
+static struct tee_driver_ops optee_supp_ops = {
+       .get_version = optee_get_version,
+       .open = optee_open,
+       .release = optee_release,
+       .supp_recv = optee_supp_recv,
+       .supp_send = optee_supp_send,
+};
+
+static struct tee_desc optee_supp_desc = {
+       .name = DRIVER_NAME "-supp",
+       .ops = &optee_supp_ops,
+       .owner = THIS_MODULE,
+       .flags = TEE_DESC_PRIVILEGED,
+};
+
+static bool optee_msg_api_uid_is_optee_api(optee_invoke_fn *invoke_fn)
+{
+       struct arm_smccc_res res;
+
+       invoke_fn(OPTEE_SMC_CALLS_UID, 0, 0, 0, 0, 0, 0, 0, &res);
+
+       if (res.a0 == OPTEE_MSG_UID_0 && res.a1 == OPTEE_MSG_UID_1 &&
+           res.a2 == OPTEE_MSG_UID_2 && res.a3 == OPTEE_MSG_UID_3)
+               return true;
+       return false;
+}
+
+static bool optee_msg_api_revision_is_compatible(optee_invoke_fn *invoke_fn)
+{
+       union {
+               struct arm_smccc_res smccc;
+               struct optee_smc_calls_revision_result result;
+       } res;
+
+       invoke_fn(OPTEE_SMC_CALLS_REVISION, 0, 0, 0, 0, 0, 0, 0, &res.smccc);
+
+       if (res.result.major == OPTEE_MSG_REVISION_MAJOR &&
+           (int)res.result.minor >= OPTEE_MSG_REVISION_MINOR)
+               return true;
+       return false;
+}
+
+static bool optee_msg_exchange_capabilities(optee_invoke_fn *invoke_fn,
+                                           u32 *sec_caps)
+{
+       union {
+               struct arm_smccc_res smccc;
+               struct optee_smc_exchange_capabilities_result result;
+       } res;
+       u32 a1 = 0;
+
+       /*
+        * TODO This isn't enough to tell if it's UP system (from kernel
+        * point of view) or not, is_smp() returns the the information
+        * needed, but can't be called directly from here.
+        */
+       if (!IS_ENABLED(CONFIG_SMP) || nr_cpu_ids == 1)
+               a1 |= OPTEE_SMC_NSEC_CAP_UNIPROCESSOR;
+
+       invoke_fn(OPTEE_SMC_EXCHANGE_CAPABILITIES, a1, 0, 0, 0, 0, 0, 0,
+                 &res.smccc);
+
+       if (res.result.status != OPTEE_SMC_RETURN_OK)
+               return false;
+
+       *sec_caps = res.result.capabilities;
+       return true;
+}
+
+static struct tee_shm_pool *
+optee_config_shm_memremap(optee_invoke_fn *invoke_fn, void **memremaped_shm)
+{
+       union {
+               struct arm_smccc_res smccc;
+               struct optee_smc_get_shm_config_result result;
+       } res;
+       struct tee_shm_pool *pool;
+       unsigned long vaddr;
+       phys_addr_t paddr;
+       size_t size;
+       phys_addr_t begin;
+       phys_addr_t end;
+       void *va;
+       struct tee_shm_pool_mem_info priv_info;
+       struct tee_shm_pool_mem_info dmabuf_info;
+
+       invoke_fn(OPTEE_SMC_GET_SHM_CONFIG, 0, 0, 0, 0, 0, 0, 0, &res.smccc);
+       if (res.result.status != OPTEE_SMC_RETURN_OK) {
+               pr_info("shm service not available\n");
+               return ERR_PTR(-ENOENT);
+       }
+
+       if (res.result.settings != OPTEE_SMC_SHM_CACHED) {
+               pr_err("only normal cached shared memory supported\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       begin = roundup(res.result.start, PAGE_SIZE);
+       end = rounddown(res.result.start + res.result.size, PAGE_SIZE);
+       paddr = begin;
+       size = end - begin;
+
+       if (size < 2 * OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE) {
+               pr_err("too small shared memory area\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       va = memremap(paddr, size, MEMREMAP_WB);
+       if (!va) {
+               pr_err("shared memory ioremap failed\n");
+               return ERR_PTR(-EINVAL);
+       }
+       vaddr = (unsigned long)va;
+
+       priv_info.vaddr = vaddr;
+       priv_info.paddr = paddr;
+       priv_info.size = OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE;
+       dmabuf_info.vaddr = vaddr + OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE;
+       dmabuf_info.paddr = paddr + OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE;
+       dmabuf_info.size = size - OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE;
+
+       pool = tee_shm_pool_alloc_res_mem(&priv_info, &dmabuf_info);
+       if (IS_ERR(pool)) {
+               memunmap(va);
+               goto out;
+       }
+
+       *memremaped_shm = va;
+out:
+       return pool;
+}
+
+/* Simple wrapper functions to be able to use a function pointer */
+static void optee_smccc_smc(unsigned long a0, unsigned long a1,
+                           unsigned long a2, unsigned long a3,
+                           unsigned long a4, unsigned long a5,
+                           unsigned long a6, unsigned long a7,
+                           struct arm_smccc_res *res)
+{
+       arm_smccc_smc(a0, a1, a2, a3, a4, a5, a6, a7, res);
+}
+
+static void optee_smccc_hvc(unsigned long a0, unsigned long a1,
+                           unsigned long a2, unsigned long a3,
+                           unsigned long a4, unsigned long a5,
+                           unsigned long a6, unsigned long a7,
+                           struct arm_smccc_res *res)
+{
+       arm_smccc_hvc(a0, a1, a2, a3, a4, a5, a6, a7, res);
+}
+
+static optee_invoke_fn *get_invoke_func(struct device_node *np)
+{
+       const char *method;
+
+       pr_info("probing for conduit method from DT.\n");
+
+       if (of_property_read_string(np, "method", &method)) {
+               pr_warn("missing \"method\" property\n");
+               return ERR_PTR(-ENXIO);
+       }
+
+       if (!strcmp("hvc", method))
+               return optee_smccc_hvc;
+       else if (!strcmp("smc", method))
+               return optee_smccc_smc;
+
+       pr_warn("invalid \"method\" property: %s\n", method);
+       return ERR_PTR(-EINVAL);
+}
+
+static struct optee *optee_probe(struct device_node *np)
+{
+       optee_invoke_fn *invoke_fn;
+       struct tee_shm_pool *pool;
+       struct optee *optee = NULL;
+       void *memremaped_shm = NULL;
+       struct tee_device *teedev;
+       u32 sec_caps;
+       int rc;
+
+       invoke_fn = get_invoke_func(np);
+       if (IS_ERR(invoke_fn))
+               return (void *)invoke_fn;
+
+       if (!optee_msg_api_uid_is_optee_api(invoke_fn)) {
+               pr_warn("api uid mismatch\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       if (!optee_msg_api_revision_is_compatible(invoke_fn)) {
+               pr_warn("api revision mismatch\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       if (!optee_msg_exchange_capabilities(invoke_fn, &sec_caps)) {
+               pr_warn("capabilities mismatch\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       /*
+        * We have no other option for shared memory, if secure world
+        * doesn't have any reserved memory we can use we can't continue.
+        */
+       if (!(sec_caps & OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM))
+               return ERR_PTR(-EINVAL);
+
+       pool = optee_config_shm_memremap(invoke_fn, &memremaped_shm);
+       if (IS_ERR(pool))
+               return (void *)pool;
+
+       optee = kzalloc(sizeof(*optee), GFP_KERNEL);
+       if (!optee) {
+               rc = -ENOMEM;
+               goto err;
+       }
+
+       optee->invoke_fn = invoke_fn;
+
+       teedev = tee_device_alloc(&optee_desc, NULL, pool, optee);
+       if (IS_ERR(teedev)) {
+               rc = PTR_ERR(teedev);
+               goto err;
+       }
+       optee->teedev = teedev;
+
+       teedev = tee_device_alloc(&optee_supp_desc, NULL, pool, optee);
+       if (IS_ERR(teedev)) {
+               rc = PTR_ERR(teedev);
+               goto err;
+       }
+       optee->supp_teedev = teedev;
+
+       rc = tee_device_register(optee->teedev);
+       if (rc)
+               goto err;
+
+       rc = tee_device_register(optee->supp_teedev);
+       if (rc)
+               goto err;
+
+       mutex_init(&optee->call_queue.mutex);
+       INIT_LIST_HEAD(&optee->call_queue.waiters);
+       optee_wait_queue_init(&optee->wait_queue);
+       optee_supp_init(&optee->supp);
+       optee->memremaped_shm = memremaped_shm;
+       optee->pool = pool;
+
+       optee_enable_shm_cache(optee);
+
+       pr_info("initialized driver\n");
+       return optee;
+err:
+       if (optee) {
+               /*
+                * tee_device_unregister() is safe to call even if the
+                * devices hasn't been registered with
+                * tee_device_register() yet.
+                */
+               tee_device_unregister(optee->supp_teedev);
+               tee_device_unregister(optee->teedev);
+               kfree(optee);
+       }
+       if (pool)
+               tee_shm_pool_free(pool);
+       if (memremaped_shm)
+               memunmap(memremaped_shm);
+       return ERR_PTR(rc);
+}
+
+static void optee_remove(struct optee *optee)
+{
+       /*
+        * Ask OP-TEE to free all cached shared memory objects to decrease
+        * reference counters and also avoid wild pointers in secure world
+        * into the old shared memory range.
+        */
+       optee_disable_shm_cache(optee);
+
+       /*
+        * The two devices has to be unregistered before we can free the
+        * other resources.
+        */
+       tee_device_unregister(optee->supp_teedev);
+       tee_device_unregister(optee->teedev);
+
+       tee_shm_pool_free(optee->pool);
+       if (optee->memremaped_shm)
+               memunmap(optee->memremaped_shm);
+       optee_wait_queue_exit(&optee->wait_queue);
+       optee_supp_uninit(&optee->supp);
+       mutex_destroy(&optee->call_queue.mutex);
+
+       kfree(optee);
+}
+
+static const struct of_device_id optee_match[] = {
+       { .compatible = "linaro,optee-tz" },
+       {},
+};
+
+static struct optee *optee_svc;
+
+static int __init optee_driver_init(void)
+{
+       struct device_node *fw_np;
+       struct device_node *np;
+       struct optee *optee;
+
+       /* Node is supposed to be below /firmware */
+       fw_np = of_find_node_by_name(NULL, "firmware");
+       if (!fw_np)
+               return -ENODEV;
+
+       np = of_find_matching_node(fw_np, optee_match);
+       of_node_put(fw_np);
+       if (!np)
+               return -ENODEV;
+
+       optee = optee_probe(np);
+       of_node_put(np);
+
+       if (IS_ERR(optee))
+               return PTR_ERR(optee);
+
+       optee_svc = optee;
+
+       return 0;
+}
+module_init(optee_driver_init);
+
+static void __exit optee_driver_exit(void)
+{
+       struct optee *optee = optee_svc;
+
+       optee_svc = NULL;
+       if (optee)
+               optee_remove(optee);
+}
+module_exit(optee_driver_exit);
+
+MODULE_AUTHOR("Linaro");
+MODULE_DESCRIPTION("OP-TEE driver");
+MODULE_SUPPORTED_DEVICE("");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/tee/optee/optee_msg.h b/drivers/tee/optee/optee_msg.h
new file mode 100644 (file)
index 0000000..dd7a06e
--- /dev/null
@@ -0,0 +1,418 @@
+/*
+ * Copyright (c) 2015-2016, Linaro Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _OPTEE_MSG_H
+#define _OPTEE_MSG_H
+
+#include <linux/bitops.h>
+#include <linux/types.h>
+
+/*
+ * This file defines the OP-TEE message protocol used to communicate
+ * with an instance of OP-TEE running in secure world.
+ *
+ * This file is divided into three sections.
+ * 1. Formatting of messages.
+ * 2. Requests from normal world
+ * 3. Requests from secure world, Remote Procedure Call (RPC), handled by
+ *    tee-supplicant.
+ */
+
+/*****************************************************************************
+ * Part 1 - formatting of messages
+ *****************************************************************************/
+
+#define OPTEE_MSG_ATTR_TYPE_NONE               0x0
+#define OPTEE_MSG_ATTR_TYPE_VALUE_INPUT                0x1
+#define OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT       0x2
+#define OPTEE_MSG_ATTR_TYPE_VALUE_INOUT                0x3
+#define OPTEE_MSG_ATTR_TYPE_RMEM_INPUT         0x5
+#define OPTEE_MSG_ATTR_TYPE_RMEM_OUTPUT                0x6
+#define OPTEE_MSG_ATTR_TYPE_RMEM_INOUT         0x7
+#define OPTEE_MSG_ATTR_TYPE_TMEM_INPUT         0x9
+#define OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT                0xa
+#define OPTEE_MSG_ATTR_TYPE_TMEM_INOUT         0xb
+
+#define OPTEE_MSG_ATTR_TYPE_MASK               GENMASK(7, 0)
+
+/*
+ * Meta parameter to be absorbed by the Secure OS and not passed
+ * to the Trusted Application.
+ *
+ * Currently only used with OPTEE_MSG_CMD_OPEN_SESSION.
+ */
+#define OPTEE_MSG_ATTR_META                    BIT(8)
+
+/*
+ * The temporary shared memory object is not physically contigous and this
+ * temp memref is followed by another fragment until the last temp memref
+ * that doesn't have this bit set.
+ */
+#define OPTEE_MSG_ATTR_FRAGMENT                        BIT(9)
+
+/*
+ * Memory attributes for caching passed with temp memrefs. The actual value
+ * used is defined outside the message protocol with the exception of
+ * OPTEE_MSG_ATTR_CACHE_PREDEFINED which means the attributes already
+ * defined for the memory range should be used. If optee_smc.h is used as
+ * bearer of this protocol OPTEE_SMC_SHM_* is used for values.
+ */
+#define OPTEE_MSG_ATTR_CACHE_SHIFT             16
+#define OPTEE_MSG_ATTR_CACHE_MASK              GENMASK(2, 0)
+#define OPTEE_MSG_ATTR_CACHE_PREDEFINED                0
+
+/*
+ * Same values as TEE_LOGIN_* from TEE Internal API
+ */
+#define OPTEE_MSG_LOGIN_PUBLIC                 0x00000000
+#define OPTEE_MSG_LOGIN_USER                   0x00000001
+#define OPTEE_MSG_LOGIN_GROUP                  0x00000002
+#define OPTEE_MSG_LOGIN_APPLICATION            0x00000004
+#define OPTEE_MSG_LOGIN_APPLICATION_USER       0x00000005
+#define OPTEE_MSG_LOGIN_APPLICATION_GROUP      0x00000006
+
+/**
+ * struct optee_msg_param_tmem - temporary memory reference parameter
+ * @buf_ptr:   Address of the buffer
+ * @size:      Size of the buffer
+ * @shm_ref:   Temporary shared memory reference, pointer to a struct tee_shm
+ *
+ * Secure and normal world communicates pointers as physical address
+ * instead of the virtual address. This is because secure and normal world
+ * have completely independent memory mapping. Normal world can even have a
+ * hypervisor which need to translate the guest physical address (AKA IPA
+ * in ARM documentation) to a real physical address before passing the
+ * structure to secure world.
+ */
+struct optee_msg_param_tmem {
+       u64 buf_ptr;
+       u64 size;
+       u64 shm_ref;
+};
+
+/**
+ * struct optee_msg_param_rmem - registered memory reference parameter
+ * @offs:      Offset into shared memory reference
+ * @size:      Size of the buffer
+ * @shm_ref:   Shared memory reference, pointer to a struct tee_shm
+ */
+struct optee_msg_param_rmem {
+       u64 offs;
+       u64 size;
+       u64 shm_ref;
+};
+
+/**
+ * struct optee_msg_param_value - opaque value parameter
+ *
+ * Value parameters are passed unchecked between normal and secure world.
+ */
+struct optee_msg_param_value {
+       u64 a;
+       u64 b;
+       u64 c;
+};
+
+/**
+ * struct optee_msg_param - parameter used together with struct optee_msg_arg
+ * @attr:      attributes
+ * @tmem:      parameter by temporary memory reference
+ * @rmem:      parameter by registered memory reference
+ * @value:     parameter by opaque value
+ *
+ * @attr & OPTEE_MSG_ATTR_TYPE_MASK indicates if tmem, rmem or value is used in
+ * the union. OPTEE_MSG_ATTR_TYPE_VALUE_* indicates value,
+ * OPTEE_MSG_ATTR_TYPE_TMEM_* indicates tmem and
+ * OPTEE_MSG_ATTR_TYPE_RMEM_* indicates rmem.
+ * OPTEE_MSG_ATTR_TYPE_NONE indicates that none of the members are used.
+ */
+struct optee_msg_param {
+       u64 attr;
+       union {
+               struct optee_msg_param_tmem tmem;
+               struct optee_msg_param_rmem rmem;
+               struct optee_msg_param_value value;
+       } u;
+};
+
+/**
+ * struct optee_msg_arg - call argument
+ * @cmd: Command, one of OPTEE_MSG_CMD_* or OPTEE_MSG_RPC_CMD_*
+ * @func: Trusted Application function, specific to the Trusted Application,
+ *          used if cmd == OPTEE_MSG_CMD_INVOKE_COMMAND
+ * @session: In parameter for all OPTEE_MSG_CMD_* except
+ *          OPTEE_MSG_CMD_OPEN_SESSION where it's an output parameter instead
+ * @cancel_id: Cancellation id, a unique value to identify this request
+ * @ret: return value
+ * @ret_origin: origin of the return value
+ * @num_params: number of parameters supplied to the OS Command
+ * @params: the parameters supplied to the OS Command
+ *
+ * All normal calls to Trusted OS uses this struct. If cmd requires further
+ * information than what these field holds it can be passed as a parameter
+ * tagged as meta (setting the OPTEE_MSG_ATTR_META bit in corresponding
+ * attrs field). All parameters tagged as meta has to come first.
+ *
+ * Temp memref parameters can be fragmented if supported by the Trusted OS
+ * (when optee_smc.h is bearer of this protocol this is indicated with
+ * OPTEE_SMC_SEC_CAP_UNREGISTERED_SHM). If a logical memref parameter is
+ * fragmented then has all but the last fragment the
+ * OPTEE_MSG_ATTR_FRAGMENT bit set in attrs. Even if a memref is fragmented
+ * it will still be presented as a single logical memref to the Trusted
+ * Application.
+ */
+struct optee_msg_arg {
+       u32 cmd;
+       u32 func;
+       u32 session;
+       u32 cancel_id;
+       u32 pad;
+       u32 ret;
+       u32 ret_origin;
+       u32 num_params;
+
+       /* num_params tells the actual number of element in params */
+       struct optee_msg_param params[0];
+};
+
+/**
+ * OPTEE_MSG_GET_ARG_SIZE - return size of struct optee_msg_arg
+ *
+ * @num_params: Number of parameters embedded in the struct optee_msg_arg
+ *
+ * Returns the size of the struct optee_msg_arg together with the number
+ * of embedded parameters.
+ */
+#define OPTEE_MSG_GET_ARG_SIZE(num_params) \
+       (sizeof(struct optee_msg_arg) + \
+        sizeof(struct optee_msg_param) * (num_params))
+
+/*****************************************************************************
+ * Part 2 - requests from normal world
+ *****************************************************************************/
+
+/*
+ * Return the following UID if using API specified in this file without
+ * further extensions:
+ * 384fb3e0-e7f8-11e3-af63-0002a5d5c51b.
+ * Represented in 4 32-bit words in OPTEE_MSG_UID_0, OPTEE_MSG_UID_1,
+ * OPTEE_MSG_UID_2, OPTEE_MSG_UID_3.
+ */
+#define OPTEE_MSG_UID_0                        0x384fb3e0
+#define OPTEE_MSG_UID_1                        0xe7f811e3
+#define OPTEE_MSG_UID_2                        0xaf630002
+#define OPTEE_MSG_UID_3                        0xa5d5c51b
+#define OPTEE_MSG_FUNCID_CALLS_UID     0xFF01
+
+/*
+ * Returns 2.0 if using API specified in this file without further
+ * extensions. Represented in 2 32-bit words in OPTEE_MSG_REVISION_MAJOR
+ * and OPTEE_MSG_REVISION_MINOR
+ */
+#define OPTEE_MSG_REVISION_MAJOR       2
+#define OPTEE_MSG_REVISION_MINOR       0
+#define OPTEE_MSG_FUNCID_CALLS_REVISION        0xFF03
+
+/*
+ * Get UUID of Trusted OS.
+ *
+ * Used by non-secure world to figure out which Trusted OS is installed.
+ * Note that returned UUID is the UUID of the Trusted OS, not of the API.
+ *
+ * Returns UUID in 4 32-bit words in the same way as
+ * OPTEE_MSG_FUNCID_CALLS_UID described above.
+ */
+#define OPTEE_MSG_OS_OPTEE_UUID_0      0x486178e0
+#define OPTEE_MSG_OS_OPTEE_UUID_1      0xe7f811e3
+#define OPTEE_MSG_OS_OPTEE_UUID_2      0xbc5e0002
+#define OPTEE_MSG_OS_OPTEE_UUID_3      0xa5d5c51b
+#define OPTEE_MSG_FUNCID_GET_OS_UUID   0x0000
+
+/*
+ * Get revision of Trusted OS.
+ *
+ * Used by non-secure world to figure out which version of the Trusted OS
+ * is installed. Note that the returned revision is the revision of the
+ * Trusted OS, not of the API.
+ *
+ * Returns revision in 2 32-bit words in the same way as
+ * OPTEE_MSG_CALLS_REVISION described above.
+ */
+#define OPTEE_MSG_FUNCID_GET_OS_REVISION       0x0001
+
+/*
+ * Do a secure call with struct optee_msg_arg as argument
+ * The OPTEE_MSG_CMD_* below defines what goes in struct optee_msg_arg::cmd
+ *
+ * OPTEE_MSG_CMD_OPEN_SESSION opens a session to a Trusted Application.
+ * The first two parameters are tagged as meta, holding two value
+ * parameters to pass the following information:
+ * param[0].u.value.a-b uuid of Trusted Application
+ * param[1].u.value.a-b uuid of Client
+ * param[1].u.value.c Login class of client OPTEE_MSG_LOGIN_*
+ *
+ * OPTEE_MSG_CMD_INVOKE_COMMAND invokes a command a previously opened
+ * session to a Trusted Application.  struct optee_msg_arg::func is Trusted
+ * Application function, specific to the Trusted Application.
+ *
+ * OPTEE_MSG_CMD_CLOSE_SESSION closes a previously opened session to
+ * Trusted Application.
+ *
+ * OPTEE_MSG_CMD_CANCEL cancels a currently invoked command.
+ *
+ * OPTEE_MSG_CMD_REGISTER_SHM registers a shared memory reference. The
+ * information is passed as:
+ * [in] param[0].attr                  OPTEE_MSG_ATTR_TYPE_TMEM_INPUT
+ *                                     [| OPTEE_MSG_ATTR_FRAGMENT]
+ * [in] param[0].u.tmem.buf_ptr                physical address (of first fragment)
+ * [in] param[0].u.tmem.size           size (of first fragment)
+ * [in] param[0].u.tmem.shm_ref                holds shared memory reference
+ * ...
+ * The shared memory can optionally be fragmented, temp memrefs can follow
+ * each other with all but the last with the OPTEE_MSG_ATTR_FRAGMENT bit set.
+ *
+ * OPTEE_MSG_CMD_UNREGISTER_SHM unregisteres a previously registered shared
+ * memory reference. The information is passed as:
+ * [in] param[0].attr                  OPTEE_MSG_ATTR_TYPE_RMEM_INPUT
+ * [in] param[0].u.rmem.shm_ref                holds shared memory reference
+ * [in] param[0].u.rmem.offs           0
+ * [in] param[0].u.rmem.size           0
+ */
+#define OPTEE_MSG_CMD_OPEN_SESSION     0
+#define OPTEE_MSG_CMD_INVOKE_COMMAND   1
+#define OPTEE_MSG_CMD_CLOSE_SESSION    2
+#define OPTEE_MSG_CMD_CANCEL           3
+#define OPTEE_MSG_CMD_REGISTER_SHM     4
+#define OPTEE_MSG_CMD_UNREGISTER_SHM   5
+#define OPTEE_MSG_FUNCID_CALL_WITH_ARG 0x0004
+
+/*****************************************************************************
+ * Part 3 - Requests from secure world, RPC
+ *****************************************************************************/
+
+/*
+ * All RPC is done with a struct optee_msg_arg as bearer of information,
+ * struct optee_msg_arg::arg holds values defined by OPTEE_MSG_RPC_CMD_* below
+ *
+ * RPC communication with tee-supplicant is reversed compared to normal
+ * client communication desribed above. The supplicant receives requests
+ * and sends responses.
+ */
+
+/*
+ * Load a TA into memory, defined in tee-supplicant
+ */
+#define OPTEE_MSG_RPC_CMD_LOAD_TA      0
+
+/*
+ * Reserved
+ */
+#define OPTEE_MSG_RPC_CMD_RPMB         1
+
+/*
+ * File system access, defined in tee-supplicant
+ */
+#define OPTEE_MSG_RPC_CMD_FS           2
+
+/*
+ * Get time
+ *
+ * Returns number of seconds and nano seconds since the Epoch,
+ * 1970-01-01 00:00:00 +0000 (UTC).
+ *
+ * [out] param[0].u.value.a    Number of seconds
+ * [out] param[0].u.value.b    Number of nano seconds.
+ */
+#define OPTEE_MSG_RPC_CMD_GET_TIME     3
+
+/*
+ * Wait queue primitive, helper for secure world to implement a wait queue.
+ *
+ * If secure world need to wait for a secure world mutex it issues a sleep
+ * request instead of spinning in secure world. Conversely is a wakeup
+ * request issued when a secure world mutex with a thread waiting thread is
+ * unlocked.
+ *
+ * Waiting on a key
+ * [in] param[0].u.value.a OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP
+ * [in] param[0].u.value.b wait key
+ *
+ * Waking up a key
+ * [in] param[0].u.value.a OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP
+ * [in] param[0].u.value.b wakeup key
+ */
+#define OPTEE_MSG_RPC_CMD_WAIT_QUEUE   4
+#define OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP 0
+#define OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP        1
+
+/*
+ * Suspend execution
+ *
+ * [in] param[0].value .a number of milliseconds to suspend
+ */
+#define OPTEE_MSG_RPC_CMD_SUSPEND      5
+
+/*
+ * Allocate a piece of shared memory
+ *
+ * Shared memory can optionally be fragmented, to support that additional
+ * spare param entries are allocated to make room for eventual fragments.
+ * The spare param entries has .attr = OPTEE_MSG_ATTR_TYPE_NONE when
+ * unused. All returned temp memrefs except the last should have the
+ * OPTEE_MSG_ATTR_FRAGMENT bit set in the attr field.
+ *
+ * [in]  param[0].u.value.a            type of memory one of
+ *                                     OPTEE_MSG_RPC_SHM_TYPE_* below
+ * [in]  param[0].u.value.b            requested size
+ * [in]  param[0].u.value.c            required alignment
+ *
+ * [out] param[0].u.tmem.buf_ptr       physical address (of first fragment)
+ * [out] param[0].u.tmem.size          size (of first fragment)
+ * [out] param[0].u.tmem.shm_ref       shared memory reference
+ * ...
+ * [out] param[n].u.tmem.buf_ptr       physical address
+ * [out] param[n].u.tmem.size          size
+ * [out] param[n].u.tmem.shm_ref       shared memory reference (same value
+ *                                     as in param[n-1].u.tmem.shm_ref)
+ */
+#define OPTEE_MSG_RPC_CMD_SHM_ALLOC    6
+/* Memory that can be shared with a non-secure user space application */
+#define OPTEE_MSG_RPC_SHM_TYPE_APPL    0
+/* Memory only shared with non-secure kernel */
+#define OPTEE_MSG_RPC_SHM_TYPE_KERNEL  1
+
+/*
+ * Free shared memory previously allocated with OPTEE_MSG_RPC_CMD_SHM_ALLOC
+ *
+ * [in]  param[0].u.value.a            type of memory one of
+ *                                     OPTEE_MSG_RPC_SHM_TYPE_* above
+ * [in]  param[0].u.value.b            value of shared memory reference
+ *                                     returned in param[0].u.tmem.shm_ref
+ *                                     above
+ */
+#define OPTEE_MSG_RPC_CMD_SHM_FREE     7
+
+#endif /* _OPTEE_MSG_H */
diff --git a/drivers/tee/optee/optee_private.h b/drivers/tee/optee/optee_private.h
new file mode 100644 (file)
index 0000000..c374cd5
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2015, Linaro Limited
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef OPTEE_PRIVATE_H
+#define OPTEE_PRIVATE_H
+
+#include <linux/arm-smccc.h>
+#include <linux/semaphore.h>
+#include <linux/tee_drv.h>
+#include <linux/types.h>
+#include "optee_msg.h"
+
+#define OPTEE_MAX_ARG_SIZE     1024
+
+/* Some Global Platform error codes used in this driver */
+#define TEEC_SUCCESS                   0x00000000
+#define TEEC_ERROR_BAD_PARAMETERS      0xFFFF0006
+#define TEEC_ERROR_COMMUNICATION       0xFFFF000E
+#define TEEC_ERROR_OUT_OF_MEMORY       0xFFFF000C
+
+#define TEEC_ORIGIN_COMMS              0x00000002
+
+typedef void (optee_invoke_fn)(unsigned long, unsigned long, unsigned long,
+                               unsigned long, unsigned long, unsigned long,
+                               unsigned long, unsigned long,
+                               struct arm_smccc_res *);
+
+struct optee_call_queue {
+       /* Serializes access to this struct */
+       struct mutex mutex;
+       struct list_head waiters;
+};
+
+struct optee_wait_queue {
+       /* Serializes access to this struct */
+       struct mutex mu;
+       struct list_head db;
+};
+
+/**
+ * struct optee_supp - supplicant synchronization struct
+ * @ctx                        the context of current connected supplicant.
+ *                     if !NULL the supplicant device is available for use,
+ *                     else busy
+ * @ctx_mutex:         held while accessing @ctx
+ * @func:              supplicant function id to call
+ * @ret:               call return value
+ * @num_params:                number of elements in @param
+ * @param:             parameters for @func
+ * @req_posted:                if true, a request has been posted to the supplicant
+ * @supp_next_send:    if true, next step is for supplicant to send response
+ * @thrd_mutex:                held by the thread doing a request to supplicant
+ * @supp_mutex:                held by supplicant while operating on this struct
+ * @data_to_supp:      supplicant is waiting on this for next request
+ * @data_from_supp:    requesting thread is waiting on this to get the result
+ */
+struct optee_supp {
+       struct tee_context *ctx;
+       /* Serializes access of ctx */
+       struct mutex ctx_mutex;
+
+       u32 func;
+       u32 ret;
+       size_t num_params;
+       struct tee_param *param;
+
+       bool req_posted;
+       bool supp_next_send;
+       /* Serializes access to this struct for requesting thread */
+       struct mutex thrd_mutex;
+       /* Serializes access to this struct for supplicant threads */
+       struct mutex supp_mutex;
+       struct completion data_to_supp;
+       struct completion data_from_supp;
+};
+
+/**
+ * struct optee - main service struct
+ * @supp_teedev:       supplicant device
+ * @teedev:            client device
+ * @invoke_fn:         function to issue smc or hvc
+ * @call_queue:                queue of threads waiting to call @invoke_fn
+ * @wait_queue:                queue of threads from secure world waiting for a
+ *                     secure world sync object
+ * @supp:              supplicant synchronization struct for RPC to supplicant
+ * @pool:              shared memory pool
+ * @memremaped_shm     virtual address of memory in shared memory pool
+ */
+struct optee {
+       struct tee_device *supp_teedev;
+       struct tee_device *teedev;
+       optee_invoke_fn *invoke_fn;
+       struct optee_call_queue call_queue;
+       struct optee_wait_queue wait_queue;
+       struct optee_supp supp;
+       struct tee_shm_pool *pool;
+       void *memremaped_shm;
+};
+
+struct optee_session {
+       struct list_head list_node;
+       u32 session_id;
+};
+
+struct optee_context_data {
+       /* Serializes access to this struct */
+       struct mutex mutex;
+       struct list_head sess_list;
+};
+
+struct optee_rpc_param {
+       u32     a0;
+       u32     a1;
+       u32     a2;
+       u32     a3;
+       u32     a4;
+       u32     a5;
+       u32     a6;
+       u32     a7;
+};
+
+void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param);
+
+void optee_wait_queue_init(struct optee_wait_queue *wq);
+void optee_wait_queue_exit(struct optee_wait_queue *wq);
+
+u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
+                       struct tee_param *param);
+
+int optee_supp_read(struct tee_context *ctx, void __user *buf, size_t len);
+int optee_supp_write(struct tee_context *ctx, void __user *buf, size_t len);
+void optee_supp_init(struct optee_supp *supp);
+void optee_supp_uninit(struct optee_supp *supp);
+
+int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+                   struct tee_param *param);
+int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params,
+                   struct tee_param *param);
+
+u32 optee_do_call_with_arg(struct tee_context *ctx, phys_addr_t parg);
+int optee_open_session(struct tee_context *ctx,
+                      struct tee_ioctl_open_session_arg *arg,
+                      struct tee_param *param);
+int optee_close_session(struct tee_context *ctx, u32 session);
+int optee_invoke_func(struct tee_context *ctx, struct tee_ioctl_invoke_arg *arg,
+                     struct tee_param *param);
+int optee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session);
+
+void optee_enable_shm_cache(struct optee *optee);
+void optee_disable_shm_cache(struct optee *optee);
+
+int optee_from_msg_param(struct tee_param *params, size_t num_params,
+                        const struct optee_msg_param *msg_params);
+int optee_to_msg_param(struct optee_msg_param *msg_params, size_t num_params,
+                      const struct tee_param *params);
+
+/*
+ * Small helpers
+ */
+
+static inline void *reg_pair_to_ptr(u32 reg0, u32 reg1)
+{
+       return (void *)(unsigned long)(((u64)reg0 << 32) | reg1);
+}
+
+static inline void reg_pair_from_64(u32 *reg0, u32 *reg1, u64 val)
+{
+       *reg0 = val >> 32;
+       *reg1 = val;
+}
+
+#endif /*OPTEE_PRIVATE_H*/
diff --git a/drivers/tee/optee/optee_smc.h b/drivers/tee/optee/optee_smc.h
new file mode 100644 (file)
index 0000000..13b7c98
--- /dev/null
@@ -0,0 +1,450 @@
+/*
+ * Copyright (c) 2015-2016, Linaro Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef OPTEE_SMC_H
+#define OPTEE_SMC_H
+
+#include <linux/arm-smccc.h>
+#include <linux/bitops.h>
+
+#define OPTEE_SMC_STD_CALL_VAL(func_num) \
+       ARM_SMCCC_CALL_VAL(ARM_SMCCC_STD_CALL, ARM_SMCCC_SMC_32, \
+                          ARM_SMCCC_OWNER_TRUSTED_OS, (func_num))
+#define OPTEE_SMC_FAST_CALL_VAL(func_num) \
+       ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, \
+                          ARM_SMCCC_OWNER_TRUSTED_OS, (func_num))
+
+/*
+ * Function specified by SMC Calling convention.
+ */
+#define OPTEE_SMC_FUNCID_CALLS_COUNT   0xFF00
+#define OPTEE_SMC_CALLS_COUNT \
+       ARM_SMCCC_CALL_VAL(OPTEE_SMC_FAST_CALL, SMCCC_SMC_32, \
+                          SMCCC_OWNER_TRUSTED_OS_END, \
+                          OPTEE_SMC_FUNCID_CALLS_COUNT)
+
+/*
+ * Normal cached memory (write-back), shareable for SMP systems and not
+ * shareable for UP systems.
+ */
+#define OPTEE_SMC_SHM_CACHED           1
+
+/*
+ * a0..a7 is used as register names in the descriptions below, on arm32
+ * that translates to r0..r7 and on arm64 to w0..w7. In both cases it's
+ * 32-bit registers.
+ */
+
+/*
+ * Function specified by SMC Calling convention
+ *
+ * Return one of the following UIDs if using API specified in this file
+ * without further extentions:
+ * 65cb6b93-af0c-4617-8ed6-644a8d1140f8
+ * see also OPTEE_SMC_UID_* in optee_msg.h
+ */
+#define OPTEE_SMC_FUNCID_CALLS_UID OPTEE_MSG_FUNCID_CALLS_UID
+#define OPTEE_SMC_CALLS_UID \
+       ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, \
+                          ARM_SMCCC_OWNER_TRUSTED_OS_END, \
+                          OPTEE_SMC_FUNCID_CALLS_UID)
+
+/*
+ * Function specified by SMC Calling convention
+ *
+ * Returns 2.0 if using API specified in this file without further extentions.
+ * see also OPTEE_MSG_REVISION_* in optee_msg.h
+ */
+#define OPTEE_SMC_FUNCID_CALLS_REVISION OPTEE_MSG_FUNCID_CALLS_REVISION
+#define OPTEE_SMC_CALLS_REVISION \
+       ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, ARM_SMCCC_SMC_32, \
+                          ARM_SMCCC_OWNER_TRUSTED_OS_END, \
+                          OPTEE_SMC_FUNCID_CALLS_REVISION)
+
+struct optee_smc_calls_revision_result {
+       unsigned long major;
+       unsigned long minor;
+       unsigned long reserved0;
+       unsigned long reserved1;
+};
+
+/*
+ * Get UUID of Trusted OS.
+ *
+ * Used by non-secure world to figure out which Trusted OS is installed.
+ * Note that returned UUID is the UUID of the Trusted OS, not of the API.
+ *
+ * Returns UUID in a0-4 in the same way as OPTEE_SMC_CALLS_UID
+ * described above.
+ */
+#define OPTEE_SMC_FUNCID_GET_OS_UUID OPTEE_MSG_FUNCID_GET_OS_UUID
+#define OPTEE_SMC_CALL_GET_OS_UUID \
+       OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_OS_UUID)
+
+/*
+ * Get revision of Trusted OS.
+ *
+ * Used by non-secure world to figure out which version of the Trusted OS
+ * is installed. Note that the returned revision is the revision of the
+ * Trusted OS, not of the API.
+ *
+ * Returns revision in a0-1 in the same way as OPTEE_SMC_CALLS_REVISION
+ * described above.
+ */
+#define OPTEE_SMC_FUNCID_GET_OS_REVISION OPTEE_MSG_FUNCID_GET_OS_REVISION
+#define OPTEE_SMC_CALL_GET_OS_REVISION \
+       OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_OS_REVISION)
+
+/*
+ * Call with struct optee_msg_arg as argument
+ *
+ * Call register usage:
+ * a0  SMC Function ID, OPTEE_SMC*CALL_WITH_ARG
+ * a1  Upper 32bit of a 64bit physical pointer to a struct optee_msg_arg
+ * a2  Lower 32bit of a 64bit physical pointer to a struct optee_msg_arg
+ * a3  Cache settings, not used if physical pointer is in a predefined shared
+ *     memory area else per OPTEE_SMC_SHM_*
+ * a4-6        Not used
+ * a7  Hypervisor Client ID register
+ *
+ * Normal return register usage:
+ * a0  Return value, OPTEE_SMC_RETURN_*
+ * a1-3        Not used
+ * a4-7        Preserved
+ *
+ * OPTEE_SMC_RETURN_ETHREAD_LIMIT return register usage:
+ * a0  Return value, OPTEE_SMC_RETURN_ETHREAD_LIMIT
+ * a1-3        Preserved
+ * a4-7        Preserved
+ *
+ * RPC return register usage:
+ * a0  Return value, OPTEE_SMC_RETURN_IS_RPC(val)
+ * a1-2        RPC parameters
+ * a3-7        Resume information, must be preserved
+ *
+ * Possible return values:
+ * OPTEE_SMC_RETURN_UNKNOWN_FUNCTION   Trusted OS does not recognize this
+ *                                     function.
+ * OPTEE_SMC_RETURN_OK                 Call completed, result updated in
+ *                                     the previously supplied struct
+ *                                     optee_msg_arg.
+ * OPTEE_SMC_RETURN_ETHREAD_LIMIT      Number of Trusted OS threads exceeded,
+ *                                     try again later.
+ * OPTEE_SMC_RETURN_EBADADDR           Bad physcial pointer to struct
+ *                                     optee_msg_arg.
+ * OPTEE_SMC_RETURN_EBADCMD            Bad/unknown cmd in struct optee_msg_arg
+ * OPTEE_SMC_RETURN_IS_RPC()           Call suspended by RPC call to normal
+ *                                     world.
+ */
+#define OPTEE_SMC_FUNCID_CALL_WITH_ARG OPTEE_MSG_FUNCID_CALL_WITH_ARG
+#define OPTEE_SMC_CALL_WITH_ARG \
+       OPTEE_SMC_STD_CALL_VAL(OPTEE_SMC_FUNCID_CALL_WITH_ARG)
+
+/*
+ * Get Shared Memory Config
+ *
+ * Returns the Secure/Non-secure shared memory config.
+ *
+ * Call register usage:
+ * a0  SMC Function ID, OPTEE_SMC_GET_SHM_CONFIG
+ * a1-6        Not used
+ * a7  Hypervisor Client ID register
+ *
+ * Have config return register usage:
+ * a0  OPTEE_SMC_RETURN_OK
+ * a1  Physical address of start of SHM
+ * a2  Size of of SHM
+ * a3  Cache settings of memory, as defined by the
+ *     OPTEE_SMC_SHM_* values above
+ * a4-7        Preserved
+ *
+ * Not available register usage:
+ * a0  OPTEE_SMC_RETURN_ENOTAVAIL
+ * a1-3 Not used
+ * a4-7        Preserved
+ */
+#define OPTEE_SMC_FUNCID_GET_SHM_CONFIG        7
+#define OPTEE_SMC_GET_SHM_CONFIG \
+       OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_GET_SHM_CONFIG)
+
+struct optee_smc_get_shm_config_result {
+       unsigned long status;
+       unsigned long start;
+       unsigned long size;
+       unsigned long settings;
+};
+
+/*
+ * Exchanges capabilities between normal world and secure world
+ *
+ * Call register usage:
+ * a0  SMC Function ID, OPTEE_SMC_EXCHANGE_CAPABILITIES
+ * a1  bitfield of normal world capabilities OPTEE_SMC_NSEC_CAP_*
+ * a2-6        Not used
+ * a7  Hypervisor Client ID register
+ *
+ * Normal return register usage:
+ * a0  OPTEE_SMC_RETURN_OK
+ * a1  bitfield of secure world capabilities OPTEE_SMC_SEC_CAP_*
+ * a2-7        Preserved
+ *
+ * Error return register usage:
+ * a0  OPTEE_SMC_RETURN_ENOTAVAIL, can't use the capabilities from normal world
+ * a1  bitfield of secure world capabilities OPTEE_SMC_SEC_CAP_*
+ * a2-7 Preserved
+ */
+/* Normal world works as a uniprocessor system */
+#define OPTEE_SMC_NSEC_CAP_UNIPROCESSOR                BIT(0)
+/* Secure world has reserved shared memory for normal world to use */
+#define OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM    BIT(0)
+/* Secure world can communicate via previously unregistered shared memory */
+#define OPTEE_SMC_SEC_CAP_UNREGISTERED_SHM     BIT(1)
+#define OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES 9
+#define OPTEE_SMC_EXCHANGE_CAPABILITIES \
+       OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_EXCHANGE_CAPABILITIES)
+
+struct optee_smc_exchange_capabilities_result {
+       unsigned long status;
+       unsigned long capabilities;
+       unsigned long reserved0;
+       unsigned long reserved1;
+};
+
+/*
+ * Disable and empties cache of shared memory objects
+ *
+ * Secure world can cache frequently used shared memory objects, for
+ * example objects used as RPC arguments. When secure world is idle this
+ * function returns one shared memory reference to free. To disable the
+ * cache and free all cached objects this function has to be called until
+ * it returns OPTEE_SMC_RETURN_ENOTAVAIL.
+ *
+ * Call register usage:
+ * a0  SMC Function ID, OPTEE_SMC_DISABLE_SHM_CACHE
+ * a1-6        Not used
+ * a7  Hypervisor Client ID register
+ *
+ * Normal return register usage:
+ * a0  OPTEE_SMC_RETURN_OK
+ * a1  Upper 32bit of a 64bit Shared memory cookie
+ * a2  Lower 32bit of a 64bit Shared memory cookie
+ * a3-7        Preserved
+ *
+ * Cache empty return register usage:
+ * a0  OPTEE_SMC_RETURN_ENOTAVAIL
+ * a1-7        Preserved
+ *
+ * Not idle return register usage:
+ * a0  OPTEE_SMC_RETURN_EBUSY
+ * a1-7        Preserved
+ */
+#define OPTEE_SMC_FUNCID_DISABLE_SHM_CACHE     10
+#define OPTEE_SMC_DISABLE_SHM_CACHE \
+       OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_DISABLE_SHM_CACHE)
+
+struct optee_smc_disable_shm_cache_result {
+       unsigned long status;
+       unsigned long shm_upper32;
+       unsigned long shm_lower32;
+       unsigned long reserved0;
+};
+
+/*
+ * Enable cache of shared memory objects
+ *
+ * Secure world can cache frequently used shared memory objects, for
+ * example objects used as RPC arguments. When secure world is idle this
+ * function returns OPTEE_SMC_RETURN_OK and the cache is enabled. If
+ * secure world isn't idle OPTEE_SMC_RETURN_EBUSY is returned.
+ *
+ * Call register usage:
+ * a0  SMC Function ID, OPTEE_SMC_ENABLE_SHM_CACHE
+ * a1-6        Not used
+ * a7  Hypervisor Client ID register
+ *
+ * Normal return register usage:
+ * a0  OPTEE_SMC_RETURN_OK
+ * a1-7        Preserved
+ *
+ * Not idle return register usage:
+ * a0  OPTEE_SMC_RETURN_EBUSY
+ * a1-7        Preserved
+ */
+#define OPTEE_SMC_FUNCID_ENABLE_SHM_CACHE      11
+#define OPTEE_SMC_ENABLE_SHM_CACHE \
+       OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_ENABLE_SHM_CACHE)
+
+/*
+ * Resume from RPC (for example after processing an IRQ)
+ *
+ * Call register usage:
+ * a0  SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC
+ * a1-3        Value of a1-3 when OPTEE_SMC_CALL_WITH_ARG returned
+ *     OPTEE_SMC_RETURN_RPC in a0
+ *
+ * Return register usage is the same as for OPTEE_SMC_*CALL_WITH_ARG above.
+ *
+ * Possible return values
+ * OPTEE_SMC_RETURN_UNKNOWN_FUNCTION   Trusted OS does not recognize this
+ *                                     function.
+ * OPTEE_SMC_RETURN_OK                 Original call completed, result
+ *                                     updated in the previously supplied.
+ *                                     struct optee_msg_arg
+ * OPTEE_SMC_RETURN_RPC                        Call suspended by RPC call to normal
+ *                                     world.
+ * OPTEE_SMC_RETURN_ERESUME            Resume failed, the opaque resume
+ *                                     information was corrupt.
+ */
+#define OPTEE_SMC_FUNCID_RETURN_FROM_RPC       3
+#define OPTEE_SMC_CALL_RETURN_FROM_RPC \
+       OPTEE_SMC_STD_CALL_VAL(OPTEE_SMC_FUNCID_RETURN_FROM_RPC)
+
+#define OPTEE_SMC_RETURN_RPC_PREFIX_MASK       0xFFFF0000
+#define OPTEE_SMC_RETURN_RPC_PREFIX            0xFFFF0000
+#define OPTEE_SMC_RETURN_RPC_FUNC_MASK         0x0000FFFF
+
+#define OPTEE_SMC_RETURN_GET_RPC_FUNC(ret) \
+       ((ret) & OPTEE_SMC_RETURN_RPC_FUNC_MASK)
+
+#define OPTEE_SMC_RPC_VAL(func)                ((func) | OPTEE_SMC_RETURN_RPC_PREFIX)
+
+/*
+ * Allocate memory for RPC parameter passing. The memory is used to hold a
+ * struct optee_msg_arg.
+ *
+ * "Call" register usage:
+ * a0  This value, OPTEE_SMC_RETURN_RPC_ALLOC
+ * a1  Size in bytes of required argument memory
+ * a2  Not used
+ * a3  Resume information, must be preserved
+ * a4-5        Not used
+ * a6-7        Resume information, must be preserved
+ *
+ * "Return" register usage:
+ * a0  SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC.
+ * a1  Upper 32bits of 64bit physical pointer to allocated
+ *     memory, (a1 == 0 && a2 == 0) if size was 0 or if memory can't
+ *     be allocated.
+ * a2  Lower 32bits of 64bit physical pointer to allocated
+ *     memory, (a1 == 0 && a2 == 0) if size was 0 or if memory can't
+ *     be allocated
+ * a3  Preserved
+ * a4  Upper 32bits of 64bit Shared memory cookie used when freeing
+ *     the memory or doing an RPC
+ * a5  Lower 32bits of 64bit Shared memory cookie used when freeing
+ *     the memory or doing an RPC
+ * a6-7        Preserved
+ */
+#define OPTEE_SMC_RPC_FUNC_ALLOC       0
+#define OPTEE_SMC_RETURN_RPC_ALLOC \
+       OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_ALLOC)
+
+/*
+ * Free memory previously allocated by OPTEE_SMC_RETURN_RPC_ALLOC
+ *
+ * "Call" register usage:
+ * a0  This value, OPTEE_SMC_RETURN_RPC_FREE
+ * a1  Upper 32bits of 64bit shared memory cookie belonging to this
+ *     argument memory
+ * a2  Lower 32bits of 64bit shared memory cookie belonging to this
+ *     argument memory
+ * a3-7        Resume information, must be preserved
+ *
+ * "Return" register usage:
+ * a0  SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC.
+ * a1-2        Not used
+ * a3-7        Preserved
+ */
+#define OPTEE_SMC_RPC_FUNC_FREE                2
+#define OPTEE_SMC_RETURN_RPC_FREE \
+       OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_FREE)
+
+/*
+ * Deliver an IRQ in normal world.
+ *
+ * "Call" register usage:
+ * a0  OPTEE_SMC_RETURN_RPC_IRQ
+ * a1-7        Resume information, must be preserved
+ *
+ * "Return" register usage:
+ * a0  SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC.
+ * a1-7        Preserved
+ */
+#define OPTEE_SMC_RPC_FUNC_IRQ         4
+#define OPTEE_SMC_RETURN_RPC_IRQ \
+       OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_IRQ)
+
+/*
+ * Do an RPC request. The supplied struct optee_msg_arg tells which
+ * request to do and the parameters for the request. The following fields
+ * are used (the rest are unused):
+ * - cmd               the Request ID
+ * - ret               return value of the request, filled in by normal world
+ * - num_params                number of parameters for the request
+ * - params            the parameters
+ * - param_attrs       attributes of the parameters
+ *
+ * "Call" register usage:
+ * a0  OPTEE_SMC_RETURN_RPC_CMD
+ * a1  Upper 32bit of a 64bit Shared memory cookie holding a
+ *     struct optee_msg_arg, must be preserved, only the data should
+ *     be updated
+ * a2  Lower 32bit of a 64bit Shared memory cookie holding a
+ *     struct optee_msg_arg, must be preserved, only the data should
+ *     be updated
+ * a3-7        Resume information, must be preserved
+ *
+ * "Return" register usage:
+ * a0  SMC Function ID, OPTEE_SMC_CALL_RETURN_FROM_RPC.
+ * a1-2        Not used
+ * a3-7        Preserved
+ */
+#define OPTEE_SMC_RPC_FUNC_CMD         5
+#define OPTEE_SMC_RETURN_RPC_CMD \
+       OPTEE_SMC_RPC_VAL(OPTEE_SMC_RPC_FUNC_CMD)
+
+/* Returned in a0 */
+#define OPTEE_SMC_RETURN_UNKNOWN_FUNCTION 0xFFFFFFFF
+
+/* Returned in a0 only from Trusted OS functions */
+#define OPTEE_SMC_RETURN_OK            0x0
+#define OPTEE_SMC_RETURN_ETHREAD_LIMIT 0x1
+#define OPTEE_SMC_RETURN_EBUSY         0x2
+#define OPTEE_SMC_RETURN_ERESUME       0x3
+#define OPTEE_SMC_RETURN_EBADADDR      0x4
+#define OPTEE_SMC_RETURN_EBADCMD       0x5
+#define OPTEE_SMC_RETURN_ENOMEM                0x6
+#define OPTEE_SMC_RETURN_ENOTAVAIL     0x7
+#define OPTEE_SMC_RETURN_IS_RPC(ret)   __optee_smc_return_is_rpc((ret))
+
+static inline bool __optee_smc_return_is_rpc(u32 ret)
+{
+       return ret != OPTEE_SMC_RETURN_UNKNOWN_FUNCTION &&
+              (ret & OPTEE_SMC_RETURN_RPC_PREFIX_MASK) ==
+                       OPTEE_SMC_RETURN_RPC_PREFIX;
+}
+
+#endif /* OPTEE_SMC_H */
diff --git a/drivers/tee/optee/rpc.c b/drivers/tee/optee/rpc.c
new file mode 100644 (file)
index 0000000..8814eca
--- /dev/null
@@ -0,0 +1,396 @@
+/*
+ * Copyright (c) 2015-2016, Linaro Limited
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/tee_drv.h>
+#include "optee_private.h"
+#include "optee_smc.h"
+
+struct wq_entry {
+       struct list_head link;
+       struct completion c;
+       u32 key;
+};
+
+void optee_wait_queue_init(struct optee_wait_queue *priv)
+{
+       mutex_init(&priv->mu);
+       INIT_LIST_HEAD(&priv->db);
+}
+
+void optee_wait_queue_exit(struct optee_wait_queue *priv)
+{
+       mutex_destroy(&priv->mu);
+}
+
+static void handle_rpc_func_cmd_get_time(struct optee_msg_arg *arg)
+{
+       struct timespec64 ts;
+
+       if (arg->num_params != 1)
+               goto bad;
+       if ((arg->params[0].attr & OPTEE_MSG_ATTR_TYPE_MASK) !=
+                       OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT)
+               goto bad;
+
+       getnstimeofday64(&ts);
+       arg->params[0].u.value.a = ts.tv_sec;
+       arg->params[0].u.value.b = ts.tv_nsec;
+
+       arg->ret = TEEC_SUCCESS;
+       return;
+bad:
+       arg->ret = TEEC_ERROR_BAD_PARAMETERS;
+}
+
+static struct wq_entry *wq_entry_get(struct optee_wait_queue *wq, u32 key)
+{
+       struct wq_entry *w;
+
+       mutex_lock(&wq->mu);
+
+       list_for_each_entry(w, &wq->db, link)
+               if (w->key == key)
+                       goto out;
+
+       w = kmalloc(sizeof(*w), GFP_KERNEL);
+       if (w) {
+               init_completion(&w->c);
+               w->key = key;
+               list_add_tail(&w->link, &wq->db);
+       }
+out:
+       mutex_unlock(&wq->mu);
+       return w;
+}
+
+static void wq_sleep(struct optee_wait_queue *wq, u32 key)
+{
+       struct wq_entry *w = wq_entry_get(wq, key);
+
+       if (w) {
+               wait_for_completion(&w->c);
+               mutex_lock(&wq->mu);
+               list_del(&w->link);
+               mutex_unlock(&wq->mu);
+               kfree(w);
+       }
+}
+
+static void wq_wakeup(struct optee_wait_queue *wq, u32 key)
+{
+       struct wq_entry *w = wq_entry_get(wq, key);
+
+       if (w)
+               complete(&w->c);
+}
+
+static void handle_rpc_func_cmd_wq(struct optee *optee,
+                                  struct optee_msg_arg *arg)
+{
+       if (arg->num_params != 1)
+               goto bad;
+
+       if ((arg->params[0].attr & OPTEE_MSG_ATTR_TYPE_MASK) !=
+                       OPTEE_MSG_ATTR_TYPE_VALUE_INPUT)
+               goto bad;
+
+       switch (arg->params[0].u.value.a) {
+       case OPTEE_MSG_RPC_WAIT_QUEUE_SLEEP:
+               wq_sleep(&optee->wait_queue, arg->params[0].u.value.b);
+               break;
+       case OPTEE_MSG_RPC_WAIT_QUEUE_WAKEUP:
+               wq_wakeup(&optee->wait_queue, arg->params[0].u.value.b);
+               break;
+       default:
+               goto bad;
+       }
+
+       arg->ret = TEEC_SUCCESS;
+       return;
+bad:
+       arg->ret = TEEC_ERROR_BAD_PARAMETERS;
+}
+
+static void handle_rpc_func_cmd_wait(struct optee_msg_arg *arg)
+{
+       u32 msec_to_wait;
+
+       if (arg->num_params != 1)
+               goto bad;
+
+       if ((arg->params[0].attr & OPTEE_MSG_ATTR_TYPE_MASK) !=
+                       OPTEE_MSG_ATTR_TYPE_VALUE_INPUT)
+               goto bad;
+
+       msec_to_wait = arg->params[0].u.value.a;
+
+       /* set task's state to interruptible sleep */
+       set_current_state(TASK_INTERRUPTIBLE);
+
+       /* take a nap */
+       msleep(msec_to_wait);
+
+       arg->ret = TEEC_SUCCESS;
+       return;
+bad:
+       arg->ret = TEEC_ERROR_BAD_PARAMETERS;
+}
+
+static void handle_rpc_supp_cmd(struct tee_context *ctx,
+                               struct optee_msg_arg *arg)
+{
+       struct tee_param *params;
+
+       arg->ret_origin = TEEC_ORIGIN_COMMS;
+
+       params = kmalloc_array(arg->num_params, sizeof(struct tee_param),
+                              GFP_KERNEL);
+       if (!params) {
+               arg->ret = TEEC_ERROR_OUT_OF_MEMORY;
+               return;
+       }
+
+       if (optee_from_msg_param(params, arg->num_params, arg->params)) {
+               arg->ret = TEEC_ERROR_BAD_PARAMETERS;
+               goto out;
+       }
+
+       arg->ret = optee_supp_thrd_req(ctx, arg->cmd, arg->num_params, params);
+
+       if (optee_to_msg_param(arg->params, arg->num_params, params))
+               arg->ret = TEEC_ERROR_BAD_PARAMETERS;
+out:
+       kfree(params);
+}
+
+static struct tee_shm *cmd_alloc_suppl(struct tee_context *ctx, size_t sz)
+{
+       u32 ret;
+       struct tee_param param;
+       struct optee *optee = tee_get_drvdata(ctx->teedev);
+       struct tee_shm *shm;
+
+       param.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT;
+       param.u.value.a = OPTEE_MSG_RPC_SHM_TYPE_APPL;
+       param.u.value.b = sz;
+       param.u.value.c = 0;
+
+       ret = optee_supp_thrd_req(ctx, OPTEE_MSG_RPC_CMD_SHM_ALLOC, 1, &param);
+       if (ret)
+               return ERR_PTR(-ENOMEM);
+
+       mutex_lock(&optee->supp.ctx_mutex);
+       /* Increases count as secure world doesn't have a reference */
+       shm = tee_shm_get_from_id(optee->supp.ctx, param.u.value.c);
+       mutex_unlock(&optee->supp.ctx_mutex);
+       return shm;
+}
+
+static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
+                                         struct optee_msg_arg *arg)
+{
+       phys_addr_t pa;
+       struct tee_shm *shm;
+       size_t sz;
+       size_t n;
+
+       arg->ret_origin = TEEC_ORIGIN_COMMS;
+
+       if (!arg->num_params ||
+           arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) {
+               arg->ret = TEEC_ERROR_BAD_PARAMETERS;
+               return;
+       }
+
+       for (n = 1; n < arg->num_params; n++) {
+               if (arg->params[n].attr != OPTEE_MSG_ATTR_TYPE_NONE) {
+                       arg->ret = TEEC_ERROR_BAD_PARAMETERS;
+                       return;
+               }
+       }
+
+       sz = arg->params[0].u.value.b;
+       switch (arg->params[0].u.value.a) {
+       case OPTEE_MSG_RPC_SHM_TYPE_APPL:
+               shm = cmd_alloc_suppl(ctx, sz);
+               break;
+       case OPTEE_MSG_RPC_SHM_TYPE_KERNEL:
+               shm = tee_shm_alloc(ctx, sz, TEE_SHM_MAPPED);
+               break;
+       default:
+               arg->ret = TEEC_ERROR_BAD_PARAMETERS;
+               return;
+       }
+
+       if (IS_ERR(shm)) {
+               arg->ret = TEEC_ERROR_OUT_OF_MEMORY;
+               return;
+       }
+
+       if (tee_shm_get_pa(shm, 0, &pa)) {
+               arg->ret = TEEC_ERROR_BAD_PARAMETERS;
+               goto bad;
+       }
+
+       arg->params[0].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT;
+       arg->params[0].u.tmem.buf_ptr = pa;
+       arg->params[0].u.tmem.size = sz;
+       arg->params[0].u.tmem.shm_ref = (unsigned long)shm;
+       arg->ret = TEEC_SUCCESS;
+       return;
+bad:
+       tee_shm_free(shm);
+}
+
+static void cmd_free_suppl(struct tee_context *ctx, struct tee_shm *shm)
+{
+       struct tee_param param;
+
+       param.attr = TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT;
+       param.u.value.a = OPTEE_MSG_RPC_SHM_TYPE_APPL;
+       param.u.value.b = tee_shm_get_id(shm);
+       param.u.value.c = 0;
+
+       /*
+        * Match the tee_shm_get_from_id() in cmd_alloc_suppl() as secure
+        * world has released its reference.
+        *
+        * It's better to do this before sending the request to supplicant
+        * as we'd like to let the process doing the initial allocation to
+        * do release the last reference too in order to avoid stacking
+        * many pending fput() on the client process. This could otherwise
+        * happen if secure world does many allocate and free in a single
+        * invoke.
+        */
+       tee_shm_put(shm);
+
+       optee_supp_thrd_req(ctx, OPTEE_MSG_RPC_CMD_SHM_FREE, 1, &param);
+}
+
+static void handle_rpc_func_cmd_shm_free(struct tee_context *ctx,
+                                        struct optee_msg_arg *arg)
+{
+       struct tee_shm *shm;
+
+       arg->ret_origin = TEEC_ORIGIN_COMMS;
+
+       if (arg->num_params != 1 ||
+           arg->params[0].attr != OPTEE_MSG_ATTR_TYPE_VALUE_INPUT) {
+               arg->ret = TEEC_ERROR_BAD_PARAMETERS;
+               return;
+       }
+
+       shm = (struct tee_shm *)(unsigned long)arg->params[0].u.value.b;
+       switch (arg->params[0].u.value.a) {
+       case OPTEE_MSG_RPC_SHM_TYPE_APPL:
+               cmd_free_suppl(ctx, shm);
+               break;
+       case OPTEE_MSG_RPC_SHM_TYPE_KERNEL:
+               tee_shm_free(shm);
+               break;
+       default:
+               arg->ret = TEEC_ERROR_BAD_PARAMETERS;
+       }
+       arg->ret = TEEC_SUCCESS;
+}
+
+static void handle_rpc_func_cmd(struct tee_context *ctx, struct optee *optee,
+                               struct tee_shm *shm)
+{
+       struct optee_msg_arg *arg;
+
+       arg = tee_shm_get_va(shm, 0);
+       if (IS_ERR(arg)) {
+               pr_err("%s: tee_shm_get_va %p failed\n", __func__, shm);
+               return;
+       }
+
+       switch (arg->cmd) {
+       case OPTEE_MSG_RPC_CMD_GET_TIME:
+               handle_rpc_func_cmd_get_time(arg);
+               break;
+       case OPTEE_MSG_RPC_CMD_WAIT_QUEUE:
+               handle_rpc_func_cmd_wq(optee, arg);
+               break;
+       case OPTEE_MSG_RPC_CMD_SUSPEND:
+               handle_rpc_func_cmd_wait(arg);
+               break;
+       case OPTEE_MSG_RPC_CMD_SHM_ALLOC:
+               handle_rpc_func_cmd_shm_alloc(ctx, arg);
+               break;
+       case OPTEE_MSG_RPC_CMD_SHM_FREE:
+               handle_rpc_func_cmd_shm_free(ctx, arg);
+               break;
+       default:
+               handle_rpc_supp_cmd(ctx, arg);
+       }
+}
+
+/**
+ * optee_handle_rpc() - handle RPC from secure world
+ * @ctx:       context doing the RPC
+ * @param:     value of registers for the RPC
+ *
+ * Result of RPC is written back into @param.
+ */
+void optee_handle_rpc(struct tee_context *ctx, struct optee_rpc_param *param)
+{
+       struct tee_device *teedev = ctx->teedev;
+       struct optee *optee = tee_get_drvdata(teedev);
+       struct tee_shm *shm;
+       phys_addr_t pa;
+
+       switch (OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0)) {
+       case OPTEE_SMC_RPC_FUNC_ALLOC:
+               shm = tee_shm_alloc(ctx, param->a1, TEE_SHM_MAPPED);
+               if (!IS_ERR(shm) && !tee_shm_get_pa(shm, 0, &pa)) {
+                       reg_pair_from_64(&param->a1, &param->a2, pa);
+                       reg_pair_from_64(&param->a4, &param->a5,
+                                        (unsigned long)shm);
+               } else {
+                       param->a1 = 0;
+                       param->a2 = 0;
+                       param->a4 = 0;
+                       param->a5 = 0;
+               }
+               break;
+       case OPTEE_SMC_RPC_FUNC_FREE:
+               shm = reg_pair_to_ptr(param->a1, param->a2);
+               tee_shm_free(shm);
+               break;
+       case OPTEE_SMC_RPC_FUNC_IRQ:
+               /*
+                * An IRQ was raised while secure world was executing,
+                * since all IRQs are handled in Linux a dummy RPC is
+                * performed to let Linux take the IRQ through the normal
+                * vector.
+                */
+               break;
+       case OPTEE_SMC_RPC_FUNC_CMD:
+               shm = reg_pair_to_ptr(param->a1, param->a2);
+               handle_rpc_func_cmd(ctx, optee, shm);
+               break;
+       default:
+               pr_warn("Unknown RPC func 0x%x\n",
+                       (u32)OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0));
+               break;
+       }
+
+       param->a0 = OPTEE_SMC_CALL_RETURN_FROM_RPC;
+}
diff --git a/drivers/tee/optee/supp.c b/drivers/tee/optee/supp.c
new file mode 100644 (file)
index 0000000..b4ea067
--- /dev/null
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2015, Linaro Limited
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include "optee_private.h"
+
+void optee_supp_init(struct optee_supp *supp)
+{
+       memset(supp, 0, sizeof(*supp));
+       mutex_init(&supp->ctx_mutex);
+       mutex_init(&supp->thrd_mutex);
+       mutex_init(&supp->supp_mutex);
+       init_completion(&supp->data_to_supp);
+       init_completion(&supp->data_from_supp);
+}
+
+void optee_supp_uninit(struct optee_supp *supp)
+{
+       mutex_destroy(&supp->ctx_mutex);
+       mutex_destroy(&supp->thrd_mutex);
+       mutex_destroy(&supp->supp_mutex);
+}
+
+/**
+ * optee_supp_thrd_req() - request service from supplicant
+ * @ctx:       context doing the request
+ * @func:      function requested
+ * @num_params:        number of elements in @param array
+ * @param:     parameters for function
+ *
+ * Returns result of operation to be passed to secure world
+ */
+u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,
+                       struct tee_param *param)
+{
+       bool interruptable;
+       struct optee *optee = tee_get_drvdata(ctx->teedev);
+       struct optee_supp *supp = &optee->supp;
+       u32 ret;
+
+       /*
+        * Other threads blocks here until we've copied our answer from
+        * supplicant.
+        */
+       while (mutex_lock_interruptible(&supp->thrd_mutex)) {
+               /* See comment below on when the RPC can be interrupted. */
+               mutex_lock(&supp->ctx_mutex);
+               interruptable = !supp->ctx;
+               mutex_unlock(&supp->ctx_mutex);
+               if (interruptable)
+                       return TEEC_ERROR_COMMUNICATION;
+       }
+
+       /*
+        * We have exclusive access now since the supplicant at this
+        * point is either doing a
+        * wait_for_completion_interruptible(&supp->data_to_supp) or is in
+        * userspace still about to do the ioctl() to enter
+        * optee_supp_recv() below.
+        */
+
+       supp->func = func;
+       supp->num_params = num_params;
+       supp->param = param;
+       supp->req_posted = true;
+
+       /* Let supplicant get the data */
+       complete(&supp->data_to_supp);
+
+       /*
+        * Wait for supplicant to process and return result, once we've
+        * returned from wait_for_completion(data_from_supp) we have
+        * exclusive access again.
+        */
+       while (wait_for_completion_interruptible(&supp->data_from_supp)) {
+               mutex_lock(&supp->ctx_mutex);
+               interruptable = !supp->ctx;
+               if (interruptable) {
+                       /*
+                        * There's no supplicant available and since the
+                        * supp->ctx_mutex currently is held none can
+                        * become available until the mutex released
+                        * again.
+                        *
+                        * Interrupting an RPC to supplicant is only
+                        * allowed as a way of slightly improving the user
+                        * experience in case the supplicant hasn't been
+                        * started yet. During normal operation the supplicant
+                        * will serve all requests in a timely manner and
+                        * interrupting then wouldn't make sense.
+                        */
+                       supp->ret = TEEC_ERROR_COMMUNICATION;
+                       init_completion(&supp->data_to_supp);
+               }
+               mutex_unlock(&supp->ctx_mutex);
+               if (interruptable)
+                       break;
+       }
+
+       ret = supp->ret;
+       supp->param = NULL;
+       supp->req_posted = false;
+
+       /* We're done, let someone else talk to the supplicant now. */
+       mutex_unlock(&supp->thrd_mutex);
+
+       return ret;
+}
+
+/**
+ * optee_supp_recv() - receive request for supplicant
+ * @ctx:       context receiving the request
+ * @func:      requested function in supplicant
+ * @num_params:        number of elements allocated in @param, updated with number
+ *             used elements
+ * @param:     space for parameters for @func
+ *
+ * Returns 0 on success or <0 on failure
+ */
+int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,
+                   struct tee_param *param)
+{
+       struct tee_device *teedev = ctx->teedev;
+       struct optee *optee = tee_get_drvdata(teedev);
+       struct optee_supp *supp = &optee->supp;
+       int rc;
+
+       /*
+        * In case two threads in one supplicant is calling this function
+        * simultaneously we need to protect the data with a mutex which
+        * we'll release before returning.
+        */
+       mutex_lock(&supp->supp_mutex);
+
+       if (supp->supp_next_send) {
+               /*
+                * optee_supp_recv() has been called again without
+                * a optee_supp_send() in between. Supplicant has
+                * probably been restarted before it was able to
+                * write back last result. Abort last request and
+                * wait for a new.
+                */
+               if (supp->req_posted) {
+                       supp->ret = TEEC_ERROR_COMMUNICATION;
+                       supp->supp_next_send = false;
+                       complete(&supp->data_from_supp);
+               }
+       }
+
+       /*
+        * This is where supplicant will be hanging most of the
+        * time, let's make this interruptable so we can easily
+        * restart supplicant if needed.
+        */
+       if (wait_for_completion_interruptible(&supp->data_to_supp)) {
+               rc = -ERESTARTSYS;
+               goto out;
+       }
+
+       /* We have exlusive access to the data */
+
+       if (*num_params < supp->num_params) {
+               /*
+                * Not enough room for parameters, tell supplicant
+                * it failed and abort last request.
+                */
+               supp->ret = TEEC_ERROR_COMMUNICATION;
+               rc = -EINVAL;
+               complete(&supp->data_from_supp);
+               goto out;
+       }
+
+       *func = supp->func;
+       *num_params = supp->num_params;
+       memcpy(param, supp->param,
+              sizeof(struct tee_param) * supp->num_params);
+
+       /* Allow optee_supp_send() below to do its work */
+       supp->supp_next_send = true;
+
+       rc = 0;
+out:
+       mutex_unlock(&supp->supp_mutex);
+       return rc;
+}
+
+/**
+ * optee_supp_send() - send result of request from supplicant
+ * @ctx:       context sending result
+ * @ret:       return value of request
+ * @num_params:        number of parameters returned
+ * @param:     returned parameters
+ *
+ * Returns 0 on success or <0 on failure.
+ */
+int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params,
+                   struct tee_param *param)
+{
+       struct tee_device *teedev = ctx->teedev;
+       struct optee *optee = tee_get_drvdata(teedev);
+       struct optee_supp *supp = &optee->supp;
+       size_t n;
+       int rc = 0;
+
+       /*
+        * We still have exclusive access to the data since that's how we
+        * left it when returning from optee_supp_read().
+        */
+
+       /* See comment on mutex in optee_supp_read() above */
+       mutex_lock(&supp->supp_mutex);
+
+       if (!supp->supp_next_send) {
+               /*
+                * Something strange is going on, supplicant shouldn't
+                * enter optee_supp_send() in this state
+                */
+               rc = -ENOENT;
+               goto out;
+       }
+
+       if (num_params != supp->num_params) {
+               /*
+                * Something is wrong, let supplicant restart. Next call to
+                * optee_supp_recv() will give an error to the requesting
+                * thread and release it.
+                */
+               rc = -EINVAL;
+               goto out;
+       }
+
+       /* Update out and in/out parameters */
+       for (n = 0; n < num_params; n++) {
+               struct tee_param *p = supp->param + n;
+
+               switch (p->attr) {
+               case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
+               case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
+                       p->u.value.a = param[n].u.value.a;
+                       p->u.value.b = param[n].u.value.b;
+                       p->u.value.c = param[n].u.value.c;
+                       break;
+               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
+               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
+                       p->u.memref.size = param[n].u.memref.size;
+                       break;
+               default:
+                       break;
+               }
+       }
+       supp->ret = ret;
+
+       /* Allow optee_supp_recv() above to do its work */
+       supp->supp_next_send = false;
+
+       /* Let the requesting thread continue */
+       complete(&supp->data_from_supp);
+out:
+       mutex_unlock(&supp->supp_mutex);
+       return rc;
+}
diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c
new file mode 100644 (file)
index 0000000..5c60bf4
--- /dev/null
@@ -0,0 +1,893 @@
+/*
+ * Copyright (c) 2015-2016, Linaro Limited
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/fs.h>
+#include <linux/idr.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/tee_drv.h>
+#include <linux/uaccess.h>
+#include "tee_private.h"
+
+#define TEE_NUM_DEVICES        32
+
+#define TEE_IOCTL_PARAM_SIZE(x) (sizeof(struct tee_param) * (x))
+
+/*
+ * Unprivileged devices in the lower half range and privileged devices in
+ * the upper half range.
+ */
+static DECLARE_BITMAP(dev_mask, TEE_NUM_DEVICES);
+static DEFINE_SPINLOCK(driver_lock);
+
+static struct class *tee_class;
+static dev_t tee_devt;
+
+static int tee_open(struct inode *inode, struct file *filp)
+{
+       int rc;
+       struct tee_device *teedev;
+       struct tee_context *ctx;
+
+       teedev = container_of(inode->i_cdev, struct tee_device, cdev);
+       if (!tee_device_get(teedev))
+               return -EINVAL;
+
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       if (!ctx) {
+               rc = -ENOMEM;
+               goto err;
+       }
+
+       ctx->teedev = teedev;
+       INIT_LIST_HEAD(&ctx->list_shm);
+       filp->private_data = ctx;
+       rc = teedev->desc->ops->open(ctx);
+       if (rc)
+               goto err;
+
+       return 0;
+err:
+       kfree(ctx);
+       tee_device_put(teedev);
+       return rc;
+}
+
+static int tee_release(struct inode *inode, struct file *filp)
+{
+       struct tee_context *ctx = filp->private_data;
+       struct tee_device *teedev = ctx->teedev;
+       struct tee_shm *shm;
+
+       ctx->teedev->desc->ops->release(ctx);
+       mutex_lock(&ctx->teedev->mutex);
+       list_for_each_entry(shm, &ctx->list_shm, link)
+               shm->ctx = NULL;
+       mutex_unlock(&ctx->teedev->mutex);
+       kfree(ctx);
+       tee_device_put(teedev);
+       return 0;
+}
+
+static int tee_ioctl_version(struct tee_context *ctx,
+                            struct tee_ioctl_version_data __user *uvers)
+{
+       struct tee_ioctl_version_data vers;
+
+       ctx->teedev->desc->ops->get_version(ctx->teedev, &vers);
+       if (copy_to_user(uvers, &vers, sizeof(vers)))
+               return -EFAULT;
+       return 0;
+}
+
+static int tee_ioctl_shm_alloc(struct tee_context *ctx,
+                              struct tee_ioctl_shm_alloc_data __user *udata)
+{
+       long ret;
+       struct tee_ioctl_shm_alloc_data data;
+       struct tee_shm *shm;
+
+       if (copy_from_user(&data, udata, sizeof(data)))
+               return -EFAULT;
+
+       /* Currently no input flags are supported */
+       if (data.flags)
+               return -EINVAL;
+
+       data.id = -1;
+
+       shm = tee_shm_alloc(ctx, data.size, TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
+       if (IS_ERR(shm))
+               return PTR_ERR(shm);
+
+       data.id = shm->id;
+       data.flags = shm->flags;
+       data.size = shm->size;
+
+       if (copy_to_user(udata, &data, sizeof(data)))
+               ret = -EFAULT;
+       else
+               ret = tee_shm_get_fd(shm);
+
+       /*
+        * When user space closes the file descriptor the shared memory
+        * should be freed or if tee_shm_get_fd() failed then it will
+        * be freed immediately.
+        */
+       tee_shm_put(shm);
+       return ret;
+}
+
+static int params_from_user(struct tee_context *ctx, struct tee_param *params,
+                           size_t num_params,
+                           struct tee_ioctl_param __user *uparams)
+{
+       size_t n;
+
+       for (n = 0; n < num_params; n++) {
+               struct tee_shm *shm;
+               struct tee_ioctl_param ip;
+
+               if (copy_from_user(&ip, uparams + n, sizeof(ip)))
+                       return -EFAULT;
+
+               /* All unused attribute bits has to be zero */
+               if (ip.attr & ~TEE_IOCTL_PARAM_ATTR_TYPE_MASK)
+                       return -EINVAL;
+
+               params[n].attr = ip.attr;
+               switch (ip.attr) {
+               case TEE_IOCTL_PARAM_ATTR_TYPE_NONE:
+               case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
+                       break;
+               case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
+               case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
+                       params[n].u.value.a = ip.a;
+                       params[n].u.value.b = ip.b;
+                       params[n].u.value.c = ip.c;
+                       break;
+               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
+               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
+               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
+                       /*
+                        * If we fail to get a pointer to a shared memory
+                        * object (and increase the ref count) from an
+                        * identifier we return an error. All pointers that
+                        * has been added in params have an increased ref
+                        * count. It's the callers responibility to do
+                        * tee_shm_put() on all resolved pointers.
+                        */
+                       shm = tee_shm_get_from_id(ctx, ip.c);
+                       if (IS_ERR(shm))
+                               return PTR_ERR(shm);
+
+                       params[n].u.memref.shm_offs = ip.a;
+                       params[n].u.memref.size = ip.b;
+                       params[n].u.memref.shm = shm;
+                       break;
+               default:
+                       /* Unknown attribute */
+                       return -EINVAL;
+               }
+       }
+       return 0;
+}
+
+static int params_to_user(struct tee_ioctl_param __user *uparams,
+                         size_t num_params, struct tee_param *params)
+{
+       size_t n;
+
+       for (n = 0; n < num_params; n++) {
+               struct tee_ioctl_param __user *up = uparams + n;
+               struct tee_param *p = params + n;
+
+               switch (p->attr) {
+               case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
+               case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
+                       if (put_user(p->u.value.a, &up->a) ||
+                           put_user(p->u.value.b, &up->b) ||
+                           put_user(p->u.value.c, &up->c))
+                               return -EFAULT;
+                       break;
+               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
+               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
+                       if (put_user((u64)p->u.memref.size, &up->b))
+                               return -EFAULT;
+               default:
+                       break;
+               }
+       }
+       return 0;
+}
+
+static bool param_is_memref(struct tee_param *param)
+{
+       switch (param->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) {
+       case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
+       case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
+       case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static int tee_ioctl_open_session(struct tee_context *ctx,
+                                 struct tee_ioctl_buf_data __user *ubuf)
+{
+       int rc;
+       size_t n;
+       struct tee_ioctl_buf_data buf;
+       struct tee_ioctl_open_session_arg __user *uarg;
+       struct tee_ioctl_open_session_arg arg;
+       struct tee_ioctl_param __user *uparams = NULL;
+       struct tee_param *params = NULL;
+       bool have_session = false;
+
+       if (!ctx->teedev->desc->ops->open_session)
+               return -EINVAL;
+
+       if (copy_from_user(&buf, ubuf, sizeof(buf)))
+               return -EFAULT;
+
+       if (buf.buf_len > TEE_MAX_ARG_SIZE ||
+           buf.buf_len < sizeof(struct tee_ioctl_open_session_arg))
+               return -EINVAL;
+
+       uarg = u64_to_user_ptr(buf.buf_ptr);
+       if (copy_from_user(&arg, uarg, sizeof(arg)))
+               return -EFAULT;
+
+       if (sizeof(arg) + TEE_IOCTL_PARAM_SIZE(arg.num_params) != buf.buf_len)
+               return -EINVAL;
+
+       if (arg.num_params) {
+               params = kcalloc(arg.num_params, sizeof(struct tee_param),
+                                GFP_KERNEL);
+               if (!params)
+                       return -ENOMEM;
+               uparams = uarg->params;
+               rc = params_from_user(ctx, params, arg.num_params, uparams);
+               if (rc)
+                       goto out;
+       }
+
+       rc = ctx->teedev->desc->ops->open_session(ctx, &arg, params);
+       if (rc)
+               goto out;
+       have_session = true;
+
+       if (put_user(arg.session, &uarg->session) ||
+           put_user(arg.ret, &uarg->ret) ||
+           put_user(arg.ret_origin, &uarg->ret_origin)) {
+               rc = -EFAULT;
+               goto out;
+       }
+       rc = params_to_user(uparams, arg.num_params, params);
+out:
+       /*
+        * If we've succeeded to open the session but failed to communicate
+        * it back to user space, close the session again to avoid leakage.
+        */
+       if (rc && have_session && ctx->teedev->desc->ops->close_session)
+               ctx->teedev->desc->ops->close_session(ctx, arg.session);
+
+       if (params) {
+               /* Decrease ref count for all valid shared memory pointers */
+               for (n = 0; n < arg.num_params; n++)
+                       if (param_is_memref(params + n) &&
+                           params[n].u.memref.shm)
+                               tee_shm_put(params[n].u.memref.shm);
+               kfree(params);
+       }
+
+       return rc;
+}
+
+static int tee_ioctl_invoke(struct tee_context *ctx,
+                           struct tee_ioctl_buf_data __user *ubuf)
+{
+       int rc;
+       size_t n;
+       struct tee_ioctl_buf_data buf;
+       struct tee_ioctl_invoke_arg __user *uarg;
+       struct tee_ioctl_invoke_arg arg;
+       struct tee_ioctl_param __user *uparams = NULL;
+       struct tee_param *params = NULL;
+
+       if (!ctx->teedev->desc->ops->invoke_func)
+               return -EINVAL;
+
+       if (copy_from_user(&buf, ubuf, sizeof(buf)))
+               return -EFAULT;
+
+       if (buf.buf_len > TEE_MAX_ARG_SIZE ||
+           buf.buf_len < sizeof(struct tee_ioctl_invoke_arg))
+               return -EINVAL;
+
+       uarg = u64_to_user_ptr(buf.buf_ptr);
+       if (copy_from_user(&arg, uarg, sizeof(arg)))
+               return -EFAULT;
+
+       if (sizeof(arg) + TEE_IOCTL_PARAM_SIZE(arg.num_params) != buf.buf_len)
+               return -EINVAL;
+
+       if (arg.num_params) {
+               params = kcalloc(arg.num_params, sizeof(struct tee_param),
+                                GFP_KERNEL);
+               if (!params)
+                       return -ENOMEM;
+               uparams = uarg->params;
+               rc = params_from_user(ctx, params, arg.num_params, uparams);
+               if (rc)
+                       goto out;
+       }
+
+       rc = ctx->teedev->desc->ops->invoke_func(ctx, &arg, params);
+       if (rc)
+               goto out;
+
+       if (put_user(arg.ret, &uarg->ret) ||
+           put_user(arg.ret_origin, &uarg->ret_origin)) {
+               rc = -EFAULT;
+               goto out;
+       }
+       rc = params_to_user(uparams, arg.num_params, params);
+out:
+       if (params) {
+               /* Decrease ref count for all valid shared memory pointers */
+               for (n = 0; n < arg.num_params; n++)
+                       if (param_is_memref(params + n) &&
+                           params[n].u.memref.shm)
+                               tee_shm_put(params[n].u.memref.shm);
+               kfree(params);
+       }
+       return rc;
+}
+
+static int tee_ioctl_cancel(struct tee_context *ctx,
+                           struct tee_ioctl_cancel_arg __user *uarg)
+{
+       struct tee_ioctl_cancel_arg arg;
+
+       if (!ctx->teedev->desc->ops->cancel_req)
+               return -EINVAL;
+
+       if (copy_from_user(&arg, uarg, sizeof(arg)))
+               return -EFAULT;
+
+       return ctx->teedev->desc->ops->cancel_req(ctx, arg.cancel_id,
+                                                 arg.session);
+}
+
+static int
+tee_ioctl_close_session(struct tee_context *ctx,
+                       struct tee_ioctl_close_session_arg __user *uarg)
+{
+       struct tee_ioctl_close_session_arg arg;
+
+       if (!ctx->teedev->desc->ops->close_session)
+               return -EINVAL;
+
+       if (copy_from_user(&arg, uarg, sizeof(arg)))
+               return -EFAULT;
+
+       return ctx->teedev->desc->ops->close_session(ctx, arg.session);
+}
+
+static int params_to_supp(struct tee_context *ctx,
+                         struct tee_ioctl_param __user *uparams,
+                         size_t num_params, struct tee_param *params)
+{
+       size_t n;
+
+       for (n = 0; n < num_params; n++) {
+               struct tee_ioctl_param ip;
+               struct tee_param *p = params + n;
+
+               ip.attr = p->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK;
+               switch (p->attr) {
+               case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT:
+               case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
+                       ip.a = p->u.value.a;
+                       ip.b = p->u.value.b;
+                       ip.c = p->u.value.c;
+                       break;
+               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT:
+               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
+               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
+                       ip.b = p->u.memref.size;
+                       if (!p->u.memref.shm) {
+                               ip.a = 0;
+                               ip.c = (u64)-1; /* invalid shm id */
+                               break;
+                       }
+                       ip.a = p->u.memref.shm_offs;
+                       ip.c = p->u.memref.shm->id;
+                       break;
+               default:
+                       ip.a = 0;
+                       ip.b = 0;
+                       ip.c = 0;
+                       break;
+               }
+
+               if (copy_to_user(uparams + n, &ip, sizeof(ip)))
+                       return -EFAULT;
+       }
+
+       return 0;
+}
+
+static int tee_ioctl_supp_recv(struct tee_context *ctx,
+                              struct tee_ioctl_buf_data __user *ubuf)
+{
+       int rc;
+       struct tee_ioctl_buf_data buf;
+       struct tee_iocl_supp_recv_arg __user *uarg;
+       struct tee_param *params;
+       u32 num_params;
+       u32 func;
+
+       if (!ctx->teedev->desc->ops->supp_recv)
+               return -EINVAL;
+
+       if (copy_from_user(&buf, ubuf, sizeof(buf)))
+               return -EFAULT;
+
+       if (buf.buf_len > TEE_MAX_ARG_SIZE ||
+           buf.buf_len < sizeof(struct tee_iocl_supp_recv_arg))
+               return -EINVAL;
+
+       uarg = u64_to_user_ptr(buf.buf_ptr);
+       if (get_user(num_params, &uarg->num_params))
+               return -EFAULT;
+
+       if (sizeof(*uarg) + TEE_IOCTL_PARAM_SIZE(num_params) != buf.buf_len)
+               return -EINVAL;
+
+       params = kcalloc(num_params, sizeof(struct tee_param), GFP_KERNEL);
+       if (!params)
+               return -ENOMEM;
+
+       rc = ctx->teedev->desc->ops->supp_recv(ctx, &func, &num_params, params);
+       if (rc)
+               goto out;
+
+       if (put_user(func, &uarg->func) ||
+           put_user(num_params, &uarg->num_params)) {
+               rc = -EFAULT;
+               goto out;
+       }
+
+       rc = params_to_supp(ctx, uarg->params, num_params, params);
+out:
+       kfree(params);
+       return rc;
+}
+
+static int params_from_supp(struct tee_param *params, size_t num_params,
+                           struct tee_ioctl_param __user *uparams)
+{
+       size_t n;
+
+       for (n = 0; n < num_params; n++) {
+               struct tee_param *p = params + n;
+               struct tee_ioctl_param ip;
+
+               if (copy_from_user(&ip, uparams + n, sizeof(ip)))
+                       return -EFAULT;
+
+               /* All unused attribute bits has to be zero */
+               if (ip.attr & ~TEE_IOCTL_PARAM_ATTR_TYPE_MASK)
+                       return -EINVAL;
+
+               p->attr = ip.attr;
+               switch (ip.attr) {
+               case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT:
+               case TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT:
+                       /* Only out and in/out values can be updated */
+                       p->u.value.a = ip.a;
+                       p->u.value.b = ip.b;
+                       p->u.value.c = ip.c;
+                       break;
+               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT:
+               case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT:
+                       /*
+                        * Only the size of the memref can be updated.
+                        * Since we don't have access to the original
+                        * parameters here, only store the supplied size.
+                        * The driver will copy the updated size into the
+                        * original parameters.
+                        */
+                       p->u.memref.shm = NULL;
+                       p->u.memref.shm_offs = 0;
+                       p->u.memref.size = ip.b;
+                       break;
+               default:
+                       memset(&p->u, 0, sizeof(p->u));
+                       break;
+               }
+       }
+       return 0;
+}
+
+static int tee_ioctl_supp_send(struct tee_context *ctx,
+                              struct tee_ioctl_buf_data __user *ubuf)
+{
+       long rc;
+       struct tee_ioctl_buf_data buf;
+       struct tee_iocl_supp_send_arg __user *uarg;
+       struct tee_param *params;
+       u32 num_params;
+       u32 ret;
+
+       /* Not valid for this driver */
+       if (!ctx->teedev->desc->ops->supp_send)
+               return -EINVAL;
+
+       if (copy_from_user(&buf, ubuf, sizeof(buf)))
+               return -EFAULT;
+
+       if (buf.buf_len > TEE_MAX_ARG_SIZE ||
+           buf.buf_len < sizeof(struct tee_iocl_supp_send_arg))
+               return -EINVAL;
+
+       uarg = u64_to_user_ptr(buf.buf_ptr);
+       if (get_user(ret, &uarg->ret) ||
+           get_user(num_params, &uarg->num_params))
+               return -EFAULT;
+
+       if (sizeof(*uarg) + TEE_IOCTL_PARAM_SIZE(num_params) > buf.buf_len)
+               return -EINVAL;
+
+       params = kcalloc(num_params, sizeof(struct tee_param), GFP_KERNEL);
+       if (!params)
+               return -ENOMEM;
+
+       rc = params_from_supp(params, num_params, uarg->params);
+       if (rc)
+               goto out;
+
+       rc = ctx->teedev->desc->ops->supp_send(ctx, ret, num_params, params);
+out:
+       kfree(params);
+       return rc;
+}
+
+static long tee_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+       struct tee_context *ctx = filp->private_data;
+       void __user *uarg = (void __user *)arg;
+
+       switch (cmd) {
+       case TEE_IOC_VERSION:
+               return tee_ioctl_version(ctx, uarg);
+       case TEE_IOC_SHM_ALLOC:
+               return tee_ioctl_shm_alloc(ctx, uarg);
+       case TEE_IOC_OPEN_SESSION:
+               return tee_ioctl_open_session(ctx, uarg);
+       case TEE_IOC_INVOKE:
+               return tee_ioctl_invoke(ctx, uarg);
+       case TEE_IOC_CANCEL:
+               return tee_ioctl_cancel(ctx, uarg);
+       case TEE_IOC_CLOSE_SESSION:
+               return tee_ioctl_close_session(ctx, uarg);
+       case TEE_IOC_SUPPL_RECV:
+               return tee_ioctl_supp_recv(ctx, uarg);
+       case TEE_IOC_SUPPL_SEND:
+               return tee_ioctl_supp_send(ctx, uarg);
+       default:
+               return -EINVAL;
+       }
+}
+
+static const struct file_operations tee_fops = {
+       .owner = THIS_MODULE,
+       .open = tee_open,
+       .release = tee_release,
+       .unlocked_ioctl = tee_ioctl,
+       .compat_ioctl = tee_ioctl,
+};
+
+static void tee_release_device(struct device *dev)
+{
+       struct tee_device *teedev = container_of(dev, struct tee_device, dev);
+
+       spin_lock(&driver_lock);
+       clear_bit(teedev->id, dev_mask);
+       spin_unlock(&driver_lock);
+       mutex_destroy(&teedev->mutex);
+       idr_destroy(&teedev->idr);
+       kfree(teedev);
+}
+
+/**
+ * tee_device_alloc() - Allocate a new struct tee_device instance
+ * @teedesc:   Descriptor for this driver
+ * @dev:       Parent device for this device
+ * @pool:      Shared memory pool, NULL if not used
+ * @driver_data: Private driver data for this device
+ *
+ * Allocates a new struct tee_device instance. The device is
+ * removed by tee_device_unregister().
+ *
+ * @returns a pointer to a 'struct tee_device' or an ERR_PTR on failure
+ */
+struct tee_device *tee_device_alloc(const struct tee_desc *teedesc,
+                                   struct device *dev,
+                                   struct tee_shm_pool *pool,
+                                   void *driver_data)
+{
+       struct tee_device *teedev;
+       void *ret;
+       int rc;
+       int offs = 0;
+
+       if (!teedesc || !teedesc->name || !teedesc->ops ||
+           !teedesc->ops->get_version || !teedesc->ops->open ||
+           !teedesc->ops->release || !pool)
+               return ERR_PTR(-EINVAL);
+
+       teedev = kzalloc(sizeof(*teedev), GFP_KERNEL);
+       if (!teedev) {
+               ret = ERR_PTR(-ENOMEM);
+               goto err;
+       }
+
+       if (teedesc->flags & TEE_DESC_PRIVILEGED)
+               offs = TEE_NUM_DEVICES / 2;
+
+       spin_lock(&driver_lock);
+       teedev->id = find_next_zero_bit(dev_mask, TEE_NUM_DEVICES, offs);
+       if (teedev->id < TEE_NUM_DEVICES)
+               set_bit(teedev->id, dev_mask);
+       spin_unlock(&driver_lock);
+
+       if (teedev->id >= TEE_NUM_DEVICES) {
+               ret = ERR_PTR(-ENOMEM);
+               goto err;
+       }
+
+       snprintf(teedev->name, sizeof(teedev->name), "tee%s%d",
+                teedesc->flags & TEE_DESC_PRIVILEGED ? "priv" : "",
+                teedev->id - offs);
+
+       teedev->dev.class = tee_class;
+       teedev->dev.release = tee_release_device;
+       teedev->dev.parent = dev;
+
+       teedev->dev.devt = MKDEV(MAJOR(tee_devt), teedev->id);
+
+       rc = dev_set_name(&teedev->dev, "%s", teedev->name);
+       if (rc) {
+               ret = ERR_PTR(rc);
+               goto err_devt;
+       }
+
+       cdev_init(&teedev->cdev, &tee_fops);
+       teedev->cdev.owner = teedesc->owner;
+       teedev->cdev.kobj.parent = &teedev->dev.kobj;
+
+       dev_set_drvdata(&teedev->dev, driver_data);
+       device_initialize(&teedev->dev);
+
+       /* 1 as tee_device_unregister() does one final tee_device_put() */
+       teedev->num_users = 1;
+       init_completion(&teedev->c_no_users);
+       mutex_init(&teedev->mutex);
+       idr_init(&teedev->idr);
+
+       teedev->desc = teedesc;
+       teedev->pool = pool;
+
+       return teedev;
+err_devt:
+       unregister_chrdev_region(teedev->dev.devt, 1);
+err:
+       pr_err("could not register %s driver\n",
+              teedesc->flags & TEE_DESC_PRIVILEGED ? "privileged" : "client");
+       if (teedev && teedev->id < TEE_NUM_DEVICES) {
+               spin_lock(&driver_lock);
+               clear_bit(teedev->id, dev_mask);
+               spin_unlock(&driver_lock);
+       }
+       kfree(teedev);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(tee_device_alloc);
+
+static ssize_t implementation_id_show(struct device *dev,
+                                     struct device_attribute *attr, char *buf)
+{
+       struct tee_device *teedev = container_of(dev, struct tee_device, dev);
+       struct tee_ioctl_version_data vers;
+
+       teedev->desc->ops->get_version(teedev, &vers);
+       return scnprintf(buf, PAGE_SIZE, "%d\n", vers.impl_id);
+}
+static DEVICE_ATTR_RO(implementation_id);
+
+static struct attribute *tee_dev_attrs[] = {
+       &dev_attr_implementation_id.attr,
+       NULL
+};
+
+static const struct attribute_group tee_dev_group = {
+       .attrs = tee_dev_attrs,
+};
+
+/**
+ * tee_device_register() - Registers a TEE device
+ * @teedev:    Device to register
+ *
+ * tee_device_unregister() need to be called to remove the @teedev if
+ * this function fails.
+ *
+ * @returns < 0 on failure
+ */
+int tee_device_register(struct tee_device *teedev)
+{
+       int rc;
+
+       if (teedev->flags & TEE_DEVICE_FLAG_REGISTERED) {
+               dev_err(&teedev->dev, "attempt to register twice\n");
+               return -EINVAL;
+       }
+
+       rc = cdev_add(&teedev->cdev, teedev->dev.devt, 1);
+       if (rc) {
+               dev_err(&teedev->dev,
+                       "unable to cdev_add() %s, major %d, minor %d, err=%d\n",
+                       teedev->name, MAJOR(teedev->dev.devt),
+                       MINOR(teedev->dev.devt), rc);
+               return rc;
+       }
+
+       rc = device_add(&teedev->dev);
+       if (rc) {
+               dev_err(&teedev->dev,
+                       "unable to device_add() %s, major %d, minor %d, err=%d\n",
+                       teedev->name, MAJOR(teedev->dev.devt),
+                       MINOR(teedev->dev.devt), rc);
+               goto err_device_add;
+       }
+
+       rc = sysfs_create_group(&teedev->dev.kobj, &tee_dev_group);
+       if (rc) {
+               dev_err(&teedev->dev,
+                       "failed to create sysfs attributes, err=%d\n", rc);
+               goto err_sysfs_create_group;
+       }
+
+       teedev->flags |= TEE_DEVICE_FLAG_REGISTERED;
+       return 0;
+
+err_sysfs_create_group:
+       device_del(&teedev->dev);
+err_device_add:
+       cdev_del(&teedev->cdev);
+       return rc;
+}
+EXPORT_SYMBOL_GPL(tee_device_register);
+
+void tee_device_put(struct tee_device *teedev)
+{
+       mutex_lock(&teedev->mutex);
+       /* Shouldn't put in this state */
+       if (!WARN_ON(!teedev->desc)) {
+               teedev->num_users--;
+               if (!teedev->num_users) {
+                       teedev->desc = NULL;
+                       complete(&teedev->c_no_users);
+               }
+       }
+       mutex_unlock(&teedev->mutex);
+}
+
+bool tee_device_get(struct tee_device *teedev)
+{
+       mutex_lock(&teedev->mutex);
+       if (!teedev->desc) {
+               mutex_unlock(&teedev->mutex);
+               return false;
+       }
+       teedev->num_users++;
+       mutex_unlock(&teedev->mutex);
+       return true;
+}
+
+/**
+ * tee_device_unregister() - Removes a TEE device
+ * @teedev:    Device to unregister
+ *
+ * This function should be called to remove the @teedev even if
+ * tee_device_register() hasn't been called yet. Does nothing if
+ * @teedev is NULL.
+ */
+void tee_device_unregister(struct tee_device *teedev)
+{
+       if (!teedev)
+               return;
+
+       if (teedev->flags & TEE_DEVICE_FLAG_REGISTERED) {
+               sysfs_remove_group(&teedev->dev.kobj, &tee_dev_group);
+               cdev_del(&teedev->cdev);
+               device_del(&teedev->dev);
+       }
+
+       tee_device_put(teedev);
+       wait_for_completion(&teedev->c_no_users);
+
+       /*
+        * No need to take a mutex any longer now since teedev->desc was
+        * set to NULL before teedev->c_no_users was completed.
+        */
+
+       teedev->pool = NULL;
+
+       put_device(&teedev->dev);
+}
+EXPORT_SYMBOL_GPL(tee_device_unregister);
+
+/**
+ * tee_get_drvdata() - Return driver_data pointer
+ * @teedev:    Device containing the driver_data pointer
+ * @returns the driver_data pointer supplied to tee_register().
+ */
+void *tee_get_drvdata(struct tee_device *teedev)
+{
+       return dev_get_drvdata(&teedev->dev);
+}
+EXPORT_SYMBOL_GPL(tee_get_drvdata);
+
+static int __init tee_init(void)
+{
+       int rc;
+
+       tee_class = class_create(THIS_MODULE, "tee");
+       if (IS_ERR(tee_class)) {
+               pr_err("couldn't create class\n");
+               return PTR_ERR(tee_class);
+       }
+
+       rc = alloc_chrdev_region(&tee_devt, 0, TEE_NUM_DEVICES, "tee");
+       if (rc) {
+               pr_err("failed to allocate char dev region\n");
+               class_destroy(tee_class);
+               tee_class = NULL;
+       }
+
+       return rc;
+}
+
+static void __exit tee_exit(void)
+{
+       class_destroy(tee_class);
+       tee_class = NULL;
+       unregister_chrdev_region(tee_devt, TEE_NUM_DEVICES);
+}
+
+subsys_initcall(tee_init);
+module_exit(tee_exit);
+
+MODULE_AUTHOR("Linaro");
+MODULE_DESCRIPTION("TEE Driver");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/tee/tee_private.h b/drivers/tee/tee_private.h
new file mode 100644 (file)
index 0000000..21cb6be
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2015-2016, Linaro Limited
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#ifndef TEE_PRIVATE_H
+#define TEE_PRIVATE_H
+
+#include <linux/cdev.h>
+#include <linux/completion.h>
+#include <linux/device.h>
+#include <linux/kref.h>
+#include <linux/mutex.h>
+#include <linux/types.h>
+
+struct tee_device;
+
+/**
+ * struct tee_shm - shared memory object
+ * @teedev:    device used to allocate the object
+ * @ctx:       context using the object, if NULL the context is gone
+ * @link       link element
+ * @paddr:     physical address of the shared memory
+ * @kaddr:     virtual address of the shared memory
+ * @size:      size of shared memory
+ * @dmabuf:    dmabuf used to for exporting to user space
+ * @flags:     defined by TEE_SHM_* in tee_drv.h
+ * @id:                unique id of a shared memory object on this device
+ */
+struct tee_shm {
+       struct tee_device *teedev;
+       struct tee_context *ctx;
+       struct list_head link;
+       phys_addr_t paddr;
+       void *kaddr;
+       size_t size;
+       struct dma_buf *dmabuf;
+       u32 flags;
+       int id;
+};
+
+struct tee_shm_pool_mgr;
+
+/**
+ * struct tee_shm_pool_mgr_ops - shared memory pool manager operations
+ * @alloc:     called when allocating shared memory
+ * @free:      called when freeing shared memory
+ */
+struct tee_shm_pool_mgr_ops {
+       int (*alloc)(struct tee_shm_pool_mgr *poolmgr, struct tee_shm *shm,
+                    size_t size);
+       void (*free)(struct tee_shm_pool_mgr *poolmgr, struct tee_shm *shm);
+};
+
+/**
+ * struct tee_shm_pool_mgr - shared memory manager
+ * @ops:               operations
+ * @private_data:      private data for the shared memory manager
+ */
+struct tee_shm_pool_mgr {
+       const struct tee_shm_pool_mgr_ops *ops;
+       void *private_data;
+};
+
+/**
+ * struct tee_shm_pool - shared memory pool
+ * @private_mgr:       pool manager for shared memory only between kernel
+ *                     and secure world
+ * @dma_buf_mgr:       pool manager for shared memory exported to user space
+ * @destroy:           called when destroying the pool
+ * @private_data:      private data for the pool
+ */
+struct tee_shm_pool {
+       struct tee_shm_pool_mgr private_mgr;
+       struct tee_shm_pool_mgr dma_buf_mgr;
+       void (*destroy)(struct tee_shm_pool *pool);
+       void *private_data;
+};
+
+#define TEE_DEVICE_FLAG_REGISTERED     0x1
+#define TEE_MAX_DEV_NAME_LEN           32
+
+/**
+ * struct tee_device - TEE Device representation
+ * @name:      name of device
+ * @desc:      description of device
+ * @id:                unique id of device
+ * @flags:     represented by TEE_DEVICE_FLAG_REGISTERED above
+ * @dev:       embedded basic device structure
+ * @cdev:      embedded cdev
+ * @num_users: number of active users of this device
+ * @c_no_user: completion used when unregistering the device
+ * @mutex:     mutex protecting @num_users and @idr
+ * @idr:       register of shared memory object allocated on this device
+ * @pool:      shared memory pool
+ */
+struct tee_device {
+       char name[TEE_MAX_DEV_NAME_LEN];
+       const struct tee_desc *desc;
+       int id;
+       unsigned int flags;
+
+       struct device dev;
+       struct cdev cdev;
+
+       size_t num_users;
+       struct completion c_no_users;
+       struct mutex mutex;     /* protects num_users and idr */
+
+       struct idr idr;
+       struct tee_shm_pool *pool;
+};
+
+int tee_shm_init(void);
+
+int tee_shm_get_fd(struct tee_shm *shm);
+
+bool tee_device_get(struct tee_device *teedev);
+void tee_device_put(struct tee_device *teedev);
+
+#endif /*TEE_PRIVATE_H*/
diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
new file mode 100644 (file)
index 0000000..d356d7f
--- /dev/null
@@ -0,0 +1,358 @@
+/*
+ * Copyright (c) 2015-2016, Linaro Limited
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/device.h>
+#include <linux/dma-buf.h>
+#include <linux/fdtable.h>
+#include <linux/idr.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/tee_drv.h>
+#include "tee_private.h"
+
+static void tee_shm_release(struct tee_shm *shm)
+{
+       struct tee_device *teedev = shm->teedev;
+       struct tee_shm_pool_mgr *poolm;
+
+       mutex_lock(&teedev->mutex);
+       idr_remove(&teedev->idr, shm->id);
+       if (shm->ctx)
+               list_del(&shm->link);
+       mutex_unlock(&teedev->mutex);
+
+       if (shm->flags & TEE_SHM_DMA_BUF)
+               poolm = &teedev->pool->dma_buf_mgr;
+       else
+               poolm = &teedev->pool->private_mgr;
+
+       poolm->ops->free(poolm, shm);
+       kfree(shm);
+
+       tee_device_put(teedev);
+}
+
+static struct sg_table *tee_shm_op_map_dma_buf(struct dma_buf_attachment
+                       *attach, enum dma_data_direction dir)
+{
+       return NULL;
+}
+
+static void tee_shm_op_unmap_dma_buf(struct dma_buf_attachment *attach,
+                                    struct sg_table *table,
+                                    enum dma_data_direction dir)
+{
+}
+
+static void tee_shm_op_release(struct dma_buf *dmabuf)
+{
+       struct tee_shm *shm = dmabuf->priv;
+
+       tee_shm_release(shm);
+}
+
+static void *tee_shm_op_map_atomic(struct dma_buf *dmabuf, unsigned long pgnum)
+{
+       return NULL;
+}
+
+static void *tee_shm_op_map(struct dma_buf *dmabuf, unsigned long pgnum)
+{
+       return NULL;
+}
+
+static int tee_shm_op_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma)
+{
+       struct tee_shm *shm = dmabuf->priv;
+       size_t size = vma->vm_end - vma->vm_start;
+
+       return remap_pfn_range(vma, vma->vm_start, shm->paddr >> PAGE_SHIFT,
+                              size, vma->vm_page_prot);
+}
+
+static struct dma_buf_ops tee_shm_dma_buf_ops = {
+       .map_dma_buf = tee_shm_op_map_dma_buf,
+       .unmap_dma_buf = tee_shm_op_unmap_dma_buf,
+       .release = tee_shm_op_release,
+       .map_atomic = tee_shm_op_map_atomic,
+       .map = tee_shm_op_map,
+       .mmap = tee_shm_op_mmap,
+};
+
+/**
+ * tee_shm_alloc() - Allocate shared memory
+ * @ctx:       Context that allocates the shared memory
+ * @size:      Requested size of shared memory
+ * @flags:     Flags setting properties for the requested shared memory.
+ *
+ * Memory allocated as global shared memory is automatically freed when the
+ * TEE file pointer is closed. The @flags field uses the bits defined by
+ * TEE_SHM_* in <linux/tee_drv.h>. TEE_SHM_MAPPED must currently always be
+ * set. If TEE_SHM_DMA_BUF global shared memory will be allocated and
+ * associated with a dma-buf handle, else driver private memory.
+ */
+struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
+{
+       struct tee_device *teedev = ctx->teedev;
+       struct tee_shm_pool_mgr *poolm = NULL;
+       struct tee_shm *shm;
+       void *ret;
+       int rc;
+
+       if (!(flags & TEE_SHM_MAPPED)) {
+               dev_err(teedev->dev.parent,
+                       "only mapped allocations supported\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       if ((flags & ~(TEE_SHM_MAPPED | TEE_SHM_DMA_BUF))) {
+               dev_err(teedev->dev.parent, "invalid shm flags 0x%x", flags);
+               return ERR_PTR(-EINVAL);
+       }
+
+       if (!tee_device_get(teedev))
+               return ERR_PTR(-EINVAL);
+
+       if (!teedev->pool) {
+               /* teedev has been detached from driver */
+               ret = ERR_PTR(-EINVAL);
+               goto err_dev_put;
+       }
+
+       shm = kzalloc(sizeof(*shm), GFP_KERNEL);
+       if (!shm) {
+               ret = ERR_PTR(-ENOMEM);
+               goto err_dev_put;
+       }
+
+       shm->flags = flags;
+       shm->teedev = teedev;
+       shm->ctx = ctx;
+       if (flags & TEE_SHM_DMA_BUF)
+               poolm = &teedev->pool->dma_buf_mgr;
+       else
+               poolm = &teedev->pool->private_mgr;
+
+       rc = poolm->ops->alloc(poolm, shm, size);
+       if (rc) {
+               ret = ERR_PTR(rc);
+               goto err_kfree;
+       }
+
+       mutex_lock(&teedev->mutex);
+       shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL);
+       mutex_unlock(&teedev->mutex);
+       if (shm->id < 0) {
+               ret = ERR_PTR(shm->id);
+               goto err_pool_free;
+       }
+
+       if (flags & TEE_SHM_DMA_BUF) {
+               DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
+
+               exp_info.ops = &tee_shm_dma_buf_ops;
+               exp_info.size = shm->size;
+               exp_info.flags = O_RDWR;
+               exp_info.priv = shm;
+
+               shm->dmabuf = dma_buf_export(&exp_info);
+               if (IS_ERR(shm->dmabuf)) {
+                       ret = ERR_CAST(shm->dmabuf);
+                       goto err_rem;
+               }
+       }
+       mutex_lock(&teedev->mutex);
+       list_add_tail(&shm->link, &ctx->list_shm);
+       mutex_unlock(&teedev->mutex);
+
+       return shm;
+err_rem:
+       mutex_lock(&teedev->mutex);
+       idr_remove(&teedev->idr, shm->id);
+       mutex_unlock(&teedev->mutex);
+err_pool_free:
+       poolm->ops->free(poolm, shm);
+err_kfree:
+       kfree(shm);
+err_dev_put:
+       tee_device_put(teedev);
+       return ret;
+}
+EXPORT_SYMBOL_GPL(tee_shm_alloc);
+
+/**
+ * tee_shm_get_fd() - Increase reference count and return file descriptor
+ * @shm:       Shared memory handle
+ * @returns user space file descriptor to shared memory
+ */
+int tee_shm_get_fd(struct tee_shm *shm)
+{
+       u32 req_flags = TEE_SHM_MAPPED | TEE_SHM_DMA_BUF;
+       int fd;
+
+       if ((shm->flags & req_flags) != req_flags)
+               return -EINVAL;
+
+       fd = dma_buf_fd(shm->dmabuf, O_CLOEXEC);
+       if (fd >= 0)
+               get_dma_buf(shm->dmabuf);
+       return fd;
+}
+
+/**
+ * tee_shm_free() - Free shared memory
+ * @shm:       Handle to shared memory to free
+ */
+void tee_shm_free(struct tee_shm *shm)
+{
+       /*
+        * dma_buf_put() decreases the dmabuf reference counter and will
+        * call tee_shm_release() when the last reference is gone.
+        *
+        * In the case of driver private memory we call tee_shm_release
+        * directly instead as it doesn't have a reference counter.
+        */
+       if (shm->flags & TEE_SHM_DMA_BUF)
+               dma_buf_put(shm->dmabuf);
+       else
+               tee_shm_release(shm);
+}
+EXPORT_SYMBOL_GPL(tee_shm_free);
+
+/**
+ * tee_shm_va2pa() - Get physical address of a virtual address
+ * @shm:       Shared memory handle
+ * @va:                Virtual address to tranlsate
+ * @pa:                Returned physical address
+ * @returns 0 on success and < 0 on failure
+ */
+int tee_shm_va2pa(struct tee_shm *shm, void *va, phys_addr_t *pa)
+{
+       /* Check that we're in the range of the shm */
+       if ((char *)va < (char *)shm->kaddr)
+               return -EINVAL;
+       if ((char *)va >= ((char *)shm->kaddr + shm->size))
+               return -EINVAL;
+
+       return tee_shm_get_pa(
+                       shm, (unsigned long)va - (unsigned long)shm->kaddr, pa);
+}
+EXPORT_SYMBOL_GPL(tee_shm_va2pa);
+
+/**
+ * tee_shm_pa2va() - Get virtual address of a physical address
+ * @shm:       Shared memory handle
+ * @pa:                Physical address to tranlsate
+ * @va:                Returned virtual address
+ * @returns 0 on success and < 0 on failure
+ */
+int tee_shm_pa2va(struct tee_shm *shm, phys_addr_t pa, void **va)
+{
+       /* Check that we're in the range of the shm */
+       if (pa < shm->paddr)
+               return -EINVAL;
+       if (pa >= (shm->paddr + shm->size))
+               return -EINVAL;
+
+       if (va) {
+               void *v = tee_shm_get_va(shm, pa - shm->paddr);
+
+               if (IS_ERR(v))
+                       return PTR_ERR(v);
+               *va = v;
+       }
+       return 0;
+}
+EXPORT_SYMBOL_GPL(tee_shm_pa2va);
+
+/**
+ * tee_shm_get_va() - Get virtual address of a shared memory plus an offset
+ * @shm:       Shared memory handle
+ * @offs:      Offset from start of this shared memory
+ * @returns virtual address of the shared memory + offs if offs is within
+ *     the bounds of this shared memory, else an ERR_PTR
+ */
+void *tee_shm_get_va(struct tee_shm *shm, size_t offs)
+{
+       if (offs >= shm->size)
+               return ERR_PTR(-EINVAL);
+       return (char *)shm->kaddr + offs;
+}
+EXPORT_SYMBOL_GPL(tee_shm_get_va);
+
+/**
+ * tee_shm_get_pa() - Get physical address of a shared memory plus an offset
+ * @shm:       Shared memory handle
+ * @offs:      Offset from start of this shared memory
+ * @pa:                Physical address to return
+ * @returns 0 if offs is within the bounds of this shared memory, else an
+ *     error code.
+ */
+int tee_shm_get_pa(struct tee_shm *shm, size_t offs, phys_addr_t *pa)
+{
+       if (offs >= shm->size)
+               return -EINVAL;
+       if (pa)
+               *pa = shm->paddr + offs;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(tee_shm_get_pa);
+
+/**
+ * tee_shm_get_from_id() - Find shared memory object and increase reference
+ * count
+ * @ctx:       Context owning the shared memory
+ * @id:                Id of shared memory object
+ * @returns a pointer to 'struct tee_shm' on success or an ERR_PTR on failure
+ */
+struct tee_shm *tee_shm_get_from_id(struct tee_context *ctx, int id)
+{
+       struct tee_device *teedev;
+       struct tee_shm *shm;
+
+       if (!ctx)
+               return ERR_PTR(-EINVAL);
+
+       teedev = ctx->teedev;
+       mutex_lock(&teedev->mutex);
+       shm = idr_find(&teedev->idr, id);
+       if (!shm || shm->ctx != ctx)
+               shm = ERR_PTR(-EINVAL);
+       else if (shm->flags & TEE_SHM_DMA_BUF)
+               get_dma_buf(shm->dmabuf);
+       mutex_unlock(&teedev->mutex);
+       return shm;
+}
+EXPORT_SYMBOL_GPL(tee_shm_get_from_id);
+
+/**
+ * tee_shm_get_id() - Get id of a shared memory object
+ * @shm:       Shared memory handle
+ * @returns id
+ */
+int tee_shm_get_id(struct tee_shm *shm)
+{
+       return shm->id;
+}
+EXPORT_SYMBOL_GPL(tee_shm_get_id);
+
+/**
+ * tee_shm_put() - Decrease reference count on a shared memory handle
+ * @shm:       Shared memory handle
+ */
+void tee_shm_put(struct tee_shm *shm)
+{
+       if (shm->flags & TEE_SHM_DMA_BUF)
+               dma_buf_put(shm->dmabuf);
+}
+EXPORT_SYMBOL_GPL(tee_shm_put);
diff --git a/drivers/tee/tee_shm_pool.c b/drivers/tee/tee_shm_pool.c
new file mode 100644 (file)
index 0000000..fb4f852
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2015, Linaro Limited
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <linux/device.h>
+#include <linux/dma-buf.h>
+#include <linux/genalloc.h>
+#include <linux/slab.h>
+#include <linux/tee_drv.h>
+#include "tee_private.h"
+
+static int pool_op_gen_alloc(struct tee_shm_pool_mgr *poolm,
+                            struct tee_shm *shm, size_t size)
+{
+       unsigned long va;
+       struct gen_pool *genpool = poolm->private_data;
+       size_t s = roundup(size, 1 << genpool->min_alloc_order);
+
+       va = gen_pool_alloc(genpool, s);
+       if (!va)
+               return -ENOMEM;
+
+       memset((void *)va, 0, s);
+       shm->kaddr = (void *)va;
+       shm->paddr = gen_pool_virt_to_phys(genpool, va);
+       shm->size = s;
+       return 0;
+}
+
+static void pool_op_gen_free(struct tee_shm_pool_mgr *poolm,
+                            struct tee_shm *shm)
+{
+       gen_pool_free(poolm->private_data, (unsigned long)shm->kaddr,
+                     shm->size);
+       shm->kaddr = NULL;
+}
+
+static const struct tee_shm_pool_mgr_ops pool_ops_generic = {
+       .alloc = pool_op_gen_alloc,
+       .free = pool_op_gen_free,
+};
+
+static void pool_res_mem_destroy(struct tee_shm_pool *pool)
+{
+       gen_pool_destroy(pool->private_mgr.private_data);
+       gen_pool_destroy(pool->dma_buf_mgr.private_data);
+}
+
+static int pool_res_mem_mgr_init(struct tee_shm_pool_mgr *mgr,
+                                struct tee_shm_pool_mem_info *info,
+                                int min_alloc_order)
+{
+       size_t page_mask = PAGE_SIZE - 1;
+       struct gen_pool *genpool = NULL;
+       int rc;
+
+       /*
+        * Start and end must be page aligned
+        */
+       if ((info->vaddr & page_mask) || (info->paddr & page_mask) ||
+           (info->size & page_mask))
+               return -EINVAL;
+
+       genpool = gen_pool_create(min_alloc_order, -1);
+       if (!genpool)
+               return -ENOMEM;
+
+       gen_pool_set_algo(genpool, gen_pool_best_fit, NULL);
+       rc = gen_pool_add_virt(genpool, info->vaddr, info->paddr, info->size,
+                              -1);
+       if (rc) {
+               gen_pool_destroy(genpool);
+               return rc;
+       }
+
+       mgr->private_data = genpool;
+       mgr->ops = &pool_ops_generic;
+       return 0;
+}
+
+/**
+ * tee_shm_pool_alloc_res_mem() - Create a shared memory pool from reserved
+ * memory range
+ * @priv_info: Information for driver private shared memory pool
+ * @dmabuf_info: Information for dma-buf shared memory pool
+ *
+ * Start and end of pools will must be page aligned.
+ *
+ * Allocation with the flag TEE_SHM_DMA_BUF set will use the range supplied
+ * in @dmabuf, others will use the range provided by @priv.
+ *
+ * @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure.
+ */
+struct tee_shm_pool *
+tee_shm_pool_alloc_res_mem(struct tee_shm_pool_mem_info *priv_info,
+                          struct tee_shm_pool_mem_info *dmabuf_info)
+{
+       struct tee_shm_pool *pool = NULL;
+       int ret;
+
+       pool = kzalloc(sizeof(*pool), GFP_KERNEL);
+       if (!pool) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       /*
+        * Create the pool for driver private shared memory
+        */
+       ret = pool_res_mem_mgr_init(&pool->private_mgr, priv_info,
+                                   3 /* 8 byte aligned */);
+       if (ret)
+               goto err;
+
+       /*
+        * Create the pool for dma_buf shared memory
+        */
+       ret = pool_res_mem_mgr_init(&pool->dma_buf_mgr, dmabuf_info,
+                                   PAGE_SHIFT);
+       if (ret)
+               goto err;
+
+       pool->destroy = pool_res_mem_destroy;
+       return pool;
+err:
+       if (ret == -ENOMEM)
+               pr_err("%s: can't allocate memory for res_mem shared memory pool\n", __func__);
+       if (pool && pool->private_mgr.private_data)
+               gen_pool_destroy(pool->private_mgr.private_data);
+       kfree(pool);
+       return ERR_PTR(ret);
+}
+EXPORT_SYMBOL_GPL(tee_shm_pool_alloc_res_mem);
+
+/**
+ * tee_shm_pool_free() - Free a shared memory pool
+ * @pool:      The shared memory pool to free
+ *
+ * There must be no remaining shared memory allocated from this pool when
+ * this function is called.
+ */
+void tee_shm_pool_free(struct tee_shm_pool *pool)
+{
+       pool->destroy(pool);
+       kfree(pool);
+}
+EXPORT_SYMBOL_GPL(tee_shm_pool_free);
index 6871ecc5b9512553368920272910f69c6493ecdd..b5b5facb87473e4de8c30fa29a105251965cd027 100644 (file)
@@ -15,6 +15,23 @@ menuconfig THERMAL
 
 if THERMAL
 
+config THERMAL_EMERGENCY_POWEROFF_DELAY_MS
+       int "Emergency poweroff delay in milli-seconds"
+       depends on THERMAL
+       default 0
+       help
+         Thermal subsystem will issue a graceful shutdown when
+         critical temperatures are reached using orderly_poweroff(). In
+         case of failure of an orderly_poweroff(), the thermal emergency
+         poweroff kicks in after a delay has elapsed and shuts down the system.
+         This config is number of milliseconds to delay before emergency
+         poweroff kicks in. Similarly to the critical trip point,
+         the delay should be carefully profiled so as to give adequate
+         time for orderly_poweroff() to finish on regular execution.
+         If set to 0 emergency poweroff will not be supported.
+
+         In doubt, leave as 0.
+
 config THERMAL_HWMON
        bool
        prompt "Expose thermal sensors as hwmon device"
@@ -291,6 +308,16 @@ config ARMADA_THERMAL
          Enable this option if you want to have support for thermal management
          controller present in Armada 370 and Armada XP SoC.
 
+config DA9062_THERMAL
+       tristate "DA9062/DA9061 Dialog Semiconductor thermal driver"
+       depends on MFD_DA9062 || COMPILE_TEST
+       depends on OF
+       help
+         Enable this for the Dialog Semiconductor thermal sensor driver.
+         This will report PMIC junction over-temperature for one thermal trip
+         zone.
+         Compatible with the DA9062 and DA9061 PMICs.
+
 config INTEL_POWERCLAMP
        tristate "Intel PowerClamp idle injection driver"
        depends on THERMAL
@@ -380,6 +407,11 @@ config MTK_THERMAL
          Enable this option if you want to have support for thermal management
          controller present in Mediatek SoCs
 
+menu "Broadcom thermal drivers"
+depends on ARCH_BCM || COMPILE_TEST
+source "drivers/thermal/broadcom/Kconfig"
+endmenu
+
 menu "Texas Instruments thermal drivers"
 depends on ARCH_HAS_BANDGAP || COMPILE_TEST
 depends on HAS_IOMEM
index c2372f10dae5f23a1113cdd87c5da6cdc711ae12..094d7039981ca3eb2371562c16393fa35e19bd10 100644 (file)
@@ -27,6 +27,7 @@ thermal_sys-$(CONFIG_CLOCK_THERMAL)   += clock_cooling.o
 thermal_sys-$(CONFIG_DEVFREQ_THERMAL) += devfreq_cooling.o
 
 # platform thermal drivers
+obj-y                          += broadcom/
 obj-$(CONFIG_QCOM_SPMI_TEMP_ALARM)     += qcom-spmi-temp-alarm.o
 obj-$(CONFIG_SPEAR_THERMAL)    += spear_thermal.o
 obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o
@@ -41,6 +42,7 @@ obj-$(CONFIG_TANGO_THERMAL)   += tango_thermal.o
 obj-$(CONFIG_IMX_THERMAL)      += imx_thermal.o
 obj-$(CONFIG_MAX77620_THERMAL) += max77620_thermal.o
 obj-$(CONFIG_QORIQ_THERMAL)    += qoriq_thermal.o
+obj-$(CONFIG_DA9062_THERMAL)   += da9062-thermal.o
 obj-$(CONFIG_INTEL_POWERCLAMP) += intel_powerclamp.o
 obj-$(CONFIG_X86_PKG_TEMP_THERMAL)     += x86_pkg_temp_thermal.o
 obj-$(CONFIG_INTEL_SOC_DTS_IOSF_CORE)  += intel_soc_dts_iosf.o
diff --git a/drivers/thermal/broadcom/Kconfig b/drivers/thermal/broadcom/Kconfig
new file mode 100644 (file)
index 0000000..ab08af4
--- /dev/null
@@ -0,0 +1,16 @@
+config BCM2835_THERMAL
+       tristate "Thermal sensors on bcm2835 SoC"
+       depends on ARCH_BCM2835 || COMPILE_TEST
+       depends on HAS_IOMEM
+       depends on THERMAL_OF
+       help
+         Support for thermal sensors on Broadcom bcm2835 SoCs.
+
+config BCM_NS_THERMAL
+       tristate "Northstar thermal driver"
+       depends on ARCH_BCM_IPROC || COMPILE_TEST
+       help
+         Northstar is a family of SoCs that includes e.g. BCM4708, BCM47081,
+         BCM4709 and BCM47094. It contains DMU (Device Management Unit) block
+         with a thermal sensor that allows checking CPU temperature. This
+         driver provides support for it.
diff --git a/drivers/thermal/broadcom/Makefile b/drivers/thermal/broadcom/Makefile
new file mode 100644 (file)
index 0000000..c6f62e4
--- /dev/null
@@ -0,0 +1,2 @@
+obj-$(CONFIG_BCM2835_THERMAL)          += bcm2835_thermal.o
+obj-$(CONFIG_BCM_NS_THERMAL)           += ns-thermal.o
diff --git a/drivers/thermal/broadcom/bcm2835_thermal.c b/drivers/thermal/broadcom/bcm2835_thermal.c
new file mode 100644 (file)
index 0000000..0ecf808
--- /dev/null
@@ -0,0 +1,314 @@
+/*
+ * Driver for Broadcom BCM2835 SoC temperature sensor
+ *
+ * Copyright (C) 2016 Martin Sperl
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/thermal.h>
+
+#define BCM2835_TS_TSENSCTL                    0x00
+#define BCM2835_TS_TSENSSTAT                   0x04
+
+#define BCM2835_TS_TSENSCTL_PRWDW              BIT(0)
+#define BCM2835_TS_TSENSCTL_RSTB               BIT(1)
+
+/*
+ * bandgap reference voltage in 6 mV increments
+ * 000b = 1178 mV, 001b = 1184 mV, ... 111b = 1220 mV
+ */
+#define BCM2835_TS_TSENSCTL_CTRL_BITS          3
+#define BCM2835_TS_TSENSCTL_CTRL_SHIFT         2
+#define BCM2835_TS_TSENSCTL_CTRL_MASK              \
+       GENMASK(BCM2835_TS_TSENSCTL_CTRL_BITS +     \
+               BCM2835_TS_TSENSCTL_CTRL_SHIFT - 1, \
+               BCM2835_TS_TSENSCTL_CTRL_SHIFT)
+#define BCM2835_TS_TSENSCTL_CTRL_DEFAULT       1
+#define BCM2835_TS_TSENSCTL_EN_INT             BIT(5)
+#define BCM2835_TS_TSENSCTL_DIRECT             BIT(6)
+#define BCM2835_TS_TSENSCTL_CLR_INT            BIT(7)
+#define BCM2835_TS_TSENSCTL_THOLD_SHIFT                8
+#define BCM2835_TS_TSENSCTL_THOLD_BITS         10
+#define BCM2835_TS_TSENSCTL_THOLD_MASK              \
+       GENMASK(BCM2835_TS_TSENSCTL_THOLD_BITS +     \
+               BCM2835_TS_TSENSCTL_THOLD_SHIFT - 1, \
+               BCM2835_TS_TSENSCTL_THOLD_SHIFT)
+/*
+ * time how long the block to be asserted in reset
+ * which based on a clock counter (TSENS clock assumed)
+ */
+#define BCM2835_TS_TSENSCTL_RSTDELAY_SHIFT     18
+#define BCM2835_TS_TSENSCTL_RSTDELAY_BITS      8
+#define BCM2835_TS_TSENSCTL_REGULEN            BIT(26)
+
+#define BCM2835_TS_TSENSSTAT_DATA_BITS         10
+#define BCM2835_TS_TSENSSTAT_DATA_SHIFT                0
+#define BCM2835_TS_TSENSSTAT_DATA_MASK              \
+       GENMASK(BCM2835_TS_TSENSSTAT_DATA_BITS +     \
+               BCM2835_TS_TSENSSTAT_DATA_SHIFT - 1, \
+               BCM2835_TS_TSENSSTAT_DATA_SHIFT)
+#define BCM2835_TS_TSENSSTAT_VALID             BIT(10)
+#define BCM2835_TS_TSENSSTAT_INTERRUPT         BIT(11)
+
+struct bcm2835_thermal_data {
+       struct thermal_zone_device *tz;
+       void __iomem *regs;
+       struct clk *clk;
+       struct dentry *debugfsdir;
+};
+
+static int bcm2835_thermal_adc2temp(u32 adc, int offset, int slope)
+{
+       return offset + slope * adc;
+}
+
+static int bcm2835_thermal_temp2adc(int temp, int offset, int slope)
+{
+       temp -= offset;
+       temp /= slope;
+
+       if (temp < 0)
+               temp = 0;
+       if (temp >= BIT(BCM2835_TS_TSENSSTAT_DATA_BITS))
+               temp = BIT(BCM2835_TS_TSENSSTAT_DATA_BITS) - 1;
+
+       return temp;
+}
+
+static int bcm2835_thermal_get_temp(void *d, int *temp)
+{
+       struct bcm2835_thermal_data *data = d;
+       u32 val = readl(data->regs + BCM2835_TS_TSENSSTAT);
+
+       if (!(val & BCM2835_TS_TSENSSTAT_VALID))
+               return -EIO;
+
+       val &= BCM2835_TS_TSENSSTAT_DATA_MASK;
+
+       *temp = bcm2835_thermal_adc2temp(
+               val,
+               thermal_zone_get_offset(data->tz),
+               thermal_zone_get_slope(data->tz));
+
+       return 0;
+}
+
+static const struct debugfs_reg32 bcm2835_thermal_regs[] = {
+       {
+               .name = "ctl",
+               .offset = 0
+       },
+       {
+               .name = "stat",
+               .offset = 4
+       }
+};
+
+static void bcm2835_thermal_debugfs(struct platform_device *pdev)
+{
+       struct thermal_zone_device *tz = platform_get_drvdata(pdev);
+       struct bcm2835_thermal_data *data = tz->devdata;
+       struct debugfs_regset32 *regset;
+
+       data->debugfsdir = debugfs_create_dir("bcm2835_thermal", NULL);
+       if (!data->debugfsdir)
+               return;
+
+       regset = devm_kzalloc(&pdev->dev, sizeof(*regset), GFP_KERNEL);
+       if (!regset)
+               return;
+
+       regset->regs = bcm2835_thermal_regs;
+       regset->nregs = ARRAY_SIZE(bcm2835_thermal_regs);
+       regset->base = data->regs;
+
+       debugfs_create_regset32("regset", 0444, data->debugfsdir, regset);
+}
+
+static struct thermal_zone_of_device_ops bcm2835_thermal_ops = {
+       .get_temp = bcm2835_thermal_get_temp,
+};
+
+/*
+ * Note: as per Raspberry Foundation FAQ
+ * (https://www.raspberrypi.org/help/faqs/#performanceOperatingTemperature)
+ * the recommended temperature range for the SoC -40C to +85C
+ * so the trip limit is set to 80C.
+ * this applies to all the BCM283X SoC
+ */
+
+static const struct of_device_id bcm2835_thermal_of_match_table[] = {
+       {
+               .compatible = "brcm,bcm2835-thermal",
+       },
+       {
+               .compatible = "brcm,bcm2836-thermal",
+       },
+       {
+               .compatible = "brcm,bcm2837-thermal",
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(of, bcm2835_thermal_of_match_table);
+
+static int bcm2835_thermal_probe(struct platform_device *pdev)
+{
+       const struct of_device_id *match;
+       struct thermal_zone_device *tz;
+       struct bcm2835_thermal_data *data;
+       struct resource *res;
+       int err = 0;
+       u32 val;
+       unsigned long rate;
+
+       data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       match = of_match_device(bcm2835_thermal_of_match_table,
+                               &pdev->dev);
+       if (!match)
+               return -EINVAL;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       data->regs = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(data->regs)) {
+               err = PTR_ERR(data->regs);
+               dev_err(&pdev->dev, "Could not get registers: %d\n", err);
+               return err;
+       }
+
+       data->clk = devm_clk_get(&pdev->dev, NULL);
+       if (IS_ERR(data->clk)) {
+               err = PTR_ERR(data->clk);
+               if (err != -EPROBE_DEFER)
+                       dev_err(&pdev->dev, "Could not get clk: %d\n", err);
+               return err;
+       }
+
+       err = clk_prepare_enable(data->clk);
+       if (err)
+               return err;
+
+       rate = clk_get_rate(data->clk);
+       if ((rate < 1920000) || (rate > 5000000))
+               dev_warn(&pdev->dev,
+                        "Clock %pCn running at %pCr Hz is outside of the recommended range: 1.92 to 5MHz\n",
+                        data->clk, data->clk);
+
+       /* register of thermal sensor and get info from DT */
+       tz = thermal_zone_of_sensor_register(&pdev->dev, 0, data,
+                                            &bcm2835_thermal_ops);
+       if (IS_ERR(tz)) {
+               err = PTR_ERR(tz);
+               dev_err(&pdev->dev,
+                       "Failed to register the thermal device: %d\n",
+                       err);
+               goto err_clk;
+       }
+
+       /*
+        * right now the FW does set up the HW-block, so we are not
+        * touching the configuration registers.
+        * But if the HW is not enabled, then set it up
+        * using "sane" values used by the firmware right now.
+        */
+       val = readl(data->regs + BCM2835_TS_TSENSCTL);
+       if (!(val & BCM2835_TS_TSENSCTL_RSTB)) {
+               int trip_temp, offset, slope;
+
+               slope = thermal_zone_get_slope(tz);
+               offset = thermal_zone_get_offset(tz);
+               /*
+                * For now we deal only with critical, otherwise
+                * would need to iterate
+                */
+               err = tz->ops->get_trip_temp(tz, 0, &trip_temp);
+               if (err < 0) {
+                       err = PTR_ERR(tz);
+                       dev_err(&pdev->dev,
+                               "Not able to read trip_temp: %d\n",
+                               err);
+                       goto err_tz;
+               }
+
+               /* set bandgap reference voltage and enable voltage regulator */
+               val = (BCM2835_TS_TSENSCTL_CTRL_DEFAULT <<
+                      BCM2835_TS_TSENSCTL_CTRL_SHIFT) |
+                     BCM2835_TS_TSENSCTL_REGULEN;
+
+               /* use the recommended reset duration */
+               val |= (0xFE << BCM2835_TS_TSENSCTL_RSTDELAY_SHIFT);
+
+               /*  trip_adc value from info */
+               val |= bcm2835_thermal_temp2adc(trip_temp,
+                                               offset,
+                                               slope)
+                       << BCM2835_TS_TSENSCTL_THOLD_SHIFT;
+
+               /* write the value back to the register as 2 steps */
+               writel(val, data->regs + BCM2835_TS_TSENSCTL);
+               val |= BCM2835_TS_TSENSCTL_RSTB;
+               writel(val, data->regs + BCM2835_TS_TSENSCTL);
+       }
+
+       data->tz = tz;
+
+       platform_set_drvdata(pdev, tz);
+
+       bcm2835_thermal_debugfs(pdev);
+
+       return 0;
+err_tz:
+       thermal_zone_of_sensor_unregister(&pdev->dev, tz);
+err_clk:
+       clk_disable_unprepare(data->clk);
+
+       return err;
+}
+
+static int bcm2835_thermal_remove(struct platform_device *pdev)
+{
+       struct thermal_zone_device *tz = platform_get_drvdata(pdev);
+       struct bcm2835_thermal_data *data = tz->devdata;
+
+       debugfs_remove_recursive(data->debugfsdir);
+       thermal_zone_of_sensor_unregister(&pdev->dev, tz);
+       clk_disable_unprepare(data->clk);
+
+       return 0;
+}
+
+static struct platform_driver bcm2835_thermal_driver = {
+       .probe = bcm2835_thermal_probe,
+       .remove = bcm2835_thermal_remove,
+       .driver = {
+               .name = "bcm2835_thermal",
+               .of_match_table = bcm2835_thermal_of_match_table,
+       },
+};
+module_platform_driver(bcm2835_thermal_driver);
+
+MODULE_AUTHOR("Martin Sperl");
+MODULE_DESCRIPTION("Thermal driver for bcm2835 chip");
+MODULE_LICENSE("GPL");
diff --git a/drivers/thermal/broadcom/ns-thermal.c b/drivers/thermal/broadcom/ns-thermal.c
new file mode 100644 (file)
index 0000000..322e741
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2017 Rafał Miłecki <rafal@milecki.pl>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/thermal.h>
+
+#define PVTMON_CONTROL0                                        0x00
+#define PVTMON_CONTROL0_SEL_MASK                       0x0000000e
+#define PVTMON_CONTROL0_SEL_TEMP_MONITOR               0x00000000
+#define PVTMON_CONTROL0_SEL_TEST_MODE                  0x0000000e
+#define PVTMON_STATUS                                  0x08
+
+struct ns_thermal {
+       struct thermal_zone_device *tz;
+       void __iomem *pvtmon;
+};
+
+static int ns_thermal_get_temp(void *data, int *temp)
+{
+       struct ns_thermal *ns_thermal = data;
+       int offset = thermal_zone_get_offset(ns_thermal->tz);
+       int slope = thermal_zone_get_slope(ns_thermal->tz);
+       u32 val;
+
+       val = readl(ns_thermal->pvtmon + PVTMON_CONTROL0);
+       if ((val & PVTMON_CONTROL0_SEL_MASK) != PVTMON_CONTROL0_SEL_TEMP_MONITOR) {
+               /* Clear current mode selection */
+               val &= ~PVTMON_CONTROL0_SEL_MASK;
+
+               /* Set temp monitor mode (it's the default actually) */
+               val |= PVTMON_CONTROL0_SEL_TEMP_MONITOR;
+
+               writel(val, ns_thermal->pvtmon + PVTMON_CONTROL0);
+       }
+
+       val = readl(ns_thermal->pvtmon + PVTMON_STATUS);
+       *temp = slope * val + offset;
+
+       return 0;
+}
+
+static const struct thermal_zone_of_device_ops ns_thermal_ops = {
+       .get_temp = ns_thermal_get_temp,
+};
+
+static int ns_thermal_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct ns_thermal *ns_thermal;
+
+       ns_thermal = devm_kzalloc(dev, sizeof(*ns_thermal), GFP_KERNEL);
+       if (!ns_thermal)
+               return -ENOMEM;
+
+       ns_thermal->pvtmon = of_iomap(dev_of_node(dev), 0);
+       if (WARN_ON(!ns_thermal->pvtmon))
+               return -ENOENT;
+
+       ns_thermal->tz = devm_thermal_zone_of_sensor_register(dev, 0,
+                                                             ns_thermal,
+                                                             &ns_thermal_ops);
+       if (IS_ERR(ns_thermal->tz)) {
+               iounmap(ns_thermal->pvtmon);
+               return PTR_ERR(ns_thermal->tz);
+       }
+
+       platform_set_drvdata(pdev, ns_thermal);
+
+       return 0;
+}
+
+static int ns_thermal_remove(struct platform_device *pdev)
+{
+       struct ns_thermal *ns_thermal = platform_get_drvdata(pdev);
+
+       iounmap(ns_thermal->pvtmon);
+
+       return 0;
+}
+
+static const struct of_device_id ns_thermal_of_match[] = {
+       { .compatible = "brcm,ns-thermal", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, ns_thermal_of_match);
+
+static struct platform_driver ns_thermal_driver = {
+       .probe          = ns_thermal_probe,
+       .remove         = ns_thermal_remove,
+       .driver = {
+               .name = "ns-thermal",
+               .of_match_table = ns_thermal_of_match,
+       },
+};
+module_platform_driver(ns_thermal_driver);
+
+MODULE_AUTHOR("Rafał Miłecki <rafal@milecki.pl>");
+MODULE_DESCRIPTION("Northstar thermal driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/thermal/da9062-thermal.c b/drivers/thermal/da9062-thermal.c
new file mode 100644 (file)
index 0000000..dd8dd94
--- /dev/null
@@ -0,0 +1,315 @@
+/*
+ * Thermal device driver for DA9062 and DA9061
+ * Copyright (C) 2017  Dialog Semiconductor
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/* When over-temperature is reached, an interrupt from the device will be
+ * triggered. Following this event the interrupt will be disabled and
+ * periodic transmission of uevents (HOT trip point) should define the
+ * first level of temperature supervision. It is expected that any final
+ * implementation of the thermal driver will include a .notify() function
+ * to implement these uevents to userspace.
+ *
+ * These uevents are intended to indicate non-invasive temperature control
+ * of the system, where the necessary measures for cooling are the
+ * responsibility of the host software. Once the temperature falls again,
+ * the IRQ is re-enabled so the start of a new over-temperature event can
+ * be detected without constant software monitoring.
+ */
+
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/thermal.h>
+#include <linux/workqueue.h>
+
+#include <linux/mfd/da9062/core.h>
+#include <linux/mfd/da9062/registers.h>
+
+/* Minimum, maximum and default polling millisecond periods are provided
+ * here as an example. It is expected that any final implementation to also
+ * include a modification of these settings to match the required
+ * application.
+ */
+#define DA9062_DEFAULT_POLLING_MS_PERIOD       3000
+#define DA9062_MAX_POLLING_MS_PERIOD           10000
+#define DA9062_MIN_POLLING_MS_PERIOD           1000
+
+#define DA9062_MILLI_CELSIUS(t)                        ((t) * 1000)
+
+struct da9062_thermal_config {
+       const char *name;
+};
+
+struct da9062_thermal {
+       struct da9062 *hw;
+       struct delayed_work work;
+       struct thermal_zone_device *zone;
+       enum thermal_device_mode mode;
+       struct mutex lock; /* protection for da9062_thermal temperature */
+       int temperature;
+       int irq;
+       const struct da9062_thermal_config *config;
+       struct device *dev;
+};
+
+static void da9062_thermal_poll_on(struct work_struct *work)
+{
+       struct da9062_thermal *thermal = container_of(work,
+                                               struct da9062_thermal,
+                                               work.work);
+       unsigned long delay;
+       unsigned int val;
+       int ret;
+
+       /* clear E_TEMP */
+       ret = regmap_write(thermal->hw->regmap,
+                          DA9062AA_EVENT_B,
+                          DA9062AA_E_TEMP_MASK);
+       if (ret < 0) {
+               dev_err(thermal->dev,
+                       "Cannot clear the TJUNC temperature status\n");
+               goto err_enable_irq;
+       }
+
+       /* Now read E_TEMP again: it is acting like a status bit.
+        * If over-temperature, then this status will be true.
+        * If not over-temperature, this status will be false.
+        */
+       ret = regmap_read(thermal->hw->regmap,
+                         DA9062AA_EVENT_B,
+                         &val);
+       if (ret < 0) {
+               dev_err(thermal->dev,
+                       "Cannot check the TJUNC temperature status\n");
+               goto err_enable_irq;
+       }
+
+       if (val & DA9062AA_E_TEMP_MASK) {
+               mutex_lock(&thermal->lock);
+               thermal->temperature = DA9062_MILLI_CELSIUS(125);
+               mutex_unlock(&thermal->lock);
+               thermal_zone_device_update(thermal->zone,
+                                          THERMAL_EVENT_UNSPECIFIED);
+
+               delay = msecs_to_jiffies(thermal->zone->passive_delay);
+               schedule_delayed_work(&thermal->work, delay);
+               return;
+       }
+
+       mutex_lock(&thermal->lock);
+       thermal->temperature = DA9062_MILLI_CELSIUS(0);
+       mutex_unlock(&thermal->lock);
+       thermal_zone_device_update(thermal->zone,
+                                  THERMAL_EVENT_UNSPECIFIED);
+
+err_enable_irq:
+       enable_irq(thermal->irq);
+}
+
+static irqreturn_t da9062_thermal_irq_handler(int irq, void *data)
+{
+       struct da9062_thermal *thermal = data;
+
+       disable_irq_nosync(thermal->irq);
+       schedule_delayed_work(&thermal->work, 0);
+
+       return IRQ_HANDLED;
+}
+
+static int da9062_thermal_get_mode(struct thermal_zone_device *z,
+                                  enum thermal_device_mode *mode)
+{
+       struct da9062_thermal *thermal = z->devdata;
+       *mode = thermal->mode;
+       return 0;
+}
+
+static int da9062_thermal_get_trip_type(struct thermal_zone_device *z,
+                                       int trip,
+                                       enum thermal_trip_type *type)
+{
+       struct da9062_thermal *thermal = z->devdata;
+
+       switch (trip) {
+       case 0:
+               *type = THERMAL_TRIP_HOT;
+               break;
+       default:
+               dev_err(thermal->dev,
+                       "Driver does not support more than 1 trip-wire\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int da9062_thermal_get_trip_temp(struct thermal_zone_device *z,
+                                       int trip,
+                                       int *temp)
+{
+       struct da9062_thermal *thermal = z->devdata;
+
+       switch (trip) {
+       case 0:
+               *temp = DA9062_MILLI_CELSIUS(125);
+               break;
+       default:
+               dev_err(thermal->dev,
+                       "Driver does not support more than 1 trip-wire\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static int da9062_thermal_get_temp(struct thermal_zone_device *z,
+                                  int *temp)
+{
+       struct da9062_thermal *thermal = z->devdata;
+
+       mutex_lock(&thermal->lock);
+       *temp = thermal->temperature;
+       mutex_unlock(&thermal->lock);
+
+       return 0;
+}
+
+static struct thermal_zone_device_ops da9062_thermal_ops = {
+       .get_temp       = da9062_thermal_get_temp,
+       .get_mode       = da9062_thermal_get_mode,
+       .get_trip_type  = da9062_thermal_get_trip_type,
+       .get_trip_temp  = da9062_thermal_get_trip_temp,
+};
+
+static const struct da9062_thermal_config da9062_config = {
+       .name = "da9062-thermal",
+};
+
+static const struct of_device_id da9062_compatible_reg_id_table[] = {
+       { .compatible = "dlg,da9062-thermal", .data = &da9062_config },
+       { },
+};
+
+MODULE_DEVICE_TABLE(of, da9062_compatible_reg_id_table);
+
+static int da9062_thermal_probe(struct platform_device *pdev)
+{
+       struct da9062 *chip = dev_get_drvdata(pdev->dev.parent);
+       struct da9062_thermal *thermal;
+       unsigned int pp_tmp = DA9062_DEFAULT_POLLING_MS_PERIOD;
+       const struct of_device_id *match;
+       int ret = 0;
+
+       match = of_match_node(da9062_compatible_reg_id_table,
+                             pdev->dev.of_node);
+       if (!match)
+               return -ENXIO;
+
+       if (pdev->dev.of_node) {
+               if (!of_property_read_u32(pdev->dev.of_node,
+                                         "polling-delay-passive",
+                                         &pp_tmp)) {
+                       if (pp_tmp < DA9062_MIN_POLLING_MS_PERIOD ||
+                           pp_tmp > DA9062_MAX_POLLING_MS_PERIOD) {
+                               dev_warn(&pdev->dev,
+                                        "Out-of-range polling period %d ms\n",
+                                        pp_tmp);
+                               pp_tmp = DA9062_DEFAULT_POLLING_MS_PERIOD;
+                       }
+               }
+       }
+
+       thermal = devm_kzalloc(&pdev->dev, sizeof(struct da9062_thermal),
+                              GFP_KERNEL);
+       if (!thermal) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       thermal->config = match->data;
+       thermal->hw = chip;
+       thermal->mode = THERMAL_DEVICE_ENABLED;
+       thermal->dev = &pdev->dev;
+
+       INIT_DELAYED_WORK(&thermal->work, da9062_thermal_poll_on);
+       mutex_init(&thermal->lock);
+
+       thermal->zone = thermal_zone_device_register(thermal->config->name,
+                                       1, 0, thermal,
+                                       &da9062_thermal_ops, NULL, pp_tmp,
+                                       0);
+       if (IS_ERR(thermal->zone)) {
+               dev_err(&pdev->dev, "Cannot register thermal zone device\n");
+               ret = PTR_ERR(thermal->zone);
+               goto err;
+       }
+
+       dev_dbg(&pdev->dev,
+               "TJUNC temperature polling period set at %d ms\n",
+               thermal->zone->passive_delay);
+
+       ret = platform_get_irq_byname(pdev, "THERMAL");
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Failed to get platform IRQ.\n");
+               goto err_zone;
+       }
+       thermal->irq = ret;
+
+       ret = request_threaded_irq(thermal->irq, NULL,
+                                  da9062_thermal_irq_handler,
+                                  IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+                                  "THERMAL", thermal);
+       if (ret) {
+               dev_err(&pdev->dev,
+                       "Failed to request thermal device IRQ.\n");
+               goto err_zone;
+       }
+
+       platform_set_drvdata(pdev, thermal);
+       return 0;
+
+err_zone:
+       thermal_zone_device_unregister(thermal->zone);
+err:
+       return ret;
+}
+
+static int da9062_thermal_remove(struct platform_device *pdev)
+{
+       struct  da9062_thermal *thermal = platform_get_drvdata(pdev);
+
+       free_irq(thermal->irq, thermal);
+       cancel_delayed_work_sync(&thermal->work);
+       thermal_zone_device_unregister(thermal->zone);
+       return 0;
+}
+
+static struct platform_driver da9062_thermal_driver = {
+       .probe  = da9062_thermal_probe,
+       .remove = da9062_thermal_remove,
+       .driver = {
+               .name   = "da9062-thermal",
+               .of_match_table = da9062_compatible_reg_id_table,
+       },
+};
+
+module_platform_driver(da9062_thermal_driver);
+
+MODULE_AUTHOR("Steve Twiss");
+MODULE_DESCRIPTION("Thermal TJUNC device driver for Dialog DA9062 and DA9061");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:da9062-thermal");
index 4bf4ad58cffda0172a48138248f4b406790c58e8..ef59256887ff63d04db5efc08a4f082a68bb75b8 100644 (file)
@@ -28,6 +28,8 @@
 
 #include <trace/events/thermal.h>
 
+#define SCALE_ERROR_MITIGATION 100
+
 static DEFINE_IDA(devfreq_ida);
 
 /**
@@ -45,6 +47,12 @@ static DEFINE_IDA(devfreq_ida);
  * @freq_table_size:   Size of the @freq_table and @power_table
  * @power_ops: Pointer to devfreq_cooling_power, used to generate the
  *             @power_table.
+ * @res_util:  Resource utilization scaling factor for the power.
+ *             It is multiplied by 100 to minimize the error. It is used
+ *             for estimation of the power budget instead of using
+ *             'utilization' (which is 'busy_time / 'total_time').
+ *             The 'res_util' range is from 100 to (power_table[state] * 100)
+ *             for the corresponding 'state'.
  */
 struct devfreq_cooling_device {
        int id;
@@ -55,6 +63,8 @@ struct devfreq_cooling_device {
        u32 *freq_table;
        size_t freq_table_size;
        struct devfreq_cooling_power *power_ops;
+       u32 res_util;
+       int capped_state;
 };
 
 /**
@@ -164,27 +174,12 @@ freq_get_state(struct devfreq_cooling_device *dfc, unsigned long freq)
        return THERMAL_CSTATE_INVALID;
 }
 
-/**
- * get_static_power() - calculate the static power
- * @dfc:       Pointer to devfreq cooling device
- * @freq:      Frequency in Hz
- *
- * Calculate the static power in milliwatts using the supplied
- * get_static_power().  The current voltage is calculated using the
- * OPP library.  If no get_static_power() was supplied, assume the
- * static power is negligible.
- */
-static unsigned long
-get_static_power(struct devfreq_cooling_device *dfc, unsigned long freq)
+static unsigned long get_voltage(struct devfreq *df, unsigned long freq)
 {
-       struct devfreq *df = dfc->devfreq;
        struct device *dev = df->dev.parent;
        unsigned long voltage;
        struct dev_pm_opp *opp;
 
-       if (!dfc->power_ops->get_static_power)
-               return 0;
-
        opp = dev_pm_opp_find_freq_exact(dev, freq, true);
        if (PTR_ERR(opp) == -ERANGE)
                opp = dev_pm_opp_find_freq_exact(dev, freq, false);
@@ -202,9 +197,35 @@ get_static_power(struct devfreq_cooling_device *dfc, unsigned long freq)
                dev_err_ratelimited(dev,
                                    "Failed to get voltage for frequency %lu\n",
                                    freq);
-               return 0;
        }
 
+       return voltage;
+}
+
+/**
+ * get_static_power() - calculate the static power
+ * @dfc:       Pointer to devfreq cooling device
+ * @freq:      Frequency in Hz
+ *
+ * Calculate the static power in milliwatts using the supplied
+ * get_static_power().  The current voltage is calculated using the
+ * OPP library.  If no get_static_power() was supplied, assume the
+ * static power is negligible.
+ */
+static unsigned long
+get_static_power(struct devfreq_cooling_device *dfc, unsigned long freq)
+{
+       struct devfreq *df = dfc->devfreq;
+       unsigned long voltage;
+
+       if (!dfc->power_ops->get_static_power)
+               return 0;
+
+       voltage = get_voltage(df, freq);
+
+       if (voltage == 0)
+               return 0;
+
        return dfc->power_ops->get_static_power(df, voltage);
 }
 
@@ -239,6 +260,16 @@ get_dynamic_power(struct devfreq_cooling_device *dfc, unsigned long freq,
        return power;
 }
 
+
+static inline unsigned long get_total_power(struct devfreq_cooling_device *dfc,
+                                           unsigned long freq,
+                                           unsigned long voltage)
+{
+       return get_static_power(dfc, freq) + get_dynamic_power(dfc, freq,
+                                                              voltage);
+}
+
+
 static int devfreq_cooling_get_requested_power(struct thermal_cooling_device *cdev,
                                               struct thermal_zone_device *tz,
                                               u32 *power)
@@ -248,27 +279,55 @@ static int devfreq_cooling_get_requested_power(struct thermal_cooling_device *cd
        struct devfreq_dev_status *status = &df->last_status;
        unsigned long state;
        unsigned long freq = status->current_frequency;
-       u32 dyn_power, static_power;
+       unsigned long voltage;
+       u32 dyn_power = 0;
+       u32 static_power = 0;
+       int res;
 
-       /* Get dynamic power for state */
        state = freq_get_state(dfc, freq);
-       if (state == THERMAL_CSTATE_INVALID)
-               return -EAGAIN;
+       if (state == THERMAL_CSTATE_INVALID) {
+               res = -EAGAIN;
+               goto fail;
+       }
 
-       dyn_power = dfc->power_table[state];
+       if (dfc->power_ops->get_real_power) {
+               voltage = get_voltage(df, freq);
+               if (voltage == 0) {
+                       res = -EINVAL;
+                       goto fail;
+               }
 
-       /* Scale dynamic power for utilization */
-       dyn_power = (dyn_power * status->busy_time) / status->total_time;
+               res = dfc->power_ops->get_real_power(df, power, freq, voltage);
+               if (!res) {
+                       state = dfc->capped_state;
+                       dfc->res_util = dfc->power_table[state];
+                       dfc->res_util *= SCALE_ERROR_MITIGATION;
 
-       /* Get static power */
-       static_power = get_static_power(dfc, freq);
+                       if (*power > 1)
+                               dfc->res_util /= *power;
+               } else {
+                       goto fail;
+               }
+       } else {
+               dyn_power = dfc->power_table[state];
 
-       trace_thermal_power_devfreq_get_power(cdev, status, freq, dyn_power,
-                                             static_power);
+               /* Scale dynamic power for utilization */
+               dyn_power *= status->busy_time;
+               dyn_power /= status->total_time;
+               /* Get static power */
+               static_power = get_static_power(dfc, freq);
 
-       *power = dyn_power + static_power;
+               *power = dyn_power + static_power;
+       }
+
+       trace_thermal_power_devfreq_get_power(cdev, status, freq, dyn_power,
+                                             static_power, *power);
 
        return 0;
+fail:
+       /* It is safe to set max in this case */
+       dfc->res_util = SCALE_ERROR_MITIGATION;
+       return res;
 }
 
 static int devfreq_cooling_state2power(struct thermal_cooling_device *cdev,
@@ -301,26 +360,34 @@ static int devfreq_cooling_power2state(struct thermal_cooling_device *cdev,
        unsigned long busy_time;
        s32 dyn_power;
        u32 static_power;
+       s32 est_power;
        int i;
 
-       static_power = get_static_power(dfc, freq);
+       if (dfc->power_ops->get_real_power) {
+               /* Scale for resource utilization */
+               est_power = power * dfc->res_util;
+               est_power /= SCALE_ERROR_MITIGATION;
+       } else {
+               static_power = get_static_power(dfc, freq);
 
-       dyn_power = power - static_power;
-       dyn_power = dyn_power > 0 ? dyn_power : 0;
+               dyn_power = power - static_power;
+               dyn_power = dyn_power > 0 ? dyn_power : 0;
 
-       /* Scale dynamic power for utilization */
-       busy_time = status->busy_time ?: 1;
-       dyn_power = (dyn_power * status->total_time) / busy_time;
+               /* Scale dynamic power for utilization */
+               busy_time = status->busy_time ?: 1;
+               est_power = (dyn_power * status->total_time) / busy_time;
+       }
 
        /*
         * Find the first cooling state that is within the power
         * budget for dynamic power.
         */
        for (i = 0; i < dfc->freq_table_size - 1; i++)
-               if (dyn_power >= dfc->power_table[i])
+               if (est_power >= dfc->power_table[i])
                        break;
 
        *state = i;
+       dfc->capped_state = i;
        trace_thermal_power_devfreq_limit(cdev, freq, *state, power);
        return 0;
 }
@@ -376,7 +443,7 @@ static int devfreq_cooling_gen_tables(struct devfreq_cooling_device *dfc)
        }
 
        for (i = 0, freq = ULONG_MAX; i < num_opps; i++, freq--) {
-               unsigned long power_dyn, voltage;
+               unsigned long power, voltage;
                struct dev_pm_opp *opp;
 
                opp = dev_pm_opp_find_freq_floor(dev, &freq);
@@ -389,12 +456,15 @@ static int devfreq_cooling_gen_tables(struct devfreq_cooling_device *dfc)
                dev_pm_opp_put(opp);
 
                if (dfc->power_ops) {
-                       power_dyn = get_dynamic_power(dfc, freq, voltage);
+                       if (dfc->power_ops->get_real_power)
+                               power = get_total_power(dfc, freq, voltage);
+                       else
+                               power = get_dynamic_power(dfc, freq, voltage);
 
-                       dev_dbg(dev, "Dynamic power table: %lu MHz @ %lu mV: %lu = %lu mW\n",
-                               freq / 1000000, voltage, power_dyn, power_dyn);
+                       dev_dbg(dev, "Power table: %lu MHz @ %lu mV: %lu = %lu mW\n",
+                               freq / 1000000, voltage, power, power);
 
-                       power_table[i] = power_dyn;
+                       power_table[i] = power;
                }
 
                freq_table[i] = freq;
index b2bbaa1c60b07e449ddafac601cedca234d936c8..c27868b2c6afc5f438754f370961fee1c3eaac8e 100644 (file)
@@ -73,8 +73,12 @@ static int __init intel_soc_thermal_init(void)
                                           IRQF_TRIGGER_RISING | IRQF_ONESHOT,
                                           "soc_dts", soc_dts);
                if (err) {
-                       pr_err("request_threaded_irq ret %d\n", err);
-                       goto error_irq;
+                       /*
+                        * Do not just error out because the user space thermal
+                        * daemon such as DPTF may use polling instead of being
+                        * interrupt driven.
+                        */
+                       pr_warn("request_threaded_irq ret %d\n", err);
                }
        }
 
@@ -88,7 +92,6 @@ static int __init intel_soc_thermal_init(void)
 error_trips:
        if (soc_dts_thres_irq)
                free_irq(soc_dts_thres_irq, soc_dts);
-error_irq:
        intel_soc_dts_iosf_exit(soc_dts);
 
        return err;
index 1aff7fde54b18f217232f0c74cbf3787f55670e0..7737f14846f9e77b0515093d33d13a19c96bf13a 100644 (file)
@@ -191,7 +191,7 @@ static const int mt8173_bank_data[MT8173_NUM_ZONES][3] = {
 };
 
 static const int mt8173_msr[MT8173_NUM_SENSORS_PER_ZONE] = {
-       TEMP_MSR0, TEMP_MSR1, TEMP_MSR2, TEMP_MSR2
+       TEMP_MSR0, TEMP_MSR1, TEMP_MSR2, TEMP_MSR3
 };
 
 static const int mt8173_adcpnp[MT8173_NUM_SENSORS_PER_ZONE] = {
index d33c845244b1d819b774ed482f78665013ee5203..37fcefd06d9f81b4eb1238634103b5e1ab06a5c3 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/module.h>
-#include <linux/mutex.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
+#include <linux/spinlock.h>
 #include <linux/thermal.h>
 
+#include "thermal_core.h"
+
 /* Register offsets */
 #define REG_GEN3_IRQSTR                0x04
 #define REG_GEN3_IRQMSK                0x08
 #define REG_GEN3_THCODE2       0x54
 #define REG_GEN3_THCODE3       0x58
 
+/* IRQ{STR,MSK,EN} bits */
+#define IRQ_TEMP1              BIT(0)
+#define IRQ_TEMP2              BIT(1)
+#define IRQ_TEMP3              BIT(2)
+#define IRQ_TEMPD1             BIT(3)
+#define IRQ_TEMPD2             BIT(4)
+#define IRQ_TEMPD3             BIT(5)
+
 /* CTSR bits */
 #define CTSR_PONM      BIT(8)
 #define CTSR_AOUT      BIT(7)
@@ -72,11 +82,15 @@ struct rcar_gen3_thermal_tsc {
        void __iomem *base;
        struct thermal_zone_device *zone;
        struct equation_coefs coef;
-       struct mutex lock;
+       int low;
+       int high;
 };
 
 struct rcar_gen3_thermal_priv {
        struct rcar_gen3_thermal_tsc *tscs[TSC_MAX_NUM];
+       unsigned int num_tscs;
+       spinlock_t lock; /* Protect interrupts on and off */
+       const struct rcar_gen3_thermal_data *data;
 };
 
 struct rcar_gen3_thermal_data {
@@ -114,6 +128,7 @@ static inline void rcar_gen3_thermal_write(struct rcar_gen3_thermal_tsc *tsc,
 
 #define FIXPT_SHIFT 7
 #define FIXPT_INT(_x) ((_x) << FIXPT_SHIFT)
+#define INT_FIXPT(_x) ((_x) >> FIXPT_SHIFT)
 #define FIXPT_DIV(_a, _b) DIV_ROUND_CLOSEST(((_a) << FIXPT_SHIFT), (_b))
 #define FIXPT_TO_MCELSIUS(_x) ((_x) * 1000 >> FIXPT_SHIFT)
 
@@ -163,16 +178,12 @@ static int rcar_gen3_thermal_get_temp(void *devdata, int *temp)
        u32 reg;
 
        /* Read register and convert to mili Celsius */
-       mutex_lock(&tsc->lock);
-
        reg = rcar_gen3_thermal_read(tsc, REG_GEN3_TEMP) & CTEMP_MASK;
 
        val1 = FIXPT_DIV(FIXPT_INT(reg) - tsc->coef.b1, tsc->coef.a1);
        val2 = FIXPT_DIV(FIXPT_INT(reg) - tsc->coef.b2, tsc->coef.a2);
        mcelsius = FIXPT_TO_MCELSIUS((val1 + val2) / 2);
 
-       mutex_unlock(&tsc->lock);
-
        /* Make sure we are inside specifications */
        if ((mcelsius < MCELSIUS(-40)) || (mcelsius > MCELSIUS(125)))
                return -EIO;
@@ -183,10 +194,90 @@ static int rcar_gen3_thermal_get_temp(void *devdata, int *temp)
        return 0;
 }
 
+static int rcar_gen3_thermal_mcelsius_to_temp(struct rcar_gen3_thermal_tsc *tsc,
+                                             int mcelsius)
+{
+       int celsius, val1, val2;
+
+       celsius = DIV_ROUND_CLOSEST(mcelsius, 1000);
+       val1 = celsius * tsc->coef.a1 + tsc->coef.b1;
+       val2 = celsius * tsc->coef.a2 + tsc->coef.b2;
+
+       return INT_FIXPT((val1 + val2) / 2);
+}
+
+static int rcar_gen3_thermal_set_trips(void *devdata, int low, int high)
+{
+       struct rcar_gen3_thermal_tsc *tsc = devdata;
+
+       low = clamp_val(low, -40000, 125000);
+       high = clamp_val(high, -40000, 125000);
+
+       rcar_gen3_thermal_write(tsc, REG_GEN3_IRQTEMP1,
+                               rcar_gen3_thermal_mcelsius_to_temp(tsc, low));
+
+       rcar_gen3_thermal_write(tsc, REG_GEN3_IRQTEMP2,
+                               rcar_gen3_thermal_mcelsius_to_temp(tsc, high));
+
+       tsc->low = low;
+       tsc->high = high;
+
+       return 0;
+}
+
 static struct thermal_zone_of_device_ops rcar_gen3_tz_of_ops = {
        .get_temp       = rcar_gen3_thermal_get_temp,
+       .set_trips      = rcar_gen3_thermal_set_trips,
 };
 
+static void rcar_thermal_irq_set(struct rcar_gen3_thermal_priv *priv, bool on)
+{
+       unsigned int i;
+       u32 val = on ? IRQ_TEMPD1 | IRQ_TEMP2 : 0;
+
+       for (i = 0; i < priv->num_tscs; i++)
+               rcar_gen3_thermal_write(priv->tscs[i], REG_GEN3_IRQMSK, val);
+}
+
+static irqreturn_t rcar_gen3_thermal_irq(int irq, void *data)
+{
+       struct rcar_gen3_thermal_priv *priv = data;
+       u32 status;
+       int i, ret = IRQ_HANDLED;
+
+       spin_lock(&priv->lock);
+       for (i = 0; i < priv->num_tscs; i++) {
+               status = rcar_gen3_thermal_read(priv->tscs[i], REG_GEN3_IRQSTR);
+               rcar_gen3_thermal_write(priv->tscs[i], REG_GEN3_IRQSTR, 0);
+               if (status)
+                       ret = IRQ_WAKE_THREAD;
+       }
+
+       if (ret == IRQ_WAKE_THREAD)
+               rcar_thermal_irq_set(priv, false);
+
+       spin_unlock(&priv->lock);
+
+       return ret;
+}
+
+static irqreturn_t rcar_gen3_thermal_irq_thread(int irq, void *data)
+{
+       struct rcar_gen3_thermal_priv *priv = data;
+       unsigned long flags;
+       int i;
+
+       for (i = 0; i < priv->num_tscs; i++)
+               thermal_zone_device_update(priv->tscs[i]->zone,
+                                          THERMAL_EVENT_UNSPECIFIED);
+
+       spin_lock_irqsave(&priv->lock, flags);
+       rcar_thermal_irq_set(priv, true);
+       spin_unlock_irqrestore(&priv->lock, flags);
+
+       return IRQ_HANDLED;
+}
+
 static void r8a7795_thermal_init(struct rcar_gen3_thermal_tsc *tsc)
 {
        rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR,  CTSR_THBGR);
@@ -195,7 +286,11 @@ static void r8a7795_thermal_init(struct rcar_gen3_thermal_tsc *tsc)
        usleep_range(1000, 2000);
 
        rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR, CTSR_PONM);
+
        rcar_gen3_thermal_write(tsc, REG_GEN3_IRQCTL, 0x3F);
+       rcar_gen3_thermal_write(tsc, REG_GEN3_IRQMSK, 0);
+       rcar_gen3_thermal_write(tsc, REG_GEN3_IRQEN, IRQ_TEMPD1 | IRQ_TEMP2);
+
        rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR,
                                CTSR_PONM | CTSR_AOUT | CTSR_THBGR | CTSR_VMEN);
 
@@ -219,9 +314,14 @@ static void r8a7796_thermal_init(struct rcar_gen3_thermal_tsc *tsc)
        usleep_range(1000, 2000);
 
        rcar_gen3_thermal_write(tsc, REG_GEN3_IRQCTL, 0x3F);
+       rcar_gen3_thermal_write(tsc, REG_GEN3_IRQMSK, 0);
+       rcar_gen3_thermal_write(tsc, REG_GEN3_IRQEN, IRQ_TEMPD1 | IRQ_TEMP2);
+
        reg_val = rcar_gen3_thermal_read(tsc, REG_GEN3_THCTR);
        reg_val |= THCTR_THSST;
        rcar_gen3_thermal_write(tsc, REG_GEN3_THCTR, reg_val);
+
+       usleep_range(1000, 2000);
 }
 
 static const struct rcar_gen3_thermal_data r8a7795_data = {
@@ -255,9 +355,8 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        struct resource *res;
        struct thermal_zone_device *zone;
-       int ret, i;
-       const struct rcar_gen3_thermal_data *match_data =
-               of_device_get_match_data(dev);
+       int ret, irq, i;
+       char *irqname;
 
        /* default values if FUSEs are missing */
        /* TODO: Read values from hardware on supported platforms */
@@ -272,24 +371,50 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
        if (!priv)
                return -ENOMEM;
 
+       priv->data = of_device_get_match_data(dev);
+
+       spin_lock_init(&priv->lock);
+
        platform_set_drvdata(pdev, priv);
 
+       /*
+        * Request 2 (of the 3 possible) IRQs, the driver only needs to
+        * to trigger on the low and high trip points of the current
+        * temp window at this point.
+        */
+       for (i = 0; i < 2; i++) {
+               irq = platform_get_irq(pdev, i);
+               if (irq < 0)
+                       return irq;
+
+               irqname = devm_kasprintf(dev, GFP_KERNEL, "%s:ch%d",
+                                        dev_name(dev), i);
+               if (!irqname)
+                       return -ENOMEM;
+
+               ret = devm_request_threaded_irq(dev, irq, rcar_gen3_thermal_irq,
+                                               rcar_gen3_thermal_irq_thread,
+                                               IRQF_SHARED, irqname, priv);
+               if (ret)
+                       return ret;
+       }
+
        pm_runtime_enable(dev);
        pm_runtime_get_sync(dev);
 
        for (i = 0; i < TSC_MAX_NUM; i++) {
                struct rcar_gen3_thermal_tsc *tsc;
 
+               res = platform_get_resource(pdev, IORESOURCE_MEM, i);
+               if (!res)
+                       break;
+
                tsc = devm_kzalloc(dev, sizeof(*tsc), GFP_KERNEL);
                if (!tsc) {
                        ret = -ENOMEM;
                        goto error_unregister;
                }
 
-               res = platform_get_resource(pdev, IORESOURCE_MEM, i);
-               if (!res)
-                       break;
-
                tsc->base = devm_ioremap_resource(dev, res);
                if (IS_ERR(tsc->base)) {
                        ret = PTR_ERR(tsc->base);
@@ -297,9 +422,8 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
                }
 
                priv->tscs[i] = tsc;
-               mutex_init(&tsc->lock);
 
-               match_data->thermal_init(tsc);
+               priv->data->thermal_init(tsc);
                rcar_gen3_thermal_calc_coefs(&tsc->coef, ptat, thcode[i]);
 
                zone = devm_thermal_zone_of_sensor_register(dev, i, tsc,
@@ -310,8 +434,23 @@ static int rcar_gen3_thermal_probe(struct platform_device *pdev)
                        goto error_unregister;
                }
                tsc->zone = zone;
+
+               ret = of_thermal_get_ntrips(tsc->zone);
+               if (ret < 0)
+                       goto error_unregister;
+
+               dev_info(dev, "TSC%d: Loaded %d trip points\n", i, ret);
        }
 
+       priv->num_tscs = i;
+
+       if (!priv->num_tscs) {
+               ret = -ENODEV;
+               goto error_unregister;
+       }
+
+       rcar_thermal_irq_set(priv, true);
+
        return 0;
 
 error_unregister:
@@ -320,9 +459,39 @@ error_unregister:
        return ret;
 }
 
+static int __maybe_unused rcar_gen3_thermal_suspend(struct device *dev)
+{
+       struct rcar_gen3_thermal_priv *priv = dev_get_drvdata(dev);
+
+       rcar_thermal_irq_set(priv, false);
+
+       return 0;
+}
+
+static int __maybe_unused rcar_gen3_thermal_resume(struct device *dev)
+{
+       struct rcar_gen3_thermal_priv *priv = dev_get_drvdata(dev);
+       unsigned int i;
+
+       for (i = 0; i < priv->num_tscs; i++) {
+               struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i];
+
+               priv->data->thermal_init(tsc);
+               rcar_gen3_thermal_set_trips(tsc, tsc->low, tsc->high);
+       }
+
+       rcar_thermal_irq_set(priv, true);
+
+       return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(rcar_gen3_thermal_pm_ops, rcar_gen3_thermal_suspend,
+                        rcar_gen3_thermal_resume);
+
 static struct platform_driver rcar_gen3_thermal_driver = {
        .driver = {
                .name   = "rcar_gen3_thermal",
+               .pm = &rcar_gen3_thermal_pm_ops,
                .of_match_table = rcar_gen3_thermal_dt_ids,
        },
        .probe          = rcar_gen3_thermal_probe,
index 11f0675cb7e552456d36ec49c82a46d5cf016d04..b21b9cc2c8d6412897193a4ce53e295966737e9c 100644 (file)
@@ -45,8 +45,10 @@ static LIST_HEAD(thermal_governor_list);
 
 static DEFINE_MUTEX(thermal_list_lock);
 static DEFINE_MUTEX(thermal_governor_lock);
+static DEFINE_MUTEX(poweroff_lock);
 
 static atomic_t in_suspend;
+static bool power_off_triggered;
 
 static struct thermal_governor *def_governor;
 
@@ -322,6 +324,54 @@ static void handle_non_critical_trips(struct thermal_zone_device *tz,
                       def_governor->throttle(tz, trip);
 }
 
+/**
+ * thermal_emergency_poweroff_func - emergency poweroff work after a known delay
+ * @work: work_struct associated with the emergency poweroff function
+ *
+ * This function is called in very critical situations to force
+ * a kernel poweroff after a configurable timeout value.
+ */
+static void thermal_emergency_poweroff_func(struct work_struct *work)
+{
+       /*
+        * We have reached here after the emergency thermal shutdown
+        * Waiting period has expired. This means orderly_poweroff has
+        * not been able to shut off the system for some reason.
+        * Try to shut down the system immediately using kernel_power_off
+        * if populated
+        */
+       WARN(1, "Attempting kernel_power_off: Temperature too high\n");
+       kernel_power_off();
+
+       /*
+        * Worst of the worst case trigger emergency restart
+        */
+       WARN(1, "Attempting emergency_restart: Temperature too high\n");
+       emergency_restart();
+}
+
+static DECLARE_DELAYED_WORK(thermal_emergency_poweroff_work,
+                           thermal_emergency_poweroff_func);
+
+/**
+ * thermal_emergency_poweroff - Trigger an emergency system poweroff
+ *
+ * This may be called from any critical situation to trigger a system shutdown
+ * after a known period of time. By default this is not scheduled.
+ */
+void thermal_emergency_poweroff(void)
+{
+       int poweroff_delay_ms = CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS;
+       /*
+        * poweroff_delay_ms must be a carefully profiled positive value.
+        * Its a must for thermal_emergency_poweroff_work to be scheduled
+        */
+       if (poweroff_delay_ms <= 0)
+               return;
+       schedule_delayed_work(&thermal_emergency_poweroff_work,
+                             msecs_to_jiffies(poweroff_delay_ms));
+}
+
 static void handle_critical_trips(struct thermal_zone_device *tz,
                                  int trip, enum thermal_trip_type trip_type)
 {
@@ -342,7 +392,17 @@ static void handle_critical_trips(struct thermal_zone_device *tz,
                dev_emerg(&tz->device,
                          "critical temperature reached(%d C),shutting down\n",
                          tz->temperature / 1000);
-               orderly_poweroff(true);
+               mutex_lock(&poweroff_lock);
+               if (!power_off_triggered) {
+                       /*
+                        * Queue a backup emergency shutdown in the event of
+                        * orderly_poweroff failure
+                        */
+                       thermal_emergency_poweroff();
+                       orderly_poweroff(true);
+                       power_off_triggered = true;
+               }
+               mutex_unlock(&poweroff_lock);
        }
 }
 
@@ -1463,6 +1523,7 @@ static int __init thermal_init(void)
 {
        int result;
 
+       mutex_init(&poweroff_lock);
        result = thermal_register_governors();
        if (result)
                goto error;
@@ -1497,6 +1558,7 @@ error:
        ida_destroy(&thermal_cdev_ida);
        mutex_destroy(&thermal_list_lock);
        mutex_destroy(&thermal_governor_lock);
+       mutex_destroy(&poweroff_lock);
        return result;
 }
 
index 118d7d8477155fd947f3735f0fc7674815de9a23..4167373327d91a051f99d158af7bf3a6f8323669 100644 (file)
@@ -410,8 +410,6 @@ const struct ti_bandgap_data dra752_data = {
                .domain = "cpu",
                .register_cooling = ti_thermal_register_cpu_cooling,
                .unregister_cooling = ti_thermal_unregister_cpu_cooling,
-               .slope = DRA752_GRADIENT_SLOPE,
-               .constant = DRA752_GRADIENT_CONST,
                .slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB,
                .constant_pcb = DRA752_GRADIENT_CONST_W_PCB,
                },
@@ -419,8 +417,6 @@ const struct ti_bandgap_data dra752_data = {
                .registers = &dra752_gpu_temp_sensor_registers,
                .ts_data = &dra752_gpu_temp_sensor_data,
                .domain = "gpu",
-               .slope = DRA752_GRADIENT_SLOPE,
-               .constant = DRA752_GRADIENT_CONST,
                .slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB,
                .constant_pcb = DRA752_GRADIENT_CONST_W_PCB,
                },
@@ -428,8 +424,6 @@ const struct ti_bandgap_data dra752_data = {
                .registers = &dra752_core_temp_sensor_registers,
                .ts_data = &dra752_core_temp_sensor_data,
                .domain = "core",
-               .slope = DRA752_GRADIENT_SLOPE,
-               .constant = DRA752_GRADIENT_CONST,
                .slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB,
                .constant_pcb = DRA752_GRADIENT_CONST_W_PCB,
                },
@@ -437,8 +431,6 @@ const struct ti_bandgap_data dra752_data = {
                .registers = &dra752_dspeve_temp_sensor_registers,
                .ts_data = &dra752_dspeve_temp_sensor_data,
                .domain = "dspeve",
-               .slope = DRA752_GRADIENT_SLOPE,
-               .constant = DRA752_GRADIENT_CONST,
                .slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB,
                .constant_pcb = DRA752_GRADIENT_CONST_W_PCB,
                },
@@ -446,8 +438,6 @@ const struct ti_bandgap_data dra752_data = {
                .registers = &dra752_iva_temp_sensor_registers,
                .ts_data = &dra752_iva_temp_sensor_data,
                .domain = "iva",
-               .slope = DRA752_GRADIENT_SLOPE,
-               .constant = DRA752_GRADIENT_CONST,
                .slope_pcb = DRA752_GRADIENT_SLOPE_W_PCB,
                .constant_pcb = DRA752_GRADIENT_CONST_W_PCB,
                },
index 3ee34340edabca6de32e0e411735b56b20e0ce25..c6d217913dd1d89251b9a1a5f5bcc20724b555f6 100644 (file)
@@ -91,8 +91,6 @@ const struct ti_bandgap_data omap34xx_data = {
                .registers = &omap34xx_mpu_temp_sensor_registers,
                .ts_data = &omap34xx_mpu_temp_sensor_data,
                .domain = "cpu",
-               .slope = 0,
-               .constant = 20000,
                .slope_pcb = 0,
                .constant_pcb = 20000,
                .register_cooling = NULL,
@@ -164,8 +162,6 @@ const struct ti_bandgap_data omap36xx_data = {
                .registers = &omap36xx_mpu_temp_sensor_registers,
                .ts_data = &omap36xx_mpu_temp_sensor_data,
                .domain = "cpu",
-               .slope = 0,
-               .constant = 20000,
                .slope_pcb = 0,
                .constant_pcb = 20000,
                .register_cooling = NULL,
index d255d33da9eb328f358e3d40471a8ed2be355703..fd11133606038e40ffeb1d4c279496e3a327f5bd 100644 (file)
@@ -82,8 +82,6 @@ const struct ti_bandgap_data omap4430_data = {
                .registers = &omap4430_mpu_temp_sensor_registers,
                .ts_data = &omap4430_mpu_temp_sensor_data,
                .domain = "cpu",
-               .slope = OMAP_GRADIENT_SLOPE_4430,
-               .constant = OMAP_GRADIENT_CONST_4430,
                .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_4430,
                .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_4430,
                .register_cooling = ti_thermal_register_cpu_cooling,
@@ -222,8 +220,6 @@ const struct ti_bandgap_data omap4460_data = {
                .registers = &omap4460_mpu_temp_sensor_registers,
                .ts_data = &omap4460_mpu_temp_sensor_data,
                .domain = "cpu",
-               .slope = OMAP_GRADIENT_SLOPE_4460,
-               .constant = OMAP_GRADIENT_CONST_4460,
                .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_4460,
                .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_4460,
                .register_cooling = ti_thermal_register_cpu_cooling,
@@ -255,8 +251,6 @@ const struct ti_bandgap_data omap4470_data = {
                .registers = &omap4460_mpu_temp_sensor_registers,
                .ts_data = &omap4460_mpu_temp_sensor_data,
                .domain = "cpu",
-               .slope = OMAP_GRADIENT_SLOPE_4470,
-               .constant = OMAP_GRADIENT_CONST_4470,
                .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_4470,
                .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_4470,
                .register_cooling = ti_thermal_register_cpu_cooling,
index 79ff70c446ba195ef893125b377567ff4ac2e58b..cd9a304fb571ce7749aebad6d93606b4fce503de 100644 (file)
@@ -336,8 +336,6 @@ const struct ti_bandgap_data omap5430_data = {
                .domain = "cpu",
                .register_cooling = ti_thermal_register_cpu_cooling,
                .unregister_cooling = ti_thermal_unregister_cpu_cooling,
-               .slope = OMAP_GRADIENT_SLOPE_5430_CPU,
-               .constant = OMAP_GRADIENT_CONST_5430_CPU,
                .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_5430_CPU,
                .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_5430_CPU,
                },
@@ -345,8 +343,6 @@ const struct ti_bandgap_data omap5430_data = {
                .registers = &omap5430_gpu_temp_sensor_registers,
                .ts_data = &omap5430_gpu_temp_sensor_data,
                .domain = "gpu",
-               .slope = OMAP_GRADIENT_SLOPE_5430_GPU,
-               .constant = OMAP_GRADIENT_CONST_5430_GPU,
                .slope_pcb = OMAP_GRADIENT_SLOPE_W_PCB_5430_GPU,
                .constant_pcb = OMAP_GRADIENT_CONST_W_PCB_5430_GPU,
                },
index fe0adb898764901b841d31b3696c5b5c15f15cac..209c664c28235a57aec27fd0d23dbf616b9641d8 100644 (file)
@@ -254,8 +254,6 @@ struct ti_bandgap {
  * @ts_data: pointer to struct with thresholds, limits of temperature sensor
  * @registers: pointer to the list of register offsets and bitfields
  * @domain: the name of the domain where the sensor is located
- * @slope: sensor gradient slope info for hotspot extrapolation equation
- * @constant: sensor gradient const info for hotspot extrapolation equation
  * @slope_pcb: sensor gradient slope info for hotspot extrapolation equation
  *             with no external influence
  * @constant_pcb: sensor gradient const info for hotspot extrapolation equation
@@ -274,8 +272,6 @@ struct ti_temp_sensor {
        struct temp_sensor_registers    *registers;
        char                            *domain;
        /* for hotspot extrapolation */
-       const int                       slope;
-       const int                       constant;
        const int                       slope_pcb;
        const int                       constant_pcb;
        int (*register_cooling)(struct ti_bandgap *bgp, int id);
index 0586bd0f2bab676f1c780bc1bc0499919ed5f88e..02790f69e26cec5ea5ed1a51c7993457a189e11b 100644 (file)
@@ -96,8 +96,8 @@ static inline int __ti_thermal_get_temp(void *devdata, int *temp)
                return ret;
 
        /* Default constants */
-       slope = s->slope;
-       constant = s->constant;
+       slope = thermal_zone_get_slope(data->ti_thermal);
+       constant = thermal_zone_get_offset(data->ti_thermal);
 
        pcb_tz = data->pcb_tz;
        /* In case pcb zone is available, use the extrapolation rule with it */
@@ -126,119 +126,6 @@ static inline int ti_thermal_get_temp(struct thermal_zone_device *thermal,
        return __ti_thermal_get_temp(data, temp);
 }
 
-/* Bind callback functions for thermal zone */
-static int ti_thermal_bind(struct thermal_zone_device *thermal,
-                          struct thermal_cooling_device *cdev)
-{
-       struct ti_thermal_data *data = thermal->devdata;
-       int id;
-
-       if (!data || IS_ERR(data))
-               return -ENODEV;
-
-       /* check if this is the cooling device we registered */
-       if (data->cool_dev != cdev)
-               return 0;
-
-       id = data->sensor_id;
-
-       /* Simple thing, two trips, one passive another critical */
-       return thermal_zone_bind_cooling_device(thermal, 0, cdev,
-       /* bind with min and max states defined by cpu_cooling */
-                                               THERMAL_NO_LIMIT,
-                                               THERMAL_NO_LIMIT,
-                                               THERMAL_WEIGHT_DEFAULT);
-}
-
-/* Unbind callback functions for thermal zone */
-static int ti_thermal_unbind(struct thermal_zone_device *thermal,
-                            struct thermal_cooling_device *cdev)
-{
-       struct ti_thermal_data *data = thermal->devdata;
-
-       if (!data || IS_ERR(data))
-               return -ENODEV;
-
-       /* check if this is the cooling device we registered */
-       if (data->cool_dev != cdev)
-               return 0;
-
-       /* Simple thing, two trips, one passive another critical */
-       return thermal_zone_unbind_cooling_device(thermal, 0, cdev);
-}
-
-/* Get mode callback functions for thermal zone */
-static int ti_thermal_get_mode(struct thermal_zone_device *thermal,
-                              enum thermal_device_mode *mode)
-{
-       struct ti_thermal_data *data = thermal->devdata;
-
-       if (data)
-               *mode = data->mode;
-
-       return 0;
-}
-
-/* Set mode callback functions for thermal zone */
-static int ti_thermal_set_mode(struct thermal_zone_device *thermal,
-                              enum thermal_device_mode mode)
-{
-       struct ti_thermal_data *data = thermal->devdata;
-       struct ti_bandgap *bgp;
-
-       bgp = data->bgp;
-
-       if (!data->ti_thermal) {
-               dev_notice(&thermal->device, "thermal zone not registered\n");
-               return 0;
-       }
-
-       mutex_lock(&data->ti_thermal->lock);
-
-       if (mode == THERMAL_DEVICE_ENABLED)
-               data->ti_thermal->polling_delay = FAST_TEMP_MONITORING_RATE;
-       else
-               data->ti_thermal->polling_delay = 0;
-
-       mutex_unlock(&data->ti_thermal->lock);
-
-       data->mode = mode;
-       ti_bandgap_write_update_interval(bgp, data->sensor_id,
-                                       data->ti_thermal->polling_delay);
-       thermal_zone_device_update(data->ti_thermal, THERMAL_EVENT_UNSPECIFIED);
-       dev_dbg(&thermal->device, "thermal polling set for duration=%d msec\n",
-               data->ti_thermal->polling_delay);
-
-       return 0;
-}
-
-/* Get trip type callback functions for thermal zone */
-static int ti_thermal_get_trip_type(struct thermal_zone_device *thermal,
-                                   int trip, enum thermal_trip_type *type)
-{
-       if (!ti_thermal_is_valid_trip(trip))
-               return -EINVAL;
-
-       if (trip + 1 == OMAP_TRIP_NUMBER)
-               *type = THERMAL_TRIP_CRITICAL;
-       else
-               *type = THERMAL_TRIP_PASSIVE;
-
-       return 0;
-}
-
-/* Get trip temperature callback functions for thermal zone */
-static int ti_thermal_get_trip_temp(struct thermal_zone_device *thermal,
-                                   int trip, int *temp)
-{
-       if (!ti_thermal_is_valid_trip(trip))
-               return -EINVAL;
-
-       *temp = ti_thermal_get_trip_value(trip);
-
-       return 0;
-}
-
 static int __ti_thermal_get_trend(void *p, int trip, enum thermal_trend *trend)
 {
        struct ti_thermal_data *data = p;
@@ -262,38 +149,11 @@ static int __ti_thermal_get_trend(void *p, int trip, enum thermal_trend *trend)
        return 0;
 }
 
-/* Get the temperature trend callback functions for thermal zone */
-static int ti_thermal_get_trend(struct thermal_zone_device *thermal,
-                               int trip, enum thermal_trend *trend)
-{
-       return __ti_thermal_get_trend(thermal->devdata, trip, trend);
-}
-
-/* Get critical temperature callback functions for thermal zone */
-static int ti_thermal_get_crit_temp(struct thermal_zone_device *thermal,
-                                   int *temp)
-{
-       /* shutdown zone */
-       return ti_thermal_get_trip_temp(thermal, OMAP_TRIP_NUMBER - 1, temp);
-}
-
 static const struct thermal_zone_of_device_ops ti_of_thermal_ops = {
        .get_temp = __ti_thermal_get_temp,
        .get_trend = __ti_thermal_get_trend,
 };
 
-static struct thermal_zone_device_ops ti_thermal_ops = {
-       .get_temp = ti_thermal_get_temp,
-       .get_trend = ti_thermal_get_trend,
-       .bind = ti_thermal_bind,
-       .unbind = ti_thermal_unbind,
-       .get_mode = ti_thermal_get_mode,
-       .set_mode = ti_thermal_set_mode,
-       .get_trip_type = ti_thermal_get_trip_type,
-       .get_trip_temp = ti_thermal_get_trip_temp,
-       .get_crit_temp = ti_thermal_get_crit_temp,
-};
-
 static struct ti_thermal_data
 *ti_thermal_build_data(struct ti_bandgap *bgp, int id)
 {
@@ -331,18 +191,10 @@ int ti_thermal_expose_sensor(struct ti_bandgap *bgp, int id,
        data->ti_thermal = devm_thermal_zone_of_sensor_register(bgp->dev, id,
                                        data, &ti_of_thermal_ops);
        if (IS_ERR(data->ti_thermal)) {
-               /* Create thermal zone */
-               data->ti_thermal = thermal_zone_device_register(domain,
-                               OMAP_TRIP_NUMBER, 0, data, &ti_thermal_ops,
-                               NULL, FAST_TEMP_MONITORING_RATE,
-                               FAST_TEMP_MONITORING_RATE);
-               if (IS_ERR(data->ti_thermal)) {
-                       dev_err(bgp->dev, "thermal zone device is NULL\n");
-                       return PTR_ERR(data->ti_thermal);
-               }
-               data->ti_thermal->polling_delay = FAST_TEMP_MONITORING_RATE;
-               data->our_zone = true;
+               dev_err(bgp->dev, "thermal zone device is NULL\n");
+               return PTR_ERR(data->ti_thermal);
        }
+
        ti_bandgap_set_sensor_data(bgp, id, data);
        ti_bandgap_write_update_interval(bgp, data->sensor_id,
                                        data->ti_thermal->polling_delay);
index f8b7ffea6194f25662e5919463896ba936392861..8e85ca973967d9525f41b0747ebd0f4725d1b4dc 100644 (file)
 
 #include "ti-bandgap.h"
 
-/* sensors gradient and offsets */
-#define OMAP_GRADIENT_SLOPE_4430                               0
-#define OMAP_GRADIENT_CONST_4430                               20000
-#define OMAP_GRADIENT_SLOPE_4460                               348
-#define OMAP_GRADIENT_CONST_4460                               -9301
-#define OMAP_GRADIENT_SLOPE_4470                               308
-#define OMAP_GRADIENT_CONST_4470                               -7896
-
-#define OMAP_GRADIENT_SLOPE_5430_CPU                           65
-#define OMAP_GRADIENT_CONST_5430_CPU                           -1791
-#define OMAP_GRADIENT_SLOPE_5430_GPU                           117
-#define OMAP_GRADIENT_CONST_5430_GPU                           -2992
-
-#define DRA752_GRADIENT_SLOPE                                  0
-#define DRA752_GRADIENT_CONST                                  2000
-
 /* PCB sensor calculation constants */
 #define OMAP_GRADIENT_SLOPE_W_PCB_4430                         0
 #define OMAP_GRADIENT_CONST_W_PCB_4430                         20000
index b95bed92da9f050c576ce891309876cf53c837af..f02becdb3e33850c368d2903656ebf16265c654c 100644 (file)
@@ -1,5 +1,6 @@
 obj-$(CONFIG_TTY)              += tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o \
-                                  tty_buffer.o tty_port.o tty_mutex.o tty_ldsem.o
+                                  tty_buffer.o tty_port.o tty_mutex.o \
+                                  tty_ldsem.o tty_baudrate.o tty_jobctrl.o
 obj-$(CONFIG_LEGACY_PTYS)      += pty.o
 obj-$(CONFIG_UNIX98_PTYS)      += pty.o
 obj-$(CONFIG_AUDIT)            += tty_audit.o
index 5e4fa920686151f94042af7b9e193d3d0486481f..104f09c58163ca5e135abbd7b4fe5907249a66fc 100644 (file)
@@ -156,8 +156,8 @@ static unsigned int cy_isa_addresses[] = {
 static long maddr[NR_CARDS];
 static int irq[NR_CARDS];
 
-module_param_array(maddr, long, NULL, 0);
-module_param_array(irq, int, NULL, 0);
+module_param_hw_array(maddr, long, iomem, NULL, 0);
+module_param_hw_array(irq, int, irq, NULL, 0);
 
 #endif                         /* CONFIG_ISA */
 
index b19ae36a05ec753c4edade42ff1f55c036a28c8a..a8d399188242efe428bb579f845b716396465d9f 100644 (file)
@@ -920,17 +920,17 @@ int hvc_remove(struct hvc_struct *hp)
 
        tty = tty_port_tty_get(&hp->port);
 
+       console_lock();
        spin_lock_irqsave(&hp->lock, flags);
        if (hp->index < MAX_NR_HVC_CONSOLES) {
-               console_lock();
                vtermnos[hp->index] = -1;
                cons_ops[hp->index] = NULL;
-               console_unlock();
        }
 
        /* Don't whack hp->irq because tty_hangup() will need to free the irq. */
 
        spin_unlock_irqrestore(&hp->lock, flags);
+       console_unlock();
 
        /*
         * We 'put' the instance that was grabbed when the kref instance
index 7823d6d998cfd8ca70ab32eb2f51f43c34ef9f3c..99bb875178d7170f50d6500a3d6ec5fb8be757b0 100644 (file)
@@ -1575,7 +1575,7 @@ static int __init hvcs_module_init(void)
         */
        rc = driver_create_file(&(hvcs_vio_driver.driver), &driver_attr_rescan);
        if (rc)
-               pr_warning("HVCS: Failed to create rescan file (err %d)\n", rc);
+               pr_warn("HVCS: Failed to create rescan file (err %d)\n", rc);
 
        return 0;
 }
index 4caf0c3b1f99569935a221ee92a383b3697aca58..3b251f4e5df046e3d8028f4ed5a86deba5fa0b04 100644 (file)
@@ -179,7 +179,7 @@ MODULE_FIRMWARE("c320tunx.cod");
 
 module_param_array(type, uint, NULL, 0);
 MODULE_PARM_DESC(type, "card type: C218=2, C320=4");
-module_param_array(baseaddr, ulong, NULL, 0);
+module_param_hw_array(baseaddr, ulong, ioport, NULL, 0);
 MODULE_PARM_DESC(baseaddr, "base address");
 module_param_array(numports, uint, NULL, 0);
 MODULE_PARM_DESC(numports, "numports (ignored for C218)");
index 7b8f383fb090ca8836e0fbc58fff80c190cb516b..8bd6fb6d9391fe419e0a2553ffe6f82f59c469fe 100644 (file)
@@ -183,7 +183,7 @@ static int ttymajor = MXSERMAJOR;
 
 MODULE_AUTHOR("Casper Yang");
 MODULE_DESCRIPTION("MOXA Smartio/Industio Family Multiport Board Device Driver");
-module_param_array(ioaddr, ulong, NULL, 0);
+module_param_hw_array(ioaddr, ulong, ioport, NULL, 0);
 MODULE_PARM_DESC(ioaddr, "ISA io addresses to look for a moxa board");
 module_param(ttymajor, int, 0);
 MODULE_LICENSE("GPL");
index 55577cf9b6a4e0eba43462bba0bd5b5039172f17..2667a205a5abcf47ed4ab059ff350b5f35ea3fe1 100644 (file)
@@ -89,18 +89,14 @@ module_param(debug, int, 0600);
 /**
  *     struct gsm_mux_net      -       network interface
  *     @struct gsm_dlci* dlci
- *     @struct net_device_stats stats;
  *
  *     Created when net interface is initialized.
  **/
 struct gsm_mux_net {
        struct kref ref;
        struct gsm_dlci *dlci;
-       struct net_device_stats stats;
 };
 
-#define STATS(net) (((struct gsm_mux_net *)netdev_priv(net))->stats)
-
 /*
  *     Each block of data we have queued to go out is in the form of
  *     a gsm_msg which holds everything we need in a link layer independent
@@ -2613,10 +2609,6 @@ static int gsm_mux_net_close(struct net_device *net)
        return 0;
 }
 
-static struct net_device_stats *gsm_mux_net_get_stats(struct net_device *net)
-{
-       return &((struct gsm_mux_net *)netdev_priv(net))->stats;
-}
 static void dlci_net_free(struct gsm_dlci *dlci)
 {
        if (!dlci->net) {
@@ -2660,8 +2652,8 @@ static int gsm_mux_net_start_xmit(struct sk_buff *skb,
        muxnet_get(mux_net);
 
        skb_queue_head(&dlci->skb_list, skb);
-       STATS(net).tx_packets++;
-       STATS(net).tx_bytes += skb->len;
+       net->stats.tx_packets++;
+       net->stats.tx_bytes += skb->len;
        gsm_dlci_data_kick(dlci);
        /* And tell the kernel when the last transmit started. */
        netif_trans_update(net);
@@ -2676,7 +2668,7 @@ static void gsm_mux_net_tx_timeout(struct net_device *net)
        dev_dbg(&net->dev, "Tx timed out.\n");
 
        /* Update statistics */
-       STATS(net).tx_errors++;
+       net->stats.tx_errors++;
 }
 
 static void gsm_mux_rx_netchar(struct gsm_dlci *dlci,
@@ -2691,7 +2683,7 @@ static void gsm_mux_rx_netchar(struct gsm_dlci *dlci,
        skb = dev_alloc_skb(size + NET_IP_ALIGN);
        if (!skb) {
                /* We got no receive buffer. */
-               STATS(net).rx_dropped++;
+               net->stats.rx_dropped++;
                muxnet_put(mux_net);
                return;
        }
@@ -2705,8 +2697,8 @@ static void gsm_mux_rx_netchar(struct gsm_dlci *dlci,
        netif_rx(skb);
 
        /* update out statistics */
-       STATS(net).rx_packets++;
-       STATS(net).rx_bytes += size;
+       net->stats.rx_packets++;
+       net->stats.rx_bytes += size;
        muxnet_put(mux_net);
        return;
 }
@@ -2718,7 +2710,6 @@ static void gsm_mux_net_init(struct net_device *net)
                .ndo_stop               = gsm_mux_net_close,
                .ndo_start_xmit         = gsm_mux_net_start_xmit,
                .ndo_tx_timeout         = gsm_mux_net_tx_timeout,
-               .ndo_get_stats          = gsm_mux_net_get_stats,
        };
 
        net->netdev_ops = &gsm_netdev_ops;
index e94aea8c0d0535cbc05933bb02067263e62e8292..7b2a466616d6ef7acb2bc3ce8d773be9e4446375 100644 (file)
@@ -939,11 +939,11 @@ static struct n_hdlc_buf *n_hdlc_buf_get(struct n_hdlc_buf_list *buf_list)
        return buf;
 }      /* end of n_hdlc_buf_get() */
 
-static char hdlc_banner[] __initdata =
+static const char hdlc_banner[] __initconst =
        KERN_INFO "HDLC line discipline maxframe=%u\n";
-static char hdlc_register_ok[] __initdata =
+static const char hdlc_register_ok[] __initconst =
        KERN_INFO "N_HDLC line discipline registered.\n";
-static char hdlc_register_fail[] __initdata =
+static const char hdlc_register_fail[] __initconst =
        KERN_ERR "error registering line discipline: %d\n";
 
 static int __init n_hdlc_init(void)
@@ -968,9 +968,9 @@ static int __init n_hdlc_init(void)
        
 }      /* end of init_module() */
 
-static char hdlc_unregister_ok[] __exitdata =
+static const char hdlc_unregister_ok[] __exitdata =
        KERN_INFO "N_HDLC: line discipline unregistered\n";
-static char hdlc_unregister_fail[] __exitdata =
+static const char hdlc_unregister_fail[] __exitdata =
        KERN_ERR "N_HDLC: can't unregister line discipline (err = %d)\n";
 
 static void __exit n_hdlc_exit(void)
index 66b59a15780db0c33021d32251ecb9886c758703..65799575c66681184057cc0565e5a45bcdd25681 100644 (file)
@@ -216,16 +216,11 @@ static int pty_signal(struct tty_struct *tty, int sig)
 static void pty_flush_buffer(struct tty_struct *tty)
 {
        struct tty_struct *to = tty->link;
-       struct tty_ldisc *ld;
 
        if (!to)
                return;
 
-       ld = tty_ldisc_ref(to);
-       tty_buffer_flush(to, ld);
-       if (ld)
-               tty_ldisc_deref(ld);
-
+       tty_buffer_flush(to, NULL);
        if (to->packet) {
                spin_lock_irq(&tty->ctrl_lock);
                tty->ctrl_status |= TIOCPKT_FLUSHWRITE;
index d66c1edd98926d5d410895ba8a39b1ed82d10340..b51a877da986d90719cdad9d0dfd7a1e148088e1 100644 (file)
@@ -250,15 +250,15 @@ static int sReadAiopNumChan(WordIO_t io);
 
 MODULE_AUTHOR("Theodore Ts'o");
 MODULE_DESCRIPTION("Comtrol RocketPort driver");
-module_param(board1, ulong, 0);
+module_param_hw(board1, ulong, ioport, 0);
 MODULE_PARM_DESC(board1, "I/O port for (ISA) board #1");
-module_param(board2, ulong, 0);
+module_param_hw(board2, ulong, ioport, 0);
 MODULE_PARM_DESC(board2, "I/O port for (ISA) board #2");
-module_param(board3, ulong, 0);
+module_param_hw(board3, ulong, ioport, 0);
 MODULE_PARM_DESC(board3, "I/O port for (ISA) board #3");
-module_param(board4, ulong, 0);
+module_param_hw(board4, ulong, ioport, 0);
 MODULE_PARM_DESC(board4, "I/O port for (ISA) board #4");
-module_param(controller, ulong, 0);
+module_param_hw(controller, ulong, ioport, 0);
 MODULE_PARM_DESC(controller, "I/O port for (ISA) rocketport controller");
 module_param(support_low_speed, bool, 0);
 MODULE_PARM_DESC(support_low_speed, "1 means support 50 baud, 0 means support 460400 baud");
index 1c4829a56351d4fa1bda397afa09004680d0cab4..433de5ea9b02f53386b9367e64ad880ac6795e07 100644 (file)
@@ -116,17 +116,41 @@ void serdev_device_close(struct serdev_device *serdev)
 }
 EXPORT_SYMBOL_GPL(serdev_device_close);
 
-int serdev_device_write_buf(struct serdev_device *serdev,
-                           const unsigned char *buf, size_t count)
+void serdev_device_write_wakeup(struct serdev_device *serdev)
+{
+       complete(&serdev->write_comp);
+}
+EXPORT_SYMBOL_GPL(serdev_device_write_wakeup);
+
+int serdev_device_write(struct serdev_device *serdev,
+                       const unsigned char *buf, size_t count,
+                       unsigned long timeout)
 {
        struct serdev_controller *ctrl = serdev->ctrl;
+       int ret;
 
-       if (!ctrl || !ctrl->ops->write_buf)
+       if (!ctrl || !ctrl->ops->write_buf ||
+           (timeout && !serdev->ops->write_wakeup))
                return -EINVAL;
 
-       return ctrl->ops->write_buf(ctrl, buf, count);
+       mutex_lock(&serdev->write_lock);
+       do {
+               reinit_completion(&serdev->write_comp);
+
+               ret = ctrl->ops->write_buf(ctrl, buf, count);
+               if (ret < 0)
+                       break;
+
+               buf += ret;
+               count -= ret;
+
+       } while (count &&
+                (timeout = wait_for_completion_timeout(&serdev->write_comp,
+                                                       timeout)));
+       mutex_unlock(&serdev->write_lock);
+       return ret < 0 ? ret : (count ? -ETIMEDOUT : 0);
 }
-EXPORT_SYMBOL_GPL(serdev_device_write_buf);
+EXPORT_SYMBOL_GPL(serdev_device_write);
 
 void serdev_device_write_flush(struct serdev_device *serdev)
 {
@@ -262,6 +286,8 @@ struct serdev_device *serdev_device_alloc(struct serdev_controller *ctrl)
        serdev->dev.parent = &ctrl->dev;
        serdev->dev.bus = &serdev_bus_type;
        serdev->dev.type = &serdev_device_type;
+       init_completion(&serdev->write_comp);
+       mutex_init(&serdev->write_lock);
        return serdev;
 }
 EXPORT_SYMBOL_GPL(serdev_device_alloc);
index 76e03a7de9cc3d790a230948f599ef2db4b93249..1aab3010fbfae76e2c25cb60085f21051a1f24cf 100644 (file)
@@ -218,7 +218,7 @@ static int serial_link_irq_chain(struct uart_8250_port *up)
                spin_unlock_irq(&i->lock);
                irq_flags |= up->port.irqflags;
                ret = request_irq(up->port.irq, serial8250_interrupt,
-                                 irq_flags, "serial", i);
+                                 irq_flags, up->port.name, i);
                if (ret < 0)
                        serial_do_unlink(i, up);
        }
@@ -1191,7 +1191,7 @@ module_exit(serial8250_exit);
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Generic 8250/16x50 serial driver");
 
-module_param(share_irqs, uint, 0644);
+module_param_hw(share_irqs, uint, other, 0644);
 MODULE_PARM_DESC(share_irqs, "Share IRQs with other non-8250/16x50 devices (unsafe)");
 
 module_param(nr_uarts, uint, 0644);
@@ -1201,7 +1201,7 @@ module_param(skip_txen_test, uint, 0644);
 MODULE_PARM_DESC(skip_txen_test, "Skip checking for the TXEN bug at init time");
 
 #ifdef CONFIG_SERIAL_8250_RSA
-module_param_array(probe_rsa, ulong, &probe_rsa_count, 0444);
+module_param_hw_array(probe_rsa, ulong, ioport, &probe_rsa_count, 0444);
 MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA");
 #endif
 MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR);
index e65808c482f1847d09d819a24defb0e5cf6508b5..787b1160d3a535aceafc40f742652deb9d5f2182 100644 (file)
@@ -530,12 +530,11 @@ static int dw8250_probe(struct platform_device *pdev)
        }
 
        data->rst = devm_reset_control_get_optional(dev, NULL);
-       if (IS_ERR(data->rst) && PTR_ERR(data->rst) == -EPROBE_DEFER) {
-               err = -EPROBE_DEFER;
+       if (IS_ERR(data->rst)) {
+               err = PTR_ERR(data->rst);
                goto err_pclk;
        }
-       if (!IS_ERR(data->rst))
-               reset_control_deassert(data->rst);
+       reset_control_deassert(data->rst);
 
        dw8250_quirks(p, data);
 
@@ -567,8 +566,7 @@ static int dw8250_probe(struct platform_device *pdev)
        return 0;
 
 err_reset:
-       if (!IS_ERR(data->rst))
-               reset_control_assert(data->rst);
+       reset_control_assert(data->rst);
 
 err_pclk:
        if (!IS_ERR(data->pclk))
@@ -589,8 +587,7 @@ static int dw8250_remove(struct platform_device *pdev)
 
        serial8250_unregister_port(data->line);
 
-       if (!IS_ERR(data->rst))
-               reset_control_assert(data->rst);
+       reset_control_assert(data->rst);
 
        if (!IS_ERR(data->pclk))
                clk_disable_unprepare(data->pclk);
index 85a12f03240247494366a231d24fa86ba042dfdb..82fc48eca1df705521c99036d1a0d7f6e7d63402 100644 (file)
@@ -39,6 +39,7 @@
 
 static unsigned int __init serial8250_early_in(struct uart_port *port, int offset)
 {
+       int reg_offset = offset;
        offset <<= port->regshift;
 
        switch (port->iotype) {
@@ -52,6 +53,8 @@ static unsigned int __init serial8250_early_in(struct uart_port *port, int offse
                return ioread32be(port->membase + offset);
        case UPIO_PORT:
                return inb(port->iobase + offset);
+       case UPIO_AU:
+               return port->serial_in(port, reg_offset);
        default:
                return 0;
        }
@@ -59,6 +62,7 @@ static unsigned int __init serial8250_early_in(struct uart_port *port, int offse
 
 static void __init serial8250_early_out(struct uart_port *port, int offset, int value)
 {
+       int reg_offset = offset;
        offset <<= port->regshift;
 
        switch (port->iotype) {
@@ -77,6 +81,9 @@ static void __init serial8250_early_out(struct uart_port *port, int offset, int
        case UPIO_PORT:
                outb(value, port->iobase + offset);
                break;
+       case UPIO_AU:
+               port->serial_out(port, reg_offset, value);
+               break;
        }
 }
 
@@ -172,3 +179,20 @@ OF_EARLYCON_DECLARE(omap8250, "ti,omap3-uart", early_omap8250_setup);
 OF_EARLYCON_DECLARE(omap8250, "ti,omap4-uart", early_omap8250_setup);
 
 #endif
+
+#ifdef CONFIG_SERIAL_8250_RT288X
+
+unsigned int au_serial_in(struct uart_port *p, int offset);
+void au_serial_out(struct uart_port *p, int offset, int value);
+
+static int __init early_au_setup(struct earlycon_device *dev, const char *opt)
+{
+       dev->port.serial_in = au_serial_in;
+       dev->port.serial_out = au_serial_out;
+       dev->port.iotype = UPIO_AU;
+       dev->con->write = early_serial8250_write;
+       return 0;
+}
+OF_EARLYCON_DECLARE(palmchip, "ralink,rt2880-uart", early_au_setup);
+
+#endif
index b89c4ffc048655dc65c241afef5bfb21c13841bd..1270ff163f637bf5c61f7cbf3ad3ff51c69366b9 100644 (file)
@@ -483,5 +483,5 @@ static struct pci_driver exar_pci_driver = {
 module_pci_driver(exar_pci_driver);
 
 MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Exar Serial Dricer");
+MODULE_DESCRIPTION("Exar Serial Driver");
 MODULE_AUTHOR("Sudip Mukherjee <sudip.mukherjee@codethink.co.uk>");
index b67e7a5449353ca8ac2f3a67e0af132517c4f643..e500f7dd2470a28254b1d8d57374a4fbd0fc02fa 100644 (file)
  * The IRQ setting mode of F81866 is not the same with F81216 series.
  *     Level/Low: IRQ_MODE0:0, IRQ_MODE1:0
  *     Edge/High: IRQ_MODE0:1, IRQ_MODE1:0
+ *
+ * Clock speeds for UART (register F2h)
+ * 00: 1.8432MHz.
+ * 01: 18.432MHz.
+ * 10: 24MHz.
+ * 11: 14.769MHz.
  */
 #define F81866_IRQ_MODE                0xf0
 #define F81866_IRQ_SHARE       BIT(0)
 #define F81866_LDN_LOW         0x10
 #define F81866_LDN_HIGH                0x16
 
+#define F81866_UART_CLK 0xF2
+#define F81866_UART_CLK_MASK (BIT(1) | BIT(0))
+#define F81866_UART_CLK_1_8432MHZ 0
+#define F81866_UART_CLK_14_769MHZ (BIT(1) | BIT(0))
+#define F81866_UART_CLK_18_432MHZ BIT(0)
+#define F81866_UART_CLK_24MHZ BIT(1)
+
 struct fintek_8250 {
        u16 pid;
        u16 base_port;
@@ -256,8 +269,26 @@ static void fintek_8250_set_max_fifo(struct fintek_8250 *pdata)
        }
 }
 
-static int probe_setup_port(struct fintek_8250 *pdata, u16 io_address,
-                         unsigned int irq)
+static void fintek_8250_goto_highspeed(struct uart_8250_port *uart,
+                             struct fintek_8250 *pdata)
+{
+       sio_write_reg(pdata, LDN, pdata->index);
+
+       switch (pdata->pid) {
+       case CHIP_ID_F81866: /* set uart clock for high speed serial mode */
+               sio_write_mask_reg(pdata, F81866_UART_CLK,
+                       F81866_UART_CLK_MASK,
+                       F81866_UART_CLK_14_769MHZ);
+
+                       uart->port.uartclk = 921600 * 16;
+               break;
+       default: /* leave clock speed untouched */
+               break;
+       }
+}
+
+static int probe_setup_port(struct fintek_8250 *pdata,
+                                       struct uart_8250_port *uart)
 {
        static const u16 addr[] = {0x4e, 0x2e};
        static const u8 keys[] = {0x77, 0xa0, 0x87, 0x67};
@@ -284,18 +315,20 @@ static int probe_setup_port(struct fintek_8250 *pdata, u16 io_address,
                                sio_write_reg(pdata, LDN, k);
                                aux = sio_read_reg(pdata, IO_ADDR1);
                                aux |= sio_read_reg(pdata, IO_ADDR2) << 8;
-                               if (aux != io_address)
+                               if (aux != uart->port.iobase)
                                        continue;
 
                                pdata->index = k;
 
-                               irq_data = irq_get_irq_data(irq);
+                               irq_data = irq_get_irq_data(uart->port.irq);
                                if (irq_data)
                                        level_mode =
                                                irqd_is_level_type(irq_data);
 
                                fintek_8250_set_irq_mode(pdata, level_mode);
                                fintek_8250_set_max_fifo(pdata);
+                               fintek_8250_goto_highspeed(uart, pdata);
+
                                fintek_8250_exit_key(addr[i]);
 
                                return 0;
@@ -330,7 +363,7 @@ int fintek_8250_probe(struct uart_8250_port *uart)
        struct fintek_8250 *pdata;
        struct fintek_8250 probe_data;
 
-       if (probe_setup_port(&probe_data, uart->port.iobase, uart->port.irq))
+       if (probe_setup_port(&probe_data, uart))
                return -ENODEV;
 
        pdata = devm_kzalloc(uart->port.dev, sizeof(*pdata), GFP_KERNEL);
index f3ea90f0e411bcec99312d51fe77b0af88377006..7dddd7e6a01cbd45308efe1860fc34ddd154275c 100644 (file)
@@ -183,7 +183,6 @@ static void qrk_serial_setup_dma(struct lpss8250 *lpss, struct uart_port *port)
        if (ret)
                return;
 
-       pci_set_master(pdev);
        pci_try_set_mwi(pdev);
 
        /* Special DMA address for UART */
@@ -216,6 +215,8 @@ static int qrk_serial_setup(struct lpss8250 *lpss, struct uart_port *port)
        struct pci_dev *pdev = to_pci_dev(port->dev);
        int ret;
 
+       pci_set_master(pdev);
+
        ret = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES);
        if (ret < 0)
                return ret;
index 6119516ef5fcd3a604ae0a41a70b9f6f51f7fa1d..09a65a3ec7f7df0bb3f7355fd7758d797169f960 100644 (file)
@@ -328,7 +328,7 @@ static const s8 au_io_out_map[8] = {
        -1,     /* UART_SCR (unmapped) */
 };
 
-static unsigned int au_serial_in(struct uart_port *p, int offset)
+unsigned int au_serial_in(struct uart_port *p, int offset)
 {
        if (offset >= ARRAY_SIZE(au_io_in_map))
                return UINT_MAX;
@@ -338,7 +338,7 @@ static unsigned int au_serial_in(struct uart_port *p, int offset)
        return __raw_readl(p->membase + (offset << p->regshift));
 }
 
-static void au_serial_out(struct uart_port *p, int offset, int value)
+void au_serial_out(struct uart_port *p, int offset, int value)
 {
        if (offset >= ARRAY_SIZE(au_io_out_map))
                return;
index 6117ac8da48f739fc4bf904b5a52db31b5861b50..5c8850f7a2a05a252ccf4762f1b594fd67697877 100644 (file)
@@ -630,6 +630,15 @@ config SERIAL_UARTLITE_CONSOLE
          console (the system console is the device which receives all kernel
          messages and warnings and which allows logins in single user mode).
 
+config SERIAL_UARTLITE_NR_UARTS
+       int "Maximum number of uartlite serial ports"
+       depends on SERIAL_UARTLITE
+       range 1 256
+       default 1
+       help
+         Set this to the number of uartlites in your system, or the number
+         you think you might implement.
+
 config SERIAL_SUNCORE
        bool
        depends on SPARC
@@ -1343,6 +1352,7 @@ config SERIAL_ALTERA_JTAGUART_CONSOLE
        bool "Altera JTAG UART console support"
        depends on SERIAL_ALTERA_JTAGUART=y
        select SERIAL_CORE_CONSOLE
+       select SERIAL_EARLYCON
        help
          Enable a Altera JTAG UART port to be the system console.
 
@@ -1382,6 +1392,7 @@ config SERIAL_ALTERA_UART_CONSOLE
        bool "Altera UART console support"
        depends on SERIAL_ALTERA_UART=y
        select SERIAL_CORE_CONSOLE
+       select SERIAL_EARLYCON
        help
          Enable a Altera UART port to be the system console.
 
index 2d6288bc45543f4d68ada0e44538564230db79c6..53c03e005132105a6735e17fcbb132ca6d9582dc 100644 (file)
@@ -3,7 +3,6 @@
 #
 
 obj-$(CONFIG_SERIAL_CORE) += serial_core.o
-obj-$(CONFIG_SERIAL_21285) += 21285.o
 
 obj-$(CONFIG_SERIAL_EARLYCON) += earlycon.o
 obj-$(CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST) += earlycon-arm-semihost.o
@@ -17,6 +16,8 @@ obj-$(CONFIG_SERIAL_SUNZILOG) += sunzilog.o
 obj-$(CONFIG_SERIAL_SUNSU) += sunsu.o
 obj-$(CONFIG_SERIAL_SUNSAB) += sunsab.o
 
+obj-$(CONFIG_SERIAL_21285) += 21285.o
+
 # Now bring in any enabled 8250/16450/16550 type drivers.
 obj-$(CONFIG_SERIAL_8250) += 8250/
 
index e409d7dac7abfd5800a5b9a56d013cb569ca26f1..18e3f8342b8554ae4e7d414dd39653fb3a33b26f 100644 (file)
@@ -383,6 +383,26 @@ console_initcall(altera_jtaguart_console_init);
 
 #define        ALTERA_JTAGUART_CONSOLE (&altera_jtaguart_console)
 
+static void altera_jtaguart_earlycon_write(struct console *co, const char *s,
+                                          unsigned int count)
+{
+       struct earlycon_device *dev = co->data;
+
+       uart_console_write(&dev->port, s, count, altera_jtaguart_console_putc);
+}
+
+static int __init altera_jtaguart_earlycon_setup(struct earlycon_device *dev,
+                                                const char *options)
+{
+       if (!dev->port.membase)
+               return -ENODEV;
+
+       dev->con->write = altera_jtaguart_earlycon_write;
+       return 0;
+}
+
+OF_EARLYCON_DECLARE(juart, "altr,juart-1.0", altera_jtaguart_earlycon_setup);
+
 #else
 
 #define        ALTERA_JTAGUART_CONSOLE NULL
index 820a74208696bf57b275542ef810663c6ea175b7..46d3438a0d27014ce97115e7a17b0eb024f12035 100644 (file)
@@ -489,6 +489,38 @@ console_initcall(altera_uart_console_init);
 
 #define        ALTERA_UART_CONSOLE     (&altera_uart_console)
 
+static void altera_uart_earlycon_write(struct console *co, const char *s,
+                                      unsigned int count)
+{
+       struct earlycon_device *dev = co->data;
+
+       uart_console_write(&dev->port, s, count, altera_uart_console_putc);
+}
+
+static int __init altera_uart_earlycon_setup(struct earlycon_device *dev,
+                                            const char *options)
+{
+       struct uart_port *port = &dev->port;
+
+       if (!port->membase)
+               return -ENODEV;
+
+       /* Enable RX interrupts now */
+       writel(ALTERA_UART_CONTROL_RRDY_MSK,
+              port->membase + ALTERA_UART_CONTROL_REG);
+
+       if (dev->baud) {
+               unsigned int baudclk = port->uartclk / dev->baud;
+
+               writel(baudclk, port->membase + ALTERA_UART_DIVISOR_REG);
+       }
+
+       dev->con->write = altera_uart_earlycon_write;
+       return 0;
+}
+
+OF_EARLYCON_DECLARE(uart, "altr,uart-1.0", altera_uart_earlycon_setup);
+
 #else
 
 #define        ALTERA_UART_CONSOLE     NULL
index b0a377725d636c11cddad62470d821a31f1fff96..8a857bb34fbb26c6d60784d3fe7576730a9aa5b3 100644 (file)
@@ -1327,14 +1327,15 @@ static void pl011_stop_tx(struct uart_port *port)
        pl011_dma_tx_stop(uap);
 }
 
-static void pl011_tx_chars(struct uart_amba_port *uap, bool from_irq);
+static bool pl011_tx_chars(struct uart_amba_port *uap, bool from_irq);
 
 /* Start TX with programmed I/O only (no DMA) */
 static void pl011_start_tx_pio(struct uart_amba_port *uap)
 {
-       uap->im |= UART011_TXIM;
-       pl011_write(uap->im, uap, REG_IMSC);
-       pl011_tx_chars(uap, false);
+       if (pl011_tx_chars(uap, false)) {
+               uap->im |= UART011_TXIM;
+               pl011_write(uap->im, uap, REG_IMSC);
+       }
 }
 
 static void pl011_start_tx(struct uart_port *port)
@@ -1414,25 +1415,26 @@ static bool pl011_tx_char(struct uart_amba_port *uap, unsigned char c,
        return true;
 }
 
-static void pl011_tx_chars(struct uart_amba_port *uap, bool from_irq)
+/* Returns true if tx interrupts have to be (kept) enabled  */
+static bool pl011_tx_chars(struct uart_amba_port *uap, bool from_irq)
 {
        struct circ_buf *xmit = &uap->port.state->xmit;
        int count = uap->fifosize >> 1;
 
        if (uap->port.x_char) {
                if (!pl011_tx_char(uap, uap->port.x_char, from_irq))
-                       return;
+                       return true;
                uap->port.x_char = 0;
                --count;
        }
        if (uart_circ_empty(xmit) || uart_tx_stopped(&uap->port)) {
                pl011_stop_tx(&uap->port);
-               return;
+               return false;
        }
 
        /* If we are using DMA mode, try to send some characters. */
        if (pl011_dma_tx_irq(uap))
-               return;
+               return true;
 
        do {
                if (likely(from_irq) && count-- == 0)
@@ -1447,8 +1449,11 @@ static void pl011_tx_chars(struct uart_amba_port *uap, bool from_irq)
        if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
                uart_write_wakeup(&uap->port);
 
-       if (uart_circ_empty(xmit))
+       if (uart_circ_empty(xmit)) {
                pl011_stop_tx(&uap->port);
+               return false;
+       }
+       return true;
 }
 
 static void pl011_modem_status(struct uart_amba_port *uap)
@@ -2470,19 +2475,34 @@ static int __init pl011_early_console_setup(struct earlycon_device *device,
        if (!device->port.membase)
                return -ENODEV;
 
-       /* On QDF2400 SOCs affected by Erratum 44, the "qdf2400_e44" must
-        * also be specified, e.g. "earlycon=pl011,<address>,qdf2400_e44".
-        */
-       if (!strcmp(device->options, "qdf2400_e44"))
-               device->con->write = qdf2400_e44_early_write;
-       else
-               device->con->write = pl011_early_write;
+       device->con->write = pl011_early_write;
 
        return 0;
 }
 OF_EARLYCON_DECLARE(pl011, "arm,pl011", pl011_early_console_setup);
 OF_EARLYCON_DECLARE(pl011, "arm,sbsa-uart", pl011_early_console_setup);
-EARLYCON_DECLARE(qdf2400_e44, pl011_early_console_setup);
+
+/*
+ * On Qualcomm Datacenter Technologies QDF2400 SOCs affected by
+ * Erratum 44, traditional earlycon can be enabled by specifying
+ * "earlycon=qdf2400_e44,<address>".  Any options are ignored.
+ *
+ * Alternatively, you can just specify "earlycon", and the early console
+ * will be enabled with the information from the SPCR table.  In this
+ * case, the SPCR code will detect the need for the E44 work-around,
+ * and set the console name to "qdf2400_e44".
+ */
+static int __init
+qdf2400_e44_early_console_setup(struct earlycon_device *device,
+                               const char *opt)
+{
+       if (!device->port.membase)
+               return -ENODEV;
+
+       device->con->write = qdf2400_e44_early_write;
+       return 0;
+}
+EARLYCON_DECLARE(qdf2400_e44, qdf2400_e44_early_console_setup);
 
 #else
 #define AMBA_CONSOLE   NULL
index 1f50a83ef958609c3f27473b135e84e65303330d..c355ac9abafcc12adb5f8fd3205adaf4a16f86c1 100644 (file)
@@ -38,7 +38,6 @@
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
 #include <linux/atmel_pdc.h>
-#include <linux/atmel_serial.h>
 #include <linux/uaccess.h>
 #include <linux/platform_data/atmel.h>
 #include <linux/timer.h>
@@ -71,6 +70,7 @@
 #include <linux/serial_core.h>
 
 #include "serial_mctrl_gpio.h"
+#include "atmel_serial.h"
 
 static void atmel_start_rx(struct uart_port *port);
 static void atmel_stop_rx(struct uart_port *port);
@@ -119,8 +119,9 @@ struct atmel_uart_char {
 /*
  * at91: 6 USARTs and one DBGU port (SAM9260)
  * avr32: 4
+ * samx7: 3 USARTs and 5 UARTs
  */
-#define ATMEL_MAX_UART         7
+#define ATMEL_MAX_UART         8
 
 /*
  * We wrap our port structure around the generic uart_port.
@@ -175,6 +176,7 @@ struct atmel_uart_port {
        unsigned int            pending_status;
        spinlock_t              lock_suspended;
 
+#ifdef CONFIG_PM
        struct {
                u32             cr;
                u32             mr;
@@ -185,6 +187,7 @@ struct atmel_uart_port {
                u32             fmr;
                u32             fimr;
        } cache;
+#endif
 
        int (*prepare_rx)(struct uart_port *port);
        int (*prepare_tx)(struct uart_port *port);
index f02934ffb3293de45601f434be9dd7786cafdfe4..15df1ba7809510b45c6d96b17d72e92064301973 100644 (file)
@@ -1705,6 +1705,13 @@ lpuart_console_write(struct console *co, const char *s, unsigned int count)
 {
        struct lpuart_port *sport = lpuart_ports[co->index];
        unsigned char  old_cr2, cr2;
+       unsigned long flags;
+       int locked = 1;
+
+       if (sport->port.sysrq || oops_in_progress)
+               locked = spin_trylock_irqsave(&sport->port.lock, flags);
+       else
+               spin_lock_irqsave(&sport->port.lock, flags);
 
        /* first save CR2 and then disable interrupts */
        cr2 = old_cr2 = readb(sport->port.membase + UARTCR2);
@@ -1719,6 +1726,9 @@ lpuart_console_write(struct console *co, const char *s, unsigned int count)
                barrier();
 
        writeb(old_cr2, sport->port.membase + UARTCR2);
+
+       if (locked)
+               spin_unlock_irqrestore(&sport->port.lock, flags);
 }
 
 static void
@@ -1726,6 +1736,13 @@ lpuart32_console_write(struct console *co, const char *s, unsigned int count)
 {
        struct lpuart_port *sport = lpuart_ports[co->index];
        unsigned long  old_cr, cr;
+       unsigned long flags;
+       int locked = 1;
+
+       if (sport->port.sysrq || oops_in_progress)
+               locked = spin_trylock_irqsave(&sport->port.lock, flags);
+       else
+               spin_lock_irqsave(&sport->port.lock, flags);
 
        /* first save CR2 and then disable interrupts */
        cr = old_cr = lpuart32_read(sport->port.membase + UARTCTRL);
@@ -1740,6 +1757,9 @@ lpuart32_console_write(struct console *co, const char *s, unsigned int count)
                barrier();
 
        lpuart32_write(old_cr, sport->port.membase + UARTCTRL);
+
+       if (locked)
+               spin_unlock_irqrestore(&sport->port.lock, flags);
 }
 
 /*
index e3e152cbc75e71d7bc4e966f8a4ec3a1884c2b95..33509b4beaec237715de1e8febd63e861fbb9c15 100644 (file)
@@ -719,6 +719,27 @@ out:
        return IRQ_HANDLED;
 }
 
+static void imx_disable_rx_int(struct imx_port *sport)
+{
+       unsigned long temp;
+
+       sport->dma_is_rxing = 1;
+
+       /* disable the receiver ready and aging timer interrupts */
+       temp = readl(sport->port.membase + UCR1);
+       temp &= ~(UCR1_RRDYEN);
+       writel(temp, sport->port.membase + UCR1);
+
+       temp = readl(sport->port.membase + UCR2);
+       temp &= ~(UCR2_ATEN);
+       writel(temp, sport->port.membase + UCR2);
+
+       /* disable the rx errors interrupts */
+       temp = readl(sport->port.membase + UCR4);
+       temp &= ~UCR4_OREN;
+       writel(temp, sport->port.membase + UCR4);
+}
+
 static void clear_rx_errors(struct imx_port *sport);
 static int start_rx_dma(struct imx_port *sport);
 /*
@@ -734,21 +755,8 @@ static void imx_dma_rxint(struct imx_port *sport)
 
        temp = readl(sport->port.membase + USR2);
        if ((temp & USR2_RDR) && !sport->dma_is_rxing) {
-               sport->dma_is_rxing = 1;
 
-               /* disable the receiver ready and aging timer interrupts */
-               temp = readl(sport->port.membase + UCR1);
-               temp &= ~(UCR1_RRDYEN);
-               writel(temp, sport->port.membase + UCR1);
-
-               temp = readl(sport->port.membase + UCR2);
-               temp &= ~(UCR2_ATEN);
-               writel(temp, sport->port.membase + UCR2);
-
-               /* disable the rx errors interrupts */
-               temp = readl(sport->port.membase + UCR4);
-               temp &= ~UCR4_OREN;
-               writel(temp, sport->port.membase + UCR4);
+               imx_disable_rx_int(sport);
 
                /* tell the DMA to receive the data. */
                start_rx_dma(sport);
@@ -1317,19 +1325,10 @@ static int imx_startup(struct uart_port *port)
        if (!is_imx1_uart(sport)) {
                temp = readl(sport->port.membase + UCR3);
 
-               /*
-                * The effect of RI and DCD differs depending on the UFCR_DCEDTE
-                * bit. In DCE mode they control the outputs, in DTE mode they
-                * enable the respective irqs. At least the DCD irq cannot be
-                * cleared on i.MX25 at least, so it's not usable and must be
-                * disabled. I don't have test hardware to check if RI has the
-                * same problem but I consider this likely so it's disabled for
-                * now, too.
-                */
-               temp |= IMX21_UCR3_RXDMUXSEL | UCR3_ADNIMP |
-                       UCR3_DTRDEN | UCR3_RI | UCR3_DCD;
+               temp |= UCR3_DTRDEN | UCR3_RI | UCR3_DCD;
 
                if (sport->dte_mode)
+                       /* disable broken interrupts */
                        temp &= ~(UCR3_RI | UCR3_DCD);
 
                writel(temp, sport->port.membase + UCR3);
@@ -1339,6 +1338,33 @@ static int imx_startup(struct uart_port *port)
         * Enable modem status interrupts
         */
        imx_enable_ms(&sport->port);
+
+       /*
+        * If the serial port is opened for reading start RX DMA immediately
+        * instead of waiting for RX FIFO interrupts. In our iMX53 the average
+        * delay for the first reception dropped from approximately 35000
+        * microseconds to 1000 microseconds.
+        */
+       if (sport->dma_is_enabled) {
+               struct tty_struct *tty = sport->port.state->port.tty;
+               struct tty_file_private *file_priv;
+               int readcnt = 0;
+
+               spin_lock(&tty->files_lock);
+
+               if (!list_empty(&tty->tty_files))
+                       list_for_each_entry(file_priv, &tty->tty_files, list)
+                               if (!(file_priv->file->f_flags & O_WRONLY))
+                                       readcnt++;
+
+               spin_unlock(&tty->files_lock);
+
+               if (readcnt > 0) {
+                       imx_disable_rx_int(sport);
+                       start_rx_dma(sport);
+               }
+       }
+
        spin_unlock_irqrestore(&sport->port.lock, flags);
 
        return 0;
@@ -1584,8 +1610,6 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios,
 
        ufcr = readl(sport->port.membase + UFCR);
        ufcr = (ufcr & (~UFCR_RFDIV)) | UFCR_RFDIV_REG(div);
-       if (sport->dte_mode)
-               ufcr |= UFCR_DCEDTE;
        writel(ufcr, sport->port.membase + UFCR);
 
        writel(num, sport->port.membase + UBIR);
@@ -2153,6 +2177,27 @@ static int serial_imx_probe(struct platform_device *pdev)
                 UCR1_TXMPTYEN | UCR1_RTSDEN);
        writel_relaxed(reg, sport->port.membase + UCR1);
 
+       if (!is_imx1_uart(sport) && sport->dte_mode) {
+               /*
+                * The DCEDTE bit changes the direction of DSR, DCD, DTR and RI
+                * and influences if UCR3_RI and UCR3_DCD changes the level of RI
+                * and DCD (when they are outputs) or enables the respective
+                * irqs. So set this bit early, i.e. before requesting irqs.
+                */
+               writel(UFCR_DCEDTE, sport->port.membase + UFCR);
+
+               /*
+                * Disable UCR3_RI and UCR3_DCD irqs. They are also not
+                * enabled later because they cannot be cleared
+                * (confirmed on i.MX25) which makes them unusable.
+                */
+               writel(IMX21_UCR3_RXDMUXSEL | UCR3_ADNIMP | UCR3_DSR,
+                      sport->port.membase + UCR3);
+
+       } else {
+               writel(0, sport->port.membase + UFCR);
+       }
+
        clk_disable_unprepare(sport->clk_ipg);
 
        /*
index a4734649a0f0f8b0ea3de17c5c26c3a2acc54c19..1ea05ac57aa7197b4f690776acc609d376faade4 100644 (file)
@@ -1770,7 +1770,8 @@ static int serial_omap_probe(struct platform_device *pdev)
        return 0;
 
 err_add_port:
-       pm_runtime_put(&pdev->dev);
+       pm_runtime_dont_use_autosuspend(&pdev->dev);
+       pm_runtime_put_sync(&pdev->dev);
        pm_runtime_disable(&pdev->dev);
        pm_qos_remove_request(&up->pm_qos_request);
        device_init_wakeup(up->dev, false);
@@ -1783,9 +1784,13 @@ static int serial_omap_remove(struct platform_device *dev)
 {
        struct uart_omap_port *up = platform_get_drvdata(dev);
 
+       pm_runtime_get_sync(up->dev);
+
+       uart_remove_one_port(&serial_omap_reg, &up->port);
+
+       pm_runtime_dont_use_autosuspend(up->dev);
        pm_runtime_put_sync(up->dev);
        pm_runtime_disable(up->dev);
-       uart_remove_one_port(&serial_omap_reg, &up->port);
        pm_qos_remove_request(&up->pm_qos_request);
        device_init_wakeup(&dev->dev, false);
 
index 7a17aedbf902e05034129a832941f27fe5dc38c8..8aca18c4cdea4076e8666baff7d7f4953d6a6e1f 100644 (file)
@@ -859,7 +859,7 @@ static void s3c24xx_serial_break_ctl(struct uart_port *port, int break_state)
 static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p)
 {
        struct s3c24xx_uart_dma *dma = p->dma;
-       unsigned long flags;
+       int ret;
 
        /* Default slave configuration parameters */
        dma->rx_conf.direction          = DMA_DEV_TO_MEM;
@@ -884,8 +884,8 @@ static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p)
 
        dma->tx_chan = dma_request_chan(p->port.dev, "tx");
        if (IS_ERR(dma->tx_chan)) {
-               dma_release_channel(dma->rx_chan);
-               return PTR_ERR(dma->tx_chan);
+               ret = PTR_ERR(dma->tx_chan);
+               goto err_release_rx;
        }
 
        dmaengine_slave_config(dma->tx_chan, &dma->tx_conf);
@@ -894,26 +894,38 @@ static int s3c24xx_serial_request_dma(struct s3c24xx_uart_port *p)
        dma->rx_size = PAGE_SIZE;
 
        dma->rx_buf = kmalloc(dma->rx_size, GFP_KERNEL);
-
        if (!dma->rx_buf) {
-               dma_release_channel(dma->rx_chan);
-               dma_release_channel(dma->tx_chan);
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto err_release_tx;
        }
 
-       dma->rx_addr = dma_map_single(dma->rx_chan->device->dev, dma->rx_buf,
+       dma->rx_addr = dma_map_single(p->port.dev, dma->rx_buf,
                                dma->rx_size, DMA_FROM_DEVICE);
-
-       spin_lock_irqsave(&p->port.lock, flags);
+       if (dma_mapping_error(p->port.dev, dma->rx_addr)) {
+               ret = -EIO;
+               goto err_free_rx;
+       }
 
        /* TX buffer */
-       dma->tx_addr = dma_map_single(dma->tx_chan->device->dev,
-                               p->port.state->xmit.buf,
+       dma->tx_addr = dma_map_single(p->port.dev, p->port.state->xmit.buf,
                                UART_XMIT_SIZE, DMA_TO_DEVICE);
-
-       spin_unlock_irqrestore(&p->port.lock, flags);
+       if (dma_mapping_error(p->port.dev, dma->tx_addr)) {
+               ret = -EIO;
+               goto err_unmap_rx;
+       }
 
        return 0;
+
+err_unmap_rx:
+       dma_unmap_single(p->port.dev, dma->rx_addr, dma->rx_size,
+                        DMA_FROM_DEVICE);
+err_free_rx:
+       kfree(dma->rx_buf);
+err_release_tx:
+       dma_release_channel(dma->tx_chan);
+err_release_rx:
+       dma_release_channel(dma->rx_chan);
+       return ret;
 }
 
 static void s3c24xx_serial_release_dma(struct s3c24xx_uart_port *p)
@@ -922,7 +934,7 @@ static void s3c24xx_serial_release_dma(struct s3c24xx_uart_port *p)
 
        if (dma->rx_chan) {
                dmaengine_terminate_all(dma->rx_chan);
-               dma_unmap_single(dma->rx_chan->device->dev, dma->rx_addr,
+               dma_unmap_single(p->port.dev, dma->rx_addr,
                                dma->rx_size, DMA_FROM_DEVICE);
                kfree(dma->rx_buf);
                dma_release_channel(dma->rx_chan);
@@ -931,7 +943,7 @@ static void s3c24xx_serial_release_dma(struct s3c24xx_uart_port *p)
 
        if (dma->tx_chan) {
                dmaengine_terminate_all(dma->tx_chan);
-               dma_unmap_single(dma->tx_chan->device->dev, dma->tx_addr,
+               dma_unmap_single(p->port.dev, dma->tx_addr,
                                UART_XMIT_SIZE, DMA_TO_DEVICE);
                dma_release_channel(dma->tx_chan);
                dma->tx_chan = NULL;
index 771f361c47ea17850cf4b946d135795e100c0865..041625cc24bbe736cdc021fa0385fbe332f2d792 100644 (file)
@@ -41,7 +41,7 @@
 #include <linux/tty_flip.h>
 #include <linux/types.h>
 
-#include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <asm/io.h>
 #include <asm/war.h>
 
@@ -103,7 +103,7 @@ struct sbd_port {
 struct sbd_duart {
        struct sbd_port         sport[2];
        unsigned long           mapctrl;
-       atomic_t                map_guard;
+       refcount_t              map_guard;
 };
 
 #define to_sport(uport) container_of(uport, struct sbd_port, port)
@@ -654,15 +654,13 @@ static void sbd_release_port(struct uart_port *uport)
 {
        struct sbd_port *sport = to_sport(uport);
        struct sbd_duart *duart = sport->duart;
-       int map_guard;
 
        iounmap(sport->memctrl);
        sport->memctrl = NULL;
        iounmap(uport->membase);
        uport->membase = NULL;
 
-       map_guard = atomic_add_return(-1, &duart->map_guard);
-       if (!map_guard)
+       if(refcount_dec_and_test(&duart->map_guard))
                release_mem_region(duart->mapctrl, DUART_CHANREG_SPACING);
        release_mem_region(uport->mapbase, DUART_CHANREG_SPACING);
 }
@@ -698,7 +696,6 @@ static int sbd_request_port(struct uart_port *uport)
 {
        const char *err = KERN_ERR "sbd: Unable to reserve MMIO resource\n";
        struct sbd_duart *duart = to_sport(uport)->duart;
-       int map_guard;
        int ret = 0;
 
        if (!request_mem_region(uport->mapbase, DUART_CHANREG_SPACING,
@@ -706,11 +703,11 @@ static int sbd_request_port(struct uart_port *uport)
                printk(err);
                return -EBUSY;
        }
-       map_guard = atomic_add_return(1, &duart->map_guard);
-       if (map_guard == 1) {
+       refcount_inc(&duart->map_guard);
+       if (refcount_read(&duart->map_guard) == 1) {
                if (!request_mem_region(duart->mapctrl, DUART_CHANREG_SPACING,
                                        "sb1250-duart")) {
-                       atomic_add(-1, &duart->map_guard);
+                       refcount_dec(&duart->map_guard);
                        printk(err);
                        ret = -EBUSY;
                }
@@ -718,8 +715,7 @@ static int sbd_request_port(struct uart_port *uport)
        if (!ret) {
                ret = sbd_map_port(uport);
                if (ret) {
-                       map_guard = atomic_add_return(-1, &duart->map_guard);
-                       if (!map_guard)
+                       if (refcount_dec_and_test(&duart->map_guard))
                                release_mem_region(duart->mapctrl,
                                                   DUART_CHANREG_SPACING);
                }
index 3fe56894974a7c4c3ae04a4d54946043be1d243c..0f45b7884a2c58a299668591e87bead1f6628f98 100644 (file)
@@ -2117,9 +2117,8 @@ int uart_suspend_port(struct uart_driver *drv, struct uart_port *uport)
                for (tries = 3; !ops->tx_empty(uport) && tries; tries--)
                        msleep(10);
                if (!tries)
-                       dev_err(uport->dev, "%s%d: Unable to drain transmitter\n",
-                               drv->dev_name,
-                               drv->tty_driver->name_base + uport->line);
+                       dev_err(uport->dev, "%s: Unable to drain transmitter\n",
+                               uport->name);
 
                ops->shutdown(uport);
        }
@@ -2248,11 +2247,10 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port)
                break;
        }
 
-       printk(KERN_INFO "%s%s%s%d at %s (irq = %d, base_baud = %d) is a %s\n",
+       pr_info("%s%s%s at %s (irq = %d, base_baud = %d) is a %s\n",
               port->dev ? dev_name(port->dev) : "",
               port->dev ? ": " : "",
-              drv->dev_name,
-              drv->tty_driver->name_base + port->line,
+              port->name,
               address, port->irq, port->uartclk / 16, uart_type(port));
 }
 
@@ -2331,9 +2329,6 @@ static int uart_poll_init(struct tty_driver *driver, int line, char *options)
        int flow = 'n';
        int ret = 0;
 
-       if (!state)
-               return -1;
-
        tport = &state->port;
        mutex_lock(&tport->mutex);
 
@@ -2368,13 +2363,12 @@ static int uart_poll_get_char(struct tty_driver *driver, int line)
        struct uart_port *port;
        int ret = -1;
 
-       if (state) {
-               port = uart_port_ref(state);
-               if (port) {
-                       ret = port->ops->poll_get_char(port);
-                       uart_port_deref(port);
-               }
+       port = uart_port_ref(state);
+       if (port) {
+               ret = port->ops->poll_get_char(port);
+               uart_port_deref(port);
        }
+
        return ret;
 }
 
@@ -2384,9 +2378,6 @@ static void uart_poll_put_char(struct tty_driver *driver, int line, char ch)
        struct uart_state *state = drv->state + line;
        struct uart_port *port;
 
-       if (!state)
-               return;
-
        port = uart_port_ref(state);
        if (!port)
                return;
@@ -2751,6 +2742,12 @@ int uart_add_one_port(struct uart_driver *drv, struct uart_port *uport)
        state->pm_state = UART_PM_STATE_UNDEFINED;
        uport->cons = drv->cons;
        uport->minor = drv->tty_driver->minor_start + uport->line;
+       uport->name = kasprintf(GFP_KERNEL, "%s%d", drv->dev_name,
+                               drv->tty_driver->name_base + uport->line);
+       if (!uport->name) {
+               ret = -ENOMEM;
+               goto out;
+       }
 
        /*
         * If this port is a console, then the spinlock is already
@@ -2868,6 +2865,7 @@ int uart_remove_one_port(struct uart_driver *drv, struct uart_port *uport)
        if (uport->type != PORT_UNKNOWN && uport->ops->release_port)
                uport->ops->release_port(uport);
        kfree(uport->tty_groups);
+       kfree(uport->name);
 
        /*
         * Indicate that there isn't a port here anymore.
index 9a47cc4f16a2798f7c0a084d44621d371a2f59a9..71707e8e6e3ffe768ad76e52b118b74e32ad35e0 100644 (file)
@@ -683,24 +683,37 @@ static void sci_init_pins(struct uart_port *port, unsigned int cflag)
        }
 
        if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
+               u16 data = serial_port_in(port, SCPDR);
                u16 ctrl = serial_port_in(port, SCPCR);
 
                /* Enable RXD and TXD pin functions */
                ctrl &= ~(SCPCR_RXDC | SCPCR_TXDC);
                if (to_sci_port(port)->has_rtscts) {
-                       /* RTS# is output, driven 1 */
-                       ctrl |= SCPCR_RTSC;
-                       serial_port_out(port, SCPDR,
-                               serial_port_in(port, SCPDR) | SCPDR_RTSD);
+                       /* RTS# is output, active low, unless autorts */
+                       if (!(port->mctrl & TIOCM_RTS)) {
+                               ctrl |= SCPCR_RTSC;
+                               data |= SCPDR_RTSD;
+                       } else if (!s->autorts) {
+                               ctrl |= SCPCR_RTSC;
+                               data &= ~SCPDR_RTSD;
+                       } else {
+                               /* Enable RTS# pin function */
+                               ctrl &= ~SCPCR_RTSC;
+                       }
                        /* Enable CTS# pin function */
                        ctrl &= ~SCPCR_CTSC;
                }
+               serial_port_out(port, SCPDR, data);
                serial_port_out(port, SCPCR, ctrl);
        } else if (sci_getreg(port, SCSPTR)->size) {
                u16 status = serial_port_in(port, SCSPTR);
 
-               /* RTS# is output, driven 1 */
-               status |= SCSPTR_RTSIO | SCSPTR_RTSDT;
+               /* RTS# is always output; and active low, unless autorts */
+               status |= SCSPTR_RTSIO;
+               if (!(port->mctrl & TIOCM_RTS))
+                       status |= SCSPTR_RTSDT;
+               else if (!s->autorts)
+                       status &= ~SCSPTR_RTSDT;
                /* CTS# and SCK are inputs */
                status &= ~(SCSPTR_CTSIO | SCSPTR_SCKIO);
                serial_port_out(port, SCSPTR, status);
@@ -1985,11 +1998,13 @@ static int sci_startup(struct uart_port *port)
 
        dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
 
+       sci_request_dma(port);
+
        ret = sci_request_irq(s);
-       if (unlikely(ret < 0))
+       if (unlikely(ret < 0)) {
+               sci_free_dma(port);
                return ret;
-
-       sci_request_dma(port);
+       }
 
        return 0;
 }
@@ -2021,8 +2036,8 @@ static void sci_shutdown(struct uart_port *port)
        }
 #endif
 
-       sci_free_dma(port);
        sci_free_irq(s);
+       sci_free_dma(port);
 }
 
 static int sci_sck_calc(struct sci_port *s, unsigned int bps,
@@ -2157,10 +2172,6 @@ static void sci_reset(struct uart_port *port)
        unsigned int status;
        struct sci_port *s = to_sci_port(port);
 
-       do {
-               status = serial_port_in(port, SCxSR);
-       } while (!(status & SCxSR_TEND(port)));
-
        serial_port_out(port, SCSCR, 0x00);     /* TE=0, RE=0, CKE1=0 */
 
        reg = sci_getreg(port, SCFCR);
@@ -2374,6 +2385,10 @@ done:
 
                serial_port_out(port, SCFCR, ctrl);
        }
+       if (port->flags & UPF_HARD_FLOW) {
+               /* Refresh (Auto) RTS */
+               sci_set_mctrl(port, port->mctrl);
+       }
 
        scr_val |= SCSCR_RE | SCSCR_TE |
                   (s->cfg->scscr & ~(SCSCR_CKE1 | SCSCR_CKE0));
index d98e3dc4838e637b34d3e3984c9570c656fa37b3..90996ad97b3718cfa85a0505a47b7e8d7be770c9 100644 (file)
@@ -36,7 +36,7 @@
 #define SPRD_FIFO_SIZE         128
 #define SPRD_DEF_RATE          26000000
 #define SPRD_BAUD_IO_LIMIT     3000000
-#define SPRD_TIMEOUT           256
+#define SPRD_TIMEOUT           256000
 
 /* the offset of serial registers and BITs for them */
 /* data registers */
index c334bcc59c649eedc2933ac29c4dc1ef45ae21d2..f5335be344f67ced2a601c81e3713a7d90e275c7 100644 (file)
@@ -887,13 +887,12 @@ static void asc_console_write(struct console *co, const char *s, unsigned count)
        int locked = 1;
        u32 intenable;
 
-       local_irq_save(flags);
        if (port->sysrq)
                locked = 0; /* asc_interrupt has already claimed the lock */
        else if (oops_in_progress)
-               locked = spin_trylock(&port->lock);
+               locked = spin_trylock_irqsave(&port->lock, flags);
        else
-               spin_lock(&port->lock);
+               spin_lock_irqsave(&port->lock, flags);
 
        /*
         * Disable interrupts so we don't get the IRQ line bouncing
@@ -911,14 +910,13 @@ static void asc_console_write(struct console *co, const char *s, unsigned count)
        asc_out(port, ASC_INTEN, intenable);
 
        if (locked)
-               spin_unlock(&port->lock);
-       local_irq_restore(flags);
+               spin_unlock_irqrestore(&port->lock, flags);
 }
 
 static int asc_console_setup(struct console *co, char *options)
 {
        struct asc_port *ascport;
-       int baud = 9600;
+       int baud = 115200;
        int bits = 8;
        int parity = 'n';
        int flow = 'n';
@@ -986,7 +984,7 @@ static struct platform_driver asc_serial_driver = {
 static int __init asc_init(void)
 {
        int ret;
-       static char banner[] __initdata =
+       static const char banner[] __initconst =
                KERN_INFO "STMicroelectronics ASC driver initialized\n";
 
        printk(banner);
index 817bb0d3f326ed982631c135ddd5f7a4b170b7a5..c9b8d702dadc35abcb6f3b74a07f62e836b2f9e2 100644 (file)
@@ -28,7 +28,7 @@
 #define ULITE_NAME             "ttyUL"
 #define ULITE_MAJOR            204
 #define ULITE_MINOR            187
-#define ULITE_NR_UARTS         16
+#define ULITE_NR_UARTS         CONFIG_SERIAL_UARTLITE_NR_UARTS
 
 /* ---------------------------------------------------------------------
  * Register definitions
index ad77d0ed0c467dbc2b20f41a9959ed10cf3e8390..c0539950f8d7f29725dd4433e6905d5e3d07b1c7 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/module.h>
+#include <linux/pm_runtime.h>
 
 #define CDNS_UART_TTY_NAME     "ttyPS"
 #define CDNS_UART_NAME         "xuartps"
@@ -176,6 +177,7 @@ MODULE_PARM_DESC(rx_timeout, "Rx timeout, 1-255");
 #define CDNS_UART_BDIV_MIN     4
 #define CDNS_UART_BDIV_MAX     255
 #define CDNS_UART_CD_MAX       65535
+#define UART_AUTOSUSPEND_TIMEOUT       3000
 
 /**
  * struct cdns_uart - device data
@@ -1065,16 +1067,13 @@ static void cdns_uart_poll_put_char(struct uart_port *port, unsigned char c)
 static void cdns_uart_pm(struct uart_port *port, unsigned int state,
                   unsigned int oldstate)
 {
-       struct cdns_uart *cdns_uart = port->private_data;
-
        switch (state) {
        case UART_PM_STATE_OFF:
-               clk_disable(cdns_uart->uartclk);
-               clk_disable(cdns_uart->pclk);
+               pm_runtime_mark_last_busy(port->dev);
+               pm_runtime_put_autosuspend(port->dev);
                break;
        default:
-               clk_enable(cdns_uart->pclk);
-               clk_enable(cdns_uart->uartclk);
+               pm_runtime_get_sync(port->dev);
                break;
        }
 }
@@ -1353,12 +1352,7 @@ static int cdns_uart_suspend(struct device *device)
         * the suspend.
         */
        uart_suspend_port(&cdns_uart_uart_driver, port);
-       if (console_suspend_enabled && !may_wake) {
-               struct cdns_uart *cdns_uart = port->private_data;
-
-               clk_disable(cdns_uart->uartclk);
-               clk_disable(cdns_uart->pclk);
-       } else {
+       if (!(console_suspend_enabled && !may_wake)) {
                unsigned long flags = 0;
 
                spin_lock_irqsave(&port->lock, flags);
@@ -1423,6 +1417,8 @@ static int cdns_uart_resume(struct device *device)
                ctrl_reg |= CDNS_UART_CR_TX_EN | CDNS_UART_CR_RX_EN;
                writel(ctrl_reg, port->membase + CDNS_UART_CR);
 
+               clk_disable(cdns_uart->uartclk);
+               clk_disable(cdns_uart->pclk);
                spin_unlock_irqrestore(&port->lock, flags);
        } else {
                spin_lock_irqsave(&port->lock, flags);
@@ -1436,9 +1432,33 @@ static int cdns_uart_resume(struct device *device)
        return uart_resume_port(&cdns_uart_uart_driver, port);
 }
 #endif /* ! CONFIG_PM_SLEEP */
+static int __maybe_unused cdns_runtime_suspend(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct uart_port *port = platform_get_drvdata(pdev);
+       struct cdns_uart *cdns_uart = port->private_data;
+
+       clk_disable(cdns_uart->uartclk);
+       clk_disable(cdns_uart->pclk);
+       return 0;
+};
+
+static int __maybe_unused cdns_runtime_resume(struct device *dev)
+{
+       struct platform_device *pdev = to_platform_device(dev);
+       struct uart_port *port = platform_get_drvdata(pdev);
+       struct cdns_uart *cdns_uart = port->private_data;
 
-static SIMPLE_DEV_PM_OPS(cdns_uart_dev_pm_ops, cdns_uart_suspend,
-               cdns_uart_resume);
+       clk_enable(cdns_uart->pclk);
+       clk_enable(cdns_uart->uartclk);
+       return 0;
+};
+
+static const struct dev_pm_ops cdns_uart_dev_pm_ops = {
+       SET_SYSTEM_SLEEP_PM_OPS(cdns_uart_suspend, cdns_uart_resume)
+       SET_RUNTIME_PM_OPS(cdns_runtime_suspend,
+                          cdns_runtime_resume, NULL)
+};
 
 static const struct cdns_platform_data zynqmp_uart_def = {
                                .quirks = CDNS_UART_RXBS_SUPPORT, };
@@ -1501,12 +1521,12 @@ static int cdns_uart_probe(struct platform_device *pdev)
                return PTR_ERR(cdns_uart_data->uartclk);
        }
 
-       rc = clk_prepare(cdns_uart_data->pclk);
+       rc = clk_prepare_enable(cdns_uart_data->pclk);
        if (rc) {
                dev_err(&pdev->dev, "Unable to enable pclk clock.\n");
                return rc;
        }
-       rc = clk_prepare(cdns_uart_data->uartclk);
+       rc = clk_prepare_enable(cdns_uart_data->uartclk);
        if (rc) {
                dev_err(&pdev->dev, "Unable to enable device clock.\n");
                goto err_out_clk_dis_pclk;
@@ -1558,6 +1578,11 @@ static int cdns_uart_probe(struct platform_device *pdev)
        cdns_uart_data->port = port;
        platform_set_drvdata(pdev, port);
 
+       pm_runtime_use_autosuspend(&pdev->dev);
+       pm_runtime_set_autosuspend_delay(&pdev->dev, UART_AUTOSUSPEND_TIMEOUT);
+       pm_runtime_set_active(&pdev->dev);
+       pm_runtime_enable(&pdev->dev);
+
        rc = uart_add_one_port(&cdns_uart_uart_driver, port);
        if (rc) {
                dev_err(&pdev->dev,
@@ -1573,9 +1598,12 @@ err_out_notif_unreg:
                        &cdns_uart_data->clk_rate_change_nb);
 #endif
 err_out_clk_disable:
-       clk_unprepare(cdns_uart_data->uartclk);
+       pm_runtime_disable(&pdev->dev);
+       pm_runtime_set_suspended(&pdev->dev);
+       pm_runtime_dont_use_autosuspend(&pdev->dev);
+       clk_disable_unprepare(cdns_uart_data->uartclk);
 err_out_clk_dis_pclk:
-       clk_unprepare(cdns_uart_data->pclk);
+       clk_disable_unprepare(cdns_uart_data->pclk);
 
        return rc;
 }
@@ -1599,8 +1627,11 @@ static int cdns_uart_remove(struct platform_device *pdev)
 #endif
        rc = uart_remove_one_port(&cdns_uart_uart_driver, port);
        port->mapbase = 0;
-       clk_unprepare(cdns_uart_data->uartclk);
-       clk_unprepare(cdns_uart_data->pclk);
+       clk_disable_unprepare(cdns_uart_data->uartclk);
+       clk_disable_unprepare(cdns_uart_data->pclk);
+       pm_runtime_disable(&pdev->dev);
+       pm_runtime_set_suspended(&pdev->dev);
+       pm_runtime_dont_use_autosuspend(&pdev->dev);
        return rc;
 }
 
index 657eed82eeb372d96e5f480bae3eb7c92dee06fa..a2c308f7d6374515bf8a0ac0a9e6ea8b59f5032b 100644 (file)
@@ -869,9 +869,9 @@ static int txholdbufs[MAX_TOTAL_DEVICES];
        
 module_param(break_on_load, bool, 0);
 module_param(ttymajor, int, 0);
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
-module_param_array(dma, int, NULL, 0);
+module_param_hw_array(io, int, ioport, NULL, 0);
+module_param_hw_array(irq, int, irq, NULL, 0);
+module_param_hw_array(dma, int, dma, NULL, 0);
 module_param(debug_level, int, 0);
 module_param_array(maxframe, int, NULL, 0);
 module_param_array(txdmabufs, int, NULL, 0);
diff --git a/drivers/tty/tty_baudrate.c b/drivers/tty/tty_baudrate.c
new file mode 100644 (file)
index 0000000..5c33fd2
--- /dev/null
@@ -0,0 +1,232 @@
+/*
+ *  Copyright (C) 1991, 1992, 1993, 1994  Linus Torvalds
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/termios.h>
+#include <linux/tty.h>
+#include <linux/export.h>
+
+
+/*
+ * Routine which returns the baud rate of the tty
+ *
+ * Note that the baud_table needs to be kept in sync with the
+ * include/asm/termbits.h file.
+ */
+static const speed_t baud_table[] = {
+       0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
+       9600, 19200, 38400, 57600, 115200, 230400, 460800,
+#ifdef __sparc__
+       76800, 153600, 307200, 614400, 921600
+#else
+       500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,
+       2500000, 3000000, 3500000, 4000000
+#endif
+};
+
+#ifndef __sparc__
+static const tcflag_t baud_bits[] = {
+       B0, B50, B75, B110, B134, B150, B200, B300, B600,
+       B1200, B1800, B2400, B4800, B9600, B19200, B38400,
+       B57600, B115200, B230400, B460800, B500000, B576000,
+       B921600, B1000000, B1152000, B1500000, B2000000, B2500000,
+       B3000000, B3500000, B4000000
+};
+#else
+static const tcflag_t baud_bits[] = {
+       B0, B50, B75, B110, B134, B150, B200, B300, B600,
+       B1200, B1800, B2400, B4800, B9600, B19200, B38400,
+       B57600, B115200, B230400, B460800, B76800, B153600,
+       B307200, B614400, B921600
+};
+#endif
+
+static int n_baud_table = ARRAY_SIZE(baud_table);
+
+/**
+ *     tty_termios_baud_rate
+ *     @termios: termios structure
+ *
+ *     Convert termios baud rate data into a speed. This should be called
+ *     with the termios lock held if this termios is a terminal termios
+ *     structure. May change the termios data. Device drivers can call this
+ *     function but should use ->c_[io]speed directly as they are updated.
+ *
+ *     Locking: none
+ */
+
+speed_t tty_termios_baud_rate(struct ktermios *termios)
+{
+       unsigned int cbaud;
+
+       cbaud = termios->c_cflag & CBAUD;
+
+#ifdef BOTHER
+       /* Magic token for arbitrary speed via c_ispeed/c_ospeed */
+       if (cbaud == BOTHER)
+               return termios->c_ospeed;
+#endif
+       if (cbaud & CBAUDEX) {
+               cbaud &= ~CBAUDEX;
+
+               if (cbaud < 1 || cbaud + 15 > n_baud_table)
+                       termios->c_cflag &= ~CBAUDEX;
+               else
+                       cbaud += 15;
+       }
+       return baud_table[cbaud];
+}
+EXPORT_SYMBOL(tty_termios_baud_rate);
+
+/**
+ *     tty_termios_input_baud_rate
+ *     @termios: termios structure
+ *
+ *     Convert termios baud rate data into a speed. This should be called
+ *     with the termios lock held if this termios is a terminal termios
+ *     structure. May change the termios data. Device drivers can call this
+ *     function but should use ->c_[io]speed directly as they are updated.
+ *
+ *     Locking: none
+ */
+
+speed_t tty_termios_input_baud_rate(struct ktermios *termios)
+{
+#ifdef IBSHIFT
+       unsigned int cbaud = (termios->c_cflag >> IBSHIFT) & CBAUD;
+
+       if (cbaud == B0)
+               return tty_termios_baud_rate(termios);
+
+       /* Magic token for arbitrary speed via c_ispeed*/
+       if (cbaud == BOTHER)
+               return termios->c_ispeed;
+
+       if (cbaud & CBAUDEX) {
+               cbaud &= ~CBAUDEX;
+
+               if (cbaud < 1 || cbaud + 15 > n_baud_table)
+                       termios->c_cflag &= ~(CBAUDEX << IBSHIFT);
+               else
+                       cbaud += 15;
+       }
+       return baud_table[cbaud];
+#else
+       return tty_termios_baud_rate(termios);
+#endif
+}
+EXPORT_SYMBOL(tty_termios_input_baud_rate);
+
+/**
+ *     tty_termios_encode_baud_rate
+ *     @termios: ktermios structure holding user requested state
+ *     @ispeed: input speed
+ *     @ospeed: output speed
+ *
+ *     Encode the speeds set into the passed termios structure. This is
+ *     used as a library helper for drivers so that they can report back
+ *     the actual speed selected when it differs from the speed requested
+ *
+ *     For maximal back compatibility with legacy SYS5/POSIX *nix behaviour
+ *     we need to carefully set the bits when the user does not get the
+ *     desired speed. We allow small margins and preserve as much of possible
+ *     of the input intent to keep compatibility.
+ *
+ *     Locking: Caller should hold termios lock. This is already held
+ *     when calling this function from the driver termios handler.
+ *
+ *     The ifdefs deal with platforms whose owners have yet to update them
+ *     and will all go away once this is done.
+ */
+
+void tty_termios_encode_baud_rate(struct ktermios *termios,
+                                 speed_t ibaud, speed_t obaud)
+{
+       int i = 0;
+       int ifound = -1, ofound = -1;
+       int iclose = ibaud/50, oclose = obaud/50;
+       int ibinput = 0;
+
+       if (obaud == 0)                 /* CD dropped             */
+               ibaud = 0;              /* Clear ibaud to be sure */
+
+       termios->c_ispeed = ibaud;
+       termios->c_ospeed = obaud;
+
+#ifdef BOTHER
+       /* If the user asked for a precise weird speed give a precise weird
+          answer. If they asked for a Bfoo speed they may have problems
+          digesting non-exact replies so fuzz a bit */
+
+       if ((termios->c_cflag & CBAUD) == BOTHER)
+               oclose = 0;
+       if (((termios->c_cflag >> IBSHIFT) & CBAUD) == BOTHER)
+               iclose = 0;
+       if ((termios->c_cflag >> IBSHIFT) & CBAUD)
+               ibinput = 1;    /* An input speed was specified */
+#endif
+       termios->c_cflag &= ~CBAUD;
+
+       /*
+        *      Our goal is to find a close match to the standard baud rate
+        *      returned. Walk the baud rate table and if we get a very close
+        *      match then report back the speed as a POSIX Bxxxx value by
+        *      preference
+        */
+
+       do {
+               if (obaud - oclose <= baud_table[i] &&
+                   obaud + oclose >= baud_table[i]) {
+                       termios->c_cflag |= baud_bits[i];
+                       ofound = i;
+               }
+               if (ibaud - iclose <= baud_table[i] &&
+                   ibaud + iclose >= baud_table[i]) {
+                       /* For the case input == output don't set IBAUD bits
+                          if the user didn't do so */
+                       if (ofound == i && !ibinput)
+                               ifound  = i;
+#ifdef IBSHIFT
+                       else {
+                               ifound = i;
+                               termios->c_cflag |= (baud_bits[i] << IBSHIFT);
+                       }
+#endif
+               }
+       } while (++i < n_baud_table);
+
+       /*
+        *      If we found no match then use BOTHER if provided or warn
+        *      the user their platform maintainer needs to wake up if not.
+        */
+#ifdef BOTHER
+       if (ofound == -1)
+               termios->c_cflag |= BOTHER;
+       /* Set exact input bits only if the input and output differ or the
+          user already did */
+       if (ifound == -1 && (ibaud != obaud || ibinput))
+               termios->c_cflag |= (BOTHER << IBSHIFT);
+#else
+       if (ifound == -1 || ofound == -1)
+               pr_warn_once("tty: Unable to return correct speed data as your architecture needs updating.\n");
+#endif
+}
+EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
+
+/**
+ *     tty_encode_baud_rate            -       set baud rate of the tty
+ *     @ibaud: input baud rate
+ *     @obad: output baud rate
+ *
+ *     Update the current termios data for the tty with the new speed
+ *     settings. The caller must hold the termios_rwsem for the tty in
+ *     question.
+ */
+
+void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud)
+{
+       tty_termios_encode_baud_rate(&tty->termios, ibaud, obaud);
+}
+EXPORT_SYMBOL_GPL(tty_encode_baud_rate);
index 309d25065bb69da0dda1820458b1b98fc1cd6c7c..0c150b5a9dd68d7bba0e91a50c45ecd5df831cac 100644 (file)
@@ -377,65 +377,6 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line)
 EXPORT_SYMBOL_GPL(tty_find_polling_driver);
 #endif
 
-static int is_ignored(int sig)
-{
-       return (sigismember(&current->blocked, sig) ||
-               current->sighand->action[sig-1].sa.sa_handler == SIG_IGN);
-}
-
-/**
- *     tty_check_change        -       check for POSIX terminal changes
- *     @tty: tty to check
- *
- *     If we try to write to, or set the state of, a terminal and we're
- *     not in the foreground, send a SIGTTOU.  If the signal is blocked or
- *     ignored, go ahead and perform the operation.  (POSIX 7.2)
- *
- *     Locking: ctrl_lock
- */
-
-int __tty_check_change(struct tty_struct *tty, int sig)
-{
-       unsigned long flags;
-       struct pid *pgrp, *tty_pgrp;
-       int ret = 0;
-
-       if (current->signal->tty != tty)
-               return 0;
-
-       rcu_read_lock();
-       pgrp = task_pgrp(current);
-
-       spin_lock_irqsave(&tty->ctrl_lock, flags);
-       tty_pgrp = tty->pgrp;
-       spin_unlock_irqrestore(&tty->ctrl_lock, flags);
-
-       if (tty_pgrp && pgrp != tty->pgrp) {
-               if (is_ignored(sig)) {
-                       if (sig == SIGTTIN)
-                               ret = -EIO;
-               } else if (is_current_pgrp_orphaned())
-                       ret = -EIO;
-               else {
-                       kill_pgrp(pgrp, sig, 1);
-                       set_thread_flag(TIF_SIGPENDING);
-                       ret = -ERESTARTSYS;
-               }
-       }
-       rcu_read_unlock();
-
-       if (!tty_pgrp)
-               tty_warn(tty, "sig=%d, tty->pgrp == NULL!\n", sig);
-
-       return ret;
-}
-
-int tty_check_change(struct tty_struct *tty)
-{
-       return __tty_check_change(tty, SIGTTOU);
-}
-EXPORT_SYMBOL(tty_check_change);
-
 static ssize_t hung_up_tty_read(struct file *file, char __user *buf,
                                size_t count, loff_t *ppos)
 {
@@ -509,79 +450,6 @@ static const struct file_operations hung_up_tty_fops = {
 static DEFINE_SPINLOCK(redirect_lock);
 static struct file *redirect;
 
-
-void proc_clear_tty(struct task_struct *p)
-{
-       unsigned long flags;
-       struct tty_struct *tty;
-       spin_lock_irqsave(&p->sighand->siglock, flags);
-       tty = p->signal->tty;
-       p->signal->tty = NULL;
-       spin_unlock_irqrestore(&p->sighand->siglock, flags);
-       tty_kref_put(tty);
-}
-
-/**
- * proc_set_tty -  set the controlling terminal
- *
- * Only callable by the session leader and only if it does not already have
- * a controlling terminal.
- *
- * Caller must hold:  tty_lock()
- *                   a readlock on tasklist_lock
- *                   sighand lock
- */
-static void __proc_set_tty(struct tty_struct *tty)
-{
-       unsigned long flags;
-
-       spin_lock_irqsave(&tty->ctrl_lock, flags);
-       /*
-        * The session and fg pgrp references will be non-NULL if
-        * tiocsctty() is stealing the controlling tty
-        */
-       put_pid(tty->session);
-       put_pid(tty->pgrp);
-       tty->pgrp = get_pid(task_pgrp(current));
-       spin_unlock_irqrestore(&tty->ctrl_lock, flags);
-       tty->session = get_pid(task_session(current));
-       if (current->signal->tty) {
-               tty_debug(tty, "current tty %s not NULL!!\n",
-                         current->signal->tty->name);
-               tty_kref_put(current->signal->tty);
-       }
-       put_pid(current->signal->tty_old_pgrp);
-       current->signal->tty = tty_kref_get(tty);
-       current->signal->tty_old_pgrp = NULL;
-}
-
-static void proc_set_tty(struct tty_struct *tty)
-{
-       spin_lock_irq(&current->sighand->siglock);
-       __proc_set_tty(tty);
-       spin_unlock_irq(&current->sighand->siglock);
-}
-
-struct tty_struct *get_current_tty(void)
-{
-       struct tty_struct *tty;
-       unsigned long flags;
-
-       spin_lock_irqsave(&current->sighand->siglock, flags);
-       tty = tty_kref_get(current->signal->tty);
-       spin_unlock_irqrestore(&current->sighand->siglock, flags);
-       return tty;
-}
-EXPORT_SYMBOL_GPL(get_current_tty);
-
-static void session_clear_tty(struct pid *session)
-{
-       struct task_struct *p;
-       do_each_pid_task(session, PIDTYPE_SID, p) {
-               proc_clear_tty(p);
-       } while_each_pid_task(session, PIDTYPE_SID, p);
-}
-
 /**
  *     tty_wakeup      -       request more data
  *     @tty: terminal
@@ -608,60 +476,6 @@ void tty_wakeup(struct tty_struct *tty)
 
 EXPORT_SYMBOL_GPL(tty_wakeup);
 
-/**
- *     tty_signal_session_leader       - sends SIGHUP to session leader
- *     @tty            controlling tty
- *     @exit_session   if non-zero, signal all foreground group processes
- *
- *     Send SIGHUP and SIGCONT to the session leader and its process group.
- *     Optionally, signal all processes in the foreground process group.
- *
- *     Returns the number of processes in the session with this tty
- *     as their controlling terminal. This value is used to drop
- *     tty references for those processes.
- */
-static int tty_signal_session_leader(struct tty_struct *tty, int exit_session)
-{
-       struct task_struct *p;
-       int refs = 0;
-       struct pid *tty_pgrp = NULL;
-
-       read_lock(&tasklist_lock);
-       if (tty->session) {
-               do_each_pid_task(tty->session, PIDTYPE_SID, p) {
-                       spin_lock_irq(&p->sighand->siglock);
-                       if (p->signal->tty == tty) {
-                               p->signal->tty = NULL;
-                               /* We defer the dereferences outside fo
-                                  the tasklist lock */
-                               refs++;
-                       }
-                       if (!p->signal->leader) {
-                               spin_unlock_irq(&p->sighand->siglock);
-                               continue;
-                       }
-                       __group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p);
-                       __group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p);
-                       put_pid(p->signal->tty_old_pgrp);  /* A noop */
-                       spin_lock(&tty->ctrl_lock);
-                       tty_pgrp = get_pid(tty->pgrp);
-                       if (tty->pgrp)
-                               p->signal->tty_old_pgrp = get_pid(tty->pgrp);
-                       spin_unlock(&tty->ctrl_lock);
-                       spin_unlock_irq(&p->sighand->siglock);
-               } while_each_pid_task(tty->session, PIDTYPE_SID, p);
-       }
-       read_unlock(&tasklist_lock);
-
-       if (tty_pgrp) {
-               if (exit_session)
-                       kill_pgrp(tty_pgrp, SIGHUP, exit_session);
-               put_pid(tty_pgrp);
-       }
-
-       return refs;
-}
-
 /**
  *     __tty_hangup            -       actual handler for hangup events
  *     @work: tty device
@@ -840,7 +654,7 @@ void tty_vhangup_self(void)
  *     is complete. That guarantee is necessary for security reasons.
  */
 
-static void tty_vhangup_session(struct tty_struct *tty)
+void tty_vhangup_session(struct tty_struct *tty)
 {
        tty_debug_hangup(tty, "session hangup\n");
        __tty_hangup(tty, 1);
@@ -861,106 +675,6 @@ int tty_hung_up_p(struct file *filp)
 
 EXPORT_SYMBOL(tty_hung_up_p);
 
-/**
- *     disassociate_ctty       -       disconnect controlling tty
- *     @on_exit: true if exiting so need to "hang up" the session
- *
- *     This function is typically called only by the session leader, when
- *     it wants to disassociate itself from its controlling tty.
- *
- *     It performs the following functions:
- *     (1)  Sends a SIGHUP and SIGCONT to the foreground process group
- *     (2)  Clears the tty from being controlling the session
- *     (3)  Clears the controlling tty for all processes in the
- *             session group.
- *
- *     The argument on_exit is set to 1 if called when a process is
- *     exiting; it is 0 if called by the ioctl TIOCNOTTY.
- *
- *     Locking:
- *             BTM is taken for hysterical raisins, and held when
- *               called from no_tty().
- *               tty_mutex is taken to protect tty
- *               ->siglock is taken to protect ->signal/->sighand
- *               tasklist_lock is taken to walk process list for sessions
- *                 ->siglock is taken to protect ->signal/->sighand
- */
-
-void disassociate_ctty(int on_exit)
-{
-       struct tty_struct *tty;
-
-       if (!current->signal->leader)
-               return;
-
-       tty = get_current_tty();
-       if (tty) {
-               if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) {
-                       tty_vhangup_session(tty);
-               } else {
-                       struct pid *tty_pgrp = tty_get_pgrp(tty);
-                       if (tty_pgrp) {
-                               kill_pgrp(tty_pgrp, SIGHUP, on_exit);
-                               if (!on_exit)
-                                       kill_pgrp(tty_pgrp, SIGCONT, on_exit);
-                               put_pid(tty_pgrp);
-                       }
-               }
-               tty_kref_put(tty);
-
-       } else if (on_exit) {
-               struct pid *old_pgrp;
-               spin_lock_irq(&current->sighand->siglock);
-               old_pgrp = current->signal->tty_old_pgrp;
-               current->signal->tty_old_pgrp = NULL;
-               spin_unlock_irq(&current->sighand->siglock);
-               if (old_pgrp) {
-                       kill_pgrp(old_pgrp, SIGHUP, on_exit);
-                       kill_pgrp(old_pgrp, SIGCONT, on_exit);
-                       put_pid(old_pgrp);
-               }
-               return;
-       }
-
-       spin_lock_irq(&current->sighand->siglock);
-       put_pid(current->signal->tty_old_pgrp);
-       current->signal->tty_old_pgrp = NULL;
-
-       tty = tty_kref_get(current->signal->tty);
-       if (tty) {
-               unsigned long flags;
-               spin_lock_irqsave(&tty->ctrl_lock, flags);
-               put_pid(tty->session);
-               put_pid(tty->pgrp);
-               tty->session = NULL;
-               tty->pgrp = NULL;
-               spin_unlock_irqrestore(&tty->ctrl_lock, flags);
-               tty_kref_put(tty);
-       } else
-               tty_debug_hangup(tty, "no current tty\n");
-
-       spin_unlock_irq(&current->sighand->siglock);
-       /* Now clear signal->tty under the lock */
-       read_lock(&tasklist_lock);
-       session_clear_tty(task_session(current));
-       read_unlock(&tasklist_lock);
-}
-
-/**
- *
- *     no_tty  - Ensure the current process does not have a controlling tty
- */
-void no_tty(void)
-{
-       /* FIXME: Review locking here. The tty_lock never covered any race
-          between a new association and proc_clear_tty but possible we need
-          to protect against this anyway */
-       struct task_struct *tsk = current;
-       disassociate_ctty(0);
-       proc_clear_tty(tsk);
-}
-
-
 /**
  *     stop_tty        -       propagate flow control
  *     @tty: tty to stop
@@ -1520,7 +1234,7 @@ struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx)
         * This code guarantees that either everything succeeds and the
         * TTY is ready for operation, or else the table slots are vacated
         * and the allocated memory released.  (Except that the termios
-        * and locked termios may be retained.)
+        * may be retained.)
         */
 
        if (!try_module_get(driver->owner))
@@ -2163,38 +1877,13 @@ retry_open:
        }
        clear_bit(TTY_HUPPED, &tty->flags);
 
-
-       read_lock(&tasklist_lock);
-       spin_lock_irq(&current->sighand->siglock);
        noctty = (filp->f_flags & O_NOCTTY) ||
-                       (IS_ENABLED(CONFIG_VT) && device == MKDEV(TTY_MAJOR, 0)) ||
-                       device == MKDEV(TTYAUX_MAJOR, 1) ||
-                       (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
-                        tty->driver->subtype == PTY_TYPE_MASTER);
-
-       if (!noctty &&
-           current->signal->leader &&
-           !current->signal->tty &&
-           tty->session == NULL) {
-               /*
-                * Don't let a process that only has write access to the tty
-                * obtain the privileges associated with having a tty as
-                * controlling terminal (being able to reopen it with full
-                * access through /dev/tty, being able to perform pushback).
-                * Many distributions set the group of all ttys to "tty" and
-                * grant write-only access to all terminals for setgid tty
-                * binaries, which should not imply full privileges on all ttys.
-                *
-                * This could theoretically break old code that performs open()
-                * on a write-only file descriptor. In that case, it might be
-                * necessary to also permit this if
-                * inode_permission(inode, MAY_READ) == 0.
-                */
-               if (filp->f_mode & FMODE_READ)
-                       __proc_set_tty(tty);
-       }
-       spin_unlock_irq(&current->sighand->siglock);
-       read_unlock(&tasklist_lock);
+                (IS_ENABLED(CONFIG_VT) && device == MKDEV(TTY_MAJOR, 0)) ||
+                device == MKDEV(TTYAUX_MAJOR, 1) ||
+                (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
+                 tty->driver->subtype == PTY_TYPE_MASTER);
+       if (!noctty)
+               tty_open_proc_set_tty(filp, tty);
        tty_unlock(tty);
        return 0;
 }
@@ -2456,211 +2145,6 @@ static int fionbio(struct file *file, int __user *p)
        return 0;
 }
 
-/**
- *     tiocsctty       -       set controlling tty
- *     @tty: tty structure
- *     @arg: user argument
- *
- *     This ioctl is used to manage job control. It permits a session
- *     leader to set this tty as the controlling tty for the session.
- *
- *     Locking:
- *             Takes tty_lock() to serialize proc_set_tty() for this tty
- *             Takes tasklist_lock internally to walk sessions
- *             Takes ->siglock() when updating signal->tty
- */
-
-static int tiocsctty(struct tty_struct *tty, struct file *file, int arg)
-{
-       int ret = 0;
-
-       tty_lock(tty);
-       read_lock(&tasklist_lock);
-
-       if (current->signal->leader && (task_session(current) == tty->session))
-               goto unlock;
-
-       /*
-        * The process must be a session leader and
-        * not have a controlling tty already.
-        */
-       if (!current->signal->leader || current->signal->tty) {
-               ret = -EPERM;
-               goto unlock;
-       }
-
-       if (tty->session) {
-               /*
-                * This tty is already the controlling
-                * tty for another session group!
-                */
-               if (arg == 1 && capable(CAP_SYS_ADMIN)) {
-                       /*
-                        * Steal it away
-                        */
-                       session_clear_tty(tty->session);
-               } else {
-                       ret = -EPERM;
-                       goto unlock;
-               }
-       }
-
-       /* See the comment in tty_open(). */
-       if ((file->f_mode & FMODE_READ) == 0 && !capable(CAP_SYS_ADMIN)) {
-               ret = -EPERM;
-               goto unlock;
-       }
-
-       proc_set_tty(tty);
-unlock:
-       read_unlock(&tasklist_lock);
-       tty_unlock(tty);
-       return ret;
-}
-
-/**
- *     tty_get_pgrp    -       return a ref counted pgrp pid
- *     @tty: tty to read
- *
- *     Returns a refcounted instance of the pid struct for the process
- *     group controlling the tty.
- */
-
-struct pid *tty_get_pgrp(struct tty_struct *tty)
-{
-       unsigned long flags;
-       struct pid *pgrp;
-
-       spin_lock_irqsave(&tty->ctrl_lock, flags);
-       pgrp = get_pid(tty->pgrp);
-       spin_unlock_irqrestore(&tty->ctrl_lock, flags);
-
-       return pgrp;
-}
-EXPORT_SYMBOL_GPL(tty_get_pgrp);
-
-/*
- * This checks not only the pgrp, but falls back on the pid if no
- * satisfactory pgrp is found. I dunno - gdb doesn't work correctly
- * without this...
- *
- * The caller must hold rcu lock or the tasklist lock.
- */
-static struct pid *session_of_pgrp(struct pid *pgrp)
-{
-       struct task_struct *p;
-       struct pid *sid = NULL;
-
-       p = pid_task(pgrp, PIDTYPE_PGID);
-       if (p == NULL)
-               p = pid_task(pgrp, PIDTYPE_PID);
-       if (p != NULL)
-               sid = task_session(p);
-
-       return sid;
-}
-
-/**
- *     tiocgpgrp               -       get process group
- *     @tty: tty passed by user
- *     @real_tty: tty side of the tty passed by the user if a pty else the tty
- *     @p: returned pid
- *
- *     Obtain the process group of the tty. If there is no process group
- *     return an error.
- *
- *     Locking: none. Reference to current->signal->tty is safe.
- */
-
-static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
-{
-       struct pid *pid;
-       int ret;
-       /*
-        * (tty == real_tty) is a cheap way of
-        * testing if the tty is NOT a master pty.
-        */
-       if (tty == real_tty && current->signal->tty != real_tty)
-               return -ENOTTY;
-       pid = tty_get_pgrp(real_tty);
-       ret =  put_user(pid_vnr(pid), p);
-       put_pid(pid);
-       return ret;
-}
-
-/**
- *     tiocspgrp               -       attempt to set process group
- *     @tty: tty passed by user
- *     @real_tty: tty side device matching tty passed by user
- *     @p: pid pointer
- *
- *     Set the process group of the tty to the session passed. Only
- *     permitted where the tty session is our session.
- *
- *     Locking: RCU, ctrl lock
- */
-
-static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
-{
-       struct pid *pgrp;
-       pid_t pgrp_nr;
-       int retval = tty_check_change(real_tty);
-
-       if (retval == -EIO)
-               return -ENOTTY;
-       if (retval)
-               return retval;
-       if (!current->signal->tty ||
-           (current->signal->tty != real_tty) ||
-           (real_tty->session != task_session(current)))
-               return -ENOTTY;
-       if (get_user(pgrp_nr, p))
-               return -EFAULT;
-       if (pgrp_nr < 0)
-               return -EINVAL;
-       rcu_read_lock();
-       pgrp = find_vpid(pgrp_nr);
-       retval = -ESRCH;
-       if (!pgrp)
-               goto out_unlock;
-       retval = -EPERM;
-       if (session_of_pgrp(pgrp) != task_session(current))
-               goto out_unlock;
-       retval = 0;
-       spin_lock_irq(&tty->ctrl_lock);
-       put_pid(real_tty->pgrp);
-       real_tty->pgrp = get_pid(pgrp);
-       spin_unlock_irq(&tty->ctrl_lock);
-out_unlock:
-       rcu_read_unlock();
-       return retval;
-}
-
-/**
- *     tiocgsid                -       get session id
- *     @tty: tty passed by user
- *     @real_tty: tty side of the tty passed by the user if a pty else the tty
- *     @p: pointer to returned session id
- *
- *     Obtain the session id of the tty. If there is no session
- *     return an error.
- *
- *     Locking: none. Reference to current->signal->tty is safe.
- */
-
-static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
-{
-       /*
-        * (tty == real_tty) is a cheap way of
-        * testing if the tty is NOT a master pty.
-       */
-       if (tty == real_tty && current->signal->tty != real_tty)
-               return -ENOTTY;
-       if (!real_tty->session)
-               return -ENOTTY;
-       return put_user(pid_vnr(real_tty->session), p);
-}
-
 /**
  *     tiocsetd        -       set line discipline
  *     @tty: tty device
@@ -2843,8 +2327,8 @@ static void tty_warn_deprecated_flags(struct serial_struct __user *ss)
        flags &= ASYNC_DEPRECATED;
 
        if (flags && __ratelimit(&depr_flags))
-               pr_warning("%s: '%s' is using deprecated serial flags (with no effect): %.8x\n",
-                               __func__, get_task_comm(comm, current), flags);
+               pr_warn("%s: '%s' is using deprecated serial flags (with no effect): %.8x\n",
+                       __func__, get_task_comm(comm, current), flags);
 }
 
 /*
@@ -2920,19 +2404,6 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                int excl = test_bit(TTY_EXCLUSIVE, &tty->flags);
                return put_user(excl, (int __user *)p);
        }
-       case TIOCNOTTY:
-               if (current->signal->tty != tty)
-                       return -ENOTTY;
-               no_tty();
-               return 0;
-       case TIOCSCTTY:
-               return tiocsctty(real_tty, file, arg);
-       case TIOCGPGRP:
-               return tiocgpgrp(tty, real_tty, p);
-       case TIOCSPGRP:
-               return tiocspgrp(tty, real_tty, p);
-       case TIOCGSID:
-               return tiocgsid(tty, real_tty, p);
        case TIOCGETD:
                return tiocgetd(tty, p);
        case TIOCSETD:
@@ -2993,6 +2464,10 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
        case TIOCSSERIAL:
                tty_warn_deprecated_flags(p);
                break;
+       default:
+               retval = tty_jobctrl_ioctl(tty, real_tty, file, cmd, arg);
+               if (retval != -ENOIOCTLCMD)
+                       return retval;
        }
        if (tty->ops->ioctl) {
                retval = tty->ops->ioctl(tty, cmd, arg);
@@ -3293,9 +2768,9 @@ struct device *tty_register_device_attr(struct tty_driver *driver,
 {
        char name[64];
        dev_t devt = MKDEV(driver->major, driver->minor_start) + index;
-       struct device *dev = NULL;
-       int retval = -ENODEV;
-       bool cdev = false;
+       struct ktermios *tp;
+       struct device *dev;
+       int retval;
 
        if (index >= driver->num) {
                pr_err("%s: Attempt to register invalid tty line number (%d)\n",
@@ -3308,18 +2783,9 @@ struct device *tty_register_device_attr(struct tty_driver *driver,
        else
                tty_line_name(driver, index, name);
 
-       if (!(driver->flags & TTY_DRIVER_DYNAMIC_ALLOC)) {
-               retval = tty_cdev_add(driver, devt, index, 1);
-               if (retval)
-                       goto error;
-               cdev = true;
-       }
-
        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-       if (!dev) {
-               retval = -ENOMEM;
-               goto error;
-       }
+       if (!dev)
+               return ERR_PTR(-ENOMEM);
 
        dev->devt = devt;
        dev->class = tty_class;
@@ -3329,18 +2795,38 @@ struct device *tty_register_device_attr(struct tty_driver *driver,
        dev->groups = attr_grp;
        dev_set_drvdata(dev, drvdata);
 
+       dev_set_uevent_suppress(dev, 1);
+
        retval = device_register(dev);
        if (retval)
-               goto error;
+               goto err_put;
+
+       if (!(driver->flags & TTY_DRIVER_DYNAMIC_ALLOC)) {
+               /*
+                * Free any saved termios data so that the termios state is
+                * reset when reusing a minor number.
+                */
+               tp = driver->termios[index];
+               if (tp) {
+                       driver->termios[index] = NULL;
+                       kfree(tp);
+               }
+
+               retval = tty_cdev_add(driver, devt, index, 1);
+               if (retval)
+                       goto err_del;
+       }
+
+       dev_set_uevent_suppress(dev, 0);
+       kobject_uevent(&dev->kobj, KOBJ_ADD);
 
        return dev;
 
-error:
+err_del:
+       device_del(dev);
+err_put:
        put_device(dev);
-       if (cdev) {
-               cdev_del(driver->cdevs[index]);
-               driver->cdevs[index] = NULL;
-       }
+
        return ERR_PTR(retval);
 }
 EXPORT_SYMBOL_GPL(tty_register_device_attr);
@@ -3441,11 +2927,6 @@ static void destruct_tty_driver(struct kref *kref)
        struct ktermios *tp;
 
        if (driver->flags & TTY_DRIVER_INSTALLED) {
-               /*
-                * Free the termios and termios_locked structures because
-                * we don't want to get memory leaks when modular tty
-                * drivers are removed from the kernel.
-                */
                for (i = 0; i < driver->num; i++) {
                        tp = driver->termios[i];
                        if (tp) {
@@ -3578,30 +3059,6 @@ void tty_default_fops(struct file_operations *fops)
        *fops = tty_fops;
 }
 
-/*
- * Initialize the console device. This is called *early*, so
- * we can't necessarily depend on lots of kernel help here.
- * Just do some early initializations, and do the complex setup
- * later.
- */
-void __init console_init(void)
-{
-       initcall_t *call;
-
-       /* Setup the default TTY line discipline. */
-       n_tty_init();
-
-       /*
-        * set up the console device so that later boot sequences can
-        * inform about problems etc..
-        */
-       call = __con_initcall_start;
-       while (call < __con_initcall_end) {
-               (*call)();
-               call++;
-       }
-}
-
 static char *tty_devnode(struct device *dev, umode_t *mode)
 {
        if (!mode)
index a9a978731c5b0d66f3a96b8cb076ef84ac7b3b0d..efa96e6c4c1b44f1e37a8fa94c8a4caa52e9a688 100644 (file)
@@ -258,228 +258,6 @@ static void unset_locked_termios(struct tty_struct *tty, struct ktermios *old)
        /* FIXME: What should we do for i/ospeed */
 }
 
-/*
- * Routine which returns the baud rate of the tty
- *
- * Note that the baud_table needs to be kept in sync with the
- * include/asm/termbits.h file.
- */
-static const speed_t baud_table[] = {
-       0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
-       9600, 19200, 38400, 57600, 115200, 230400, 460800,
-#ifdef __sparc__
-       76800, 153600, 307200, 614400, 921600
-#else
-       500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,
-       2500000, 3000000, 3500000, 4000000
-#endif
-};
-
-#ifndef __sparc__
-static const tcflag_t baud_bits[] = {
-       B0, B50, B75, B110, B134, B150, B200, B300, B600,
-       B1200, B1800, B2400, B4800, B9600, B19200, B38400,
-       B57600, B115200, B230400, B460800, B500000, B576000,
-       B921600, B1000000, B1152000, B1500000, B2000000, B2500000,
-       B3000000, B3500000, B4000000
-};
-#else
-static const tcflag_t baud_bits[] = {
-       B0, B50, B75, B110, B134, B150, B200, B300, B600,
-       B1200, B1800, B2400, B4800, B9600, B19200, B38400,
-       B57600, B115200, B230400, B460800, B76800, B153600,
-       B307200, B614400, B921600
-};
-#endif
-
-static int n_baud_table = ARRAY_SIZE(baud_table);
-
-/**
- *     tty_termios_baud_rate
- *     @termios: termios structure
- *
- *     Convert termios baud rate data into a speed. This should be called
- *     with the termios lock held if this termios is a terminal termios
- *     structure. May change the termios data. Device drivers can call this
- *     function but should use ->c_[io]speed directly as they are updated.
- *
- *     Locking: none
- */
-
-speed_t tty_termios_baud_rate(struct ktermios *termios)
-{
-       unsigned int cbaud;
-
-       cbaud = termios->c_cflag & CBAUD;
-
-#ifdef BOTHER
-       /* Magic token for arbitrary speed via c_ispeed/c_ospeed */
-       if (cbaud == BOTHER)
-               return termios->c_ospeed;
-#endif
-       if (cbaud & CBAUDEX) {
-               cbaud &= ~CBAUDEX;
-
-               if (cbaud < 1 || cbaud + 15 > n_baud_table)
-                       termios->c_cflag &= ~CBAUDEX;
-               else
-                       cbaud += 15;
-       }
-       return baud_table[cbaud];
-}
-EXPORT_SYMBOL(tty_termios_baud_rate);
-
-/**
- *     tty_termios_input_baud_rate
- *     @termios: termios structure
- *
- *     Convert termios baud rate data into a speed. This should be called
- *     with the termios lock held if this termios is a terminal termios
- *     structure. May change the termios data. Device drivers can call this
- *     function but should use ->c_[io]speed directly as they are updated.
- *
- *     Locking: none
- */
-
-speed_t tty_termios_input_baud_rate(struct ktermios *termios)
-{
-#ifdef IBSHIFT
-       unsigned int cbaud = (termios->c_cflag >> IBSHIFT) & CBAUD;
-
-       if (cbaud == B0)
-               return tty_termios_baud_rate(termios);
-
-       /* Magic token for arbitrary speed via c_ispeed*/
-       if (cbaud == BOTHER)
-               return termios->c_ispeed;
-
-       if (cbaud & CBAUDEX) {
-               cbaud &= ~CBAUDEX;
-
-               if (cbaud < 1 || cbaud + 15 > n_baud_table)
-                       termios->c_cflag &= ~(CBAUDEX << IBSHIFT);
-               else
-                       cbaud += 15;
-       }
-       return baud_table[cbaud];
-#else
-       return tty_termios_baud_rate(termios);
-#endif
-}
-EXPORT_SYMBOL(tty_termios_input_baud_rate);
-
-/**
- *     tty_termios_encode_baud_rate
- *     @termios: ktermios structure holding user requested state
- *     @ispeed: input speed
- *     @ospeed: output speed
- *
- *     Encode the speeds set into the passed termios structure. This is
- *     used as a library helper for drivers so that they can report back
- *     the actual speed selected when it differs from the speed requested
- *
- *     For maximal back compatibility with legacy SYS5/POSIX *nix behaviour
- *     we need to carefully set the bits when the user does not get the
- *     desired speed. We allow small margins and preserve as much of possible
- *     of the input intent to keep compatibility.
- *
- *     Locking: Caller should hold termios lock. This is already held
- *     when calling this function from the driver termios handler.
- *
- *     The ifdefs deal with platforms whose owners have yet to update them
- *     and will all go away once this is done.
- */
-
-void tty_termios_encode_baud_rate(struct ktermios *termios,
-                                 speed_t ibaud, speed_t obaud)
-{
-       int i = 0;
-       int ifound = -1, ofound = -1;
-       int iclose = ibaud/50, oclose = obaud/50;
-       int ibinput = 0;
-
-       if (obaud == 0)                 /* CD dropped             */
-               ibaud = 0;              /* Clear ibaud to be sure */
-
-       termios->c_ispeed = ibaud;
-       termios->c_ospeed = obaud;
-
-#ifdef BOTHER
-       /* If the user asked for a precise weird speed give a precise weird
-          answer. If they asked for a Bfoo speed they may have problems
-          digesting non-exact replies so fuzz a bit */
-
-       if ((termios->c_cflag & CBAUD) == BOTHER)
-               oclose = 0;
-       if (((termios->c_cflag >> IBSHIFT) & CBAUD) == BOTHER)
-               iclose = 0;
-       if ((termios->c_cflag >> IBSHIFT) & CBAUD)
-               ibinput = 1;    /* An input speed was specified */
-#endif
-       termios->c_cflag &= ~CBAUD;
-
-       /*
-        *      Our goal is to find a close match to the standard baud rate
-        *      returned. Walk the baud rate table and if we get a very close
-        *      match then report back the speed as a POSIX Bxxxx value by
-        *      preference
-        */
-
-       do {
-               if (obaud - oclose <= baud_table[i] &&
-                   obaud + oclose >= baud_table[i]) {
-                       termios->c_cflag |= baud_bits[i];
-                       ofound = i;
-               }
-               if (ibaud - iclose <= baud_table[i] &&
-                   ibaud + iclose >= baud_table[i]) {
-                       /* For the case input == output don't set IBAUD bits
-                          if the user didn't do so */
-                       if (ofound == i && !ibinput)
-                               ifound  = i;
-#ifdef IBSHIFT
-                       else {
-                               ifound = i;
-                               termios->c_cflag |= (baud_bits[i] << IBSHIFT);
-                       }
-#endif
-               }
-       } while (++i < n_baud_table);
-
-       /*
-        *      If we found no match then use BOTHER if provided or warn
-        *      the user their platform maintainer needs to wake up if not.
-        */
-#ifdef BOTHER
-       if (ofound == -1)
-               termios->c_cflag |= BOTHER;
-       /* Set exact input bits only if the input and output differ or the
-          user already did */
-       if (ifound == -1 && (ibaud != obaud || ibinput))
-               termios->c_cflag |= (BOTHER << IBSHIFT);
-#else
-       if (ifound == -1 || ofound == -1)
-               pr_warn_once("tty: Unable to return correct speed data as your architecture needs updating.\n");
-#endif
-}
-EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
-
-/**
- *     tty_encode_baud_rate            -       set baud rate of the tty
- *     @ibaud: input baud rate
- *     @obad: output baud rate
- *
- *     Update the current termios data for the tty with the new speed
- *     settings. The caller must hold the termios_rwsem for the tty in
- *     question.
- */
-
-void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud)
-{
-       tty_termios_encode_baud_rate(&tty->termios, ibaud, obaud);
-}
-EXPORT_SYMBOL_GPL(tty_encode_baud_rate);
-
 /**
  *     tty_termios_copy_hw     -       copy hardware settings
  *     @new: New termios
diff --git a/drivers/tty/tty_jobctrl.c b/drivers/tty/tty_jobctrl.c
new file mode 100644 (file)
index 0000000..e703230
--- /dev/null
@@ -0,0 +1,554 @@
+/*
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/signal.h>
+#include <linux/sched/signal.h>
+#include <linux/sched/task.h>
+#include <linux/tty.h>
+#include <linux/fcntl.h>
+#include <linux/uaccess.h>
+
+static int is_ignored(int sig)
+{
+       return (sigismember(&current->blocked, sig) ||
+               current->sighand->action[sig-1].sa.sa_handler == SIG_IGN);
+}
+
+/**
+ *     tty_check_change        -       check for POSIX terminal changes
+ *     @tty: tty to check
+ *
+ *     If we try to write to, or set the state of, a terminal and we're
+ *     not in the foreground, send a SIGTTOU.  If the signal is blocked or
+ *     ignored, go ahead and perform the operation.  (POSIX 7.2)
+ *
+ *     Locking: ctrl_lock
+ */
+int __tty_check_change(struct tty_struct *tty, int sig)
+{
+       unsigned long flags;
+       struct pid *pgrp, *tty_pgrp;
+       int ret = 0;
+
+       if (current->signal->tty != tty)
+               return 0;
+
+       rcu_read_lock();
+       pgrp = task_pgrp(current);
+
+       spin_lock_irqsave(&tty->ctrl_lock, flags);
+       tty_pgrp = tty->pgrp;
+       spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+
+       if (tty_pgrp && pgrp != tty->pgrp) {
+               if (is_ignored(sig)) {
+                       if (sig == SIGTTIN)
+                               ret = -EIO;
+               } else if (is_current_pgrp_orphaned())
+                       ret = -EIO;
+               else {
+                       kill_pgrp(pgrp, sig, 1);
+                       set_thread_flag(TIF_SIGPENDING);
+                       ret = -ERESTARTSYS;
+               }
+       }
+       rcu_read_unlock();
+
+       if (!tty_pgrp)
+               tty_warn(tty, "sig=%d, tty->pgrp == NULL!\n", sig);
+
+       return ret;
+}
+
+int tty_check_change(struct tty_struct *tty)
+{
+       return __tty_check_change(tty, SIGTTOU);
+}
+EXPORT_SYMBOL(tty_check_change);
+
+void proc_clear_tty(struct task_struct *p)
+{
+       unsigned long flags;
+       struct tty_struct *tty;
+       spin_lock_irqsave(&p->sighand->siglock, flags);
+       tty = p->signal->tty;
+       p->signal->tty = NULL;
+       spin_unlock_irqrestore(&p->sighand->siglock, flags);
+       tty_kref_put(tty);
+}
+
+/**
+ * proc_set_tty -  set the controlling terminal
+ *
+ * Only callable by the session leader and only if it does not already have
+ * a controlling terminal.
+ *
+ * Caller must hold:  tty_lock()
+ *                   a readlock on tasklist_lock
+ *                   sighand lock
+ */
+static void __proc_set_tty(struct tty_struct *tty)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&tty->ctrl_lock, flags);
+       /*
+        * The session and fg pgrp references will be non-NULL if
+        * tiocsctty() is stealing the controlling tty
+        */
+       put_pid(tty->session);
+       put_pid(tty->pgrp);
+       tty->pgrp = get_pid(task_pgrp(current));
+       spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+       tty->session = get_pid(task_session(current));
+       if (current->signal->tty) {
+               tty_debug(tty, "current tty %s not NULL!!\n",
+                         current->signal->tty->name);
+               tty_kref_put(current->signal->tty);
+       }
+       put_pid(current->signal->tty_old_pgrp);
+       current->signal->tty = tty_kref_get(tty);
+       current->signal->tty_old_pgrp = NULL;
+}
+
+static void proc_set_tty(struct tty_struct *tty)
+{
+       spin_lock_irq(&current->sighand->siglock);
+       __proc_set_tty(tty);
+       spin_unlock_irq(&current->sighand->siglock);
+}
+
+/*
+ * Called by tty_open() to set the controlling tty if applicable.
+ */
+void tty_open_proc_set_tty(struct file *filp, struct tty_struct *tty)
+{
+       read_lock(&tasklist_lock);
+       spin_lock_irq(&current->sighand->siglock);
+       if (current->signal->leader &&
+           !current->signal->tty &&
+           tty->session == NULL) {
+               /*
+                * Don't let a process that only has write access to the tty
+                * obtain the privileges associated with having a tty as
+                * controlling terminal (being able to reopen it with full
+                * access through /dev/tty, being able to perform pushback).
+                * Many distributions set the group of all ttys to "tty" and
+                * grant write-only access to all terminals for setgid tty
+                * binaries, which should not imply full privileges on all ttys.
+                *
+                * This could theoretically break old code that performs open()
+                * on a write-only file descriptor. In that case, it might be
+                * necessary to also permit this if
+                * inode_permission(inode, MAY_READ) == 0.
+                */
+               if (filp->f_mode & FMODE_READ)
+                       __proc_set_tty(tty);
+       }
+       spin_unlock_irq(&current->sighand->siglock);
+       read_unlock(&tasklist_lock);
+}
+
+struct tty_struct *get_current_tty(void)
+{
+       struct tty_struct *tty;
+       unsigned long flags;
+
+       spin_lock_irqsave(&current->sighand->siglock, flags);
+       tty = tty_kref_get(current->signal->tty);
+       spin_unlock_irqrestore(&current->sighand->siglock, flags);
+       return tty;
+}
+EXPORT_SYMBOL_GPL(get_current_tty);
+
+/*
+ * Called from tty_release().
+ */
+void session_clear_tty(struct pid *session)
+{
+       struct task_struct *p;
+       do_each_pid_task(session, PIDTYPE_SID, p) {
+               proc_clear_tty(p);
+       } while_each_pid_task(session, PIDTYPE_SID, p);
+}
+
+/**
+ *     tty_signal_session_leader       - sends SIGHUP to session leader
+ *     @tty            controlling tty
+ *     @exit_session   if non-zero, signal all foreground group processes
+ *
+ *     Send SIGHUP and SIGCONT to the session leader and its process group.
+ *     Optionally, signal all processes in the foreground process group.
+ *
+ *     Returns the number of processes in the session with this tty
+ *     as their controlling terminal. This value is used to drop
+ *     tty references for those processes.
+ */
+int tty_signal_session_leader(struct tty_struct *tty, int exit_session)
+{
+       struct task_struct *p;
+       int refs = 0;
+       struct pid *tty_pgrp = NULL;
+
+       read_lock(&tasklist_lock);
+       if (tty->session) {
+               do_each_pid_task(tty->session, PIDTYPE_SID, p) {
+                       spin_lock_irq(&p->sighand->siglock);
+                       if (p->signal->tty == tty) {
+                               p->signal->tty = NULL;
+                               /* We defer the dereferences outside fo
+                                  the tasklist lock */
+                               refs++;
+                       }
+                       if (!p->signal->leader) {
+                               spin_unlock_irq(&p->sighand->siglock);
+                               continue;
+                       }
+                       __group_send_sig_info(SIGHUP, SEND_SIG_PRIV, p);
+                       __group_send_sig_info(SIGCONT, SEND_SIG_PRIV, p);
+                       put_pid(p->signal->tty_old_pgrp);  /* A noop */
+                       spin_lock(&tty->ctrl_lock);
+                       tty_pgrp = get_pid(tty->pgrp);
+                       if (tty->pgrp)
+                               p->signal->tty_old_pgrp = get_pid(tty->pgrp);
+                       spin_unlock(&tty->ctrl_lock);
+                       spin_unlock_irq(&p->sighand->siglock);
+               } while_each_pid_task(tty->session, PIDTYPE_SID, p);
+       }
+       read_unlock(&tasklist_lock);
+
+       if (tty_pgrp) {
+               if (exit_session)
+                       kill_pgrp(tty_pgrp, SIGHUP, exit_session);
+               put_pid(tty_pgrp);
+       }
+
+       return refs;
+}
+
+/**
+ *     disassociate_ctty       -       disconnect controlling tty
+ *     @on_exit: true if exiting so need to "hang up" the session
+ *
+ *     This function is typically called only by the session leader, when
+ *     it wants to disassociate itself from its controlling tty.
+ *
+ *     It performs the following functions:
+ *     (1)  Sends a SIGHUP and SIGCONT to the foreground process group
+ *     (2)  Clears the tty from being controlling the session
+ *     (3)  Clears the controlling tty for all processes in the
+ *             session group.
+ *
+ *     The argument on_exit is set to 1 if called when a process is
+ *     exiting; it is 0 if called by the ioctl TIOCNOTTY.
+ *
+ *     Locking:
+ *             BTM is taken for hysterical raisons, and held when
+ *               called from no_tty().
+ *               tty_mutex is taken to protect tty
+ *               ->siglock is taken to protect ->signal/->sighand
+ *               tasklist_lock is taken to walk process list for sessions
+ *                 ->siglock is taken to protect ->signal/->sighand
+ */
+void disassociate_ctty(int on_exit)
+{
+       struct tty_struct *tty;
+
+       if (!current->signal->leader)
+               return;
+
+       tty = get_current_tty();
+       if (tty) {
+               if (on_exit && tty->driver->type != TTY_DRIVER_TYPE_PTY) {
+                       tty_vhangup_session(tty);
+               } else {
+                       struct pid *tty_pgrp = tty_get_pgrp(tty);
+                       if (tty_pgrp) {
+                               kill_pgrp(tty_pgrp, SIGHUP, on_exit);
+                               if (!on_exit)
+                                       kill_pgrp(tty_pgrp, SIGCONT, on_exit);
+                               put_pid(tty_pgrp);
+                       }
+               }
+               tty_kref_put(tty);
+
+       } else if (on_exit) {
+               struct pid *old_pgrp;
+               spin_lock_irq(&current->sighand->siglock);
+               old_pgrp = current->signal->tty_old_pgrp;
+               current->signal->tty_old_pgrp = NULL;
+               spin_unlock_irq(&current->sighand->siglock);
+               if (old_pgrp) {
+                       kill_pgrp(old_pgrp, SIGHUP, on_exit);
+                       kill_pgrp(old_pgrp, SIGCONT, on_exit);
+                       put_pid(old_pgrp);
+               }
+               return;
+       }
+
+       spin_lock_irq(&current->sighand->siglock);
+       put_pid(current->signal->tty_old_pgrp);
+       current->signal->tty_old_pgrp = NULL;
+
+       tty = tty_kref_get(current->signal->tty);
+       if (tty) {
+               unsigned long flags;
+               spin_lock_irqsave(&tty->ctrl_lock, flags);
+               put_pid(tty->session);
+               put_pid(tty->pgrp);
+               tty->session = NULL;
+               tty->pgrp = NULL;
+               spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+               tty_kref_put(tty);
+       }
+
+       spin_unlock_irq(&current->sighand->siglock);
+       /* Now clear signal->tty under the lock */
+       read_lock(&tasklist_lock);
+       session_clear_tty(task_session(current));
+       read_unlock(&tasklist_lock);
+}
+
+/**
+ *
+ *     no_tty  - Ensure the current process does not have a controlling tty
+ */
+void no_tty(void)
+{
+       /* FIXME: Review locking here. The tty_lock never covered any race
+          between a new association and proc_clear_tty but possible we need
+          to protect against this anyway */
+       struct task_struct *tsk = current;
+       disassociate_ctty(0);
+       proc_clear_tty(tsk);
+}
+
+/**
+ *     tiocsctty       -       set controlling tty
+ *     @tty: tty structure
+ *     @arg: user argument
+ *
+ *     This ioctl is used to manage job control. It permits a session
+ *     leader to set this tty as the controlling tty for the session.
+ *
+ *     Locking:
+ *             Takes tty_lock() to serialize proc_set_tty() for this tty
+ *             Takes tasklist_lock internally to walk sessions
+ *             Takes ->siglock() when updating signal->tty
+ */
+static int tiocsctty(struct tty_struct *tty, struct file *file, int arg)
+{
+       int ret = 0;
+
+       tty_lock(tty);
+       read_lock(&tasklist_lock);
+
+       if (current->signal->leader && (task_session(current) == tty->session))
+               goto unlock;
+
+       /*
+        * The process must be a session leader and
+        * not have a controlling tty already.
+        */
+       if (!current->signal->leader || current->signal->tty) {
+               ret = -EPERM;
+               goto unlock;
+       }
+
+       if (tty->session) {
+               /*
+                * This tty is already the controlling
+                * tty for another session group!
+                */
+               if (arg == 1 && capable(CAP_SYS_ADMIN)) {
+                       /*
+                        * Steal it away
+                        */
+                       session_clear_tty(tty->session);
+               } else {
+                       ret = -EPERM;
+                       goto unlock;
+               }
+       }
+
+       /* See the comment in tty_open_proc_set_tty(). */
+       if ((file->f_mode & FMODE_READ) == 0 && !capable(CAP_SYS_ADMIN)) {
+               ret = -EPERM;
+               goto unlock;
+       }
+
+       proc_set_tty(tty);
+unlock:
+       read_unlock(&tasklist_lock);
+       tty_unlock(tty);
+       return ret;
+}
+
+/**
+ *     tty_get_pgrp    -       return a ref counted pgrp pid
+ *     @tty: tty to read
+ *
+ *     Returns a refcounted instance of the pid struct for the process
+ *     group controlling the tty.
+ */
+struct pid *tty_get_pgrp(struct tty_struct *tty)
+{
+       unsigned long flags;
+       struct pid *pgrp;
+
+       spin_lock_irqsave(&tty->ctrl_lock, flags);
+       pgrp = get_pid(tty->pgrp);
+       spin_unlock_irqrestore(&tty->ctrl_lock, flags);
+
+       return pgrp;
+}
+EXPORT_SYMBOL_GPL(tty_get_pgrp);
+
+/*
+ * This checks not only the pgrp, but falls back on the pid if no
+ * satisfactory pgrp is found. I dunno - gdb doesn't work correctly
+ * without this...
+ *
+ * The caller must hold rcu lock or the tasklist lock.
+ */
+static struct pid *session_of_pgrp(struct pid *pgrp)
+{
+       struct task_struct *p;
+       struct pid *sid = NULL;
+
+       p = pid_task(pgrp, PIDTYPE_PGID);
+       if (p == NULL)
+               p = pid_task(pgrp, PIDTYPE_PID);
+       if (p != NULL)
+               sid = task_session(p);
+
+       return sid;
+}
+
+/**
+ *     tiocgpgrp               -       get process group
+ *     @tty: tty passed by user
+ *     @real_tty: tty side of the tty passed by the user if a pty else the tty
+ *     @p: returned pid
+ *
+ *     Obtain the process group of the tty. If there is no process group
+ *     return an error.
+ *
+ *     Locking: none. Reference to current->signal->tty is safe.
+ */
+static int tiocgpgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
+{
+       struct pid *pid;
+       int ret;
+       /*
+        * (tty == real_tty) is a cheap way of
+        * testing if the tty is NOT a master pty.
+        */
+       if (tty == real_tty && current->signal->tty != real_tty)
+               return -ENOTTY;
+       pid = tty_get_pgrp(real_tty);
+       ret =  put_user(pid_vnr(pid), p);
+       put_pid(pid);
+       return ret;
+}
+
+/**
+ *     tiocspgrp               -       attempt to set process group
+ *     @tty: tty passed by user
+ *     @real_tty: tty side device matching tty passed by user
+ *     @p: pid pointer
+ *
+ *     Set the process group of the tty to the session passed. Only
+ *     permitted where the tty session is our session.
+ *
+ *     Locking: RCU, ctrl lock
+ */
+static int tiocspgrp(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
+{
+       struct pid *pgrp;
+       pid_t pgrp_nr;
+       int retval = tty_check_change(real_tty);
+
+       if (retval == -EIO)
+               return -ENOTTY;
+       if (retval)
+               return retval;
+       if (!current->signal->tty ||
+           (current->signal->tty != real_tty) ||
+           (real_tty->session != task_session(current)))
+               return -ENOTTY;
+       if (get_user(pgrp_nr, p))
+               return -EFAULT;
+       if (pgrp_nr < 0)
+               return -EINVAL;
+       rcu_read_lock();
+       pgrp = find_vpid(pgrp_nr);
+       retval = -ESRCH;
+       if (!pgrp)
+               goto out_unlock;
+       retval = -EPERM;
+       if (session_of_pgrp(pgrp) != task_session(current))
+               goto out_unlock;
+       retval = 0;
+       spin_lock_irq(&tty->ctrl_lock);
+       put_pid(real_tty->pgrp);
+       real_tty->pgrp = get_pid(pgrp);
+       spin_unlock_irq(&tty->ctrl_lock);
+out_unlock:
+       rcu_read_unlock();
+       return retval;
+}
+
+/**
+ *     tiocgsid                -       get session id
+ *     @tty: tty passed by user
+ *     @real_tty: tty side of the tty passed by the user if a pty else the tty
+ *     @p: pointer to returned session id
+ *
+ *     Obtain the session id of the tty. If there is no session
+ *     return an error.
+ *
+ *     Locking: none. Reference to current->signal->tty is safe.
+ */
+static int tiocgsid(struct tty_struct *tty, struct tty_struct *real_tty, pid_t __user *p)
+{
+       /*
+        * (tty == real_tty) is a cheap way of
+        * testing if the tty is NOT a master pty.
+       */
+       if (tty == real_tty && current->signal->tty != real_tty)
+               return -ENOTTY;
+       if (!real_tty->session)
+               return -ENOTTY;
+       return put_user(pid_vnr(real_tty->session), p);
+}
+
+/*
+ * Called from tty_ioctl(). If tty is a pty then real_tty is the slave side,
+ * if not then tty == real_tty.
+ */
+long tty_jobctrl_ioctl(struct tty_struct *tty, struct tty_struct *real_tty,
+                      struct file *file, unsigned int cmd, unsigned long arg)
+{
+       void __user *p = (void __user *)arg;
+
+       switch (cmd) {
+       case TIOCNOTTY:
+               if (current->signal->tty != tty)
+                       return -ENOTTY;
+               no_tty();
+               return 0;
+       case TIOCSCTTY:
+               return tiocsctty(real_tty, file, arg);
+       case TIOCGPGRP:
+               return tiocgpgrp(tty, real_tty, p);
+       case TIOCSPGRP:
+               return tiocspgrp(tty, real_tty, p);
+       case TIOCGSID:
+               return tiocgsid(tty, real_tty, p);
+       }
+       return -ENOIOCTLCMD;
+}
index 36e1b8c7680f1d8fc5a64ba16e2fc52a0a379b40..accbd1257bc4a36938918965592e4a1e470098a6 100644 (file)
@@ -80,21 +80,17 @@ void clear_selection(void)
 
 /*
  * User settable table: what characters are to be considered alphabetic?
- * 256 bits. Locked by the console lock.
+ * 128 bits. Locked by the console lock.
  */
-static u32 inwordLut[8]={
+static u32 inwordLut[]={
   0x00000000, /* control chars     */
-  0x03FF0000, /* digits            */
+  0x03FFE000, /* digits and "-./"  */
   0x87FFFFFE, /* uppercase and '_' */
   0x07FFFFFE, /* lowercase         */
-  0x00000000,
-  0x00000000,
-  0xFF7FFFFF, /* latin-1 accented letters, not multiplication sign */
-  0xFF7FFFFF  /* latin-1 accented letters, not division sign */
 };
 
 static inline int inword(const u16 c) {
-       return c > 0xff || (( inwordLut[c>>5] >> (c & 0x1F) ) & 1);
+       return c > 0x7f || (( inwordLut[c>>5] >> (c & 0x1F) ) & 1);
 }
 
 /**
@@ -106,10 +102,10 @@ static inline int inword(const u16 c) {
  */
 int sel_loadlut(char __user *p)
 {
-       u32 tmplut[8];
-       if (copy_from_user(tmplut, (u32 __user *)(p+4), 32))
+       u32 tmplut[ARRAY_SIZE(inwordLut)];
+       if (copy_from_user(tmplut, (u32 __user *)(p+4), sizeof(inwordLut)))
                return -EFAULT;
-       memcpy(inwordLut, tmplut, 32);
+       memcpy(inwordLut, tmplut, sizeof(inwordLut));
        return 0;
 }
 
index 5c4933bb4b5336258f3d31f22971a1aea87c0dd9..9c9945284bcf240d319b98f986c2573b4d16e307 100644 (file)
@@ -181,7 +181,7 @@ int console_blanked;
 
 static int vesa_blank_mode; /* 0:none 1:suspendV 2:suspendH 3:powerdown */
 static int vesa_off_interval;
-static int blankinterval = 10*60;
+static int blankinterval;
 core_param(consoleblank, blankinterval, int, 0444);
 
 static DECLARE_WORK(console_work, console_callback);
index 9b519897cc17b8f31236bd51bfa283fbf5ada319..f61f852d6cfd114978036208bf2b0a5c841231d4 100644 (file)
@@ -817,12 +817,9 @@ static int vhost_net_open(struct inode *inode, struct file *f)
        struct vhost_virtqueue **vqs;
        int i;
 
-       n = kmalloc(sizeof *n, GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
-       if (!n) {
-               n = vmalloc(sizeof *n);
-               if (!n)
-                       return -ENOMEM;
-       }
+       n = kvmalloc(sizeof *n, GFP_KERNEL | __GFP_REPEAT);
+       if (!n)
+               return -ENOMEM;
        vqs = kmalloc(VHOST_NET_VQ_MAX * sizeof(*vqs), GFP_KERNEL);
        if (!vqs) {
                kvfree(n);
index f0ba362d4c101aa970a12943d1e69944d54058b7..042030e5a0357ad698181f817e6a75ca7c3087e3 100644 (file)
@@ -534,18 +534,9 @@ err_mm:
 }
 EXPORT_SYMBOL_GPL(vhost_dev_set_owner);
 
-static void *vhost_kvzalloc(unsigned long size)
-{
-       void *n = kzalloc(size, GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
-
-       if (!n)
-               n = vzalloc(size);
-       return n;
-}
-
 struct vhost_umem *vhost_dev_reset_owner_prepare(void)
 {
-       return vhost_kvzalloc(sizeof(struct vhost_umem));
+       return kvzalloc(sizeof(struct vhost_umem), GFP_KERNEL);
 }
 EXPORT_SYMBOL_GPL(vhost_dev_reset_owner_prepare);
 
@@ -1276,7 +1267,7 @@ EXPORT_SYMBOL_GPL(vhost_vq_access_ok);
 
 static struct vhost_umem *vhost_umem_alloc(void)
 {
-       struct vhost_umem *umem = vhost_kvzalloc(sizeof(*umem));
+       struct vhost_umem *umem = kvzalloc(sizeof(*umem), GFP_KERNEL);
 
        if (!umem)
                return NULL;
@@ -1302,7 +1293,7 @@ static long vhost_set_memory(struct vhost_dev *d, struct vhost_memory __user *m)
                return -EOPNOTSUPP;
        if (mem.nregions > max_mem_regions)
                return -E2BIG;
-       newmem = vhost_kvzalloc(size + mem.nregions * sizeof(*m->regions));
+       newmem = kvzalloc(size + mem.nregions * sizeof(*m->regions), GFP_KERNEL);
        if (!newmem)
                return -ENOMEM;
 
index d939ac1a499747ed80dd060a5a2984686375359e..3acef3c5d8edeca06d09e4b5d7e4ddeed0c8936c 100644 (file)
@@ -508,12 +508,9 @@ static int vhost_vsock_dev_open(struct inode *inode, struct file *file)
        /* This struct is large and allocation could fail, fall back to vmalloc
         * if there is no other way.
         */
-       vsock = kzalloc(sizeof(*vsock), GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
-       if (!vsock) {
-               vsock = vmalloc(sizeof(*vsock));
-               if (!vsock)
-                       return -ENOMEM;
-       }
+       vsock = kvmalloc(sizeof(*vsock), GFP_KERNEL | __GFP_REPEAT);
+       if (!vsock)
+               return -ENOMEM;
 
        vqs = kmalloc_array(ARRAY_SIZE(vsock->vqs), sizeof(*vqs), GFP_KERNEL);
        if (!vqs) {
index 9ad3c17d645689b79e56364377a71671eb4aac23..445b2c230b56ade5695c9e074ed9548b1a77caff 100644 (file)
@@ -2,6 +2,7 @@ obj-$(CONFIG_VGASTATE)            += vgastate.o
 obj-$(CONFIG_HDMI)                += hdmi.o
 
 obj-$(CONFIG_VT)                 += console/
+obj-$(CONFIG_FB_STI)             += console/
 obj-$(CONFIG_LOGO)               += logo/
 obj-y                            += backlight/
 
index 5b71bd905a6066ee53e3615d82b2d889a031d10c..2111d06f8c81a5260235befb029d59901e7bde28 100644 (file)
@@ -6,7 +6,7 @@ menu "Console display driver support"
 
 config VGA_CONSOLE
        bool "VGA text console" if EXPERT || !X86
-       depends on !4xx && !8xx && !SPARC && !M68K && !PARISC && !FRV && \
+       depends on !4xx && !PPC_8xx && !SPARC && !M68K && !PARISC && !FRV && \
                !SUPERH && !BLACKFIN && !AVR32 && !MN10300 && !CRIS && \
                (!ARM || ARCH_FOOTBRIDGE || ARCH_INTEGRATOR || ARCH_NETWINDER) && \
                !ARM64 && !ARC && !MICROBLAZE && !OPENRISC
index 922e4eaed9c5b5278572a79eb1cfc14e267a8bd5..5c6696bb56da89d1ca86f00f16c3c408303ca5ad 100644 (file)
@@ -689,8 +689,6 @@ config FB_STI
        select FB_CFB_FILLRECT
        select FB_CFB_COPYAREA
        select FB_CFB_IMAGEBLIT
-       select STI_CONSOLE
-       select VT
        default y
        ---help---
          STI refers to the HP "Standard Text Interface" which is a set of
index fb75b7e5a19ab52748e4a1980d56046e15716908..0c325b4da61de876d998463389ef040373be8645 100644 (file)
@@ -101,7 +101,7 @@ extern unsigned int vram_size;      /* set by setup.c */
 #ifdef HAS_VIDC20
 #include <mach/acornfb.h>
 
-#define MAX_SIZE       2*1024*1024
+#define MAX_SIZE       (2*1024*1024)
 
 /* VIDC20 has a different set of rules from the VIDC:
  *  hcr  : must be multiple of 4
@@ -162,7 +162,7 @@ static void acornfb_set_timing(struct fb_info *info)
        if (memcmp(&current_vidc, &vidc, sizeof(vidc))) {
                current_vidc = vidc;
 
-               vidc_writel(VIDC20_CTRL| vidc.control);
+               vidc_writel(VIDC20_CTRL | vidc.control);
                vidc_writel(0xd0000000 | vidc.pll_ctl);
                vidc_writel(0x80000000 | vidc.h_cycle);
                vidc_writel(0x81000000 | vidc.h_sync_width);
@@ -297,7 +297,7 @@ acornfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue,
                pal.p = 0;
                vidc_writel(0x10000000);
                for (i = 0; i < 256; i += 1) {
-                       pal.vidc20.red   = current_par.palette[ i       & 31].vidc20.red;
+                       pal.vidc20.red   = current_par.palette[i       & 31].vidc20.red;
                        pal.vidc20.green = current_par.palette[(i >> 1) & 31].vidc20.green;
                        pal.vidc20.blue  = current_par.palette[(i >> 2) & 31].vidc20.blue;
                        vidc_writel(pal.p);
@@ -1043,8 +1043,7 @@ static int acornfb_probe(struct platform_device *dev)
                base = dma_alloc_wc(current_par.dev, size, &handle,
                                    GFP_KERNEL);
                if (base == NULL) {
-                       printk(KERN_ERR "acornfb: unable to allocate screen "
-                              "memory\n");
+                       printk(KERN_ERR "acornfb: unable to allocate screen memory\n");
                        return -ENOMEM;
                }
 
@@ -1103,8 +1102,7 @@ static int acornfb_probe(struct platform_device *dev)
        v_sync = h_sync / (fb_info.var.yres + fb_info.var.upper_margin +
                 fb_info.var.lower_margin + fb_info.var.vsync_len);
 
-       printk(KERN_INFO "Acornfb: %dkB %cRAM, %s, using %dx%d, "
-               "%d.%03dkHz, %dHz\n",
+       printk(KERN_INFO "Acornfb: %dkB %cRAM, %s, using %dx%d, %d.%03dkHz, %dHz\n",
                fb_info.fix.smem_len / 1024,
                current_par.using_vram ? 'V' : 'D',
                VIDC_NAME, fb_info.var.xres, fb_info.var.yres,
index 0fab92c628280359ec79023b545ff893c12a2d6c..ffc2c33c6cef520a9aec6473b1b5fd1af96039fd 100644 (file)
@@ -881,8 +881,8 @@ static int clcdfb_of_dma_setup(struct clcd_fb *fb)
        if (err)
                return err;
 
-       framesize = fb->panel->mode.xres * fb->panel->mode.yres *
-                       fb->panel->bpp / 8;
+       framesize = PAGE_ALIGN(fb->panel->mode.xres * fb->panel->mode.yres *
+                       fb->panel->bpp / 8);
        fb->fb.screen_base = dma_alloc_coherent(&fb->dev->dev, framesize,
                        &dma, GFP_KERNEL);
        if (!fb->fb.screen_base)
index 1928cb2b5386fad37b55f1e6995cfaef88b979e2..7e87d0d616581dbf2e58045b424198524d28b3f4 100644 (file)
@@ -645,17 +645,17 @@ module_param(nosplash, uint, 0);
 MODULE_PARM_DESC(nosplash, "Disable doing the splash screen");
 module_param(arcfb_enable, uint, 0);
 MODULE_PARM_DESC(arcfb_enable, "Enable communication with Arc board");
-module_param(dio_addr, ulong, 0);
+module_param_hw(dio_addr, ulong, ioport, 0);
 MODULE_PARM_DESC(dio_addr, "IO address for data, eg: 0x480");
-module_param(cio_addr, ulong, 0);
+module_param_hw(cio_addr, ulong, ioport, 0);
 MODULE_PARM_DESC(cio_addr, "IO address for control, eg: 0x400");
-module_param(c2io_addr, ulong, 0);
+module_param_hw(c2io_addr, ulong, ioport, 0);
 MODULE_PARM_DESC(c2io_addr, "IO address for secondary control, eg: 0x408");
 module_param(splashval, ulong, 0);
 MODULE_PARM_DESC(splashval, "Splash pattern: 0xFF is black, 0x00 is green");
 module_param(tuhold, ulong, 0);
 MODULE_PARM_DESC(tuhold, "Time to hold between strobing data to Arc board");
-module_param(irq, uint, 0);
+module_param_hw(irq, uint, irq, 0);
 MODULE_PARM_DESC(irq, "IRQ for the Arc board");
 
 module_init(arcfb_init);
index 218339a4edaac46e5b223d07f12f335b8966c66f..6b4c7872b37519f9fe6238d4fa505d76e14d4c92 100644 (file)
@@ -2453,8 +2453,8 @@ static int radeonfb_pci_register(struct pci_dev *pdev,
                err |= sysfs_create_bin_file(&rinfo->pdev->dev.kobj,
                                                &edid2_attr);
        if (err)
-               pr_warning("%s() Creating sysfs files failed, continuing\n",
-                          __func__);
+               pr_warn("%s() Creating sysfs files failed, continuing\n",
+                       __func__);
 
        /* save current mode regs before we switch into the new one
         * so we can restore this upon __exit
index 62c0cf79674fec39137fe39552288b26e23773e5..687ebb053438b343d63c77881aeebcdc0ad7f857 100644 (file)
@@ -1073,9 +1073,9 @@ void fb_edid_add_monspecs(unsigned char *edid, struct fb_monspecs *specs)
        for (i = specs->modedb_len + num; i < specs->modedb_len + num + svd_n; i++) {
                int idx = svd[i - specs->modedb_len - num];
                if (!idx || idx >= ARRAY_SIZE(cea_modes)) {
-                       pr_warning("Reserved SVD code %d\n", idx);
+                       pr_warn("Reserved SVD code %d\n", idx);
                } else if (!cea_modes[idx].xres) {
-                       pr_warning("Unimplemented SVD code %d\n", idx);
+                       pr_warn("Unimplemented SVD code %d\n", idx);
                } else {
                        memcpy(&m[i], cea_modes + idx, sizeof(m[i]));
                        pr_debug("Adding SVD #%d: %ux%u@%u\n", idx,
index 483ab2592d0c056e9920834303b722105e5eca16..2488baab7c89253b4606faf3b5ae3877939b9201 100644 (file)
@@ -81,7 +81,7 @@ static u32 voffset;
 static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor);
 static int i810fb_init_pci(struct pci_dev *dev,
                           const struct pci_device_id *entry);
-static void __exit i810fb_remove_pci(struct pci_dev *dev);
+static void i810fb_remove_pci(struct pci_dev *dev);
 static int i810fb_resume(struct pci_dev *dev);
 static int i810fb_suspend(struct pci_dev *dev, pm_message_t state);
 
@@ -128,7 +128,7 @@ static struct pci_driver i810fb_driver = {
        .name     =     "i810fb",
        .id_table =     i810fb_pci_tbl,
        .probe    =     i810fb_init_pci,
-       .remove   =     __exit_p(i810fb_remove_pci),
+       .remove   =     i810fb_remove_pci,
        .suspend  =     i810fb_suspend,
        .resume   =     i810fb_resume,
 };
@@ -2123,7 +2123,7 @@ static void i810fb_release_resource(struct fb_info *info,
 
 }
 
-static void __exit i810fb_remove_pci(struct pci_dev *dev)
+static void i810fb_remove_pci(struct pci_dev *dev)
 {
        struct fb_info *info = pci_get_drvdata(dev);
        struct i810fb_par *par = info->par;
index 1b0faadb30801921d74231b6fc788fac5b67d9cd..c166e0725be5dab13e9a685a93ea7ea9c23a3351 100644 (file)
 
 #define IMXFB_LSCR1_DEFAULT 0x00120300
 
+#define LCDC_LAUSCR    0x80
+#define LAUSCR_AUS_MODE        (1<<31)
+
 /* Used fb-mode. Can be set on kernel command line, therefore file-static. */
 static const char *fb_mode;
 
@@ -158,6 +161,7 @@ struct imxfb_info {
        dma_addr_t              dbar2;
 
        u_int                   pcr;
+       u_int                   lauscr;
        u_int                   pwmr;
        u_int                   lscr1;
        u_int                   dmacr;
@@ -422,6 +426,11 @@ static int imxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
        pcr |= imxfb_mode->pcr & ~(0x3f | (7 << 25));
 
        fbi->pcr = pcr;
+       /*
+        * The LCDC AUS Mode Control Register does not exist on imx1.
+        */
+       if (!is_imx1_fb(fbi) && imxfb_mode->aus_mode)
+               fbi->lauscr = LAUSCR_AUS_MODE;
 
        /*
         * Copy the RGB parameters for this display
@@ -638,6 +647,9 @@ static int imxfb_activate_var(struct fb_var_screeninfo *var, struct fb_info *inf
        if (fbi->dmacr)
                writel(fbi->dmacr, fbi->regs + LCDC_DMACR);
 
+       if (fbi->lauscr)
+               writel(fbi->lauscr, fbi->regs + LCDC_LAUSCR);
+
        return 0;
 }
 
@@ -734,6 +746,11 @@ static int imxfb_of_read_mode(struct device *dev, struct device_node *np,
        imxfb_mode->bpp = bpp;
        imxfb_mode->pcr = pcr;
 
+       /*
+        * fsl,aus-mode is optional
+        */
+       imxfb_mode->aus_mode = of_property_read_bool(np, "fsl,aus-mode");
+
        return 0;
 }
 
index ff2a5d2023e1f88078c90b56746303783cbd7429..6b444400a86c2252c7f0c165869113f8393ca1a3 100644 (file)
@@ -934,7 +934,7 @@ static __inline__ int var_to_refresh(const struct fb_var_screeninfo *var)
 }
 
 /***************************************************************
- *                Various intialisation functions              *
+ *                Various initialisation functions             *
  ***************************************************************/
 
 static void get_initial_mode(struct intelfb_info *dinfo)
index 053deacad7cc12d3415e7e5d3b6c0b55e91e22ea..a3677313396e21fa78c266ff5df7a972ccc360a1 100644 (file)
@@ -193,11 +193,11 @@ module_exit(n411_exit);
 
 module_param(nosplash, uint, 0);
 MODULE_PARM_DESC(nosplash, "Disable doing the splash screen");
-module_param(dio_addr, ulong, 0);
+module_param_hw(dio_addr, ulong, ioport, 0);
 MODULE_PARM_DESC(dio_addr, "IO address for data, eg: 0x480");
-module_param(cio_addr, ulong, 0);
+module_param_hw(cio_addr, ulong, ioport, 0);
 MODULE_PARM_DESC(cio_addr, "IO address for control, eg: 0x400");
-module_param(c2io_addr, ulong, 0);
+module_param_hw(c2io_addr, ulong, ioport, 0);
 MODULE_PARM_DESC(c2io_addr, "IO address for secondary control, eg: 0x408");
 module_param(splashval, ulong, 0);
 MODULE_PARM_DESC(splashval, "Splash pattern: 0x00 is black, 0x01 is white");
index c81f150589e1f8a2c4a9c342d305ef2684f121cb..df9e6ebcfad5f8d37048e3db8901406e96177c1a 100644 (file)
@@ -174,7 +174,7 @@ static void hw_guard_wait(struct mipid_device *md)
 {
        unsigned long wait = md->hw_guard_end - jiffies;
 
-       if ((long)wait > 0 && wait <= md->hw_guard_wait) {
+       if ((long)wait > 0 && time_before_eq(wait,  md->hw_guard_wait)) {
                set_current_state(TASK_UNINTERRUPTIBLE);
                schedule_timeout(wait);
        }
index 47d7f69ad9ad858a75595922f032341d319f442d..48c6500c24e1f4b05a93d4a274c4a366cb8c0d6f 100644 (file)
@@ -941,11 +941,13 @@ static int dss_init_features(struct platform_device *pdev)
        return 0;
 }
 
+static void dss_uninit_ports(struct platform_device *pdev);
+
 static int dss_init_ports(struct platform_device *pdev)
 {
        struct device_node *parent = pdev->dev.of_node;
        struct device_node *port;
-       int r;
+       int r, ret = 0;
 
        if (parent == NULL)
                return 0;
@@ -972,17 +974,21 @@ static int dss_init_ports(struct platform_device *pdev)
 
                switch (port_type) {
                case OMAP_DISPLAY_TYPE_DPI:
-                       dpi_init_port(pdev, port);
+                       ret = dpi_init_port(pdev, port);
                        break;
                case OMAP_DISPLAY_TYPE_SDI:
-                       sdi_init_port(pdev, port);
+                       ret = sdi_init_port(pdev, port);
                        break;
                default:
                        break;
                }
-       } while ((port = omapdss_of_get_next_port(parent, port)) != NULL);
+       } while (!ret &&
+                (port = omapdss_of_get_next_port(parent, port)) != NULL);
 
-       return 0;
+       if (ret)
+               dss_uninit_ports(pdev);
+
+       return ret;
 }
 
 static void dss_uninit_ports(struct platform_device *pdev)
index ffe2dd482f840b51e83d3180bc327c1aefdc029e..39922f072db4f89ed5212a8e509cb2e2ca86c2d8 100644 (file)
@@ -247,7 +247,7 @@ err_alloc:
        return err;
 }
 
-static int __exit pmagaafb_remove(struct device *dev)
+static int pmagaafb_remove(struct device *dev)
 {
        struct tc_dev *tdev = to_tc_dev(dev);
        struct fb_info *info = dev_get_drvdata(dev);
@@ -280,7 +280,7 @@ static struct tc_driver pmagaafb_driver = {
                .name   = "pmagaafb",
                .bus    = &tc_bus_type,
                .probe  = pmagaafb_probe,
-               .remove = __exit_p(pmagaafb_remove),
+               .remove = pmagaafb_remove,
        },
 };
 
index df02fb4b7fd1c2fe6363ef5173ed516479811da1..1fd02f40708eb79740db54a292ca87e8e24cab9c 100644 (file)
@@ -235,7 +235,7 @@ err_alloc:
        return err;
 }
 
-static int __exit pmagbafb_remove(struct device *dev)
+static int pmagbafb_remove(struct device *dev)
 {
        struct tc_dev *tdev = to_tc_dev(dev);
        struct fb_info *info = dev_get_drvdata(dev);
@@ -270,7 +270,7 @@ static struct tc_driver pmagbafb_driver = {
                .name   = "pmagbafb",
                .bus    = &tc_bus_type,
                .probe  = pmagbafb_probe,
-               .remove = __exit_p(pmagbafb_remove),
+               .remove = pmagbafb_remove,
        },
 };
 
index a7a179a0bb33f2d85beb0301945375dad45e8f79..46e96c4515060f0c58ade6ff892f711ad39aa0a6 100644 (file)
@@ -353,7 +353,7 @@ err_alloc:
        return err;
 }
 
-static int __exit pmagbbfb_remove(struct device *dev)
+static int pmagbbfb_remove(struct device *dev)
 {
        struct tc_dev *tdev = to_tc_dev(dev);
        struct fb_info *info = dev_get_drvdata(dev);
@@ -388,7 +388,7 @@ static struct tc_driver pmagbbfb_driver = {
                .name   = "pmagbbfb",
                .bus    = &tc_bus_type,
                .probe  = pmagbbfb_probe,
-               .remove = __exit_p(pmagbbfb_remove),
+               .remove = pmagbbfb_remove,
        },
 };
 
index ef73f14d7ba00d4b185739d65006cb50ebea7580..b21a89b03fb474a4a1c5b8821ad8861cd55b7e35 100644 (file)
@@ -645,7 +645,7 @@ static void overlay1fb_disable(struct pxafb_layer *ofb)
        lcd_writel(ofb->fbi, FBR1, ofb->fbi->fdadr[DMA_OV1] | 0x3);
 
        if (wait_for_completion_timeout(&ofb->branch_done, 1 * HZ) == 0)
-               pr_warning("%s: timeout disabling overlay1\n", __func__);
+               pr_warn("%s: timeout disabling overlay1\n", __func__);
 
        lcd_writel(ofb->fbi, LCCR5, lccr5);
 }
@@ -710,7 +710,7 @@ static void overlay2fb_disable(struct pxafb_layer *ofb)
        lcd_writel(ofb->fbi, FBR4, ofb->fbi->fdadr[DMA_OV2_Cr] | 0x3);
 
        if (wait_for_completion_timeout(&ofb->branch_done, 1 * HZ) == 0)
-               pr_warning("%s: timeout disabling overlay2\n", __func__);
+               pr_warn("%s: timeout disabling overlay2\n", __func__);
 }
 
 static struct pxafb_layer_ops ofb_ops[] = {
@@ -1187,8 +1187,7 @@ int pxafb_smart_flush(struct fb_info *info)
        lcd_writel(fbi, LCCR0, fbi->reg_lccr0 | LCCR0_ENB);
 
        if (wait_for_completion_timeout(&fbi->command_done, HZ/2) == 0) {
-               pr_warning("%s: timeout waiting for command done\n",
-                               __func__);
+               pr_warn("%s: timeout waiting for command done\n", __func__);
                ret = -ETIMEDOUT;
        }
 
index d80bc8a3200fa9c8435bc0b606a4bae0f02728f1..67e314fdd9471513b911d07d33c0ff3c13e25a05 100644 (file)
@@ -1600,6 +1600,7 @@ static int sm501fb_start(struct sm501fb_info *info,
        info->fbmem = ioremap(res->start, resource_size(res));
        if (info->fbmem == NULL) {
                dev_err(dev, "cannot remap framebuffer\n");
+               ret = -ENXIO;
                goto err_mem_res;
        }
 
index e9c2f7ba3c8e6c34382b6b0b58a7d65e41e8292d..6a3c353de7c35468e68f271126dca1c0b447ae82 100644 (file)
@@ -1487,15 +1487,25 @@ static struct device_attribute fb_device_attrs[] = {
 static int dlfb_select_std_channel(struct dlfb_data *dev)
 {
        int ret;
-       u8 set_def_chn[] = {       0x57, 0xCD, 0xDC, 0xA7,
+       void *buf;
+       static const u8 set_def_chn[] = {
+                               0x57, 0xCD, 0xDC, 0xA7,
                                0x1C, 0x88, 0x5E, 0x15,
                                0x60, 0xFE, 0xC6, 0x97,
                                0x16, 0x3D, 0x47, 0xF2  };
 
+       buf = kmemdup(set_def_chn, sizeof(set_def_chn), GFP_KERNEL);
+
+       if (!buf)
+               return -ENOMEM;
+
        ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
                        NR_USB_REQUEST_CHANNEL,
                        (USB_DIR_OUT | USB_TYPE_VENDOR), 0, 0,
-                       set_def_chn, sizeof(set_def_chn), USB_CTRL_SET_TIMEOUT);
+                       buf, sizeof(set_def_chn), USB_CTRL_SET_TIMEOUT);
+
+       kfree(buf);
+
        return ret;
 }
 
index 1c1e95a0b8faa04006c857158c79ac11bc904d96..ce4c4729a5e8c30ea1222b584e159b4a45c24b48 100644 (file)
@@ -37,7 +37,7 @@
 #include <linux/mm.h>
 #include <linux/fb.h>
 #include <linux/pci.h>
-#include <asm/cacheflush.h>
+#include <asm/set_memory.h>
 #include <asm/tlbflush.h>
 #include <linux/mmzone.h>
 
index 3ee309c50b2d015fb3d463dd88f6b99253beea12..46f63960fa9e6aa2913be8b804c1de24ce1245be 100644 (file)
@@ -18,6 +18,8 @@
  * frame buffer.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/console.h>
 #include <linux/kernel.h>
 #include <linux/errno.h>
@@ -380,10 +382,18 @@ static int xenfb_probe(struct xenbus_device *dev,
                        video[KPARAM_MEM] = val;
        }
 
+       video[KPARAM_WIDTH] = xenbus_read_unsigned(dev->otherend, "width",
+                                                  video[KPARAM_WIDTH]);
+       video[KPARAM_HEIGHT] = xenbus_read_unsigned(dev->otherend, "height",
+                                                   video[KPARAM_HEIGHT]);
+
        /* If requested res does not fit in available memory, use default */
        fb_size = video[KPARAM_MEM] * 1024 * 1024;
        if (video[KPARAM_WIDTH] * video[KPARAM_HEIGHT] * XENFB_DEPTH / 8
            > fb_size) {
+               pr_warn("display parameters %d,%d,%d invalid, use defaults\n",
+                       video[KPARAM_MEM], video[KPARAM_WIDTH],
+                       video[KPARAM_HEIGHT]);
                video[KPARAM_WIDTH] = XENFB_WIDTH;
                video[KPARAM_HEIGHT] = XENFB_HEIGHT;
                fb_size = XENFB_DEFAULT_FB_LEN;
index b6bc4a0bda2a120a30cdb6a18f66fff9d7de0862..4d50bfd13e7c9f58f9f8f472627d6b7051e1e922 100644 (file)
@@ -34,7 +34,7 @@ static int __init fb_logo_late_init(void)
        return 0;
 }
 
-late_initcall(fb_logo_late_init);
+late_initcall_sync(fb_logo_late_init);
 
 /* logo's are marked __initdata. Use __ref to tell
  * modpost that it is intended that this function uses data
index 150ce2abf6c8f193b4e3b5c9fa66001cd709f39e..d3eca879a0a85474f858e79b759d8b4920ba9709 100644 (file)
@@ -243,11 +243,8 @@ static long ioctl_memcpy(struct fsl_hv_ioctl_memcpy __user *p)
        sg_list = PTR_ALIGN(sg_list_unaligned, sizeof(struct fh_sg_list));
 
        /* Get the physical addresses of the source buffer */
-       down_read(&current->mm->mmap_sem);
-       num_pinned = get_user_pages(param.local_vaddr - lb_offset,
-               num_pages, (param.source == -1) ? 0 : FOLL_WRITE,
-               pages, NULL);
-       up_read(&current->mm->mmap_sem);
+       num_pinned = get_user_pages_unlocked(param.local_vaddr - lb_offset,
+               num_pages, pages, (param.source == -1) ? 0 : FOLL_WRITE);
 
        if (num_pinned != num_pages) {
                /* get_user_pages() failed */
index 34adf9b9c0538815db33f62ed842de49be5222e7..408c174ef0d5c076dc2f51da612b8e0f3dfa8269 100644 (file)
@@ -418,8 +418,7 @@ static int init_vqs(struct virtio_balloon *vb)
         * optionally stat.
         */
        nvqs = virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_STATS_VQ) ? 3 : 2;
-       err = vb->vdev->config->find_vqs(vb->vdev, nvqs, vqs, callbacks, names,
-                       NULL);
+       err = virtio_find_vqs(vb->vdev, nvqs, vqs, callbacks, names, NULL);
        if (err)
                return err;
 
index 79f1293cda9327a051feef083871bdbc62038496..3a0468f2ceb08a3c4cd3eac033477b8049ebd89d 100644 (file)
@@ -173,8 +173,7 @@ static int virtinput_init_vqs(struct virtio_input *vi)
        static const char * const names[] = { "events", "status" };
        int err;
 
-       err = vi->vdev->config->find_vqs(vi->vdev, 2, vqs, cbs, names,
-                       NULL);
+       err = virtio_find_vqs(vi->vdev, 2, vqs, cbs, names, NULL);
        if (err)
                return err;
        vi->evt = vqs[0];
index 78343b8f9034b35ea7d18e6f8a5b3e3df4bae9e0..74dc7170fd351e02d1732357b0705f66c507f7ce 100644 (file)
@@ -351,7 +351,7 @@ static void vm_del_vqs(struct virtio_device *vdev)
 
 static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index,
                                  void (*callback)(struct virtqueue *vq),
-                                 const char *name)
+                                 const char *name, bool ctx)
 {
        struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
        struct virtio_mmio_vq_info *info;
@@ -388,7 +388,7 @@ static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index,
 
        /* Create the vring */
        vq = vring_create_virtqueue(index, num, VIRTIO_MMIO_VRING_ALIGN, vdev,
-                                true, true, vm_notify, callback, name);
+                                true, true, ctx, vm_notify, callback, name);
        if (!vq) {
                err = -ENOMEM;
                goto error_new_virtqueue;
@@ -447,6 +447,7 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs,
                       struct virtqueue *vqs[],
                       vq_callback_t *callbacks[],
                       const char * const names[],
+                      const bool *ctx,
                       struct irq_affinity *desc)
 {
        struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
@@ -459,7 +460,8 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs,
                return err;
 
        for (i = 0; i < nvqs; ++i) {
-               vqs[i] = vm_setup_vq(vdev, i, callbacks[i], names[i]);
+               vqs[i] = vm_setup_vq(vdev, i, callbacks[i], names[i],
+                                    ctx ? ctx[i] : false);
                if (IS_ERR(vqs[i])) {
                        vm_del_vqs(vdev);
                        return PTR_ERR(vqs[i]);
index 698d5d06fa039ca1a27b151a3dcf5d322784e3f0..007a4f3660862e1aa6e9a16207ae54bbbab61d58 100644 (file)
@@ -172,6 +172,7 @@ error:
 static struct virtqueue *vp_setup_vq(struct virtio_device *vdev, unsigned index,
                                     void (*callback)(struct virtqueue *vq),
                                     const char *name,
+                                    bool ctx,
                                     u16 msix_vec)
 {
        struct virtio_pci_device *vp_dev = to_vp_device(vdev);
@@ -183,7 +184,7 @@ static struct virtqueue *vp_setup_vq(struct virtio_device *vdev, unsigned index,
        if (!info)
                return ERR_PTR(-ENOMEM);
 
-       vq = vp_dev->setup_vq(vp_dev, info, index, callback, name,
+       vq = vp_dev->setup_vq(vp_dev, info, index, callback, name, ctx,
                              msix_vec);
        if (IS_ERR(vq))
                goto out_info;
@@ -274,6 +275,7 @@ void vp_del_vqs(struct virtio_device *vdev)
 static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs,
                struct virtqueue *vqs[], vq_callback_t *callbacks[],
                const char * const names[], bool per_vq_vectors,
+               const bool *ctx,
                struct irq_affinity *desc)
 {
        struct virtio_pci_device *vp_dev = to_vp_device(vdev);
@@ -315,6 +317,7 @@ static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs,
                else
                        msix_vec = VP_MSIX_VQ_VECTOR;
                vqs[i] = vp_setup_vq(vdev, i, callbacks[i], names[i],
+                                    ctx ? ctx[i] : false,
                                     msix_vec);
                if (IS_ERR(vqs[i])) {
                        err = PTR_ERR(vqs[i]);
@@ -345,7 +348,7 @@ error_find:
 
 static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs,
                struct virtqueue *vqs[], vq_callback_t *callbacks[],
-               const char * const names[])
+               const char * const names[], const bool *ctx)
 {
        struct virtio_pci_device *vp_dev = to_vp_device(vdev);
        int i, err;
@@ -367,6 +370,7 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs,
                        continue;
                }
                vqs[i] = vp_setup_vq(vdev, i, callbacks[i], names[i],
+                                    ctx ? ctx[i] : false,
                                     VIRTIO_MSI_NO_VECTOR);
                if (IS_ERR(vqs[i])) {
                        err = PTR_ERR(vqs[i]);
@@ -383,20 +387,21 @@ out_del_vqs:
 /* the config->find_vqs() implementation */
 int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
                struct virtqueue *vqs[], vq_callback_t *callbacks[],
-               const char * const names[], struct irq_affinity *desc)
+               const char * const names[], const bool *ctx,
+               struct irq_affinity *desc)
 {
        int err;
 
        /* Try MSI-X with one vector per queue. */
-       err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, true, desc);
+       err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, true, ctx, desc);
        if (!err)
                return 0;
        /* Fallback: MSI-X with one vector for config, one shared for queues. */
-       err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, false, desc);
+       err = vp_find_vqs_msix(vdev, nvqs, vqs, callbacks, names, false, ctx, desc);
        if (!err)
                return 0;
        /* Finally fall back to regular interrupts. */
-       return vp_find_vqs_intx(vdev, nvqs, vqs, callbacks, names);
+       return vp_find_vqs_intx(vdev, nvqs, vqs, callbacks, names, ctx);
 }
 
 const char *vp_bus_name(struct virtio_device *vdev)
index e96334aec1e0d70842d1a9fc53462ab728be87c0..135ee3cf7175881a8259a192ba102978196687c7 100644 (file)
@@ -102,6 +102,7 @@ struct virtio_pci_device {
                                      unsigned idx,
                                      void (*callback)(struct virtqueue *vq),
                                      const char *name,
+                                     bool ctx,
                                      u16 msix_vec);
        void (*del_vq)(struct virtio_pci_vq_info *info);
 
@@ -131,7 +132,8 @@ void vp_del_vqs(struct virtio_device *vdev);
 /* the config->find_vqs() implementation */
 int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs,
                struct virtqueue *vqs[], vq_callback_t *callbacks[],
-               const char * const names[], struct irq_affinity *desc);
+               const char * const names[], const bool *ctx,
+               struct irq_affinity *desc);
 const char *vp_bus_name(struct virtio_device *vdev);
 
 /* Setup the affinity for a virtqueue:
index 4bfa48fb1324660f82ae6272d2e1ecc33522ba3e..2780886e8ba3d393ba4847366983c2ab56a7ed3e 100644 (file)
@@ -116,6 +116,7 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
                                  unsigned index,
                                  void (*callback)(struct virtqueue *vq),
                                  const char *name,
+                                 bool ctx,
                                  u16 msix_vec)
 {
        struct virtqueue *vq;
@@ -135,7 +136,8 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
        /* create the vring */
        vq = vring_create_virtqueue(index, num,
                                    VIRTIO_PCI_VRING_ALIGN, &vp_dev->vdev,
-                                   true, false, vp_notify, callback, name);
+                                   true, false, ctx,
+                                   vp_notify, callback, name);
        if (!vq)
                return ERR_PTR(-ENOMEM);
 
index 8978f109d2d79828e5b0c12649debc481dfacd7f..2555d80f6eec4b4a78860b46f453092051b50a24 100644 (file)
@@ -297,6 +297,7 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
                                  unsigned index,
                                  void (*callback)(struct virtqueue *vq),
                                  const char *name,
+                                 bool ctx,
                                  u16 msix_vec)
 {
        struct virtio_pci_common_cfg __iomem *cfg = vp_dev->common;
@@ -328,7 +329,8 @@ static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev,
        /* create the vring */
        vq = vring_create_virtqueue(index, num,
                                    SMP_CACHE_BYTES, &vp_dev->vdev,
-                                   true, true, vp_notify, callback, name);
+                                   true, true, ctx,
+                                   vp_notify, callback, name);
        if (!vq)
                return ERR_PTR(-ENOMEM);
 
@@ -387,12 +389,14 @@ err_map_notify:
 }
 
 static int vp_modern_find_vqs(struct virtio_device *vdev, unsigned nvqs,
-               struct virtqueue *vqs[], vq_callback_t *callbacks[],
-               const char * const names[], struct irq_affinity *desc)
+                             struct virtqueue *vqs[],
+                             vq_callback_t *callbacks[],
+                             const char * const names[], const bool *ctx,
+                             struct irq_affinity *desc)
 {
        struct virtio_pci_device *vp_dev = to_vp_device(vdev);
        struct virtqueue *vq;
-       int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, desc);
+       int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names, ctx, desc);
 
        if (rc)
                return rc;
index 409aeaa49246a0edd7c6da07ca38b58c3f876109..5e1b548828e60745ba87581d2b9bcb6380b092f8 100644 (file)
@@ -263,6 +263,7 @@ static inline int virtqueue_add(struct virtqueue *_vq,
                                unsigned int out_sgs,
                                unsigned int in_sgs,
                                void *data,
+                               void *ctx,
                                gfp_t gfp)
 {
        struct vring_virtqueue *vq = to_vvq(_vq);
@@ -275,6 +276,7 @@ static inline int virtqueue_add(struct virtqueue *_vq,
        START_USE(vq);
 
        BUG_ON(data == NULL);
+       BUG_ON(ctx && vq->indirect);
 
        if (unlikely(vq->broken)) {
                END_USE(vq);
@@ -389,6 +391,8 @@ static inline int virtqueue_add(struct virtqueue *_vq,
        vq->desc_state[head].data = data;
        if (indirect)
                vq->desc_state[head].indir_desc = desc;
+       if (ctx)
+               vq->desc_state[head].indir_desc = ctx;
 
        /* Put entry in available array (but don't update avail->idx until they
         * do sync). */
@@ -461,7 +465,8 @@ int virtqueue_add_sgs(struct virtqueue *_vq,
                for (sg = sgs[i]; sg; sg = sg_next(sg))
                        total_sg++;
        }
-       return virtqueue_add(_vq, sgs, total_sg, out_sgs, in_sgs, data, gfp);
+       return virtqueue_add(_vq, sgs, total_sg, out_sgs, in_sgs,
+                            data, NULL, gfp);
 }
 EXPORT_SYMBOL_GPL(virtqueue_add_sgs);
 
@@ -483,7 +488,7 @@ int virtqueue_add_outbuf(struct virtqueue *vq,
                         void *data,
                         gfp_t gfp)
 {
-       return virtqueue_add(vq, &sg, num, 1, 0, data, gfp);
+       return virtqueue_add(vq, &sg, num, 1, 0, data, NULL, gfp);
 }
 EXPORT_SYMBOL_GPL(virtqueue_add_outbuf);
 
@@ -505,10 +510,34 @@ int virtqueue_add_inbuf(struct virtqueue *vq,
                        void *data,
                        gfp_t gfp)
 {
-       return virtqueue_add(vq, &sg, num, 0, 1, data, gfp);
+       return virtqueue_add(vq, &sg, num, 0, 1, data, NULL, gfp);
 }
 EXPORT_SYMBOL_GPL(virtqueue_add_inbuf);
 
+/**
+ * virtqueue_add_inbuf_ctx - expose input buffers to other end
+ * @vq: the struct virtqueue we're talking about.
+ * @sg: scatterlist (must be well-formed and terminated!)
+ * @num: the number of entries in @sg writable by other side
+ * @data: the token identifying the buffer.
+ * @ctx: extra context for the token
+ * @gfp: how to do memory allocations (if necessary).
+ *
+ * Caller must ensure we don't call this with other virtqueue operations
+ * at the same time (except where noted).
+ *
+ * Returns zero or a negative error (ie. ENOSPC, ENOMEM, EIO).
+ */
+int virtqueue_add_inbuf_ctx(struct virtqueue *vq,
+                       struct scatterlist *sg, unsigned int num,
+                       void *data,
+                       void *ctx,
+                       gfp_t gfp)
+{
+       return virtqueue_add(vq, &sg, num, 0, 1, data, ctx, gfp);
+}
+EXPORT_SYMBOL_GPL(virtqueue_add_inbuf_ctx);
+
 /**
  * virtqueue_kick_prepare - first half of split virtqueue_kick call.
  * @vq: the struct virtqueue
@@ -598,7 +627,8 @@ bool virtqueue_kick(struct virtqueue *vq)
 }
 EXPORT_SYMBOL_GPL(virtqueue_kick);
 
-static void detach_buf(struct vring_virtqueue *vq, unsigned int head)
+static void detach_buf(struct vring_virtqueue *vq, unsigned int head,
+                      void **ctx)
 {
        unsigned int i, j;
        __virtio16 nextflag = cpu_to_virtio16(vq->vq.vdev, VRING_DESC_F_NEXT);
@@ -622,10 +652,15 @@ static void detach_buf(struct vring_virtqueue *vq, unsigned int head)
        /* Plus final descriptor */
        vq->vq.num_free++;
 
-       /* Free the indirect table, if any, now that it's unmapped. */
-       if (vq->desc_state[head].indir_desc) {
+       if (vq->indirect) {
                struct vring_desc *indir_desc = vq->desc_state[head].indir_desc;
-               u32 len = virtio32_to_cpu(vq->vq.vdev, vq->vring.desc[head].len);
+               u32 len;
+
+               /* Free the indirect table, if any, now that it's unmapped. */
+               if (!indir_desc)
+                       return;
+
+               len = virtio32_to_cpu(vq->vq.vdev, vq->vring.desc[head].len);
 
                BUG_ON(!(vq->vring.desc[head].flags &
                         cpu_to_virtio16(vq->vq.vdev, VRING_DESC_F_INDIRECT)));
@@ -634,8 +669,10 @@ static void detach_buf(struct vring_virtqueue *vq, unsigned int head)
                for (j = 0; j < len / sizeof(struct vring_desc); j++)
                        vring_unmap_one(vq, &indir_desc[j]);
 
-               kfree(vq->desc_state[head].indir_desc);
+               kfree(indir_desc);
                vq->desc_state[head].indir_desc = NULL;
+       } else if (ctx) {
+               *ctx = vq->desc_state[head].indir_desc;
        }
 }
 
@@ -660,7 +697,8 @@ static inline bool more_used(const struct vring_virtqueue *vq)
  * Returns NULL if there are no used buffers, or the "data" token
  * handed to virtqueue_add_*().
  */
-void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int *len)
+void *virtqueue_get_buf_ctx(struct virtqueue *_vq, unsigned int *len,
+                           void **ctx)
 {
        struct vring_virtqueue *vq = to_vvq(_vq);
        void *ret;
@@ -698,7 +736,7 @@ void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int *len)
 
        /* detach_buf clears data, so grab it now. */
        ret = vq->desc_state[i].data;
-       detach_buf(vq, i);
+       detach_buf(vq, i, ctx);
        vq->last_used_idx++;
        /* If we expect an interrupt for the next entry, tell host
         * by writing event index and flush out the write before
@@ -715,8 +753,13 @@ void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int *len)
        END_USE(vq);
        return ret;
 }
-EXPORT_SYMBOL_GPL(virtqueue_get_buf);
+EXPORT_SYMBOL_GPL(virtqueue_get_buf_ctx);
 
+void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int *len)
+{
+       return virtqueue_get_buf_ctx(_vq, len, NULL);
+}
+EXPORT_SYMBOL_GPL(virtqueue_get_buf);
 /**
  * virtqueue_disable_cb - disable callbacks
  * @vq: the struct virtqueue we're talking about.
@@ -878,7 +921,7 @@ void *virtqueue_detach_unused_buf(struct virtqueue *_vq)
                        continue;
                /* detach_buf clears data, so grab it now. */
                buf = vq->desc_state[i].data;
-               detach_buf(vq, i);
+               detach_buf(vq, i, NULL);
                vq->avail_idx_shadow--;
                vq->vring.avail->idx = cpu_to_virtio16(_vq->vdev, vq->avail_idx_shadow);
                END_USE(vq);
@@ -916,6 +959,7 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index,
                                        struct vring vring,
                                        struct virtio_device *vdev,
                                        bool weak_barriers,
+                                       bool context,
                                        bool (*notify)(struct virtqueue *),
                                        void (*callback)(struct virtqueue *),
                                        const char *name)
@@ -950,7 +994,8 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index,
        vq->last_add_time_valid = false;
 #endif
 
-       vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC);
+       vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC) &&
+               !context;
        vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX);
 
        /* No callback?  Tell other side not to bother us. */
@@ -1019,6 +1064,7 @@ struct virtqueue *vring_create_virtqueue(
        struct virtio_device *vdev,
        bool weak_barriers,
        bool may_reduce_num,
+       bool context,
        bool (*notify)(struct virtqueue *),
        void (*callback)(struct virtqueue *),
        const char *name)
@@ -1058,7 +1104,7 @@ struct virtqueue *vring_create_virtqueue(
        queue_size_in_bytes = vring_size(num, vring_align);
        vring_init(&vring, num, queue, vring_align);
 
-       vq = __vring_new_virtqueue(index, vring, vdev, weak_barriers,
+       vq = __vring_new_virtqueue(index, vring, vdev, weak_barriers, context,
                                   notify, callback, name);
        if (!vq) {
                vring_free_queue(vdev, queue_size_in_bytes, queue,
@@ -1079,6 +1125,7 @@ struct virtqueue *vring_new_virtqueue(unsigned int index,
                                      unsigned int vring_align,
                                      struct virtio_device *vdev,
                                      bool weak_barriers,
+                                     bool context,
                                      void *pages,
                                      bool (*notify)(struct virtqueue *vq),
                                      void (*callback)(struct virtqueue *vq),
@@ -1086,7 +1133,7 @@ struct virtqueue *vring_new_virtqueue(unsigned int index,
 {
        struct vring vring;
        vring_init(&vring, num, pages, vring_align);
-       return __vring_new_virtqueue(index, vring, vdev, weak_barriers,
+       return __vring_new_virtqueue(index, vring, vdev, weak_barriers, context,
                                     notify, callback, name);
 }
 EXPORT_SYMBOL_GPL(vring_new_virtqueue);
index 6d03e8e30f8bf4369cfaa6cecde6cb2a6dccb03c..6c3f78e45c265da4b6f9cfefdb8af16a96b30874 100644 (file)
@@ -289,7 +289,7 @@ MODULE_DESCRIPTION("sma cpu5 watchdog driver");
 MODULE_SUPPORTED_DEVICE("sma cpu5 watchdog");
 MODULE_LICENSE("GPL");
 
-module_param(port, int, 0);
+module_param_hw(port, int, ioport, 0);
 MODULE_PARM_DESC(port, "base address of watchdog card, default is 0x91");
 
 module_param(verbose, int, 0);
index 23ee53240c4c1858f7d8aa0f7530d43dcc44f650..38e96712264f92648304ba8282a2e4ba8be90319 100644 (file)
@@ -97,9 +97,9 @@ MODULE_PARM_DESC(nowayout,
 #define WDT_TIMER_CFG          0xf3
 
 
-module_param(io, int, 0);
+module_param_hw(io, int, ioport, 0);
 MODULE_PARM_DESC(io, "Eurotech WDT io port (default=0x3f0)");
-module_param(irq, int, 0);
+module_param_hw(irq, int, irq, 0);
 MODULE_PARM_DESC(irq, "Eurotech WDT irq (default=10)");
 module_param(ev, charp, 0);
 MODULE_PARM_DESC(ev, "Eurotech WDT event type (default is `int')");
index 70c7194e2810dff05ddc0535dc5d8d7579ab7e77..67fbe35ce7cfe5438f18b0ffb4ebdbfdc057b8fe 100644 (file)
@@ -34,7 +34,7 @@
 #include <linux/nmi.h>
 #include <linux/kdebug.h>
 #include <linux/notifier.h>
-#include <asm/cacheflush.h>
+#include <asm/set_memory.h>
 #endif /* CONFIG_HPWDT_NMI_DECODING */
 #include <asm/nmi.h>
 #include <asm/frame.h>
index 9f15dd9435d1a4efe5dd69fbab25363be026fe46..06a892e36a8d889ab1c6936b3209d8cd61a2f8c1 100644 (file)
@@ -579,7 +579,7 @@ MODULE_AUTHOR("Marcus Junker <junker@anduras.de>");
 MODULE_DESCRIPTION("PC87413 WDT driver");
 MODULE_LICENSE("GPL");
 
-module_param(io, int, 0);
+module_param_hw(io, int, ioport, 0);
 MODULE_PARM_DESC(io, MODNAME " I/O port (default: "
                                        __MODULE_STRING(IO_DEFAULT) ").");
 
index 131193a7acdfd0bb07660095e0ff57c500eed6cb..b34d3d5ba632398e357261bd5e666b9e9efc2157 100644 (file)
@@ -88,7 +88,7 @@ MODULE_PARM_DESC(isapnp,
        "When set to 0 driver ISA PnP support will be disabled");
 #endif
 
-module_param(io, int, 0);
+module_param_hw(io, int, ioport, 0);
 MODULE_PARM_DESC(io, "io port");
 module_param(timeout, int, 0);
 MODULE_PARM_DESC(timeout, "range is 0-255 minutes, default is 1");
index e0206b5b7d8955526f9598a6cc012fcdfd090873..e481fbbc4ae706b601dd64e21adcb58a5483c1f0 100644 (file)
@@ -78,9 +78,9 @@ static int irq = 11;
 
 static DEFINE_SPINLOCK(wdt_lock);
 
-module_param(io, int, 0);
+module_param_hw(io, int, ioport, 0);
 MODULE_PARM_DESC(io, "WDT io port (default=0x240)");
-module_param(irq, int, 0);
+module_param_hw(irq, int, irq, 0);
 MODULE_PARM_DESC(irq, "WDT irq (default=11)");
 
 /* Support for the Fan Tachometer on the WDT501-P */
index 6890897a6f30edab0c0d87926942463f9b481aa9..10f1ef5826595ae53e927243bcdfa5f66c4121c6 100644 (file)
@@ -87,18 +87,6 @@ struct user_evtchn {
        bool enabled;
 };
 
-static evtchn_port_t *evtchn_alloc_ring(unsigned int size)
-{
-       evtchn_port_t *ring;
-       size_t s = size * sizeof(*ring);
-
-       ring = kmalloc(s, GFP_KERNEL);
-       if (!ring)
-               ring = vmalloc(s);
-
-       return ring;
-}
-
 static void evtchn_free_ring(evtchn_port_t *ring)
 {
        kvfree(ring);
@@ -334,7 +322,7 @@ static int evtchn_resize_ring(struct per_user_data *u)
        else
                new_size = 2 * u->ring_size;
 
-       new_ring = evtchn_alloc_ring(new_size);
+       new_ring = kvmalloc(new_size * sizeof(*new_ring), GFP_KERNEL);
        if (!new_ring)
                return -ENOMEM;
 
index 328c3987b112dcf84fe40005d936bfbfed601f91..967f069385d0cf1fa9933cdeb0f8804dc0324e06 100644 (file)
@@ -44,14 +44,14 @@ static const struct file_operations capabilities_file_ops = {
 
 static int xenfs_fill_super(struct super_block *sb, void *data, int silent)
 {
-       static struct tree_descr xenfs_files[] = {
+       static const struct tree_descr xenfs_files[] = {
                [2] = { "xenbus", &xen_xenbus_fops, S_IRUSR|S_IWUSR },
                { "capabilities", &capabilities_file_ops, S_IRUGO },
                { "privcmd", &xen_privcmd_fops, S_IRUSR|S_IWUSR },
                {""},
        };
 
-       static struct tree_descr xenfs_init_files[] = {
+       static const struct tree_descr xenfs_init_files[] = {
                [2] = { "xenbus", &xen_xenbus_fops, S_IRUSR|S_IWUSR },
                { "capabilities", &capabilities_file_ops, S_IRUGO },
                { "privcmd", &xen_privcmd_fops, S_IRUSR|S_IWUSR },
index e297e1b52636dadb9bf3f3acb2102c079e73e0e6..fa3e81c2a97b269f2065a45b8045d4944427c1d1 100644 (file)
@@ -176,7 +176,8 @@ quiet_cmd_fwbin = MK_FW   $@
 wordsize_deps := $(wildcard include/config/64bit.h include/config/32bit.h \
                include/config/ppc32.h include/config/ppc64.h \
                include/config/superh32.h include/config/superh64.h \
-               include/config/x86_32.h include/config/x86_64.h)
+               include/config/x86_32.h include/config/x86_64.h \
+               firmware/Makefile)
 
 $(patsubst %,$(obj)/%.gen.S, $(fw-shipped-y)): %: $(wordsize_deps)
        $(call cmd,fwbin,$(patsubst %.gen.S,%,$@))
index 83eab52fb3f69a75aa06a9f2a31760a384508f41..b0e42b6a96b97e37b03b7b61e9def73e814f421e 100644 (file)
@@ -39,6 +39,7 @@ config FS_DAX
        depends on MMU
        depends on !(ARM || MIPS || SPARC)
        select FS_IOMAP
+       select DAX
        help
          Direct Access (DAX) can be used on memory-backed block devices.
          If the block device supports DAX and the filesystem supports DAX,
index 2f8bab390d1379731ce889ff2b1beec5ddf91a53..773749be8290cb782324d341865861a2e64d199a 100644 (file)
@@ -7,7 +7,7 @@
 #include <linux/types.h>
 #include <linux/fs.h>
 #include <linux/buffer_head.h>
-#include <linux/amigaffs.h>
+#include "amigaffs.h"
 #include <linux/mutex.h>
 #include <linux/workqueue.h>
 
@@ -173,7 +173,7 @@ extern int  affs_link(struct dentry *olddentry, struct inode *dir,
                          struct dentry *dentry);
 extern int     affs_symlink(struct inode *dir, struct dentry *dentry,
                             const char *symname);
-extern int     affs_rename(struct inode *old_dir, struct dentry *old_dentry,
+extern int     affs_rename2(struct inode *old_dir, struct dentry *old_dentry,
                            struct inode *new_dir, struct dentry *new_dentry,
                            unsigned int flags);
 
similarity index 100%
rename from include/linux/amigaffs.h
rename to fs/affs/amigaffs.h
index f1e7294381c5aa48a386a3a7c0db7f4832c568ec..591ecd7f3063731d0eebe1435714e0be3949d455 100644 (file)
@@ -35,7 +35,7 @@ const struct inode_operations affs_dir_inode_operations = {
        .symlink        = affs_symlink,
        .mkdir          = affs_mkdir,
        .rmdir          = affs_rmdir,
-       .rename         = affs_rename,
+       .rename         = affs_rename2,
        .setattr        = affs_notify_change,
 };
 
index 0deec9cc2362c23fae1e25e88b12ff7769d823e2..196ee7f6fdc40e45235178b55abbc54461fbbb49 100644 (file)
@@ -499,7 +499,7 @@ affs_getemptyblk_ino(struct inode *inode, int block)
 }
 
 static int
-affs_do_readpage_ofs(struct page *page, unsigned to)
+affs_do_readpage_ofs(struct page *page, unsigned to, int create)
 {
        struct inode *inode = page->mapping->host;
        struct super_block *sb = inode->i_sb;
@@ -518,7 +518,7 @@ affs_do_readpage_ofs(struct page *page, unsigned to)
        boff = tmp % bsize;
 
        while (pos < to) {
-               bh = affs_bread_ino(inode, bidx, 0);
+               bh = affs_bread_ino(inode, bidx, create);
                if (IS_ERR(bh))
                        return PTR_ERR(bh);
                tmp = min(bsize - boff, to - pos);
@@ -620,7 +620,7 @@ affs_readpage_ofs(struct file *file, struct page *page)
                memset(page_address(page) + to, 0, PAGE_SIZE - to);
        }
 
-       err = affs_do_readpage_ofs(page, to);
+       err = affs_do_readpage_ofs(page, to, 0);
        if (!err)
                SetPageUptodate(page);
        unlock_page(page);
@@ -657,7 +657,7 @@ static int affs_write_begin_ofs(struct file *file, struct address_space *mapping
                return 0;
 
        /* XXX: inefficient but safe in the face of short writes */
-       err = affs_do_readpage_ofs(page, PAGE_SIZE);
+       err = affs_do_readpage_ofs(page, PAGE_SIZE, 1);
        if (err) {
                unlock_page(page);
                put_page(page);
@@ -679,7 +679,7 @@ static int affs_write_end_ofs(struct file *file, struct address_space *mapping,
        int written;
 
        from = pos & (PAGE_SIZE - 1);
-       to = pos + len;
+       to = from + len;
        /*
         * XXX: not sure if this can handle short copies (len < copied), but
         * we don't have to, because the page should always be uptodate here,
index abcc59899229c68165b9bcf0830885ecf707ecac..fd4ef3c40e4054ba9f23dec2198b650ef53e4cae 100644 (file)
@@ -140,6 +140,7 @@ struct inode *affs_iget(struct super_block *sb, unsigned long ino)
                inode->i_fop = &affs_file_operations;
                break;
        case ST_SOFTLINK:
+               inode->i_size = strlen((char *)AFFS_HEAD(bh)->table);
                inode->i_mode |= S_IFLNK;
                inode_nohighmem(inode);
                inode->i_op = &affs_symlink_inode_operations;
index 96dd1d09a2735676f51b94ff9390bbc114cf8367..46d3ace6761d7df89dcbbc598991a41561e16518 100644 (file)
@@ -365,6 +365,7 @@ affs_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
                                symname++;
        }
        *p = 0;
+       inode->i_size = i + 1;
        mark_buffer_dirty_inode(bh, inode);
        affs_brelse(bh);
        mark_inode_dirty(inode);
@@ -393,21 +394,14 @@ affs_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry)
        return affs_add_entry(dir, inode, dentry, ST_LINKFILE);
 }
 
-int
+static int
 affs_rename(struct inode *old_dir, struct dentry *old_dentry,
-           struct inode *new_dir, struct dentry *new_dentry,
-           unsigned int flags)
+           struct inode *new_dir, struct dentry *new_dentry)
 {
        struct super_block *sb = old_dir->i_sb;
        struct buffer_head *bh = NULL;
        int retval;
 
-       if (flags & ~RENAME_NOREPLACE)
-               return -EINVAL;
-
-       pr_debug("%s(old=%lu,\"%pd\" to new=%lu,\"%pd\")\n", __func__,
-                old_dir->i_ino, old_dentry, new_dir->i_ino, new_dentry);
-
        retval = affs_check_name(new_dentry->d_name.name,
                                 new_dentry->d_name.len,
                                 affs_nofilenametruncate(old_dentry));
@@ -447,6 +441,76 @@ done:
        return retval;
 }
 
+static int
+affs_xrename(struct inode *old_dir, struct dentry *old_dentry,
+            struct inode *new_dir, struct dentry *new_dentry)
+{
+
+       struct super_block *sb = old_dir->i_sb;
+       struct buffer_head *bh_old = NULL;
+       struct buffer_head *bh_new = NULL;
+       int retval;
+
+       bh_old = affs_bread(sb, d_inode(old_dentry)->i_ino);
+       if (!bh_old)
+               return -EIO;
+
+       bh_new = affs_bread(sb, d_inode(new_dentry)->i_ino);
+       if (!bh_new)
+               return -EIO;
+
+       /* Remove old header from its parent directory. */
+       affs_lock_dir(old_dir);
+       retval = affs_remove_hash(old_dir, bh_old);
+       affs_unlock_dir(old_dir);
+       if (retval)
+               goto done;
+
+       /* Remove new header from its parent directory. */
+       affs_lock_dir(new_dir);
+       retval = affs_remove_hash(new_dir, bh_new);
+       affs_unlock_dir(new_dir);
+       if (retval)
+               goto done;
+
+       /* Insert old into the new directory with the new name. */
+       affs_copy_name(AFFS_TAIL(sb, bh_old)->name, new_dentry);
+       affs_fix_checksum(sb, bh_old);
+       affs_lock_dir(new_dir);
+       retval = affs_insert_hash(new_dir, bh_old);
+       affs_unlock_dir(new_dir);
+
+       /* Insert new into the old directory with the old name. */
+       affs_copy_name(AFFS_TAIL(sb, bh_new)->name, old_dentry);
+       affs_fix_checksum(sb, bh_new);
+       affs_lock_dir(old_dir);
+       retval = affs_insert_hash(old_dir, bh_new);
+       affs_unlock_dir(old_dir);
+done:
+       mark_buffer_dirty_inode(bh_old, new_dir);
+       mark_buffer_dirty_inode(bh_new, old_dir);
+       affs_brelse(bh_old);
+       affs_brelse(bh_new);
+       return retval;
+}
+
+int affs_rename2(struct inode *old_dir, struct dentry *old_dentry,
+                       struct inode *new_dir, struct dentry *new_dentry,
+                       unsigned int flags)
+{
+
+       if (flags & ~(RENAME_NOREPLACE | RENAME_EXCHANGE))
+               return -EINVAL;
+
+       pr_debug("%s(old=%lu,\"%pd\" to new=%lu,\"%pd\")\n", __func__,
+                old_dir->i_ino, old_dentry, new_dir->i_ino, new_dentry);
+
+       if (flags & RENAME_EXCHANGE)
+               return affs_xrename(old_dir, old_dentry, new_dir, new_dentry);
+
+       return affs_rename(old_dir, old_dentry, new_dir, new_dentry);
+}
+
 static struct dentry *affs_get_parent(struct dentry *child)
 {
        struct inode *parent;
@@ -477,11 +541,6 @@ static struct inode *affs_nfs_get_inode(struct super_block *sb, u64 ino,
        if (IS_ERR(inode))
                return ERR_CAST(inode);
 
-       if (generation && inode->i_generation != generation) {
-               iput(inode);
-               return ERR_PTR(-ESTALE);
-       }
-
        return inode;
 }
 
index f2deec0a62f0c613349d6f7d94bd6077d2cceb96..25e312cb60716caef70a66f12eb391f8aa234005 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     fs/bfs/inode.c
  *     BFS superblock and inode operations.
- *     Copyright (C) 1999-2006 Tigran Aivazian <tigran@aivazian.fsnet.co.uk>
+ *     Copyright (C) 1999-2006 Tigran Aivazian <aivazian.tigran@gmail.com>
  *     From fs/minix, Copyright (C) 1991, 1992 Linus Torvalds.
  *
  *      Made endianness-clean by Andrew Stribblehill <ads@wompom.org>, 2005.
@@ -19,7 +19,7 @@
 #include <linux/uaccess.h>
 #include "bfs.h"
 
-MODULE_AUTHOR("Tigran Aivazian <tigran@aivazian.fsnet.co.uk>");
+MODULE_AUTHOR("Tigran Aivazian <aivazian.tigran@gmail.com>");
 MODULE_DESCRIPTION("SCO UnixWare BFS filesystem for Linux");
 MODULE_LICENSE("GPL");
 
index bee1a36bc2ec4e0be1343c11bb07da13bbcb384f..f4718098ac31885b64ebaba7c03af5fe75515092 100644 (file)
@@ -818,7 +818,7 @@ static const struct super_operations s_ops = {
 static int bm_fill_super(struct super_block *sb, void *data, int silent)
 {
        int err;
-       static struct tree_descr bm_files[] = {
+       static const struct tree_descr bm_files[] = {
                [2] = {"status", &bm_status_operations, S_IWUSR|S_IRUGO},
                [3] = {"register", &bm_register_operations, S_IWUSR},
                /* last one */ {""}
index 2a305c1a2d881a78e8251288908a7bafcc840af9..519599dddd3692ee373a9eb00d95d5757556ad42 100644 (file)
@@ -717,72 +717,6 @@ int bdev_write_page(struct block_device *bdev, sector_t sector,
 }
 EXPORT_SYMBOL_GPL(bdev_write_page);
 
-int bdev_dax_pgoff(struct block_device *bdev, sector_t sector, size_t size,
-               pgoff_t *pgoff)
-{
-       phys_addr_t phys_off = (get_start_sect(bdev) + sector) * 512;
-
-       if (pgoff)
-               *pgoff = PHYS_PFN(phys_off);
-       if (phys_off % PAGE_SIZE || size % PAGE_SIZE)
-               return -EINVAL;
-       return 0;
-}
-EXPORT_SYMBOL(bdev_dax_pgoff);
-
-/**
- * bdev_dax_supported() - Check if the device supports dax for filesystem
- * @sb: The superblock of the device
- * @blocksize: The block size of the device
- *
- * This is a library function for filesystems to check if the block device
- * can be mounted with dax option.
- *
- * Return: negative errno if unsupported, 0 if supported.
- */
-int bdev_dax_supported(struct super_block *sb, int blocksize)
-{
-       struct block_device *bdev = sb->s_bdev;
-       struct dax_device *dax_dev;
-       pgoff_t pgoff;
-       int err, id;
-       void *kaddr;
-       pfn_t pfn;
-       long len;
-
-       if (blocksize != PAGE_SIZE) {
-               vfs_msg(sb, KERN_ERR, "error: unsupported blocksize for dax");
-               return -EINVAL;
-       }
-
-       err = bdev_dax_pgoff(bdev, 0, PAGE_SIZE, &pgoff);
-       if (err) {
-               vfs_msg(sb, KERN_ERR, "error: unaligned partition for dax");
-               return err;
-       }
-
-       dax_dev = dax_get_by_host(bdev->bd_disk->disk_name);
-       if (!dax_dev) {
-               vfs_msg(sb, KERN_ERR, "error: device does not support dax");
-               return -EOPNOTSUPP;
-       }
-
-       id = dax_read_lock();
-       len = dax_direct_access(dax_dev, pgoff, 1, &kaddr, &pfn);
-       dax_read_unlock(id);
-
-       put_dax(dax_dev);
-
-       if (len < 1) {
-               vfs_msg(sb, KERN_ERR,
-                               "error: dax access failed (%ld)", len);
-               return len < 0 ? len : -EIO;
-       }
-
-       return 0;
-}
-EXPORT_SYMBOL_GPL(bdev_dax_supported);
-
 /*
  * pseudo-fs
  */
index 7699e16784d313459181c746d0b8c30d468e23a7..24865da63d8fdfd2a979429a426b42fe8781e0aa 100644 (file)
 #include "delayed-ref.h"
 #include "locking.h"
 
+enum merge_mode {
+       MERGE_IDENTICAL_KEYS = 1,
+       MERGE_IDENTICAL_PARENTS,
+};
+
 /* Just an arbitrary number so we can be sure this happened */
 #define BACKREF_FOUND_SHARED 6
 
@@ -533,7 +538,7 @@ static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path,
         * slot==nritems. In that case, go to the next leaf before we continue.
         */
        if (path->slots[0] >= btrfs_header_nritems(path->nodes[0])) {
-               if (time_seq == (u64)-1)
+               if (time_seq == SEQ_LAST)
                        ret = btrfs_next_leaf(root, path);
                else
                        ret = btrfs_next_old_leaf(root, path, time_seq);
@@ -577,7 +582,7 @@ static int add_all_parents(struct btrfs_root *root, struct btrfs_path *path,
                        eie = NULL;
                }
 next:
-               if (time_seq == (u64)-1)
+               if (time_seq == SEQ_LAST)
                        ret = btrfs_next_item(root, path);
                else
                        ret = btrfs_next_old_item(root, path, time_seq);
@@ -629,7 +634,7 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
 
        if (path->search_commit_root)
                root_level = btrfs_header_level(root->commit_root);
-       else if (time_seq == (u64)-1)
+       else if (time_seq == SEQ_LAST)
                root_level = btrfs_header_level(root->node);
        else
                root_level = btrfs_old_root_level(root, time_seq);
@@ -640,7 +645,7 @@ static int __resolve_indirect_ref(struct btrfs_fs_info *fs_info,
        }
 
        path->lowest_level = level;
-       if (time_seq == (u64)-1)
+       if (time_seq == SEQ_LAST)
                ret = btrfs_search_slot(NULL, root, &ref->key_for_search, path,
                                        0, 0);
        else
@@ -809,14 +814,12 @@ static int __add_missing_keys(struct btrfs_fs_info *fs_info,
 /*
  * merge backrefs and adjust counts accordingly
  *
- * mode = 1: merge identical keys, if key is set
- *    FIXME: if we add more keys in __add_prelim_ref, we can merge more here.
- *           additionally, we could even add a key range for the blocks we
- *           looked into to merge even more (-> replace unresolved refs by those
- *           having a parent).
- * mode = 2: merge identical parents
+ *    FIXME: For MERGE_IDENTICAL_KEYS, if we add more keys in __add_prelim_ref
+ *           then we can merge more here. Additionally, we could even add a key
+ *           range for the blocks we looked into to merge even more (-> replace
+ *           unresolved refs by those having a parent).
  */
-static void __merge_refs(struct list_head *head, int mode)
+static void __merge_refs(struct list_head *head, enum merge_mode mode)
 {
        struct __prelim_ref *pos1;
 
@@ -829,7 +832,7 @@ static void __merge_refs(struct list_head *head, int mode)
 
                        if (!ref_for_same_block(ref1, ref2))
                                continue;
-                       if (mode == 1) {
+                       if (mode == MERGE_IDENTICAL_KEYS) {
                                if (!ref1->parent && ref2->parent)
                                        swap(ref1, ref2);
                        } else {
@@ -1196,7 +1199,7 @@ static int __add_keyed_refs(struct btrfs_fs_info *fs_info,
  *
  * NOTE: This can return values > 0
  *
- * If time_seq is set to (u64)-1, it will not search delayed_refs, and behave
+ * If time_seq is set to SEQ_LAST, it will not search delayed_refs, and behave
  * much like trans == NULL case, the difference only lies in it will not
  * commit root.
  * The special case is for qgroup to search roots in commit_transaction().
@@ -1243,7 +1246,7 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans,
                path->skip_locking = 1;
        }
 
-       if (time_seq == (u64)-1)
+       if (time_seq == SEQ_LAST)
                path->skip_locking = 1;
 
        /*
@@ -1273,9 +1276,9 @@ again:
 
 #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
        if (trans && likely(trans->type != __TRANS_DUMMY) &&
-           time_seq != (u64)-1) {
+           time_seq != SEQ_LAST) {
 #else
-       if (trans && time_seq != (u64)-1) {
+       if (trans && time_seq != SEQ_LAST) {
 #endif
                /*
                 * look if there are updates for this ref queued and lock the
@@ -1286,7 +1289,7 @@ again:
                head = btrfs_find_delayed_ref_head(delayed_refs, bytenr);
                if (head) {
                        if (!mutex_trylock(&head->mutex)) {
-                               atomic_inc(&head->node.refs);
+                               refcount_inc(&head->node.refs);
                                spin_unlock(&delayed_refs->lock);
 
                                btrfs_release_path(path);
@@ -1374,7 +1377,7 @@ again:
        if (ret)
                goto out;
 
-       __merge_refs(&prefs, 1);
+       __merge_refs(&prefs, MERGE_IDENTICAL_KEYS);
 
        ret = __resolve_indirect_refs(fs_info, path, time_seq, &prefs,
                                      extent_item_pos, total_refs,
@@ -1382,7 +1385,7 @@ again:
        if (ret)
                goto out;
 
-       __merge_refs(&prefs, 2);
+       __merge_refs(&prefs, MERGE_IDENTICAL_PARENTS);
 
        while (!list_empty(&prefs)) {
                ref = list_first_entry(&prefs, struct __prelim_ref, list);
index 0c6baaba0651ce10ba5e394ad82a03a917ced4e6..b8622e4d1744de68180f96036ad5ddbc3c195ca8 100644 (file)
@@ -124,6 +124,13 @@ struct btrfs_inode {
         */
        u64 delalloc_bytes;
 
+       /*
+        * Total number of bytes pending delalloc that fall within a file
+        * range that is either a hole or beyond EOF (and no prealloc extent
+        * exists in the range). This is always <= delalloc_bytes.
+        */
+       u64 new_delalloc_bytes;
+
        /*
         * total number of bytes pending defrag, used by stat to check whether
         * it needs COW.
index c7721a6aa3bb5346cbd9103b4ee3e9f4528a8c4e..10e6b282d09d6e8d31b4ac8740d0119ccad3e786 100644 (file)
@@ -44,7 +44,7 @@
 
 struct compressed_bio {
        /* number of bios pending for this compressed extent */
-       atomic_t pending_bios;
+       refcount_t pending_bios;
 
        /* the pages with the compressed data on them */
        struct page **compressed_pages;
@@ -161,7 +161,7 @@ static void end_compressed_bio_read(struct bio *bio)
        /* if there are more bios still pending for this compressed
         * extent, just exit
         */
-       if (!atomic_dec_and_test(&cb->pending_bios))
+       if (!refcount_dec_and_test(&cb->pending_bios))
                goto out;
 
        inode = cb->inode;
@@ -274,7 +274,7 @@ static void end_compressed_bio_write(struct bio *bio)
        /* if there are more bios still pending for this compressed
         * extent, just exit
         */
-       if (!atomic_dec_and_test(&cb->pending_bios))
+       if (!refcount_dec_and_test(&cb->pending_bios))
                goto out;
 
        /* ok, we're the last bio for this extent, step one is to
@@ -342,7 +342,7 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start,
        cb = kmalloc(compressed_bio_size(fs_info, compressed_len), GFP_NOFS);
        if (!cb)
                return -ENOMEM;
-       atomic_set(&cb->pending_bios, 0);
+       refcount_set(&cb->pending_bios, 0);
        cb->errors = 0;
        cb->inode = inode;
        cb->start = start;
@@ -363,7 +363,7 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start,
        bio_set_op_attrs(bio, REQ_OP_WRITE, 0);
        bio->bi_private = cb;
        bio->bi_end_io = end_compressed_bio_write;
-       atomic_inc(&cb->pending_bios);
+       refcount_set(&cb->pending_bios, 1);
 
        /* create and submit bios for the compressed pages */
        bytes_left = compressed_len;
@@ -388,7 +388,7 @@ int btrfs_submit_compressed_write(struct inode *inode, u64 start,
                         * we inc the count.  Otherwise, the cb might get
                         * freed before we're done setting it up
                         */
-                       atomic_inc(&cb->pending_bios);
+                       refcount_inc(&cb->pending_bios);
                        ret = btrfs_bio_wq_end_io(fs_info, bio,
                                                  BTRFS_WQ_ENDIO_DATA);
                        BUG_ON(ret); /* -ENOMEM */
@@ -607,7 +607,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
        if (!cb)
                goto out;
 
-       atomic_set(&cb->pending_bios, 0);
+       refcount_set(&cb->pending_bios, 0);
        cb->errors = 0;
        cb->inode = inode;
        cb->mirror_num = mirror_num;
@@ -656,7 +656,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
        bio_set_op_attrs (comp_bio, REQ_OP_READ, 0);
        comp_bio->bi_private = cb;
        comp_bio->bi_end_io = end_compressed_bio_read;
-       atomic_inc(&cb->pending_bios);
+       refcount_set(&cb->pending_bios, 1);
 
        for (pg_index = 0; pg_index < nr_pages; pg_index++) {
                page = cb->compressed_pages[pg_index];
@@ -685,7 +685,7 @@ int btrfs_submit_compressed_read(struct inode *inode, struct bio *bio,
                         * we inc the count.  Otherwise, the cb might get
                         * freed before we're done setting it up
                         */
-                       atomic_inc(&cb->pending_bios);
+                       refcount_inc(&cb->pending_bios);
 
                        if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) {
                                ret = btrfs_lookup_bio_sums(inode, comp_bio,
index 7dc8844037e03b7cfb738d81af6c22b33ee2b31d..a3a75f1de002295c425f5957de7e9aba269a7682 100644 (file)
@@ -567,7 +567,7 @@ tree_mod_log_insert_key(struct btrfs_fs_info *fs_info,
 static noinline int
 tree_mod_log_insert_move(struct btrfs_fs_info *fs_info,
                         struct extent_buffer *eb, int dst_slot, int src_slot,
-                        int nr_items, gfp_t flags)
+                        int nr_items)
 {
        struct tree_mod_elem *tm = NULL;
        struct tree_mod_elem **tm_list = NULL;
@@ -578,11 +578,11 @@ tree_mod_log_insert_move(struct btrfs_fs_info *fs_info,
        if (!tree_mod_need_log(fs_info, eb))
                return 0;
 
-       tm_list = kcalloc(nr_items, sizeof(struct tree_mod_elem *), flags);
+       tm_list = kcalloc(nr_items, sizeof(struct tree_mod_elem *), GFP_NOFS);
        if (!tm_list)
                return -ENOMEM;
 
-       tm = kzalloc(sizeof(*tm), flags);
+       tm = kzalloc(sizeof(*tm), GFP_NOFS);
        if (!tm) {
                ret = -ENOMEM;
                goto free_tms;
@@ -596,7 +596,7 @@ tree_mod_log_insert_move(struct btrfs_fs_info *fs_info,
 
        for (i = 0; i + dst_slot < src_slot && i < nr_items; i++) {
                tm_list[i] = alloc_tree_mod_elem(eb, i + dst_slot,
-                   MOD_LOG_KEY_REMOVE_WHILE_MOVING, flags);
+                   MOD_LOG_KEY_REMOVE_WHILE_MOVING, GFP_NOFS);
                if (!tm_list[i]) {
                        ret = -ENOMEM;
                        goto free_tms;
@@ -663,7 +663,7 @@ __tree_mod_log_free_eb(struct btrfs_fs_info *fs_info,
 static noinline int
 tree_mod_log_insert_root(struct btrfs_fs_info *fs_info,
                         struct extent_buffer *old_root,
-                        struct extent_buffer *new_root, gfp_t flags,
+                        struct extent_buffer *new_root,
                         int log_removal)
 {
        struct tree_mod_elem *tm = NULL;
@@ -678,14 +678,14 @@ tree_mod_log_insert_root(struct btrfs_fs_info *fs_info,
        if (log_removal && btrfs_header_level(old_root) > 0) {
                nritems = btrfs_header_nritems(old_root);
                tm_list = kcalloc(nritems, sizeof(struct tree_mod_elem *),
-                                 flags);
+                                 GFP_NOFS);
                if (!tm_list) {
                        ret = -ENOMEM;
                        goto free_tms;
                }
                for (i = 0; i < nritems; i++) {
                        tm_list[i] = alloc_tree_mod_elem(old_root, i,
-                           MOD_LOG_KEY_REMOVE_WHILE_FREEING, flags);
+                           MOD_LOG_KEY_REMOVE_WHILE_FREEING, GFP_NOFS);
                        if (!tm_list[i]) {
                                ret = -ENOMEM;
                                goto free_tms;
@@ -693,7 +693,7 @@ tree_mod_log_insert_root(struct btrfs_fs_info *fs_info,
                }
        }
 
-       tm = kzalloc(sizeof(*tm), flags);
+       tm = kzalloc(sizeof(*tm), GFP_NOFS);
        if (!tm) {
                ret = -ENOMEM;
                goto free_tms;
@@ -873,7 +873,7 @@ tree_mod_log_eb_move(struct btrfs_fs_info *fs_info, struct extent_buffer *dst,
 {
        int ret;
        ret = tree_mod_log_insert_move(fs_info, dst, dst_offset, src_offset,
-                                      nr_items, GFP_NOFS);
+                                      nr_items);
        BUG_ON(ret < 0);
 }
 
@@ -943,7 +943,7 @@ tree_mod_log_set_root_pointer(struct btrfs_root *root,
 {
        int ret;
        ret = tree_mod_log_insert_root(root->fs_info, root->node,
-                                      new_root_node, GFP_NOFS, log_removal);
+                                      new_root_node, log_removal);
        BUG_ON(ret < 0);
 }
 
@@ -5392,13 +5392,10 @@ int btrfs_compare_trees(struct btrfs_root *left_root,
                goto out;
        }
 
-       tmp_buf = kmalloc(fs_info->nodesize, GFP_KERNEL | __GFP_NOWARN);
+       tmp_buf = kvmalloc(fs_info->nodesize, GFP_KERNEL);
        if (!tmp_buf) {
-               tmp_buf = vmalloc(fs_info->nodesize);
-               if (!tmp_buf) {
-                       ret = -ENOMEM;
-                       goto out;
-               }
+               ret = -ENOMEM;
+               goto out;
        }
 
        left_path->search_commit_root = 1;
index 3e21211e99c39571968f79c95d88eb3eaba6f262..643c70d2b2e65ab96a93ff4c022756ea7e59d179 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/security.h>
 #include <linux/sizes.h>
 #include <linux/dynamic_debug.h>
+#include <linux/refcount.h>
 #include "extent_io.h"
 #include "extent_map.h"
 #include "async-thread.h"
@@ -518,7 +519,7 @@ struct btrfs_caching_control {
        struct btrfs_work work;
        struct btrfs_block_group_cache *block_group;
        u64 progress;
-       atomic_t count;
+       refcount_t count;
 };
 
 /* Once caching_thread() finds this much free space, it will wake up waiters. */
@@ -538,6 +539,14 @@ struct btrfs_io_ctl {
        unsigned check_crcs:1;
 };
 
+/*
+ * Tree to record all locked full stripes of a RAID5/6 block group
+ */
+struct btrfs_full_stripe_locks_tree {
+       struct rb_root root;
+       struct mutex lock;
+};
+
 struct btrfs_block_group_cache {
        struct btrfs_key key;
        struct btrfs_block_group_item item;
@@ -648,6 +657,9 @@ struct btrfs_block_group_cache {
         * Protected by free_space_lock.
         */
        int needs_free_space;
+
+       /* Record locked full stripes for RAID5/6 block group */
+       struct btrfs_full_stripe_locks_tree full_stripe_locks_root;
 };
 
 /* delayed seq elem */
@@ -658,6 +670,8 @@ struct seq_list {
 
 #define SEQ_LIST_INIT(name)    { .list = LIST_HEAD_INIT((name).list), .seq = 0 }
 
+#define SEQ_LAST       ((u64)-1)
+
 enum btrfs_orphan_cleanup_state {
        ORPHAN_CLEANUP_STARTED  = 1,
        ORPHAN_CLEANUP_DONE     = 2,
@@ -702,6 +716,11 @@ struct btrfs_delayed_root;
 #define BTRFS_FS_BTREE_ERR                     11
 #define BTRFS_FS_LOG1_ERR                      12
 #define BTRFS_FS_LOG2_ERR                      13
+/*
+ * Indicate that a whole-filesystem exclusive operation is running
+ * (device replace, resize, device add/delete, balance)
+ */
+#define BTRFS_FS_EXCL_OP                       14
 
 struct btrfs_fs_info {
        u8 fsid[BTRFS_FSID_SIZE];
@@ -1066,8 +1085,6 @@ struct btrfs_fs_info {
        /* device replace state */
        struct btrfs_dev_replace dev_replace;
 
-       atomic_t mutually_exclusive_operation_running;
-
        struct percpu_counter bio_counter;
        wait_queue_head_t replace_wait;
 
@@ -1220,7 +1237,7 @@ struct btrfs_root {
        dev_t anon_dev;
 
        spinlock_t root_item_lock;
-       atomic_t refs;
+       refcount_t refs;
 
        struct mutex delalloc_mutex;
        spinlock_t delalloc_lock;
@@ -3646,6 +3663,12 @@ int btrfs_scrub_cancel_dev(struct btrfs_fs_info *info,
                           struct btrfs_device *dev);
 int btrfs_scrub_progress(struct btrfs_fs_info *fs_info, u64 devid,
                         struct btrfs_scrub_progress *progress);
+static inline void btrfs_init_full_stripe_locks_tree(
+                       struct btrfs_full_stripe_locks_tree *locks_root)
+{
+       locks_root->root = RB_ROOT;
+       mutex_init(&locks_root->lock);
+}
 
 /* dev-replace.c */
 void btrfs_bio_counter_inc_blocked(struct btrfs_fs_info *fs_info);
@@ -3670,8 +3693,7 @@ struct reada_control *btrfs_reada_add(struct btrfs_root *root,
                              struct btrfs_key *start, struct btrfs_key *end);
 int btrfs_reada_wait(void *handle);
 void btrfs_reada_detach(void *handle);
-int btree_readahead_hook(struct btrfs_fs_info *fs_info,
-                        struct extent_buffer *eb, int err);
+int btree_readahead_hook(struct extent_buffer *eb, int err);
 
 static inline int is_fstree(u64 rootid)
 {
index 1aff676f0e5b5b6c63efd32eee44958b40968e2a..8ae409b5a61d7186f050780beced1bf72cd572ca 100644 (file)
@@ -52,7 +52,7 @@ static inline void btrfs_init_delayed_node(
 {
        delayed_node->root = root;
        delayed_node->inode_id = inode_id;
-       atomic_set(&delayed_node->refs, 0);
+       refcount_set(&delayed_node->refs, 0);
        delayed_node->ins_root = RB_ROOT;
        delayed_node->del_root = RB_ROOT;
        mutex_init(&delayed_node->mutex);
@@ -81,7 +81,7 @@ static struct btrfs_delayed_node *btrfs_get_delayed_node(
 
        node = READ_ONCE(btrfs_inode->delayed_node);
        if (node) {
-               atomic_inc(&node->refs);
+               refcount_inc(&node->refs);
                return node;
        }
 
@@ -89,14 +89,14 @@ static struct btrfs_delayed_node *btrfs_get_delayed_node(
        node = radix_tree_lookup(&root->delayed_nodes_tree, ino);
        if (node) {
                if (btrfs_inode->delayed_node) {
-                       atomic_inc(&node->refs);        /* can be accessed */
+                       refcount_inc(&node->refs);      /* can be accessed */
                        BUG_ON(btrfs_inode->delayed_node != node);
                        spin_unlock(&root->inode_lock);
                        return node;
                }
                btrfs_inode->delayed_node = node;
                /* can be accessed and cached in the inode */
-               atomic_add(2, &node->refs);
+               refcount_add(2, &node->refs);
                spin_unlock(&root->inode_lock);
                return node;
        }
@@ -125,7 +125,7 @@ again:
        btrfs_init_delayed_node(node, root, ino);
 
        /* cached in the btrfs inode and can be accessed */
-       atomic_add(2, &node->refs);
+       refcount_set(&node->refs, 2);
 
        ret = radix_tree_preload(GFP_NOFS);
        if (ret) {
@@ -166,7 +166,7 @@ static void btrfs_queue_delayed_node(struct btrfs_delayed_root *root,
        } else {
                list_add_tail(&node->n_list, &root->node_list);
                list_add_tail(&node->p_list, &root->prepare_list);
-               atomic_inc(&node->refs);        /* inserted into list */
+               refcount_inc(&node->refs);      /* inserted into list */
                root->nodes++;
                set_bit(BTRFS_DELAYED_NODE_IN_LIST, &node->flags);
        }
@@ -180,7 +180,7 @@ static void btrfs_dequeue_delayed_node(struct btrfs_delayed_root *root,
        spin_lock(&root->lock);
        if (test_bit(BTRFS_DELAYED_NODE_IN_LIST, &node->flags)) {
                root->nodes--;
-               atomic_dec(&node->refs);        /* not in the list */
+               refcount_dec(&node->refs);      /* not in the list */
                list_del_init(&node->n_list);
                if (!list_empty(&node->p_list))
                        list_del_init(&node->p_list);
@@ -201,7 +201,7 @@ static struct btrfs_delayed_node *btrfs_first_delayed_node(
 
        p = delayed_root->node_list.next;
        node = list_entry(p, struct btrfs_delayed_node, n_list);
-       atomic_inc(&node->refs);
+       refcount_inc(&node->refs);
 out:
        spin_unlock(&delayed_root->lock);
 
@@ -228,7 +228,7 @@ static struct btrfs_delayed_node *btrfs_next_delayed_node(
                p = node->n_list.next;
 
        next = list_entry(p, struct btrfs_delayed_node, n_list);
-       atomic_inc(&next->refs);
+       refcount_inc(&next->refs);
 out:
        spin_unlock(&delayed_root->lock);
 
@@ -253,11 +253,11 @@ static void __btrfs_release_delayed_node(
                btrfs_dequeue_delayed_node(delayed_root, delayed_node);
        mutex_unlock(&delayed_node->mutex);
 
-       if (atomic_dec_and_test(&delayed_node->refs)) {
+       if (refcount_dec_and_test(&delayed_node->refs)) {
                bool free = false;
                struct btrfs_root *root = delayed_node->root;
                spin_lock(&root->inode_lock);
-               if (atomic_read(&delayed_node->refs) == 0) {
+               if (refcount_read(&delayed_node->refs) == 0) {
                        radix_tree_delete(&root->delayed_nodes_tree,
                                          delayed_node->inode_id);
                        free = true;
@@ -286,7 +286,7 @@ static struct btrfs_delayed_node *btrfs_first_prepared_delayed_node(
        p = delayed_root->prepare_list.next;
        list_del_init(p);
        node = list_entry(p, struct btrfs_delayed_node, p_list);
-       atomic_inc(&node->refs);
+       refcount_inc(&node->refs);
 out:
        spin_unlock(&delayed_root->lock);
 
@@ -308,7 +308,7 @@ static struct btrfs_delayed_item *btrfs_alloc_delayed_item(u32 data_len)
                item->ins_or_del = 0;
                item->bytes_reserved = 0;
                item->delayed_node = NULL;
-               atomic_set(&item->refs, 1);
+               refcount_set(&item->refs, 1);
        }
        return item;
 }
@@ -483,7 +483,7 @@ static void btrfs_release_delayed_item(struct btrfs_delayed_item *item)
 {
        if (item) {
                __btrfs_remove_delayed_item(item);
-               if (atomic_dec_and_test(&item->refs))
+               if (refcount_dec_and_test(&item->refs))
                        kfree(item);
        }
 }
@@ -1600,14 +1600,14 @@ bool btrfs_readdir_get_delayed_items(struct inode *inode,
        mutex_lock(&delayed_node->mutex);
        item = __btrfs_first_delayed_insertion_item(delayed_node);
        while (item) {
-               atomic_inc(&item->refs);
+               refcount_inc(&item->refs);
                list_add_tail(&item->readdir_list, ins_list);
                item = __btrfs_next_delayed_item(item);
        }
 
        item = __btrfs_first_delayed_deletion_item(delayed_node);
        while (item) {
-               atomic_inc(&item->refs);
+               refcount_inc(&item->refs);
                list_add_tail(&item->readdir_list, del_list);
                item = __btrfs_next_delayed_item(item);
        }
@@ -1621,7 +1621,7 @@ bool btrfs_readdir_get_delayed_items(struct inode *inode,
         * insert/delete delayed items in this period. So we also needn't
         * requeue or dequeue this delayed node.
         */
-       atomic_dec(&delayed_node->refs);
+       refcount_dec(&delayed_node->refs);
 
        return true;
 }
@@ -1634,13 +1634,13 @@ void btrfs_readdir_put_delayed_items(struct inode *inode,
 
        list_for_each_entry_safe(curr, next, ins_list, readdir_list) {
                list_del(&curr->readdir_list);
-               if (atomic_dec_and_test(&curr->refs))
+               if (refcount_dec_and_test(&curr->refs))
                        kfree(curr);
        }
 
        list_for_each_entry_safe(curr, next, del_list, readdir_list) {
                list_del(&curr->readdir_list);
-               if (atomic_dec_and_test(&curr->refs))
+               if (refcount_dec_and_test(&curr->refs))
                        kfree(curr);
        }
 
@@ -1667,7 +1667,7 @@ int btrfs_should_delete_dir_index(struct list_head *del_list,
                list_del(&curr->readdir_list);
                ret = (curr->key.offset == index);
 
-               if (atomic_dec_and_test(&curr->refs))
+               if (refcount_dec_and_test(&curr->refs))
                        kfree(curr);
 
                if (ret)
@@ -1705,7 +1705,7 @@ int btrfs_readdir_delayed_dir_index(struct dir_context *ctx,
                list_del(&curr->readdir_list);
 
                if (curr->key.offset < ctx->pos) {
-                       if (atomic_dec_and_test(&curr->refs))
+                       if (refcount_dec_and_test(&curr->refs))
                                kfree(curr);
                        continue;
                }
@@ -1722,7 +1722,7 @@ int btrfs_readdir_delayed_dir_index(struct dir_context *ctx,
                over = !dir_emit(ctx, name, name_len,
                               location.objectid, d_type);
 
-               if (atomic_dec_and_test(&curr->refs))
+               if (refcount_dec_and_test(&curr->refs))
                        kfree(curr);
 
                if (over)
@@ -1963,7 +1963,7 @@ void btrfs_kill_all_delayed_nodes(struct btrfs_root *root)
                inode_id = delayed_nodes[n - 1]->inode_id + 1;
 
                for (i = 0; i < n; i++)
-                       atomic_inc(&delayed_nodes[i]->refs);
+                       refcount_inc(&delayed_nodes[i]->refs);
                spin_unlock(&root->inode_lock);
 
                for (i = 0; i < n; i++) {
index 40327cc3b99a3bdcd517827652969299e1ce2a2b..c4189d4959343219eadf1db68d8aa5dd3f8d6ee4 100644 (file)
@@ -26,7 +26,7 @@
 #include <linux/list.h>
 #include <linux/wait.h>
 #include <linux/atomic.h>
-
+#include <linux/refcount.h>
 #include "ctree.h"
 
 /* types of the delayed item */
@@ -67,7 +67,7 @@ struct btrfs_delayed_node {
        struct rb_root del_root;
        struct mutex mutex;
        struct btrfs_inode_item inode_item;
-       atomic_t refs;
+       refcount_t refs;
        u64 index_cnt;
        unsigned long flags;
        int count;
@@ -80,7 +80,7 @@ struct btrfs_delayed_item {
        struct list_head readdir_list;  /* used for readdir items */
        u64 bytes_reserved;
        struct btrfs_delayed_node *delayed_node;
-       atomic_t refs;
+       refcount_t refs;
        int ins_or_del;
        u32 data_len;
        char data[0];
index 6eb80952efb3310ae55de9c2e234319abe14465a..be70d90dfee591953d53100b3c872d0efc5f324f 100644 (file)
@@ -164,7 +164,7 @@ int btrfs_delayed_ref_lock(struct btrfs_trans_handle *trans,
        if (mutex_trylock(&head->mutex))
                return 0;
 
-       atomic_inc(&head->node.refs);
+       refcount_inc(&head->node.refs);
        spin_unlock(&delayed_refs->lock);
 
        mutex_lock(&head->mutex);
@@ -590,7 +590,7 @@ add_delayed_ref_head(struct btrfs_fs_info *fs_info,
        delayed_refs = &trans->transaction->delayed_refs;
 
        /* first set the basic ref node struct up */
-       atomic_set(&ref->refs, 1);
+       refcount_set(&ref->refs, 1);
        ref->bytenr = bytenr;
        ref->num_bytes = num_bytes;
        ref->ref_mod = count_mod;
@@ -682,7 +682,7 @@ add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
        delayed_refs = &trans->transaction->delayed_refs;
 
        /* first set the basic ref node struct up */
-       atomic_set(&ref->refs, 1);
+       refcount_set(&ref->refs, 1);
        ref->bytenr = bytenr;
        ref->num_bytes = num_bytes;
        ref->ref_mod = 1;
@@ -739,7 +739,7 @@ add_delayed_data_ref(struct btrfs_fs_info *fs_info,
                seq = atomic64_read(&fs_info->tree_mod_seq);
 
        /* first set the basic ref node struct up */
-       atomic_set(&ref->refs, 1);
+       refcount_set(&ref->refs, 1);
        ref->bytenr = bytenr;
        ref->num_bytes = num_bytes;
        ref->ref_mod = 1;
index 0e537f98f1a1c63c529c118baed1cac26efa194e..c0264ff01b53cfe9e2fa44a7cdd7e9352012f0ee 100644 (file)
@@ -18,6 +18,8 @@
 #ifndef __DELAYED_REF__
 #define __DELAYED_REF__
 
+#include <linux/refcount.h>
+
 /* these are the possible values of struct btrfs_delayed_ref_node->action */
 #define BTRFS_ADD_DELAYED_REF    1 /* add one backref to the tree */
 #define BTRFS_DROP_DELAYED_REF   2 /* delete one backref from the tree */
@@ -53,7 +55,7 @@ struct btrfs_delayed_ref_node {
        u64 seq;
 
        /* ref count on this data structure */
-       atomic_t refs;
+       refcount_t refs;
 
        /*
         * how many refs is this entry adding or deleting.  For
@@ -220,8 +222,8 @@ btrfs_free_delayed_extent_op(struct btrfs_delayed_extent_op *op)
 
 static inline void btrfs_put_delayed_ref(struct btrfs_delayed_ref_node *ref)
 {
-       WARN_ON(atomic_read(&ref->refs) == 0);
-       if (atomic_dec_and_test(&ref->refs)) {
+       WARN_ON(refcount_read(&ref->refs) == 0);
+       if (refcount_dec_and_test(&ref->refs)) {
                WARN_ON(ref->in_tree);
                switch (ref->type) {
                case BTRFS_TREE_BLOCK_REF_KEY:
index e653921f05d93936581785553a8964124f5df1c0..5fe1ca8abc70577fe28ee6fd69899d11b618d479 100644 (file)
@@ -546,8 +546,10 @@ static int btrfs_dev_replace_finishing(struct btrfs_fs_info *fs_info,
                mutex_unlock(&fs_info->chunk_mutex);
                mutex_unlock(&fs_info->fs_devices->device_list_mutex);
                mutex_unlock(&uuid_mutex);
+               btrfs_rm_dev_replace_blocked(fs_info);
                if (tgt_device)
                        btrfs_destroy_dev_replace_tgtdev(fs_info, tgt_device);
+               btrfs_rm_dev_replace_unblocked(fs_info);
                mutex_unlock(&dev_replace->lock_finishing_cancel_unmount);
 
                return scrub_ret;
@@ -665,7 +667,7 @@ void btrfs_dev_replace_status(struct btrfs_fs_info *fs_info,
        case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED:
        case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED:
                srcdev = dev_replace->srcdev;
-               args->status.progress_1000 = div_u64(dev_replace->cursor_left,
+               args->status.progress_1000 = div64_u64(dev_replace->cursor_left,
                        div_u64(btrfs_device_get_total_bytes(srcdev), 1000));
                break;
        }
@@ -784,8 +786,7 @@ int btrfs_resume_dev_replace_async(struct btrfs_fs_info *fs_info)
        }
        btrfs_dev_replace_unlock(dev_replace, 1);
 
-       WARN_ON(atomic_xchg(
-               &fs_info->mutually_exclusive_operation_running, 1));
+       WARN_ON(test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags));
        task = kthread_run(btrfs_dev_replace_kthread, fs_info, "btrfs-devrepl");
        return PTR_ERR_OR_ZERO(task);
 }
@@ -814,7 +815,7 @@ static int btrfs_dev_replace_kthread(void *data)
                        (unsigned int)progress);
        }
        btrfs_dev_replace_continue_on_mount(fs_info);
-       atomic_set(&fs_info->mutually_exclusive_operation_running, 0);
+       clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
 
        return 0;
 }
index 061c1d1f774f289d854ea6114a74aaf9c2a67b84..8685d67185d01bf90bcd2cf6d7cdd168e044c777 100644 (file)
@@ -762,7 +762,7 @@ static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio,
 err:
        if (reads_done &&
            test_and_clear_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags))
-               btree_readahead_hook(fs_info, eb, ret);
+               btree_readahead_hook(eb, ret);
 
        if (ret) {
                /*
@@ -787,7 +787,7 @@ static int btree_io_failed_hook(struct page *page, int failed_mirror)
        eb->read_mirror = failed_mirror;
        atomic_dec(&eb->io_pages);
        if (test_and_clear_bit(EXTENT_BUFFER_READAHEAD, &eb->bflags))
-               btree_readahead_hook(eb->fs_info, eb, -EIO);
+               btree_readahead_hook(eb, -EIO);
        return -EIO;    /* we fixed nothing */
 }
 
@@ -1340,7 +1340,7 @@ static void __setup_root(struct btrfs_root *root, struct btrfs_fs_info *fs_info,
        atomic_set(&root->log_writers, 0);
        atomic_set(&root->log_batch, 0);
        atomic_set(&root->orphan_inodes, 0);
-       atomic_set(&root->refs, 1);
+       refcount_set(&root->refs, 1);
        atomic_set(&root->will_be_snapshoted, 0);
        atomic64_set(&root->qgroup_meta_rsv, 0);
        root->log_transid = 0;
@@ -3497,10 +3497,11 @@ static void btrfs_end_empty_barrier(struct bio *bio)
  */
 static int write_dev_flush(struct btrfs_device *device, int wait)
 {
+       struct request_queue *q = bdev_get_queue(device->bdev);
        struct bio *bio;
        int ret = 0;
 
-       if (device->nobarriers)
+       if (!test_bit(QUEUE_FLAG_WC, &q->queue_flags))
                return 0;
 
        if (wait) {
@@ -4321,7 +4322,7 @@ static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans,
                head = rb_entry(node, struct btrfs_delayed_ref_head,
                                href_node);
                if (!mutex_trylock(&head->mutex)) {
-                       atomic_inc(&head->node.refs);
+                       refcount_inc(&head->node.refs);
                        spin_unlock(&delayed_refs->lock);
 
                        mutex_lock(&head->mutex);
@@ -4593,7 +4594,7 @@ static int btrfs_cleanup_transaction(struct btrfs_fs_info *fs_info)
                t = list_first_entry(&fs_info->trans_list,
                                     struct btrfs_transaction, list);
                if (t->state >= TRANS_STATE_COMMIT_START) {
-                       atomic_inc(&t->use_count);
+                       refcount_inc(&t->use_count);
                        spin_unlock(&fs_info->trans_lock);
                        btrfs_wait_for_commit(fs_info, t->transid);
                        btrfs_put_transaction(t);
index 2e0ec29bfd69f04b4232b75754010594bd3d5f95..21f1ceb85b76737a67c1ffbc02cbd725b09fb510 100644 (file)
@@ -101,14 +101,14 @@ struct btrfs_root *btrfs_alloc_dummy_root(struct btrfs_fs_info *fs_info);
  */
 static inline struct btrfs_root *btrfs_grab_fs_root(struct btrfs_root *root)
 {
-       if (atomic_inc_not_zero(&root->refs))
+       if (refcount_inc_not_zero(&root->refs))
                return root;
        return NULL;
 }
 
 static inline void btrfs_put_fs_root(struct btrfs_root *root)
 {
-       if (atomic_dec_and_test(&root->refs))
+       if (refcount_dec_and_test(&root->refs))
                kfree(root);
 }
 
index be5477676cc829e4efe89349fc9b7df540fd0dff..e390451c72e6cdb93492e519cea82d5d7b3dfaf9 100644 (file)
@@ -131,6 +131,16 @@ void btrfs_put_block_group(struct btrfs_block_group_cache *cache)
        if (atomic_dec_and_test(&cache->count)) {
                WARN_ON(cache->pinned > 0);
                WARN_ON(cache->reserved > 0);
+
+               /*
+                * If not empty, someone is still holding mutex of
+                * full_stripe_lock, which can only be released by caller.
+                * And it will definitely cause use-after-free when caller
+                * tries to release full stripe lock.
+                *
+                * No better way to resolve, but only to warn.
+                */
+               WARN_ON(!RB_EMPTY_ROOT(&cache->full_stripe_locks_root.root));
                kfree(cache->free_space_ctl);
                kfree(cache);
        }
@@ -316,14 +326,14 @@ get_caching_control(struct btrfs_block_group_cache *cache)
        }
 
        ctl = cache->caching_ctl;
-       atomic_inc(&ctl->count);
+       refcount_inc(&ctl->count);
        spin_unlock(&cache->lock);
        return ctl;
 }
 
 static void put_caching_control(struct btrfs_caching_control *ctl)
 {
-       if (atomic_dec_and_test(&ctl->count))
+       if (refcount_dec_and_test(&ctl->count))
                kfree(ctl);
 }
 
@@ -599,7 +609,7 @@ static int cache_block_group(struct btrfs_block_group_cache *cache,
        init_waitqueue_head(&caching_ctl->wait);
        caching_ctl->block_group = cache;
        caching_ctl->progress = cache->key.objectid;
-       atomic_set(&caching_ctl->count, 1);
+       refcount_set(&caching_ctl->count, 1);
        btrfs_init_work(&caching_ctl->work, btrfs_cache_helper,
                        caching_thread, NULL, NULL);
 
@@ -620,7 +630,7 @@ static int cache_block_group(struct btrfs_block_group_cache *cache,
                struct btrfs_caching_control *ctl;
 
                ctl = cache->caching_ctl;
-               atomic_inc(&ctl->count);
+               refcount_inc(&ctl->count);
                prepare_to_wait(&ctl->wait, &wait, TASK_UNINTERRUPTIBLE);
                spin_unlock(&cache->lock);
 
@@ -707,7 +717,7 @@ static int cache_block_group(struct btrfs_block_group_cache *cache,
        }
 
        down_write(&fs_info->commit_root_sem);
-       atomic_inc(&caching_ctl->count);
+       refcount_inc(&caching_ctl->count);
        list_add_tail(&caching_ctl->list, &fs_info->caching_block_groups);
        up_write(&fs_info->commit_root_sem);
 
@@ -892,7 +902,7 @@ search_again:
        head = btrfs_find_delayed_ref_head(delayed_refs, bytenr);
        if (head) {
                if (!mutex_trylock(&head->mutex)) {
-                       atomic_inc(&head->node.refs);
+                       refcount_inc(&head->node.refs);
                        spin_unlock(&delayed_refs->lock);
 
                        btrfs_release_path(path);
@@ -2980,7 +2990,7 @@ again:
                                struct btrfs_delayed_ref_node *ref;
 
                                ref = &head->node;
-                               atomic_inc(&ref->refs);
+                               refcount_inc(&ref->refs);
 
                                spin_unlock(&delayed_refs->lock);
                                /*
@@ -3003,7 +3013,6 @@ again:
                goto again;
        }
 out:
-       assert_qgroups_uptodate(trans);
        trans->can_flush_pending_bgs = can_flush_pending_bgs;
        return 0;
 }
@@ -3057,7 +3066,7 @@ static noinline int check_delayed_ref(struct btrfs_root *root,
        }
 
        if (!mutex_trylock(&head->mutex)) {
-               atomic_inc(&head->node.refs);
+               refcount_inc(&head->node.refs);
                spin_unlock(&delayed_refs->lock);
 
                btrfs_release_path(path);
@@ -3443,7 +3452,8 @@ again:
                /*
                 * don't bother trying to write stuff out _if_
                 * a) we're not cached,
-                * b) we're with nospace_cache mount option.
+                * b) we're with nospace_cache mount option,
+                * c) we're with v2 space_cache (FREE_SPACE_TREE).
                 */
                dcs = BTRFS_DC_WRITTEN;
                spin_unlock(&block_group->lock);
@@ -9917,6 +9927,7 @@ btrfs_create_block_group_cache(struct btrfs_fs_info *fs_info,
        btrfs_init_free_space_ctl(cache);
        atomic_set(&cache->trimming, 0);
        mutex_init(&cache->free_space_lock);
+       btrfs_init_full_stripe_locks_tree(&cache->full_stripe_locks_root);
 
        return cache;
 }
@@ -10416,7 +10427,7 @@ int btrfs_remove_block_group(struct btrfs_trans_handle *trans,
                                    &fs_info->caching_block_groups, list)
                                if (ctl->block_group == block_group) {
                                        caching_ctl = ctl;
-                                       atomic_inc(&caching_ctl->count);
+                                       refcount_inc(&caching_ctl->count);
                                        break;
                                }
                }
@@ -10850,7 +10861,7 @@ static int btrfs_trim_free_extents(struct btrfs_device *device,
                spin_lock(&fs_info->trans_lock);
                trans = fs_info->running_transaction;
                if (trans)
-                       atomic_inc(&trans->use_count);
+                       refcount_inc(&trans->use_count);
                spin_unlock(&fs_info->trans_lock);
 
                ret = find_free_dev_extent_start(trans, device, minlen, start,
index 27fdb250b4467f65a8c6a42d06835f3bb3a36aec..d8da3edf2ac39ebcc0bde0ede7da74f0f81ad9ea 100644 (file)
@@ -68,7 +68,7 @@ void btrfs_leak_debug_check(void)
                pr_err("BTRFS: state leak: start %llu end %llu state %u in tree %d refs %d\n",
                       state->start, state->end, state->state,
                       extent_state_in_tree(state),
-                      atomic_read(&state->refs));
+                      refcount_read(&state->refs));
                list_del(&state->leak_list);
                kmem_cache_free(extent_state_cache, state);
        }
@@ -238,7 +238,7 @@ static struct extent_state *alloc_extent_state(gfp_t mask)
        state->failrec = NULL;
        RB_CLEAR_NODE(&state->rb_node);
        btrfs_leak_debug_add(&state->leak_list, &states);
-       atomic_set(&state->refs, 1);
+       refcount_set(&state->refs, 1);
        init_waitqueue_head(&state->wq);
        trace_alloc_extent_state(state, mask, _RET_IP_);
        return state;
@@ -248,7 +248,7 @@ void free_extent_state(struct extent_state *state)
 {
        if (!state)
                return;
-       if (atomic_dec_and_test(&state->refs)) {
+       if (refcount_dec_and_test(&state->refs)) {
                WARN_ON(extent_state_in_tree(state));
                btrfs_leak_debug_del(&state->leak_list);
                trace_free_extent_state(state, _RET_IP_);
@@ -641,7 +641,7 @@ again:
                if (cached && extent_state_in_tree(cached) &&
                    cached->start <= start && cached->end > start) {
                        if (clear)
-                               atomic_dec(&cached->refs);
+                               refcount_dec(&cached->refs);
                        state = cached;
                        goto hit_next;
                }
@@ -793,7 +793,7 @@ process_node:
 
                if (state->state & bits) {
                        start = state->start;
-                       atomic_inc(&state->refs);
+                       refcount_inc(&state->refs);
                        wait_on_state(tree, state);
                        free_extent_state(state);
                        goto again;
@@ -834,7 +834,7 @@ static void cache_state_if_flags(struct extent_state *state,
        if (cached_ptr && !(*cached_ptr)) {
                if (!flags || (state->state & flags)) {
                        *cached_ptr = state;
-                       atomic_inc(&state->refs);
+                       refcount_inc(&state->refs);
                }
        }
 }
@@ -1538,7 +1538,7 @@ static noinline u64 find_delalloc_range(struct extent_io_tree *tree,
                if (!found) {
                        *start = state->start;
                        *cached_state = state;
-                       atomic_inc(&state->refs);
+                       refcount_inc(&state->refs);
                }
                found++;
                *end = state->end;
@@ -2004,16 +2004,11 @@ int repair_io_failure(struct btrfs_inode *inode, u64 start, u64 length,
        u64 map_length = 0;
        u64 sector;
        struct btrfs_bio *bbio = NULL;
-       struct btrfs_mapping_tree *map_tree = &fs_info->mapping_tree;
        int ret;
 
        ASSERT(!(fs_info->sb->s_flags & MS_RDONLY));
        BUG_ON(!mirror_num);
 
-       /* we can't repair anything in raid56 yet */
-       if (btrfs_is_parity_mirror(map_tree, logical, length, mirror_num))
-               return 0;
-
        bio = btrfs_io_bio_alloc(GFP_NOFS, 1);
        if (!bio)
                return -EIO;
@@ -2026,17 +2021,35 @@ int repair_io_failure(struct btrfs_inode *inode, u64 start, u64 length,
         * read repair operation.
         */
        btrfs_bio_counter_inc_blocked(fs_info);
-       ret = btrfs_map_block(fs_info, BTRFS_MAP_WRITE, logical,
-                             &map_length, &bbio, mirror_num);
-       if (ret) {
-               btrfs_bio_counter_dec(fs_info);
-               bio_put(bio);
-               return -EIO;
+       if (btrfs_is_parity_mirror(fs_info, logical, length, mirror_num)) {
+               /*
+                * Note that we don't use BTRFS_MAP_WRITE because it's supposed
+                * to update all raid stripes, but here we just want to correct
+                * bad stripe, thus BTRFS_MAP_READ is abused to only get the bad
+                * stripe's dev and sector.
+                */
+               ret = btrfs_map_block(fs_info, BTRFS_MAP_READ, logical,
+                                     &map_length, &bbio, 0);
+               if (ret) {
+                       btrfs_bio_counter_dec(fs_info);
+                       bio_put(bio);
+                       return -EIO;
+               }
+               ASSERT(bbio->mirror_num == 1);
+       } else {
+               ret = btrfs_map_block(fs_info, BTRFS_MAP_WRITE, logical,
+                                     &map_length, &bbio, mirror_num);
+               if (ret) {
+                       btrfs_bio_counter_dec(fs_info);
+                       bio_put(bio);
+                       return -EIO;
+               }
+               BUG_ON(mirror_num != bbio->mirror_num);
        }
-       BUG_ON(mirror_num != bbio->mirror_num);
-       sector = bbio->stripes[mirror_num-1].physical >> 9;
+
+       sector = bbio->stripes[bbio->mirror_num - 1].physical >> 9;
        bio->bi_iter.bi_sector = sector;
-       dev = bbio->stripes[mirror_num-1].dev;
+       dev = bbio->stripes[bbio->mirror_num - 1].dev;
        btrfs_put_bbio(bbio);
        if (!dev || !dev->bdev || !dev->writeable) {
                btrfs_bio_counter_dec(fs_info);
@@ -2859,7 +2872,7 @@ __get_extent_map(struct inode *inode, struct page *page, size_t pg_offset,
                em = *em_cached;
                if (extent_map_in_tree(em) && start >= em->start &&
                    start < extent_map_end(em)) {
-                       atomic_inc(&em->refs);
+                       refcount_inc(&em->refs);
                        return em;
                }
 
@@ -2870,7 +2883,7 @@ __get_extent_map(struct inode *inode, struct page *page, size_t pg_offset,
        em = get_extent(BTRFS_I(inode), page, pg_offset, start, len, 0);
        if (em_cached && !IS_ERR_OR_NULL(em)) {
                BUG_ON(*em_cached);
-               atomic_inc(&em->refs);
+               refcount_inc(&em->refs);
                *em_cached = em;
        }
        return em;
index 3e4fad4a909d110d9283f979ccb9dec9a48c607c..1eafa2f0ede370ae802bb882557b3d4ad5c26340 100644 (file)
@@ -2,6 +2,7 @@
 #define __EXTENTIO__
 
 #include <linux/rbtree.h>
+#include <linux/refcount.h>
 #include "ulist.h"
 
 /* bits for the extent state */
 #define EXTENT_DEFRAG          (1U << 6)
 #define EXTENT_BOUNDARY                (1U << 9)
 #define EXTENT_NODATASUM       (1U << 10)
-#define EXTENT_DO_ACCOUNTING   (1U << 11)
+#define EXTENT_CLEAR_META_RESV (1U << 11)
 #define EXTENT_FIRST_DELALLOC  (1U << 12)
 #define EXTENT_NEED_WAIT       (1U << 13)
 #define EXTENT_DAMAGED         (1U << 14)
 #define EXTENT_NORESERVE       (1U << 15)
 #define EXTENT_QGROUP_RESERVED (1U << 16)
 #define EXTENT_CLEAR_DATA_RESV (1U << 17)
+#define EXTENT_DELALLOC_NEW    (1U << 18)
 #define EXTENT_IOBITS          (EXTENT_LOCKED | EXTENT_WRITEBACK)
+#define EXTENT_DO_ACCOUNTING    (EXTENT_CLEAR_META_RESV | \
+                                EXTENT_CLEAR_DATA_RESV)
 #define EXTENT_CTLBITS         (EXTENT_DO_ACCOUNTING | EXTENT_FIRST_DELALLOC)
 
 /*
@@ -143,7 +147,7 @@ struct extent_state {
 
        /* ADD NEW ELEMENTS AFTER THIS */
        wait_queue_head_t wq;
-       atomic_t refs;
+       refcount_t refs;
        unsigned state;
 
        struct io_failure_record *failrec;
index 26f9ac719d20b4bff1a6b0a456ca45dd1752b4c7..69850155870c067d82768c67f3895a2e7a7c487d 100644 (file)
@@ -55,7 +55,7 @@ struct extent_map *alloc_extent_map(void)
        em->flags = 0;
        em->compress_type = BTRFS_COMPRESS_NONE;
        em->generation = 0;
-       atomic_set(&em->refs, 1);
+       refcount_set(&em->refs, 1);
        INIT_LIST_HEAD(&em->list);
        return em;
 }
@@ -71,8 +71,8 @@ void free_extent_map(struct extent_map *em)
 {
        if (!em)
                return;
-       WARN_ON(atomic_read(&em->refs) == 0);
-       if (atomic_dec_and_test(&em->refs)) {
+       WARN_ON(refcount_read(&em->refs) == 0);
+       if (refcount_dec_and_test(&em->refs)) {
                WARN_ON(extent_map_in_tree(em));
                WARN_ON(!list_empty(&em->list));
                if (test_bit(EXTENT_FLAG_FS_MAPPING, &em->flags))
@@ -322,7 +322,7 @@ static inline void setup_extent_mapping(struct extent_map_tree *tree,
                                        struct extent_map *em,
                                        int modified)
 {
-       atomic_inc(&em->refs);
+       refcount_inc(&em->refs);
        em->mod_start = em->start;
        em->mod_len = em->len;
 
@@ -381,7 +381,7 @@ __lookup_extent_mapping(struct extent_map_tree *tree,
        if (strict && !(end > em->start && start < extent_map_end(em)))
                return NULL;
 
-       atomic_inc(&em->refs);
+       refcount_inc(&em->refs);
        return em;
 }
 
index eb8b8fae036bc3c67ceea03220cdca503626546f..a67b2def54131f10326c71092f80f2cd2d706212 100644 (file)
@@ -2,6 +2,7 @@
 #define __EXTENTMAP__
 
 #include <linux/rbtree.h>
+#include <linux/refcount.h>
 
 #define EXTENT_MAP_LAST_BYTE ((u64)-4)
 #define EXTENT_MAP_HOLE ((u64)-3)
@@ -41,7 +42,7 @@ struct extent_map {
                 */
                struct map_lookup *map_lookup;
        };
-       atomic_t refs;
+       refcount_t refs;
        unsigned int compress_type;
        struct list_head list;
 };
index 520cb7230b2d2cb5ca798c0030fa446957799456..da1096eb1a406f648b1bb0c7f3ee1da0e3013646 100644 (file)
@@ -1404,6 +1404,47 @@ fail:
 
 }
 
+static int btrfs_find_new_delalloc_bytes(struct btrfs_inode *inode,
+                                        const u64 start,
+                                        const u64 len,
+                                        struct extent_state **cached_state)
+{
+       u64 search_start = start;
+       const u64 end = start + len - 1;
+
+       while (search_start < end) {
+               const u64 search_len = end - search_start + 1;
+               struct extent_map *em;
+               u64 em_len;
+               int ret = 0;
+
+               em = btrfs_get_extent(inode, NULL, 0, search_start,
+                                     search_len, 0);
+               if (IS_ERR(em))
+                       return PTR_ERR(em);
+
+               if (em->block_start != EXTENT_MAP_HOLE)
+                       goto next;
+
+               em_len = em->len;
+               if (em->start < search_start)
+                       em_len -= search_start - em->start;
+               if (em_len > search_len)
+                       em_len = search_len;
+
+               ret = set_extent_bit(&inode->io_tree, search_start,
+                                    search_start + em_len - 1,
+                                    EXTENT_DELALLOC_NEW,
+                                    NULL, cached_state, GFP_NOFS);
+next:
+               search_start = extent_map_end(em);
+               free_extent_map(em);
+               if (ret)
+                       return ret;
+       }
+       return 0;
+}
+
 /*
  * This function locks the extent and properly waits for data=ordered extents
  * to finish before allowing the pages to be modified if need.
@@ -1432,8 +1473,11 @@ lock_and_cleanup_extent_if_need(struct btrfs_inode *inode, struct page **pages,
                + round_up(pos + write_bytes - start_pos,
                           fs_info->sectorsize) - 1;
 
-       if (start_pos < inode->vfs_inode.i_size) {
+       if (start_pos < inode->vfs_inode.i_size ||
+           (inode->flags & BTRFS_INODE_PREALLOC)) {
                struct btrfs_ordered_extent *ordered;
+               unsigned int clear_bits;
+
                lock_extent_bits(&inode->io_tree, start_pos, last_pos,
                                cached_state);
                ordered = btrfs_lookup_ordered_range(inode, start_pos,
@@ -1454,11 +1498,19 @@ lock_and_cleanup_extent_if_need(struct btrfs_inode *inode, struct page **pages,
                }
                if (ordered)
                        btrfs_put_ordered_extent(ordered);
-
+               ret = btrfs_find_new_delalloc_bytes(inode, start_pos,
+                                                   last_pos - start_pos + 1,
+                                                   cached_state);
+               clear_bits = EXTENT_DIRTY | EXTENT_DELALLOC |
+                       EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG;
+               if (ret)
+                       clear_bits |= EXTENT_DELALLOC_NEW | EXTENT_LOCKED;
                clear_extent_bit(&inode->io_tree, start_pos,
-                                 last_pos, EXTENT_DIRTY | EXTENT_DELALLOC |
-                                 EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG,
-                                 0, 0, cached_state, GFP_NOFS);
+                                last_pos, clear_bits,
+                                (clear_bits & EXTENT_LOCKED) ? 1 : 0,
+                                0, cached_state, GFP_NOFS);
+               if (ret)
+                       return ret;
                *lockstart = start_pos;
                *lockend = last_pos;
                ret = 1;
@@ -2342,13 +2394,8 @@ static int find_first_non_hole(struct inode *inode, u64 *start, u64 *len)
        int ret = 0;
 
        em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, *start, *len, 0);
-       if (IS_ERR_OR_NULL(em)) {
-               if (!em)
-                       ret = -ENOMEM;
-               else
-                       ret = PTR_ERR(em);
-               return ret;
-       }
+       if (IS_ERR(em))
+               return PTR_ERR(em);
 
        /* Hole or vacuum extent(only exists in no-hole mode) */
        if (em->block_start == EXTENT_MAP_HOLE) {
@@ -2835,11 +2882,8 @@ static long btrfs_fallocate(struct file *file, int mode,
        while (1) {
                em = btrfs_get_extent(BTRFS_I(inode), NULL, 0, cur_offset,
                                      alloc_end - cur_offset, 0);
-               if (IS_ERR_OR_NULL(em)) {
-                       if (!em)
-                               ret = -ENOMEM;
-                       else
-                               ret = PTR_ERR(em);
+               if (IS_ERR(em)) {
+                       ret = PTR_ERR(em);
                        break;
                }
                last_byte = min(extent_map_end(em), alloc_end);
@@ -2856,8 +2900,10 @@ static long btrfs_fallocate(struct file *file, int mode,
                        }
                        ret = btrfs_qgroup_reserve_data(inode, cur_offset,
                                        last_byte - cur_offset);
-                       if (ret < 0)
+                       if (ret < 0) {
+                               free_extent_map(em);
                                break;
+                       }
                } else {
                        /*
                         * Do not need to reserve unwritten extent for this
index da6841efac26b1be3509ad3e410c34e72b253a65..c5e6180cdb8c9250e3a525e311a42795c4831c32 100644 (file)
@@ -355,7 +355,7 @@ static void io_ctl_map_page(struct btrfs_io_ctl *io_ctl, int clear)
        io_ctl->orig = io_ctl->cur;
        io_ctl->size = PAGE_SIZE;
        if (clear)
-               memset(io_ctl->cur, 0, PAGE_SIZE);
+               clear_page(io_ctl->cur);
 }
 
 static void io_ctl_drop_pages(struct btrfs_io_ctl *io_ctl)
index dd7fb22a955a6bff32be4632053bcd9086efe6e2..fc0bd84067582523b958db030a3439d1088f5832 100644 (file)
@@ -167,8 +167,7 @@ static u8 *alloc_bitmap(u32 bitmap_size)
        if (mem)
                return mem;
 
-       return __vmalloc(bitmap_size, GFP_NOFS | __GFP_HIGHMEM | __GFP_ZERO,
-                        PAGE_KERNEL);
+       return __vmalloc(bitmap_size, GFP_NOFS | __GFP_ZERO, PAGE_KERNEL);
 }
 
 int convert_free_space_to_bitmaps(struct btrfs_trans_handle *trans,
index 5e71f1ea3391b034dc8e6f55f62d82dbe76e9811..17cbe9306fafd9b9e7247bec4308494ed770b28b 100644 (file)
@@ -115,6 +115,31 @@ static struct extent_map *create_io_em(struct inode *inode, u64 start, u64 len,
                                       u64 ram_bytes, int compress_type,
                                       int type);
 
+static void __endio_write_update_ordered(struct inode *inode,
+                                        const u64 offset, const u64 bytes,
+                                        const bool uptodate);
+
+/*
+ * Cleanup all submitted ordered extents in specified range to handle errors
+ * from the fill_dellaloc() callback.
+ *
+ * NOTE: caller must ensure that when an error happens, it can not call
+ * extent_clear_unlock_delalloc() to clear both the bits EXTENT_DO_ACCOUNTING
+ * and EXTENT_DELALLOC simultaneously, because that causes the reserved metadata
+ * to be released, which we want to happen only when finishing the ordered
+ * extent (btrfs_finish_ordered_io()). Also note that the caller of the
+ * fill_delalloc() callback already does proper cleanup for the first page of
+ * the range, that is, it invokes the callback writepage_end_io_hook() for the
+ * range of the first page.
+ */
+static inline void btrfs_cleanup_ordered_extents(struct inode *inode,
+                                                const u64 offset,
+                                                const u64 bytes)
+{
+       return __endio_write_update_ordered(inode, offset + PAGE_SIZE,
+                                           bytes - PAGE_SIZE, false);
+}
+
 static int btrfs_dirty_inode(struct inode *inode);
 
 #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
@@ -547,7 +572,7 @@ cont:
                }
                if (ret <= 0) {
                        unsigned long clear_flags = EXTENT_DELALLOC |
-                               EXTENT_DEFRAG;
+                               EXTENT_DELALLOC_NEW | EXTENT_DEFRAG;
                        unsigned long page_error_op;
 
                        clear_flags |= (ret < 0) ? EXTENT_DO_ACCOUNTING : 0;
@@ -565,8 +590,10 @@ cont:
                                                     PAGE_SET_WRITEBACK |
                                                     page_error_op |
                                                     PAGE_END_WRITEBACK);
-                       btrfs_free_reserved_data_space_noquota(inode, start,
-                                               end - start + 1);
+                       if (ret == 0)
+                               btrfs_free_reserved_data_space_noquota(inode,
+                                                              start,
+                                                              end - start + 1);
                        goto free_pages_out;
                }
        }
@@ -852,6 +879,7 @@ out_free:
                                     async_extent->start +
                                     async_extent->ram_size - 1,
                                     NULL, EXTENT_LOCKED | EXTENT_DELALLOC |
+                                    EXTENT_DELALLOC_NEW |
                                     EXTENT_DEFRAG | EXTENT_DO_ACCOUNTING,
                                     PAGE_UNLOCK | PAGE_CLEAR_DIRTY |
                                     PAGE_SET_WRITEBACK | PAGE_END_WRITEBACK |
@@ -918,10 +946,13 @@ static noinline int cow_file_range(struct inode *inode,
        u64 num_bytes;
        unsigned long ram_size;
        u64 disk_num_bytes;
-       u64 cur_alloc_size;
+       u64 cur_alloc_size = 0;
        u64 blocksize = fs_info->sectorsize;
        struct btrfs_key ins;
        struct extent_map *em;
+       unsigned clear_bits;
+       unsigned long page_ops;
+       bool extent_reserved = false;
        int ret = 0;
 
        if (btrfs_is_free_space_inode(BTRFS_I(inode))) {
@@ -944,6 +975,7 @@ static noinline int cow_file_range(struct inode *inode,
                        extent_clear_unlock_delalloc(inode, start, end,
                                     delalloc_end, NULL,
                                     EXTENT_LOCKED | EXTENT_DELALLOC |
+                                    EXTENT_DELALLOC_NEW |
                                     EXTENT_DEFRAG, PAGE_UNLOCK |
                                     PAGE_CLEAR_DIRTY | PAGE_SET_WRITEBACK |
                                     PAGE_END_WRITEBACK);
@@ -966,14 +998,14 @@ static noinline int cow_file_range(struct inode *inode,
                        start + num_bytes - 1, 0);
 
        while (disk_num_bytes > 0) {
-               unsigned long op;
-
                cur_alloc_size = disk_num_bytes;
                ret = btrfs_reserve_extent(root, cur_alloc_size, cur_alloc_size,
                                           fs_info->sectorsize, 0, alloc_hint,
                                           &ins, 1, 1);
                if (ret < 0)
                        goto out_unlock;
+               cur_alloc_size = ins.offset;
+               extent_reserved = true;
 
                ram_size = ins.offset;
                em = create_io_em(inode, start, ins.offset, /* len */
@@ -988,7 +1020,6 @@ static noinline int cow_file_range(struct inode *inode,
                        goto out_reserve;
                free_extent_map(em);
 
-               cur_alloc_size = ins.offset;
                ret = btrfs_add_ordered_extent(inode, start, ins.objectid,
                                               ram_size, cur_alloc_size, 0);
                if (ret)
@@ -998,15 +1029,24 @@ static noinline int cow_file_range(struct inode *inode,
                    BTRFS_DATA_RELOC_TREE_OBJECTID) {
                        ret = btrfs_reloc_clone_csums(inode, start,
                                                      cur_alloc_size);
+                       /*
+                        * Only drop cache here, and process as normal.
+                        *
+                        * We must not allow extent_clear_unlock_delalloc()
+                        * at out_unlock label to free meta of this ordered
+                        * extent, as its meta should be freed by
+                        * btrfs_finish_ordered_io().
+                        *
+                        * So we must continue until @start is increased to
+                        * skip current ordered extent.
+                        */
                        if (ret)
-                               goto out_drop_extent_cache;
+                               btrfs_drop_extent_cache(BTRFS_I(inode), start,
+                                               start + ram_size - 1, 0);
                }
 
                btrfs_dec_block_group_reservations(fs_info, ins.objectid);
 
-               if (disk_num_bytes < cur_alloc_size)
-                       break;
-
                /* we're not doing compressed IO, don't unlock the first
                 * page (which the caller expects to stay locked), don't
                 * clear any dirty bits and don't set any writeback bits
@@ -1014,18 +1054,30 @@ static noinline int cow_file_range(struct inode *inode,
                 * Do set the Private2 bit so we know this page was properly
                 * setup for writepage
                 */
-               op = unlock ? PAGE_UNLOCK : 0;
-               op |= PAGE_SET_PRIVATE2;
+               page_ops = unlock ? PAGE_UNLOCK : 0;
+               page_ops |= PAGE_SET_PRIVATE2;
 
                extent_clear_unlock_delalloc(inode, start,
                                             start + ram_size - 1,
                                             delalloc_end, locked_page,
                                             EXTENT_LOCKED | EXTENT_DELALLOC,
-                                            op);
-               disk_num_bytes -= cur_alloc_size;
+                                            page_ops);
+               if (disk_num_bytes < cur_alloc_size)
+                       disk_num_bytes = 0;
+               else
+                       disk_num_bytes -= cur_alloc_size;
                num_bytes -= cur_alloc_size;
                alloc_hint = ins.objectid + ins.offset;
                start += cur_alloc_size;
+               extent_reserved = false;
+
+               /*
+                * btrfs_reloc_clone_csums() error, since start is increased
+                * extent_clear_unlock_delalloc() at out_unlock label won't
+                * free metadata of current ordered extent, we're OK to exit.
+                */
+               if (ret)
+                       goto out_unlock;
        }
 out:
        return ret;
@@ -1036,12 +1088,35 @@ out_reserve:
        btrfs_dec_block_group_reservations(fs_info, ins.objectid);
        btrfs_free_reserved_extent(fs_info, ins.objectid, ins.offset, 1);
 out_unlock:
+       clear_bits = EXTENT_LOCKED | EXTENT_DELALLOC | EXTENT_DELALLOC_NEW |
+               EXTENT_DEFRAG | EXTENT_CLEAR_META_RESV;
+       page_ops = PAGE_UNLOCK | PAGE_CLEAR_DIRTY | PAGE_SET_WRITEBACK |
+               PAGE_END_WRITEBACK;
+       /*
+        * If we reserved an extent for our delalloc range (or a subrange) and
+        * failed to create the respective ordered extent, then it means that
+        * when we reserved the extent we decremented the extent's size from
+        * the data space_info's bytes_may_use counter and incremented the
+        * space_info's bytes_reserved counter by the same amount. We must make
+        * sure extent_clear_unlock_delalloc() does not try to decrement again
+        * the data space_info's bytes_may_use counter, therefore we do not pass
+        * it the flag EXTENT_CLEAR_DATA_RESV.
+        */
+       if (extent_reserved) {
+               extent_clear_unlock_delalloc(inode, start,
+                                            start + cur_alloc_size,
+                                            start + cur_alloc_size,
+                                            locked_page,
+                                            clear_bits,
+                                            page_ops);
+               start += cur_alloc_size;
+               if (start >= end)
+                       goto out;
+       }
        extent_clear_unlock_delalloc(inode, start, end, delalloc_end,
                                     locked_page,
-                                    EXTENT_LOCKED | EXTENT_DO_ACCOUNTING |
-                                    EXTENT_DELALLOC | EXTENT_DEFRAG,
-                                    PAGE_UNLOCK | PAGE_CLEAR_DIRTY |
-                                    PAGE_SET_WRITEBACK | PAGE_END_WRITEBACK);
+                                    clear_bits | EXTENT_CLEAR_DATA_RESV,
+                                    page_ops);
        goto out;
 }
 
@@ -1414,15 +1489,14 @@ out_check:
                BUG_ON(ret); /* -ENOMEM */
 
                if (root->root_key.objectid ==
-                   BTRFS_DATA_RELOC_TREE_OBJECTID) {
+                   BTRFS_DATA_RELOC_TREE_OBJECTID)
+                       /*
+                        * Error handled later, as we must prevent
+                        * extent_clear_unlock_delalloc() in error handler
+                        * from freeing metadata of created ordered extent.
+                        */
                        ret = btrfs_reloc_clone_csums(inode, cur_offset,
                                                      num_bytes);
-                       if (ret) {
-                               if (!nolock && nocow)
-                                       btrfs_end_write_no_snapshoting(root);
-                               goto error;
-                       }
-               }
 
                extent_clear_unlock_delalloc(inode, cur_offset,
                                             cur_offset + num_bytes - 1, end,
@@ -1434,6 +1508,14 @@ out_check:
                if (!nolock && nocow)
                        btrfs_end_write_no_snapshoting(root);
                cur_offset = extent_end;
+
+               /*
+                * btrfs_reloc_clone_csums() error, now we're OK to call error
+                * handler, as metadata for created ordered extent will only
+                * be freed by btrfs_finish_ordered_io().
+                */
+               if (ret)
+                       goto error;
                if (cur_offset > end)
                        break;
        }
@@ -1509,6 +1591,8 @@ static int run_delalloc_range(struct inode *inode, struct page *locked_page,
                ret = cow_file_range_async(inode, locked_page, start, end,
                                           page_started, nr_written);
        }
+       if (ret)
+               btrfs_cleanup_ordered_extents(inode, start, end - start + 1);
        return ret;
 }
 
@@ -1693,6 +1777,14 @@ static void btrfs_set_bit_hook(struct inode *inode,
                        btrfs_add_delalloc_inodes(root, inode);
                spin_unlock(&BTRFS_I(inode)->lock);
        }
+
+       if (!(state->state & EXTENT_DELALLOC_NEW) &&
+           (*bits & EXTENT_DELALLOC_NEW)) {
+               spin_lock(&BTRFS_I(inode)->lock);
+               BTRFS_I(inode)->new_delalloc_bytes += state->end + 1 -
+                       state->start;
+               spin_unlock(&BTRFS_I(inode)->lock);
+       }
 }
 
 /*
@@ -1722,7 +1814,7 @@ static void btrfs_clear_bit_hook(struct btrfs_inode *inode,
 
                if (*bits & EXTENT_FIRST_DELALLOC) {
                        *bits &= ~EXTENT_FIRST_DELALLOC;
-               } else if (!(*bits & EXTENT_DO_ACCOUNTING)) {
+               } else if (!(*bits & EXTENT_CLEAR_META_RESV)) {
                        spin_lock(&inode->lock);
                        inode->outstanding_extents -= num_extents;
                        spin_unlock(&inode->lock);
@@ -1733,7 +1825,7 @@ static void btrfs_clear_bit_hook(struct btrfs_inode *inode,
                 * don't need to call dellalloc_release_metadata if there is an
                 * error.
                 */
-               if (*bits & EXTENT_DO_ACCOUNTING &&
+               if (*bits & EXTENT_CLEAR_META_RESV &&
                    root != fs_info->tree_root)
                        btrfs_delalloc_release_metadata(inode, len);
 
@@ -1741,10 +1833,9 @@ static void btrfs_clear_bit_hook(struct btrfs_inode *inode,
                if (btrfs_is_testing(fs_info))
                        return;
 
-               if (root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID
-                   && do_list && !(state->state & EXTENT_NORESERVE)
-                   && (*bits & (EXTENT_DO_ACCOUNTING |
-                   EXTENT_CLEAR_DATA_RESV)))
+               if (root->root_key.objectid != BTRFS_DATA_RELOC_TREE_OBJECTID &&
+                   do_list && !(state->state & EXTENT_NORESERVE) &&
+                   (*bits & EXTENT_CLEAR_DATA_RESV))
                        btrfs_free_reserved_data_space_noquota(
                                        &inode->vfs_inode,
                                        state->start, len);
@@ -1759,6 +1850,14 @@ static void btrfs_clear_bit_hook(struct btrfs_inode *inode,
                        btrfs_del_delalloc_inode(root, inode);
                spin_unlock(&inode->lock);
        }
+
+       if ((state->state & EXTENT_DELALLOC_NEW) &&
+           (*bits & EXTENT_DELALLOC_NEW)) {
+               spin_lock(&inode->lock);
+               ASSERT(inode->new_delalloc_bytes >= len);
+               inode->new_delalloc_bytes -= len;
+               spin_unlock(&inode->lock);
+       }
 }
 
 /*
@@ -2791,6 +2890,13 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
        u64 logical_len = ordered_extent->len;
        bool nolock;
        bool truncated = false;
+       bool range_locked = false;
+       bool clear_new_delalloc_bytes = false;
+
+       if (!test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags) &&
+           !test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags) &&
+           !test_bit(BTRFS_ORDERED_DIRECT, &ordered_extent->flags))
+               clear_new_delalloc_bytes = true;
 
        nolock = btrfs_is_free_space_inode(BTRFS_I(inode));
 
@@ -2839,6 +2945,7 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
                goto out;
        }
 
+       range_locked = true;
        lock_extent_bits(io_tree, ordered_extent->file_offset,
                         ordered_extent->file_offset + ordered_extent->len - 1,
                         &cached_state);
@@ -2864,7 +2971,7 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
        if (IS_ERR(trans)) {
                ret = PTR_ERR(trans);
                trans = NULL;
-               goto out_unlock;
+               goto out;
        }
 
        trans->block_rsv = &fs_info->delalloc_block_rsv;
@@ -2896,7 +3003,7 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
                           trans->transid);
        if (ret < 0) {
                btrfs_abort_transaction(trans, ret);
-               goto out_unlock;
+               goto out;
        }
 
        add_pending_csums(trans, inode, &ordered_extent->list);
@@ -2905,14 +3012,26 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
        ret = btrfs_update_inode_fallback(trans, root, inode);
        if (ret) { /* -ENOMEM or corruption */
                btrfs_abort_transaction(trans, ret);
-               goto out_unlock;
+               goto out;
        }
        ret = 0;
-out_unlock:
-       unlock_extent_cached(io_tree, ordered_extent->file_offset,
-                            ordered_extent->file_offset +
-                            ordered_extent->len - 1, &cached_state, GFP_NOFS);
 out:
+       if (range_locked || clear_new_delalloc_bytes) {
+               unsigned int clear_bits = 0;
+
+               if (range_locked)
+                       clear_bits |= EXTENT_LOCKED;
+               if (clear_new_delalloc_bytes)
+                       clear_bits |= EXTENT_DELALLOC_NEW;
+               clear_extent_bit(&BTRFS_I(inode)->io_tree,
+                                ordered_extent->file_offset,
+                                ordered_extent->file_offset +
+                                ordered_extent->len - 1,
+                                clear_bits,
+                                (clear_bits & EXTENT_LOCKED) ? 1 : 0,
+                                0, &cached_state, GFP_NOFS);
+       }
+
        if (root != fs_info->tree_root)
                btrfs_delalloc_release_metadata(BTRFS_I(inode),
                                ordered_extent->len);
@@ -4401,9 +4520,17 @@ search_again:
                        if (extent_type != BTRFS_FILE_EXTENT_INLINE) {
                                item_end +=
                                    btrfs_file_extent_num_bytes(leaf, fi);
+
+                               trace_btrfs_truncate_show_fi_regular(
+                                       BTRFS_I(inode), leaf, fi,
+                                       found_key.offset);
                        } else if (extent_type == BTRFS_FILE_EXTENT_INLINE) {
                                item_end += btrfs_file_extent_inline_len(leaf,
                                                         path->slots[0], fi);
+
+                               trace_btrfs_truncate_show_fi_inline(
+                                       BTRFS_I(inode), leaf, fi, path->slots[0],
+                                       found_key.offset);
                        }
                        item_end--;
                }
@@ -4603,13 +4730,6 @@ error:
 
        btrfs_free_path(path);
 
-       if (err == 0) {
-               /* only inline file may have last_size != new_size */
-               if (new_size >= fs_info->sectorsize ||
-                   new_size > fs_info->max_inline)
-                       ASSERT(last_size == new_size);
-       }
-
        if (be_nice && bytes_deleted > SZ_32M) {
                unsigned long updates = trans->delayed_ref_updates;
                if (updates) {
@@ -6735,7 +6855,6 @@ static noinline int uncompress_inline(struct btrfs_path *path,
  *
  * This also copies inline extents directly into the page.
  */
-
 struct extent_map *btrfs_get_extent(struct btrfs_inode *inode,
                struct page *page,
            size_t pg_offset, u64 start, u64 len,
@@ -6835,11 +6954,18 @@ again:
            found_type == BTRFS_FILE_EXTENT_PREALLOC) {
                extent_end = extent_start +
                       btrfs_file_extent_num_bytes(leaf, item);
+
+               trace_btrfs_get_extent_show_fi_regular(inode, leaf, item,
+                                                      extent_start);
        } else if (found_type == BTRFS_FILE_EXTENT_INLINE) {
                size_t size;
                size = btrfs_file_extent_inline_len(leaf, path->slots[0], item);
                extent_end = ALIGN(extent_start + size,
                                   fs_info->sectorsize);
+
+               trace_btrfs_get_extent_show_fi_inline(inode, leaf, item,
+                                                     path->slots[0],
+                                                     extent_start);
        }
 next:
        if (start >= extent_end) {
@@ -7037,19 +7163,17 @@ struct extent_map *btrfs_get_extent_fiemap(struct btrfs_inode *inode,
        em = btrfs_get_extent(inode, page, pg_offset, start, len, create);
        if (IS_ERR(em))
                return em;
-       if (em) {
-               /*
-                * if our em maps to
-                * -  a hole or
-                * -  a pre-alloc extent,
-                * there might actually be delalloc bytes behind it.
-                */
-               if (em->block_start != EXTENT_MAP_HOLE &&
-                   !test_bit(EXTENT_FLAG_PREALLOC, &em->flags))
-                       return em;
-               else
-                       hole_em = em;
-       }
+       /*
+        * If our em maps to:
+        * - a hole or
+        * - a pre-alloc extent,
+        * there might actually be delalloc bytes behind it.
+        */
+       if (em->block_start != EXTENT_MAP_HOLE &&
+           !test_bit(EXTENT_FLAG_PREALLOC, &em->flags))
+               return em;
+       else
+               hole_em = em;
 
        /* check to see if we've wrapped (len == -1 or similar) */
        end = start + len;
@@ -8127,17 +8251,26 @@ static void btrfs_endio_direct_read(struct bio *bio)
        bio_put(bio);
 }
 
-static void btrfs_endio_direct_write_update_ordered(struct inode *inode,
-                                                   const u64 offset,
-                                                   const u64 bytes,
-                                                   const int uptodate)
+static void __endio_write_update_ordered(struct inode *inode,
+                                        const u64 offset, const u64 bytes,
+                                        const bool uptodate)
 {
        struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
        struct btrfs_ordered_extent *ordered = NULL;
+       struct btrfs_workqueue *wq;
+       btrfs_work_func_t func;
        u64 ordered_offset = offset;
        u64 ordered_bytes = bytes;
        int ret;
 
+       if (btrfs_is_free_space_inode(BTRFS_I(inode))) {
+               wq = fs_info->endio_freespace_worker;
+               func = btrfs_freespace_write_helper;
+       } else {
+               wq = fs_info->endio_write_workers;
+               func = btrfs_endio_write_helper;
+       }
+
 again:
        ret = btrfs_dec_test_first_ordered_pending(inode, &ordered,
                                                   &ordered_offset,
@@ -8146,9 +8279,8 @@ again:
        if (!ret)
                goto out_test;
 
-       btrfs_init_work(&ordered->work, btrfs_endio_write_helper,
-                       finish_ordered_fn, NULL, NULL);
-       btrfs_queue_work(fs_info->endio_write_workers, &ordered->work);
+       btrfs_init_work(&ordered->work, func, finish_ordered_fn, NULL, NULL);
+       btrfs_queue_work(wq, &ordered->work);
 out_test:
        /*
         * our bio might span multiple ordered extents.  If we haven't
@@ -8166,10 +8298,8 @@ static void btrfs_endio_direct_write(struct bio *bio)
        struct btrfs_dio_private *dip = bio->bi_private;
        struct bio *dio_bio = dip->dio_bio;
 
-       btrfs_endio_direct_write_update_ordered(dip->inode,
-                                               dip->logical_offset,
-                                               dip->bytes,
-                                               !bio->bi_error);
+       __endio_write_update_ordered(dip->inode, dip->logical_offset,
+                                    dip->bytes, !bio->bi_error);
 
        kfree(dip);
 
@@ -8530,10 +8660,10 @@ free_ordered:
                io_bio = NULL;
        } else {
                if (write)
-                       btrfs_endio_direct_write_update_ordered(inode,
+                       __endio_write_update_ordered(inode,
                                                file_offset,
                                                dio_bio->bi_iter.bi_size,
-                                               0);
+                                               false);
                else
                        unlock_extent(&BTRFS_I(inode)->io_tree, file_offset,
                              file_offset + dio_bio->bi_iter.bi_size - 1);
@@ -8668,11 +8798,11 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
                         */
                        if (dio_data.unsubmitted_oe_range_start <
                            dio_data.unsubmitted_oe_range_end)
-                               btrfs_endio_direct_write_update_ordered(inode,
+                               __endio_write_update_ordered(inode,
                                        dio_data.unsubmitted_oe_range_start,
                                        dio_data.unsubmitted_oe_range_end -
                                        dio_data.unsubmitted_oe_range_start,
-                                       0);
+                                       false);
                } else if (ret >= 0 && (size_t)ret < count)
                        btrfs_delalloc_release_space(inode, offset,
                                                     count - (size_t)ret);
@@ -8819,6 +8949,7 @@ again:
                if (!inode_evicting)
                        clear_extent_bit(tree, start, end,
                                         EXTENT_DIRTY | EXTENT_DELALLOC |
+                                        EXTENT_DELALLOC_NEW |
                                         EXTENT_LOCKED | EXTENT_DO_ACCOUNTING |
                                         EXTENT_DEFRAG, 1, 0, &cached_state,
                                         GFP_NOFS);
@@ -8876,8 +9007,8 @@ again:
        if (!inode_evicting) {
                clear_extent_bit(tree, page_start, page_end,
                                 EXTENT_LOCKED | EXTENT_DIRTY |
-                                EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING |
-                                EXTENT_DEFRAG, 1, 1,
+                                EXTENT_DELALLOC | EXTENT_DELALLOC_NEW |
+                                EXTENT_DO_ACCOUNTING | EXTENT_DEFRAG, 1, 1,
                                 &cached_state, GFP_NOFS);
 
                __btrfs_releasepage(page, GFP_NOFS);
@@ -9248,6 +9379,7 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
        ei->last_sub_trans = 0;
        ei->logged_trans = 0;
        ei->delalloc_bytes = 0;
+       ei->new_delalloc_bytes = 0;
        ei->defrag_bytes = 0;
        ei->disk_i_size = 0;
        ei->flags = 0;
@@ -9313,6 +9445,7 @@ void btrfs_destroy_inode(struct inode *inode)
        WARN_ON(BTRFS_I(inode)->outstanding_extents);
        WARN_ON(BTRFS_I(inode)->reserved_extents);
        WARN_ON(BTRFS_I(inode)->delalloc_bytes);
+       WARN_ON(BTRFS_I(inode)->new_delalloc_bytes);
        WARN_ON(BTRFS_I(inode)->csum_bytes);
        WARN_ON(BTRFS_I(inode)->defrag_bytes);
 
@@ -9436,7 +9569,7 @@ static int btrfs_getattr(const struct path *path, struct kstat *stat,
        stat->dev = BTRFS_I(inode)->root->anon_dev;
 
        spin_lock(&BTRFS_I(inode)->lock);
-       delalloc_bytes = BTRFS_I(inode)->delalloc_bytes;
+       delalloc_bytes = BTRFS_I(inode)->new_delalloc_bytes;
        spin_unlock(&BTRFS_I(inode)->lock);
        stat->blocks = (ALIGN(inode_get_bytes(inode), blocksize) +
                        ALIGN(delalloc_bytes, blocksize)) >> 9;
index dabfc7ac48a674db12252722c99509d9462dbe53..e176375f374f917be5c50a46ed1c94444d1949d3 100644 (file)
@@ -1504,7 +1504,7 @@ static noinline int btrfs_ioctl_resize(struct file *file,
        if (ret)
                return ret;
 
-       if (atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1)) {
+       if (test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) {
                mnt_drop_write_file(file);
                return BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
        }
@@ -1619,7 +1619,7 @@ out_free:
        kfree(vol_args);
 out:
        mutex_unlock(&fs_info->volume_mutex);
-       atomic_set(&fs_info->mutually_exclusive_operation_running, 0);
+       clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
        mnt_drop_write_file(file);
        return ret;
 }
@@ -2661,7 +2661,7 @@ static long btrfs_ioctl_add_dev(struct btrfs_fs_info *fs_info, void __user *arg)
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
-       if (atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1))
+       if (test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags))
                return BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
 
        mutex_lock(&fs_info->volume_mutex);
@@ -2680,7 +2680,7 @@ static long btrfs_ioctl_add_dev(struct btrfs_fs_info *fs_info, void __user *arg)
        kfree(vol_args);
 out:
        mutex_unlock(&fs_info->volume_mutex);
-       atomic_set(&fs_info->mutually_exclusive_operation_running, 0);
+       clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
        return ret;
 }
 
@@ -2708,7 +2708,7 @@ static long btrfs_ioctl_rm_dev_v2(struct file *file, void __user *arg)
        if (vol_args->flags & ~BTRFS_VOL_ARG_V2_FLAGS_SUPPORTED)
                return -EOPNOTSUPP;
 
-       if (atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1)) {
+       if (test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) {
                ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
                goto out;
        }
@@ -2721,7 +2721,7 @@ static long btrfs_ioctl_rm_dev_v2(struct file *file, void __user *arg)
                ret = btrfs_rm_device(fs_info, vol_args->name, 0);
        }
        mutex_unlock(&fs_info->volume_mutex);
-       atomic_set(&fs_info->mutually_exclusive_operation_running, 0);
+       clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
 
        if (!ret) {
                if (vol_args->flags & BTRFS_DEVICE_SPEC_BY_ID)
@@ -2752,7 +2752,7 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg)
        if (ret)
                return ret;
 
-       if (atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1)) {
+       if (test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) {
                ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
                goto out_drop_write;
        }
@@ -2772,7 +2772,7 @@ static long btrfs_ioctl_rm_dev(struct file *file, void __user *arg)
                btrfs_info(fs_info, "disk deleted %s", vol_args->name);
        kfree(vol_args);
 out:
-       atomic_set(&fs_info->mutually_exclusive_operation_running, 0);
+       clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
 out_drop_write:
        mnt_drop_write_file(file);
 
@@ -3539,12 +3539,9 @@ static int btrfs_clone(struct inode *src, struct inode *inode,
        u64 last_dest_end = destoff;
 
        ret = -ENOMEM;
-       buf = kmalloc(fs_info->nodesize, GFP_KERNEL | __GFP_NOWARN);
-       if (!buf) {
-               buf = vmalloc(fs_info->nodesize);
-               if (!buf)
-                       return ret;
-       }
+       buf = kvmalloc(fs_info->nodesize, GFP_KERNEL);
+       if (!buf)
+               return ret;
 
        path = btrfs_alloc_path();
        if (!path) {
@@ -4442,13 +4439,11 @@ static long btrfs_ioctl_dev_replace(struct btrfs_fs_info *fs_info,
                        ret = -EROFS;
                        goto out;
                }
-               if (atomic_xchg(
-                       &fs_info->mutually_exclusive_operation_running, 1)) {
+               if (test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) {
                        ret = BTRFS_ERROR_DEV_EXCL_RUN_IN_PROGRESS;
                } else {
                        ret = btrfs_dev_replace_by_ioctl(fs_info, p);
-                       atomic_set(
-                        &fs_info->mutually_exclusive_operation_running, 0);
+                       clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
                }
                break;
        case BTRFS_IOCTL_DEV_REPLACE_CMD_STATUS:
@@ -4643,7 +4638,7 @@ static long btrfs_ioctl_balance(struct file *file, void __user *arg)
                return ret;
 
 again:
-       if (!atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1)) {
+       if (!test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags)) {
                mutex_lock(&fs_info->volume_mutex);
                mutex_lock(&fs_info->balance_mutex);
                need_unlock = true;
@@ -4689,7 +4684,7 @@ again:
        }
 
 locked:
-       BUG_ON(!atomic_read(&fs_info->mutually_exclusive_operation_running));
+       BUG_ON(!test_bit(BTRFS_FS_EXCL_OP, &fs_info->flags));
 
        if (arg) {
                bargs = memdup_user(arg, sizeof(*bargs));
@@ -4745,11 +4740,10 @@ locked:
 
 do_balance:
        /*
-        * Ownership of bctl and mutually_exclusive_operation_running
+        * Ownership of bctl and filesystem flag BTRFS_FS_EXCL_OP
         * goes to to btrfs_balance.  bctl is freed in __cancel_balance,
         * or, if restriper was paused all the way until unmount, in
-        * free_fs_info.  mutually_exclusive_operation_running is
-        * cleared in __cancel_balance.
+        * free_fs_info.  The flag is cleared in __cancel_balance.
         */
        need_unlock = false;
 
@@ -4769,7 +4763,7 @@ out_unlock:
        mutex_unlock(&fs_info->balance_mutex);
        mutex_unlock(&fs_info->volume_mutex);
        if (need_unlock)
-               atomic_set(&fs_info->mutually_exclusive_operation_running, 0);
+               clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
 out:
        mnt_drop_write_file(file);
        return ret;
index 9a46878ba60fa973562139f32629810b476ed453..7b40e2e7292a41a047b0f8e300304822b7c63e74 100644 (file)
@@ -212,7 +212,7 @@ static int __btrfs_add_ordered_extent(struct inode *inode, u64 file_offset,
                set_bit(BTRFS_ORDERED_DIRECT, &entry->flags);
 
        /* one ref for the tree */
-       atomic_set(&entry->refs, 1);
+       refcount_set(&entry->refs, 1);
        init_waitqueue_head(&entry->wait);
        INIT_LIST_HEAD(&entry->list);
        INIT_LIST_HEAD(&entry->root_extent_list);
@@ -358,7 +358,7 @@ int btrfs_dec_test_first_ordered_pending(struct inode *inode,
 out:
        if (!ret && cached && entry) {
                *cached = entry;
-               atomic_inc(&entry->refs);
+               refcount_inc(&entry->refs);
        }
        spin_unlock_irqrestore(&tree->lock, flags);
        return ret == 0;
@@ -425,7 +425,7 @@ have_entry:
 out:
        if (!ret && cached && entry) {
                *cached = entry;
-               atomic_inc(&entry->refs);
+               refcount_inc(&entry->refs);
        }
        spin_unlock_irqrestore(&tree->lock, flags);
        return ret == 0;
@@ -456,7 +456,7 @@ void btrfs_get_logged_extents(struct btrfs_inode *inode,
                if (test_and_set_bit(BTRFS_ORDERED_LOGGED, &ordered->flags))
                        continue;
                list_add(&ordered->log_list, logged_list);
-               atomic_inc(&ordered->refs);
+               refcount_inc(&ordered->refs);
        }
        spin_unlock_irq(&tree->lock);
 }
@@ -565,7 +565,7 @@ void btrfs_put_ordered_extent(struct btrfs_ordered_extent *entry)
 
        trace_btrfs_ordered_extent_put(entry->inode, entry);
 
-       if (atomic_dec_and_test(&entry->refs)) {
+       if (refcount_dec_and_test(&entry->refs)) {
                ASSERT(list_empty(&entry->log_list));
                ASSERT(list_empty(&entry->trans_list));
                ASSERT(list_empty(&entry->root_extent_list));
@@ -623,7 +623,7 @@ void btrfs_remove_ordered_extent(struct inode *inode,
                spin_lock(&fs_info->trans_lock);
                trans = fs_info->running_transaction;
                if (trans)
-                       atomic_inc(&trans->use_count);
+                       refcount_inc(&trans->use_count);
                spin_unlock(&fs_info->trans_lock);
 
                ASSERT(trans);
@@ -690,7 +690,7 @@ int btrfs_wait_ordered_extents(struct btrfs_root *root, int nr,
 
                list_move_tail(&ordered->root_extent_list,
                               &root->ordered_extents);
-               atomic_inc(&ordered->refs);
+               refcount_inc(&ordered->refs);
                spin_unlock(&root->ordered_extent_lock);
 
                btrfs_init_work(&ordered->flush_work,
@@ -870,7 +870,7 @@ struct btrfs_ordered_extent *btrfs_lookup_ordered_extent(struct inode *inode,
        if (!offset_in_entry(entry, file_offset))
                entry = NULL;
        if (entry)
-               atomic_inc(&entry->refs);
+               refcount_inc(&entry->refs);
 out:
        spin_unlock_irq(&tree->lock);
        return entry;
@@ -911,7 +911,7 @@ struct btrfs_ordered_extent *btrfs_lookup_ordered_range(
        }
 out:
        if (entry)
-               atomic_inc(&entry->refs);
+               refcount_inc(&entry->refs);
        spin_unlock_irq(&tree->lock);
        return entry;
 }
@@ -948,7 +948,7 @@ btrfs_lookup_first_ordered_extent(struct inode *inode, u64 file_offset)
                goto out;
 
        entry = rb_entry(node, struct btrfs_ordered_extent, rb_node);
-       atomic_inc(&entry->refs);
+       refcount_inc(&entry->refs);
 out:
        spin_unlock_irq(&tree->lock);
        return entry;
index 195c93b67fe002861153fb58f6506fa93deb0434..e0c1d5b8d859c95c9e870b8feb735c921a09d8f1 100644 (file)
@@ -113,7 +113,7 @@ struct btrfs_ordered_extent {
        int compress_type;
 
        /* reference count */
-       atomic_t refs;
+       refcount_t refs;
 
        /* the inode we belong to */
        struct inode *inode;
index afbea61d957e893db09effb75ec47c7d670e24e3..deffbeb74a0be7499c42578efc51903c3737f3bf 100644 (file)
  *  - check all ioctl parameters
  */
 
-/*
- * one struct for each qgroup, organized in fs_info->qgroup_tree.
- */
-struct btrfs_qgroup {
-       u64 qgroupid;
-
-       /*
-        * state
-        */
-       u64 rfer;       /* referenced */
-       u64 rfer_cmpr;  /* referenced compressed */
-       u64 excl;       /* exclusive */
-       u64 excl_cmpr;  /* exclusive compressed */
-
-       /*
-        * limits
-        */
-       u64 lim_flags;  /* which limits are set */
-       u64 max_rfer;
-       u64 max_excl;
-       u64 rsv_rfer;
-       u64 rsv_excl;
-
-       /*
-        * reservation tracking
-        */
-       u64 reserved;
-
-       /*
-        * lists
-        */
-       struct list_head groups;  /* groups this group is member of */
-       struct list_head members; /* groups that are members of this group */
-       struct list_head dirty;   /* dirty groups */
-       struct rb_node node;      /* tree of qgroups */
-
-       /*
-        * temp variables for accounting operations
-        * Refer to qgroup_shared_accounting() for details.
-        */
-       u64 old_refcnt;
-       u64 new_refcnt;
-};
-
 static void btrfs_qgroup_update_old_refcnt(struct btrfs_qgroup *qg, u64 seq,
                                           int mod)
 {
@@ -1078,6 +1034,7 @@ static int __qgroup_excl_accounting(struct btrfs_fs_info *fs_info,
        qgroup->excl += sign * num_bytes;
        qgroup->excl_cmpr += sign * num_bytes;
        if (sign > 0) {
+               trace_qgroup_update_reserve(fs_info, qgroup, -(s64)num_bytes);
                if (qgroup->reserved < num_bytes)
                        report_reserved_underflow(fs_info, qgroup, num_bytes);
                else
@@ -1103,6 +1060,8 @@ static int __qgroup_excl_accounting(struct btrfs_fs_info *fs_info,
                WARN_ON(sign < 0 && qgroup->excl < num_bytes);
                qgroup->excl += sign * num_bytes;
                if (sign > 0) {
+                       trace_qgroup_update_reserve(fs_info, qgroup,
+                                                   -(s64)num_bytes);
                        if (qgroup->reserved < num_bytes)
                                report_reserved_underflow(fs_info, qgroup,
                                                          num_bytes);
@@ -2058,12 +2017,12 @@ int btrfs_qgroup_account_extents(struct btrfs_trans_handle *trans,
 
                if (!ret) {
                        /*
-                        * Use (u64)-1 as time_seq to do special search, which
+                        * Use SEQ_LAST as time_seq to do special search, which
                         * doesn't lock tree or delayed_refs and search current
                         * root. It's safe inside commit_transaction().
                         */
                        ret = btrfs_find_all_roots(trans, fs_info,
-                                       record->bytenr, (u64)-1, &new_roots);
+                                       record->bytenr, SEQ_LAST, &new_roots);
                        if (ret < 0)
                                goto cleanup;
                        if (qgroup_to_skip)
@@ -2370,6 +2329,7 @@ static int qgroup_reserve(struct btrfs_root *root, u64 num_bytes, bool enforce)
        struct btrfs_fs_info *fs_info = root->fs_info;
        u64 ref_root = root->root_key.objectid;
        int ret = 0;
+       int retried = 0;
        struct ulist_node *unode;
        struct ulist_iterator uiter;
 
@@ -2378,7 +2338,7 @@ static int qgroup_reserve(struct btrfs_root *root, u64 num_bytes, bool enforce)
 
        if (num_bytes == 0)
                return 0;
-
+retry:
        spin_lock(&fs_info->qgroup_lock);
        quota_root = fs_info->quota_root;
        if (!quota_root)
@@ -2405,6 +2365,27 @@ static int qgroup_reserve(struct btrfs_root *root, u64 num_bytes, bool enforce)
                qg = unode_aux_to_qgroup(unode);
 
                if (enforce && !qgroup_check_limits(qg, num_bytes)) {
+                       /*
+                        * Commit the tree and retry, since we may have
+                        * deletions which would free up space.
+                        */
+                       if (!retried && qg->reserved > 0) {
+                               struct btrfs_trans_handle *trans;
+
+                               spin_unlock(&fs_info->qgroup_lock);
+                               ret = btrfs_start_delalloc_inodes(root, 0);
+                               if (ret)
+                                       return ret;
+                               btrfs_wait_ordered_extents(root, -1, 0, (u64)-1);
+                               trans = btrfs_join_transaction(root);
+                               if (IS_ERR(trans))
+                                       return PTR_ERR(trans);
+                               ret = btrfs_commit_transaction(trans);
+                               if (ret)
+                                       return ret;
+                               retried++;
+                               goto retry;
+                       }
                        ret = -EDQUOT;
                        goto out;
                }
@@ -2427,6 +2408,7 @@ static int qgroup_reserve(struct btrfs_root *root, u64 num_bytes, bool enforce)
 
                qg = unode_aux_to_qgroup(unode);
 
+               trace_qgroup_update_reserve(fs_info, qg, num_bytes);
                qg->reserved += num_bytes;
        }
 
@@ -2472,6 +2454,7 @@ void btrfs_qgroup_free_refroot(struct btrfs_fs_info *fs_info,
 
                qg = unode_aux_to_qgroup(unode);
 
+               trace_qgroup_update_reserve(fs_info, qg, -(s64)num_bytes);
                if (qg->reserved < num_bytes)
                        report_reserved_underflow(fs_info, qg, num_bytes);
                else
@@ -2490,18 +2473,6 @@ out:
        spin_unlock(&fs_info->qgroup_lock);
 }
 
-void assert_qgroups_uptodate(struct btrfs_trans_handle *trans)
-{
-       if (list_empty(&trans->qgroup_ref_list) && !trans->delayed_ref_elem.seq)
-               return;
-       btrfs_err(trans->fs_info,
-               "qgroups not uptodate in trans handle %p:  list is%s empty, seq is %#x.%x",
-               trans, list_empty(&trans->qgroup_ref_list) ? "" : " not",
-               (u32)(trans->delayed_ref_elem.seq >> 32),
-               (u32)trans->delayed_ref_elem.seq);
-       BUG();
-}
-
 /*
  * returns < 0 on error, 0 when more leafs are to be scanned.
  * returns 1 when done.
@@ -2889,14 +2860,14 @@ static int __btrfs_qgroup_release_data(struct inode *inode, u64 start, u64 len,
        if (ret < 0)
                goto out;
 
-       if (free) {
-               btrfs_qgroup_free_refroot(BTRFS_I(inode)->root->fs_info,
-                               BTRFS_I(inode)->root->objectid,
-                               changeset.bytes_changed);
+       if (free)
                trace_op = QGROUP_FREE;
-       }
        trace_btrfs_qgroup_release_data(inode, start, len,
                                        changeset.bytes_changed, trace_op);
+       if (free)
+               btrfs_qgroup_free_refroot(BTRFS_I(inode)->root->fs_info,
+                               BTRFS_I(inode)->root->objectid,
+                               changeset.bytes_changed);
 out:
        ulist_release(&changeset.range_changed);
        return ret;
@@ -2948,6 +2919,7 @@ int btrfs_qgroup_reserve_meta(struct btrfs_root *root, int num_bytes,
                return 0;
 
        BUG_ON(num_bytes != round_down(num_bytes, fs_info->nodesize));
+       trace_qgroup_meta_reserve(root, (s64)num_bytes);
        ret = qgroup_reserve(root, num_bytes, enforce);
        if (ret < 0)
                return ret;
@@ -2967,6 +2939,7 @@ void btrfs_qgroup_free_meta_all(struct btrfs_root *root)
        reserved = atomic64_xchg(&root->qgroup_meta_rsv, 0);
        if (reserved == 0)
                return;
+       trace_qgroup_meta_reserve(root, -(s64)reserved);
        btrfs_qgroup_free_refroot(fs_info, root->objectid, reserved);
 }
 
@@ -2981,6 +2954,7 @@ void btrfs_qgroup_free_meta(struct btrfs_root *root, int num_bytes)
        BUG_ON(num_bytes != round_down(num_bytes, fs_info->nodesize));
        WARN_ON(atomic64_read(&root->qgroup_meta_rsv) < num_bytes);
        atomic64_sub(num_bytes, &root->qgroup_meta_rsv);
+       trace_qgroup_meta_reserve(root, -(s64)num_bytes);
        btrfs_qgroup_free_refroot(fs_info, root->objectid, num_bytes);
 }
 
index 26932a8a19930bc48ff14ad3c154a7326ce3a111..fe04d3f295c67f0b97b79095885878237260a274 100644 (file)
@@ -61,6 +61,50 @@ struct btrfs_qgroup_extent_record {
        struct ulist *old_roots;
 };
 
+/*
+ * one struct for each qgroup, organized in fs_info->qgroup_tree.
+ */
+struct btrfs_qgroup {
+       u64 qgroupid;
+
+       /*
+        * state
+        */
+       u64 rfer;       /* referenced */
+       u64 rfer_cmpr;  /* referenced compressed */
+       u64 excl;       /* exclusive */
+       u64 excl_cmpr;  /* exclusive compressed */
+
+       /*
+        * limits
+        */
+       u64 lim_flags;  /* which limits are set */
+       u64 max_rfer;
+       u64 max_excl;
+       u64 rsv_rfer;
+       u64 rsv_excl;
+
+       /*
+        * reservation tracking
+        */
+       u64 reserved;
+
+       /*
+        * lists
+        */
+       struct list_head groups;  /* groups this group is member of */
+       struct list_head members; /* groups that are members of this group */
+       struct list_head dirty;   /* dirty groups */
+       struct rb_node node;      /* tree of qgroups */
+
+       /*
+        * temp variables for accounting operations
+        * Refer to qgroup_shared_accounting() for details.
+        */
+       u64 old_refcnt;
+       u64 new_refcnt;
+};
+
 /*
  * For qgroup event trace points only
  */
@@ -186,17 +230,12 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans,
                         struct btrfs_qgroup_inherit *inherit);
 void btrfs_qgroup_free_refroot(struct btrfs_fs_info *fs_info,
                               u64 ref_root, u64 num_bytes);
-/*
- * TODO: Add proper trace point for it, as btrfs_qgroup_free() is
- * called by everywhere, can't provide good trace for delayed ref case.
- */
 static inline void btrfs_qgroup_free_delayed_ref(struct btrfs_fs_info *fs_info,
                                                 u64 ref_root, u64 num_bytes)
 {
-       btrfs_qgroup_free_refroot(fs_info, ref_root, num_bytes);
        trace_btrfs_qgroup_free_delayed_ref(fs_info, ref_root, num_bytes);
+       btrfs_qgroup_free_refroot(fs_info, ref_root, num_bytes);
 }
-void assert_qgroups_uptodate(struct btrfs_trans_handle *trans);
 
 #ifdef CONFIG_BTRFS_FS_RUN_SANITY_TESTS
 int btrfs_verify_qgroup_counts(struct btrfs_fs_info *fs_info, u64 qgroupid,
index 1571bf26dc077a0575b39977ead28e229d68550f..d8ea0eb76325e9b25d42dfa4a99c63918981aa2f 100644 (file)
@@ -149,7 +149,7 @@ struct btrfs_raid_bio {
 
        int generic_bio_cnt;
 
-       atomic_t refs;
+       refcount_t refs;
 
        atomic_t stripes_pending;
 
@@ -389,7 +389,7 @@ static void __remove_rbio_from_cache(struct btrfs_raid_bio *rbio)
                if (bio_list_empty(&rbio->bio_list)) {
                        if (!list_empty(&rbio->hash_list)) {
                                list_del_init(&rbio->hash_list);
-                               atomic_dec(&rbio->refs);
+                               refcount_dec(&rbio->refs);
                                BUG_ON(!list_empty(&rbio->plug_list));
                        }
                }
@@ -480,7 +480,7 @@ static void cache_rbio(struct btrfs_raid_bio *rbio)
 
        /* bump our ref if we were not in the list before */
        if (!test_and_set_bit(RBIO_CACHE_BIT, &rbio->flags))
-               atomic_inc(&rbio->refs);
+               refcount_inc(&rbio->refs);
 
        if (!list_empty(&rbio->stripe_cache)){
                list_move(&rbio->stripe_cache, &table->stripe_cache);
@@ -689,7 +689,7 @@ static noinline int lock_stripe_add(struct btrfs_raid_bio *rbio)
                            test_bit(RBIO_CACHE_BIT, &cur->flags) &&
                            !test_bit(RBIO_RMW_LOCKED_BIT, &cur->flags)) {
                                list_del_init(&cur->hash_list);
-                               atomic_dec(&cur->refs);
+                               refcount_dec(&cur->refs);
 
                                steal_rbio(cur, rbio);
                                cache_drop = cur;
@@ -738,7 +738,7 @@ static noinline int lock_stripe_add(struct btrfs_raid_bio *rbio)
                }
        }
 lockit:
-       atomic_inc(&rbio->refs);
+       refcount_inc(&rbio->refs);
        list_add(&rbio->hash_list, &h->hash_list);
 out:
        spin_unlock_irqrestore(&h->lock, flags);
@@ -784,7 +784,7 @@ static noinline void unlock_stripe(struct btrfs_raid_bio *rbio)
                }
 
                list_del_init(&rbio->hash_list);
-               atomic_dec(&rbio->refs);
+               refcount_dec(&rbio->refs);
 
                /*
                 * we use the plug list to hold all the rbios
@@ -801,7 +801,7 @@ static noinline void unlock_stripe(struct btrfs_raid_bio *rbio)
                        list_del_init(&rbio->plug_list);
 
                        list_add(&next->hash_list, &h->hash_list);
-                       atomic_inc(&next->refs);
+                       refcount_inc(&next->refs);
                        spin_unlock(&rbio->bio_list_lock);
                        spin_unlock_irqrestore(&h->lock, flags);
 
@@ -843,8 +843,7 @@ static void __free_raid_bio(struct btrfs_raid_bio *rbio)
 {
        int i;
 
-       WARN_ON(atomic_read(&rbio->refs) < 0);
-       if (!atomic_dec_and_test(&rbio->refs))
+       if (!refcount_dec_and_test(&rbio->refs))
                return;
 
        WARN_ON(!list_empty(&rbio->stripe_cache));
@@ -997,7 +996,7 @@ static struct btrfs_raid_bio *alloc_rbio(struct btrfs_fs_info *fs_info,
        rbio->stripe_npages = stripe_npages;
        rbio->faila = -1;
        rbio->failb = -1;
-       atomic_set(&rbio->refs, 1);
+       refcount_set(&rbio->refs, 1);
        atomic_set(&rbio->error, 0);
        atomic_set(&rbio->stripes_pending, 0);
 
@@ -2118,6 +2117,11 @@ int raid56_parity_recover(struct btrfs_fs_info *fs_info, struct bio *bio,
        struct btrfs_raid_bio *rbio;
        int ret;
 
+       if (generic_io) {
+               ASSERT(bbio->mirror_num == mirror_num);
+               btrfs_io_bio(bio)->mirror_num = mirror_num;
+       }
+
        rbio = alloc_rbio(fs_info, bbio, stripe_len);
        if (IS_ERR(rbio)) {
                if (generic_io)
@@ -2194,6 +2198,8 @@ static void read_rebuild_work(struct btrfs_work *work)
 /*
  * The following code is used to scrub/replace the parity stripe
  *
+ * Caller must have already increased bio_counter for getting @bbio.
+ *
  * Note: We need make sure all the pages that add into the scrub/replace
  * raid bio are correct and not be changed during the scrub/replace. That
  * is those pages just hold metadata or file data with checksum.
@@ -2231,6 +2237,12 @@ raid56_parity_alloc_scrub_rbio(struct btrfs_fs_info *fs_info, struct bio *bio,
        ASSERT(rbio->stripe_npages == stripe_nsectors);
        bitmap_copy(rbio->dbitmap, dbitmap, stripe_nsectors);
 
+       /*
+        * We have already increased bio_counter when getting bbio, record it
+        * so we can free it at rbio_orig_end_io().
+        */
+       rbio->generic_bio_cnt = 1;
+
        return rbio;
 }
 
@@ -2673,6 +2685,12 @@ raid56_alloc_missing_rbio(struct btrfs_fs_info *fs_info, struct bio *bio,
                return NULL;
        }
 
+       /*
+        * When we get bbio, we have already increased bio_counter, record it
+        * so we can free it at rbio_orig_end_io()
+        */
+       rbio->generic_bio_cnt = 1;
+
        return rbio;
 }
 
index e88bca87f5d275c7c25b2ee6279fe4cdc1482413..a17e775a4a89fca1e48214c5abb02756dd1c69d6 100644 (file)
@@ -209,9 +209,9 @@ cleanup:
        return;
 }
 
-int btree_readahead_hook(struct btrfs_fs_info *fs_info,
-                        struct extent_buffer *eb, int err)
+int btree_readahead_hook(struct extent_buffer *eb, int err)
 {
+       struct btrfs_fs_info *fs_info = eb->fs_info;
        int ret = 0;
        struct reada_extent *re;
 
@@ -235,10 +235,10 @@ start_machine:
        return ret;
 }
 
-static struct reada_zone *reada_find_zone(struct btrfs_fs_info *fs_info,
-                                         struct btrfs_device *dev, u64 logical,
+static struct reada_zone *reada_find_zone(struct btrfs_device *dev, u64 logical,
                                          struct btrfs_bio *bbio)
 {
+       struct btrfs_fs_info *fs_info = dev->fs_info;
        int ret;
        struct reada_zone *zone;
        struct btrfs_block_group_cache *cache = NULL;
@@ -270,6 +270,12 @@ static struct reada_zone *reada_find_zone(struct btrfs_fs_info *fs_info,
        if (!zone)
                return NULL;
 
+       ret = radix_tree_preload(GFP_KERNEL);
+       if (ret) {
+               kfree(zone);
+               return NULL;
+       }
+
        zone->start = start;
        zone->end = end;
        INIT_LIST_HEAD(&zone->list);
@@ -299,6 +305,7 @@ static struct reada_zone *reada_find_zone(struct btrfs_fs_info *fs_info,
                        zone = NULL;
        }
        spin_unlock(&fs_info->reada_lock);
+       radix_tree_preload_end();
 
        return zone;
 }
@@ -313,7 +320,6 @@ static struct reada_extent *reada_find_extent(struct btrfs_fs_info *fs_info,
        struct btrfs_bio *bbio = NULL;
        struct btrfs_device *dev;
        struct btrfs_device *prev_dev;
-       u32 blocksize;
        u64 length;
        int real_stripes;
        int nzones = 0;
@@ -334,7 +340,6 @@ static struct reada_extent *reada_find_extent(struct btrfs_fs_info *fs_info,
        if (!re)
                return NULL;
 
-       blocksize = fs_info->nodesize;
        re->logical = logical;
        re->top = *top;
        INIT_LIST_HEAD(&re->extctl);
@@ -344,10 +349,10 @@ static struct reada_extent *reada_find_extent(struct btrfs_fs_info *fs_info,
        /*
         * map block
         */
-       length = blocksize;
+       length = fs_info->nodesize;
        ret = btrfs_map_block(fs_info, BTRFS_MAP_GET_READ_MIRRORS, logical,
                        &length, &bbio, 0);
-       if (ret || !bbio || length < blocksize)
+       if (ret || !bbio || length < fs_info->nodesize)
                goto error;
 
        if (bbio->num_stripes > BTRFS_MAX_MIRRORS) {
@@ -367,7 +372,7 @@ static struct reada_extent *reada_find_extent(struct btrfs_fs_info *fs_info,
                 if (!dev->bdev)
                        continue;
 
-               zone = reada_find_zone(fs_info, dev, logical, bbio);
+               zone = reada_find_zone(dev, logical, bbio);
                if (!zone)
                        continue;
 
@@ -386,6 +391,10 @@ static struct reada_extent *reada_find_extent(struct btrfs_fs_info *fs_info,
                goto error;
        }
 
+       ret = radix_tree_preload(GFP_KERNEL);
+       if (ret)
+               goto error;
+
        /* insert extent in reada_tree + all per-device trees, all or nothing */
        btrfs_dev_replace_lock(&fs_info->dev_replace, 0);
        spin_lock(&fs_info->reada_lock);
@@ -395,13 +404,16 @@ static struct reada_extent *reada_find_extent(struct btrfs_fs_info *fs_info,
                re_exist->refcnt++;
                spin_unlock(&fs_info->reada_lock);
                btrfs_dev_replace_unlock(&fs_info->dev_replace, 0);
+               radix_tree_preload_end();
                goto error;
        }
        if (ret) {
                spin_unlock(&fs_info->reada_lock);
                btrfs_dev_replace_unlock(&fs_info->dev_replace, 0);
+               radix_tree_preload_end();
                goto error;
        }
+       radix_tree_preload_end();
        prev_dev = NULL;
        dev_replace_is_ongoing = btrfs_dev_replace_is_ongoing(
                        &fs_info->dev_replace);
@@ -639,9 +651,9 @@ static int reada_pick_zone(struct btrfs_device *dev)
        return 1;
 }
 
-static int reada_start_machine_dev(struct btrfs_fs_info *fs_info,
-                                  struct btrfs_device *dev)
+static int reada_start_machine_dev(struct btrfs_device *dev)
 {
+       struct btrfs_fs_info *fs_info = dev->fs_info;
        struct reada_extent *re = NULL;
        int mirror_num = 0;
        struct extent_buffer *eb = NULL;
@@ -754,8 +766,7 @@ static void __reada_start_machine(struct btrfs_fs_info *fs_info)
                list_for_each_entry(device, &fs_devices->devices, dev_list) {
                        if (atomic_read(&device->reada_in_flight) <
                            MAX_IN_FLIGHT)
-                               enqueued += reada_start_machine_dev(fs_info,
-                                                                   device);
+                               enqueued += reada_start_machine_dev(device);
                }
                mutex_unlock(&fs_devices->device_list_mutex);
                total += enqueued;
index a08224eab8b47111b2fc6f7f51ac33e6ca69814e..7d6bc308bf4308f653cc300c1354602ddd0df911 100644 (file)
@@ -501,8 +501,9 @@ void btrfs_update_root_times(struct btrfs_trans_handle *trans,
                             struct btrfs_root *root)
 {
        struct btrfs_root_item *item = &root->root_item;
-       struct timespec ct = current_fs_time(root->fs_info->sb);
+       struct timespec ct;
 
+       ktime_get_real_ts(&ct);
        spin_lock(&root->root_item_lock);
        btrfs_set_root_ctransid(item, trans->transid);
        btrfs_set_stack_timespec_sec(&item->ctime, ct.tv_sec);
index b0251eb1239fce83226650be88c31122a9f108af..c7b45eb2403d09e94b2538dabcb5a1f0116c55dd 100644 (file)
@@ -64,7 +64,7 @@ struct scrub_ctx;
 #define SCRUB_MAX_PAGES_PER_BLOCK      16      /* 64k per node/leaf/sector */
 
 struct scrub_recover {
-       atomic_t                refs;
+       refcount_t              refs;
        struct btrfs_bio        *bbio;
        u64                     map_length;
 };
@@ -112,7 +112,7 @@ struct scrub_block {
        struct scrub_page       *pagev[SCRUB_MAX_PAGES_PER_BLOCK];
        int                     page_count;
        atomic_t                outstanding_pages;
-       atomic_t                refs; /* free mem on transition to zero */
+       refcount_t              refs; /* free mem on transition to zero */
        struct scrub_ctx        *sctx;
        struct scrub_parity     *sparity;
        struct {
@@ -140,9 +140,9 @@ struct scrub_parity {
 
        int                     nsectors;
 
-       int                     stripe_len;
+       u64                     stripe_len;
 
-       atomic_t                refs;
+       refcount_t              refs;
 
        struct list_head        spages;
 
@@ -202,7 +202,7 @@ struct scrub_ctx {
         * doesn't free the scrub context before or while the workers are
         * doing the wakeup() call.
         */
-       atomic_t                refs;
+       refcount_t              refs;
 };
 
 struct scrub_fixup_nodatasum {
@@ -240,6 +240,13 @@ struct scrub_warning {
        struct btrfs_device     *dev;
 };
 
+struct full_stripe_lock {
+       struct rb_node node;
+       u64 logical;
+       u64 refs;
+       struct mutex mutex;
+};
+
 static void scrub_pending_bio_inc(struct scrub_ctx *sctx);
 static void scrub_pending_bio_dec(struct scrub_ctx *sctx);
 static void scrub_pending_trans_workers_inc(struct scrub_ctx *sctx);
@@ -305,7 +312,7 @@ static void scrub_put_ctx(struct scrub_ctx *sctx);
 
 static void scrub_pending_bio_inc(struct scrub_ctx *sctx)
 {
-       atomic_inc(&sctx->refs);
+       refcount_inc(&sctx->refs);
        atomic_inc(&sctx->bios_in_flight);
 }
 
@@ -348,6 +355,222 @@ static void scrub_blocked_if_needed(struct btrfs_fs_info *fs_info)
        scrub_pause_off(fs_info);
 }
 
+/*
+ * Insert new full stripe lock into full stripe locks tree
+ *
+ * Return pointer to existing or newly inserted full_stripe_lock structure if
+ * everything works well.
+ * Return ERR_PTR(-ENOMEM) if we failed to allocate memory
+ *
+ * NOTE: caller must hold full_stripe_locks_root->lock before calling this
+ * function
+ */
+static struct full_stripe_lock *insert_full_stripe_lock(
+               struct btrfs_full_stripe_locks_tree *locks_root,
+               u64 fstripe_logical)
+{
+       struct rb_node **p;
+       struct rb_node *parent = NULL;
+       struct full_stripe_lock *entry;
+       struct full_stripe_lock *ret;
+
+       WARN_ON(!mutex_is_locked(&locks_root->lock));
+
+       p = &locks_root->root.rb_node;
+       while (*p) {
+               parent = *p;
+               entry = rb_entry(parent, struct full_stripe_lock, node);
+               if (fstripe_logical < entry->logical) {
+                       p = &(*p)->rb_left;
+               } else if (fstripe_logical > entry->logical) {
+                       p = &(*p)->rb_right;
+               } else {
+                       entry->refs++;
+                       return entry;
+               }
+       }
+
+       /* Insert new lock */
+       ret = kmalloc(sizeof(*ret), GFP_KERNEL);
+       if (!ret)
+               return ERR_PTR(-ENOMEM);
+       ret->logical = fstripe_logical;
+       ret->refs = 1;
+       mutex_init(&ret->mutex);
+
+       rb_link_node(&ret->node, parent, p);
+       rb_insert_color(&ret->node, &locks_root->root);
+       return ret;
+}
+
+/*
+ * Search for a full stripe lock of a block group
+ *
+ * Return pointer to existing full stripe lock if found
+ * Return NULL if not found
+ */
+static struct full_stripe_lock *search_full_stripe_lock(
+               struct btrfs_full_stripe_locks_tree *locks_root,
+               u64 fstripe_logical)
+{
+       struct rb_node *node;
+       struct full_stripe_lock *entry;
+
+       WARN_ON(!mutex_is_locked(&locks_root->lock));
+
+       node = locks_root->root.rb_node;
+       while (node) {
+               entry = rb_entry(node, struct full_stripe_lock, node);
+               if (fstripe_logical < entry->logical)
+                       node = node->rb_left;
+               else if (fstripe_logical > entry->logical)
+                       node = node->rb_right;
+               else
+                       return entry;
+       }
+       return NULL;
+}
+
+/*
+ * Helper to get full stripe logical from a normal bytenr.
+ *
+ * Caller must ensure @cache is a RAID56 block group.
+ */
+static u64 get_full_stripe_logical(struct btrfs_block_group_cache *cache,
+                                  u64 bytenr)
+{
+       u64 ret;
+
+       /*
+        * Due to chunk item size limit, full stripe length should not be
+        * larger than U32_MAX. Just a sanity check here.
+        */
+       WARN_ON_ONCE(cache->full_stripe_len >= U32_MAX);
+
+       /*
+        * round_down() can only handle power of 2, while RAID56 full
+        * stripe length can be 64KiB * n, so we need to manually round down.
+        */
+       ret = div64_u64(bytenr - cache->key.objectid, cache->full_stripe_len) *
+               cache->full_stripe_len + cache->key.objectid;
+       return ret;
+}
+
+/*
+ * Lock a full stripe to avoid concurrency of recovery and read
+ *
+ * It's only used for profiles with parities (RAID5/6), for other profiles it
+ * does nothing.
+ *
+ * Return 0 if we locked full stripe covering @bytenr, with a mutex held.
+ * So caller must call unlock_full_stripe() at the same context.
+ *
+ * Return <0 if encounters error.
+ */
+static int lock_full_stripe(struct btrfs_fs_info *fs_info, u64 bytenr,
+                           bool *locked_ret)
+{
+       struct btrfs_block_group_cache *bg_cache;
+       struct btrfs_full_stripe_locks_tree *locks_root;
+       struct full_stripe_lock *existing;
+       u64 fstripe_start;
+       int ret = 0;
+
+       *locked_ret = false;
+       bg_cache = btrfs_lookup_block_group(fs_info, bytenr);
+       if (!bg_cache) {
+               ASSERT(0);
+               return -ENOENT;
+       }
+
+       /* Profiles not based on parity don't need full stripe lock */
+       if (!(bg_cache->flags & BTRFS_BLOCK_GROUP_RAID56_MASK))
+               goto out;
+       locks_root = &bg_cache->full_stripe_locks_root;
+
+       fstripe_start = get_full_stripe_logical(bg_cache, bytenr);
+
+       /* Now insert the full stripe lock */
+       mutex_lock(&locks_root->lock);
+       existing = insert_full_stripe_lock(locks_root, fstripe_start);
+       mutex_unlock(&locks_root->lock);
+       if (IS_ERR(existing)) {
+               ret = PTR_ERR(existing);
+               goto out;
+       }
+       mutex_lock(&existing->mutex);
+       *locked_ret = true;
+out:
+       btrfs_put_block_group(bg_cache);
+       return ret;
+}
+
+/*
+ * Unlock a full stripe.
+ *
+ * NOTE: Caller must ensure it's the same context calling corresponding
+ * lock_full_stripe().
+ *
+ * Return 0 if we unlock full stripe without problem.
+ * Return <0 for error
+ */
+static int unlock_full_stripe(struct btrfs_fs_info *fs_info, u64 bytenr,
+                             bool locked)
+{
+       struct btrfs_block_group_cache *bg_cache;
+       struct btrfs_full_stripe_locks_tree *locks_root;
+       struct full_stripe_lock *fstripe_lock;
+       u64 fstripe_start;
+       bool freeit = false;
+       int ret = 0;
+
+       /* If we didn't acquire full stripe lock, no need to continue */
+       if (!locked)
+               return 0;
+
+       bg_cache = btrfs_lookup_block_group(fs_info, bytenr);
+       if (!bg_cache) {
+               ASSERT(0);
+               return -ENOENT;
+       }
+       if (!(bg_cache->flags & BTRFS_BLOCK_GROUP_RAID56_MASK))
+               goto out;
+
+       locks_root = &bg_cache->full_stripe_locks_root;
+       fstripe_start = get_full_stripe_logical(bg_cache, bytenr);
+
+       mutex_lock(&locks_root->lock);
+       fstripe_lock = search_full_stripe_lock(locks_root, fstripe_start);
+       /* Unpaired unlock_full_stripe() detected */
+       if (!fstripe_lock) {
+               WARN_ON(1);
+               ret = -ENOENT;
+               mutex_unlock(&locks_root->lock);
+               goto out;
+       }
+
+       if (fstripe_lock->refs == 0) {
+               WARN_ON(1);
+               btrfs_warn(fs_info, "full stripe lock at %llu refcount underflow",
+                       fstripe_lock->logical);
+       } else {
+               fstripe_lock->refs--;
+       }
+
+       if (fstripe_lock->refs == 0) {
+               rb_erase(&fstripe_lock->node, &locks_root->root);
+               freeit = true;
+       }
+       mutex_unlock(&locks_root->lock);
+
+       mutex_unlock(&fstripe_lock->mutex);
+       if (freeit)
+               kfree(fstripe_lock);
+out:
+       btrfs_put_block_group(bg_cache);
+       return ret;
+}
+
 /*
  * used for workers that require transaction commits (i.e., for the
  * NOCOW case)
@@ -356,7 +579,7 @@ static void scrub_pending_trans_workers_inc(struct scrub_ctx *sctx)
 {
        struct btrfs_fs_info *fs_info = sctx->fs_info;
 
-       atomic_inc(&sctx->refs);
+       refcount_inc(&sctx->refs);
        /*
         * increment scrubs_running to prevent cancel requests from
         * completing as long as a worker is running. we must also
@@ -447,7 +670,7 @@ static noinline_for_stack void scrub_free_ctx(struct scrub_ctx *sctx)
 
 static void scrub_put_ctx(struct scrub_ctx *sctx)
 {
-       if (atomic_dec_and_test(&sctx->refs))
+       if (refcount_dec_and_test(&sctx->refs))
                scrub_free_ctx(sctx);
 }
 
@@ -462,7 +685,7 @@ struct scrub_ctx *scrub_setup_ctx(struct btrfs_device *dev, int is_dev_replace)
        sctx = kzalloc(sizeof(*sctx), GFP_KERNEL);
        if (!sctx)
                goto nomem;
-       atomic_set(&sctx->refs, 1);
+       refcount_set(&sctx->refs, 1);
        sctx->is_dev_replace = is_dev_replace;
        sctx->pages_per_rd_bio = SCRUB_PAGES_PER_RD_BIO;
        sctx->curr = -1;
@@ -857,12 +1080,14 @@ out:
 
 static inline void scrub_get_recover(struct scrub_recover *recover)
 {
-       atomic_inc(&recover->refs);
+       refcount_inc(&recover->refs);
 }
 
-static inline void scrub_put_recover(struct scrub_recover *recover)
+static inline void scrub_put_recover(struct btrfs_fs_info *fs_info,
+                                    struct scrub_recover *recover)
 {
-       if (atomic_dec_and_test(&recover->refs)) {
+       if (refcount_dec_and_test(&recover->refs)) {
+               btrfs_bio_counter_dec(fs_info);
                btrfs_put_bbio(recover->bbio);
                kfree(recover);
        }
@@ -892,6 +1117,7 @@ static int scrub_handle_errored_block(struct scrub_block *sblock_to_check)
        int mirror_index;
        int page_num;
        int success;
+       bool full_stripe_locked;
        static DEFINE_RATELIMIT_STATE(_rs, DEFAULT_RATELIMIT_INTERVAL,
                                      DEFAULT_RATELIMIT_BURST);
 
@@ -917,6 +1143,24 @@ static int scrub_handle_errored_block(struct scrub_block *sblock_to_check)
        have_csum = sblock_to_check->pagev[0]->have_csum;
        dev = sblock_to_check->pagev[0]->dev;
 
+       /*
+        * For RAID5/6, race can happen for a different device scrub thread.
+        * For data corruption, Parity and Data threads will both try
+        * to recovery the data.
+        * Race can lead to doubly added csum error, or even unrecoverable
+        * error.
+        */
+       ret = lock_full_stripe(fs_info, logical, &full_stripe_locked);
+       if (ret < 0) {
+               spin_lock(&sctx->stat_lock);
+               if (ret == -ENOMEM)
+                       sctx->stat.malloc_errors++;
+               sctx->stat.read_errors++;
+               sctx->stat.uncorrectable_errors++;
+               spin_unlock(&sctx->stat_lock);
+               return ret;
+       }
+
        if (sctx->is_dev_replace && !is_metadata && !have_csum) {
                sblocks_for_recheck = NULL;
                goto nodatasum_case;
@@ -1241,7 +1485,7 @@ out:
                                sblock->pagev[page_index]->sblock = NULL;
                                recover = sblock->pagev[page_index]->recover;
                                if (recover) {
-                                       scrub_put_recover(recover);
+                                       scrub_put_recover(fs_info, recover);
                                        sblock->pagev[page_index]->recover =
                                                                        NULL;
                                }
@@ -1251,6 +1495,9 @@ out:
                kfree(sblocks_for_recheck);
        }
 
+       ret = unlock_full_stripe(fs_info, logical, full_stripe_locked);
+       if (ret < 0)
+               return ret;
        return 0;
 }
 
@@ -1330,20 +1577,23 @@ static int scrub_setup_recheck_block(struct scrub_block *original_sblock,
                 * with a length of PAGE_SIZE, each returned stripe
                 * represents one mirror
                 */
+               btrfs_bio_counter_inc_blocked(fs_info);
                ret = btrfs_map_sblock(fs_info, BTRFS_MAP_GET_READ_MIRRORS,
-                               logical, &mapped_length, &bbio, 0, 1);
+                               logical, &mapped_length, &bbio);
                if (ret || !bbio || mapped_length < sublen) {
                        btrfs_put_bbio(bbio);
+                       btrfs_bio_counter_dec(fs_info);
                        return -EIO;
                }
 
                recover = kzalloc(sizeof(struct scrub_recover), GFP_NOFS);
                if (!recover) {
                        btrfs_put_bbio(bbio);
+                       btrfs_bio_counter_dec(fs_info);
                        return -ENOMEM;
                }
 
-               atomic_set(&recover->refs, 1);
+               refcount_set(&recover->refs, 1);
                recover->bbio = bbio;
                recover->map_length = mapped_length;
 
@@ -1365,7 +1615,7 @@ leave_nomem:
                                spin_lock(&sctx->stat_lock);
                                sctx->stat.malloc_errors++;
                                spin_unlock(&sctx->stat_lock);
-                               scrub_put_recover(recover);
+                               scrub_put_recover(fs_info, recover);
                                return -ENOMEM;
                        }
                        scrub_page_get(page);
@@ -1407,7 +1657,7 @@ leave_nomem:
                        scrub_get_recover(recover);
                        page->recover = recover;
                }
-               scrub_put_recover(recover);
+               scrub_put_recover(fs_info, recover);
                length -= sublen;
                logical += sublen;
                page_index++;
@@ -1497,14 +1747,18 @@ static void scrub_recheck_block(struct btrfs_fs_info *fs_info,
 
                bio_add_page(bio, page->page, PAGE_SIZE, 0);
                if (!retry_failed_mirror && scrub_is_page_on_raid56(page)) {
-                       if (scrub_submit_raid56_bio_wait(fs_info, bio, page))
+                       if (scrub_submit_raid56_bio_wait(fs_info, bio, page)) {
+                               page->io_error = 1;
                                sblock->no_io_error_seen = 0;
+                       }
                } else {
                        bio->bi_iter.bi_sector = page->physical >> 9;
                        bio_set_op_attrs(bio, REQ_OP_READ, 0);
 
-                       if (btrfsic_submit_bio_wait(bio))
+                       if (btrfsic_submit_bio_wait(bio)) {
+                               page->io_error = 1;
                                sblock->no_io_error_seen = 0;
+                       }
                }
 
                bio_put(bio);
@@ -1634,7 +1888,7 @@ static int scrub_write_page_to_dev_replace(struct scrub_block *sblock,
        if (spage->io_error) {
                void *mapped_buffer = kmap_atomic(spage->page);
 
-               memset(mapped_buffer, 0, PAGE_SIZE);
+               clear_page(mapped_buffer);
                flush_dcache_page(spage->page);
                kunmap_atomic(mapped_buffer);
        }
@@ -1998,12 +2252,12 @@ static int scrub_checksum_super(struct scrub_block *sblock)
 
 static void scrub_block_get(struct scrub_block *sblock)
 {
-       atomic_inc(&sblock->refs);
+       refcount_inc(&sblock->refs);
 }
 
 static void scrub_block_put(struct scrub_block *sblock)
 {
-       if (atomic_dec_and_test(&sblock->refs)) {
+       if (refcount_dec_and_test(&sblock->refs)) {
                int i;
 
                if (sblock->sparity)
@@ -2187,8 +2441,9 @@ static void scrub_missing_raid56_pages(struct scrub_block *sblock)
        int ret;
        int i;
 
+       btrfs_bio_counter_inc_blocked(fs_info);
        ret = btrfs_map_sblock(fs_info, BTRFS_MAP_GET_READ_MIRRORS, logical,
-                       &length, &bbio, 0, 1);
+                       &length, &bbio);
        if (ret || !bbio || !bbio->raid_map)
                goto bbio_out;
 
@@ -2231,6 +2486,7 @@ static void scrub_missing_raid56_pages(struct scrub_block *sblock)
 rbio_out:
        bio_put(bio);
 bbio_out:
+       btrfs_bio_counter_dec(fs_info);
        btrfs_put_bbio(bbio);
        spin_lock(&sctx->stat_lock);
        sctx->stat.malloc_errors++;
@@ -2255,7 +2511,7 @@ static int scrub_pages(struct scrub_ctx *sctx, u64 logical, u64 len,
 
        /* one ref inside this function, plus one for each page added to
         * a bio later on */
-       atomic_set(&sblock->refs, 1);
+       refcount_set(&sblock->refs, 1);
        sblock->sctx = sctx;
        sblock->no_io_error_seen = 1;
 
@@ -2385,7 +2641,7 @@ static inline void __scrub_mark_bitmap(struct scrub_parity *sparity,
                                       unsigned long *bitmap,
                                       u64 start, u64 len)
 {
-       u32 offset;
+       u64 offset;
        int nsectors;
        int sectorsize = sparity->sctx->fs_info->sectorsize;
 
@@ -2395,8 +2651,8 @@ static inline void __scrub_mark_bitmap(struct scrub_parity *sparity,
        }
 
        start -= sparity->logic_start;
-       start = div_u64_rem(start, sparity->stripe_len, &offset);
-       offset /= sectorsize;
+       start = div64_u64_rem(start, sparity->stripe_len, &offset);
+       offset = div_u64(offset, sectorsize);
        nsectors = (int)len / sectorsize;
 
        if (offset + nsectors <= sparity->nsectors) {
@@ -2555,7 +2811,7 @@ static int scrub_pages_for_parity(struct scrub_parity *sparity,
 
        /* one ref inside this function, plus one for each page added to
         * a bio later on */
-       atomic_set(&sblock->refs, 1);
+       refcount_set(&sblock->refs, 1);
        sblock->sctx = sctx;
        sblock->no_io_error_seen = 1;
        sblock->sparity = sparity;
@@ -2694,7 +2950,7 @@ static int get_raid56_logic_offset(u64 physical, int num,
        for (i = 0; i < nr_data_stripes(map); i++) {
                *offset = last_offset + i * map->stripe_len;
 
-               stripe_nr = div_u64(*offset, map->stripe_len);
+               stripe_nr = div64_u64(*offset, map->stripe_len);
                stripe_nr = div_u64(stripe_nr, nr_data_stripes(map));
 
                /* Work out the disk rotation on this stripe-set */
@@ -2765,7 +3021,6 @@ static void scrub_parity_check_and_repair(struct scrub_parity *sparity)
        struct btrfs_fs_info *fs_info = sctx->fs_info;
        struct bio *bio;
        struct btrfs_raid_bio *rbio;
-       struct scrub_page *spage;
        struct btrfs_bio *bbio = NULL;
        u64 length;
        int ret;
@@ -2775,8 +3030,10 @@ static void scrub_parity_check_and_repair(struct scrub_parity *sparity)
                goto out;
 
        length = sparity->logic_end - sparity->logic_start;
+
+       btrfs_bio_counter_inc_blocked(fs_info);
        ret = btrfs_map_sblock(fs_info, BTRFS_MAP_WRITE, sparity->logic_start,
-                              &length, &bbio, 0, 1);
+                              &length, &bbio);
        if (ret || !bbio || !bbio->raid_map)
                goto bbio_out;
 
@@ -2795,9 +3052,6 @@ static void scrub_parity_check_and_repair(struct scrub_parity *sparity)
        if (!rbio)
                goto rbio_out;
 
-       list_for_each_entry(spage, &sparity->spages, list)
-               raid56_add_scrub_pages(rbio, spage->page, spage->logical);
-
        scrub_pending_bio_inc(sctx);
        raid56_parity_submit_scrub_rbio(rbio);
        return;
@@ -2805,6 +3059,7 @@ static void scrub_parity_check_and_repair(struct scrub_parity *sparity)
 rbio_out:
        bio_put(bio);
 bbio_out:
+       btrfs_bio_counter_dec(fs_info);
        btrfs_put_bbio(bbio);
        bitmap_or(sparity->ebitmap, sparity->ebitmap, sparity->dbitmap,
                  sparity->nsectors);
@@ -2822,12 +3077,12 @@ static inline int scrub_calc_parity_bitmap_len(int nsectors)
 
 static void scrub_parity_get(struct scrub_parity *sparity)
 {
-       atomic_inc(&sparity->refs);
+       refcount_inc(&sparity->refs);
 }
 
 static void scrub_parity_put(struct scrub_parity *sparity)
 {
-       if (!atomic_dec_and_test(&sparity->refs))
+       if (!refcount_dec_and_test(&sparity->refs))
                return;
 
        scrub_parity_check_and_repair(sparity);
@@ -2879,7 +3134,7 @@ static noinline_for_stack int scrub_raid56_parity(struct scrub_ctx *sctx,
        sparity->scrub_dev = sdev;
        sparity->logic_start = logic_start;
        sparity->logic_end = logic_end;
-       atomic_set(&sparity->refs, 1);
+       refcount_set(&sparity->refs, 1);
        INIT_LIST_HEAD(&sparity->spages);
        sparity->dbitmap = sparity->bitmap;
        sparity->ebitmap = (void *)sparity->bitmap + bitmap_len;
@@ -3098,7 +3353,7 @@ static noinline_for_stack int scrub_stripe(struct scrub_ctx *sctx,
 
        physical = map->stripes[num].physical;
        offset = 0;
-       nstripes = div_u64(length, map->stripe_len);
+       nstripes = div64_u64(length, map->stripe_len);
        if (map->type & BTRFS_BLOCK_GROUP_RAID0) {
                offset = map->stripe_len * num;
                increment = map->stripe_len * map->num_stripes;
index a60d5bfb8a49e2bfc3faef10f4ea353a9da5f8b8..fc496a6f842a87d3544e80b3b9e063d57417f788 100644 (file)
@@ -5184,13 +5184,19 @@ static int is_extent_unchanged(struct send_ctx *sctx,
        while (key.offset < ekey->offset + left_len) {
                ei = btrfs_item_ptr(eb, slot, struct btrfs_file_extent_item);
                right_type = btrfs_file_extent_type(eb, ei);
-               if (right_type != BTRFS_FILE_EXTENT_REG) {
+               if (right_type != BTRFS_FILE_EXTENT_REG &&
+                   right_type != BTRFS_FILE_EXTENT_INLINE) {
                        ret = 0;
                        goto out;
                }
 
                right_disknr = btrfs_file_extent_disk_bytenr(eb, ei);
-               right_len = btrfs_file_extent_num_bytes(eb, ei);
+               if (right_type == BTRFS_FILE_EXTENT_INLINE) {
+                       right_len = btrfs_file_extent_inline_len(eb, slot, ei);
+                       right_len = PAGE_ALIGN(right_len);
+               } else {
+                       right_len = btrfs_file_extent_num_bytes(eb, ei);
+               }
                right_offset = btrfs_file_extent_offset(eb, ei);
                right_gen = btrfs_file_extent_generation(eb, ei);
 
@@ -5204,6 +5210,19 @@ static int is_extent_unchanged(struct send_ctx *sctx,
                        goto out;
                }
 
+               /*
+                * We just wanted to see if when we have an inline extent, what
+                * follows it is a regular extent (wanted to check the above
+                * condition for inline extents too). This should normally not
+                * happen but it's possible for example when we have an inline
+                * compressed extent representing data with a size matching
+                * the page size (currently the same as sector size).
+                */
+               if (right_type == BTRFS_FILE_EXTENT_INLINE) {
+                       ret = 0;
+                       goto out;
+               }
+
                left_offset_fixed = left_offset;
                if (key.offset < ekey->offset) {
                        /* Fix the right offset for 2a and 7. */
@@ -6360,22 +6379,16 @@ long btrfs_ioctl_send(struct file *mnt_file, void __user *arg_)
        sctx->clone_roots_cnt = arg->clone_sources_count;
 
        sctx->send_max_size = BTRFS_SEND_BUF_SIZE;
-       sctx->send_buf = kmalloc(sctx->send_max_size, GFP_KERNEL | __GFP_NOWARN);
+       sctx->send_buf = kvmalloc(sctx->send_max_size, GFP_KERNEL);
        if (!sctx->send_buf) {
-               sctx->send_buf = vmalloc(sctx->send_max_size);
-               if (!sctx->send_buf) {
-                       ret = -ENOMEM;
-                       goto out;
-               }
+               ret = -ENOMEM;
+               goto out;
        }
 
-       sctx->read_buf = kmalloc(BTRFS_SEND_READ_SIZE, GFP_KERNEL | __GFP_NOWARN);
+       sctx->read_buf = kvmalloc(BTRFS_SEND_READ_SIZE, GFP_KERNEL);
        if (!sctx->read_buf) {
-               sctx->read_buf = vmalloc(BTRFS_SEND_READ_SIZE);
-               if (!sctx->read_buf) {
-                       ret = -ENOMEM;
-                       goto out;
-               }
+               ret = -ENOMEM;
+               goto out;
        }
 
        sctx->pending_dir_moves = RB_ROOT;
@@ -6396,13 +6409,10 @@ long btrfs_ioctl_send(struct file *mnt_file, void __user *arg_)
        alloc_size = arg->clone_sources_count * sizeof(*arg->clone_sources);
 
        if (arg->clone_sources_count) {
-               clone_sources_tmp = kmalloc(alloc_size, GFP_KERNEL | __GFP_NOWARN);
+               clone_sources_tmp = kvmalloc(alloc_size, GFP_KERNEL);
                if (!clone_sources_tmp) {
-                       clone_sources_tmp = vmalloc(alloc_size);
-                       if (!clone_sources_tmp) {
-                               ret = -ENOMEM;
-                               goto out;
-                       }
+                       ret = -ENOMEM;
+                       goto out;
                }
 
                ret = copy_from_user(clone_sources_tmp, arg->clone_sources,
index 72a053c9a7f097bfc9086ed6e0035e62dfd76bb1..4f1cdd5058f12b9970b5894828498624a28c77b5 100644 (file)
@@ -1795,8 +1795,7 @@ static int btrfs_remount(struct super_block *sb, int *flags, char *data)
                }
 
                if (fs_info->fs_devices->missing_devices >
-                    fs_info->num_tolerated_disk_barrier_failures &&
-                   !(*flags & MS_RDONLY)) {
+                    fs_info->num_tolerated_disk_barrier_failures) {
                        btrfs_warn(fs_info,
                                "too many missing devices, writeable remount is not allowed");
                        ret = -EACCES;
index ea272432c9305177a1059db321f8aae6f89a09f3..b18ab8f327a53dd10b09bee6169f34ecff5eb809 100644 (file)
@@ -237,7 +237,6 @@ void btrfs_init_dummy_trans(struct btrfs_trans_handle *trans)
 {
        memset(trans, 0, sizeof(*trans));
        trans->transid = 1;
-       INIT_LIST_HEAD(&trans->qgroup_ref_list);
        trans->type = __TRANS_DUMMY;
 }
 
index 61b807de3e164e38877230cdfd1e9a545573f1be..2168654c90a1e6cab355d8270b23db68de0253c3 100644 (file)
@@ -60,8 +60,8 @@ static const unsigned int btrfs_blocked_trans_types[TRANS_STATE_MAX] = {
 
 void btrfs_put_transaction(struct btrfs_transaction *transaction)
 {
-       WARN_ON(atomic_read(&transaction->use_count) == 0);
-       if (atomic_dec_and_test(&transaction->use_count)) {
+       WARN_ON(refcount_read(&transaction->use_count) == 0);
+       if (refcount_dec_and_test(&transaction->use_count)) {
                BUG_ON(!list_empty(&transaction->list));
                WARN_ON(!RB_EMPTY_ROOT(&transaction->delayed_refs.href_root));
                if (transaction->delayed_refs.pending_csums)
@@ -207,7 +207,7 @@ loop:
                        spin_unlock(&fs_info->trans_lock);
                        return -EBUSY;
                }
-               atomic_inc(&cur_trans->use_count);
+               refcount_inc(&cur_trans->use_count);
                atomic_inc(&cur_trans->num_writers);
                extwriter_counter_inc(cur_trans, type);
                spin_unlock(&fs_info->trans_lock);
@@ -257,7 +257,7 @@ loop:
         * One for this trans handle, one so it will live on until we
         * commit the transaction.
         */
-       atomic_set(&cur_trans->use_count, 2);
+       refcount_set(&cur_trans->use_count, 2);
        atomic_set(&cur_trans->pending_ordered, 0);
        cur_trans->flags = 0;
        cur_trans->start_time = get_seconds();
@@ -432,7 +432,7 @@ static void wait_current_trans(struct btrfs_fs_info *fs_info)
        spin_lock(&fs_info->trans_lock);
        cur_trans = fs_info->running_transaction;
        if (cur_trans && is_transaction_blocked(cur_trans)) {
-               atomic_inc(&cur_trans->use_count);
+               refcount_inc(&cur_trans->use_count);
                spin_unlock(&fs_info->trans_lock);
 
                wait_event(fs_info->transaction_wait,
@@ -572,7 +572,6 @@ again:
 
        h->type = type;
        h->can_flush_pending_bgs = true;
-       INIT_LIST_HEAD(&h->qgroup_ref_list);
        INIT_LIST_HEAD(&h->new_bgs);
 
        smp_mb();
@@ -744,7 +743,7 @@ int btrfs_wait_for_commit(struct btrfs_fs_info *fs_info, u64 transid)
                list_for_each_entry(t, &fs_info->trans_list, list) {
                        if (t->transid == transid) {
                                cur_trans = t;
-                               atomic_inc(&cur_trans->use_count);
+                               refcount_inc(&cur_trans->use_count);
                                ret = 0;
                                break;
                        }
@@ -773,7 +772,7 @@ int btrfs_wait_for_commit(struct btrfs_fs_info *fs_info, u64 transid)
                                if (t->state == TRANS_STATE_COMPLETED)
                                        break;
                                cur_trans = t;
-                               atomic_inc(&cur_trans->use_count);
+                               refcount_inc(&cur_trans->use_count);
                                break;
                        }
                }
@@ -917,7 +916,6 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
                wake_up_process(info->transaction_kthread);
                err = -EIO;
        }
-       assert_qgroups_uptodate(trans);
 
        kmem_cache_free(btrfs_trans_handle_cachep, trans);
        if (must_run_delayed_refs) {
@@ -1839,7 +1837,7 @@ int btrfs_commit_transaction_async(struct btrfs_trans_handle *trans,
 
        /* take transaction reference */
        cur_trans = trans->transaction;
-       atomic_inc(&cur_trans->use_count);
+       refcount_inc(&cur_trans->use_count);
 
        btrfs_end_transaction(trans);
 
@@ -2015,7 +2013,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
        spin_lock(&fs_info->trans_lock);
        if (cur_trans->state >= TRANS_STATE_COMMIT_START) {
                spin_unlock(&fs_info->trans_lock);
-               atomic_inc(&cur_trans->use_count);
+               refcount_inc(&cur_trans->use_count);
                ret = btrfs_end_transaction(trans);
 
                wait_for_commit(cur_trans);
@@ -2035,7 +2033,7 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
                prev_trans = list_entry(cur_trans->list.prev,
                                        struct btrfs_transaction, list);
                if (prev_trans->state != TRANS_STATE_COMPLETED) {
-                       atomic_inc(&prev_trans->use_count);
+                       refcount_inc(&prev_trans->use_count);
                        spin_unlock(&fs_info->trans_lock);
 
                        wait_for_commit(prev_trans);
@@ -2130,13 +2128,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
                goto scrub_continue;
        }
 
-       /* Reocrd old roots for later qgroup accounting */
-       ret = btrfs_qgroup_prepare_account_extents(trans, fs_info);
-       if (ret) {
-               mutex_unlock(&fs_info->reloc_mutex);
-               goto scrub_continue;
-       }
-
        /*
         * make sure none of the code above managed to slip in a
         * delayed item
@@ -2178,6 +2169,24 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
         */
        btrfs_free_log_root_tree(trans, fs_info);
 
+       /*
+        * commit_fs_roots() can call btrfs_save_ino_cache(), which generates
+        * new delayed refs. Must handle them or qgroup can be wrong.
+        */
+       ret = btrfs_run_delayed_refs(trans, fs_info, (unsigned long)-1);
+       if (ret) {
+               mutex_unlock(&fs_info->tree_log_mutex);
+               mutex_unlock(&fs_info->reloc_mutex);
+               goto scrub_continue;
+       }
+
+       ret = btrfs_qgroup_prepare_account_extents(trans, fs_info);
+       if (ret) {
+               mutex_unlock(&fs_info->tree_log_mutex);
+               mutex_unlock(&fs_info->reloc_mutex);
+               goto scrub_continue;
+       }
+
        /*
         * Since fs roots are all committed, we can get a quite accurate
         * new_roots. So let's do quota accounting.
@@ -2223,7 +2232,6 @@ int btrfs_commit_transaction(struct btrfs_trans_handle *trans)
 
        switch_commit_roots(cur_trans, fs_info);
 
-       assert_qgroups_uptodate(trans);
        ASSERT(list_empty(&cur_trans->dirty_bgs));
        ASSERT(list_empty(&cur_trans->io_bgs));
        update_super_roots(fs_info);
index 5dfb5590fff654a077fd95704682293bfc948a8f..c55e44560103b48e2a917701899c611732d8a013 100644 (file)
@@ -18,6 +18,8 @@
 
 #ifndef __BTRFS_TRANSACTION__
 #define __BTRFS_TRANSACTION__
+
+#include <linux/refcount.h>
 #include "btrfs_inode.h"
 #include "delayed-ref.h"
 #include "ctree.h"
@@ -49,7 +51,7 @@ struct btrfs_transaction {
         * transaction can end
         */
        atomic_t num_writers;
-       atomic_t use_count;
+       refcount_t use_count;
        atomic_t pending_ordered;
 
        unsigned long flags;
@@ -125,8 +127,6 @@ struct btrfs_trans_handle {
        unsigned int type;
        struct btrfs_root *root;
        struct btrfs_fs_info *fs_info;
-       struct seq_list delayed_ref_elem;
-       struct list_head qgroup_ref_list;
        struct list_head new_bgs;
 };
 
index a59674c3e69efb76d27d6705b41ca76d94e82e15..ccfe9fe7754a8d4d80fd3e5b1f0a1d2f2118e4e6 100644 (file)
@@ -4196,7 +4196,7 @@ static int btrfs_log_changed_extents(struct btrfs_trans_handle *trans,
                if (em->generation <= test_gen)
                        continue;
                /* Need a ref to keep it from getting evicted from cache */
-               atomic_inc(&em->refs);
+               refcount_inc(&em->refs);
                set_bit(EXTENT_FLAG_LOGGING, &em->flags);
                list_add_tail(&em->list, &extents);
                num++;
index ab8a66d852f91cb04206361a551b8c57760c9c40..017b67daa3bbf375919019e5c089b94f97d3e2a5 100644 (file)
@@ -139,6 +139,11 @@ static int btrfs_relocate_sys_chunks(struct btrfs_fs_info *fs_info);
 static void __btrfs_reset_dev_stats(struct btrfs_device *dev);
 static void btrfs_dev_stat_print_on_error(struct btrfs_device *dev);
 static void btrfs_dev_stat_print_on_load(struct btrfs_device *device);
+static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
+                            enum btrfs_map_op op,
+                            u64 logical, u64 *length,
+                            struct btrfs_bio **bbio_ret,
+                            int mirror_num, int need_raid_map);
 
 DEFINE_MUTEX(uuid_mutex);
 static LIST_HEAD(fs_uuids);
@@ -1008,14 +1013,13 @@ static int __btrfs_open_devices(struct btrfs_fs_devices *fs_devices,
                q = bdev_get_queue(bdev);
                if (blk_queue_discard(q))
                        device->can_discard = 1;
+               if (!blk_queue_nonrot(q))
+                       fs_devices->rotating = 1;
 
                device->bdev = bdev;
                device->in_fs_metadata = 0;
                device->mode = flags;
 
-               if (!blk_queue_nonrot(bdev_get_queue(bdev)))
-                       fs_devices->rotating = 1;
-
                fs_devices->open_devices++;
                if (device->writeable &&
                    device->devid != BTRFS_DEV_REPLACE_DEVID) {
@@ -2417,7 +2421,7 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
        fs_info->free_chunk_space += device->total_bytes;
        spin_unlock(&fs_info->free_chunk_lock);
 
-       if (!blk_queue_nonrot(bdev_get_queue(bdev)))
+       if (!blk_queue_nonrot(q))
                fs_info->fs_devices->rotating = 1;
 
        tmp = btrfs_super_total_bytes(fs_info->super_copy);
@@ -2795,10 +2799,38 @@ static int btrfs_del_sys_chunk(struct btrfs_fs_info *fs_info,
        return ret;
 }
 
+static struct extent_map *get_chunk_map(struct btrfs_fs_info *fs_info,
+                                       u64 logical, u64 length)
+{
+       struct extent_map_tree *em_tree;
+       struct extent_map *em;
+
+       em_tree = &fs_info->mapping_tree.map_tree;
+       read_lock(&em_tree->lock);
+       em = lookup_extent_mapping(em_tree, logical, length);
+       read_unlock(&em_tree->lock);
+
+       if (!em) {
+               btrfs_crit(fs_info, "unable to find logical %llu length %llu",
+                          logical, length);
+               return ERR_PTR(-EINVAL);
+       }
+
+       if (em->start > logical || em->start + em->len < logical) {
+               btrfs_crit(fs_info,
+                          "found a bad mapping, wanted %llu-%llu, found %llu-%llu",
+                          logical, length, em->start, em->start + em->len);
+               free_extent_map(em);
+               return ERR_PTR(-EINVAL);
+       }
+
+       /* callers are responsible for dropping em's ref. */
+       return em;
+}
+
 int btrfs_remove_chunk(struct btrfs_trans_handle *trans,
                       struct btrfs_fs_info *fs_info, u64 chunk_offset)
 {
-       struct extent_map_tree *em_tree;
        struct extent_map *em;
        struct map_lookup *map;
        u64 dev_extent_len = 0;
@@ -2806,23 +2838,15 @@ int btrfs_remove_chunk(struct btrfs_trans_handle *trans,
        int i, ret = 0;
        struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
 
-       em_tree = &fs_info->mapping_tree.map_tree;
-
-       read_lock(&em_tree->lock);
-       em = lookup_extent_mapping(em_tree, chunk_offset, 1);
-       read_unlock(&em_tree->lock);
-
-       if (!em || em->start > chunk_offset ||
-           em->start + em->len < chunk_offset) {
+       em = get_chunk_map(fs_info, chunk_offset, 1);
+       if (IS_ERR(em)) {
                /*
                 * This is a logic error, but we don't want to just rely on the
                 * user having built with ASSERT enabled, so if ASSERT doesn't
                 * do anything we still error out.
                 */
                ASSERT(0);
-               if (em)
-                       free_extent_map(em);
-               return -EINVAL;
+               return PTR_ERR(em);
        }
        map = em->map_lookup;
        mutex_lock(&fs_info->chunk_mutex);
@@ -3736,7 +3760,7 @@ static void __cancel_balance(struct btrfs_fs_info *fs_info)
        if (ret)
                btrfs_handle_fs_error(fs_info, ret, NULL);
 
-       atomic_set(&fs_info->mutually_exclusive_operation_running, 0);
+       clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
 }
 
 /* Non-zero return value signifies invalidity */
@@ -3755,6 +3779,7 @@ int btrfs_balance(struct btrfs_balance_control *bctl,
                  struct btrfs_ioctl_balance_args *bargs)
 {
        struct btrfs_fs_info *fs_info = bctl->fs_info;
+       u64 meta_target, data_target;
        u64 allowed;
        int mixed = 0;
        int ret;
@@ -3851,11 +3876,16 @@ int btrfs_balance(struct btrfs_balance_control *bctl,
                }
        } while (read_seqretry(&fs_info->profiles_lock, seq));
 
-       if (btrfs_get_num_tolerated_disk_barrier_failures(bctl->meta.target) <
-               btrfs_get_num_tolerated_disk_barrier_failures(bctl->data.target)) {
+       /* if we're not converting, the target field is uninitialized */
+       meta_target = (bctl->meta.flags & BTRFS_BALANCE_ARGS_CONVERT) ?
+               bctl->meta.target : fs_info->avail_metadata_alloc_bits;
+       data_target = (bctl->data.flags & BTRFS_BALANCE_ARGS_CONVERT) ?
+               bctl->data.target : fs_info->avail_data_alloc_bits;
+       if (btrfs_get_num_tolerated_disk_barrier_failures(meta_target) <
+               btrfs_get_num_tolerated_disk_barrier_failures(data_target)) {
                btrfs_warn(fs_info,
                           "metadata profile 0x%llx has lower redundancy than data profile 0x%llx",
-                          bctl->meta.target, bctl->data.target);
+                          meta_target, data_target);
        }
 
        if (bctl->sys.flags & BTRFS_BALANCE_ARGS_CONVERT) {
@@ -3910,7 +3940,7 @@ out:
                __cancel_balance(fs_info);
        else {
                kfree(bctl);
-               atomic_set(&fs_info->mutually_exclusive_operation_running, 0);
+               clear_bit(BTRFS_FS_EXCL_OP, &fs_info->flags);
        }
        return ret;
 }
@@ -4000,7 +4030,7 @@ int btrfs_recover_balance(struct btrfs_fs_info *fs_info)
        btrfs_balance_sys(leaf, item, &disk_bargs);
        btrfs_disk_balance_args_to_cpu(&bctl->sys, &disk_bargs);
 
-       WARN_ON(atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1));
+       WARN_ON(test_and_set_bit(BTRFS_FS_EXCL_OP, &fs_info->flags));
 
        mutex_lock(&fs_info->volume_mutex);
        mutex_lock(&fs_info->balance_mutex);
@@ -4785,7 +4815,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
        stripe_size = div_u64(stripe_size, dev_stripes);
 
        /* align to BTRFS_STRIPE_LEN */
-       stripe_size = div_u64(stripe_size, raid_stripe_len);
+       stripe_size = div64_u64(stripe_size, raid_stripe_len);
        stripe_size *= raid_stripe_len;
 
        map = kmalloc(map_lookup_size(num_stripes), GFP_NOFS);
@@ -4833,7 +4863,7 @@ static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
        ret = add_extent_mapping(em_tree, em, 0);
        if (!ret) {
                list_add_tail(&em->list, &trans->transaction->pending_chunks);
-               atomic_inc(&em->refs);
+               refcount_inc(&em->refs);
        }
        write_unlock(&em_tree->lock);
        if (ret) {
@@ -4888,7 +4918,6 @@ int btrfs_finish_chunk_alloc(struct btrfs_trans_handle *trans,
        struct btrfs_device *device;
        struct btrfs_chunk *chunk;
        struct btrfs_stripe *stripe;
-       struct extent_map_tree *em_tree;
        struct extent_map *em;
        struct map_lookup *map;
        size_t item_size;
@@ -4897,24 +4926,9 @@ int btrfs_finish_chunk_alloc(struct btrfs_trans_handle *trans,
        int i = 0;
        int ret = 0;
 
-       em_tree = &fs_info->mapping_tree.map_tree;
-       read_lock(&em_tree->lock);
-       em = lookup_extent_mapping(em_tree, chunk_offset, chunk_size);
-       read_unlock(&em_tree->lock);
-
-       if (!em) {
-               btrfs_crit(fs_info, "unable to find logical %Lu len %Lu",
-                          chunk_offset, chunk_size);
-               return -EINVAL;
-       }
-
-       if (em->start != chunk_offset || em->len != chunk_size) {
-               btrfs_crit(fs_info,
-                          "found a bad mapping, wanted %Lu-%Lu, found %Lu-%Lu",
-                           chunk_offset, chunk_size, em->start, em->len);
-               free_extent_map(em);
-               return -EINVAL;
-       }
+       em = get_chunk_map(fs_info, chunk_offset, chunk_size);
+       if (IS_ERR(em))
+               return PTR_ERR(em);
 
        map = em->map_lookup;
        item_size = btrfs_chunk_item_size(map->num_stripes);
@@ -5055,15 +5069,12 @@ int btrfs_chunk_readonly(struct btrfs_fs_info *fs_info, u64 chunk_offset)
 {
        struct extent_map *em;
        struct map_lookup *map;
-       struct btrfs_mapping_tree *map_tree = &fs_info->mapping_tree;
        int readonly = 0;
        int miss_ndevs = 0;
        int i;
 
-       read_lock(&map_tree->map_tree.lock);
-       em = lookup_extent_mapping(&map_tree->map_tree, chunk_offset, 1);
-       read_unlock(&map_tree->map_tree.lock);
-       if (!em)
+       em = get_chunk_map(fs_info, chunk_offset, 1);
+       if (IS_ERR(em))
                return 1;
 
        map = em->map_lookup;
@@ -5117,34 +5128,19 @@ void btrfs_mapping_tree_free(struct btrfs_mapping_tree *tree)
 
 int btrfs_num_copies(struct btrfs_fs_info *fs_info, u64 logical, u64 len)
 {
-       struct btrfs_mapping_tree *map_tree = &fs_info->mapping_tree;
        struct extent_map *em;
        struct map_lookup *map;
-       struct extent_map_tree *em_tree = &map_tree->map_tree;
        int ret;
 
-       read_lock(&em_tree->lock);
-       em = lookup_extent_mapping(em_tree, logical, len);
-       read_unlock(&em_tree->lock);
-
-       /*
-        * We could return errors for these cases, but that could get ugly and
-        * we'd probably do the same thing which is just not do anything else
-        * and exit, so return 1 so the callers don't try to use other copies.
-        */
-       if (!em) {
-               btrfs_crit(fs_info, "No mapping for %Lu-%Lu", logical,
-                           logical+len);
-               return 1;
-       }
-
-       if (em->start > logical || em->start + em->len < logical) {
-               btrfs_crit(fs_info, "Invalid mapping for %Lu-%Lu, got %Lu-%Lu",
-                          logical, logical+len, em->start,
-                          em->start + em->len);
-               free_extent_map(em);
+       em = get_chunk_map(fs_info, logical, len);
+       if (IS_ERR(em))
+               /*
+                * We could return errors for these cases, but that could get
+                * ugly and we'd probably do the same thing which is just not do
+                * anything else and exit, so return 1 so the callers don't try
+                * to use other copies.
+                */
                return 1;
-       }
 
        map = em->map_lookup;
        if (map->type & (BTRFS_BLOCK_GROUP_DUP | BTRFS_BLOCK_GROUP_RAID1))
@@ -5160,7 +5156,8 @@ int btrfs_num_copies(struct btrfs_fs_info *fs_info, u64 logical, u64 len)
        free_extent_map(em);
 
        btrfs_dev_replace_lock(&fs_info->dev_replace, 0);
-       if (btrfs_dev_replace_is_ongoing(&fs_info->dev_replace))
+       if (btrfs_dev_replace_is_ongoing(&fs_info->dev_replace) &&
+           fs_info->dev_replace.tgtdev)
                ret++;
        btrfs_dev_replace_unlock(&fs_info->dev_replace, 0);
 
@@ -5173,15 +5170,11 @@ unsigned long btrfs_full_stripe_len(struct btrfs_fs_info *fs_info,
 {
        struct extent_map *em;
        struct map_lookup *map;
-       struct extent_map_tree *em_tree = &map_tree->map_tree;
        unsigned long len = fs_info->sectorsize;
 
-       read_lock(&em_tree->lock);
-       em = lookup_extent_mapping(em_tree, logical, len);
-       read_unlock(&em_tree->lock);
-       BUG_ON(!em);
+       em = get_chunk_map(fs_info, logical, len);
+       WARN_ON(IS_ERR(em));
 
-       BUG_ON(em->start > logical || em->start + em->len < logical);
        map = em->map_lookup;
        if (map->type & BTRFS_BLOCK_GROUP_RAID56_MASK)
                len = map->stripe_len * nr_data_stripes(map);
@@ -5189,20 +5182,16 @@ unsigned long btrfs_full_stripe_len(struct btrfs_fs_info *fs_info,
        return len;
 }
 
-int btrfs_is_parity_mirror(struct btrfs_mapping_tree *map_tree,
+int btrfs_is_parity_mirror(struct btrfs_fs_info *fs_info,
                           u64 logical, u64 len, int mirror_num)
 {
        struct extent_map *em;
        struct map_lookup *map;
-       struct extent_map_tree *em_tree = &map_tree->map_tree;
        int ret = 0;
 
-       read_lock(&em_tree->lock);
-       em = lookup_extent_mapping(em_tree, logical, len);
-       read_unlock(&em_tree->lock);
-       BUG_ON(!em);
+       em = get_chunk_map(fs_info, logical, len);
+       WARN_ON(IS_ERR(em));
 
-       BUG_ON(em->start > logical || em->start + em->len < logical);
        map = em->map_lookup;
        if (map->type & BTRFS_BLOCK_GROUP_RAID56_MASK)
                ret = 1;
@@ -5295,25 +5284,353 @@ static struct btrfs_bio *alloc_btrfs_bio(int total_stripes, int real_stripes)
                GFP_NOFS|__GFP_NOFAIL);
 
        atomic_set(&bbio->error, 0);
-       atomic_set(&bbio->refs, 1);
+       refcount_set(&bbio->refs, 1);
 
        return bbio;
 }
 
 void btrfs_get_bbio(struct btrfs_bio *bbio)
 {
-       WARN_ON(!atomic_read(&bbio->refs));
-       atomic_inc(&bbio->refs);
+       WARN_ON(!refcount_read(&bbio->refs));
+       refcount_inc(&bbio->refs);
 }
 
 void btrfs_put_bbio(struct btrfs_bio *bbio)
 {
        if (!bbio)
                return;
-       if (atomic_dec_and_test(&bbio->refs))
+       if (refcount_dec_and_test(&bbio->refs))
                kfree(bbio);
 }
 
+/* can REQ_OP_DISCARD be sent with other REQ like REQ_OP_WRITE? */
+/*
+ * Please note that, discard won't be sent to target device of device
+ * replace.
+ */
+static int __btrfs_map_block_for_discard(struct btrfs_fs_info *fs_info,
+                                        u64 logical, u64 length,
+                                        struct btrfs_bio **bbio_ret)
+{
+       struct extent_map *em;
+       struct map_lookup *map;
+       struct btrfs_bio *bbio;
+       u64 offset;
+       u64 stripe_nr;
+       u64 stripe_nr_end;
+       u64 stripe_end_offset;
+       u64 stripe_cnt;
+       u64 stripe_len;
+       u64 stripe_offset;
+       u64 num_stripes;
+       u32 stripe_index;
+       u32 factor = 0;
+       u32 sub_stripes = 0;
+       u64 stripes_per_dev = 0;
+       u32 remaining_stripes = 0;
+       u32 last_stripe = 0;
+       int ret = 0;
+       int i;
+
+       /* discard always return a bbio */
+       ASSERT(bbio_ret);
+
+       em = get_chunk_map(fs_info, logical, length);
+       if (IS_ERR(em))
+               return PTR_ERR(em);
+
+       map = em->map_lookup;
+       /* we don't discard raid56 yet */
+       if (map->type & BTRFS_BLOCK_GROUP_RAID56_MASK) {
+               ret = -EOPNOTSUPP;
+               goto out;
+       }
+
+       offset = logical - em->start;
+       length = min_t(u64, em->len - offset, length);
+
+       stripe_len = map->stripe_len;
+       /*
+        * stripe_nr counts the total number of stripes we have to stride
+        * to get to this block
+        */
+       stripe_nr = div64_u64(offset, stripe_len);
+
+       /* stripe_offset is the offset of this block in its stripe */
+       stripe_offset = offset - stripe_nr * stripe_len;
+
+       stripe_nr_end = round_up(offset + length, map->stripe_len);
+       stripe_nr_end = div64_u64(stripe_nr_end, map->stripe_len);
+       stripe_cnt = stripe_nr_end - stripe_nr;
+       stripe_end_offset = stripe_nr_end * map->stripe_len -
+                           (offset + length);
+       /*
+        * after this, stripe_nr is the number of stripes on this
+        * device we have to walk to find the data, and stripe_index is
+        * the number of our device in the stripe array
+        */
+       num_stripes = 1;
+       stripe_index = 0;
+       if (map->type & (BTRFS_BLOCK_GROUP_RAID0 |
+                        BTRFS_BLOCK_GROUP_RAID10)) {
+               if (map->type & BTRFS_BLOCK_GROUP_RAID0)
+                       sub_stripes = 1;
+               else
+                       sub_stripes = map->sub_stripes;
+
+               factor = map->num_stripes / sub_stripes;
+               num_stripes = min_t(u64, map->num_stripes,
+                                   sub_stripes * stripe_cnt);
+               stripe_nr = div_u64_rem(stripe_nr, factor, &stripe_index);
+               stripe_index *= sub_stripes;
+               stripes_per_dev = div_u64_rem(stripe_cnt, factor,
+                                             &remaining_stripes);
+               div_u64_rem(stripe_nr_end - 1, factor, &last_stripe);
+               last_stripe *= sub_stripes;
+       } else if (map->type & (BTRFS_BLOCK_GROUP_RAID1 |
+                               BTRFS_BLOCK_GROUP_DUP)) {
+               num_stripes = map->num_stripes;
+       } else {
+               stripe_nr = div_u64_rem(stripe_nr, map->num_stripes,
+                                       &stripe_index);
+       }
+
+       bbio = alloc_btrfs_bio(num_stripes, 0);
+       if (!bbio) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       for (i = 0; i < num_stripes; i++) {
+               bbio->stripes[i].physical =
+                       map->stripes[stripe_index].physical +
+                       stripe_offset + stripe_nr * map->stripe_len;
+               bbio->stripes[i].dev = map->stripes[stripe_index].dev;
+
+               if (map->type & (BTRFS_BLOCK_GROUP_RAID0 |
+                                BTRFS_BLOCK_GROUP_RAID10)) {
+                       bbio->stripes[i].length = stripes_per_dev *
+                               map->stripe_len;
+
+                       if (i / sub_stripes < remaining_stripes)
+                               bbio->stripes[i].length +=
+                                       map->stripe_len;
+
+                       /*
+                        * Special for the first stripe and
+                        * the last stripe:
+                        *
+                        * |-------|...|-------|
+                        *     |----------|
+                        *    off     end_off
+                        */
+                       if (i < sub_stripes)
+                               bbio->stripes[i].length -=
+                                       stripe_offset;
+
+                       if (stripe_index >= last_stripe &&
+                           stripe_index <= (last_stripe +
+                                            sub_stripes - 1))
+                               bbio->stripes[i].length -=
+                                       stripe_end_offset;
+
+                       if (i == sub_stripes - 1)
+                               stripe_offset = 0;
+               } else {
+                       bbio->stripes[i].length = length;
+               }
+
+               stripe_index++;
+               if (stripe_index == map->num_stripes) {
+                       stripe_index = 0;
+                       stripe_nr++;
+               }
+       }
+
+       *bbio_ret = bbio;
+       bbio->map_type = map->type;
+       bbio->num_stripes = num_stripes;
+out:
+       free_extent_map(em);
+       return ret;
+}
+
+/*
+ * In dev-replace case, for repair case (that's the only case where the mirror
+ * is selected explicitly when calling btrfs_map_block), blocks left of the
+ * left cursor can also be read from the target drive.
+ *
+ * For REQ_GET_READ_MIRRORS, the target drive is added as the last one to the
+ * array of stripes.
+ * For READ, it also needs to be supported using the same mirror number.
+ *
+ * If the requested block is not left of the left cursor, EIO is returned. This
+ * can happen because btrfs_num_copies() returns one more in the dev-replace
+ * case.
+ */
+static int get_extra_mirror_from_replace(struct btrfs_fs_info *fs_info,
+                                        u64 logical, u64 length,
+                                        u64 srcdev_devid, int *mirror_num,
+                                        u64 *physical)
+{
+       struct btrfs_bio *bbio = NULL;
+       int num_stripes;
+       int index_srcdev = 0;
+       int found = 0;
+       u64 physical_of_found = 0;
+       int i;
+       int ret = 0;
+
+       ret = __btrfs_map_block(fs_info, BTRFS_MAP_GET_READ_MIRRORS,
+                               logical, &length, &bbio, 0, 0);
+       if (ret) {
+               ASSERT(bbio == NULL);
+               return ret;
+       }
+
+       num_stripes = bbio->num_stripes;
+       if (*mirror_num > num_stripes) {
+               /*
+                * BTRFS_MAP_GET_READ_MIRRORS does not contain this mirror,
+                * that means that the requested area is not left of the left
+                * cursor
+                */
+               btrfs_put_bbio(bbio);
+               return -EIO;
+       }
+
+       /*
+        * process the rest of the function using the mirror_num of the source
+        * drive. Therefore look it up first.  At the end, patch the device
+        * pointer to the one of the target drive.
+        */
+       for (i = 0; i < num_stripes; i++) {
+               if (bbio->stripes[i].dev->devid != srcdev_devid)
+                       continue;
+
+               /*
+                * In case of DUP, in order to keep it simple, only add the
+                * mirror with the lowest physical address
+                */
+               if (found &&
+                   physical_of_found <= bbio->stripes[i].physical)
+                       continue;
+
+               index_srcdev = i;
+               found = 1;
+               physical_of_found = bbio->stripes[i].physical;
+       }
+
+       btrfs_put_bbio(bbio);
+
+       ASSERT(found);
+       if (!found)
+               return -EIO;
+
+       *mirror_num = index_srcdev + 1;
+       *physical = physical_of_found;
+       return ret;
+}
+
+static void handle_ops_on_dev_replace(enum btrfs_map_op op,
+                                     struct btrfs_bio **bbio_ret,
+                                     struct btrfs_dev_replace *dev_replace,
+                                     int *num_stripes_ret, int *max_errors_ret)
+{
+       struct btrfs_bio *bbio = *bbio_ret;
+       u64 srcdev_devid = dev_replace->srcdev->devid;
+       int tgtdev_indexes = 0;
+       int num_stripes = *num_stripes_ret;
+       int max_errors = *max_errors_ret;
+       int i;
+
+       if (op == BTRFS_MAP_WRITE) {
+               int index_where_to_add;
+
+               /*
+                * duplicate the write operations while the dev replace
+                * procedure is running. Since the copying of the old disk to
+                * the new disk takes place at run time while the filesystem is
+                * mounted writable, the regular write operations to the old
+                * disk have to be duplicated to go to the new disk as well.
+                *
+                * Note that device->missing is handled by the caller, and that
+                * the write to the old disk is already set up in the stripes
+                * array.
+                */
+               index_where_to_add = num_stripes;
+               for (i = 0; i < num_stripes; i++) {
+                       if (bbio->stripes[i].dev->devid == srcdev_devid) {
+                               /* write to new disk, too */
+                               struct btrfs_bio_stripe *new =
+                                       bbio->stripes + index_where_to_add;
+                               struct btrfs_bio_stripe *old =
+                                       bbio->stripes + i;
+
+                               new->physical = old->physical;
+                               new->length = old->length;
+                               new->dev = dev_replace->tgtdev;
+                               bbio->tgtdev_map[i] = index_where_to_add;
+                               index_where_to_add++;
+                               max_errors++;
+                               tgtdev_indexes++;
+                       }
+               }
+               num_stripes = index_where_to_add;
+       } else if (op == BTRFS_MAP_GET_READ_MIRRORS) {
+               int index_srcdev = 0;
+               int found = 0;
+               u64 physical_of_found = 0;
+
+               /*
+                * During the dev-replace procedure, the target drive can also
+                * be used to read data in case it is needed to repair a corrupt
+                * block elsewhere. This is possible if the requested area is
+                * left of the left cursor. In this area, the target drive is a
+                * full copy of the source drive.
+                */
+               for (i = 0; i < num_stripes; i++) {
+                       if (bbio->stripes[i].dev->devid == srcdev_devid) {
+                               /*
+                                * In case of DUP, in order to keep it simple,
+                                * only add the mirror with the lowest physical
+                                * address
+                                */
+                               if (found &&
+                                   physical_of_found <=
+                                    bbio->stripes[i].physical)
+                                       continue;
+                               index_srcdev = i;
+                               found = 1;
+                               physical_of_found = bbio->stripes[i].physical;
+                       }
+               }
+               if (found) {
+                       struct btrfs_bio_stripe *tgtdev_stripe =
+                               bbio->stripes + num_stripes;
+
+                       tgtdev_stripe->physical = physical_of_found;
+                       tgtdev_stripe->length =
+                               bbio->stripes[index_srcdev].length;
+                       tgtdev_stripe->dev = dev_replace->tgtdev;
+                       bbio->tgtdev_map[index_srcdev] = num_stripes;
+
+                       tgtdev_indexes++;
+                       num_stripes++;
+               }
+       }
+
+       *num_stripes_ret = num_stripes;
+       *max_errors_ret = max_errors;
+       bbio->num_tgtdevs = tgtdev_indexes;
+       *bbio_ret = bbio;
+}
+
+static bool need_full_stripe(enum btrfs_map_op op)
+{
+       return (op == BTRFS_MAP_WRITE || op == BTRFS_MAP_GET_READ_MIRRORS);
+}
+
 static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
                             enum btrfs_map_op op,
                             u64 logical, u64 *length,
@@ -5322,14 +5639,9 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
 {
        struct extent_map *em;
        struct map_lookup *map;
-       struct btrfs_mapping_tree *map_tree = &fs_info->mapping_tree;
-       struct extent_map_tree *em_tree = &map_tree->map_tree;
        u64 offset;
        u64 stripe_offset;
-       u64 stripe_end_offset;
        u64 stripe_nr;
-       u64 stripe_nr_orig;
-       u64 stripe_nr_end;
        u64 stripe_len;
        u32 stripe_index;
        int i;
@@ -5345,23 +5657,13 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
        u64 physical_to_patch_in_first_stripe = 0;
        u64 raid56_full_stripe_start = (u64)-1;
 
-       read_lock(&em_tree->lock);
-       em = lookup_extent_mapping(em_tree, logical, *length);
-       read_unlock(&em_tree->lock);
-
-       if (!em) {
-               btrfs_crit(fs_info, "unable to find logical %llu len %llu",
-                       logical, *length);
-               return -EINVAL;
-       }
+       if (op == BTRFS_MAP_DISCARD)
+               return __btrfs_map_block_for_discard(fs_info, logical,
+                                                    *length, bbio_ret);
 
-       if (em->start > logical || em->start + em->len < logical) {
-               btrfs_crit(fs_info,
-                          "found a bad mapping, wanted %Lu, found %Lu-%Lu",
-                          logical, em->start, em->start + em->len);
-               free_extent_map(em);
-               return -EINVAL;
-       }
+       em = get_chunk_map(fs_info, logical, *length);
+       if (IS_ERR(em))
+               return PTR_ERR(em);
 
        map = em->map_lookup;
        offset = logical - em->start;
@@ -5400,14 +5702,7 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
                raid56_full_stripe_start *= full_stripe_len;
        }
 
-       if (op == BTRFS_MAP_DISCARD) {
-               /* we don't discard raid56 yet */
-               if (map->type & BTRFS_BLOCK_GROUP_RAID56_MASK) {
-                       ret = -EOPNOTSUPP;
-                       goto out;
-               }
-               *length = min_t(u64, em->len - offset, *length);
-       } else if (map->type & BTRFS_BLOCK_GROUP_PROFILE_MASK) {
+       if (map->type & BTRFS_BLOCK_GROUP_PROFILE_MASK) {
                u64 max_len;
                /* For writes to RAID[56], allow a full stripeset across all disks.
                   For other RAID types and for RAID[56] reads, just allow a single
@@ -5438,105 +5733,28 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
                btrfs_dev_replace_set_lock_blocking(dev_replace);
 
        if (dev_replace_is_ongoing && mirror_num == map->num_stripes + 1 &&
-           op != BTRFS_MAP_WRITE && op != BTRFS_MAP_DISCARD &&
-           op != BTRFS_MAP_GET_READ_MIRRORS && dev_replace->tgtdev != NULL) {
-               /*
-                * in dev-replace case, for repair case (that's the only
-                * case where the mirror is selected explicitly when
-                * calling btrfs_map_block), blocks left of the left cursor
-                * can also be read from the target drive.
-                * For REQ_GET_READ_MIRRORS, the target drive is added as
-                * the last one to the array of stripes. For READ, it also
-                * needs to be supported using the same mirror number.
-                * If the requested block is not left of the left cursor,
-                * EIO is returned. This can happen because btrfs_num_copies()
-                * returns one more in the dev-replace case.
-                */
-               u64 tmp_length = *length;
-               struct btrfs_bio *tmp_bbio = NULL;
-               int tmp_num_stripes;
-               u64 srcdev_devid = dev_replace->srcdev->devid;
-               int index_srcdev = 0;
-               int found = 0;
-               u64 physical_of_found = 0;
-
-               ret = __btrfs_map_block(fs_info, BTRFS_MAP_GET_READ_MIRRORS,
-                            logical, &tmp_length, &tmp_bbio, 0, 0);
-               if (ret) {
-                       WARN_ON(tmp_bbio != NULL);
-                       goto out;
-               }
-
-               tmp_num_stripes = tmp_bbio->num_stripes;
-               if (mirror_num > tmp_num_stripes) {
-                       /*
-                        * BTRFS_MAP_GET_READ_MIRRORS does not contain this
-                        * mirror, that means that the requested area
-                        * is not left of the left cursor
-                        */
-                       ret = -EIO;
-                       btrfs_put_bbio(tmp_bbio);
-                       goto out;
-               }
-
-               /*
-                * process the rest of the function using the mirror_num
-                * of the source drive. Therefore look it up first.
-                * At the end, patch the device pointer to the one of the
-                * target drive.
-                */
-               for (i = 0; i < tmp_num_stripes; i++) {
-                       if (tmp_bbio->stripes[i].dev->devid != srcdev_devid)
-                               continue;
-
-                       /*
-                        * In case of DUP, in order to keep it simple, only add
-                        * the mirror with the lowest physical address
-                        */
-                       if (found &&
-                           physical_of_found <= tmp_bbio->stripes[i].physical)
-                               continue;
-
-                       index_srcdev = i;
-                       found = 1;
-                       physical_of_found = tmp_bbio->stripes[i].physical;
-               }
-
-               btrfs_put_bbio(tmp_bbio);
-
-               if (!found) {
-                       WARN_ON(1);
-                       ret = -EIO;
+           !need_full_stripe(op) && dev_replace->tgtdev != NULL) {
+               ret = get_extra_mirror_from_replace(fs_info, logical, *length,
+                                                   dev_replace->srcdev->devid,
+                                                   &mirror_num,
+                                           &physical_to_patch_in_first_stripe);
+               if (ret)
                        goto out;
-               }
-
-               mirror_num = index_srcdev + 1;
-               patch_the_first_stripe_for_dev_replace = 1;
-               physical_to_patch_in_first_stripe = physical_of_found;
+               else
+                       patch_the_first_stripe_for_dev_replace = 1;
        } else if (mirror_num > map->num_stripes) {
                mirror_num = 0;
        }
 
        num_stripes = 1;
        stripe_index = 0;
-       stripe_nr_orig = stripe_nr;
-       stripe_nr_end = ALIGN(offset + *length, map->stripe_len);
-       stripe_nr_end = div_u64(stripe_nr_end, map->stripe_len);
-       stripe_end_offset = stripe_nr_end * map->stripe_len -
-                           (offset + *length);
-
        if (map->type & BTRFS_BLOCK_GROUP_RAID0) {
-               if (op == BTRFS_MAP_DISCARD)
-                       num_stripes = min_t(u64, map->num_stripes,
-                                           stripe_nr_end - stripe_nr_orig);
                stripe_nr = div_u64_rem(stripe_nr, map->num_stripes,
                                &stripe_index);
-               if (op != BTRFS_MAP_WRITE && op != BTRFS_MAP_DISCARD &&
-                   op != BTRFS_MAP_GET_READ_MIRRORS)
+               if (op != BTRFS_MAP_WRITE && op != BTRFS_MAP_GET_READ_MIRRORS)
                        mirror_num = 1;
        } else if (map->type & BTRFS_BLOCK_GROUP_RAID1) {
-               if (op == BTRFS_MAP_WRITE || op == BTRFS_MAP_DISCARD ||
-                   op == BTRFS_MAP_GET_READ_MIRRORS)
+               if (op == BTRFS_MAP_WRITE || op == BTRFS_MAP_GET_READ_MIRRORS)
                        num_stripes = map->num_stripes;
                else if (mirror_num)
                        stripe_index = mirror_num - 1;
@@ -5549,8 +5767,7 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
                }
 
        } else if (map->type & BTRFS_BLOCK_GROUP_DUP) {
-               if (op == BTRFS_MAP_WRITE || op == BTRFS_MAP_DISCARD ||
-                   op == BTRFS_MAP_GET_READ_MIRRORS) {
+               if (op == BTRFS_MAP_WRITE || op == BTRFS_MAP_GET_READ_MIRRORS) {
                        num_stripes = map->num_stripes;
                } else if (mirror_num) {
                        stripe_index = mirror_num - 1;
@@ -5566,10 +5783,6 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
 
                if (op == BTRFS_MAP_WRITE || op == BTRFS_MAP_GET_READ_MIRRORS)
                        num_stripes = map->sub_stripes;
-               else if (op == BTRFS_MAP_DISCARD)
-                       num_stripes = min_t(u64, map->sub_stripes *
-                                           (stripe_nr_end - stripe_nr_orig),
-                                           map->num_stripes);
                else if (mirror_num)
                        stripe_index += mirror_num - 1;
                else {
@@ -5587,7 +5800,7 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
                    (op == BTRFS_MAP_WRITE || op == BTRFS_MAP_GET_READ_MIRRORS ||
                     mirror_num > 1)) {
                        /* push stripe_nr back to the start of the full stripe */
-                       stripe_nr = div_u64(raid56_full_stripe_start,
+                       stripe_nr = div64_u64(raid56_full_stripe_start,
                                        stripe_len * nr_data_stripes(map));
 
                        /* RAID[56] write or recovery. Return all stripes */
@@ -5612,8 +5825,9 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
                        /* We distribute the parity blocks across stripes */
                        div_u64_rem(stripe_nr + stripe_index, map->num_stripes,
                                        &stripe_index);
-                       if ((op != BTRFS_MAP_WRITE && op != BTRFS_MAP_DISCARD &&
-                           op != BTRFS_MAP_GET_READ_MIRRORS) && mirror_num <= 1)
+                       if ((op != BTRFS_MAP_WRITE &&
+                            op != BTRFS_MAP_GET_READ_MIRRORS) &&
+                           mirror_num <= 1)
                                mirror_num = 1;
                }
        } else {
@@ -5635,8 +5849,8 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
        }
 
        num_alloc_stripes = num_stripes;
-       if (dev_replace_is_ongoing) {
-               if (op == BTRFS_MAP_WRITE || op == BTRFS_MAP_DISCARD)
+       if (dev_replace_is_ongoing && dev_replace->tgtdev != NULL) {
+               if (op == BTRFS_MAP_WRITE)
                        num_alloc_stripes <<= 1;
                if (op == BTRFS_MAP_GET_READ_MIRRORS)
                        num_alloc_stripes++;
@@ -5648,14 +5862,12 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
                ret = -ENOMEM;
                goto out;
        }
-       if (dev_replace_is_ongoing)
+       if (dev_replace_is_ongoing && dev_replace->tgtdev != NULL)
                bbio->tgtdev_map = (int *)(bbio->stripes + num_alloc_stripes);
 
        /* build raid_map */
-       if (map->type & BTRFS_BLOCK_GROUP_RAID56_MASK &&
-           need_raid_map &&
-           ((op == BTRFS_MAP_WRITE || op == BTRFS_MAP_GET_READ_MIRRORS) ||
-           mirror_num > 1)) {
+       if (map->type & BTRFS_BLOCK_GROUP_RAID56_MASK && need_raid_map &&
+           (need_full_stripe(op) || mirror_num > 1)) {
                u64 tmp;
                unsigned rot;
 
@@ -5679,173 +5891,27 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
                                RAID6_Q_STRIPE;
        }
 
-       if (op == BTRFS_MAP_DISCARD) {
-               u32 factor = 0;
-               u32 sub_stripes = 0;
-               u64 stripes_per_dev = 0;
-               u32 remaining_stripes = 0;
-               u32 last_stripe = 0;
 
-               if (map->type &
-                   (BTRFS_BLOCK_GROUP_RAID0 | BTRFS_BLOCK_GROUP_RAID10)) {
-                       if (map->type & BTRFS_BLOCK_GROUP_RAID0)
-                               sub_stripes = 1;
-                       else
-                               sub_stripes = map->sub_stripes;
-
-                       factor = map->num_stripes / sub_stripes;
-                       stripes_per_dev = div_u64_rem(stripe_nr_end -
-                                                     stripe_nr_orig,
-                                                     factor,
-                                                     &remaining_stripes);
-                       div_u64_rem(stripe_nr_end - 1, factor, &last_stripe);
-                       last_stripe *= sub_stripes;
-               }
-
-               for (i = 0; i < num_stripes; i++) {
-                       bbio->stripes[i].physical =
-                               map->stripes[stripe_index].physical +
-                               stripe_offset + stripe_nr * map->stripe_len;
-                       bbio->stripes[i].dev = map->stripes[stripe_index].dev;
-
-                       if (map->type & (BTRFS_BLOCK_GROUP_RAID0 |
-                                        BTRFS_BLOCK_GROUP_RAID10)) {
-                               bbio->stripes[i].length = stripes_per_dev *
-                                                         map->stripe_len;
-
-                               if (i / sub_stripes < remaining_stripes)
-                                       bbio->stripes[i].length +=
-                                               map->stripe_len;
-
-                               /*
-                                * Special for the first stripe and
-                                * the last stripe:
-                                *
-                                * |-------|...|-------|
-                                *     |----------|
-                                *    off     end_off
-                                */
-                               if (i < sub_stripes)
-                                       bbio->stripes[i].length -=
-                                               stripe_offset;
-
-                               if (stripe_index >= last_stripe &&
-                                   stripe_index <= (last_stripe +
-                                                    sub_stripes - 1))
-                                       bbio->stripes[i].length -=
-                                               stripe_end_offset;
-
-                               if (i == sub_stripes - 1)
-                                       stripe_offset = 0;
-                       } else
-                               bbio->stripes[i].length = *length;
-
-                       stripe_index++;
-                       if (stripe_index == map->num_stripes) {
-                               /* This could only happen for RAID0/10 */
-                               stripe_index = 0;
-                               stripe_nr++;
-                       }
-               }
-       } else {
-               for (i = 0; i < num_stripes; i++) {
-                       bbio->stripes[i].physical =
-                               map->stripes[stripe_index].physical +
-                               stripe_offset +
-                               stripe_nr * map->stripe_len;
-                       bbio->stripes[i].dev =
-                               map->stripes[stripe_index].dev;
-                       stripe_index++;
-               }
+       for (i = 0; i < num_stripes; i++) {
+               bbio->stripes[i].physical =
+                       map->stripes[stripe_index].physical +
+                       stripe_offset +
+                       stripe_nr * map->stripe_len;
+               bbio->stripes[i].dev =
+                       map->stripes[stripe_index].dev;
+               stripe_index++;
        }
 
-       if (op == BTRFS_MAP_WRITE || op == BTRFS_MAP_GET_READ_MIRRORS)
+       if (need_full_stripe(op))
                max_errors = btrfs_chunk_max_errors(map);
 
        if (bbio->raid_map)
                sort_parity_stripes(bbio, num_stripes);
 
-       tgtdev_indexes = 0;
-       if (dev_replace_is_ongoing &&
-          (op == BTRFS_MAP_WRITE || op == BTRFS_MAP_DISCARD) &&
-           dev_replace->tgtdev != NULL) {
-               int index_where_to_add;
-               u64 srcdev_devid = dev_replace->srcdev->devid;
-
-               /*
-                * duplicate the write operations while the dev replace
-                * procedure is running. Since the copying of the old disk
-                * to the new disk takes place at run time while the
-                * filesystem is mounted writable, the regular write
-                * operations to the old disk have to be duplicated to go
-                * to the new disk as well.
-                * Note that device->missing is handled by the caller, and
-                * that the write to the old disk is already set up in the
-                * stripes array.
-                */
-               index_where_to_add = num_stripes;
-               for (i = 0; i < num_stripes; i++) {
-                       if (bbio->stripes[i].dev->devid == srcdev_devid) {
-                               /* write to new disk, too */
-                               struct btrfs_bio_stripe *new =
-                                       bbio->stripes + index_where_to_add;
-                               struct btrfs_bio_stripe *old =
-                                       bbio->stripes + i;
-
-                               new->physical = old->physical;
-                               new->length = old->length;
-                               new->dev = dev_replace->tgtdev;
-                               bbio->tgtdev_map[i] = index_where_to_add;
-                               index_where_to_add++;
-                               max_errors++;
-                               tgtdev_indexes++;
-                       }
-               }
-               num_stripes = index_where_to_add;
-       } else if (dev_replace_is_ongoing &&
-                  op == BTRFS_MAP_GET_READ_MIRRORS &&
-                  dev_replace->tgtdev != NULL) {
-               u64 srcdev_devid = dev_replace->srcdev->devid;
-               int index_srcdev = 0;
-               int found = 0;
-               u64 physical_of_found = 0;
-
-               /*
-                * During the dev-replace procedure, the target drive can
-                * also be used to read data in case it is needed to repair
-                * a corrupt block elsewhere. This is possible if the
-                * requested area is left of the left cursor. In this area,
-                * the target drive is a full copy of the source drive.
-                */
-               for (i = 0; i < num_stripes; i++) {
-                       if (bbio->stripes[i].dev->devid == srcdev_devid) {
-                               /*
-                                * In case of DUP, in order to keep it
-                                * simple, only add the mirror with the
-                                * lowest physical address
-                                */
-                               if (found &&
-                                   physical_of_found <=
-                                    bbio->stripes[i].physical)
-                                       continue;
-                               index_srcdev = i;
-                               found = 1;
-                               physical_of_found = bbio->stripes[i].physical;
-                       }
-               }
-               if (found) {
-                       struct btrfs_bio_stripe *tgtdev_stripe =
-                               bbio->stripes + num_stripes;
-
-                       tgtdev_stripe->physical = physical_of_found;
-                       tgtdev_stripe->length =
-                               bbio->stripes[index_srcdev].length;
-                       tgtdev_stripe->dev = dev_replace->tgtdev;
-                       bbio->tgtdev_map[index_srcdev] = num_stripes;
-
-                       tgtdev_indexes++;
-                       num_stripes++;
-               }
+       if (dev_replace_is_ongoing && dev_replace->tgtdev != NULL &&
+           need_full_stripe(op)) {
+               handle_ops_on_dev_replace(op, &bbio, dev_replace, &num_stripes,
+                                         &max_errors);
        }
 
        *bbio_ret = bbio;
@@ -5853,7 +5919,6 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info,
        bbio->num_stripes = num_stripes;
        bbio->max_errors = max_errors;
        bbio->mirror_num = mirror_num;
-       bbio->num_tgtdevs = tgtdev_indexes;
 
        /*
         * this is the case that REQ_READ && dev_replace_is_ongoing &&
@@ -5886,19 +5951,15 @@ int btrfs_map_block(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
 /* For Scrub/replace */
 int btrfs_map_sblock(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
                     u64 logical, u64 *length,
-                    struct btrfs_bio **bbio_ret, int mirror_num,
-                    int need_raid_map)
+                    struct btrfs_bio **bbio_ret)
 {
-       return __btrfs_map_block(fs_info, op, logical, length, bbio_ret,
-                                mirror_num, need_raid_map);
+       return __btrfs_map_block(fs_info, op, logical, length, bbio_ret, 0, 1);
 }
 
 int btrfs_rmap_block(struct btrfs_fs_info *fs_info,
                     u64 chunk_start, u64 physical, u64 devid,
                     u64 **logical, int *naddrs, int *stripe_len)
 {
-       struct btrfs_mapping_tree *map_tree = &fs_info->mapping_tree;
-       struct extent_map_tree *em_tree = &map_tree->map_tree;
        struct extent_map *em;
        struct map_lookup *map;
        u64 *buf;
@@ -5908,24 +5969,11 @@ int btrfs_rmap_block(struct btrfs_fs_info *fs_info,
        u64 rmap_len;
        int i, j, nr = 0;
 
-       read_lock(&em_tree->lock);
-       em = lookup_extent_mapping(em_tree, chunk_start, 1);
-       read_unlock(&em_tree->lock);
-
-       if (!em) {
-               btrfs_err(fs_info, "couldn't find em for chunk %Lu",
-                       chunk_start);
+       em = get_chunk_map(fs_info, chunk_start, 1);
+       if (IS_ERR(em))
                return -EIO;
-       }
 
-       if (em->start != chunk_start) {
-               btrfs_err(fs_info, "bad chunk start, em=%Lu, wanted=%Lu",
-                      em->start, chunk_start);
-               free_extent_map(em);
-               return -EIO;
-       }
        map = em->map_lookup;
-
        length = em->len;
        rmap_len = map->stripe_len;
 
@@ -5949,7 +5997,7 @@ int btrfs_rmap_block(struct btrfs_fs_info *fs_info,
                        continue;
 
                stripe_nr = physical - map->stripes[i].physical;
-               stripe_nr = div_u64(stripe_nr, map->stripe_len);
+               stripe_nr = div64_u64(stripe_nr, map->stripe_len);
 
                if (map->type & BTRFS_BLOCK_GROUP_RAID10) {
                        stripe_nr = stripe_nr * map->num_stripes + i;
index 59be81206dd7b949683ad95c80fa561c022ad812..c7d0fbc915cabdee7cfec437e18f795ace77abbb 100644 (file)
@@ -123,7 +123,6 @@ struct btrfs_device {
        struct list_head resized_list;
 
        /* for sending down flush barriers */
-       int nobarriers;
        struct bio *flush_bio;
        struct completion flush_wait;
 
@@ -298,7 +297,7 @@ struct btrfs_bio;
 typedef void (btrfs_bio_end_io_t) (struct btrfs_bio *bio, int err);
 
 struct btrfs_bio {
-       atomic_t refs;
+       refcount_t refs;
        atomic_t stripes_pending;
        struct btrfs_fs_info *fs_info;
        u64 map_type; /* get from map_lookup->type */
@@ -400,8 +399,7 @@ int btrfs_map_block(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
                    struct btrfs_bio **bbio_ret, int mirror_num);
 int btrfs_map_sblock(struct btrfs_fs_info *fs_info, enum btrfs_map_op op,
                     u64 logical, u64 *length,
-                    struct btrfs_bio **bbio_ret, int mirror_num,
-                    int need_raid_map);
+                    struct btrfs_bio **bbio_ret);
 int btrfs_rmap_block(struct btrfs_fs_info *fs_info,
                     u64 chunk_start, u64 physical, u64 devid,
                     u64 **logical, int *naddrs, int *stripe_len);
@@ -475,7 +473,7 @@ void btrfs_destroy_dev_replace_tgtdev(struct btrfs_fs_info *fs_info,
 void btrfs_init_dev_replace_tgtdev_for_resume(struct btrfs_fs_info *fs_info,
                                              struct btrfs_device *tgtdev);
 void btrfs_scratch_superblocks(struct block_device *bdev, const char *device_path);
-int btrfs_is_parity_mirror(struct btrfs_mapping_tree *map_tree,
+int btrfs_is_parity_mirror(struct btrfs_fs_info *fs_info,
                           u64 logical, u64 len, int mirror_num);
 unsigned long btrfs_full_stripe_len(struct btrfs_fs_info *fs_info,
                                    struct btrfs_mapping_tree *map_tree,
index 9196f2a270daac4d8d4612be27a0bd8288657335..161be58c5cb0f738754b79d87eda879aa3bb9553 100644 (file)
@@ -49,7 +49,6 @@
 
 static int fsync_buffers_list(spinlock_t *lock, struct list_head *list);
 static int submit_bh_wbc(int op, int op_flags, struct buffer_head *bh,
-                        unsigned long bio_flags,
                         struct writeback_control *wbc);
 
 #define BH_ENTRY(list) list_entry((list), struct buffer_head, b_assoc_buffers)
@@ -1830,7 +1829,7 @@ int __block_write_full_page(struct inode *inode, struct page *page,
        do {
                struct buffer_head *next = bh->b_this_page;
                if (buffer_async_write(bh)) {
-                       submit_bh_wbc(REQ_OP_WRITE, write_flags, bh, 0, wbc);
+                       submit_bh_wbc(REQ_OP_WRITE, write_flags, bh, wbc);
                        nr_underway++;
                }
                bh = next;
@@ -1884,7 +1883,7 @@ recover:
                struct buffer_head *next = bh->b_this_page;
                if (buffer_async_write(bh)) {
                        clear_buffer_dirty(bh);
-                       submit_bh_wbc(REQ_OP_WRITE, write_flags, bh, 0, wbc);
+                       submit_bh_wbc(REQ_OP_WRITE, write_flags, bh, wbc);
                        nr_underway++;
                }
                bh = next;
@@ -2379,8 +2378,7 @@ int generic_cont_expand_simple(struct inode *inode, loff_t size)
                goto out;
 
        err = pagecache_write_begin(NULL, mapping, size, 0,
-                               AOP_FLAG_UNINTERRUPTIBLE|AOP_FLAG_CONT_EXPAND,
-                               &page, &fsdata);
+                                   AOP_FLAG_CONT_EXPAND, &page, &fsdata);
        if (err)
                goto out;
 
@@ -2415,9 +2413,8 @@ static int cont_expand_zero(struct file *file, struct address_space *mapping,
                }
                len = PAGE_SIZE - zerofrom;
 
-               err = pagecache_write_begin(file, mapping, curpos, len,
-                                               AOP_FLAG_UNINTERRUPTIBLE,
-                                               &page, &fsdata);
+               err = pagecache_write_begin(file, mapping, curpos, len, 0,
+                                           &page, &fsdata);
                if (err)
                        goto out;
                zero_user(page, zerofrom, len);
@@ -2449,9 +2446,8 @@ static int cont_expand_zero(struct file *file, struct address_space *mapping,
                }
                len = offset - zerofrom;
 
-               err = pagecache_write_begin(file, mapping, curpos, len,
-                                               AOP_FLAG_UNINTERRUPTIBLE,
-                                               &page, &fsdata);
+               err = pagecache_write_begin(file, mapping, curpos, len, 0,
+                                           &page, &fsdata);
                if (err)
                        goto out;
                zero_user(page, zerofrom, len);
@@ -3095,7 +3091,7 @@ void guard_bio_eod(int op, struct bio *bio)
 }
 
 static int submit_bh_wbc(int op, int op_flags, struct buffer_head *bh,
-                        unsigned long bio_flags, struct writeback_control *wbc)
+                        struct writeback_control *wbc)
 {
        struct bio *bio;
 
@@ -3130,7 +3126,6 @@ static int submit_bh_wbc(int op, int op_flags, struct buffer_head *bh,
 
        bio->bi_end_io = end_bio_bh_io_sync;
        bio->bi_private = bh;
-       bio->bi_flags |= bio_flags;
 
        /* Take care of bh's that straddle the end of the device */
        guard_bio_eod(op, bio);
@@ -3145,16 +3140,9 @@ static int submit_bh_wbc(int op, int op_flags, struct buffer_head *bh,
        return 0;
 }
 
-int _submit_bh(int op, int op_flags, struct buffer_head *bh,
-              unsigned long bio_flags)
+int submit_bh(int op, int op_flags, struct buffer_head *bh)
 {
-       return submit_bh_wbc(op, op_flags, bh, bio_flags, NULL);
-}
-EXPORT_SYMBOL_GPL(_submit_bh);
-
-int submit_bh(int op, int op_flags,  struct buffer_head *bh)
-{
-       return submit_bh_wbc(op, op_flags, bh, 0, NULL);
+       return submit_bh_wbc(op, op_flags, bh, NULL);
 }
 EXPORT_SYMBOL(submit_bh);
 
index 9ecb2fd348cb3c01727a903c8ae151582179991e..1e71e6ca5ddfb09466bee7d8721d064a4a846176 100644 (file)
@@ -670,8 +670,12 @@ static void writepages_finish(struct ceph_osd_request *req)
        bool remove_page;
 
        dout("writepages_finish %p rc %d\n", inode, rc);
-       if (rc < 0)
+       if (rc < 0) {
                mapping_set_error(mapping, rc);
+               ceph_set_error_write(ci);
+       } else {
+               ceph_clear_error_write(ci);
+       }
 
        /*
         * We lost the cache cap, need to truncate the page before
@@ -703,9 +707,6 @@ static void writepages_finish(struct ceph_osd_request *req)
                                clear_bdi_congested(inode_to_bdi(inode),
                                                    BLK_RW_ASYNC);
 
-                       if (rc < 0)
-                               SetPageError(page);
-
                        ceph_put_snap_context(page_snap_context(page));
                        page->private = 0;
                        ClearPagePrivate(page);
@@ -1892,6 +1893,7 @@ static int __ceph_pool_perm_get(struct ceph_inode_info *ci,
        err = ceph_osdc_start_request(&fsc->client->osdc, rd_req, false);
 
        wr_req->r_mtime = ci->vfs_inode.i_mtime;
+       wr_req->r_abort_on_full = true;
        err2 = ceph_osdc_start_request(&fsc->client->osdc, wr_req, false);
 
        if (!err)
index 68c78be19d5b78ad181d15b6caf5cc075b6f9f99..a3ebb632294e7b90a315508c9b75671d2ce8ff6a 100644 (file)
@@ -1015,6 +1015,7 @@ static int send_cap_msg(struct cap_msg_args *arg)
        void *p;
        size_t extra_len;
        struct timespec zerotime = {0};
+       struct ceph_osd_client *osdc = &arg->session->s_mdsc->fsc->client->osdc;
 
        dout("send_cap_msg %s %llx %llx caps %s wanted %s dirty %s"
             " seq %u/%u tid %llu/%llu mseq %u follows %lld size %llu/%llu"
@@ -1076,8 +1077,12 @@ static int send_cap_msg(struct cap_msg_args *arg)
        ceph_encode_64(&p, arg->inline_data ? 0 : CEPH_INLINE_NONE);
        /* inline data size */
        ceph_encode_32(&p, 0);
-       /* osd_epoch_barrier (version 5) */
-       ceph_encode_32(&p, 0);
+       /*
+        * osd_epoch_barrier (version 5)
+        * The epoch_barrier is protected osdc->lock, so READ_ONCE here in
+        * case it was recently changed
+        */
+       ceph_encode_32(&p, READ_ONCE(osdc->epoch_barrier));
        /* oldest_flush_tid (version 6) */
        ceph_encode_64(&p, arg->oldest_flush_tid);
 
@@ -1389,7 +1394,7 @@ static void __ceph_flush_snaps(struct ceph_inode_info *ci,
                first_tid = cf->tid + 1;
 
                capsnap = container_of(cf, struct ceph_cap_snap, cap_flush);
-               atomic_inc(&capsnap->nref);
+               refcount_inc(&capsnap->nref);
                spin_unlock(&ci->i_ceph_lock);
 
                dout("__flush_snaps %p capsnap %p tid %llu %s\n",
@@ -2202,7 +2207,7 @@ static void __kick_flushing_caps(struct ceph_mds_client *mdsc,
                             inode, capsnap, cf->tid,
                             ceph_cap_string(capsnap->dirty));
 
-                       atomic_inc(&capsnap->nref);
+                       refcount_inc(&capsnap->nref);
                        spin_unlock(&ci->i_ceph_lock);
 
                        ret = __send_flush_snap(inode, session, capsnap, cap->mseq,
@@ -3633,13 +3638,19 @@ void ceph_handle_caps(struct ceph_mds_session *session,
                p += inline_len;
        }
 
+       if (le16_to_cpu(msg->hdr.version) >= 5) {
+               struct ceph_osd_client  *osdc = &mdsc->fsc->client->osdc;
+               u32                     epoch_barrier;
+
+               ceph_decode_32_safe(&p, end, epoch_barrier, bad);
+               ceph_osdc_update_epoch_barrier(osdc, epoch_barrier);
+       }
+
        if (le16_to_cpu(msg->hdr.version) >= 8) {
                u64 flush_tid;
                u32 caller_uid, caller_gid;
-               u32 osd_epoch_barrier;
                u32 pool_ns_len;
-               /* version >= 5 */
-               ceph_decode_32_safe(&p, end, osd_epoch_barrier, bad);
+
                /* version >= 6 */
                ceph_decode_64_safe(&p, end, flush_tid, bad);
                /* version >= 7 */
index 3ef11bc8d728d6129818428ba192830186e23804..4e2d112c982f4b12852ba7b8bad58327783bc3db 100644 (file)
@@ -22,20 +22,19 @@ static int mdsmap_show(struct seq_file *s, void *p)
 {
        int i;
        struct ceph_fs_client *fsc = s->private;
+       struct ceph_mdsmap *mdsmap;
 
        if (fsc->mdsc == NULL || fsc->mdsc->mdsmap == NULL)
                return 0;
-       seq_printf(s, "epoch %d\n", fsc->mdsc->mdsmap->m_epoch);
-       seq_printf(s, "root %d\n", fsc->mdsc->mdsmap->m_root);
-       seq_printf(s, "session_timeout %d\n",
-                      fsc->mdsc->mdsmap->m_session_timeout);
-       seq_printf(s, "session_autoclose %d\n",
-                      fsc->mdsc->mdsmap->m_session_autoclose);
-       for (i = 0; i < fsc->mdsc->mdsmap->m_max_mds; i++) {
-               struct ceph_entity_addr *addr =
-                       &fsc->mdsc->mdsmap->m_info[i].addr;
-               int state = fsc->mdsc->mdsmap->m_info[i].state;
-
+       mdsmap = fsc->mdsc->mdsmap;
+       seq_printf(s, "epoch %d\n", mdsmap->m_epoch);
+       seq_printf(s, "root %d\n", mdsmap->m_root);
+       seq_printf(s, "max_mds %d\n", mdsmap->m_max_mds);
+       seq_printf(s, "session_timeout %d\n", mdsmap->m_session_timeout);
+       seq_printf(s, "session_autoclose %d\n", mdsmap->m_session_autoclose);
+       for (i = 0; i < mdsmap->m_num_mds; i++) {
+               struct ceph_entity_addr *addr = &mdsmap->m_info[i].addr;
+               int state = mdsmap->m_info[i].state;
                seq_printf(s, "\tmds%d\t%s\t(%s)\n", i,
                               ceph_pr_addr(&addr->in_addr),
                               ceph_mds_state_name(state));
index 3e9ad501addfe92f171a40dffb93c65209819cbe..e071d23f61481bf23fc4407d72ea75c9d1ec2430 100644 (file)
@@ -294,7 +294,7 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx)
        struct ceph_mds_client *mdsc = fsc->mdsc;
        int i;
        int err;
-       u32 ftype;
+       unsigned frag = -1;
        struct ceph_mds_reply_info_parsed *rinfo;
 
        dout("readdir %p file %p pos %llx\n", inode, file, ctx->pos);
@@ -341,7 +341,6 @@ more:
        /* do we have the correct frag content buffered? */
        if (need_send_readdir(fi, ctx->pos)) {
                struct ceph_mds_request *req;
-               unsigned frag;
                int op = ceph_snap(inode) == CEPH_SNAPDIR ?
                        CEPH_MDS_OP_LSSNAP : CEPH_MDS_OP_READDIR;
 
@@ -352,8 +351,11 @@ more:
                }
 
                if (is_hash_order(ctx->pos)) {
-                       frag = ceph_choose_frag(ci, fpos_hash(ctx->pos),
-                                               NULL, NULL);
+                       /* fragtree isn't always accurate. choose frag
+                        * based on previous reply when possible. */
+                       if (frag == (unsigned)-1)
+                               frag = ceph_choose_frag(ci, fpos_hash(ctx->pos),
+                                                       NULL, NULL);
                } else {
                        frag = fpos_frag(ctx->pos);
                }
@@ -378,7 +380,11 @@ more:
                                ceph_mdsc_put_request(req);
                                return -ENOMEM;
                        }
+               } else if (is_hash_order(ctx->pos)) {
+                       req->r_args.readdir.offset_hash =
+                               cpu_to_le32(fpos_hash(ctx->pos));
                }
+
                req->r_dir_release_cnt = fi->dir_release_count;
                req->r_dir_ordered_cnt = fi->dir_ordered_count;
                req->r_readdir_cache_idx = fi->readdir_cache_idx;
@@ -476,6 +482,7 @@ more:
                struct ceph_mds_reply_dir_entry *rde = rinfo->dir_entries + i;
                struct ceph_vino vino;
                ino_t ino;
+               u32 ftype;
 
                BUG_ON(rde->offset < ctx->pos);
 
@@ -498,15 +505,17 @@ more:
                ctx->pos++;
        }
 
+       ceph_mdsc_put_request(fi->last_readdir);
+       fi->last_readdir = NULL;
+
        if (fi->next_offset > 2) {
-               ceph_mdsc_put_request(fi->last_readdir);
-               fi->last_readdir = NULL;
+               frag = fi->frag;
                goto more;
        }
 
        /* more frags? */
        if (!ceph_frag_is_rightmost(fi->frag)) {
-               unsigned frag = ceph_frag_next(fi->frag);
+               frag = ceph_frag_next(fi->frag);
                if (is_hash_order(ctx->pos)) {
                        loff_t new_pos = ceph_make_fpos(ceph_frag_value(frag),
                                                        fi->next_offset, true);
index 26cc95421cca6e62ef10bfd32b18cf1e526b7c51..3fdde0b283c9b86f7fa6aaa9585593699be29fca 100644 (file)
 #include "mds_client.h"
 #include "cache.h"
 
+static __le32 ceph_flags_sys2wire(u32 flags)
+{
+       u32 wire_flags = 0;
+
+       switch (flags & O_ACCMODE) {
+       case O_RDONLY:
+               wire_flags |= CEPH_O_RDONLY;
+               break;
+       case O_WRONLY:
+               wire_flags |= CEPH_O_WRONLY;
+               break;
+       case O_RDWR:
+               wire_flags |= CEPH_O_RDWR;
+               break;
+       }
+
+#define ceph_sys2wire(a) if (flags & a) { wire_flags |= CEPH_##a; flags &= ~a; }
+
+       ceph_sys2wire(O_CREAT);
+       ceph_sys2wire(O_EXCL);
+       ceph_sys2wire(O_TRUNC);
+       ceph_sys2wire(O_DIRECTORY);
+       ceph_sys2wire(O_NOFOLLOW);
+
+#undef ceph_sys2wire
+
+       if (flags)
+               dout("unused open flags: %x", flags);
+
+       return cpu_to_le32(wire_flags);
+}
+
 /*
  * Ceph file operations
  *
@@ -74,12 +106,9 @@ dio_get_pages_alloc(const struct iov_iter *it, size_t nbytes,
        align = (unsigned long)(it->iov->iov_base + it->iov_offset) &
                (PAGE_SIZE - 1);
        npages = calc_pages_for(align, nbytes);
-       pages = kmalloc(sizeof(*pages) * npages, GFP_KERNEL);
-       if (!pages) {
-               pages = vmalloc(sizeof(*pages) * npages);
-               if (!pages)
-                       return ERR_PTR(-ENOMEM);
-       }
+       pages = kvmalloc(sizeof(*pages) * npages, GFP_KERNEL);
+       if (!pages)
+               return ERR_PTR(-ENOMEM);
 
        for (idx = 0; idx < npages; ) {
                size_t start;
@@ -123,7 +152,7 @@ prepare_open_request(struct super_block *sb, int flags, int create_mode)
        if (IS_ERR(req))
                goto out;
        req->r_fmode = ceph_flags_to_mode(flags);
-       req->r_args.open.flags = cpu_to_le32(flags);
+       req->r_args.open.flags = ceph_flags_sys2wire(flags);
        req->r_args.open.mode = cpu_to_le32(create_mode);
 out:
        return req;
@@ -192,7 +221,7 @@ int ceph_renew_caps(struct inode *inode)
        spin_lock(&ci->i_ceph_lock);
        wanted = __ceph_caps_file_wanted(ci);
        if (__ceph_is_any_real_caps(ci) &&
-           (!(wanted & CEPH_CAP_ANY_WR) == 0 || ci->i_auth_cap)) {
+           (!(wanted & CEPH_CAP_ANY_WR) || ci->i_auth_cap)) {
                int issued = __ceph_caps_issued(ci, NULL);
                spin_unlock(&ci->i_ceph_lock);
                dout("renew caps %p want %s issued %s updating mds_wanted\n",
@@ -781,6 +810,7 @@ static void ceph_aio_retry_work(struct work_struct *work)
        req->r_callback = ceph_aio_complete_req;
        req->r_inode = inode;
        req->r_priv = aio_req;
+       req->r_abort_on_full = true;
 
        ret = ceph_osdc_start_request(req->r_osdc, req, false);
 out:
@@ -1088,19 +1118,22 @@ ceph_sync_write(struct kiocb *iocb, struct iov_iter *from, loff_t pos,
 
 out:
                ceph_osdc_put_request(req);
-               if (ret == 0) {
-                       pos += len;
-                       written += len;
-
-                       if (pos > i_size_read(inode)) {
-                               check_caps = ceph_inode_set_size(inode, pos);
-                               if (check_caps)
-                                       ceph_check_caps(ceph_inode(inode),
-                                                       CHECK_CAPS_AUTHONLY,
-                                                       NULL);
-                       }
-               } else
+               if (ret != 0) {
+                       ceph_set_error_write(ci);
                        break;
+               }
+
+               ceph_clear_error_write(ci);
+               pos += len;
+               written += len;
+               if (pos > i_size_read(inode)) {
+                       check_caps = ceph_inode_set_size(inode, pos);
+                       if (check_caps)
+                               ceph_check_caps(ceph_inode(inode),
+                                               CHECK_CAPS_AUTHONLY,
+                                               NULL);
+               }
+
        }
 
        if (ret != -EOLDSNAPC && written > 0) {
@@ -1306,6 +1339,7 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)
        }
 
 retry_snap:
+       /* FIXME: not complete since it doesn't account for being at quota */
        if (ceph_osdmap_flag(osdc, CEPH_OSDMAP_FULL)) {
                err = -ENOSPC;
                goto out;
@@ -1327,7 +1361,8 @@ retry_snap:
             inode, ceph_vinop(inode), pos, count, ceph_cap_string(got));
 
        if ((got & (CEPH_CAP_FILE_BUFFER|CEPH_CAP_FILE_LAZYIO)) == 0 ||
-           (iocb->ki_flags & IOCB_DIRECT) || (fi->flags & CEPH_F_SYNC)) {
+           (iocb->ki_flags & IOCB_DIRECT) || (fi->flags & CEPH_F_SYNC) ||
+           (ci->i_ceph_flags & CEPH_I_ERROR_WRITE)) {
                struct ceph_snap_context *snapc;
                struct iov_iter data;
                inode_unlock(inode);
index d3119fe3ab45fdbdb534651ef68194815dcc544b..dcce79b844064447af8e542fe34188a4f58e22d9 100644 (file)
@@ -1482,10 +1482,17 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req,
        if (test_bit(CEPH_MDS_R_ABORTED, &req->r_req_flags))
                return readdir_prepopulate_inodes_only(req, session);
 
-       if (rinfo->hash_order && req->r_path2) {
-               last_hash = ceph_str_hash(ci->i_dir_layout.dl_dir_hash,
-                                         req->r_path2, strlen(req->r_path2));
-               last_hash = ceph_frag_value(last_hash);
+       if (rinfo->hash_order) {
+               if (req->r_path2) {
+                       last_hash = ceph_str_hash(ci->i_dir_layout.dl_dir_hash,
+                                                 req->r_path2,
+                                                 strlen(req->r_path2));
+                       last_hash = ceph_frag_value(last_hash);
+               } else if (rinfo->offset_hash) {
+                       /* mds understands offset_hash */
+                       WARN_ON_ONCE(req->r_readdir_offset != 2);
+                       last_hash = le32_to_cpu(rhead->args.readdir.offset_hash);
+               }
        }
 
        if (rinfo->dir_dir &&
@@ -1510,7 +1517,7 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req,
        }
 
        if (ceph_frag_is_leftmost(frag) && req->r_readdir_offset == 2 &&
-           !(rinfo->hash_order && req->r_path2)) {
+           !(rinfo->hash_order && last_hash)) {
                /* note dir version at start of readdir so we can tell
                 * if any dentries get dropped */
                req->r_dir_release_cnt = atomic64_read(&ci->i_release_count);
index c681762d76e66be1edf7004b1de8c13568ec6022..f38e56fa97129d646285fa2b433e8130c7b85312 100644 (file)
@@ -189,6 +189,7 @@ static int parse_reply_info_dir(void **p, void *end,
                info->dir_end = !!(flags & CEPH_READDIR_FRAG_END);
                info->dir_complete = !!(flags & CEPH_READDIR_FRAG_COMPLETE);
                info->hash_order = !!(flags & CEPH_READDIR_HASH_ORDER);
+               info->offset_hash = !!(flags & CEPH_READDIR_OFFSET_HASH);
        }
        if (num == 0)
                goto done;
@@ -378,9 +379,9 @@ const char *ceph_session_state_name(int s)
 
 static struct ceph_mds_session *get_session(struct ceph_mds_session *s)
 {
-       if (atomic_inc_not_zero(&s->s_ref)) {
+       if (refcount_inc_not_zero(&s->s_ref)) {
                dout("mdsc get_session %p %d -> %d\n", s,
-                    atomic_read(&s->s_ref)-1, atomic_read(&s->s_ref));
+                    refcount_read(&s->s_ref)-1, refcount_read(&s->s_ref));
                return s;
        } else {
                dout("mdsc get_session %p 0 -- FAIL", s);
@@ -391,8 +392,8 @@ static struct ceph_mds_session *get_session(struct ceph_mds_session *s)
 void ceph_put_mds_session(struct ceph_mds_session *s)
 {
        dout("mdsc put_session %p %d -> %d\n", s,
-            atomic_read(&s->s_ref), atomic_read(&s->s_ref)-1);
-       if (atomic_dec_and_test(&s->s_ref)) {
+            refcount_read(&s->s_ref), refcount_read(&s->s_ref)-1);
+       if (refcount_dec_and_test(&s->s_ref)) {
                if (s->s_auth.authorizer)
                        ceph_auth_destroy_authorizer(s->s_auth.authorizer);
                kfree(s);
@@ -411,7 +412,7 @@ struct ceph_mds_session *__ceph_lookup_mds_session(struct ceph_mds_client *mdsc,
                return NULL;
        session = mdsc->sessions[mds];
        dout("lookup_mds_session %p %d\n", session,
-            atomic_read(&session->s_ref));
+            refcount_read(&session->s_ref));
        get_session(session);
        return session;
 }
@@ -441,7 +442,7 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc,
 {
        struct ceph_mds_session *s;
 
-       if (mds >= mdsc->mdsmap->m_max_mds)
+       if (mds >= mdsc->mdsmap->m_num_mds)
                return ERR_PTR(-EINVAL);
 
        s = kzalloc(sizeof(*s), GFP_NOFS);
@@ -466,7 +467,7 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc,
        INIT_LIST_HEAD(&s->s_caps);
        s->s_nr_caps = 0;
        s->s_trim_caps = 0;
-       atomic_set(&s->s_ref, 1);
+       refcount_set(&s->s_ref, 1);
        INIT_LIST_HEAD(&s->s_waiting);
        INIT_LIST_HEAD(&s->s_unsafe);
        s->s_num_cap_releases = 0;
@@ -494,7 +495,7 @@ static struct ceph_mds_session *register_session(struct ceph_mds_client *mdsc,
        }
        mdsc->sessions[mds] = s;
        atomic_inc(&mdsc->num_sessions);
-       atomic_inc(&s->s_ref);  /* one ref to sessions[], one to caller */
+       refcount_inc(&s->s_ref);  /* one ref to sessions[], one to caller */
 
        ceph_con_open(&s->s_con, CEPH_ENTITY_TYPE_MDS, mds,
                      ceph_mdsmap_get_addr(mdsc->mdsmap, mds));
@@ -1004,7 +1005,7 @@ static void __open_export_target_sessions(struct ceph_mds_client *mdsc,
        struct ceph_mds_session *ts;
        int i, mds = session->s_mds;
 
-       if (mds >= mdsc->mdsmap->m_max_mds)
+       if (mds >= mdsc->mdsmap->m_num_mds)
                return;
 
        mi = &mdsc->mdsmap->m_info[mds];
@@ -1551,9 +1552,15 @@ void ceph_send_cap_releases(struct ceph_mds_client *mdsc,
        struct ceph_msg *msg = NULL;
        struct ceph_mds_cap_release *head;
        struct ceph_mds_cap_item *item;
+       struct ceph_osd_client *osdc = &mdsc->fsc->client->osdc;
        struct ceph_cap *cap;
        LIST_HEAD(tmp_list);
        int num_cap_releases;
+       __le32  barrier, *cap_barrier;
+
+       down_read(&osdc->lock);
+       barrier = cpu_to_le32(osdc->epoch_barrier);
+       up_read(&osdc->lock);
 
        spin_lock(&session->s_cap_lock);
 again:
@@ -1571,7 +1578,11 @@ again:
                        head = msg->front.iov_base;
                        head->num = cpu_to_le32(0);
                        msg->front.iov_len = sizeof(*head);
+
+                       msg->hdr.version = cpu_to_le16(2);
+                       msg->hdr.compat_version = cpu_to_le16(1);
                }
+
                cap = list_first_entry(&tmp_list, struct ceph_cap,
                                        session_caps);
                list_del(&cap->session_caps);
@@ -1589,6 +1600,11 @@ again:
                ceph_put_cap(mdsc, cap);
 
                if (le32_to_cpu(head->num) == CEPH_CAPS_PER_RELEASE) {
+                       // Append cap_barrier field
+                       cap_barrier = msg->front.iov_base + msg->front.iov_len;
+                       *cap_barrier = barrier;
+                       msg->front.iov_len += sizeof(*cap_barrier);
+
                        msg->hdr.front_len = cpu_to_le32(msg->front.iov_len);
                        dout("send_cap_releases mds%d %p\n", session->s_mds, msg);
                        ceph_con_send(&session->s_con, msg);
@@ -1604,6 +1620,11 @@ again:
        spin_unlock(&session->s_cap_lock);
 
        if (msg) {
+               // Append cap_barrier field
+               cap_barrier = msg->front.iov_base + msg->front.iov_len;
+               *cap_barrier = barrier;
+               msg->front.iov_len += sizeof(*cap_barrier);
+
                msg->hdr.front_len = cpu_to_le32(msg->front.iov_len);
                dout("send_cap_releases mds%d %p\n", session->s_mds, msg);
                ceph_con_send(&session->s_con, msg);
@@ -1666,6 +1687,7 @@ struct ceph_mds_request *
 ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, int mode)
 {
        struct ceph_mds_request *req = kzalloc(sizeof(*req), GFP_NOFS);
+       struct timespec ts;
 
        if (!req)
                return ERR_PTR(-ENOMEM);
@@ -1684,7 +1706,8 @@ ceph_mdsc_create_request(struct ceph_mds_client *mdsc, int op, int mode)
        init_completion(&req->r_safe_completion);
        INIT_LIST_HEAD(&req->r_unsafe_item);
 
-       req->r_stamp = current_fs_time(mdsc->fsc->sb);
+       ktime_get_real_ts(&ts);
+       req->r_stamp = timespec_trunc(ts, mdsc->fsc->sb->s_time_gran);
 
        req->r_op = op;
        req->r_direct_mode = mode;
@@ -1991,7 +2014,7 @@ static struct ceph_msg *create_request_message(struct ceph_mds_client *mdsc,
 
        if (req->r_pagelist) {
                struct ceph_pagelist *pagelist = req->r_pagelist;
-               atomic_inc(&pagelist->refcnt);
+               refcount_inc(&pagelist->refcnt);
                ceph_msg_data_add_pagelist(msg, pagelist);
                msg->hdr.data_len = cpu_to_le32(pagelist->length);
        } else {
@@ -2638,8 +2661,10 @@ static void handle_session(struct ceph_mds_session *session,
        seq = le64_to_cpu(h->seq);
 
        mutex_lock(&mdsc->mutex);
-       if (op == CEPH_SESSION_CLOSE)
+       if (op == CEPH_SESSION_CLOSE) {
+               get_session(session);
                __unregister_session(mdsc, session);
+       }
        /* FIXME: this ttl calculation is generous */
        session->s_ttl = jiffies + HZ*mdsc->mdsmap->m_session_autoclose;
        mutex_unlock(&mdsc->mutex);
@@ -2728,6 +2753,8 @@ static void handle_session(struct ceph_mds_session *session,
                        kick_requests(mdsc, mds);
                mutex_unlock(&mdsc->mutex);
        }
+       if (op == CEPH_SESSION_CLOSE)
+               ceph_put_mds_session(session);
        return;
 
 bad:
@@ -3107,7 +3134,7 @@ static void check_new_map(struct ceph_mds_client *mdsc,
        dout("check_new_map new %u old %u\n",
             newmap->m_epoch, oldmap->m_epoch);
 
-       for (i = 0; i < oldmap->m_max_mds && i < mdsc->max_sessions; i++) {
+       for (i = 0; i < oldmap->m_num_mds && i < mdsc->max_sessions; i++) {
                if (mdsc->sessions[i] == NULL)
                        continue;
                s = mdsc->sessions[i];
@@ -3121,15 +3148,33 @@ static void check_new_map(struct ceph_mds_client *mdsc,
                     ceph_mdsmap_is_laggy(newmap, i) ? " (laggy)" : "",
                     ceph_session_state_name(s->s_state));
 
-               if (i >= newmap->m_max_mds ||
+               if (i >= newmap->m_num_mds ||
                    memcmp(ceph_mdsmap_get_addr(oldmap, i),
                           ceph_mdsmap_get_addr(newmap, i),
                           sizeof(struct ceph_entity_addr))) {
                        if (s->s_state == CEPH_MDS_SESSION_OPENING) {
                                /* the session never opened, just close it
                                 * out now */
+                               get_session(s);
+                               __unregister_session(mdsc, s);
                                __wake_requests(mdsc, &s->s_waiting);
+                               ceph_put_mds_session(s);
+                       } else if (i >= newmap->m_num_mds) {
+                               /* force close session for stopped mds */
+                               get_session(s);
                                __unregister_session(mdsc, s);
+                               __wake_requests(mdsc, &s->s_waiting);
+                               kick_requests(mdsc, i);
+                               mutex_unlock(&mdsc->mutex);
+
+                               mutex_lock(&s->s_mutex);
+                               cleanup_session_requests(mdsc, s);
+                               remove_session_caps(s);
+                               mutex_unlock(&s->s_mutex);
+
+                               ceph_put_mds_session(s);
+
+                               mutex_lock(&mdsc->mutex);
                        } else {
                                /* just close it */
                                mutex_unlock(&mdsc->mutex);
@@ -3167,7 +3212,7 @@ static void check_new_map(struct ceph_mds_client *mdsc,
                }
        }
 
-       for (i = 0; i < newmap->m_max_mds && i < mdsc->max_sessions; i++) {
+       for (i = 0; i < newmap->m_num_mds && i < mdsc->max_sessions; i++) {
                s = mdsc->sessions[i];
                if (!s)
                        continue;
@@ -3881,7 +3926,7 @@ static struct ceph_connection *con_get(struct ceph_connection *con)
        struct ceph_mds_session *s = con->private;
 
        if (get_session(s)) {
-               dout("mdsc con_get %p ok (%d)\n", s, atomic_read(&s->s_ref));
+               dout("mdsc con_get %p ok (%d)\n", s, refcount_read(&s->s_ref));
                return con;
        }
        dout("mdsc con_get %p FAIL\n", s);
@@ -3892,7 +3937,7 @@ static void con_put(struct ceph_connection *con)
 {
        struct ceph_mds_session *s = con->private;
 
-       dout("mdsc con_put %p (%d)\n", s, atomic_read(&s->s_ref) - 1);
+       dout("mdsc con_put %p (%d)\n", s, refcount_read(&s->s_ref) - 1);
        ceph_put_mds_session(s);
 }
 
index ac0475a2daa749d3d689956cc45a2913c955ca8f..db57ae98ed345e280358a2ac65e75ac6c71e7c2b 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/mutex.h>
 #include <linux/rbtree.h>
 #include <linux/spinlock.h>
+#include <linux/refcount.h>
 
 #include <linux/ceph/types.h>
 #include <linux/ceph/messenger.h>
@@ -82,9 +83,10 @@ struct ceph_mds_reply_info_parsed {
                        struct ceph_mds_reply_dirfrag *dir_dir;
                        size_t                        dir_buf_size;
                        int                           dir_nr;
-                       bool                          dir_complete;
                        bool                          dir_end;
+                       bool                          dir_complete;
                        bool                          hash_order;
+                       bool                          offset_hash;
                        struct ceph_mds_reply_dir_entry  *dir_entries;
                };
 
@@ -104,10 +106,13 @@ struct ceph_mds_reply_info_parsed {
 
 /*
  * cap releases are batched and sent to the MDS en masse.
+ *
+ * Account for per-message overhead of mds_cap_release header
+ * and __le32 for osd epoch barrier trailing field.
  */
-#define CEPH_CAPS_PER_RELEASE ((PAGE_SIZE -                    \
+#define CEPH_CAPS_PER_RELEASE ((PAGE_SIZE - sizeof(u32) -              \
                                sizeof(struct ceph_mds_cap_release)) /  \
-                              sizeof(struct ceph_mds_cap_item))
+                               sizeof(struct ceph_mds_cap_item))
 
 
 /*
@@ -156,7 +161,7 @@ struct ceph_mds_session {
        unsigned long     s_renew_requested; /* last time we sent a renew req */
        u64               s_renew_seq;
 
-       atomic_t          s_ref;
+       refcount_t          s_ref;
        struct list_head  s_waiting;  /* waiting requests */
        struct list_head  s_unsafe;   /* unsafe requests */
 };
@@ -373,7 +378,7 @@ __ceph_lookup_mds_session(struct ceph_mds_client *, int mds);
 static inline struct ceph_mds_session *
 ceph_get_mds_session(struct ceph_mds_session *s)
 {
-       atomic_inc(&s->s_ref);
+       refcount_inc(&s->s_ref);
        return s;
 }
 
index 5454e2327a5f77874d63344802709697ceb64de1..1a748cf88535bc80b8060be0cae2d4a92f85599f 100644 (file)
@@ -22,11 +22,11 @@ int ceph_mdsmap_get_random_mds(struct ceph_mdsmap *m)
        int i;
 
        /* special case for one mds */
-       if (1 == m->m_max_mds && m->m_info[0].state > 0)
+       if (1 == m->m_num_mds && m->m_info[0].state > 0)
                return 0;
 
        /* count */
-       for (i = 0; i < m->m_max_mds; i++)
+       for (i = 0; i < m->m_num_mds; i++)
                if (m->m_info[i].state > 0)
                        n++;
        if (n == 0)
@@ -135,8 +135,9 @@ struct ceph_mdsmap *ceph_mdsmap_decode(void **p, void *end)
        m->m_session_autoclose = ceph_decode_32(p);
        m->m_max_file_size = ceph_decode_64(p);
        m->m_max_mds = ceph_decode_32(p);
+       m->m_num_mds = m->m_max_mds;
 
-       m->m_info = kcalloc(m->m_max_mds, sizeof(*m->m_info), GFP_NOFS);
+       m->m_info = kcalloc(m->m_num_mds, sizeof(*m->m_info), GFP_NOFS);
        if (m->m_info == NULL)
                goto nomem;
 
@@ -207,9 +208,20 @@ struct ceph_mdsmap *ceph_mdsmap_decode(void **p, void *end)
                     ceph_pr_addr(&addr.in_addr),
                     ceph_mds_state_name(state));
 
-               if (mds < 0 || mds >= m->m_max_mds || state <= 0)
+               if (mds < 0 || state <= 0)
                        continue;
 
+               if (mds >= m->m_num_mds) {
+                       int new_num = max(mds + 1, m->m_num_mds * 2);
+                       void *new_m_info = krealloc(m->m_info,
+                                               new_num * sizeof(*m->m_info),
+                                               GFP_NOFS | __GFP_ZERO);
+                       if (!new_m_info)
+                               goto nomem;
+                       m->m_info = new_m_info;
+                       m->m_num_mds = new_num;
+               }
+
                info = &m->m_info[mds];
                info->global_id = global_id;
                info->state = state;
@@ -229,6 +241,14 @@ struct ceph_mdsmap *ceph_mdsmap_decode(void **p, void *end)
                        info->export_targets = NULL;
                }
        }
+       if (m->m_num_mds > m->m_max_mds) {
+               /* find max up mds */
+               for (i = m->m_num_mds; i >= m->m_max_mds; i--) {
+                       if (i == 0 || m->m_info[i-1].state > 0)
+                               break;
+               }
+               m->m_num_mds = i;
+       }
 
        /* pg_pools */
        ceph_decode_32_safe(p, end, n, bad);
@@ -270,12 +290,22 @@ struct ceph_mdsmap *ceph_mdsmap_decode(void **p, void *end)
 
                for (i = 0; i < n; i++) {
                        s32 mds = ceph_decode_32(p);
-                       if (mds >= 0 && mds < m->m_max_mds) {
+                       if (mds >= 0 && mds < m->m_num_mds) {
                                if (m->m_info[mds].laggy)
                                        num_laggy++;
                        }
                }
                m->m_num_laggy = num_laggy;
+
+               if (n > m->m_num_mds) {
+                       void *new_m_info = krealloc(m->m_info,
+                                                   n * sizeof(*m->m_info),
+                                                   GFP_NOFS | __GFP_ZERO);
+                       if (!new_m_info)
+                               goto nomem;
+                       m->m_info = new_m_info;
+               }
+               m->m_num_mds = n;
        }
 
        /* inc */
@@ -341,7 +371,7 @@ void ceph_mdsmap_destroy(struct ceph_mdsmap *m)
 {
        int i;
 
-       for (i = 0; i < m->m_max_mds; i++)
+       for (i = 0; i < m->m_num_mds; i++)
                kfree(m->m_info[i].export_targets);
        kfree(m->m_info);
        kfree(m->m_data_pg_pools);
@@ -357,7 +387,7 @@ bool ceph_mdsmap_is_cluster_available(struct ceph_mdsmap *m)
                return false;
        if (m->m_num_laggy > 0)
                return false;
-       for (i = 0; i < m->m_max_mds; i++) {
+       for (i = 0; i < m->m_num_mds; i++) {
                if (m->m_info[i].state == CEPH_MDS_STATE_ACTIVE)
                        nr_active++;
        }
index 8f8b41c2ef0f7d472afad0e1abcb4801ac11b221..dab5d6732345b218e12f9bf7d6fea1c5dac38d55 100644 (file)
@@ -519,7 +519,7 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci)
             capsnap->need_flush ? "" : "no_flush");
        ihold(inode);
 
-       atomic_set(&capsnap->nref, 1);
+       refcount_set(&capsnap->nref, 1);
        INIT_LIST_HEAD(&capsnap->ci_item);
 
        capsnap->follows = old_snapc->seq;
index a8c81b2052ca9052f67cd217785f1c77a510d788..8d7918ce694a9c0d980641ab66b7be6d0aaa33a5 100644 (file)
@@ -544,10 +544,6 @@ static struct ceph_fs_client *create_fs_client(struct ceph_mount_options *fsopt,
                                        struct ceph_options *opt)
 {
        struct ceph_fs_client *fsc;
-       const u64 supported_features =
-               CEPH_FEATURE_FLOCK | CEPH_FEATURE_DIRLAYOUTHASH |
-               CEPH_FEATURE_MDSENC | CEPH_FEATURE_MDS_INLINE_DATA;
-       const u64 required_features = 0;
        int page_count;
        size_t size;
        int err = -ENOMEM;
@@ -556,8 +552,7 @@ static struct ceph_fs_client *create_fs_client(struct ceph_mount_options *fsopt,
        if (!fsc)
                return ERR_PTR(-ENOMEM);
 
-       fsc->client = ceph_create_client(opt, fsc, supported_features,
-                                        required_features);
+       fsc->client = ceph_create_client(opt, fsc);
        if (IS_ERR(fsc->client)) {
                err = PTR_ERR(fsc->client);
                goto fail;
index 176186b124575225537afe7049686041d3148c26..a973acd8beaff67b5b0e67b1217c9bb7419c9982 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/writeback.h>
 #include <linux/slab.h>
 #include <linux/posix_acl.h>
+#include <linux/refcount.h>
 
 #include <linux/ceph/libceph.h>
 
@@ -160,7 +161,7 @@ struct ceph_cap_flush {
  * data before flushing the snapped state (tracked here) back to the MDS.
  */
 struct ceph_cap_snap {
-       atomic_t nref;
+       refcount_t nref;
        struct list_head ci_item;
 
        struct ceph_cap_flush cap_flush;
@@ -189,7 +190,7 @@ struct ceph_cap_snap {
 
 static inline void ceph_put_cap_snap(struct ceph_cap_snap *capsnap)
 {
-       if (atomic_dec_and_test(&capsnap->nref)) {
+       if (refcount_dec_and_test(&capsnap->nref)) {
                if (capsnap->xattr_blob)
                        ceph_buffer_put(capsnap->xattr_blob);
                kfree(capsnap);
@@ -471,6 +472,32 @@ static inline struct inode *ceph_find_inode(struct super_block *sb,
 #define CEPH_I_CAP_DROPPED     (1 << 8)  /* caps were forcibly dropped */
 #define CEPH_I_KICK_FLUSH      (1 << 9)  /* kick flushing caps */
 #define CEPH_I_FLUSH_SNAPS     (1 << 10) /* need flush snapss */
+#define CEPH_I_ERROR_WRITE     (1 << 11) /* have seen write errors */
+
+/*
+ * We set the ERROR_WRITE bit when we start seeing write errors on an inode
+ * and then clear it when they start succeeding. Note that we do a lockless
+ * check first, and only take the lock if it looks like it needs to be changed.
+ * The write submission code just takes this as a hint, so we're not too
+ * worried if a few slip through in either direction.
+ */
+static inline void ceph_set_error_write(struct ceph_inode_info *ci)
+{
+       if (!(READ_ONCE(ci->i_ceph_flags) & CEPH_I_ERROR_WRITE)) {
+               spin_lock(&ci->i_ceph_lock);
+               ci->i_ceph_flags |= CEPH_I_ERROR_WRITE;
+               spin_unlock(&ci->i_ceph_lock);
+       }
+}
+
+static inline void ceph_clear_error_write(struct ceph_inode_info *ci)
+{
+       if (READ_ONCE(ci->i_ceph_flags) & CEPH_I_ERROR_WRITE) {
+               spin_lock(&ci->i_ceph_lock);
+               ci->i_ceph_flags &= ~CEPH_I_ERROR_WRITE;
+               spin_unlock(&ci->i_ceph_lock);
+       }
+}
 
 static inline void __ceph_dir_set_complete(struct ceph_inode_info *ci,
                                           long long release_count,
index febc28f9e2c27648e1621531e90cefc482ed2e5d..75267cdd5dfd822b3290221b269cb0fde64a8e83 100644 (file)
@@ -392,6 +392,7 @@ static int __set_xattr(struct ceph_inode_info *ci,
 
        if (update_xattr) {
                int err = 0;
+
                if (xattr && (flags & XATTR_CREATE))
                        err = -EEXIST;
                else if (!xattr && (flags & XATTR_REPLACE))
@@ -399,12 +400,14 @@ static int __set_xattr(struct ceph_inode_info *ci,
                if (err) {
                        kfree(name);
                        kfree(val);
+                       kfree(*newxattr);
                        return err;
                }
                if (update_xattr < 0) {
                        if (xattr)
                                __remove_xattr(ci, xattr);
                        kfree(name);
+                       kfree(*newxattr);
                        return 0;
                }
        }
index 15bac390dff945d7fa5d785f666b2b0291fb9f65..b98436f5c7c74f9e773db0485bb9e80fcb43be99 100644 (file)
@@ -1135,20 +1135,19 @@ cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
        u32 acllen = 0;
        int rc = 0;
        struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
-       struct cifs_tcon *tcon;
+       struct smb_version_operations *ops;
 
        cifs_dbg(NOISY, "converting ACL to mode for %s\n", path);
 
        if (IS_ERR(tlink))
                return PTR_ERR(tlink);
-       tcon = tlink_tcon(tlink);
 
-       if (pfid && (tcon->ses->server->ops->get_acl_by_fid))
-               pntsd = tcon->ses->server->ops->get_acl_by_fid(cifs_sb, pfid,
-                                                         &acllen);
-       else if (tcon->ses->server->ops->get_acl)
-               pntsd = tcon->ses->server->ops->get_acl(cifs_sb, inode, path,
-                                                       &acllen);
+       ops = tlink_tcon(tlink)->ses->server->ops;
+
+       if (pfid && (ops->get_acl_by_fid))
+               pntsd = ops->get_acl_by_fid(cifs_sb, pfid, &acllen);
+       else if (ops->get_acl)
+               pntsd = ops->get_acl(cifs_sb, inode, path, &acllen);
        else {
                cifs_put_tlink(tlink);
                return -EOPNOTSUPP;
@@ -1181,23 +1180,23 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
        struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
        struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
        struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
-       struct cifs_tcon *tcon;
+       struct smb_version_operations *ops;
 
        if (IS_ERR(tlink))
                return PTR_ERR(tlink);
-       tcon = tlink_tcon(tlink);
+
+       ops = tlink_tcon(tlink)->ses->server->ops;
 
        cifs_dbg(NOISY, "set ACL from mode for %s\n", path);
 
        /* Get the security descriptor */
 
-       if (tcon->ses->server->ops->get_acl == NULL) {
+       if (ops->get_acl == NULL) {
                cifs_put_tlink(tlink);
                return -EOPNOTSUPP;
        }
 
-       pntsd = tcon->ses->server->ops->get_acl(cifs_sb, inode, path,
-                                               &secdesclen);
+       pntsd = ops->get_acl(cifs_sb, inode, path, &secdesclen);
        if (IS_ERR(pntsd)) {
                rc = PTR_ERR(pntsd);
                cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
@@ -1224,13 +1223,12 @@ id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
 
        cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc);
 
-       if (tcon->ses->server->ops->set_acl == NULL)
+       if (ops->set_acl == NULL)
                rc = -EOPNOTSUPP;
 
        if (!rc) {
                /* Set the security descriptor */
-               rc = tcon->ses->server->ops->set_acl(pnntsd, secdesclen, inode,
-                                                    path, aclflag);
+               rc = ops->set_acl(pnntsd, secdesclen, inode, path, aclflag);
                cifs_dbg(NOISY, "set_cifs_acl rc: %d\n", rc);
        }
        cifs_put_tlink(tlink);
index 058ac9b36f0470a4d04478377cdc12a041df0db4..68abbb0db60898cc417ecfa03a8c11e5fe136c93 100644 (file)
@@ -478,6 +478,7 @@ find_timestamp(struct cifs_ses *ses)
        unsigned char *blobptr;
        unsigned char *blobend;
        struct ntlmssp2_name *attrptr;
+       struct timespec ts;
 
        if (!ses->auth_key.len || !ses->auth_key.response)
                return 0;
@@ -502,7 +503,8 @@ find_timestamp(struct cifs_ses *ses)
                blobptr += attrsize; /* advance attr value */
        }
 
-       return cpu_to_le64(cifs_UnixTimeToNT(CURRENT_TIME));
+       ktime_get_real_ts(&ts);
+       return cpu_to_le64(cifs_UnixTimeToNT(ts));
 }
 
 static int calc_ntlmv2_hash(struct cifs_ses *ses, char *ntlmv2_hash,
index 8be55be70faf6c278de7b7c623501385bf21acaf..bcc7d9acad64b3a59b9c966956accb2c51d9ac13 100644 (file)
@@ -418,7 +418,7 @@ struct smb_version_operations {
        int (*validate_negotiate)(const unsigned int, struct cifs_tcon *);
        ssize_t (*query_all_EAs)(const unsigned int, struct cifs_tcon *,
                        const unsigned char *, const unsigned char *, char *,
-                       size_t, const struct nls_table *, int);
+                       size_t, struct cifs_sb_info *);
        int (*set_EA)(const unsigned int, struct cifs_tcon *, const char *,
                        const char *, const void *, const __u16,
                        const struct nls_table *, int);
index e49958c3f8bbded4265b71e47a87d736a34676da..6eb3147132e30c2225b610b01281111bb896c617 100644 (file)
@@ -480,8 +480,7 @@ extern int CIFSSMBCopy(unsigned int xid,
 extern ssize_t CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
                        const unsigned char *searchName,
                        const unsigned char *ea_name, char *EAData,
-                       size_t bufsize, const struct nls_table *nls_codepage,
-                       int remap_special_chars);
+                       size_t bufsize, struct cifs_sb_info *cifs_sb);
 extern int CIFSSMBSetEA(const unsigned int xid, struct cifs_tcon *tcon,
                const char *fileName, const char *ea_name,
                const void *ea_value, const __u16 ea_value_len,
index 205fd94f52fdf48361b800c3b29ebba6c00fe49b..fbb0d4cbda413e5349ab97c8fdfe65435efdc6ed 100644 (file)
@@ -478,14 +478,14 @@ decode_lanman_negprot_rsp(struct TCP_Server_Info *server, NEGOTIATE_RSP *pSMBr)
                 * this requirement.
                 */
                int val, seconds, remain, result;
-               struct timespec ts, utc;
-               utc = CURRENT_TIME;
+               struct timespec ts;
+               unsigned long utc = ktime_get_real_seconds();
                ts = cnvrtDosUnixTm(rsp->SrvTime.Date,
                                    rsp->SrvTime.Time, 0);
                cifs_dbg(FYI, "SrvTime %d sec since 1970 (utc: %d) diff: %d\n",
-                        (int)ts.tv_sec, (int)utc.tv_sec,
-                        (int)(utc.tv_sec - ts.tv_sec));
-               val = (int)(utc.tv_sec - ts.tv_sec);
+                        (int)ts.tv_sec, (int)utc,
+                        (int)(utc - ts.tv_sec));
+               val = (int)(utc - ts.tv_sec);
                seconds = abs(val);
                result = (seconds / MIN_TZ_ADJ) * MIN_TZ_ADJ;
                remain = seconds % MIN_TZ_ADJ;
@@ -697,9 +697,7 @@ cifs_echo_callback(struct mid_q_entry *mid)
 {
        struct TCP_Server_Info *server = mid->callback_data;
 
-       mutex_lock(&server->srv_mutex);
        DeleteMidQEntry(mid);
-       mutex_unlock(&server->srv_mutex);
        add_credits(server, 1, CIFS_ECHO_OP);
 }
 
@@ -1599,9 +1597,7 @@ cifs_readv_callback(struct mid_q_entry *mid)
        }
 
        queue_work(cifsiod_wq, &rdata->work);
-       mutex_lock(&server->srv_mutex);
        DeleteMidQEntry(mid);
-       mutex_unlock(&server->srv_mutex);
        add_credits(server, 1, 0);
 }
 
@@ -2058,7 +2054,6 @@ cifs_writev_callback(struct mid_q_entry *mid)
 {
        struct cifs_writedata *wdata = mid->callback_data;
        struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
-       struct TCP_Server_Info *server = tcon->ses->server;
        unsigned int written;
        WRITE_RSP *smb = (WRITE_RSP *)mid->resp_buf;
 
@@ -2095,9 +2090,7 @@ cifs_writev_callback(struct mid_q_entry *mid)
        }
 
        queue_work(cifsiod_wq, &wdata->work);
-       mutex_lock(&server->srv_mutex);
        DeleteMidQEntry(mid);
-       mutex_unlock(&server->srv_mutex);
        add_credits(tcon->ses->server, 1, 0);
 }
 
@@ -6076,11 +6069,13 @@ ssize_t
 CIFSSMBQAllEAs(const unsigned int xid, struct cifs_tcon *tcon,
                const unsigned char *searchName, const unsigned char *ea_name,
                char *EAData, size_t buf_size,
-               const struct nls_table *nls_codepage, int remap)
+               struct cifs_sb_info *cifs_sb)
 {
                /* BB assumes one setup word */
        TRANSACTION2_QPI_REQ *pSMB = NULL;
        TRANSACTION2_QPI_RSP *pSMBr = NULL;
+       int remap = cifs_remap(cifs_sb);
+       struct nls_table *nls_codepage = cifs_sb->local_nls;
        int rc = 0;
        int bytes_returned;
        int list_len;
index 6ef78ad838e6e3e8b4cf24e72de24fcba8e4313c..0fd081bd2a2f5d3fb4ed18fdcb7a1371cf9f5627 100644 (file)
@@ -582,7 +582,7 @@ cifs_relock_file(struct cifsFileInfo *cfile)
        struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
        int rc = 0;
 
-       down_read(&cinode->lock_sem);
+       down_read_nested(&cinode->lock_sem, SINGLE_DEPTH_NESTING);
        if (cinode->can_cache_brlcks) {
                /* can cache locks - no need to relock */
                up_read(&cinode->lock_sem);
index b261db34103ce929ed863e34753511ac94ec0355..4d1fcd76d022f6848c16294411d5a937e053e27a 100644 (file)
@@ -322,9 +322,9 @@ cifs_create_dfs_fattr(struct cifs_fattr *fattr, struct super_block *sb)
        fattr->cf_mode = S_IFDIR | S_IXUGO | S_IRWXU;
        fattr->cf_uid = cifs_sb->mnt_uid;
        fattr->cf_gid = cifs_sb->mnt_gid;
-       fattr->cf_atime = CURRENT_TIME;
-       fattr->cf_ctime = CURRENT_TIME;
-       fattr->cf_mtime = CURRENT_TIME;
+       ktime_get_real_ts(&fattr->cf_mtime);
+       fattr->cf_mtime = timespec_trunc(fattr->cf_mtime, sb->s_time_gran);
+       fattr->cf_atime = fattr->cf_ctime = fattr->cf_mtime;
        fattr->cf_nlink = 2;
        fattr->cf_flags |= CIFS_FATTR_DFS_REFERRAL;
 }
@@ -563,8 +563,7 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
 
        rc = tcon->ses->server->ops->query_all_EAs(xid, tcon, path,
                        "SETFILEBITS", ea_value, 4 /* size of buf */,
-                       cifs_sb->local_nls,
-                       cifs_remap(cifs_sb));
+                       cifs_sb);
        cifs_put_tlink(tlink);
        if (rc < 0)
                return (int)rc;
@@ -586,9 +585,10 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
 /* Fill a cifs_fattr struct with info from FILE_ALL_INFO */
 static void
 cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
-                      struct cifs_sb_info *cifs_sb, bool adjust_tz,
+                      struct super_block *sb, bool adjust_tz,
                       bool symlink)
 {
+       struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
        struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
 
        memset(fattr, 0, sizeof(*fattr));
@@ -598,8 +598,10 @@ cifs_all_info_to_fattr(struct cifs_fattr *fattr, FILE_ALL_INFO *info,
 
        if (info->LastAccessTime)
                fattr->cf_atime = cifs_NTtimeToUnix(info->LastAccessTime);
-       else
-               fattr->cf_atime = CURRENT_TIME;
+       else {
+               ktime_get_real_ts(&fattr->cf_atime);
+               fattr->cf_atime = timespec_trunc(fattr->cf_atime, sb->s_time_gran);
+       }
 
        fattr->cf_ctime = cifs_NTtimeToUnix(info->ChangeTime);
        fattr->cf_mtime = cifs_NTtimeToUnix(info->LastWriteTime);
@@ -659,7 +661,6 @@ cifs_get_file_info(struct file *filp)
        FILE_ALL_INFO find_data;
        struct cifs_fattr fattr;
        struct inode *inode = file_inode(filp);
-       struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
        struct cifsFileInfo *cfile = filp->private_data;
        struct cifs_tcon *tcon = tlink_tcon(cfile->tlink);
        struct TCP_Server_Info *server = tcon->ses->server;
@@ -671,7 +672,7 @@ cifs_get_file_info(struct file *filp)
        rc = server->ops->query_file_info(xid, tcon, &cfile->fid, &find_data);
        switch (rc) {
        case 0:
-               cifs_all_info_to_fattr(&fattr, &find_data, cifs_sb, false,
+               cifs_all_info_to_fattr(&fattr, &find_data, inode->i_sb, false,
                                       false);
                break;
        case -EREMOTE:
@@ -753,7 +754,7 @@ cifs_get_inode_info(struct inode **inode, const char *full_path,
        }
 
        if (!rc) {
-               cifs_all_info_to_fattr(&fattr, data, cifs_sb, adjust_tz,
+               cifs_all_info_to_fattr(&fattr, data, sb, adjust_tz,
                                       symlink);
        } else if (rc == -EREMOTE) {
                cifs_create_dfs_fattr(&fattr, sb);
@@ -1363,9 +1364,9 @@ out_reval:
                cifs_inode = CIFS_I(inode);
                cifs_inode->time = 0;   /* will force revalidate to get info
                                           when needed */
-               inode->i_ctime = current_fs_time(sb);
+               inode->i_ctime = current_time(inode);
        }
-       dir->i_ctime = dir->i_mtime = current_fs_time(sb);
+       dir->i_ctime = dir->i_mtime = current_time(dir);
        cifs_inode = CIFS_I(dir);
        CIFS_I(dir)->time = 0;  /* force revalidate of dir as well */
 unlink_out:
@@ -1633,7 +1634,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry)
        cifsInode->time = 0;
 
        d_inode(direntry)->i_ctime = inode->i_ctime = inode->i_mtime =
-               current_fs_time(inode->i_sb);
+               current_time(inode);
 
 rmdir_exit:
        kfree(full_path);
@@ -1806,7 +1807,7 @@ unlink_target:
        CIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0;
 
        source_dir->i_ctime = source_dir->i_mtime = target_dir->i_ctime =
-               target_dir->i_mtime = current_fs_time(source_dir->i_sb);
+               target_dir->i_mtime = current_time(source_dir);
 
 cifs_rename_exit:
        kfree(info_buf_source);
index 48ff7703b91912c79b8412539919c3ce6fe76ac6..e4afdaae743f28cf2d1396faed88e7465f875d48 100644 (file)
@@ -1240,15 +1240,19 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
                goto tcon_exit;
        }
 
-       if (rsp->ShareType & SMB2_SHARE_TYPE_DISK)
+       switch (rsp->ShareType) {
+       case SMB2_SHARE_TYPE_DISK:
                cifs_dbg(FYI, "connection to disk share\n");
-       else if (rsp->ShareType & SMB2_SHARE_TYPE_PIPE) {
+               break;
+       case SMB2_SHARE_TYPE_PIPE:
                tcon->ipc = true;
                cifs_dbg(FYI, "connection to pipe share\n");
-       } else if (rsp->ShareType & SMB2_SHARE_TYPE_PRINT) {
-               tcon->print = true;
+               break;
+       case SMB2_SHARE_TYPE_PRINT:
+               tcon->ipc = true;
                cifs_dbg(FYI, "connection to printer\n");
-       } else {
+               break;
+       default:
                cifs_dbg(VFS, "unknown share type %d\n", rsp->ShareType);
                rc = -EOPNOTSUPP;
                goto tcon_error_exit;
@@ -2173,9 +2177,7 @@ smb2_echo_callback(struct mid_q_entry *mid)
        if (mid->mid_state == MID_RESPONSE_RECEIVED)
                credits_received = le16_to_cpu(rsp->hdr.sync_hdr.CreditRequest);
 
-       mutex_lock(&server->srv_mutex);
        DeleteMidQEntry(mid);
-       mutex_unlock(&server->srv_mutex);
        add_credits(server, credits_received, CIFS_ECHO_OP);
 }
 
@@ -2433,9 +2435,7 @@ smb2_readv_callback(struct mid_q_entry *mid)
                cifs_stats_fail_inc(tcon, SMB2_READ_HE);
 
        queue_work(cifsiod_wq, &rdata->work);
-       mutex_lock(&server->srv_mutex);
        DeleteMidQEntry(mid);
-       mutex_unlock(&server->srv_mutex);
        add_credits(server, credits_received, 0);
 }
 
@@ -2594,7 +2594,6 @@ smb2_writev_callback(struct mid_q_entry *mid)
 {
        struct cifs_writedata *wdata = mid->callback_data;
        struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
-       struct TCP_Server_Info *server = tcon->ses->server;
        unsigned int written;
        struct smb2_write_rsp *rsp = (struct smb2_write_rsp *)mid->resp_buf;
        unsigned int credits_received = 1;
@@ -2634,9 +2633,7 @@ smb2_writev_callback(struct mid_q_entry *mid)
                cifs_stats_fail_inc(tcon, SMB2_WRITE_HE);
 
        queue_work(cifsiod_wq, &wdata->work);
-       mutex_lock(&server->srv_mutex);
        DeleteMidQEntry(mid);
-       mutex_unlock(&server->srv_mutex);
        add_credits(tcon->ses->server, credits_received, 0);
 }
 
index 4d64b5b8fc9c6fae67f7f3e0ec74284548ff7c32..47a125ece11ea0d3e2daa0814c8cab28b4643bb1 100644 (file)
@@ -94,7 +94,7 @@ DeleteMidQEntry(struct mid_q_entry *midEntry)
        now = jiffies;
        /* commands taking longer than one second are indications that
           something is wrong, unless it is quite a slow link or server */
-       if ((now - midEntry->when_alloc) > HZ) {
+       if (time_after(now, midEntry->when_alloc + HZ)) {
                if ((cifsFYI & CIFS_TIMER) && (midEntry->command != command)) {
                        pr_debug(" CIFS slow rsp: cmd %d mid %llu",
                               midEntry->command, midEntry->mid);
@@ -613,9 +613,7 @@ cifs_sync_mid_result(struct mid_q_entry *mid, struct TCP_Server_Info *server)
        }
        spin_unlock(&GlobalMid_Lock);
 
-       mutex_lock(&server->srv_mutex);
        DeleteMidQEntry(mid);
-       mutex_unlock(&server->srv_mutex);
        return rc;
 }
 
index 20af5187ba63cc14150185952a3f7cdf9526556d..3cb5c9e2d4e78f641549818fbbad7681b193854d 100644 (file)
@@ -235,8 +235,7 @@ static int cifs_xattr_get(const struct xattr_handler *handler,
 
                if (pTcon->ses->server->ops->query_all_EAs)
                        rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
-                               full_path, name, value, size,
-                               cifs_sb->local_nls, cifs_remap(cifs_sb));
+                               full_path, name, value, size, cifs_sb);
                break;
 
        case XATTR_CIFS_ACL: {
@@ -336,8 +335,7 @@ ssize_t cifs_listxattr(struct dentry *direntry, char *data, size_t buf_size)
 
        if (pTcon->ses->server->ops->query_all_EAs)
                rc = pTcon->ses->server->ops->query_all_EAs(xid, pTcon,
-                               full_path, NULL, data, buf_size,
-                               cifs_sb->local_nls, cifs_remap(cifs_sb));
+                               full_path, NULL, data, buf_size, cifs_sb);
 list_ea_exit:
        kfree(full_path);
        free_xid(xid);
index 11d087b2b28edd79bf03b367d45bfd49bd210352..6116d5275a3ecc7f95d3e3009cca261f8b7c075d 100644 (file)
@@ -833,7 +833,7 @@ static int compat_ioctl_preallocate(struct file *file,
  */
 #define XFORM(i) (((i) ^ ((i) << 27) ^ ((i) << 17)) & 0xffffffff)
 
-#define COMPATIBLE_IOCTL(cmd) XFORM(cmd),
+#define COMPATIBLE_IOCTL(cmd) XFORM((u32)cmd),
 /* ioctl should not be warned about even if it's not implemented.
    Valid reasons to use this:
    - It is implemented with ->compat_ioctl on some device, but programs
index 43bbd6d1037d20099bc50393ab2b255f02e188a7..c22eaf162f95c1456563b31a8362da9e531c9185 100644 (file)
--- a/fs/dax.c
+++ b/fs/dax.c
@@ -460,35 +460,6 @@ int dax_delete_mapping_entry(struct address_space *mapping, pgoff_t index)
        return ret;
 }
 
-/*
- * Invalidate exceptional DAX entry if easily possible. This handles DAX
- * entries for invalidate_inode_pages() so we evict the entry only if we can
- * do so without blocking.
- */
-int dax_invalidate_mapping_entry(struct address_space *mapping, pgoff_t index)
-{
-       int ret = 0;
-       void *entry, **slot;
-       struct radix_tree_root *page_tree = &mapping->page_tree;
-
-       spin_lock_irq(&mapping->tree_lock);
-       entry = __radix_tree_lookup(page_tree, index, NULL, &slot);
-       if (!entry || !radix_tree_exceptional_entry(entry) ||
-           slot_locked(mapping, slot))
-               goto out;
-       if (radix_tree_tag_get(page_tree, index, PAGECACHE_TAG_DIRTY) ||
-           radix_tree_tag_get(page_tree, index, PAGECACHE_TAG_TOWRITE))
-               goto out;
-       radix_tree_delete(page_tree, index);
-       mapping->nrexceptional--;
-       ret = 1;
-out:
-       spin_unlock_irq(&mapping->tree_lock);
-       if (ret)
-               dax_wake_mapping_entry_waiter(mapping, index, entry, true);
-       return ret;
-}
-
 /*
  * Invalidate exceptional DAX entry if it is clean.
  */
@@ -509,21 +480,25 @@ int dax_invalidate_mapping_entry_sync(struct address_space *mapping,
 static int dax_load_hole(struct address_space *mapping, void **entry,
                         struct vm_fault *vmf)
 {
+       struct inode *inode = mapping->host;
        struct page *page;
        int ret;
 
        /* Hole page already exists? Return it...  */
        if (!radix_tree_exceptional_entry(*entry)) {
                page = *entry;
-               goto out;
+               goto finish_fault;
        }
 
        /* This will replace locked radix tree entry with a hole page */
        page = find_or_create_page(mapping, vmf->pgoff,
                                   vmf->gfp_mask | __GFP_ZERO);
-       if (!page)
-               return VM_FAULT_OOM;
- out:
+       if (!page) {
+               ret = VM_FAULT_OOM;
+               goto out;
+       }
+
+finish_fault:
        vmf->page = page;
        ret = finish_fault(vmf);
        vmf->page = NULL;
@@ -531,8 +506,10 @@ static int dax_load_hole(struct address_space *mapping, void **entry,
        if (!ret) {
                /* Grab reference for PTE that is now referencing the page */
                get_page(page);
-               return VM_FAULT_NOPAGE;
+               ret = VM_FAULT_NOPAGE;
        }
+out:
+       trace_dax_load_hole(inode, vmf, ret);
        return ret;
 }
 
@@ -817,6 +794,7 @@ static int dax_writeback_one(struct block_device *bdev,
        spin_lock_irq(&mapping->tree_lock);
        radix_tree_tag_clear(page_tree, index, PAGECACHE_TAG_DIRTY);
        spin_unlock_irq(&mapping->tree_lock);
+       trace_dax_writeback_one(mapping->host, index, size >> PAGE_SHIFT);
  dax_unlock:
        dax_read_unlock(id);
        put_locked_mapping_entry(mapping, index, entry);
@@ -857,6 +835,8 @@ int dax_writeback_mapping_range(struct address_space *mapping,
        start_index = wbc->range_start >> PAGE_SHIFT;
        end_index = wbc->range_end >> PAGE_SHIFT;
 
+       trace_dax_writeback_range(inode, start_index, end_index);
+
        tag_pages_for_writeback(mapping, start_index, end_index);
 
        pagevec_init(&pvec, 0);
@@ -876,14 +856,14 @@ int dax_writeback_mapping_range(struct address_space *mapping,
 
                        ret = dax_writeback_one(bdev, dax_dev, mapping,
                                        indices[i], pvec.pages[i]);
-                       if (ret < 0) {
-                               put_dax(dax_dev);
-                               return ret;
-                       }
+                       if (ret < 0)
+                               goto out;
                }
        }
+out:
        put_dax(dax_dev);
-       return 0;
+       trace_dax_writeback_range_done(inode, start_index, end_index);
+       return (ret < 0 ? ret : 0);
 }
 EXPORT_SYMBOL_GPL(dax_writeback_mapping_range);
 
@@ -916,6 +896,7 @@ static int dax_insert_mapping(struct address_space *mapping,
                return PTR_ERR(ret);
        *entryp = ret;
 
+       trace_dax_insert_mapping(mapping->host, vmf, ret);
        return vm_insert_mixed(vma, vaddr, pfn);
 }
 
@@ -927,6 +908,7 @@ int dax_pfn_mkwrite(struct vm_fault *vmf)
 {
        struct file *file = vmf->vma->vm_file;
        struct address_space *mapping = file->f_mapping;
+       struct inode *inode = mapping->host;
        void *entry, **slot;
        pgoff_t index = vmf->pgoff;
 
@@ -936,6 +918,7 @@ int dax_pfn_mkwrite(struct vm_fault *vmf)
                if (entry)
                        put_unlocked_mapping_entry(mapping, index, entry);
                spin_unlock_irq(&mapping->tree_lock);
+               trace_dax_pfn_mkwrite_no_entry(inode, vmf, VM_FAULT_NOPAGE);
                return VM_FAULT_NOPAGE;
        }
        radix_tree_tag_set(&mapping->page_tree, index, PAGECACHE_TAG_DIRTY);
@@ -948,6 +931,7 @@ int dax_pfn_mkwrite(struct vm_fault *vmf)
         */
        finish_mkwrite_fault(vmf);
        put_locked_mapping_entry(mapping, index, entry);
+       trace_dax_pfn_mkwrite(inode, vmf, VM_FAULT_NOPAGE);
        return VM_FAULT_NOPAGE;
 }
 EXPORT_SYMBOL_GPL(dax_pfn_mkwrite);
@@ -980,12 +964,12 @@ int __dax_zero_page_range(struct block_device *bdev,
                void *kaddr;
                pfn_t pfn;
 
-               rc = bdev_dax_pgoff(bdev, sector, size, &pgoff);
+               rc = bdev_dax_pgoff(bdev, sector, PAGE_SIZE, &pgoff);
                if (rc)
                        return rc;
 
                id = dax_read_lock();
-               rc = dax_direct_access(dax_dev, pgoff, PHYS_PFN(size), &kaddr,
+               rc = dax_direct_access(dax_dev, pgoff, 1, &kaddr,
                                &pfn);
                if (rc < 0) {
                        dax_read_unlock(id);
@@ -1031,7 +1015,7 @@ dax_iomap_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
         * into page tables. We have to tear down these mappings so that data
         * written by write(2) is visible in mmap.
         */
-       if ((iomap->flags & IOMAP_F_NEW) && inode->i_mapping->nrpages) {
+       if (iomap->flags & IOMAP_F_NEW) {
                invalidate_inode_pages2_range(inode->i_mapping,
                                              pos >> PAGE_SHIFT,
                                              (end - 1) >> PAGE_SHIFT);
@@ -1150,34 +1134,39 @@ static int dax_iomap_pte_fault(struct vm_fault *vmf,
        int vmf_ret = 0;
        void *entry;
 
+       trace_dax_pte_fault(inode, vmf, vmf_ret);
        /*
         * Check whether offset isn't beyond end of file now. Caller is supposed
         * to hold locks serializing us with truncate / punch hole so this is
         * a reliable test.
         */
-       if (pos >= i_size_read(inode))
-               return VM_FAULT_SIGBUS;
+       if (pos >= i_size_read(inode)) {
+               vmf_ret = VM_FAULT_SIGBUS;
+               goto out;
+       }
 
        if ((vmf->flags & FAULT_FLAG_WRITE) && !vmf->cow_page)
                flags |= IOMAP_WRITE;
 
+       entry = grab_mapping_entry(mapping, vmf->pgoff, 0);
+       if (IS_ERR(entry)) {
+               vmf_ret = dax_fault_return(PTR_ERR(entry));
+               goto out;
+       }
+
        /*
         * Note that we don't bother to use iomap_apply here: DAX required
         * the file system block size to be equal the page size, which means
         * that we never have to deal with more than a single extent here.
         */
        error = ops->iomap_begin(inode, pos, PAGE_SIZE, flags, &iomap);
-       if (error)
-               return dax_fault_return(error);
-       if (WARN_ON_ONCE(iomap.offset + iomap.length < pos + PAGE_SIZE)) {
-               vmf_ret = dax_fault_return(-EIO);       /* fs corruption? */
-               goto finish_iomap;
+       if (error) {
+               vmf_ret = dax_fault_return(error);
+               goto unlock_entry;
        }
-
-       entry = grab_mapping_entry(mapping, vmf->pgoff, 0);
-       if (IS_ERR(entry)) {
-               vmf_ret = dax_fault_return(PTR_ERR(entry));
-               goto finish_iomap;
+       if (WARN_ON_ONCE(iomap.offset + iomap.length < pos + PAGE_SIZE)) {
+               error = -EIO;   /* fs corruption? */
+               goto error_finish_iomap;
        }
 
        sector = dax_iomap_sector(&iomap, pos);
@@ -1199,13 +1188,13 @@ static int dax_iomap_pte_fault(struct vm_fault *vmf,
                }
 
                if (error)
-                       goto error_unlock_entry;
+                       goto error_finish_iomap;
 
                __SetPageUptodate(vmf->cow_page);
                vmf_ret = finish_fault(vmf);
                if (!vmf_ret)
                        vmf_ret = VM_FAULT_DONE_COW;
-               goto unlock_entry;
+               goto finish_iomap;
        }
 
        switch (iomap.type) {
@@ -1225,7 +1214,7 @@ static int dax_iomap_pte_fault(struct vm_fault *vmf,
        case IOMAP_HOLE:
                if (!(vmf->flags & FAULT_FLAG_WRITE)) {
                        vmf_ret = dax_load_hole(mapping, &entry, vmf);
-                       goto unlock_entry;
+                       goto finish_iomap;
                }
                /*FALLTHRU*/
        default:
@@ -1234,10 +1223,8 @@ static int dax_iomap_pte_fault(struct vm_fault *vmf,
                break;
        }
 
- error_unlock_entry:
+ error_finish_iomap:
        vmf_ret = dax_fault_return(error) | major;
- unlock_entry:
-       put_locked_mapping_entry(mapping, vmf->pgoff, entry);
  finish_iomap:
        if (ops->iomap_end) {
                int copied = PAGE_SIZE;
@@ -1252,6 +1239,10 @@ static int dax_iomap_pte_fault(struct vm_fault *vmf,
                 */
                ops->iomap_end(inode, pos, PAGE_SIZE, copied, flags, &iomap);
        }
+ unlock_entry:
+       put_locked_mapping_entry(mapping, vmf->pgoff, entry);
+ out:
+       trace_dax_pte_fault_done(inode, vmf, vmf_ret);
        return vmf_ret;
 }
 
@@ -1396,6 +1387,16 @@ static int dax_iomap_pmd_fault(struct vm_fault *vmf,
        if ((pgoff | PG_PMD_COLOUR) > max_pgoff)
                goto fallback;
 
+       /*
+        * grab_mapping_entry() will make sure we get a 2M empty entry, a DAX
+        * PMD or a HZP entry.  If it can't (because a 4k page is already in
+        * the tree, for instance), it will return -EEXIST and we just fall
+        * back to 4k entries.
+        */
+       entry = grab_mapping_entry(mapping, pgoff, RADIX_DAX_PMD);
+       if (IS_ERR(entry))
+               goto fallback;
+
        /*
         * Note that we don't use iomap_apply here.  We aren't doing I/O, only
         * setting up a mapping, so really we're using iomap_begin() as a way
@@ -1404,21 +1405,11 @@ static int dax_iomap_pmd_fault(struct vm_fault *vmf,
        pos = (loff_t)pgoff << PAGE_SHIFT;
        error = ops->iomap_begin(inode, pos, PMD_SIZE, iomap_flags, &iomap);
        if (error)
-               goto fallback;
+               goto unlock_entry;
 
        if (iomap.offset + iomap.length < pos + PMD_SIZE)
                goto finish_iomap;
 
-       /*
-        * grab_mapping_entry() will make sure we get a 2M empty entry, a DAX
-        * PMD or a HZP entry.  If it can't (because a 4k page is already in
-        * the tree, for instance), it will return -EEXIST and we just fall
-        * back to 4k entries.
-        */
-       entry = grab_mapping_entry(mapping, pgoff, RADIX_DAX_PMD);
-       if (IS_ERR(entry))
-               goto finish_iomap;
-
        switch (iomap.type) {
        case IOMAP_MAPPED:
                result = dax_pmd_insert_mapping(vmf, &iomap, pos, &entry);
@@ -1426,7 +1417,7 @@ static int dax_iomap_pmd_fault(struct vm_fault *vmf,
        case IOMAP_UNWRITTEN:
        case IOMAP_HOLE:
                if (WARN_ON_ONCE(write))
-                       goto unlock_entry;
+                       break;
                result = dax_pmd_load_hole(vmf, &iomap, &entry);
                break;
        default:
@@ -1434,8 +1425,6 @@ static int dax_iomap_pmd_fault(struct vm_fault *vmf,
                break;
        }
 
- unlock_entry:
-       put_locked_mapping_entry(mapping, pgoff, entry);
  finish_iomap:
        if (ops->iomap_end) {
                int copied = PMD_SIZE;
@@ -1451,6 +1440,8 @@ static int dax_iomap_pmd_fault(struct vm_fault *vmf,
                ops->iomap_end(inode, pos, PMD_SIZE, copied, iomap_flags,
                                &iomap);
        }
+ unlock_entry:
+       put_locked_mapping_entry(mapping, pgoff, entry);
  fallback:
        if (result == VM_FAULT_FALLBACK) {
                split_huge_pmd(vma, vmf->pmd, vmf->address);
index 95d71eda81420a506c5a1f4a4f5283b31310d5e4..cddf39777835d0d27a71862b244cec37528b195b 100644 (file)
@@ -419,6 +419,8 @@ static void dentry_lru_add(struct dentry *dentry)
 {
        if (unlikely(!(dentry->d_flags & DCACHE_LRU_LIST)))
                d_lru_add(dentry);
+       else if (unlikely(!(dentry->d_flags & DCACHE_REFERENCED)))
+               dentry->d_flags |= DCACHE_REFERENCED;
 }
 
 /**
@@ -779,8 +781,6 @@ repeat:
                        goto kill_it;
        }
 
-       if (!(dentry->d_flags & DCACHE_REFERENCED))
-               dentry->d_flags |= DCACHE_REFERENCED;
        dentry_lru_add(dentry);
 
        dentry->d_lockref.count--;
index 7fd4ec4bb21406b1d427f24ee7789c54b62c335b..e892ae7d89f8bc078848d8752affa1598a7e1e11 100644 (file)
@@ -199,7 +199,7 @@ static const struct dentry_operations debugfs_dops = {
 
 static int debug_fill_super(struct super_block *sb, void *data, int silent)
 {
-       static struct tree_descr debug_files[] = {{""}};
+       static const struct tree_descr debug_files[] = {{""}};
        struct debugfs_fs_info *fsi;
        int err;
 
index 42f9a0a0c4caf09722bc69fa278d509a7b7f16b3..8eeb694332fe811e820ed342ebbecc25bb678a1f 100644 (file)
@@ -405,8 +405,7 @@ int exofs_set_link(struct inode *dir, struct exofs_dir_entry *de,
        int err;
 
        lock_page(page);
-       err = exofs_write_begin(NULL, page->mapping, pos, len,
-                               AOP_FLAG_UNINTERRUPTIBLE, &page, NULL);
+       err = exofs_write_begin(NULL, page->mapping, pos, len, 0, &page, NULL);
        if (err)
                EXOFS_ERR("exofs_set_link: exofs_write_begin FAILED => %d\n",
                          err);
index 26d77f9f8c12e69f48bc6cc1c4f47bb6fab27ebd..2dcbd56988843ccdfb017c9b14ca8f5b05a31b62 100644 (file)
@@ -817,7 +817,7 @@ static int ext2_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
        iomap->bdev = bdev;
        iomap->offset = (u64)first_block << blkbits;
        if (blk_queue_dax(bdev->bd_queue))
-               iomap->dax_dev = dax_get_by_host(bdev->bd_disk->disk_name);
+               iomap->dax_dev = fs_dax_get_by_host(bdev->bd_disk->disk_name);
        else
                iomap->dax_dev = NULL;
 
@@ -841,7 +841,7 @@ static int
 ext2_iomap_end(struct inode *inode, loff_t offset, loff_t length,
                ssize_t written, unsigned flags, struct iomap *iomap)
 {
-       put_dax(iomap->dax_dev);
+       fs_put_dax(iomap->dax_dev);
        if (iomap->type == IOMAP_MAPPED &&
            written < length &&
            (flags & IOMAP_WRITE))
index 8ac673c71a3612dcf1fbac84dc653253e0550a1b..9c2028b50e5c389ed6f86a89d9bf94960fcfc8cb 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/log2.h>
 #include <linux/quotaops.h>
 #include <linux/uaccess.h>
+#include <linux/dax.h>
 #include "ext2.h"
 #include "xattr.h"
 #include "acl.h"
index cefa9835f275d9b062ae9b13765ea743edb53f64..831fd6beebf01bfa65c1c4a3ae505ed84bd35526 100644 (file)
@@ -257,6 +257,7 @@ static int ext4_dax_huge_fault(struct vm_fault *vmf,
                enum page_entry_size pe_size)
 {
        int result;
+       handle_t *handle = NULL;
        struct inode *inode = file_inode(vmf->vma->vm_file);
        struct super_block *sb = inode->i_sb;
        bool write = vmf->flags & FAULT_FLAG_WRITE;
@@ -264,12 +265,24 @@ static int ext4_dax_huge_fault(struct vm_fault *vmf,
        if (write) {
                sb_start_pagefault(sb);
                file_update_time(vmf->vma->vm_file);
+               down_read(&EXT4_I(inode)->i_mmap_sem);
+               handle = ext4_journal_start_sb(sb, EXT4_HT_WRITE_PAGE,
+                                              EXT4_DATA_TRANS_BLOCKS(sb));
+       } else {
+               down_read(&EXT4_I(inode)->i_mmap_sem);
        }
-       down_read(&EXT4_I(inode)->i_mmap_sem);
-       result = dax_iomap_fault(vmf, pe_size, &ext4_iomap_ops);
-       up_read(&EXT4_I(inode)->i_mmap_sem);
-       if (write)
+       if (!IS_ERR(handle))
+               result = dax_iomap_fault(vmf, pe_size, &ext4_iomap_ops);
+       else
+               result = VM_FAULT_SIGBUS;
+       if (write) {
+               if (!IS_ERR(handle))
+                       ext4_journal_stop(handle);
+               up_read(&EXT4_I(inode)->i_mmap_sem);
                sb_end_pagefault(sb);
+       } else {
+               up_read(&EXT4_I(inode)->i_mmap_sem);
+       }
 
        return result;
 }
index 5834c4d76be80969125a9c2d56309e990ba07e84..1bd0bfa547f6deee46d8dfe039625ed1736d14ed 100644 (file)
@@ -3412,7 +3412,7 @@ retry:
        bdev = inode->i_sb->s_bdev;
        iomap->bdev = bdev;
        if (blk_queue_dax(bdev->bd_queue))
-               iomap->dax_dev = dax_get_by_host(bdev->bd_disk->disk_name);
+               iomap->dax_dev = fs_dax_get_by_host(bdev->bd_disk->disk_name);
        else
                iomap->dax_dev = NULL;
        iomap->offset = first_block << blkbits;
@@ -3447,7 +3447,7 @@ static int ext4_iomap_end(struct inode *inode, loff_t offset, loff_t length,
        int blkbits = inode->i_blkbits;
        bool truncate = false;
 
-       put_dax(iomap->dax_dev);
+       fs_put_dax(iomap->dax_dev);
        if (!(flags & IOMAP_WRITE) || (flags & IOMAP_FAULT))
                return 0;
 
index 36de58a37653c021793f85ae28a0c4e9066f9601..5083bce20ac4dc2243ace1bba19ef506b90d9c29 100644 (file)
@@ -2393,7 +2393,7 @@ int ext4_mb_alloc_groupinfo(struct super_block *sb, ext4_group_t ngroups)
                return 0;
 
        size = roundup_pow_of_two(sizeof(*sbi->s_group_info) * size);
-       new_groupinfo = ext4_kvzalloc(size, GFP_KERNEL);
+       new_groupinfo = kvzalloc(size, GFP_KERNEL);
        if (!new_groupinfo) {
                ext4_msg(sb, KERN_ERR, "can't allocate buddy meta group");
                return -ENOMEM;
index 96973ee74147718fda40f0a46e6375a7113cc43d..0b177da9ea8271f4a46208937d3c43fd20c0e9b7 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/ctype.h>
 #include <linux/log2.h>
 #include <linux/crc16.h>
+#include <linux/dax.h>
 #include <linux/cleancache.h>
 #include <linux/uaccess.h>
 
@@ -2155,7 +2156,7 @@ int ext4_alloc_flex_bg_array(struct super_block *sb, ext4_group_t ngroup)
                return 0;
 
        size = roundup_pow_of_two(size * sizeof(struct flex_groups));
-       new_groups = ext4_kvzalloc(size, GFP_KERNEL);
+       new_groups = kvzalloc(size, GFP_KERNEL);
        if (!new_groups) {
                ext4_msg(sb, KERN_ERR, "not enough memory for %d flex groups",
                         size / (int) sizeof(struct flex_groups));
@@ -3889,7 +3890,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
                        goto failed_mount;
                }
        }
-       sbi->s_group_desc = ext4_kvmalloc(db_count *
+       sbi->s_group_desc = kvmalloc(db_count *
                                          sizeof(struct buffer_head *),
                                          GFP_KERNEL);
        if (sbi->s_group_desc == NULL) {
index e26999a745220a9691614c21df5a11ee6880a021..2185c7a040a12cf8b6e190df97b58bc7eecc6299 100644 (file)
@@ -2071,26 +2071,6 @@ static inline void *f2fs_kmalloc(struct f2fs_sb_info *sbi,
        return kmalloc(size, flags);
 }
 
-static inline void *f2fs_kvmalloc(size_t size, gfp_t flags)
-{
-       void *ret;
-
-       ret = kmalloc(size, flags | __GFP_NOWARN);
-       if (!ret)
-               ret = __vmalloc(size, flags, PAGE_KERNEL);
-       return ret;
-}
-
-static inline void *f2fs_kvzalloc(size_t size, gfp_t flags)
-{
-       void *ret;
-
-       ret = kzalloc(size, flags | __GFP_NOWARN);
-       if (!ret)
-               ret = __vmalloc(size, flags | __GFP_ZERO, PAGE_KERNEL);
-       return ret;
-}
-
 #define get_inode_mode(i) \
        ((is_inode_flag_set(i, FI_ACL_MODE)) ? \
         (F2FS_I(i)->i_acl_mode) : ((i)->i_mode))
index abb0403d341484fa96e8cfc4634d1cf504b653c2..61af721329fa28563cd7ed6cbe9e3a72a459c69c 100644 (file)
@@ -1011,11 +1011,11 @@ static int __exchange_data_block(struct inode *src_inode,
        while (len) {
                olen = min((pgoff_t)4 * ADDRS_PER_BLOCK, len);
 
-               src_blkaddr = f2fs_kvzalloc(sizeof(block_t) * olen, GFP_KERNEL);
+               src_blkaddr = kvzalloc(sizeof(block_t) * olen, GFP_KERNEL);
                if (!src_blkaddr)
                        return -ENOMEM;
 
-               do_replace = f2fs_kvzalloc(sizeof(int) * olen, GFP_KERNEL);
+               do_replace = kvzalloc(sizeof(int) * olen, GFP_KERNEL);
                if (!do_replace) {
                        kvfree(src_blkaddr);
                        return -ENOMEM;
index 98351a4a4da3f41d00fa3e3256ce741b59e6d715..4547c5c5cd989373235531bb21193531bd05e720 100644 (file)
@@ -2652,17 +2652,17 @@ static int init_free_nid_cache(struct f2fs_sb_info *sbi)
 {
        struct f2fs_nm_info *nm_i = NM_I(sbi);
 
-       nm_i->free_nid_bitmap = f2fs_kvzalloc(nm_i->nat_blocks *
+       nm_i->free_nid_bitmap = kvzalloc(nm_i->nat_blocks *
                                        NAT_ENTRY_BITMAP_SIZE, GFP_KERNEL);
        if (!nm_i->free_nid_bitmap)
                return -ENOMEM;
 
-       nm_i->nat_block_bitmap = f2fs_kvzalloc(nm_i->nat_blocks / 8,
+       nm_i->nat_block_bitmap = kvzalloc(nm_i->nat_blocks / 8,
                                                                GFP_KERNEL);
        if (!nm_i->nat_block_bitmap)
                return -ENOMEM;
 
-       nm_i->free_nid_count = f2fs_kvzalloc(nm_i->nat_blocks *
+       nm_i->free_nid_count = kvzalloc(nm_i->nat_blocks *
                                        sizeof(unsigned short), GFP_KERNEL);
        if (!nm_i->free_nid_count)
                return -ENOMEM;
index de31030b5041c4e618508f8478c7a5660de7a1de..96845854e7ee808c2df5227ddf68a614fcc779ba 100644 (file)
@@ -2834,13 +2834,13 @@ static int build_sit_info(struct f2fs_sb_info *sbi)
 
        SM_I(sbi)->sit_info = sit_i;
 
-       sit_i->sentries = f2fs_kvzalloc(MAIN_SEGS(sbi) *
+       sit_i->sentries = kvzalloc(MAIN_SEGS(sbi) *
                                        sizeof(struct seg_entry), GFP_KERNEL);
        if (!sit_i->sentries)
                return -ENOMEM;
 
        bitmap_size = f2fs_bitmap_size(MAIN_SEGS(sbi));
-       sit_i->dirty_sentries_bitmap = f2fs_kvzalloc(bitmap_size, GFP_KERNEL);
+       sit_i->dirty_sentries_bitmap = kvzalloc(bitmap_size, GFP_KERNEL);
        if (!sit_i->dirty_sentries_bitmap)
                return -ENOMEM;
 
@@ -2873,7 +2873,7 @@ static int build_sit_info(struct f2fs_sb_info *sbi)
                return -ENOMEM;
 
        if (sbi->segs_per_sec > 1) {
-               sit_i->sec_entries = f2fs_kvzalloc(MAIN_SECS(sbi) *
+               sit_i->sec_entries = kvzalloc(MAIN_SECS(sbi) *
                                        sizeof(struct sec_entry), GFP_KERNEL);
                if (!sit_i->sec_entries)
                        return -ENOMEM;
@@ -2906,7 +2906,7 @@ static int build_sit_info(struct f2fs_sb_info *sbi)
        sit_i->dirty_sentries = 0;
        sit_i->sents_per_block = SIT_ENTRY_PER_BLOCK;
        sit_i->elapsed_time = le64_to_cpu(sbi->ckpt->elapsed_time);
-       sit_i->mounted_time = CURRENT_TIME_SEC.tv_sec;
+       sit_i->mounted_time = ktime_get_real_seconds();
        mutex_init(&sit_i->sentry_lock);
        return 0;
 }
@@ -2924,12 +2924,12 @@ static int build_free_segmap(struct f2fs_sb_info *sbi)
        SM_I(sbi)->free_info = free_i;
 
        bitmap_size = f2fs_bitmap_size(MAIN_SEGS(sbi));
-       free_i->free_segmap = f2fs_kvmalloc(bitmap_size, GFP_KERNEL);
+       free_i->free_segmap = kvmalloc(bitmap_size, GFP_KERNEL);
        if (!free_i->free_segmap)
                return -ENOMEM;
 
        sec_bitmap_size = f2fs_bitmap_size(MAIN_SECS(sbi));
-       free_i->free_secmap = f2fs_kvmalloc(sec_bitmap_size, GFP_KERNEL);
+       free_i->free_secmap = kvmalloc(sec_bitmap_size, GFP_KERNEL);
        if (!free_i->free_secmap)
                return -ENOMEM;
 
@@ -3109,7 +3109,7 @@ static int init_victim_secmap(struct f2fs_sb_info *sbi)
        struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
        unsigned int bitmap_size = f2fs_bitmap_size(MAIN_SECS(sbi));
 
-       dirty_i->victim_secmap = f2fs_kvzalloc(bitmap_size, GFP_KERNEL);
+       dirty_i->victim_secmap = kvzalloc(bitmap_size, GFP_KERNEL);
        if (!dirty_i->victim_secmap)
                return -ENOMEM;
        return 0;
@@ -3131,7 +3131,7 @@ static int build_dirty_segmap(struct f2fs_sb_info *sbi)
        bitmap_size = f2fs_bitmap_size(MAIN_SEGS(sbi));
 
        for (i = 0; i < NR_DIRTY_TYPE; i++) {
-               dirty_i->dirty_segmap[i] = f2fs_kvzalloc(bitmap_size, GFP_KERNEL);
+               dirty_i->dirty_segmap[i] = kvzalloc(bitmap_size, GFP_KERNEL);
                if (!dirty_i->dirty_segmap[i])
                        return -ENOMEM;
        }
index 10bf05d4cff49be8152a8e6aa434ec0ccb0827d4..010f336a75730e5920d67a38d04b64cebc59bf57 100644 (file)
@@ -712,8 +712,9 @@ static inline void set_to_next_sit(struct sit_info *sit_i, unsigned int start)
 static inline unsigned long long get_mtime(struct f2fs_sb_info *sbi)
 {
        struct sit_info *sit_i = SIT_I(sbi);
-       return sit_i->elapsed_time + CURRENT_TIME_SEC.tv_sec -
-                                               sit_i->mounted_time;
+       time64_t now = ktime_get_real_seconds();
+
+       return sit_i->elapsed_time + now - sit_i->mounted_time;
 }
 
 static inline void set_summary(struct f2fs_summary *sum, nid_t nid,
index 8bd81c2e89b2701c9b64aa46556e623e5bb4acb4..f4e7267d117fb83b69f6f5be2305fb8b375077c8 100644 (file)
@@ -899,16 +899,10 @@ static int __init fcntl_init(void)
         * Exceptions: O_NONBLOCK is a two bit define on parisc; O_NDELAY
         * is defined as O_NONBLOCK on some platforms and not on others.
         */
-       BUILD_BUG_ON(21 - 1 /* for O_RDONLY being 0 */ != HWEIGHT32(
-               O_RDONLY        | O_WRONLY      | O_RDWR        |
-               O_CREAT         | O_EXCL        | O_NOCTTY      |
-               O_TRUNC         | O_APPEND      | /* O_NONBLOCK | */
-               __O_SYNC        | O_DSYNC       | FASYNC        |
-               O_DIRECT        | O_LARGEFILE   | O_DIRECTORY   |
-               O_NOFOLLOW      | O_NOATIME     | O_CLOEXEC     |
-               __FMODE_EXEC    | O_PATH        | __O_TMPFILE   |
-               __FMODE_NONOTIFY
-               ));
+       BUILD_BUG_ON(21 - 1 /* for O_RDONLY being 0 */ !=
+               HWEIGHT32(
+                       (VALID_OPEN_FLAGS & ~(O_NONBLOCK | O_NDELAY)) |
+                       __FMODE_EXEC | __FMODE_NONOTIFY));
 
        fasync_cache = kmem_cache_create("fasync_cache",
                sizeof(struct fasync_struct), 0, SLAB_PANIC, NULL);
index ad6f094f2eff2f90314d237fa3f3cb16c5b79b66..1c2972e3a405455e292520032342276cc621d369 100644 (file)
--- a/fs/file.c
+++ b/fs/file.c
@@ -42,7 +42,7 @@ static void *alloc_fdmem(size_t size)
                if (data != NULL)
                        return data;
        }
-       return __vmalloc(size, GFP_KERNEL_ACCOUNT | __GFP_HIGHMEM, PAGE_KERNEL);
+       return __vmalloc(size, GFP_KERNEL_ACCOUNT, PAGE_KERNEL);
 }
 
 static void __free_fdtable(struct fdtable *fdt)
index 6e22748b0704c509edad6a0e93d0a6626601137b..b9ea99c5b5b31948882d37113d520ab9cdcf9564 100644 (file)
@@ -292,7 +292,7 @@ void fuse_ctl_remove_conn(struct fuse_conn *fc)
 
 static int fuse_ctl_fill_super(struct super_block *sb, void *data, int silent)
 {
-       struct tree_descr empty_descr = {""};
+       static const struct tree_descr empty_descr = {""};
        struct fuse_conn *fc;
        int err;
 
index c2d7f3a92679dd371af2a5fe9f9c2dfe1e0f39b2..c16d00e5326459c6608268f9ce3f68f30467eac6 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/pipe_fs_i.h>
 #include <linux/swap.h>
 #include <linux/splice.h>
+#include <linux/sched.h>
 
 MODULE_ALIAS_MISCDEV(FUSE_MINOR);
 MODULE_ALIAS("devname:fuse");
@@ -45,7 +46,7 @@ static void fuse_request_init(struct fuse_req *req, struct page **pages,
        INIT_LIST_HEAD(&req->list);
        INIT_LIST_HEAD(&req->intr_entry);
        init_waitqueue_head(&req->waitq);
-       atomic_set(&req->count, 1);
+       refcount_set(&req->count, 1);
        req->pages = pages;
        req->page_descs = page_descs;
        req->max_pages = npages;
@@ -102,21 +103,20 @@ void fuse_request_free(struct fuse_req *req)
 
 void __fuse_get_request(struct fuse_req *req)
 {
-       atomic_inc(&req->count);
+       refcount_inc(&req->count);
 }
 
 /* Must be called with > 1 refcount */
 static void __fuse_put_request(struct fuse_req *req)
 {
-       BUG_ON(atomic_read(&req->count) < 2);
-       atomic_dec(&req->count);
+       refcount_dec(&req->count);
 }
 
-static void fuse_req_init_context(struct fuse_req *req)
+static void fuse_req_init_context(struct fuse_conn *fc, struct fuse_req *req)
 {
        req->in.h.uid = from_kuid_munged(&init_user_ns, current_fsuid());
        req->in.h.gid = from_kgid_munged(&init_user_ns, current_fsgid());
-       req->in.h.pid = current->pid;
+       req->in.h.pid = pid_nr_ns(task_pid(current), fc->pid_ns);
 }
 
 void fuse_set_initialized(struct fuse_conn *fc)
@@ -163,7 +163,7 @@ static struct fuse_req *__fuse_get_req(struct fuse_conn *fc, unsigned npages,
                goto out;
        }
 
-       fuse_req_init_context(req);
+       fuse_req_init_context(fc, req);
        __set_bit(FR_WAITING, &req->flags);
        if (for_background)
                __set_bit(FR_BACKGROUND, &req->flags);
@@ -256,7 +256,7 @@ struct fuse_req *fuse_get_req_nofail_nopages(struct fuse_conn *fc,
        if (!req)
                req = get_reserved_req(fc, file);
 
-       fuse_req_init_context(req);
+       fuse_req_init_context(fc, req);
        __set_bit(FR_WAITING, &req->flags);
        __clear_bit(FR_BACKGROUND, &req->flags);
        return req;
@@ -264,7 +264,7 @@ struct fuse_req *fuse_get_req_nofail_nopages(struct fuse_conn *fc,
 
 void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req)
 {
-       if (atomic_dec_and_test(&req->count)) {
+       if (refcount_dec_and_test(&req->count)) {
                if (test_bit(FR_BACKGROUND, &req->flags)) {
                        /*
                         * We get here in the unlikely case that a background
@@ -1222,6 +1222,9 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
        struct fuse_in *in;
        unsigned reqsize;
 
+       if (task_active_pid_ns(current) != fc->pid_ns)
+               return -EIO;
+
  restart:
        spin_lock(&fiq->waitq.lock);
        err = -EAGAIN;
@@ -1820,6 +1823,9 @@ static ssize_t fuse_dev_do_write(struct fuse_dev *fud,
        struct fuse_req *req;
        struct fuse_out_header oh;
 
+       if (task_active_pid_ns(current) != fc->pid_ns)
+               return -EIO;
+
        if (nbytes < sizeof(struct fuse_out_header))
                return -EINVAL;
 
index ec238fb5a584b1c3cc5bc545806575160f78cde4..3ee4fdc3da9ec359ad847afa36354240329a2da6 100644 (file)
@@ -58,7 +58,7 @@ struct fuse_file *fuse_file_alloc(struct fuse_conn *fc)
        }
 
        INIT_LIST_HEAD(&ff->write_entry);
-       atomic_set(&ff->count, 1);
+       refcount_set(&ff->count, 1);
        RB_CLEAR_NODE(&ff->polled_node);
        init_waitqueue_head(&ff->poll_wait);
 
@@ -77,7 +77,7 @@ void fuse_file_free(struct fuse_file *ff)
 
 static struct fuse_file *fuse_file_get(struct fuse_file *ff)
 {
-       atomic_inc(&ff->count);
+       refcount_inc(&ff->count);
        return ff;
 }
 
@@ -88,7 +88,7 @@ static void fuse_release_end(struct fuse_conn *fc, struct fuse_req *req)
 
 static void fuse_file_put(struct fuse_file *ff, bool sync)
 {
-       if (atomic_dec_and_test(&ff->count)) {
+       if (refcount_dec_and_test(&ff->count)) {
                struct fuse_req *req = ff->reserved_req;
 
                if (ff->fc->no_open) {
@@ -293,7 +293,7 @@ static int fuse_release(struct inode *inode, struct file *file)
 
 void fuse_sync_release(struct fuse_file *ff, int flags)
 {
-       WARN_ON(atomic_read(&ff->count) != 1);
+       WARN_ON(refcount_read(&ff->count) > 1);
        fuse_prepare_release(ff, flags, FUSE_RELEASE);
        /*
         * iput(NULL) is a no-op and since the refcount is 1 and everything's
@@ -2083,7 +2083,8 @@ static int fuse_direct_mmap(struct file *file, struct vm_area_struct *vma)
        return generic_file_mmap(file, vma);
 }
 
-static int convert_fuse_file_lock(const struct fuse_file_lock *ffl,
+static int convert_fuse_file_lock(struct fuse_conn *fc,
+                                 const struct fuse_file_lock *ffl,
                                  struct file_lock *fl)
 {
        switch (ffl->type) {
@@ -2098,7 +2099,14 @@ static int convert_fuse_file_lock(const struct fuse_file_lock *ffl,
 
                fl->fl_start = ffl->start;
                fl->fl_end = ffl->end;
-               fl->fl_pid = ffl->pid;
+
+               /*
+                * Convert pid into the caller's pid namespace. If the pid
+                * does not map into the namespace fl_pid will get set to 0.
+                */
+               rcu_read_lock();
+               fl->fl_pid = pid_vnr(find_pid_ns(ffl->pid, fc->pid_ns));
+               rcu_read_unlock();
                break;
 
        default:
@@ -2147,7 +2155,7 @@ static int fuse_getlk(struct file *file, struct file_lock *fl)
        args.out.args[0].value = &outarg;
        err = fuse_simple_request(fc, &args);
        if (!err)
-               err = convert_fuse_file_lock(&outarg.lk, fl);
+               err = convert_fuse_file_lock(fc, &outarg.lk, fl);
 
        return err;
 }
@@ -2159,7 +2167,8 @@ static int fuse_setlk(struct file *file, struct file_lock *fl, int flock)
        FUSE_ARGS(args);
        struct fuse_lk_in inarg;
        int opcode = (fl->fl_flags & FL_SLEEP) ? FUSE_SETLKW : FUSE_SETLK;
-       pid_t pid = fl->fl_type != F_UNLCK ? current->tgid : 0;
+       struct pid *pid = fl->fl_type != F_UNLCK ? task_tgid(current) : NULL;
+       pid_t pid_nr = pid_nr_ns(pid, fc->pid_ns);
        int err;
 
        if (fl->fl_lmops && fl->fl_lmops->lm_grant) {
@@ -2168,10 +2177,13 @@ static int fuse_setlk(struct file *file, struct file_lock *fl, int flock)
        }
 
        /* Unlock on close is handled by the flush method */
-       if (fl->fl_flags & FL_CLOSE)
+       if ((fl->fl_flags & FL_CLOSE_POSIX) == FL_CLOSE_POSIX)
                return 0;
 
-       fuse_lk_fill(&args, file, fl, opcode, pid, flock, &inarg);
+       if (pid && pid_nr == 0)
+               return -EOVERFLOW;
+
+       fuse_lk_fill(&args, file, fl, opcode, pid_nr, flock, &inarg);
        err = fuse_simple_request(fc, &args);
 
        /* locking is restartable */
index f33341d9501a02079d1da148add1a23642c68a81..1bd7ffdad593977013c1ddd233b2a91093471471 100644 (file)
@@ -24,6 +24,8 @@
 #include <linux/workqueue.h>
 #include <linux/kref.h>
 #include <linux/xattr.h>
+#include <linux/pid_namespace.h>
+#include <linux/refcount.h>
 
 /** Max number of pages that can be used in a single read request */
 #define FUSE_MAX_PAGES_PER_REQ 32
@@ -137,7 +139,7 @@ struct fuse_file {
        u64 nodeid;
 
        /** Refcount */
-       atomic_t count;
+       refcount_t count;
 
        /** FOPEN_* flags returned by open */
        u32 open_flags;
@@ -306,7 +308,7 @@ struct fuse_req {
        struct list_head intr_entry;
 
        /** refcount */
-       atomic_t count;
+       refcount_t count;
 
        /** Unique ID for the interrupt request */
        u64 intr_unique;
@@ -448,7 +450,7 @@ struct fuse_conn {
        spinlock_t lock;
 
        /** Refcount */
-       atomic_t count;
+       refcount_t count;
 
        /** Number of fuse_dev's */
        atomic_t dev_count;
@@ -461,6 +463,9 @@ struct fuse_conn {
        /** The group id for this mount */
        kgid_t group_id;
 
+       /** The pid namespace for this mount */
+       struct pid_namespace *pid_ns;
+
        /** Maximum read size */
        unsigned max_read;
 
index 73cf051352521ad400af30befd3afbd2fc595c31..5a1b58f8fef4d2437842b73d4c1c12b2e87a32c9 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/sched.h>
 #include <linux/exportfs.h>
 #include <linux/posix_acl.h>
+#include <linux/pid_namespace.h>
 
 MODULE_AUTHOR("Miklos Szeredi <miklos@szeredi.hu>");
 MODULE_DESCRIPTION("Filesystem in Userspace");
@@ -601,7 +602,7 @@ void fuse_conn_init(struct fuse_conn *fc)
        memset(fc, 0, sizeof(*fc));
        spin_lock_init(&fc->lock);
        init_rwsem(&fc->killsb);
-       atomic_set(&fc->count, 1);
+       refcount_set(&fc->count, 1);
        atomic_set(&fc->dev_count, 1);
        init_waitqueue_head(&fc->blocked_waitq);
        init_waitqueue_head(&fc->reserved_req_waitq);
@@ -619,14 +620,16 @@ void fuse_conn_init(struct fuse_conn *fc)
        fc->connected = 1;
        fc->attr_version = 1;
        get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key));
+       fc->pid_ns = get_pid_ns(task_active_pid_ns(current));
 }
 EXPORT_SYMBOL_GPL(fuse_conn_init);
 
 void fuse_conn_put(struct fuse_conn *fc)
 {
-       if (atomic_dec_and_test(&fc->count)) {
+       if (refcount_dec_and_test(&fc->count)) {
                if (fc->destroy_req)
                        fuse_request_free(fc->destroy_req);
+               put_pid_ns(fc->pid_ns);
                fc->release(fc);
        }
 }
@@ -634,7 +637,7 @@ EXPORT_SYMBOL_GPL(fuse_conn_put);
 
 struct fuse_conn *fuse_conn_get(struct fuse_conn *fc)
 {
-       atomic_inc(&fc->count);
+       refcount_inc(&fc->count);
        return fc;
 }
 EXPORT_SYMBOL_GPL(fuse_conn_get);
index 3814a60e0aeae8ed38a3aad55786983c31c145b7..4d810be532ddcb6d9d18b234383c5167b0780e32 100644 (file)
@@ -1072,7 +1072,7 @@ out_unlock:
                        /* Every transaction boundary, we rewrite the dinode
                           to keep its di_blocks current in case of failure. */
                        ip->i_inode.i_mtime = ip->i_inode.i_ctime =
-                               CURRENT_TIME;
+                               current_time(&ip->i_inode);
                        gfs2_trans_add_meta(ip->i_gl, dibh);
                        gfs2_dinode_out(ip, dibh->b_data);
                        up_write(&ip->i_rw_mutex);
@@ -1293,7 +1293,7 @@ static int trunc_dealloc(struct gfs2_inode *ip, u64 newsize)
                gfs2_statfs_change(sdp, 0, +btotal, 0);
                gfs2_quota_change(ip, -(s64)btotal, ip->i_inode.i_uid,
                                  ip->i_inode.i_gid);
-               ip->i_inode.i_mtime = ip->i_inode.i_ctime = CURRENT_TIME;
+               ip->i_inode.i_mtime = ip->i_inode.i_ctime = current_time(&ip->i_inode);
                gfs2_trans_add_meta(ip->i_gl, dibh);
                gfs2_dinode_out(ip, dibh->b_data);
                up_write(&ip->i_rw_mutex);
index e33a0d36a93ebea7183909ff45f523302943b694..5d01826545809de7de454e2615553fc6a637ce70 100644 (file)
@@ -485,8 +485,8 @@ void hfs_file_truncate(struct inode *inode)
 
                /* XXX: Can use generic_cont_expand? */
                size = inode->i_size - 1;
-               res = pagecache_write_begin(NULL, mapping, size+1, 0,
-                               AOP_FLAG_UNINTERRUPTIBLE, &page, &fsdata);
+               res = pagecache_write_begin(NULL, mapping, size+1, 0, 0,
+                                           &page, &fsdata);
                if (!res) {
                        res = pagecache_write_end(NULL, mapping, size+1, 0, 0,
                                        page, fsdata);
index feca524ce2a5c7d6034bf0a528679fe923381507..a3eb640b4f8f8474130a893100303a0211d9037c 100644 (file)
@@ -545,9 +545,8 @@ void hfsplus_file_truncate(struct inode *inode)
                void *fsdata;
                loff_t size = inode->i_size;
 
-               res = pagecache_write_begin(NULL, mapping, size, 0,
-                                               AOP_FLAG_UNINTERRUPTIBLE,
-                                               &page, &fsdata);
+               res = pagecache_write_begin(NULL, mapping, size, 0, 0,
+                                           &page, &fsdata);
                if (res)
                        return;
                res = pagecache_write_end(NULL, mapping, size,
index 131b2bcebc48309bedb5f4ac8d1e95d867b81d65..db5914783a7130d77725502cb4182c05ff7775c2 100644 (file)
@@ -119,7 +119,7 @@ static int no_open(struct inode *inode, struct file *file)
 }
 
 /**
- * inode_init_always - perform inode structure intialisation
+ * inode_init_always - perform inode structure initialisation
  * @sb: superblock inode belongs to
  * @inode: inode to initialise
  *
@@ -402,6 +402,8 @@ static void inode_lru_list_add(struct inode *inode)
 {
        if (list_lru_add(&inode->i_sb->s_inode_lru, &inode->i_lru))
                this_cpu_inc(nr_unused);
+       else
+               inode->i_state |= I_REFERENCED;
 }
 
 /*
@@ -1489,7 +1491,6 @@ static void iput_final(struct inode *inode)
                drop = generic_drop_inode(inode);
 
        if (!drop && (sb->s_flags & MS_ACTIVE)) {
-               inode->i_state |= I_REFERENCED;
                inode_add_lru(inode);
                spin_unlock(&inode->i_lock);
                return;
index 076751d90ba256678aeb414238d18d4d27b1b42d..9676fe11c093538d284ec5c2c59e9a2a9e37c1f6 100644 (file)
@@ -126,8 +126,6 @@ static inline bool atime_needs_update_rcu(const struct path *path,
        return __atime_needs_update(path, inode, true);
 }
 
-extern bool atime_needs_update_rcu(const struct path *, struct inode *);
-
 /*
  * fs-writeback.c
  */
index 1faabe09b8fdb20f8dc355cc06ce452013ce64ec..4b10892967a5ae9a4ece5d8571e47c01c72f74da 100644 (file)
@@ -158,12 +158,6 @@ iomap_write_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
        ssize_t written = 0;
        unsigned int flags = AOP_FLAG_NOFS;
 
-       /*
-        * Copies from kernel address space cannot fail (NFSD is a big user).
-        */
-       if (!iter_is_iovec(i))
-               flags |= AOP_FLAG_UNINTERRUPTIBLE;
-
        do {
                struct page *page;
                unsigned long offset;   /* Offset into pagecache page */
@@ -291,8 +285,7 @@ iomap_dirty_actor(struct inode *inode, loff_t pos, loff_t length, void *data,
                        return PTR_ERR(rpage);
 
                status = iomap_write_begin(inode, pos, bytes,
-                               AOP_FLAG_NOFS | AOP_FLAG_UNINTERRUPTIBLE,
-                               &page, iomap);
+                                          AOP_FLAG_NOFS, &page, iomap);
                put_page(rpage);
                if (unlikely(status))
                        return status;
@@ -343,8 +336,8 @@ static int iomap_zero(struct inode *inode, loff_t pos, unsigned offset,
        struct page *page;
        int status;
 
-       status = iomap_write_begin(inode, pos, bytes,
-                       AOP_FLAG_UNINTERRUPTIBLE | AOP_FLAG_NOFS, &page, iomap);
+       status = iomap_write_begin(inode, pos, bytes, AOP_FLAG_NOFS, &page,
+                                  iomap);
        if (status)
                return status;
 
index 5a0245e362408657e6d101c10c6479ca21aa40eb..ebad34266bcfbbf4fb5d491b2f2699583f7116e1 100644 (file)
@@ -2363,7 +2363,7 @@ static int jbd2_journal_init_journal_head_cache(void)
        jbd2_journal_head_cache = kmem_cache_create("jbd2_journal_head",
                                sizeof(struct journal_head),
                                0,              /* offset */
-                               SLAB_TEMPORARY | SLAB_DESTROY_BY_RCU,
+                               SLAB_TEMPORARY | SLAB_TYPESAFE_BY_RCU,
                                NULL);          /* ctor */
        retval = 0;
        if (!jbd2_journal_head_cache) {
index 06a71dbd4833e3bdf4ea5277bc50e15ee40c45ad..389ea53ea487538061ff3b6da78e27df2f894ac1 100644 (file)
@@ -1366,7 +1366,7 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
                jffs2_add_ino_cache(c, f->inocache);
        }
        if (!f->inocache) {
-               JFFS2_ERROR("requestied to read an nonexistent ino %u\n", ino);
+               JFFS2_ERROR("requested to read a nonexistent ino %u\n", ino);
                return -ENOENT;
        }
 
index a8b62e5d43a972d3b02867e6d9c2136b23987ecd..a04395334bb156ae04853639650dc9751fb55753 100644 (file)
@@ -507,7 +507,7 @@ EXPORT_SYMBOL(simple_write_end);
  * to pass it an appropriate max_reserved value to avoid collisions.
  */
 int simple_fill_super(struct super_block *s, unsigned long magic,
-                     struct tree_descr *files)
+                     const struct tree_descr *files)
 {
        struct inode *inode;
        struct dentry *root;
index 41e491b8e5d7e40164e0e51d90534c9d8660a94e..27d577dbe51a48f21950a63758e76783fed67eca 100644 (file)
@@ -69,6 +69,7 @@ struct nlm_host *nlmclnt_init(const struct nlmclnt_initdata *nlm_init)
        if (host->h_rpcclnt == NULL && nlm_bind_host(host) == NULL)
                goto out_nobind;
 
+       host->h_nlmclnt_ops = nlm_init->nlmclnt_ops;
        return host;
 out_nobind:
        nlmclnt_release_host(host);
index 112952037933b79fa36dbea67579c576ee19be58..066ac313ae5c0fff15188d3123079acd9a7180f3 100644 (file)
@@ -150,17 +150,22 @@ static void nlmclnt_release_lockargs(struct nlm_rqst *req)
  * @host: address of a valid nlm_host context representing the NLM server
  * @cmd: fcntl-style file lock operation to perform
  * @fl: address of arguments for the lock operation
+ * @data: address of data to be sent to callback operations
  *
  */
-int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl)
+int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl, void *data)
 {
        struct nlm_rqst         *call;
        int                     status;
+       const struct nlmclnt_operations *nlmclnt_ops = host->h_nlmclnt_ops;
 
        call = nlm_alloc_call(host);
        if (call == NULL)
                return -ENOMEM;
 
+       if (nlmclnt_ops && nlmclnt_ops->nlmclnt_alloc_call)
+               nlmclnt_ops->nlmclnt_alloc_call(data);
+
        nlmclnt_locks_init_private(fl, host);
        if (!fl->fl_u.nfs_fl.owner) {
                /* lockowner allocation has failed */
@@ -169,6 +174,7 @@ int nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl)
        }
        /* Set up the argument struct */
        nlmclnt_setlockargs(call, fl);
+       call->a_callback_data = data;
 
        if (IS_SETLK(cmd) || IS_SETLKW(cmd)) {
                if (fl->fl_type != F_UNLCK) {
@@ -214,8 +220,12 @@ struct nlm_rqst *nlm_alloc_call(struct nlm_host *host)
 
 void nlmclnt_release_call(struct nlm_rqst *call)
 {
+       const struct nlmclnt_operations *nlmclnt_ops = call->a_host->h_nlmclnt_ops;
+
        if (!atomic_dec_and_test(&call->a_count))
                return;
+       if (nlmclnt_ops && nlmclnt_ops->nlmclnt_release_call)
+               nlmclnt_ops->nlmclnt_release_call(call->a_callback_data);
        nlmclnt_release_host(call->a_host);
        nlmclnt_release_lockargs(call);
        kfree(call);
@@ -687,6 +697,19 @@ out:
        return status;
 }
 
+static void nlmclnt_unlock_prepare(struct rpc_task *task, void *data)
+{
+       struct nlm_rqst *req = data;
+       const struct nlmclnt_operations *nlmclnt_ops = req->a_host->h_nlmclnt_ops;
+       bool defer_call = false;
+
+       if (nlmclnt_ops && nlmclnt_ops->nlmclnt_unlock_prepare)
+               defer_call = nlmclnt_ops->nlmclnt_unlock_prepare(task, req->a_callback_data);
+
+       if (!defer_call)
+               rpc_call_start(task);
+}
+
 static void nlmclnt_unlock_callback(struct rpc_task *task, void *data)
 {
        struct nlm_rqst *req = data;
@@ -720,6 +743,7 @@ die:
 }
 
 static const struct rpc_call_ops nlmclnt_unlock_ops = {
+       .rpc_call_prepare = nlmclnt_unlock_prepare,
        .rpc_call_done = nlmclnt_unlock_callback,
        .rpc_release = nlmclnt_rpc_release,
 };
index e7c8b9c76e48573a381d0196d0dc2166045a7b3e..5d481e8a1b5d0c732207c4a583027ec084d7a0db 100644 (file)
@@ -132,6 +132,8 @@ lockd(void *vrqstp)
 {
        int             err = 0;
        struct svc_rqst *rqstp = vrqstp;
+       struct net *net = &init_net;
+       struct lockd_net *ln = net_generic(net, lockd_net_id);
 
        /* try_to_freeze() is called from svc_recv() */
        set_freezable();
@@ -176,6 +178,8 @@ lockd(void *vrqstp)
        if (nlmsvc_ops)
                nlmsvc_invalidate_all();
        nlm_shutdown_hosts();
+       cancel_delayed_work_sync(&ln->grace_period_end);
+       locks_end_grace(&ln->lockd_manager);
        return 0;
 }
 
@@ -270,8 +274,6 @@ static void lockd_down_net(struct svc_serv *serv, struct net *net)
        if (ln->nlmsvc_users) {
                if (--ln->nlmsvc_users == 0) {
                        nlm_shutdown_hosts_net(net);
-                       cancel_delayed_work_sync(&ln->grace_period_end);
-                       locks_end_grace(&ln->lockd_manager);
                        svc_shutdown_net(serv, net);
                        dprintk("lockd_down_net: per-net data destroyed; net=%p\n", net);
                }
index 5581e020644bda687f0b4bd09645a058a18d4537..3507c80d1d4b962b579d501201f4cdd060e6248b 100644 (file)
@@ -870,15 +870,15 @@ nlmsvc_grant_reply(struct nlm_cookie *cookie, __be32 status)
        if (!(block = nlmsvc_find_block(cookie)))
                return;
 
-       if (block) {
-               if (status == nlm_lck_denied_grace_period) {
-                       /* Try again in a couple of seconds */
-                       nlmsvc_insert_block(block, 10 * HZ);
-               } else {
-                       /* Lock is now held by client, or has been rejected.
-                        * In both cases, the block should be removed. */
-                       nlmsvc_unlink_block(block);
-               }
+       if (status == nlm_lck_denied_grace_period) {
+               /* Try again in a couple of seconds */
+               nlmsvc_insert_block(block, 10 * HZ);
+       } else {
+               /*
+                * Lock is now held by client, or has been rejected.
+                * In both cases, the block should be removed.
+                */
+               nlmsvc_unlink_block(block);
        }
        nlmsvc_release_block(block);
 }
index 26811321d39b8d404046100ac3dcc4b5e04f5cc7..af2031a1fcff14fcfb05e108b9d49bfc4a74685f 100644 (file)
@@ -2504,7 +2504,7 @@ locks_remove_flock(struct file *filp, struct file_lock_context *flctx)
                .fl_owner = filp,
                .fl_pid = current->tgid,
                .fl_file = filp,
-               .fl_flags = FL_FLOCK,
+               .fl_flags = FL_FLOCK | FL_CLOSE,
                .fl_type = F_UNLCK,
                .fl_end = OFFSET_MAX,
        };
index 9a7f8bd748d817b29901e82943e06ae05811f73b..6571a5f5112ed82894fdbec1c9b6dfaf557d93b1 100644 (file)
@@ -2142,7 +2142,6 @@ OK:
 
 static const char *path_init(struct nameidata *nd, unsigned flags)
 {
-       int retval = 0;
        const char *s = nd->name->name;
 
        if (!*s)
@@ -2154,13 +2153,8 @@ static const char *path_init(struct nameidata *nd, unsigned flags)
        if (flags & LOOKUP_ROOT) {
                struct dentry *root = nd->root.dentry;
                struct inode *inode = root->d_inode;
-               if (*s) {
-                       if (!d_can_lookup(root))
-                               return ERR_PTR(-ENOTDIR);
-                       retval = inode_permission(inode, MAY_EXEC);
-                       if (retval)
-                               return ERR_PTR(retval);
-               }
+               if (*s && unlikely(!d_can_lookup(root)))
+                       return ERR_PTR(-ENOTDIR);
                nd->path = nd->root;
                nd->inode = inode;
                if (flags & LOOKUP_RCU) {
@@ -2258,6 +2252,35 @@ static inline int lookup_last(struct nameidata *nd)
        return walk_component(nd, 0);
 }
 
+static int handle_lookup_down(struct nameidata *nd)
+{
+       struct path path = nd->path;
+       struct inode *inode = nd->inode;
+       unsigned seq = nd->seq;
+       int err;
+
+       if (nd->flags & LOOKUP_RCU) {
+               /*
+                * don't bother with unlazy_walk on failure - we are
+                * at the very beginning of walk, so we lose nothing
+                * if we simply redo everything in non-RCU mode
+                */
+               if (unlikely(!__follow_mount_rcu(nd, &path, &inode, &seq)))
+                       return -ECHILD;
+       } else {
+               dget(path.dentry);
+               err = follow_managed(&path, nd);
+               if (unlikely(err < 0))
+                       return err;
+               inode = d_backing_inode(path.dentry);
+               seq = 0;
+       }
+       path_to_nameidata(&path, nd);
+       nd->inode = inode;
+       nd->seq = seq;
+       return 0;
+}
+
 /* Returns 0 and nd will be valid on success; Retuns error, otherwise. */
 static int path_lookupat(struct nameidata *nd, unsigned flags, struct path *path)
 {
@@ -2266,6 +2289,15 @@ static int path_lookupat(struct nameidata *nd, unsigned flags, struct path *path
 
        if (IS_ERR(s))
                return PTR_ERR(s);
+
+       if (unlikely(flags & LOOKUP_DOWN)) {
+               err = handle_lookup_down(nd);
+               if (unlikely(err < 0)) {
+                       terminate_walk(nd);
+                       return err;
+               }
+       }
+
        while (!(err = link_path_walk(s, nd))
                && ((err = lookup_last(nd)) > 0)) {
                s = trailing_symlink(nd);
@@ -4766,7 +4798,7 @@ int __page_symlink(struct inode *inode, const char *symname, int len, int nofs)
        struct page *page;
        void *fsdata;
        int err;
-       unsigned int flags = AOP_FLAG_UNINTERRUPTIBLE;
+       unsigned int flags = 0;
        if (nofs)
                flags |= AOP_FLAG_NOFS;
 
index b3b115bd4e1ee397f01bf0930f5f9900be5878bf..8bd3e4d448b9f07a8aa148c8d08c092f45471a7c 100644 (file)
@@ -3462,8 +3462,9 @@ static void mntns_put(struct ns_common *ns)
 static int mntns_install(struct nsproxy *nsproxy, struct ns_common *ns)
 {
        struct fs_struct *fs = current->fs;
-       struct mnt_namespace *mnt_ns = to_mnt_ns(ns);
+       struct mnt_namespace *mnt_ns = to_mnt_ns(ns), *old_mnt_ns;
        struct path root;
+       int err;
 
        if (!ns_capable(mnt_ns->user_ns, CAP_SYS_ADMIN) ||
            !ns_capable(current_user_ns(), CAP_SYS_CHROOT) ||
@@ -3474,15 +3475,18 @@ static int mntns_install(struct nsproxy *nsproxy, struct ns_common *ns)
                return -EINVAL;
 
        get_mnt_ns(mnt_ns);
-       put_mnt_ns(nsproxy->mnt_ns);
+       old_mnt_ns = nsproxy->mnt_ns;
        nsproxy->mnt_ns = mnt_ns;
 
        /* Find the root */
-       root.mnt    = &mnt_ns->root->mnt;
-       root.dentry = mnt_ns->root->mnt.mnt_root;
-       path_get(&root);
-       while(d_mountpoint(root.dentry) && follow_down_one(&root))
-               ;
+       err = vfs_path_lookup(mnt_ns->root->mnt.mnt_root, &mnt_ns->root->mnt,
+                               "/", LOOKUP_DOWN, &root);
+       if (err) {
+               /* revert to old namespace */
+               nsproxy->mnt_ns = old_mnt_ns;
+               put_mnt_ns(mnt_ns);
+               return err;
+       }
 
        /* Update the pwd and root */
        set_fs_pwd(fs, &root);
index f31fd0dd92c61d22fc477b6da0ccc62a7eb0481d..69d02cf8cf370678609175d6e5626d0dedf02c3a 100644 (file)
@@ -123,11 +123,6 @@ config PNFS_BLOCK
        depends on NFS_V4_1 && BLK_DEV_DM
        default NFS_V4
 
-config PNFS_OBJLAYOUT
-       tristate
-       depends on NFS_V4_1 && SCSI_OSD_ULD
-       default NFS_V4
-
 config PNFS_FLEXFILE_LAYOUT
        tristate
        depends on NFS_V4_1 && NFS_V3
index 6abdda209642e70d917308282d82ec2cfa0f353b..98f4e5728a67c87c13cc8ca52d00e72e7bb3bc2c 100644 (file)
@@ -31,6 +31,5 @@ nfsv4-$(CONFIG_NFS_V4_1)      += pnfs.o pnfs_dev.o pnfs_nfs.o
 nfsv4-$(CONFIG_NFS_V4_2)       += nfs42proc.o
 
 obj-$(CONFIG_PNFS_FILE_LAYOUT) += filelayout/
-obj-$(CONFIG_PNFS_OBJLAYOUT) += objlayout/
 obj-$(CONFIG_PNFS_BLOCK) += blocklayout/
 obj-$(CONFIG_PNFS_FLEXFILE_LAYOUT) += flexfilelayout/
index 773774531aff5fc081610706ea39756b0e5a5c25..73a1f928226c05706bab82a37468973bff7b185c 100644 (file)
@@ -76,7 +76,10 @@ nfs4_callback_svc(void *vrqstp)
 
        set_freezable();
 
-       while (!kthread_should_stop()) {
+       while (!kthread_freezable_should_stop(NULL)) {
+
+               if (signal_pending(current))
+                       flush_signals(current);
                /*
                 * Listen for a request on the socket
                 */
@@ -85,6 +88,8 @@ nfs4_callback_svc(void *vrqstp)
                        continue;
                svc_process(rqstp);
        }
+       svc_exit_thread(rqstp);
+       module_put_and_exit(0);
        return 0;
 }
 
@@ -103,9 +108,10 @@ nfs41_callback_svc(void *vrqstp)
 
        set_freezable();
 
-       while (!kthread_should_stop()) {
-               if (try_to_freeze())
-                       continue;
+       while (!kthread_freezable_should_stop(NULL)) {
+
+               if (signal_pending(current))
+                       flush_signals(current);
 
                prepare_to_wait(&serv->sv_cb_waitq, &wq, TASK_INTERRUPTIBLE);
                spin_lock_bh(&serv->sv_cb_lock);
@@ -121,11 +127,13 @@ nfs41_callback_svc(void *vrqstp)
                                error);
                } else {
                        spin_unlock_bh(&serv->sv_cb_lock);
-                       schedule();
+                       if (!kthread_should_stop())
+                               schedule();
                        finish_wait(&serv->sv_cb_waitq, &wq);
                }
-               flush_signals(current);
        }
+       svc_exit_thread(rqstp);
+       module_put_and_exit(0);
        return 0;
 }
 
@@ -221,14 +229,14 @@ err_bind:
 static struct svc_serv_ops nfs40_cb_sv_ops = {
        .svo_function           = nfs4_callback_svc,
        .svo_enqueue_xprt       = svc_xprt_do_enqueue,
-       .svo_setup              = svc_set_num_threads,
+       .svo_setup              = svc_set_num_threads_sync,
        .svo_module             = THIS_MODULE,
 };
 #if defined(CONFIG_NFS_V4_1)
 static struct svc_serv_ops nfs41_cb_sv_ops = {
        .svo_function           = nfs41_callback_svc,
        .svo_enqueue_xprt       = svc_xprt_do_enqueue,
-       .svo_setup              = svc_set_num_threads,
+       .svo_setup              = svc_set_num_threads_sync,
        .svo_module             = THIS_MODULE,
 };
 
@@ -280,7 +288,7 @@ static struct svc_serv *nfs_callback_create_svc(int minorversion)
                printk(KERN_WARNING "nfs_callback_create_svc: no kthread, %d users??\n",
                        cb_info->users);
 
-       serv = svc_create(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, sv_ops);
+       serv = svc_create_pooled(&nfs4_callback_program, NFS4_CALLBACK_BUFSIZE, sv_ops);
        if (!serv) {
                printk(KERN_ERR "nfs_callback_create_svc: create service failed\n");
                return ERR_PTR(-ENOMEM);
index f073a6d2c6a51a4ec91cf38783519ca957bdece4..52479f180ea1497af4f8a250db4d8c222ce8bfaa 100644 (file)
@@ -131,10 +131,11 @@ restart:
                        if (!inode)
                                continue;
                        if (!nfs_sb_active(inode->i_sb)) {
-                               rcu_read_lock();
+                               rcu_read_unlock();
                                spin_unlock(&clp->cl_lock);
                                iput(inode);
                                spin_lock(&clp->cl_lock);
+                               rcu_read_lock();
                                goto restart;
                        }
                        return inode;
@@ -170,10 +171,11 @@ restart:
                        if (!inode)
                                continue;
                        if (!nfs_sb_active(inode->i_sb)) {
-                               rcu_read_lock();
+                               rcu_read_unlock();
                                spin_unlock(&clp->cl_lock);
                                iput(inode);
                                spin_lock(&clp->cl_lock);
+                               rcu_read_lock();
                                goto restart;
                        }
                        return inode;
@@ -317,31 +319,18 @@ static u32 initiate_bulk_draining(struct nfs_client *clp,
 static u32 do_callback_layoutrecall(struct nfs_client *clp,
                                    struct cb_layoutrecallargs *args)
 {
-       u32 res;
-
-       dprintk("%s enter, type=%i\n", __func__, args->cbl_recall_type);
        if (args->cbl_recall_type == RETURN_FILE)
-               res = initiate_file_draining(clp, args);
-       else
-               res = initiate_bulk_draining(clp, args);
-       dprintk("%s returning %i\n", __func__, res);
-       return res;
-
+               return initiate_file_draining(clp, args);
+       return initiate_bulk_draining(clp, args);
 }
 
 __be32 nfs4_callback_layoutrecall(struct cb_layoutrecallargs *args,
                                  void *dummy, struct cb_process_state *cps)
 {
-       u32 res;
-
-       dprintk("%s: -->\n", __func__);
+       u32 res = NFS4ERR_OP_NOT_IN_SESSION;
 
        if (cps->clp)
                res = do_callback_layoutrecall(cps->clp, args);
-       else
-               res = NFS4ERR_OP_NOT_IN_SESSION;
-
-       dprintk("%s: exit with status = %d\n", __func__, res);
        return cpu_to_be32(res);
 }
 
@@ -364,8 +353,6 @@ __be32 nfs4_callback_devicenotify(struct cb_devicenotifyargs *args,
        struct nfs_client *clp = cps->clp;
        struct nfs_server *server = NULL;
 
-       dprintk("%s: -->\n", __func__);
-
        if (!clp) {
                res = cpu_to_be32(NFS4ERR_OP_NOT_IN_SESSION);
                goto out;
@@ -384,8 +371,6 @@ __be32 nfs4_callback_devicenotify(struct cb_devicenotifyargs *args,
                                        goto found;
                                }
                        rcu_read_unlock();
-                       dprintk("%s: layout type %u not found\n",
-                               __func__, dev->cbd_layout_type);
                        continue;
                }
 
@@ -395,8 +380,6 @@ __be32 nfs4_callback_devicenotify(struct cb_devicenotifyargs *args,
 
 out:
        kfree(args->devs);
-       dprintk("%s: exit with status = %u\n",
-               __func__, be32_to_cpu(res));
        return res;
 }
 
@@ -417,16 +400,11 @@ static __be32
 validate_seqid(const struct nfs4_slot_table *tbl, const struct nfs4_slot *slot,
                const struct cb_sequenceargs * args)
 {
-       dprintk("%s enter. slotid %u seqid %u, slot table seqid: %u\n",
-               __func__, args->csa_slotid, args->csa_sequenceid, slot->seq_nr);
-
        if (args->csa_slotid > tbl->server_highest_slotid)
                return htonl(NFS4ERR_BADSLOT);
 
        /* Replay */
        if (args->csa_sequenceid == slot->seq_nr) {
-               dprintk("%s seqid %u is a replay\n",
-                       __func__, args->csa_sequenceid);
                if (nfs4_test_locked_slot(tbl, slot->slot_nr))
                        return htonl(NFS4ERR_DELAY);
                /* Signal process_op to set this error on next op */
@@ -480,15 +458,6 @@ static bool referring_call_exists(struct nfs_client *clp,
 
                for (j = 0; j < rclist->rcl_nrefcalls; j++) {
                        ref = &rclist->rcl_refcalls[j];
-
-                       dprintk("%s: sessionid %x:%x:%x:%x sequenceid %u "
-                               "slotid %u\n", __func__,
-                               ((u32 *)&rclist->rcl_sessionid.data)[0],
-                               ((u32 *)&rclist->rcl_sessionid.data)[1],
-                               ((u32 *)&rclist->rcl_sessionid.data)[2],
-                               ((u32 *)&rclist->rcl_sessionid.data)[3],
-                               ref->rc_sequenceid, ref->rc_slotid);
-
                        status = nfs4_slot_wait_on_seqid(tbl, ref->rc_slotid,
                                        ref->rc_sequenceid, HZ >> 1) < 0;
                        if (status)
@@ -593,8 +562,6 @@ out:
                res->csr_status = status;
 
        trace_nfs4_cb_sequence(args, res, status);
-       dprintk("%s: exit with status = %d res->csr_status %d\n", __func__,
-               ntohl(status), ntohl(res->csr_status));
        return status;
 }
 
index d051fc3583a9097d46d8159860ea6c22a7ec116a..c14758e08d738eec44bf08c79acee71366ce0e70 100644 (file)
@@ -171,8 +171,6 @@ static __be32 decode_compound_hdr_arg(struct xdr_stream *xdr, struct cb_compound
                return htonl(NFS4ERR_MINOR_VERS_MISMATCH);
        }
        hdr->nops = ntohl(*p);
-       dprintk("%s: minorversion %d nops %d\n", __func__,
-               hdr->minorversion, hdr->nops);
        return 0;
 }
 
@@ -192,11 +190,8 @@ static __be32 decode_getattr_args(struct svc_rqst *rqstp, struct xdr_stream *xdr
 
        status = decode_fh(xdr, &args->fh);
        if (unlikely(status != 0))
-               goto out;
-       status = decode_bitmap(xdr, args->bitmap);
-out:
-       dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
-       return status;
+               return status;
+       return decode_bitmap(xdr, args->bitmap);
 }
 
 static __be32 decode_recall_args(struct svc_rqst *rqstp, struct xdr_stream *xdr, struct cb_recallargs *args)
@@ -206,17 +201,12 @@ static __be32 decode_recall_args(struct svc_rqst *rqstp, struct xdr_stream *xdr,
 
        status = decode_delegation_stateid(xdr, &args->stateid);
        if (unlikely(status != 0))
-               goto out;
+               return status;
        p = read_buf(xdr, 4);
-       if (unlikely(p == NULL)) {
-               status = htonl(NFS4ERR_RESOURCE);
-               goto out;
-       }
+       if (unlikely(p == NULL))
+               return htonl(NFS4ERR_RESOURCE);
        args->truncate = ntohl(*p);
-       status = decode_fh(xdr, &args->fh);
-out:
-       dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
-       return status;
+       return decode_fh(xdr, &args->fh);
 }
 
 #if defined(CONFIG_NFS_V4_1)
@@ -235,10 +225,8 @@ static __be32 decode_layoutrecall_args(struct svc_rqst *rqstp,
        uint32_t iomode;
 
        p = read_buf(xdr, 4 * sizeof(uint32_t));
-       if (unlikely(p == NULL)) {
-               status = htonl(NFS4ERR_BADXDR);
-               goto out;
-       }
+       if (unlikely(p == NULL))
+               return htonl(NFS4ERR_BADXDR);
 
        args->cbl_layout_type = ntohl(*p++);
        /* Depite the spec's xdr, iomode really belongs in the FILE switch,
@@ -252,37 +240,23 @@ static __be32 decode_layoutrecall_args(struct svc_rqst *rqstp,
                args->cbl_range.iomode = iomode;
                status = decode_fh(xdr, &args->cbl_fh);
                if (unlikely(status != 0))
-                       goto out;
+                       return status;
 
                p = read_buf(xdr, 2 * sizeof(uint64_t));
-               if (unlikely(p == NULL)) {
-                       status = htonl(NFS4ERR_BADXDR);
-                       goto out;
-               }
+               if (unlikely(p == NULL))
+                       return htonl(NFS4ERR_BADXDR);
                p = xdr_decode_hyper(p, &args->cbl_range.offset);
                p = xdr_decode_hyper(p, &args->cbl_range.length);
-               status = decode_layout_stateid(xdr, &args->cbl_stateid);
-               if (unlikely(status != 0))
-                       goto out;
+               return decode_layout_stateid(xdr, &args->cbl_stateid);
        } else if (args->cbl_recall_type == RETURN_FSID) {
                p = read_buf(xdr, 2 * sizeof(uint64_t));
-               if (unlikely(p == NULL)) {
-                       status = htonl(NFS4ERR_BADXDR);
-                       goto out;
-               }
+               if (unlikely(p == NULL))
+                       return htonl(NFS4ERR_BADXDR);
                p = xdr_decode_hyper(p, &args->cbl_fsid.major);
                p = xdr_decode_hyper(p, &args->cbl_fsid.minor);
-       } else if (args->cbl_recall_type != RETURN_ALL) {
-               status = htonl(NFS4ERR_BADXDR);
-               goto out;
-       }
-       dprintk("%s: ltype 0x%x iomode %d changed %d recall_type %d\n",
-               __func__,
-               args->cbl_layout_type, iomode,
-               args->cbl_layoutchanged, args->cbl_recall_type);
-out:
-       dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
-       return status;
+       } else if (args->cbl_recall_type != RETURN_ALL)
+               return htonl(NFS4ERR_BADXDR);
+       return 0;
 }
 
 static
@@ -437,12 +411,11 @@ static __be32 decode_cb_sequence_args(struct svc_rqst *rqstp,
 
        status = decode_sessionid(xdr, &args->csa_sessionid);
        if (status)
-               goto out;
+               return status;
 
-       status = htonl(NFS4ERR_RESOURCE);
        p = read_buf(xdr, 5 * sizeof(uint32_t));
        if (unlikely(p == NULL))
-               goto out;
+               return htonl(NFS4ERR_RESOURCE);
 
        args->csa_addr = svc_addr(rqstp);
        args->csa_sequenceid = ntohl(*p++);
@@ -456,7 +429,7 @@ static __be32 decode_cb_sequence_args(struct svc_rqst *rqstp,
                                                  sizeof(*args->csa_rclists),
                                                  GFP_KERNEL);
                if (unlikely(args->csa_rclists == NULL))
-                       goto out;
+                       return htonl(NFS4ERR_RESOURCE);
 
                for (i = 0; i < args->csa_nrclists; i++) {
                        status = decode_rc_list(xdr, &args->csa_rclists[i]);
@@ -466,27 +439,13 @@ static __be32 decode_cb_sequence_args(struct svc_rqst *rqstp,
                        }
                }
        }
-       status = 0;
-
-       dprintk("%s: sessionid %x:%x:%x:%x sequenceid %u slotid %u "
-               "highestslotid %u cachethis %d nrclists %u\n",
-               __func__,
-               ((u32 *)&args->csa_sessionid)[0],
-               ((u32 *)&args->csa_sessionid)[1],
-               ((u32 *)&args->csa_sessionid)[2],
-               ((u32 *)&args->csa_sessionid)[3],
-               args->csa_sequenceid, args->csa_slotid,
-               args->csa_highestslotid, args->csa_cachethis,
-               args->csa_nrclists);
-out:
-       dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
-       return status;
+       return 0;
 
 out_free:
        for (i = 0; i < args->csa_nrclists; i++)
                kfree(args->csa_rclists[i].rcl_refcalls);
        kfree(args->csa_rclists);
-       goto out;
+       return status;
 }
 
 static __be32 decode_recallany_args(struct svc_rqst *rqstp,
@@ -557,11 +516,8 @@ static __be32 decode_notify_lock_args(struct svc_rqst *rqstp, struct xdr_stream
 
        status = decode_fh(xdr, &args->cbnl_fh);
        if (unlikely(status != 0))
-               goto out;
-       status = decode_lockowner(xdr, args);
-out:
-       dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
-       return status;
+               return status;
+       return decode_lockowner(xdr, args);
 }
 
 #endif /* CONFIG_NFS_V4_1 */
@@ -707,7 +663,6 @@ static __be32 encode_getattr_res(struct svc_rqst *rqstp, struct xdr_stream *xdr,
        status = encode_attr_mtime(xdr, res->bitmap, &res->mtime);
        *savep = htonl((unsigned int)((char *)xdr->p - (char *)(savep+1)));
 out:
-       dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
        return status;
 }
 
@@ -734,11 +689,11 @@ static __be32 encode_cb_sequence_res(struct svc_rqst *rqstp,
        __be32 status = res->csr_status;
 
        if (unlikely(status != 0))
-               goto out;
+               return status;
 
        status = encode_sessionid(xdr, &res->csr_sessionid);
        if (status)
-               goto out;
+               return status;
 
        p = xdr_reserve_space(xdr, 4 * sizeof(uint32_t));
        if (unlikely(p == NULL))
@@ -748,9 +703,7 @@ static __be32 encode_cb_sequence_res(struct svc_rqst *rqstp,
        *p++ = htonl(res->csr_slotid);
        *p++ = htonl(res->csr_highestslotid);
        *p++ = htonl(res->csr_target_highestslotid);
-out:
-       dprintk("%s: exit with status = %d\n", __func__, ntohl(status));
-       return status;
+       return 0;
 }
 
 static __be32
@@ -871,14 +824,10 @@ static __be32 process_op(int nop, struct svc_rqst *rqstp,
        long maxlen;
        __be32 res;
 
-       dprintk("%s: start\n", __func__);
        status = decode_op_hdr(xdr_in, &op_nr);
        if (unlikely(status))
                return status;
 
-       dprintk("%s: minorversion=%d nop=%d op_nr=%u\n",
-               __func__, cps->minorversion, nop, op_nr);
-
        switch (cps->minorversion) {
        case 0:
                status = preprocess_nfs4_op(op_nr, &op);
@@ -917,7 +866,6 @@ encode_hdr:
                return res;
        if (op->encode_res != NULL && status == 0)
                status = op->encode_res(rqstp, xdr_out, resp);
-       dprintk("%s: done, status = %d\n", __func__, ntohl(status));
        return status;
 }
 
@@ -937,8 +885,6 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
        };
        unsigned int nops = 0;
 
-       dprintk("%s: start\n", __func__);
-
        xdr_init_decode(&xdr_in, &rqstp->rq_arg, rqstp->rq_arg.head[0].iov_base);
 
        p = (__be32*)((char *)rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len);
@@ -977,7 +923,6 @@ static __be32 nfs4_callback_compound(struct svc_rqst *rqstp, void *argp, void *r
        *hdr_res.nops = htonl(nops);
        nfs4_cb_free_slot(&cps);
        nfs_put_client(cps.clp);
-       dprintk("%s: done, status = %u\n", __func__, ntohl(status));
        return rpc_success;
 
 out_invalidcred:
index 04d15a0045e37173c124f78771243f8b444f3dce..ee5ddbd36088e66d21b2900fddb9c7ded0d17f9a 100644 (file)
@@ -218,6 +218,7 @@ static void nfs_cb_idr_remove_locked(struct nfs_client *clp)
 static void pnfs_init_server(struct nfs_server *server)
 {
        rpc_init_wait_queue(&server->roc_rpcwaitq, "pNFS ROC");
+       rpc_init_wait_queue(&server->uoc_rpcwaitq, "NFS UOC");
 }
 
 #else
@@ -240,8 +241,6 @@ static void pnfs_init_server(struct nfs_server *server)
  */
 void nfs_free_client(struct nfs_client *clp)
 {
-       dprintk("--> nfs_free_client(%u)\n", clp->rpc_ops->version);
-
        nfs_fscache_release_client_cookie(clp);
 
        /* -EIO all pending I/O */
@@ -256,8 +255,6 @@ void nfs_free_client(struct nfs_client *clp)
        kfree(clp->cl_hostname);
        kfree(clp->cl_acceptor);
        kfree(clp);
-
-       dprintk("<-- nfs_free_client()\n");
 }
 EXPORT_SYMBOL_GPL(nfs_free_client);
 
@@ -271,7 +268,6 @@ void nfs_put_client(struct nfs_client *clp)
        if (!clp)
                return;
 
-       dprintk("--> nfs_put_client({%d})\n", atomic_read(&clp->cl_count));
        nn = net_generic(clp->cl_net, nfs_net_id);
 
        if (atomic_dec_and_lock(&clp->cl_count, &nn->nfs_client_lock)) {
@@ -382,9 +378,6 @@ nfs_found_client(const struct nfs_client_initdata *cl_init,
        }
 
        smp_rmb();
-
-       dprintk("<-- %s found nfs_client %p for %s\n",
-               __func__, clp, cl_init->hostname ?: "");
        return clp;
 }
 
@@ -403,9 +396,6 @@ struct nfs_client *nfs_get_client(const struct nfs_client_initdata *cl_init)
                return NULL;
        }
 
-       dprintk("--> nfs_get_client(%s,v%u)\n",
-               cl_init->hostname, rpc_ops->version);
-
        /* see if the client already exists */
        do {
                spin_lock(&nn->nfs_client_lock);
@@ -430,8 +420,6 @@ struct nfs_client *nfs_get_client(const struct nfs_client_initdata *cl_init)
                new = rpc_ops->alloc_client(cl_init);
        } while (!IS_ERR(new));
 
-       dprintk("<-- nfs_get_client() Failed to find %s (%ld)\n",
-               cl_init->hostname, PTR_ERR(new));
        return new;
 }
 EXPORT_SYMBOL_GPL(nfs_get_client);
@@ -558,6 +546,7 @@ static int nfs_start_lockd(struct nfs_server *server)
                .noresvport     = server->flags & NFS_MOUNT_NORESVPORT ?
                                        1 : 0,
                .net            = clp->cl_net,
+               .nlmclnt_ops    = clp->cl_nfs_mod->rpc_ops->nlmclnt_ops,
        };
 
        if (nlm_init.nfs_version > 3)
@@ -624,27 +613,21 @@ struct nfs_client *nfs_init_client(struct nfs_client *clp,
 {
        int error;
 
-       if (clp->cl_cons_state == NFS_CS_READY) {
-               /* the client is already initialised */
-               dprintk("<-- nfs_init_client() = 0 [already %p]\n", clp);
+       /* the client is already initialised */
+       if (clp->cl_cons_state == NFS_CS_READY)
                return clp;
-       }
 
        /*
         * Create a client RPC handle for doing FSSTAT with UNIX auth only
         * - RFC 2623, sec 2.3.2
         */
        error = nfs_create_rpc_client(clp, cl_init, RPC_AUTH_UNIX);
-       if (error < 0)
-               goto error;
-       nfs_mark_client_ready(clp, NFS_CS_READY);
+       nfs_mark_client_ready(clp, error == 0 ? NFS_CS_READY : error);
+       if (error < 0) {
+               nfs_put_client(clp);
+               clp = ERR_PTR(error);
+       }
        return clp;
-
-error:
-       nfs_mark_client_ready(clp, error);
-       nfs_put_client(clp);
-       dprintk("<-- nfs_init_client() = xerror %d\n", error);
-       return ERR_PTR(error);
 }
 EXPORT_SYMBOL_GPL(nfs_init_client);
 
@@ -668,8 +651,6 @@ static int nfs_init_server(struct nfs_server *server,
        struct nfs_client *clp;
        int error;
 
-       dprintk("--> nfs_init_server()\n");
-
        nfs_init_timeout_values(&timeparms, data->nfs_server.protocol,
                        data->timeo, data->retrans);
        if (data->flags & NFS_MOUNT_NORESVPORT)
@@ -677,10 +658,8 @@ static int nfs_init_server(struct nfs_server *server,
 
        /* Allocate or find a client reference we can use */
        clp = nfs_get_client(&cl_init);
-       if (IS_ERR(clp)) {
-               dprintk("<-- nfs_init_server() = error %ld\n", PTR_ERR(clp));
+       if (IS_ERR(clp))
                return PTR_ERR(clp);
-       }
 
        server->nfs_client = clp;
 
@@ -725,13 +704,11 @@ static int nfs_init_server(struct nfs_server *server,
        server->mountd_protocol = data->mount_server.protocol;
 
        server->namelen  = data->namlen;
-       dprintk("<-- nfs_init_server() = 0 [new %p]\n", clp);
        return 0;
 
 error:
        server->nfs_client = NULL;
        nfs_put_client(clp);
-       dprintk("<-- nfs_init_server() = xerror %d\n", error);
        return error;
 }
 
@@ -798,12 +775,10 @@ int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, struct nfs
        struct nfs_client *clp = server->nfs_client;
        int error;
 
-       dprintk("--> nfs_probe_fsinfo()\n");
-
        if (clp->rpc_ops->set_capabilities != NULL) {
                error = clp->rpc_ops->set_capabilities(server, mntfh);
                if (error < 0)
-                       goto out_error;
+                       return error;
        }
 
        fsinfo.fattr = fattr;
@@ -811,7 +786,7 @@ int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, struct nfs
        memset(fsinfo.layouttype, 0, sizeof(fsinfo.layouttype));
        error = clp->rpc_ops->fsinfo(server, mntfh, &fsinfo);
        if (error < 0)
-               goto out_error;
+               return error;
 
        nfs_server_set_fsinfo(server, &fsinfo);
 
@@ -826,12 +801,7 @@ int nfs_probe_fsinfo(struct nfs_server *server, struct nfs_fh *mntfh, struct nfs
                        server->namelen = pathinfo.max_namelen;
        }
 
-       dprintk("<-- nfs_probe_fsinfo() = 0\n");
        return 0;
-
-out_error:
-       dprintk("nfs_probe_fsinfo: error = %d\n", -error);
-       return error;
 }
 EXPORT_SYMBOL_GPL(nfs_probe_fsinfo);
 
@@ -927,8 +897,6 @@ EXPORT_SYMBOL_GPL(nfs_alloc_server);
  */
 void nfs_free_server(struct nfs_server *server)
 {
-       dprintk("--> nfs_free_server()\n");
-
        nfs_server_remove_lists(server);
 
        if (server->destroy != NULL)
@@ -946,7 +914,6 @@ void nfs_free_server(struct nfs_server *server)
        nfs_free_iostats(server->io_stats);
        kfree(server);
        nfs_release_automount_timer();
-       dprintk("<-- nfs_free_server()\n");
 }
 EXPORT_SYMBOL_GPL(nfs_free_server);
 
@@ -1026,10 +993,6 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source,
        struct nfs_fattr *fattr_fsinfo;
        int error;
 
-       dprintk("--> nfs_clone_server(,%llx:%llx,)\n",
-               (unsigned long long) fattr->fsid.major,
-               (unsigned long long) fattr->fsid.minor);
-
        server = nfs_alloc_server();
        if (!server)
                return ERR_PTR(-ENOMEM);
@@ -1061,10 +1024,6 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source,
        if (server->namelen == 0 || server->namelen > NFS4_MAXNAMLEN)
                server->namelen = NFS4_MAXNAMLEN;
 
-       dprintk("Cloned FSID: %llx:%llx\n",
-               (unsigned long long) server->fsid.major,
-               (unsigned long long) server->fsid.minor);
-
        error = nfs_start_lockd(server);
        if (error < 0)
                goto out_free_server;
@@ -1073,13 +1032,11 @@ struct nfs_server *nfs_clone_server(struct nfs_server *source,
        server->mount_time = jiffies;
 
        nfs_free_fattr(fattr_fsinfo);
-       dprintk("<-- nfs_clone_server() = %p\n", server);
        return server;
 
 out_free_server:
        nfs_free_fattr(fattr_fsinfo);
        nfs_free_server(server);
-       dprintk("<-- nfs_clone_server() = error %d\n", error);
        return ERR_PTR(error);
 }
 EXPORT_SYMBOL_GPL(nfs_clone_server);
index f92ba8d6c5569099f6c469eda92446ad0d7e148d..32ccd7754f8a2875933d1f9c532b54c656971bfd 100644 (file)
@@ -57,7 +57,7 @@ static void nfs_readdir_clear_array(struct page*);
 const struct file_operations nfs_dir_operations = {
        .llseek         = nfs_llseek_dir,
        .read           = generic_read_dir,
-       .iterate_shared = nfs_readdir,
+       .iterate        = nfs_readdir,
        .open           = nfs_opendir,
        .release        = nfs_closedir,
        .fsync          = nfs_fsync_dir,
@@ -145,7 +145,6 @@ struct nfs_cache_array_entry {
 };
 
 struct nfs_cache_array {
-       atomic_t refcount;
        int size;
        int eof_index;
        u64 last_cookie;
@@ -170,27 +169,6 @@ typedef struct {
        unsigned int    eof:1;
 } nfs_readdir_descriptor_t;
 
-/*
- * The caller is responsible for calling nfs_readdir_release_array(page)
- */
-static
-struct nfs_cache_array *nfs_readdir_get_array(struct page *page)
-{
-       void *ptr;
-       if (page == NULL)
-               return ERR_PTR(-EIO);
-       ptr = kmap(page);
-       if (ptr == NULL)
-               return ERR_PTR(-ENOMEM);
-       return ptr;
-}
-
-static
-void nfs_readdir_release_array(struct page *page)
-{
-       kunmap(page);
-}
-
 /*
  * we are freeing strings created by nfs_add_to_readdir_array()
  */
@@ -201,18 +179,9 @@ void nfs_readdir_clear_array(struct page *page)
        int i;
 
        array = kmap_atomic(page);
-       if (atomic_dec_and_test(&array->refcount))
-               for (i = 0; i < array->size; i++)
-                       kfree(array->array[i].string.name);
-       kunmap_atomic(array);
-}
-
-static bool grab_page(struct page *page)
-{
-       struct nfs_cache_array *array = kmap_atomic(page);
-       bool res = atomic_inc_not_zero(&array->refcount);
+       for (i = 0; i < array->size; i++)
+               kfree(array->array[i].string.name);
        kunmap_atomic(array);
-       return res;
 }
 
 /*
@@ -239,13 +208,10 @@ int nfs_readdir_make_qstr(struct qstr *string, const char *name, unsigned int le
 static
 int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page)
 {
-       struct nfs_cache_array *array = nfs_readdir_get_array(page);
+       struct nfs_cache_array *array = kmap(page);
        struct nfs_cache_array_entry *cache_entry;
        int ret;
 
-       if (IS_ERR(array))
-               return PTR_ERR(array);
-
        cache_entry = &array->array[array->size];
 
        /* Check that this entry lies within the page bounds */
@@ -264,7 +230,7 @@ int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page)
        if (entry->eof != 0)
                array->eof_index = array->size;
 out:
-       nfs_readdir_release_array(page);
+       kunmap(page);
        return ret;
 }
 
@@ -353,11 +319,7 @@ int nfs_readdir_search_array(nfs_readdir_descriptor_t *desc)
        struct nfs_cache_array *array;
        int status;
 
-       array = nfs_readdir_get_array(desc->page);
-       if (IS_ERR(array)) {
-               status = PTR_ERR(array);
-               goto out;
-       }
+       array = kmap(desc->page);
 
        if (*desc->dir_cookie == 0)
                status = nfs_readdir_search_for_pos(array, desc);
@@ -369,8 +331,7 @@ int nfs_readdir_search_array(nfs_readdir_descriptor_t *desc)
                desc->current_index += array->size;
                desc->page_index++;
        }
-       nfs_readdir_release_array(desc->page);
-out:
+       kunmap(desc->page);
        return status;
 }
 
@@ -606,13 +567,10 @@ int nfs_readdir_page_filler(nfs_readdir_descriptor_t *desc, struct nfs_entry *en
 
 out_nopages:
        if (count == 0 || (status == -EBADCOOKIE && entry->eof != 0)) {
-               array = nfs_readdir_get_array(page);
-               if (!IS_ERR(array)) {
-                       array->eof_index = array->size;
-                       status = 0;
-                       nfs_readdir_release_array(page);
-               } else
-                       status = PTR_ERR(array);
+               array = kmap(page);
+               array->eof_index = array->size;
+               status = 0;
+               kunmap(page);
        }
 
        put_page(scratch);
@@ -674,13 +632,8 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page,
                goto out;
        }
 
-       array = nfs_readdir_get_array(page);
-       if (IS_ERR(array)) {
-               status = PTR_ERR(array);
-               goto out_label_free;
-       }
+       array = kmap(page);
        memset(array, 0, sizeof(struct nfs_cache_array));
-       atomic_set(&array->refcount, 1);
        array->eof_index = -1;
 
        status = nfs_readdir_alloc_pages(pages, array_size);
@@ -703,8 +656,7 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page,
 
        nfs_readdir_free_pages(pages, array_size);
 out_release_array:
-       nfs_readdir_release_array(page);
-out_label_free:
+       kunmap(page);
        nfs4_label_free(entry.label);
 out:
        nfs_free_fattr(entry.fattr);
@@ -743,7 +695,8 @@ int nfs_readdir_filler(nfs_readdir_descriptor_t *desc, struct page* page)
 static
 void cache_page_release(nfs_readdir_descriptor_t *desc)
 {
-       nfs_readdir_clear_array(desc->page);
+       if (!desc->page->mapping)
+               nfs_readdir_clear_array(desc->page);
        put_page(desc->page);
        desc->page = NULL;
 }
@@ -751,16 +704,8 @@ void cache_page_release(nfs_readdir_descriptor_t *desc)
 static
 struct page *get_cache_page(nfs_readdir_descriptor_t *desc)
 {
-       struct page *page;
-
-       for (;;) {
-               page = read_cache_page(desc->file->f_mapping,
+       return read_cache_page(desc->file->f_mapping,
                        desc->page_index, (filler_t *)nfs_readdir_filler, desc);
-               if (IS_ERR(page) || grab_page(page))
-                       break;
-               put_page(page);
-       }
-       return page;
 }
 
 /*
@@ -809,12 +754,7 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc)
        struct nfs_cache_array *array = NULL;
        struct nfs_open_dir_context *ctx = file->private_data;
 
-       array = nfs_readdir_get_array(desc->page);
-       if (IS_ERR(array)) {
-               res = PTR_ERR(array);
-               goto out;
-       }
-
+       array = kmap(desc->page);
        for (i = desc->cache_entry_index; i < array->size; i++) {
                struct nfs_cache_array_entry *ent;
 
@@ -835,8 +775,7 @@ int nfs_do_filldir(nfs_readdir_descriptor_t *desc)
        if (array->eof_index >= 0)
                desc->eof = 1;
 
-       nfs_readdir_release_array(desc->page);
-out:
+       kunmap(desc->page);
        cache_page_release(desc);
        dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling ended @ cookie %Lu; returning = %d\n",
                        (unsigned long long)*desc->dir_cookie, res);
@@ -966,11 +905,13 @@ out:
 
 static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int whence)
 {
+       struct inode *inode = file_inode(filp);
        struct nfs_open_dir_context *dir_ctx = filp->private_data;
 
        dfprintk(FILE, "NFS: llseek dir(%pD2, %lld, %d)\n",
                        filp, offset, whence);
 
+       inode_lock(inode);
        switch (whence) {
                case 1:
                        offset += filp->f_pos;
@@ -978,13 +919,16 @@ static loff_t nfs_llseek_dir(struct file *filp, loff_t offset, int whence)
                        if (offset >= 0)
                                break;
                default:
-                       return -EINVAL;
+                       offset = -EINVAL;
+                       goto out;
        }
        if (offset != filp->f_pos) {
                filp->f_pos = offset;
                dir_ctx->dir_cookie = 0;
                dir_ctx->duped = 0;
        }
+out:
+       inode_unlock(inode);
        return offset;
 }
 
index c1b5fed7c863b2b730e46f0139a7b6f9a5f68fa0..6fb9fad2d1e6cf6909cfe6dfb2e482bff969e7df 100644 (file)
@@ -392,16 +392,6 @@ static void nfs_direct_complete(struct nfs_direct_req *dreq)
        nfs_direct_req_release(dreq);
 }
 
-static void nfs_direct_readpage_release(struct nfs_page *req)
-{
-       dprintk("NFS: direct read done (%s/%llu %d@%lld)\n",
-               req->wb_context->dentry->d_sb->s_id,
-               (unsigned long long)NFS_FILEID(d_inode(req->wb_context->dentry)),
-               req->wb_bytes,
-               (long long)req_offset(req));
-       nfs_release_request(req);
-}
-
 static void nfs_direct_read_completion(struct nfs_pgio_header *hdr)
 {
        unsigned long bytes = 0;
@@ -426,7 +416,7 @@ static void nfs_direct_read_completion(struct nfs_pgio_header *hdr)
                        set_page_dirty(page);
                bytes += req->wb_bytes;
                nfs_list_remove_request(req);
-               nfs_direct_readpage_release(req);
+               nfs_release_request(req);
        }
 out_put:
        if (put_dreq(dreq))
@@ -700,16 +690,9 @@ static void nfs_direct_commit_complete(struct nfs_commit_data *data)
        int status = data->task.tk_status;
 
        nfs_init_cinfo_from_dreq(&cinfo, dreq);
-       if (status < 0) {
-               dprintk("NFS: %5u commit failed with error %d.\n",
-                       data->task.tk_pid, status);
-               dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
-       } else if (nfs_direct_cmp_commit_data_verf(dreq, data)) {
-               dprintk("NFS: %5u commit verify failed\n", data->task.tk_pid);
+       if (status < 0 || nfs_direct_cmp_commit_data_verf(dreq, data))
                dreq->flags = NFS_ODIRECT_RESCHED_WRITES;
-       }
 
-       dprintk("NFS: %5u commit returned %d\n", data->task.tk_pid, status);
        while (!list_empty(&data->pages)) {
                req = nfs_list_entry(data->pages.next);
                nfs_list_remove_request(req);
index 668213984d68708c3d54cccce36ad3a0c048657e..5713eb32a45ea20c1de50f2ee28f4ddcae468f67 100644 (file)
@@ -482,7 +482,7 @@ static int nfs_launder_page(struct page *page)
                inode->i_ino, (long long)page_offset(page));
 
        nfs_fscache_wait_on_page_write(nfsi, page);
-       return nfs_wb_launder_page(inode, page);
+       return nfs_wb_page(inode, page);
 }
 
 static int nfs_swap_activate(struct swap_info_struct *sis, struct file *file,
@@ -697,14 +697,14 @@ do_unlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
        if (!IS_ERR(l_ctx)) {
                status = nfs_iocounter_wait(l_ctx);
                nfs_put_lock_context(l_ctx);
-               if (status < 0)
+               /*  NOTE: special case
+                *      If we're signalled while cleaning up locks on process exit, we
+                *      still need to complete the unlock.
+                */
+               if (status < 0 && !(fl->fl_flags & FL_CLOSE))
                        return status;
        }
 
-       /* NOTE: special case
-        *      If we're signalled while cleaning up locks on process exit, we
-        *      still need to complete the unlock.
-        */
        /*
         * Use local locking if mounted with "-onolock" or with appropriate
         * "-olocal_lock="
@@ -820,9 +820,23 @@ int nfs_flock(struct file *filp, int cmd, struct file_lock *fl)
        if (NFS_SERVER(inode)->flags & NFS_MOUNT_LOCAL_FLOCK)
                is_local = 1;
 
-       /* We're simulating flock() locks using posix locks on the server */
-       if (fl->fl_type == F_UNLCK)
+       /*
+        * VFS doesn't require the open mode to match a flock() lock's type.
+        * NFS, however, may simulate flock() locking with posix locking which
+        * requires the open mode to match the lock type.
+        */
+       switch (fl->fl_type) {
+       case F_UNLCK:
                return do_unlk(filp, cmd, fl, is_local);
+       case F_RDLCK:
+               if (!(filp->f_mode & FMODE_READ))
+                       return -EBADF;
+               break;
+       case F_WRLCK:
+               if (!(filp->f_mode & FMODE_WRITE))
+                       return -EBADF;
+       }
+
        return do_setlk(filp, cmd, fl, is_local);
 }
 EXPORT_SYMBOL_GPL(nfs_flock);
index acd30baca46166c902aa5dfae1663184cc30e235..1cf85d65b7489bd56c69447d618360263febc52c 100644 (file)
@@ -921,11 +921,11 @@ fl_pnfs_update_layout(struct inode *ino,
        fl = FILELAYOUT_LSEG(lseg);
 
        status = filelayout_check_deviceid(lo, fl, gfp_flags);
-       if (status)
+       if (status) {
+               pnfs_put_lseg(lseg);
                lseg = ERR_PTR(status);
+       }
 out:
-       if (IS_ERR(lseg))
-               pnfs_put_lseg(lseg);
        return lseg;
 }
 
@@ -933,6 +933,7 @@ static void
 filelayout_pg_init_read(struct nfs_pageio_descriptor *pgio,
                        struct nfs_page *req)
 {
+       pnfs_generic_pg_check_layout(pgio);
        if (!pgio->pg_lseg) {
                pgio->pg_lseg = fl_pnfs_update_layout(pgio->pg_inode,
                                                      req->wb_context,
@@ -959,6 +960,7 @@ filelayout_pg_init_write(struct nfs_pageio_descriptor *pgio,
        struct nfs_commit_info cinfo;
        int status;
 
+       pnfs_generic_pg_check_layout(pgio);
        if (!pgio->pg_lseg) {
                pgio->pg_lseg = fl_pnfs_update_layout(pgio->pg_inode,
                                                      req->wb_context,
index 42dedf2d625fca62a418c5e4f82935dc41a53987..f5714ee01000de49c5efcd3675226a3a3b7a7074 100644 (file)
@@ -846,6 +846,7 @@ ff_layout_pg_init_read(struct nfs_pageio_descriptor *pgio,
        int ds_idx;
 
 retry:
+       pnfs_generic_pg_check_layout(pgio);
        /* Use full layout for now */
        if (!pgio->pg_lseg)
                ff_layout_pg_get_read(pgio, req, false);
@@ -894,6 +895,7 @@ ff_layout_pg_init_write(struct nfs_pageio_descriptor *pgio,
        int status;
 
 retry:
+       pnfs_generic_pg_check_layout(pgio);
        if (!pgio->pg_lseg) {
                pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
                                                   req->wb_context,
@@ -1800,16 +1802,16 @@ ff_layout_write_pagelist(struct nfs_pgio_header *hdr, int sync)
 
        ds = nfs4_ff_layout_prepare_ds(lseg, idx, true);
        if (!ds)
-               return PNFS_NOT_ATTEMPTED;
+               goto out_failed;
 
        ds_clnt = nfs4_ff_find_or_create_ds_client(lseg, idx, ds->ds_clp,
                                                   hdr->inode);
        if (IS_ERR(ds_clnt))
-               return PNFS_NOT_ATTEMPTED;
+               goto out_failed;
 
        ds_cred = ff_layout_get_ds_cred(lseg, idx, hdr->cred);
        if (!ds_cred)
-               return PNFS_NOT_ATTEMPTED;
+               goto out_failed;
 
        vers = nfs4_ff_layout_ds_version(lseg, idx);
 
@@ -1839,6 +1841,11 @@ ff_layout_write_pagelist(struct nfs_pgio_header *hdr, int sync)
                          sync, RPC_TASK_SOFTCONN);
        put_rpccred(ds_cred);
        return PNFS_ATTEMPTED;
+
+out_failed:
+       if (ff_layout_avoid_mds_available_ds(lseg))
+               return PNFS_TRY_AGAIN;
+       return PNFS_NOT_ATTEMPTED;
 }
 
 static u32 calc_ds_index_from_commit(struct pnfs_layout_segment *lseg, u32 i)
@@ -2354,10 +2361,21 @@ ff_layout_prepare_layoutstats(struct nfs42_layoutstat_args *args)
        return 0;
 }
 
+static int
+ff_layout_set_layoutdriver(struct nfs_server *server,
+               const struct nfs_fh *dummy)
+{
+#if IS_ENABLED(CONFIG_NFS_V4_2)
+       server->caps |= NFS_CAP_LAYOUTSTATS;
+#endif
+       return 0;
+}
+
 static struct pnfs_layoutdriver_type flexfilelayout_type = {
        .id                     = LAYOUT_FLEX_FILES,
        .name                   = "LAYOUT_FLEX_FILES",
        .owner                  = THIS_MODULE,
+       .set_layoutdriver       = ff_layout_set_layoutdriver,
        .alloc_layout_hdr       = ff_layout_alloc_layout_hdr,
        .free_layout_hdr        = ff_layout_free_layout_hdr,
        .alloc_lseg             = ff_layout_alloc_lseg,
index 457cfeb1d5c162e4177450eb941460a2fe39f3b1..6df7a0cf566015378aa3f76c480115675454297d 100644 (file)
@@ -119,7 +119,13 @@ nfs4_ff_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev,
                if (ds_versions[i].wsize > NFS_MAX_FILE_IO_SIZE)
                        ds_versions[i].wsize = NFS_MAX_FILE_IO_SIZE;
 
-               if (ds_versions[i].version != 3 || ds_versions[i].minor_version != 0) {
+               /*
+                * check for valid major/minor combination.
+                * currently we support dataserver which talk:
+                *   v3, v4.0, v4.1, v4.2
+                */
+               if (!((ds_versions[i].version == 3 && ds_versions[i].minor_version == 0) ||
+                       (ds_versions[i].version == 4 && ds_versions[i].minor_version < 3))) {
                        dprintk("%s: [%d] unsupported ds version %d-%d\n", __func__,
                                i, ds_versions[i].version,
                                ds_versions[i].minor_version);
@@ -415,7 +421,7 @@ nfs4_ff_layout_prepare_ds(struct pnfs_layout_segment *lseg, u32 ds_idx,
                             mirror->mirror_ds->ds_versions[0].minor_version);
 
        /* connect success, check rsize/wsize limit */
-       if (ds->ds_clp) {
+       if (!status) {
                max_payload =
                        nfs_block_size(rpc_max_payload(ds->ds_clp->cl_rpcclient),
                                       NULL);
index f489a5a71bd5cd89f0667b455e04930753e24e84..1de93ba78dc95a34292cc6160198d9be7c843de1 100644 (file)
@@ -734,7 +734,10 @@ int nfs_getattr(const struct path *path, struct kstat *stat,
        if (need_atime || nfs_need_revalidate_inode(inode)) {
                struct nfs_server *server = NFS_SERVER(inode);
 
-               nfs_readdirplus_parent_cache_miss(path->dentry);
+               if (!(server->flags & NFS_MOUNT_NOAC))
+                       nfs_readdirplus_parent_cache_miss(path->dentry);
+               else
+                       nfs_readdirplus_parent_cache_hit(path->dentry);
                err = __nfs_revalidate_inode(server, inode);
        } else
                nfs_readdirplus_parent_cache_hit(path->dentry);
index 7b38fedb7e032824ec509edca5cf465a22147851..e9b4c3320e371a90020ea25f4be44d2d76508db7 100644 (file)
@@ -495,7 +495,6 @@ void nfs_mark_request_commit(struct nfs_page *req,
                             u32 ds_commit_idx);
 int nfs_write_need_commit(struct nfs_pgio_header *);
 void nfs_writeback_update_inode(struct nfs_pgio_header *hdr);
-int nfs_commit_file(struct file *file, struct nfs_write_verifier *verf);
 int nfs_generic_commit_list(struct inode *inode, struct list_head *head,
                            int how, struct nfs_commit_info *cinfo);
 void nfs_retry_commit(struct list_head *page_list,
@@ -756,9 +755,13 @@ static inline bool nfs_error_is_fatal(int err)
 {
        switch (err) {
        case -ERESTARTSYS:
+       case -EACCES:
+       case -EDQUOT:
+       case -EFBIG:
        case -EIO:
        case -ENOSPC:
        case -EROFS:
+       case -ESTALE:
        case -E2BIG:
                return true;
        default:
index 786f175805827df3a76ef4e37307927f81372628..1a224a33a6c23c362e1bbacb8150bb9bbf02b3fd 100644 (file)
@@ -143,11 +143,8 @@ struct vfsmount *nfs_d_automount(struct path *path)
        struct nfs_fh *fh = NULL;
        struct nfs_fattr *fattr = NULL;
 
-       dprintk("--> nfs_d_automount()\n");
-
-       mnt = ERR_PTR(-ESTALE);
        if (IS_ROOT(path->dentry))
-               goto out_nofree;
+               return ERR_PTR(-ESTALE);
 
        mnt = ERR_PTR(-ENOMEM);
        fh = nfs_alloc_fhandle();
@@ -155,13 +152,10 @@ struct vfsmount *nfs_d_automount(struct path *path)
        if (fh == NULL || fattr == NULL)
                goto out;
 
-       dprintk("%s: enter\n", __func__);
-
        mnt = server->nfs_client->rpc_ops->submount(server, path->dentry, fh, fattr);
        if (IS_ERR(mnt))
                goto out;
 
-       dprintk("%s: done, success\n", __func__);
        mntget(mnt); /* prevent immediate expiration */
        mnt_set_expiry(mnt, &nfs_automount_list);
        schedule_delayed_work(&nfs_automount_task, nfs_mountpoint_expiry_timeout);
@@ -169,11 +163,6 @@ struct vfsmount *nfs_d_automount(struct path *path)
 out:
        nfs_free_fattr(fattr);
        nfs_free_fhandle(fh);
-out_nofree:
-       if (IS_ERR(mnt))
-               dprintk("<-- %s(): error %ld\n", __func__, PTR_ERR(mnt));
-       else
-               dprintk("<-- %s() = %p\n", __func__, mnt);
        return mnt;
 }
 
@@ -248,27 +237,20 @@ struct vfsmount *nfs_do_submount(struct dentry *dentry, struct nfs_fh *fh,
                .fattr = fattr,
                .authflavor = authflavor,
        };
-       struct vfsmount *mnt = ERR_PTR(-ENOMEM);
+       struct vfsmount *mnt;
        char *page = (char *) __get_free_page(GFP_USER);
        char *devname;
 
-       dprintk("--> nfs_do_submount()\n");
-
-       dprintk("%s: submounting on %pd2\n", __func__,
-                       dentry);
        if (page == NULL)
-               goto out;
+               return ERR_PTR(-ENOMEM);
+
        devname = nfs_devname(dentry, page, PAGE_SIZE);
-       mnt = (struct vfsmount *)devname;
        if (IS_ERR(devname))
-               goto free_page;
-       mnt = nfs_do_clone_mount(NFS_SB(dentry->d_sb), devname, &mountdata);
-free_page:
-       free_page((unsigned long)page);
-out:
-       dprintk("%s: done\n", __func__);
+               mnt = (struct vfsmount *)devname;
+       else
+               mnt = nfs_do_clone_mount(NFS_SB(dentry->d_sb), devname, &mountdata);
 
-       dprintk("<-- nfs_do_submount() = %p\n", mnt);
+       free_page((unsigned long)page);
        return mnt;
 }
 EXPORT_SYMBOL_GPL(nfs_do_submount);
index dc925b531f32632bb708c3f8490d0d00c7315495..0c07b567118dcd8a99d924a738c0fe7a0149bf43 100644 (file)
@@ -865,12 +865,63 @@ static void nfs3_proc_commit_setup(struct nfs_commit_data *data, struct rpc_mess
        msg->rpc_proc = &nfs3_procedures[NFS3PROC_COMMIT];
 }
 
+static void nfs3_nlm_alloc_call(void *data)
+{
+       struct nfs_lock_context *l_ctx = data;
+       if (l_ctx && test_bit(NFS_CONTEXT_UNLOCK, &l_ctx->open_context->flags)) {
+               get_nfs_open_context(l_ctx->open_context);
+               nfs_get_lock_context(l_ctx->open_context);
+       }
+}
+
+static bool nfs3_nlm_unlock_prepare(struct rpc_task *task, void *data)
+{
+       struct nfs_lock_context *l_ctx = data;
+       if (l_ctx && test_bit(NFS_CONTEXT_UNLOCK, &l_ctx->open_context->flags))
+               return nfs_async_iocounter_wait(task, l_ctx);
+       return false;
+
+}
+
+static void nfs3_nlm_release_call(void *data)
+{
+       struct nfs_lock_context *l_ctx = data;
+       struct nfs_open_context *ctx;
+       if (l_ctx && test_bit(NFS_CONTEXT_UNLOCK, &l_ctx->open_context->flags)) {
+               ctx = l_ctx->open_context;
+               nfs_put_lock_context(l_ctx);
+               put_nfs_open_context(ctx);
+       }
+}
+
+const struct nlmclnt_operations nlmclnt_fl_close_lock_ops = {
+       .nlmclnt_alloc_call = nfs3_nlm_alloc_call,
+       .nlmclnt_unlock_prepare = nfs3_nlm_unlock_prepare,
+       .nlmclnt_release_call = nfs3_nlm_release_call,
+};
+
 static int
 nfs3_proc_lock(struct file *filp, int cmd, struct file_lock *fl)
 {
        struct inode *inode = file_inode(filp);
+       struct nfs_lock_context *l_ctx = NULL;
+       struct nfs_open_context *ctx = nfs_file_open_context(filp);
+       int status;
 
-       return nlmclnt_proc(NFS_SERVER(inode)->nlm_host, cmd, fl);
+       if (fl->fl_flags & FL_CLOSE) {
+               l_ctx = nfs_get_lock_context(ctx);
+               if (IS_ERR(l_ctx))
+                       l_ctx = NULL;
+               else
+                       set_bit(NFS_CONTEXT_UNLOCK, &ctx->flags);
+       }
+
+       status = nlmclnt_proc(NFS_SERVER(inode)->nlm_host, cmd, fl, l_ctx);
+
+       if (l_ctx)
+               nfs_put_lock_context(l_ctx);
+
+       return status;
 }
 
 static int nfs3_have_delegation(struct inode *inode, fmode_t flags)
@@ -921,6 +972,7 @@ const struct nfs_rpc_ops nfs_v3_clientops = {
        .dir_inode_ops  = &nfs3_dir_inode_operations,
        .file_inode_ops = &nfs3_file_inode_operations,
        .file_ops       = &nfs_file_operations,
+       .nlmclnt_ops    = &nlmclnt_fl_close_lock_ops,
        .getroot        = nfs3_proc_get_root,
        .submount       = nfs_submount,
        .try_mount      = nfs_try_mount,
index 1e486c73ec9438d99e2e4a5b6637ec64594b626c..929d09a5310ad7df79be527a45a9aa524825b7f0 100644 (file)
@@ -167,23 +167,29 @@ static ssize_t _nfs42_proc_copy(struct file *src,
        if (status)
                return status;
 
+       res->commit_res.verf = kzalloc(sizeof(struct nfs_writeverf), GFP_NOFS);
+       if (!res->commit_res.verf)
+               return -ENOMEM;
        status = nfs4_call_sync(server->client, server, &msg,
                                &args->seq_args, &res->seq_res, 0);
        if (status == -ENOTSUPP)
                server->caps &= ~NFS_CAP_COPY;
        if (status)
-               return status;
+               goto out;
 
-       if (res->write_res.verifier.committed != NFS_FILE_SYNC) {
-               status = nfs_commit_file(dst, &res->write_res.verifier.verifier);
-               if (status)
-                       return status;
+       if (!nfs_write_verifier_cmp(&res->write_res.verifier.verifier,
+                                   &res->commit_res.verf->verifier)) {
+               status = -EAGAIN;
+               goto out;
        }
 
        truncate_pagecache_range(dst_inode, pos_dst,
                                 pos_dst + res->write_res.count);
 
-       return res->write_res.count;
+       status = res->write_res.count;
+out:
+       kfree(res->commit_res.verf);
+       return status;
 }
 
 ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
@@ -240,6 +246,9 @@ ssize_t nfs42_proc_copy(struct file *src, loff_t pos_src,
                if (err == -ENOTSUPP) {
                        err = -EOPNOTSUPP;
                        break;
+               } if (err == -EAGAIN) {
+                       dst_exception.retry = 1;
+                       continue;
                }
 
                err2 = nfs4_handle_exception(server, err, &src_exception);
@@ -379,6 +388,7 @@ nfs42_layoutstat_done(struct rpc_task *task, void *calldata)
                        pnfs_mark_layout_stateid_invalid(lo, &head);
                        spin_unlock(&inode->i_lock);
                        pnfs_free_lseg_list(&head);
+                       nfs_commit_inode(inode, 0);
                } else
                        spin_unlock(&inode->i_lock);
                break;
@@ -400,8 +410,6 @@ nfs42_layoutstat_done(struct rpc_task *task, void *calldata)
        case -EOPNOTSUPP:
                NFS_SERVER(inode)->caps &= ~NFS_CAP_LAYOUTSTATS;
        }
-
-       dprintk("%s server returns %d\n", __func__, task->tk_status);
 }
 
 static void
index 6c7296454bbc05c3ab1c18dd178314603916e40a..528362f69cc1ba6156102b113fdd5ba18c566c71 100644 (file)
                                         encode_putfh_maxsz + \
                                         encode_savefh_maxsz + \
                                         encode_putfh_maxsz + \
-                                        encode_copy_maxsz)
+                                        encode_copy_maxsz + \
+                                        encode_commit_maxsz)
 #define NFS4_dec_copy_sz               (compound_decode_hdr_maxsz + \
                                         decode_putfh_maxsz + \
                                         decode_savefh_maxsz + \
                                         decode_putfh_maxsz + \
-                                        decode_copy_maxsz)
+                                        decode_copy_maxsz + \
+                                        decode_commit_maxsz)
 #define NFS4_enc_deallocate_sz         (compound_encode_hdr_maxsz + \
                                         encode_putfh_maxsz + \
                                         encode_deallocate_maxsz + \
@@ -222,6 +224,18 @@ static void nfs4_xdr_enc_allocate(struct rpc_rqst *req,
        encode_nops(&hdr);
 }
 
+static void encode_copy_commit(struct xdr_stream *xdr,
+                         struct nfs42_copy_args *args,
+                         struct compound_hdr *hdr)
+{
+       __be32 *p;
+
+       encode_op_hdr(xdr, OP_COMMIT, decode_commit_maxsz, hdr);
+       p = reserve_space(xdr, 12);
+       p = xdr_encode_hyper(p, args->dst_pos);
+       *p = cpu_to_be32(args->count);
+}
+
 /*
  * Encode COPY request
  */
@@ -239,6 +253,7 @@ static void nfs4_xdr_enc_copy(struct rpc_rqst *req,
        encode_savefh(xdr, &hdr);
        encode_putfh(xdr, args->dst_fh, &hdr);
        encode_copy(xdr, args, &hdr);
+       encode_copy_commit(xdr, args, &hdr);
        encode_nops(&hdr);
 }
 
@@ -481,6 +496,9 @@ static int nfs4_xdr_dec_copy(struct rpc_rqst *rqstp,
        if (status)
                goto out;
        status = decode_copy(xdr, res);
+       if (status)
+               goto out;
+       status = decode_commit(xdr, &res->commit_res);
 out:
        return status;
 }
index 8346ccbf2d52e518b6fa61d0c8cbb3d033ec1f02..692a7a8bfc7afd05ad40d6e04a4a53db07e01753 100644 (file)
@@ -359,11 +359,9 @@ struct nfs_client *nfs4_init_client(struct nfs_client *clp,
        struct nfs_client *old;
        int error;
 
-       if (clp->cl_cons_state == NFS_CS_READY) {
+       if (clp->cl_cons_state == NFS_CS_READY)
                /* the client is initialised already */
-               dprintk("<-- nfs4_init_client() = 0 [already %p]\n", clp);
                return clp;
-       }
 
        /* Check NFS protocol revision and initialize RPC op vector */
        clp->rpc_ops = &nfs_v4_clientops;
@@ -421,7 +419,6 @@ struct nfs_client *nfs4_init_client(struct nfs_client *clp,
 error:
        nfs_mark_client_ready(clp, error);
        nfs_put_client(clp);
-       dprintk("<-- nfs4_init_client() = xerror %d\n", error);
        return ERR_PTR(error);
 }
 
@@ -469,6 +466,50 @@ static bool nfs4_same_verifier(nfs4_verifier *v1, nfs4_verifier *v2)
        return memcmp(v1->data, v2->data, sizeof(v1->data)) == 0;
 }
 
+static int nfs4_match_client(struct nfs_client  *pos,  struct nfs_client *new,
+                            struct nfs_client **prev, struct nfs_net *nn)
+{
+       int status;
+
+       if (pos->rpc_ops != new->rpc_ops)
+               return 1;
+
+       if (pos->cl_minorversion != new->cl_minorversion)
+               return 1;
+
+       /* If "pos" isn't marked ready, we can't trust the
+        * remaining fields in "pos", especially the client
+        * ID and serverowner fields.  Wait for CREATE_SESSION
+        * to finish. */
+       if (pos->cl_cons_state > NFS_CS_READY) {
+               atomic_inc(&pos->cl_count);
+               spin_unlock(&nn->nfs_client_lock);
+
+               nfs_put_client(*prev);
+               *prev = pos;
+
+               status = nfs_wait_client_init_complete(pos);
+               spin_lock(&nn->nfs_client_lock);
+
+               if (status < 0)
+                       return status;
+       }
+
+       if (pos->cl_cons_state != NFS_CS_READY)
+               return 1;
+
+       if (pos->cl_clientid != new->cl_clientid)
+               return 1;
+
+       /* NFSv4.1 always uses the uniform string, however someone
+        * might switch the uniquifier string on us.
+        */
+       if (!nfs4_match_client_owner_id(pos, new))
+               return 1;
+
+       return 0;
+}
+
 /**
  * nfs40_walk_client_list - Find server that recognizes a client ID
  *
@@ -497,34 +538,10 @@ int nfs40_walk_client_list(struct nfs_client *new,
        spin_lock(&nn->nfs_client_lock);
        list_for_each_entry(pos, &nn->nfs_client_list, cl_share_link) {
 
-               if (pos->rpc_ops != new->rpc_ops)
-                       continue;
-
-               if (pos->cl_minorversion != new->cl_minorversion)
-                       continue;
-
-               /* If "pos" isn't marked ready, we can't trust the
-                * remaining fields in "pos" */
-               if (pos->cl_cons_state > NFS_CS_READY) {
-                       atomic_inc(&pos->cl_count);
-                       spin_unlock(&nn->nfs_client_lock);
-
-                       nfs_put_client(prev);
-                       prev = pos;
-
-                       status = nfs_wait_client_init_complete(pos);
-                       if (status < 0)
-                               goto out;
-                       status = -NFS4ERR_STALE_CLIENTID;
-                       spin_lock(&nn->nfs_client_lock);
-               }
-               if (pos->cl_cons_state != NFS_CS_READY)
-                       continue;
-
-               if (pos->cl_clientid != new->cl_clientid)
-                       continue;
-
-               if (!nfs4_match_client_owner_id(pos, new))
+               status = nfs4_match_client(pos, new, &prev, nn);
+               if (status < 0)
+                       goto out_unlock;
+               if (status != 0)
                        continue;
                /*
                 * We just sent a new SETCLIENTID, which should have
@@ -557,8 +574,6 @@ int nfs40_walk_client_list(struct nfs_client *new,
 
                        prev = NULL;
                        *result = pos;
-                       dprintk("NFS: <-- %s using nfs_client = %p ({%d})\n",
-                               __func__, pos, atomic_read(&pos->cl_count));
                        goto out;
                case -ERESTARTSYS:
                case -ETIMEDOUT:
@@ -567,36 +582,22 @@ int nfs40_walk_client_list(struct nfs_client *new,
                         */
                        nfs4_schedule_path_down_recovery(pos);
                default:
+                       spin_lock(&nn->nfs_client_lock);
                        goto out;
                }
 
                spin_lock(&nn->nfs_client_lock);
        }
+out_unlock:
        spin_unlock(&nn->nfs_client_lock);
 
        /* No match found. The server lost our clientid */
 out:
        nfs_put_client(prev);
-       dprintk("NFS: <-- %s status = %d\n", __func__, status);
        return status;
 }
 
 #ifdef CONFIG_NFS_V4_1
-/*
- * Returns true if the client IDs match
- */
-static bool nfs4_match_clientids(u64 a, u64 b)
-{
-       if (a != b) {
-               dprintk("NFS: --> %s client ID %llx does not match %llx\n",
-                       __func__, a, b);
-               return false;
-       }
-       dprintk("NFS: --> %s client ID %llx matches %llx\n",
-               __func__, a, b);
-       return true;
-}
-
 /*
  * Returns true if the server major ids match
  */
@@ -605,36 +606,8 @@ nfs4_check_serverowner_major_id(struct nfs41_server_owner *o1,
                                struct nfs41_server_owner *o2)
 {
        if (o1->major_id_sz != o2->major_id_sz)
-               goto out_major_mismatch;
-       if (memcmp(o1->major_id, o2->major_id, o1->major_id_sz) != 0)
-               goto out_major_mismatch;
-
-       dprintk("NFS: --> %s server owner major IDs match\n", __func__);
-       return true;
-
-out_major_mismatch:
-       dprintk("NFS: --> %s server owner major IDs do not match\n",
-               __func__);
-       return false;
-}
-
-/*
- * Returns true if server minor ids match
- */
-static bool
-nfs4_check_serverowner_minor_id(struct nfs41_server_owner *o1,
-                               struct nfs41_server_owner *o2)
-{
-       /* Check eir_server_owner so_minor_id */
-       if (o1->minor_id != o2->minor_id)
-               goto out_minor_mismatch;
-
-       dprintk("NFS: --> %s server owner minor IDs match\n", __func__);
-       return true;
-
-out_minor_mismatch:
-       dprintk("NFS: --> %s server owner minor IDs do not match\n", __func__);
-       return false;
+               return false;
+       return memcmp(o1->major_id, o2->major_id, o1->major_id_sz) == 0;
 }
 
 /*
@@ -645,18 +618,9 @@ nfs4_check_server_scope(struct nfs41_server_scope *s1,
                        struct nfs41_server_scope *s2)
 {
        if (s1->server_scope_sz != s2->server_scope_sz)
-               goto out_scope_mismatch;
-       if (memcmp(s1->server_scope, s2->server_scope,
-                  s1->server_scope_sz) != 0)
-               goto out_scope_mismatch;
-
-       dprintk("NFS: --> %s server scopes match\n", __func__);
-       return true;
-
-out_scope_mismatch:
-       dprintk("NFS: --> %s server scopes do not match\n",
-               __func__);
-       return false;
+               return false;
+       return memcmp(s1->server_scope, s2->server_scope,
+                                       s1->server_scope_sz) == 0;
 }
 
 /**
@@ -680,7 +644,7 @@ int nfs4_detect_session_trunking(struct nfs_client *clp,
                                 struct rpc_xprt *xprt)
 {
        /* Check eir_clientid */
-       if (!nfs4_match_clientids(clp->cl_clientid, res->clientid))
+       if (clp->cl_clientid != res->clientid)
                goto out_err;
 
        /* Check eir_server_owner so_major_id */
@@ -689,8 +653,7 @@ int nfs4_detect_session_trunking(struct nfs_client *clp,
                goto out_err;
 
        /* Check eir_server_owner so_minor_id */
-       if (!nfs4_check_serverowner_minor_id(clp->cl_serverowner,
-                                            res->server_owner))
+       if (clp->cl_serverowner->minor_id != res->server_owner->minor_id)
                goto out_err;
 
        /* Check eir_server_scope */
@@ -739,33 +702,10 @@ int nfs41_walk_client_list(struct nfs_client *new,
                if (pos == new)
                        goto found;
 
-               if (pos->rpc_ops != new->rpc_ops)
-                       continue;
-
-               if (pos->cl_minorversion != new->cl_minorversion)
-                       continue;
-
-               /* If "pos" isn't marked ready, we can't trust the
-                * remaining fields in "pos", especially the client
-                * ID and serverowner fields.  Wait for CREATE_SESSION
-                * to finish. */
-               if (pos->cl_cons_state > NFS_CS_READY) {
-                       atomic_inc(&pos->cl_count);
-                       spin_unlock(&nn->nfs_client_lock);
-
-                       nfs_put_client(prev);
-                       prev = pos;
-
-                       status = nfs_wait_client_init_complete(pos);
-                       spin_lock(&nn->nfs_client_lock);
-                       if (status < 0)
-                               break;
-                       status = -NFS4ERR_STALE_CLIENTID;
-               }
-               if (pos->cl_cons_state != NFS_CS_READY)
-                       continue;
-
-               if (!nfs4_match_clientids(pos->cl_clientid, new->cl_clientid))
+               status = nfs4_match_client(pos, new, &prev, nn);
+               if (status < 0)
+                       goto out;
+               if (status != 0)
                        continue;
 
                /*
@@ -777,23 +717,15 @@ int nfs41_walk_client_list(struct nfs_client *new,
                                                     new->cl_serverowner))
                        continue;
 
-               /* Unlike NFSv4.0, we know that NFSv4.1 always uses the
-                * uniform string, however someone might switch the
-                * uniquifier string on us.
-                */
-               if (!nfs4_match_client_owner_id(pos, new))
-                       continue;
 found:
                atomic_inc(&pos->cl_count);
                *result = pos;
                status = 0;
-               dprintk("NFS: <-- %s using nfs_client = %p ({%d})\n",
-                       __func__, pos, atomic_read(&pos->cl_count));
                break;
        }
 
+out:
        spin_unlock(&nn->nfs_client_lock);
-       dprintk("NFS: <-- %s status = %d\n", __func__, status);
        nfs_put_client(prev);
        return status;
 }
@@ -916,9 +848,6 @@ static int nfs4_set_client(struct nfs_server *server,
                .timeparms = timeparms,
        };
        struct nfs_client *clp;
-       int error;
-
-       dprintk("--> nfs4_set_client()\n");
 
        if (server->flags & NFS_MOUNT_NORESVPORT)
                set_bit(NFS_CS_NORESVPORT, &cl_init.init_flags);
@@ -927,15 +856,11 @@ static int nfs4_set_client(struct nfs_server *server,
 
        /* Allocate or find a client reference we can use */
        clp = nfs_get_client(&cl_init);
-       if (IS_ERR(clp)) {
-               error = PTR_ERR(clp);
-               goto error;
-       }
+       if (IS_ERR(clp))
+               return PTR_ERR(clp);
 
-       if (server->nfs_client == clp) {
-               error = -ELOOP;
-               goto error;
-       }
+       if (server->nfs_client == clp)
+               return -ELOOP;
 
        /*
         * Query for the lease time on clientid setup or renewal
@@ -947,11 +872,7 @@ static int nfs4_set_client(struct nfs_server *server,
        set_bit(NFS_CS_CHECK_LEASE_TIME, &clp->cl_res_state);
 
        server->nfs_client = clp;
-       dprintk("<-- nfs4_set_client() = 0 [new %p]\n", clp);
        return 0;
-error:
-       dprintk("<-- nfs4_set_client() = xerror %d\n", error);
-       return error;
 }
 
 /*
@@ -982,7 +903,6 @@ struct nfs_client *nfs4_set_ds_client(struct nfs_server *mds_srv,
                .net = mds_clp->cl_net,
                .timeparms = &ds_timeout,
        };
-       struct nfs_client *clp;
        char buf[INET6_ADDRSTRLEN + 1];
 
        if (rpc_ntop(ds_addr, buf, sizeof(buf)) <= 0)
@@ -998,10 +918,7 @@ struct nfs_client *nfs4_set_ds_client(struct nfs_server *mds_srv,
         * (section 13.1 RFC 5661).
         */
        nfs_init_timeout_values(&ds_timeout, ds_proto, ds_timeo, ds_retrans);
-       clp = nfs_get_client(&cl_init);
-
-       dprintk("<-- %s %p\n", __func__, clp);
-       return clp;
+       return nfs_get_client(&cl_init);
 }
 EXPORT_SYMBOL_GPL(nfs4_set_ds_client);
 
@@ -1098,8 +1015,6 @@ static int nfs4_init_server(struct nfs_server *server,
        struct rpc_timeout timeparms;
        int error;
 
-       dprintk("--> nfs4_init_server()\n");
-
        nfs_init_timeout_values(&timeparms, data->nfs_server.protocol,
                        data->timeo, data->retrans);
 
@@ -1127,7 +1042,7 @@ static int nfs4_init_server(struct nfs_server *server,
                        data->minorversion,
                        data->net);
        if (error < 0)
-               goto error;
+               return error;
 
        if (data->rsize)
                server->rsize = nfs_block_size(data->rsize, NULL);
@@ -1138,16 +1053,10 @@ static int nfs4_init_server(struct nfs_server *server,
        server->acregmax = data->acregmax * HZ;
        server->acdirmin = data->acdirmin * HZ;
        server->acdirmax = data->acdirmax * HZ;
+       server->port     = data->nfs_server.port;
 
-       server->port = data->nfs_server.port;
-
-       error = nfs_init_server_rpcclient(server, &timeparms,
-                                         data->selected_flavor);
-
-error:
-       /* Done */
-       dprintk("<-- nfs4_init_server() = %d\n", error);
-       return error;
+       return nfs_init_server_rpcclient(server, &timeparms,
+                                        data->selected_flavor);
 }
 
 /*
@@ -1163,8 +1072,6 @@ struct nfs_server *nfs4_create_server(struct nfs_mount_info *mount_info,
        bool auth_probe;
        int error;
 
-       dprintk("--> nfs4_create_server()\n");
-
        server = nfs_alloc_server();
        if (!server)
                return ERR_PTR(-ENOMEM);
@@ -1180,12 +1087,10 @@ struct nfs_server *nfs4_create_server(struct nfs_mount_info *mount_info,
        if (error < 0)
                goto error;
 
-       dprintk("<-- nfs4_create_server() = %p\n", server);
        return server;
 
 error:
        nfs_free_server(server);
-       dprintk("<-- nfs4_create_server() = error %d\n", error);
        return ERR_PTR(error);
 }
 
@@ -1200,8 +1105,6 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
        bool auth_probe;
        int error;
 
-       dprintk("--> nfs4_create_referral_server()\n");
-
        server = nfs_alloc_server();
        if (!server)
                return ERR_PTR(-ENOMEM);
@@ -1235,12 +1138,10 @@ struct nfs_server *nfs4_create_referral_server(struct nfs_clone_mount *data,
        if (error < 0)
                goto error;
 
-       dprintk("<-- nfs_create_referral_server() = %p\n", server);
        return server;
 
 error:
        nfs_free_server(server);
-       dprintk("<-- nfs4_create_referral_server() = error %d\n", error);
        return ERR_PTR(error);
 }
 
@@ -1300,31 +1201,16 @@ int nfs4_update_server(struct nfs_server *server, const char *hostname,
        struct sockaddr *localaddr = (struct sockaddr *)&address;
        int error;
 
-       dprintk("--> %s: move FSID %llx:%llx to \"%s\")\n", __func__,
-                       (unsigned long long)server->fsid.major,
-                       (unsigned long long)server->fsid.minor,
-                       hostname);
-
        error = rpc_switch_client_transport(clnt, &xargs, clnt->cl_timeout);
-       if (error != 0) {
-               dprintk("<-- %s(): rpc_switch_client_transport returned %d\n",
-                       __func__, error);
-               goto out;
-       }
+       if (error != 0)
+               return error;
 
        error = rpc_localaddr(clnt, localaddr, sizeof(address));
-       if (error != 0) {
-               dprintk("<-- %s(): rpc_localaddr returned %d\n",
-                       __func__, error);
-               goto out;
-       }
+       if (error != 0)
+               return error;
 
-       error = -EAFNOSUPPORT;
-       if (rpc_ntop(localaddr, buf, sizeof(buf)) == 0) {
-               dprintk("<-- %s(): rpc_ntop returned %d\n",
-                       __func__, error);
-               goto out;
-       }
+       if (rpc_ntop(localaddr, buf, sizeof(buf)) == 0)
+               return -EAFNOSUPPORT;
 
        nfs_server_remove_lists(server);
        error = nfs4_set_client(server, hostname, sap, salen, buf,
@@ -1333,21 +1219,12 @@ int nfs4_update_server(struct nfs_server *server, const char *hostname,
        nfs_put_client(clp);
        if (error != 0) {
                nfs_server_insert_lists(server);
-               dprintk("<-- %s(): nfs4_set_client returned %d\n",
-                       __func__, error);
-               goto out;
+               return error;
        }
 
        if (server->nfs_client->cl_hostname == NULL)
                server->nfs_client->cl_hostname = kstrdup(hostname, GFP_KERNEL);
        nfs_server_insert_lists(server);
 
-       error = nfs_probe_destination(server);
-       if (error < 0)
-               goto out;
-
-       dprintk("<-- %s() succeeded\n", __func__);
-
-out:
-       return error;
+       return nfs_probe_destination(server);
 }
index 039b3eb6d83404f33224961465406d52203ff570..ac84060189626ccb07f24b366594d36372717cbb 100644 (file)
@@ -14,8 +14,6 @@ int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh, bool auth_p
        struct nfs_fsinfo fsinfo;
        int ret = -ENOMEM;
 
-       dprintk("--> nfs4_get_rootfh()\n");
-
        fsinfo.fattr = nfs_alloc_fattr();
        if (fsinfo.fattr == NULL)
                goto out;
@@ -38,6 +36,5 @@ int nfs4_get_rootfh(struct nfs_server *server, struct nfs_fh *mntfh, bool auth_p
        memcpy(&server->fsid, &fsinfo.fattr->fsid, sizeof(server->fsid));
 out:
        nfs_free_fattr(fsinfo.fattr);
-       dprintk("<-- nfs4_get_rootfh() = %d\n", ret);
        return ret;
 }
index d8b040bd9814d3199e9189519f7bdcb09c04801c..7d531da1bae37e1cd957c3181423930e1033ab8b 100644 (file)
@@ -340,7 +340,6 @@ static struct vfsmount *nfs_follow_referral(struct dentry *dentry,
 out:
        free_page((unsigned long) page);
        free_page((unsigned long) page2);
-       dprintk("%s: done\n", __func__);
        return mnt;
 }
 
@@ -358,11 +357,9 @@ static struct vfsmount *nfs_do_refmount(struct rpc_clnt *client, struct dentry *
        int err;
 
        /* BUG_ON(IS_ROOT(dentry)); */
-       dprintk("%s: enter\n", __func__);
-
        page = alloc_page(GFP_KERNEL);
        if (page == NULL)
-               goto out;
+               return mnt;
 
        fs_locations = kmalloc(sizeof(struct nfs4_fs_locations), GFP_KERNEL);
        if (fs_locations == NULL)
@@ -386,8 +383,6 @@ static struct vfsmount *nfs_do_refmount(struct rpc_clnt *client, struct dentry *
 out_free:
        __free_page(page);
        kfree(fs_locations);
-out:
-       dprintk("%s: done\n", __func__);
        return mnt;
 }
 
index 201ca3f2c4bac14986220fcdf6a6c37b734ffa96..c08c46a3b8cde00ef5aa40fae87ed2fce06faea1 100644 (file)
@@ -698,7 +698,8 @@ static int nfs41_sequence_process(struct rpc_task *task,
        session = slot->table->session;
 
        if (slot->interrupted) {
-               slot->interrupted = 0;
+               if (res->sr_status != -NFS4ERR_DELAY)
+                       slot->interrupted = 0;
                interrupted = true;
        }
 
@@ -2300,8 +2301,10 @@ static int _nfs4_proc_open(struct nfs4_opendata *data)
                if (status != 0)
                        return status;
        }
-       if (!(o_res->f_attr->valid & NFS_ATTR_FATTR))
+       if (!(o_res->f_attr->valid & NFS_ATTR_FATTR)) {
+               nfs4_sequence_free_slot(&o_res->seq_res);
                nfs4_proc_getattr(server, &o_res->fh, o_res->f_attr, o_res->f_label);
+       }
        return 0;
 }
 
@@ -3265,6 +3268,7 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f
                .rpc_resp = &res,
        };
        int status;
+       int i;
 
        bitmask[0] = FATTR4_WORD0_SUPPORTED_ATTRS |
                     FATTR4_WORD0_FH_EXPIRE_TYPE |
@@ -3330,8 +3334,13 @@ static int _nfs4_server_capabilities(struct nfs_server *server, struct nfs_fh *f
                server->cache_consistency_bitmask[0] &= FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE;
                server->cache_consistency_bitmask[1] &= FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY;
                server->cache_consistency_bitmask[2] = 0;
+
+               /* Avoid a regression due to buggy server */
+               for (i = 0; i < ARRAY_SIZE(res.exclcreat_bitmask); i++)
+                       res.exclcreat_bitmask[i] &= res.attr_bitmask[i];
                memcpy(server->exclcreat_bitmask, res.exclcreat_bitmask,
                        sizeof(server->exclcreat_bitmask));
+
                server->acl_bitmask = res.acl_bitmask;
                server->fh_expire_type = res.fh_expire_type;
        }
@@ -4610,7 +4619,7 @@ static int nfs4_proc_pgio_rpc_prepare(struct rpc_task *task,
                return 0;
        if (nfs4_set_rw_stateid(&hdr->args.stateid, hdr->args.context,
                                hdr->args.lock_context,
-                               hdr->rw_ops->rw_mode) == -EIO)
+                               hdr->rw_mode) == -EIO)
                return -EIO;
        if (unlikely(test_bit(NFS_CONTEXT_BAD, &hdr->args.context->flags)))
                return -EIO;
@@ -4804,8 +4813,10 @@ static int nfs4_proc_async_renew(struct nfs_client *clp, struct rpc_cred *cred,
        if (!atomic_inc_not_zero(&clp->cl_count))
                return -EIO;
        data = kmalloc(sizeof(*data), GFP_NOFS);
-       if (data == NULL)
+       if (data == NULL) {
+               nfs_put_client(clp);
                return -ENOMEM;
+       }
        data->client = clp;
        data->timestamp = jiffies;
        return rpc_call_async(clp->cl_rpcclient, &msg, RPC_TASK_TIMEOUT,
@@ -5782,6 +5793,7 @@ struct nfs4_unlockdata {
        struct nfs_locku_res res;
        struct nfs4_lock_state *lsp;
        struct nfs_open_context *ctx;
+       struct nfs_lock_context *l_ctx;
        struct file_lock fl;
        struct nfs_server *server;
        unsigned long timestamp;
@@ -5806,6 +5818,7 @@ static struct nfs4_unlockdata *nfs4_alloc_unlockdata(struct file_lock *fl,
        atomic_inc(&lsp->ls_count);
        /* Ensure we don't close file until we're done freeing locks! */
        p->ctx = get_nfs_open_context(ctx);
+       p->l_ctx = nfs_get_lock_context(ctx);
        memcpy(&p->fl, fl, sizeof(p->fl));
        p->server = NFS_SERVER(inode);
        return p;
@@ -5816,6 +5829,7 @@ static void nfs4_locku_release_calldata(void *data)
        struct nfs4_unlockdata *calldata = data;
        nfs_free_seqid(calldata->arg.seqid);
        nfs4_put_lock_state(calldata->lsp);
+       nfs_put_lock_context(calldata->l_ctx);
        put_nfs_open_context(calldata->ctx);
        kfree(calldata);
 }
@@ -5857,6 +5871,10 @@ static void nfs4_locku_prepare(struct rpc_task *task, void *data)
 {
        struct nfs4_unlockdata *calldata = data;
 
+       if (test_bit(NFS_CONTEXT_UNLOCK, &calldata->l_ctx->open_context->flags) &&
+               nfs_async_iocounter_wait(task, calldata->l_ctx))
+               return;
+
        if (nfs_wait_on_sequence(calldata->arg.seqid, task) != 0)
                goto out_wait;
        nfs4_stateid_copy(&calldata->arg.stateid, &calldata->lsp->ls_stateid);
@@ -5908,6 +5926,8 @@ static struct rpc_task *nfs4_do_unlck(struct file_lock *fl,
         * canceled lock is passed in, and it won't be an unlock.
         */
        fl->fl_type = F_UNLCK;
+       if (fl->fl_flags & FL_CLOSE)
+               set_bit(NFS_CONTEXT_UNLOCK, &ctx->flags);
 
        data = nfs4_alloc_unlockdata(fl, ctx, lsp, seqid);
        if (data == NULL) {
@@ -6445,9 +6465,6 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request)
        ctx = nfs_file_open_context(filp);
        state = ctx->state;
 
-       if (request->fl_start < 0 || request->fl_end < 0)
-               return -EINVAL;
-
        if (IS_GETLK(cmd)) {
                if (state != NULL)
                        return nfs4_proc_getlk(state, F_GETLK, request);
@@ -6470,20 +6487,6 @@ nfs4_proc_lock(struct file *filp, int cmd, struct file_lock *request)
            !test_bit(NFS_STATE_POSIX_LOCKS, &state->flags))
                return -ENOLCK;
 
-       /*
-        * Don't rely on the VFS having checked the file open mode,
-        * since it won't do this for flock() locks.
-        */
-       switch (request->fl_type) {
-       case F_RDLCK:
-               if (!(filp->f_mode & FMODE_READ))
-                       return -EBADF;
-               break;
-       case F_WRLCK:
-               if (!(filp->f_mode & FMODE_WRITE))
-                       return -EBADF;
-       }
-
        status = nfs4_set_lock_state(state, request);
        if (status != 0)
                return status;
@@ -7155,8 +7158,6 @@ int nfs4_proc_bind_one_conn_to_session(struct rpc_clnt *clnt,
        };
        struct rpc_task *task;
 
-       dprintk("--> %s\n", __func__);
-
        nfs4_copy_sessionid(&args.sessionid, &clp->cl_session->sess_id);
        if (!(clp->cl_session->flags & SESSION4_BACK_CHAN))
                args.dir = NFS4_CDFC4_FORE;
@@ -7176,24 +7177,20 @@ int nfs4_proc_bind_one_conn_to_session(struct rpc_clnt *clnt,
                if (memcmp(res.sessionid.data,
                    clp->cl_session->sess_id.data, NFS4_MAX_SESSIONID_LEN)) {
                        dprintk("NFS: %s: Session ID mismatch\n", __func__);
-                       status = -EIO;
-                       goto out;
+                       return -EIO;
                }
                if ((res.dir & args.dir) != res.dir || res.dir == 0) {
                        dprintk("NFS: %s: Unexpected direction from server\n",
                                __func__);
-                       status = -EIO;
-                       goto out;
+                       return -EIO;
                }
                if (res.use_conn_in_rdma_mode != args.use_conn_in_rdma_mode) {
                        dprintk("NFS: %s: Server returned RDMA mode = true\n",
                                __func__);
-                       status = -EIO;
-                       goto out;
+                       return -EIO;
                }
        }
-out:
-       dprintk("<-- %s status= %d\n", __func__, status);
+
        return status;
 }
 
@@ -7459,15 +7456,16 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
        };
        struct nfs41_exchange_id_data *calldata;
        struct rpc_task *task;
-       int status = -EIO;
+       int status;
 
        if (!atomic_inc_not_zero(&clp->cl_count))
-               goto out;
+               return -EIO;
 
-       status = -ENOMEM;
        calldata = kzalloc(sizeof(*calldata), GFP_NOFS);
-       if (!calldata)
-               goto out;
+       if (!calldata) {
+               nfs_put_client(clp);
+               return -ENOMEM;
+       }
 
        if (!xprt)
                nfs4_init_boot_verifier(clp, &verifier);
@@ -7476,10 +7474,6 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
        if (status)
                goto out_calldata;
 
-       dprintk("NFS call  exchange_id auth=%s, '%s'\n",
-               clp->cl_rpcclient->cl_auth->au_ops->au_name,
-               clp->cl_owner_id);
-
        calldata->res.server_owner = kzalloc(sizeof(struct nfs41_server_owner),
                                                GFP_NOFS);
        status = -ENOMEM;
@@ -7545,13 +7539,6 @@ static int _nfs4_proc_exchange_id(struct nfs_client *clp, struct rpc_cred *cred,
 
        rpc_put_task(task);
 out:
-       if (clp->cl_implid != NULL)
-               dprintk("NFS reply exchange_id: Server Implementation ID: "
-                       "domain: %s, name: %s, date: %llu,%u\n",
-                       clp->cl_implid->domain, clp->cl_implid->name,
-                       clp->cl_implid->date.seconds,
-                       clp->cl_implid->date.nseconds);
-       dprintk("NFS reply exchange_id: %d\n", status);
        return status;
 
 out_impl_id:
@@ -7769,17 +7756,13 @@ int nfs4_proc_get_lease_time(struct nfs_client *clp, struct nfs_fsinfo *fsinfo)
 
        nfs4_init_sequence(&args.la_seq_args, &res.lr_seq_res, 0);
        nfs4_set_sequence_privileged(&args.la_seq_args);
-       dprintk("--> %s\n", __func__);
        task = rpc_run_task(&task_setup);
 
        if (IS_ERR(task))
-               status = PTR_ERR(task);
-       else {
-               status = task->tk_status;
-               rpc_put_task(task);
-       }
-       dprintk("<-- %s return %d\n", __func__, status);
+               return PTR_ERR(task);
 
+       status = task->tk_status;
+       rpc_put_task(task);
        return status;
 }
 
@@ -8180,6 +8163,12 @@ static int nfs41_reclaim_complete_handle_errors(struct rpc_task *task, struct nf
                /* fall through */
        case -NFS4ERR_RETRY_UNCACHED_REP:
                return -EAGAIN;
+       case -NFS4ERR_BADSESSION:
+       case -NFS4ERR_DEADSESSION:
+       case -NFS4ERR_CONN_NOT_BOUND_TO_SESSION:
+               nfs4_schedule_session_recovery(clp->cl_session,
+                               task->tk_status);
+               break;
        default:
                nfs4_schedule_lease_recovery(clp);
        }
@@ -8258,7 +8247,6 @@ static int nfs41_proc_reclaim_complete(struct nfs_client *clp,
        if (status == 0)
                status = task->tk_status;
        rpc_put_task(task);
-       return 0;
 out:
        dprintk("<-- %s status=%d\n", __func__, status);
        return status;
@@ -8357,6 +8345,7 @@ nfs4_layoutget_handle_exception(struct rpc_task *task,
                 */
                pnfs_mark_layout_stateid_invalid(lo, &head);
                spin_unlock(&inode->i_lock);
+               nfs_commit_inode(inode, 0);
                pnfs_free_lseg_list(&head);
                status = -EAGAIN;
                goto out;
index 8156bad6b441095199878a900e35594863cad571..b34de036501bc90e48be043aec38485f7f755e55 100644 (file)
@@ -1649,13 +1649,14 @@ static void nfs4_state_start_reclaim_reboot(struct nfs_client *clp)
        nfs4_state_mark_reclaim_helper(clp, nfs4_state_mark_reclaim_reboot);
 }
 
-static void nfs4_reclaim_complete(struct nfs_client *clp,
+static int nfs4_reclaim_complete(struct nfs_client *clp,
                                 const struct nfs4_state_recovery_ops *ops,
                                 struct rpc_cred *cred)
 {
        /* Notify the server we're done reclaiming our state */
        if (ops->reclaim_complete)
-               (void)ops->reclaim_complete(clp, cred);
+               return ops->reclaim_complete(clp, cred);
+       return 0;
 }
 
 static void nfs4_clear_reclaim_server(struct nfs_server *server)
@@ -1702,13 +1703,16 @@ static void nfs4_state_end_reclaim_reboot(struct nfs_client *clp)
 {
        const struct nfs4_state_recovery_ops *ops;
        struct rpc_cred *cred;
+       int err;
 
        if (!nfs4_state_clear_reclaim_reboot(clp))
                return;
        ops = clp->cl_mvops->reboot_recovery_ops;
        cred = nfs4_get_clid_cred(clp);
-       nfs4_reclaim_complete(clp, ops, cred);
+       err = nfs4_reclaim_complete(clp, ops, cred);
        put_rpccred(cred);
+       if (err == -NFS4ERR_CONN_NOT_BOUND_TO_SESSION)
+               set_bit(NFS4CLNT_RECLAIM_REBOOT, &clp->cl_state);
 }
 
 static void nfs4_state_start_reclaim_nograce(struct nfs_client *clp)
index 80ce289eea05326336a7edecbe8a132ee4900d23..3aebfdc82b30320625b0011b4f968207e436fb48 100644 (file)
@@ -1000,8 +1000,9 @@ static void encode_nfs4_verifier(struct xdr_stream *xdr, const nfs4_verifier *ve
 
 static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
                                const struct nfs4_label *label,
+                               const umode_t *umask,
                                const struct nfs_server *server,
-                               bool excl_check, const umode_t *umask)
+                               const uint32_t attrmask[])
 {
        char owner_name[IDMAP_NAMESZ];
        char owner_group[IDMAP_NAMESZ];
@@ -1016,22 +1017,20 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
        /*
         * We reserve enough space to write the entire attribute buffer at once.
         */
-       if (iap->ia_valid & ATTR_SIZE) {
+       if ((iap->ia_valid & ATTR_SIZE) && (attrmask[0] & FATTR4_WORD0_SIZE)) {
                bmval[0] |= FATTR4_WORD0_SIZE;
                len += 8;
        }
-       if (!(server->attr_bitmask[2] & FATTR4_WORD2_MODE_UMASK))
-               umask = NULL;
        if (iap->ia_valid & ATTR_MODE) {
-               if (umask) {
+               if (umask && (attrmask[2] & FATTR4_WORD2_MODE_UMASK)) {
                        bmval[2] |= FATTR4_WORD2_MODE_UMASK;
                        len += 8;
-               } else {
+               } else if (attrmask[1] & FATTR4_WORD1_MODE) {
                        bmval[1] |= FATTR4_WORD1_MODE;
                        len += 4;
                }
        }
-       if (iap->ia_valid & ATTR_UID) {
+       if ((iap->ia_valid & ATTR_UID) && (attrmask[1] & FATTR4_WORD1_OWNER)) {
                owner_namelen = nfs_map_uid_to_name(server, iap->ia_uid, owner_name, IDMAP_NAMESZ);
                if (owner_namelen < 0) {
                        dprintk("nfs: couldn't resolve uid %d to string\n",
@@ -1044,7 +1043,8 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
                bmval[1] |= FATTR4_WORD1_OWNER;
                len += 4 + (XDR_QUADLEN(owner_namelen) << 2);
        }
-       if (iap->ia_valid & ATTR_GID) {
+       if ((iap->ia_valid & ATTR_GID) &&
+          (attrmask[1] & FATTR4_WORD1_OWNER_GROUP)) {
                owner_grouplen = nfs_map_gid_to_group(server, iap->ia_gid, owner_group, IDMAP_NAMESZ);
                if (owner_grouplen < 0) {
                        dprintk("nfs: couldn't resolve gid %d to string\n",
@@ -1056,32 +1056,26 @@ static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
                bmval[1] |= FATTR4_WORD1_OWNER_GROUP;
                len += 4 + (XDR_QUADLEN(owner_grouplen) << 2);
        }
-       if (iap->ia_valid & ATTR_ATIME_SET) {
-               bmval[1] |= FATTR4_WORD1_TIME_ACCESS_SET;
-               len += 16;
-       } else if (iap->ia_valid & ATTR_ATIME) {
-               bmval[1] |= FATTR4_WORD1_TIME_ACCESS_SET;
-               len += 4;
-       }
-       if (iap->ia_valid & ATTR_MTIME_SET) {
-               bmval[1] |= FATTR4_WORD1_TIME_MODIFY_SET;
-               len += 16;
-       } else if (iap->ia_valid & ATTR_MTIME) {
-               bmval[1] |= FATTR4_WORD1_TIME_MODIFY_SET;
-               len += 4;
+       if (attrmask[1] & FATTR4_WORD1_TIME_ACCESS_SET) {
+               if (iap->ia_valid & ATTR_ATIME_SET) {
+                       bmval[1] |= FATTR4_WORD1_TIME_ACCESS_SET;
+                       len += 16;
+               } else if (iap->ia_valid & ATTR_ATIME) {
+                       bmval[1] |= FATTR4_WORD1_TIME_ACCESS_SET;
+                       len += 4;
+               }
        }
-
-       if (excl_check) {
-               const u32 *excl_bmval = server->exclcreat_bitmask;
-               bmval[0] &= excl_bmval[0];
-               bmval[1] &= excl_bmval[1];
-               bmval[2] &= excl_bmval[2];
-
-               if (!(excl_bmval[2] & FATTR4_WORD2_SECURITY_LABEL))
-                       label = NULL;
+       if (attrmask[1] & FATTR4_WORD1_TIME_MODIFY_SET) {
+               if (iap->ia_valid & ATTR_MTIME_SET) {
+                       bmval[1] |= FATTR4_WORD1_TIME_MODIFY_SET;
+                       len += 16;
+               } else if (iap->ia_valid & ATTR_MTIME) {
+                       bmval[1] |= FATTR4_WORD1_TIME_MODIFY_SET;
+                       len += 4;
+               }
        }
 
-       if (label) {
+       if (label && (attrmask[2] & FATTR4_WORD2_SECURITY_LABEL)) {
                len += 4 + 4 + 4 + (XDR_QUADLEN(label->len) << 2);
                bmval[2] |= FATTR4_WORD2_SECURITY_LABEL;
        }
@@ -1188,8 +1182,8 @@ static void encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *
        }
 
        encode_string(xdr, create->name->len, create->name->name);
-       encode_attrs(xdr, create->attrs, create->label, create->server, false,
-                    &create->umask);
+       encode_attrs(xdr, create->attrs, create->label, &create->umask,
+                       create->server, create->server->attr_bitmask);
 }
 
 static void encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap, struct compound_hdr *hdr)
@@ -1409,13 +1403,13 @@ static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_op
        switch(arg->createmode) {
        case NFS4_CREATE_UNCHECKED:
                *p = cpu_to_be32(NFS4_CREATE_UNCHECKED);
-               encode_attrs(xdr, arg->u.attrs, arg->label, arg->server, false,
-                            &arg->umask);
+               encode_attrs(xdr, arg->u.attrs, arg->label, &arg->umask,
+                               arg->server, arg->server->attr_bitmask);
                break;
        case NFS4_CREATE_GUARDED:
                *p = cpu_to_be32(NFS4_CREATE_GUARDED);
-               encode_attrs(xdr, arg->u.attrs, arg->label, arg->server, false,
-                            &arg->umask);
+               encode_attrs(xdr, arg->u.attrs, arg->label, &arg->umask,
+                               arg->server, arg->server->attr_bitmask);
                break;
        case NFS4_CREATE_EXCLUSIVE:
                *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE);
@@ -1424,8 +1418,8 @@ static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_op
        case NFS4_CREATE_EXCLUSIVE4_1:
                *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE4_1);
                encode_nfs4_verifier(xdr, &arg->u.verifier);
-               encode_attrs(xdr, arg->u.attrs, arg->label, arg->server, true,
-                            &arg->umask);
+               encode_attrs(xdr, arg->u.attrs, arg->label, &arg->umask,
+                               arg->server, arg->server->exclcreat_bitmask);
        }
 }
 
@@ -1681,7 +1675,8 @@ static void encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs
 {
        encode_op_hdr(xdr, OP_SETATTR, decode_setattr_maxsz, hdr);
        encode_nfs4_stateid(xdr, &arg->stateid);
-       encode_attrs(xdr, arg->iap, arg->label, server, false, NULL);
+       encode_attrs(xdr, arg->iap, arg->label, NULL, server,
+                       server->attr_bitmask);
 }
 
 static void encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid, struct compound_hdr *hdr)
@@ -2005,16 +2000,10 @@ encode_layoutcommit(struct xdr_stream *xdr,
        *p++ = cpu_to_be32(0); /* Never send time_modify_changed */
        *p++ = cpu_to_be32(NFS_SERVER(args->inode)->pnfs_curr_ld->id);/* type */
 
-       if (NFS_SERVER(inode)->pnfs_curr_ld->encode_layoutcommit) {
-               NFS_SERVER(inode)->pnfs_curr_ld->encode_layoutcommit(
-                       NFS_I(inode)->layout, xdr, args);
-       } else {
-               encode_uint32(xdr, args->layoutupdate_len);
-               if (args->layoutupdate_pages) {
-                       xdr_write_pages(xdr, args->layoutupdate_pages, 0,
-                                       args->layoutupdate_len);
-               }
-       }
+       encode_uint32(xdr, args->layoutupdate_len);
+       if (args->layoutupdate_pages)
+               xdr_write_pages(xdr, args->layoutupdate_pages, 0,
+                               args->layoutupdate_len);
 
        return 0;
 }
@@ -2024,7 +2013,6 @@ encode_layoutreturn(struct xdr_stream *xdr,
                    const struct nfs4_layoutreturn_args *args,
                    struct compound_hdr *hdr)
 {
-       const struct pnfs_layoutdriver_type *lr_ops = NFS_SERVER(args->inode)->pnfs_curr_ld;
        __be32 *p;
 
        encode_op_hdr(xdr, OP_LAYOUTRETURN, decode_layoutreturn_maxsz, hdr);
@@ -2041,8 +2029,6 @@ encode_layoutreturn(struct xdr_stream *xdr,
        spin_unlock(&args->inode->i_lock);
        if (args->ld_private->ops && args->ld_private->ops->encode)
                args->ld_private->ops->encode(xdr, args, args->ld_private);
-       else if (lr_ops->encode_layoutreturn)
-               lr_ops->encode_layoutreturn(xdr, args);
        else
                encode_uint32(xdr, 0);
 }
@@ -5579,6 +5565,8 @@ static int decode_op_map(struct xdr_stream *xdr, struct nfs4_op_map *op_map)
        unsigned int i;
 
        p = xdr_inline_decode(xdr, 4);
+       if (!p)
+               return -EIO;
        bitmap_words = be32_to_cpup(p++);
        if (bitmap_words > NFS4_OP_MAP_NUM_WORDS)
                return -EIO;
diff --git a/fs/nfs/objlayout/Kbuild b/fs/nfs/objlayout/Kbuild
deleted file mode 100644 (file)
index ed30ea0..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#
-# Makefile for the pNFS Objects Layout Driver kernel module
-#
-objlayoutdriver-y := objio_osd.o pnfs_osd_xdr_cli.o objlayout.o
-obj-$(CONFIG_PNFS_OBJLAYOUT) += objlayoutdriver.o
diff --git a/fs/nfs/objlayout/objio_osd.c b/fs/nfs/objlayout/objio_osd.c
deleted file mode 100644 (file)
index 049c1b1..0000000
+++ /dev/null
@@ -1,675 +0,0 @@
-/*
- *  pNFS Objects layout implementation over open-osd initiator library
- *
- *  Copyright (C) 2009 Panasas Inc. [year of first publication]
- *  All rights reserved.
- *
- *  Benny Halevy <bhalevy@panasas.com>
- *  Boaz Harrosh <ooo@electrozaur.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2
- *  See the file COPYING included with this distribution for more details.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions
- *  are met:
- *
- *  1. Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *  2. Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *  3. Neither the name of the Panasas company nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <linux/module.h>
-#include <scsi/osd_ore.h>
-
-#include "objlayout.h"
-#include "../internal.h"
-
-#define NFSDBG_FACILITY         NFSDBG_PNFS_LD
-
-struct objio_dev_ent {
-       struct nfs4_deviceid_node id_node;
-       struct ore_dev od;
-};
-
-static void
-objio_free_deviceid_node(struct nfs4_deviceid_node *d)
-{
-       struct objio_dev_ent *de = container_of(d, struct objio_dev_ent, id_node);
-
-       dprintk("%s: free od=%p\n", __func__, de->od.od);
-       osduld_put_device(de->od.od);
-       kfree_rcu(d, rcu);
-}
-
-struct objio_segment {
-       struct pnfs_layout_segment lseg;
-
-       struct ore_layout layout;
-       struct ore_components oc;
-};
-
-static inline struct objio_segment *
-OBJIO_LSEG(struct pnfs_layout_segment *lseg)
-{
-       return container_of(lseg, struct objio_segment, lseg);
-}
-
-struct objio_state {
-       /* Generic layer */
-       struct objlayout_io_res oir;
-
-       bool sync;
-       /*FIXME: Support for extra_bytes at ore_get_rw_state() */
-       struct ore_io_state *ios;
-};
-
-/* Send and wait for a get_device_info of devices in the layout,
-   then look them up with the osd_initiator library */
-struct nfs4_deviceid_node *
-objio_alloc_deviceid_node(struct nfs_server *server, struct pnfs_device *pdev,
-                       gfp_t gfp_flags)
-{
-       struct pnfs_osd_deviceaddr *deviceaddr;
-       struct objio_dev_ent *ode = NULL;
-       struct osd_dev *od;
-       struct osd_dev_info odi;
-       bool retry_flag = true;
-       __be32 *p;
-       int err;
-
-       deviceaddr = kzalloc(sizeof(*deviceaddr), gfp_flags);
-       if (!deviceaddr)
-               return NULL;
-
-       p = page_address(pdev->pages[0]);
-       pnfs_osd_xdr_decode_deviceaddr(deviceaddr, p);
-
-       odi.systemid_len = deviceaddr->oda_systemid.len;
-       if (odi.systemid_len > sizeof(odi.systemid)) {
-               dprintk("%s: odi.systemid_len > sizeof(systemid=%zd)\n",
-                       __func__, sizeof(odi.systemid));
-               err = -EINVAL;
-               goto out;
-       } else if (odi.systemid_len)
-               memcpy(odi.systemid, deviceaddr->oda_systemid.data,
-                      odi.systemid_len);
-       odi.osdname_len  = deviceaddr->oda_osdname.len;
-       odi.osdname      = (u8 *)deviceaddr->oda_osdname.data;
-
-       if (!odi.osdname_len && !odi.systemid_len) {
-               dprintk("%s: !odi.osdname_len && !odi.systemid_len\n",
-                       __func__);
-               err = -ENODEV;
-               goto out;
-       }
-
-retry_lookup:
-       od = osduld_info_lookup(&odi);
-       if (IS_ERR(od)) {
-               err = PTR_ERR(od);
-               dprintk("%s: osduld_info_lookup => %d\n", __func__, err);
-               if (err == -ENODEV && retry_flag) {
-                       err = objlayout_autologin(deviceaddr);
-                       if (likely(!err)) {
-                               retry_flag = false;
-                               goto retry_lookup;
-                       }
-               }
-               goto out;
-       }
-
-       dprintk("Adding new dev_id(%llx:%llx)\n",
-               _DEVID_LO(&pdev->dev_id), _DEVID_HI(&pdev->dev_id));
-
-       ode = kzalloc(sizeof(*ode), gfp_flags);
-       if (!ode) {
-               dprintk("%s: -ENOMEM od=%p\n", __func__, od);
-               goto out;
-       }
-
-       nfs4_init_deviceid_node(&ode->id_node, server, &pdev->dev_id);
-       kfree(deviceaddr);
-
-       ode->od.od = od;
-       return &ode->id_node;
-
-out:
-       kfree(deviceaddr);
-       return NULL;
-}
-
-static void copy_single_comp(struct ore_components *oc, unsigned c,
-                            struct pnfs_osd_object_cred *src_comp)
-{
-       struct ore_comp *ocomp = &oc->comps[c];
-
-       WARN_ON(src_comp->oc_cap_key.cred_len > 0); /* libosd is NO_SEC only */
-       WARN_ON(src_comp->oc_cap.cred_len > sizeof(ocomp->cred));
-
-       ocomp->obj.partition = src_comp->oc_object_id.oid_partition_id;
-       ocomp->obj.id = src_comp->oc_object_id.oid_object_id;
-
-       memcpy(ocomp->cred, src_comp->oc_cap.cred, sizeof(ocomp->cred));
-}
-
-static int __alloc_objio_seg(unsigned numdevs, gfp_t gfp_flags,
-                      struct objio_segment **pseg)
-{
-/*     This is the in memory structure of the objio_segment
- *
- *     struct __alloc_objio_segment {
- *             struct objio_segment olseg;
- *             struct ore_dev *ods[numdevs];
- *             struct ore_comp comps[numdevs];
- *     } *aolseg;
- *     NOTE: The code as above compiles and runs perfectly. It is elegant,
- *     type safe and compact. At some Past time Linus has decided he does not
- *     like variable length arrays, For the sake of this principal we uglify
- *     the code as below.
- */
-       struct objio_segment *lseg;
-       size_t lseg_size = sizeof(*lseg) +
-                       numdevs * sizeof(lseg->oc.ods[0]) +
-                       numdevs * sizeof(*lseg->oc.comps);
-
-       lseg = kzalloc(lseg_size, gfp_flags);
-       if (unlikely(!lseg)) {
-               dprintk("%s: Failed allocation numdevs=%d size=%zd\n", __func__,
-                       numdevs, lseg_size);
-               return -ENOMEM;
-       }
-
-       lseg->oc.numdevs = numdevs;
-       lseg->oc.single_comp = EC_MULTPLE_COMPS;
-       lseg->oc.ods = (void *)(lseg + 1);
-       lseg->oc.comps = (void *)(lseg->oc.ods + numdevs);
-
-       *pseg = lseg;
-       return 0;
-}
-
-int objio_alloc_lseg(struct pnfs_layout_segment **outp,
-       struct pnfs_layout_hdr *pnfslay,
-       struct pnfs_layout_range *range,
-       struct xdr_stream *xdr,
-       gfp_t gfp_flags)
-{
-       struct nfs_server *server = NFS_SERVER(pnfslay->plh_inode);
-       struct objio_segment *objio_seg;
-       struct pnfs_osd_xdr_decode_layout_iter iter;
-       struct pnfs_osd_layout layout;
-       struct pnfs_osd_object_cred src_comp;
-       unsigned cur_comp;
-       int err;
-
-       err = pnfs_osd_xdr_decode_layout_map(&layout, &iter, xdr);
-       if (unlikely(err))
-               return err;
-
-       err = __alloc_objio_seg(layout.olo_num_comps, gfp_flags, &objio_seg);
-       if (unlikely(err))
-               return err;
-
-       objio_seg->layout.stripe_unit = layout.olo_map.odm_stripe_unit;
-       objio_seg->layout.group_width = layout.olo_map.odm_group_width;
-       objio_seg->layout.group_depth = layout.olo_map.odm_group_depth;
-       objio_seg->layout.mirrors_p1 = layout.olo_map.odm_mirror_cnt + 1;
-       objio_seg->layout.raid_algorithm = layout.olo_map.odm_raid_algorithm;
-
-       err = ore_verify_layout(layout.olo_map.odm_num_comps,
-                                         &objio_seg->layout);
-       if (unlikely(err))
-               goto err;
-
-       objio_seg->oc.first_dev = layout.olo_comps_index;
-       cur_comp = 0;
-       while (pnfs_osd_xdr_decode_layout_comp(&src_comp, &iter, xdr, &err)) {
-               struct nfs4_deviceid_node *d;
-               struct objio_dev_ent *ode;
-
-               copy_single_comp(&objio_seg->oc, cur_comp, &src_comp);
-
-               d = nfs4_find_get_deviceid(server,
-                               &src_comp.oc_object_id.oid_device_id,
-                               pnfslay->plh_lc_cred, gfp_flags);
-               if (!d) {
-                       err = -ENXIO;
-                       goto err;
-               }
-
-               ode = container_of(d, struct objio_dev_ent, id_node);
-               objio_seg->oc.ods[cur_comp++] = &ode->od;
-       }
-       /* pnfs_osd_xdr_decode_layout_comp returns false on error */
-       if (unlikely(err))
-               goto err;
-
-       *outp = &objio_seg->lseg;
-       return 0;
-
-err:
-       kfree(objio_seg);
-       dprintk("%s: Error: return %d\n", __func__, err);
-       *outp = NULL;
-       return err;
-}
-
-void objio_free_lseg(struct pnfs_layout_segment *lseg)
-{
-       int i;
-       struct objio_segment *objio_seg = OBJIO_LSEG(lseg);
-
-       for (i = 0; i < objio_seg->oc.numdevs; i++) {
-               struct ore_dev *od = objio_seg->oc.ods[i];
-               struct objio_dev_ent *ode;
-
-               if (!od)
-                       break;
-               ode = container_of(od, typeof(*ode), od);
-               nfs4_put_deviceid_node(&ode->id_node);
-       }
-       kfree(objio_seg);
-}
-
-static int
-objio_alloc_io_state(struct pnfs_layout_hdr *pnfs_layout_type, bool is_reading,
-       struct pnfs_layout_segment *lseg, struct page **pages, unsigned pgbase,
-       loff_t offset, size_t count, void *rpcdata, gfp_t gfp_flags,
-       struct objio_state **outp)
-{
-       struct objio_segment *objio_seg = OBJIO_LSEG(lseg);
-       struct ore_io_state *ios;
-       int ret;
-       struct __alloc_objio_state {
-               struct objio_state objios;
-               struct pnfs_osd_ioerr ioerrs[objio_seg->oc.numdevs];
-       } *aos;
-
-       aos = kzalloc(sizeof(*aos), gfp_flags);
-       if (unlikely(!aos))
-               return -ENOMEM;
-
-       objlayout_init_ioerrs(&aos->objios.oir, objio_seg->oc.numdevs,
-                       aos->ioerrs, rpcdata, pnfs_layout_type);
-
-       ret = ore_get_rw_state(&objio_seg->layout, &objio_seg->oc, is_reading,
-                              offset, count, &ios);
-       if (unlikely(ret)) {
-               kfree(aos);
-               return ret;
-       }
-
-       ios->pages = pages;
-       ios->pgbase = pgbase;
-       ios->private = aos;
-       BUG_ON(ios->nr_pages > (pgbase + count + PAGE_SIZE - 1) >> PAGE_SHIFT);
-
-       aos->objios.sync = 0;
-       aos->objios.ios = ios;
-       *outp = &aos->objios;
-       return 0;
-}
-
-void objio_free_result(struct objlayout_io_res *oir)
-{
-       struct objio_state *objios = container_of(oir, struct objio_state, oir);
-
-       ore_put_io_state(objios->ios);
-       kfree(objios);
-}
-
-static enum pnfs_osd_errno osd_pri_2_pnfs_err(enum osd_err_priority oep)
-{
-       switch (oep) {
-       case OSD_ERR_PRI_NO_ERROR:
-               return (enum pnfs_osd_errno)0;
-
-       case OSD_ERR_PRI_CLEAR_PAGES:
-               BUG_ON(1);
-               return 0;
-
-       case OSD_ERR_PRI_RESOURCE:
-               return PNFS_OSD_ERR_RESOURCE;
-       case OSD_ERR_PRI_BAD_CRED:
-               return PNFS_OSD_ERR_BAD_CRED;
-       case OSD_ERR_PRI_NO_ACCESS:
-               return PNFS_OSD_ERR_NO_ACCESS;
-       case OSD_ERR_PRI_UNREACHABLE:
-               return PNFS_OSD_ERR_UNREACHABLE;
-       case OSD_ERR_PRI_NOT_FOUND:
-               return PNFS_OSD_ERR_NOT_FOUND;
-       case OSD_ERR_PRI_NO_SPACE:
-               return PNFS_OSD_ERR_NO_SPACE;
-       default:
-               WARN_ON(1);
-               /* fallthrough */
-       case OSD_ERR_PRI_EIO:
-               return PNFS_OSD_ERR_EIO;
-       }
-}
-
-static void __on_dev_error(struct ore_io_state *ios,
-       struct ore_dev *od, unsigned dev_index, enum osd_err_priority oep,
-       u64 dev_offset, u64  dev_len)
-{
-       struct objio_state *objios = ios->private;
-       struct pnfs_osd_objid pooid;
-       struct objio_dev_ent *ode = container_of(od, typeof(*ode), od);
-       /* FIXME: what to do with more-then-one-group layouts. We need to
-        * translate from ore_io_state index to oc->comps index
-        */
-       unsigned comp = dev_index;
-
-       pooid.oid_device_id = ode->id_node.deviceid;
-       pooid.oid_partition_id = ios->oc->comps[comp].obj.partition;
-       pooid.oid_object_id = ios->oc->comps[comp].obj.id;
-
-       objlayout_io_set_result(&objios->oir, comp,
-                               &pooid, osd_pri_2_pnfs_err(oep),
-                               dev_offset, dev_len, !ios->reading);
-}
-
-/*
- * read
- */
-static void _read_done(struct ore_io_state *ios, void *private)
-{
-       struct objio_state *objios = private;
-       ssize_t status;
-       int ret = ore_check_io(ios, &__on_dev_error);
-
-       /* FIXME: _io_free(ios) can we dealocate the libosd resources; */
-
-       if (likely(!ret))
-               status = ios->length;
-       else
-               status = ret;
-
-       objlayout_read_done(&objios->oir, status, objios->sync);
-}
-
-int objio_read_pagelist(struct nfs_pgio_header *hdr)
-{
-       struct objio_state *objios;
-       int ret;
-
-       ret = objio_alloc_io_state(NFS_I(hdr->inode)->layout, true,
-                       hdr->lseg, hdr->args.pages, hdr->args.pgbase,
-                       hdr->args.offset, hdr->args.count, hdr,
-                       GFP_KERNEL, &objios);
-       if (unlikely(ret))
-               return ret;
-
-       objios->ios->done = _read_done;
-       dprintk("%s: offset=0x%llx length=0x%x\n", __func__,
-               hdr->args.offset, hdr->args.count);
-       ret = ore_read(objios->ios);
-       if (unlikely(ret))
-               objio_free_result(&objios->oir);
-       return ret;
-}
-
-/*
- * write
- */
-static void _write_done(struct ore_io_state *ios, void *private)
-{
-       struct objio_state *objios = private;
-       ssize_t status;
-       int ret = ore_check_io(ios, &__on_dev_error);
-
-       /* FIXME: _io_free(ios) can we dealocate the libosd resources; */
-
-       if (likely(!ret)) {
-               /* FIXME: should be based on the OSD's persistence model
-                * See OSD2r05 Section 4.13 Data persistence model */
-               objios->oir.committed = NFS_FILE_SYNC;
-               status = ios->length;
-       } else {
-               status = ret;
-       }
-
-       objlayout_write_done(&objios->oir, status, objios->sync);
-}
-
-static struct page *__r4w_get_page(void *priv, u64 offset, bool *uptodate)
-{
-       struct objio_state *objios = priv;
-       struct nfs_pgio_header *hdr = objios->oir.rpcdata;
-       struct address_space *mapping = hdr->inode->i_mapping;
-       pgoff_t index = offset / PAGE_SIZE;
-       struct page *page;
-       loff_t i_size = i_size_read(hdr->inode);
-
-       if (offset >= i_size) {
-               *uptodate = true;
-               dprintk("%s: g_zero_page index=0x%lx\n", __func__, index);
-               return ZERO_PAGE(0);
-       }
-
-       page = find_get_page(mapping, index);
-       if (!page) {
-               page = find_or_create_page(mapping, index, GFP_NOFS);
-               if (unlikely(!page)) {
-                       dprintk("%s: grab_cache_page Failed index=0x%lx\n",
-                               __func__, index);
-                       return NULL;
-               }
-               unlock_page(page);
-       }
-       *uptodate = PageUptodate(page);
-       dprintk("%s: index=0x%lx uptodate=%d\n", __func__, index, *uptodate);
-       return page;
-}
-
-static void __r4w_put_page(void *priv, struct page *page)
-{
-       dprintk("%s: index=0x%lx\n", __func__,
-               (page == ZERO_PAGE(0)) ? -1UL : page->index);
-       if (ZERO_PAGE(0) != page)
-               put_page(page);
-       return;
-}
-
-static const struct _ore_r4w_op _r4w_op = {
-       .get_page = &__r4w_get_page,
-       .put_page = &__r4w_put_page,
-};
-
-int objio_write_pagelist(struct nfs_pgio_header *hdr, int how)
-{
-       struct objio_state *objios;
-       int ret;
-
-       ret = objio_alloc_io_state(NFS_I(hdr->inode)->layout, false,
-                       hdr->lseg, hdr->args.pages, hdr->args.pgbase,
-                       hdr->args.offset, hdr->args.count, hdr, GFP_NOFS,
-                       &objios);
-       if (unlikely(ret))
-               return ret;
-
-       objios->sync = 0 != (how & FLUSH_SYNC);
-       objios->ios->r4w = &_r4w_op;
-
-       if (!objios->sync)
-               objios->ios->done = _write_done;
-
-       dprintk("%s: offset=0x%llx length=0x%x\n", __func__,
-               hdr->args.offset, hdr->args.count);
-       ret = ore_write(objios->ios);
-       if (unlikely(ret)) {
-               objio_free_result(&objios->oir);
-               return ret;
-       }
-
-       if (objios->sync)
-               _write_done(objios->ios, objios);
-
-       return 0;
-}
-
-/*
- * Return 0 if @req cannot be coalesced into @pgio, otherwise return the number
- * of bytes (maximum @req->wb_bytes) that can be coalesced.
- */
-static size_t objio_pg_test(struct nfs_pageio_descriptor *pgio,
-                         struct nfs_page *prev, struct nfs_page *req)
-{
-       struct nfs_pgio_mirror *mirror = nfs_pgio_current_mirror(pgio);
-       unsigned int size;
-
-       size = pnfs_generic_pg_test(pgio, prev, req);
-
-       if (!size || mirror->pg_count + req->wb_bytes >
-           (unsigned long)pgio->pg_layout_private)
-               return 0;
-
-       return min(size, req->wb_bytes);
-}
-
-static void objio_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
-{
-       pnfs_generic_pg_init_read(pgio, req);
-       if (unlikely(pgio->pg_lseg == NULL))
-               return; /* Not pNFS */
-
-       pgio->pg_layout_private = (void *)
-                               OBJIO_LSEG(pgio->pg_lseg)->layout.max_io_length;
-}
-
-static bool aligned_on_raid_stripe(u64 offset, struct ore_layout *layout,
-                                  unsigned long *stripe_end)
-{
-       u32 stripe_off;
-       unsigned stripe_size;
-
-       if (layout->raid_algorithm == PNFS_OSD_RAID_0)
-               return true;
-
-       stripe_size = layout->stripe_unit *
-                               (layout->group_width - layout->parity);
-
-       div_u64_rem(offset, stripe_size, &stripe_off);
-       if (!stripe_off)
-               return true;
-
-       *stripe_end = stripe_size - stripe_off;
-       return false;
-}
-
-static void objio_init_write(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
-{
-       unsigned long stripe_end = 0;
-       u64 wb_size;
-
-       if (pgio->pg_dreq == NULL)
-               wb_size = i_size_read(pgio->pg_inode) - req_offset(req);
-       else
-               wb_size = nfs_dreq_bytes_left(pgio->pg_dreq);
-
-       pnfs_generic_pg_init_write(pgio, req, wb_size);
-       if (unlikely(pgio->pg_lseg == NULL))
-               return; /* Not pNFS */
-
-       if (req->wb_offset ||
-           !aligned_on_raid_stripe(req->wb_index * PAGE_SIZE,
-                              &OBJIO_LSEG(pgio->pg_lseg)->layout,
-                              &stripe_end)) {
-               pgio->pg_layout_private = (void *)stripe_end;
-       } else {
-               pgio->pg_layout_private = (void *)
-                               OBJIO_LSEG(pgio->pg_lseg)->layout.max_io_length;
-       }
-}
-
-static const struct nfs_pageio_ops objio_pg_read_ops = {
-       .pg_init = objio_init_read,
-       .pg_test = objio_pg_test,
-       .pg_doio = pnfs_generic_pg_readpages,
-       .pg_cleanup = pnfs_generic_pg_cleanup,
-};
-
-static const struct nfs_pageio_ops objio_pg_write_ops = {
-       .pg_init = objio_init_write,
-       .pg_test = objio_pg_test,
-       .pg_doio = pnfs_generic_pg_writepages,
-       .pg_cleanup = pnfs_generic_pg_cleanup,
-};
-
-static struct pnfs_layoutdriver_type objlayout_type = {
-       .id = LAYOUT_OSD2_OBJECTS,
-       .name = "LAYOUT_OSD2_OBJECTS",
-       .flags                   = PNFS_LAYOUTRET_ON_SETATTR |
-                                  PNFS_LAYOUTRET_ON_ERROR,
-
-       .max_deviceinfo_size     = PAGE_SIZE,
-       .owner                   = THIS_MODULE,
-       .alloc_layout_hdr        = objlayout_alloc_layout_hdr,
-       .free_layout_hdr         = objlayout_free_layout_hdr,
-
-       .alloc_lseg              = objlayout_alloc_lseg,
-       .free_lseg               = objlayout_free_lseg,
-
-       .read_pagelist           = objlayout_read_pagelist,
-       .write_pagelist          = objlayout_write_pagelist,
-       .pg_read_ops             = &objio_pg_read_ops,
-       .pg_write_ops            = &objio_pg_write_ops,
-
-       .sync                    = pnfs_generic_sync,
-
-       .free_deviceid_node      = objio_free_deviceid_node,
-
-       .encode_layoutcommit     = objlayout_encode_layoutcommit,
-       .encode_layoutreturn     = objlayout_encode_layoutreturn,
-};
-
-MODULE_DESCRIPTION("pNFS Layout Driver for OSD2 objects");
-MODULE_AUTHOR("Benny Halevy <bhalevy@panasas.com>");
-MODULE_LICENSE("GPL");
-
-static int __init
-objlayout_init(void)
-{
-       int ret = pnfs_register_layoutdriver(&objlayout_type);
-
-       if (ret)
-               printk(KERN_INFO
-                       "NFS: %s: Registering OSD pNFS Layout Driver failed: error=%d\n",
-                       __func__, ret);
-       else
-               printk(KERN_INFO "NFS: %s: Registered OSD pNFS Layout Driver\n",
-                       __func__);
-       return ret;
-}
-
-static void __exit
-objlayout_exit(void)
-{
-       pnfs_unregister_layoutdriver(&objlayout_type);
-       printk(KERN_INFO "NFS: %s: Unregistered OSD pNFS Layout Driver\n",
-              __func__);
-}
-
-MODULE_ALIAS("nfs-layouttype4-2");
-
-module_init(objlayout_init);
-module_exit(objlayout_exit);
diff --git a/fs/nfs/objlayout/objlayout.c b/fs/nfs/objlayout/objlayout.c
deleted file mode 100644 (file)
index 8f3d2ac..0000000
+++ /dev/null
@@ -1,706 +0,0 @@
-/*
- *  pNFS Objects layout driver high level definitions
- *
- *  Copyright (C) 2007 Panasas Inc. [year of first publication]
- *  All rights reserved.
- *
- *  Benny Halevy <bhalevy@panasas.com>
- *  Boaz Harrosh <ooo@electrozaur.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2
- *  See the file COPYING included with this distribution for more details.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions
- *  are met:
- *
- *  1. Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *  2. Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *  3. Neither the name of the Panasas company nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <linux/kmod.h>
-#include <linux/moduleparam.h>
-#include <linux/ratelimit.h>
-#include <scsi/osd_initiator.h>
-#include "objlayout.h"
-
-#define NFSDBG_FACILITY         NFSDBG_PNFS_LD
-/*
- * Create a objlayout layout structure for the given inode and return it.
- */
-struct pnfs_layout_hdr *
-objlayout_alloc_layout_hdr(struct inode *inode, gfp_t gfp_flags)
-{
-       struct objlayout *objlay;
-
-       objlay = kzalloc(sizeof(struct objlayout), gfp_flags);
-       if (!objlay)
-               return NULL;
-       spin_lock_init(&objlay->lock);
-       INIT_LIST_HEAD(&objlay->err_list);
-       dprintk("%s: Return %p\n", __func__, objlay);
-       return &objlay->pnfs_layout;
-}
-
-/*
- * Free an objlayout layout structure
- */
-void
-objlayout_free_layout_hdr(struct pnfs_layout_hdr *lo)
-{
-       struct objlayout *objlay = OBJLAYOUT(lo);
-
-       dprintk("%s: objlay %p\n", __func__, objlay);
-
-       WARN_ON(!list_empty(&objlay->err_list));
-       kfree(objlay);
-}
-
-/*
- * Unmarshall layout and store it in pnfslay.
- */
-struct pnfs_layout_segment *
-objlayout_alloc_lseg(struct pnfs_layout_hdr *pnfslay,
-                    struct nfs4_layoutget_res *lgr,
-                    gfp_t gfp_flags)
-{
-       int status = -ENOMEM;
-       struct xdr_stream stream;
-       struct xdr_buf buf = {
-               .pages =  lgr->layoutp->pages,
-               .page_len =  lgr->layoutp->len,
-               .buflen =  lgr->layoutp->len,
-               .len = lgr->layoutp->len,
-       };
-       struct page *scratch;
-       struct pnfs_layout_segment *lseg;
-
-       dprintk("%s: Begin pnfslay %p\n", __func__, pnfslay);
-
-       scratch = alloc_page(gfp_flags);
-       if (!scratch)
-               goto err_nofree;
-
-       xdr_init_decode(&stream, &buf, NULL);
-       xdr_set_scratch_buffer(&stream, page_address(scratch), PAGE_SIZE);
-
-       status = objio_alloc_lseg(&lseg, pnfslay, &lgr->range, &stream, gfp_flags);
-       if (unlikely(status)) {
-               dprintk("%s: objio_alloc_lseg Return err %d\n", __func__,
-                       status);
-               goto err;
-       }
-
-       __free_page(scratch);
-
-       dprintk("%s: Return %p\n", __func__, lseg);
-       return lseg;
-
-err:
-       __free_page(scratch);
-err_nofree:
-       dprintk("%s: Err Return=>%d\n", __func__, status);
-       return ERR_PTR(status);
-}
-
-/*
- * Free a layout segement
- */
-void
-objlayout_free_lseg(struct pnfs_layout_segment *lseg)
-{
-       dprintk("%s: freeing layout segment %p\n", __func__, lseg);
-
-       if (unlikely(!lseg))
-               return;
-
-       objio_free_lseg(lseg);
-}
-
-/*
- * I/O Operations
- */
-static inline u64
-end_offset(u64 start, u64 len)
-{
-       u64 end;
-
-       end = start + len;
-       return end >= start ? end : NFS4_MAX_UINT64;
-}
-
-static void _fix_verify_io_params(struct pnfs_layout_segment *lseg,
-                          struct page ***p_pages, unsigned *p_pgbase,
-                          u64 offset, unsigned long count)
-{
-       u64 lseg_end_offset;
-
-       BUG_ON(offset < lseg->pls_range.offset);
-       lseg_end_offset = end_offset(lseg->pls_range.offset,
-                                    lseg->pls_range.length);
-       BUG_ON(offset >= lseg_end_offset);
-       WARN_ON(offset + count > lseg_end_offset);
-
-       if (*p_pgbase > PAGE_SIZE) {
-               dprintk("%s: pgbase(0x%x) > PAGE_SIZE\n", __func__, *p_pgbase);
-               *p_pages += *p_pgbase >> PAGE_SHIFT;
-               *p_pgbase &= ~PAGE_MASK;
-       }
-}
-
-/*
- * I/O done common code
- */
-static void
-objlayout_iodone(struct objlayout_io_res *oir)
-{
-       if (likely(oir->status >= 0)) {
-               objio_free_result(oir);
-       } else {
-               struct objlayout *objlay = oir->objlay;
-
-               spin_lock(&objlay->lock);
-               objlay->delta_space_valid = OBJ_DSU_INVALID;
-               list_add(&objlay->err_list, &oir->err_list);
-               spin_unlock(&objlay->lock);
-       }
-}
-
-/*
- * objlayout_io_set_result - Set an osd_error code on a specific osd comp.
- *
- * The @index component IO failed (error returned from target). Register
- * the error for later reporting at layout-return.
- */
-void
-objlayout_io_set_result(struct objlayout_io_res *oir, unsigned index,
-                       struct pnfs_osd_objid *pooid, int osd_error,
-                       u64 offset, u64 length, bool is_write)
-{
-       struct pnfs_osd_ioerr *ioerr = &oir->ioerrs[index];
-
-       BUG_ON(index >= oir->num_comps);
-       if (osd_error) {
-               ioerr->oer_component = *pooid;
-               ioerr->oer_comp_offset = offset;
-               ioerr->oer_comp_length = length;
-               ioerr->oer_iswrite = is_write;
-               ioerr->oer_errno = osd_error;
-
-               dprintk("%s: err[%d]: errno=%d is_write=%d dev(%llx:%llx) "
-                       "par=0x%llx obj=0x%llx offset=0x%llx length=0x%llx\n",
-                       __func__, index, ioerr->oer_errno,
-                       ioerr->oer_iswrite,
-                       _DEVID_LO(&ioerr->oer_component.oid_device_id),
-                       _DEVID_HI(&ioerr->oer_component.oid_device_id),
-                       ioerr->oer_component.oid_partition_id,
-                       ioerr->oer_component.oid_object_id,
-                       ioerr->oer_comp_offset,
-                       ioerr->oer_comp_length);
-       } else {
-               /* User need not call if no error is reported */
-               ioerr->oer_errno = 0;
-       }
-}
-
-/* Function scheduled on rpc workqueue to call ->nfs_readlist_complete().
- * This is because the osd completion is called with ints-off from
- * the block layer
- */
-static void _rpc_read_complete(struct work_struct *work)
-{
-       struct rpc_task *task;
-       struct nfs_pgio_header *hdr;
-
-       dprintk("%s enter\n", __func__);
-       task = container_of(work, struct rpc_task, u.tk_work);
-       hdr = container_of(task, struct nfs_pgio_header, task);
-
-       pnfs_ld_read_done(hdr);
-}
-
-void
-objlayout_read_done(struct objlayout_io_res *oir, ssize_t status, bool sync)
-{
-       struct nfs_pgio_header *hdr = oir->rpcdata;
-
-       oir->status = hdr->task.tk_status = status;
-       if (status >= 0)
-               hdr->res.count = status;
-       else
-               hdr->pnfs_error = status;
-       objlayout_iodone(oir);
-       /* must not use oir after this point */
-
-       dprintk("%s: Return status=%zd eof=%d sync=%d\n", __func__,
-               status, hdr->res.eof, sync);
-
-       if (sync)
-               pnfs_ld_read_done(hdr);
-       else {
-               INIT_WORK(&hdr->task.u.tk_work, _rpc_read_complete);
-               schedule_work(&hdr->task.u.tk_work);
-       }
-}
-
-/*
- * Perform sync or async reads.
- */
-enum pnfs_try_status
-objlayout_read_pagelist(struct nfs_pgio_header *hdr)
-{
-       struct inode *inode = hdr->inode;
-       loff_t offset = hdr->args.offset;
-       size_t count = hdr->args.count;
-       int err;
-       loff_t eof;
-
-       eof = i_size_read(inode);
-       if (unlikely(offset + count > eof)) {
-               if (offset >= eof) {
-                       err = 0;
-                       hdr->res.count = 0;
-                       hdr->res.eof = 1;
-                       /*FIXME: do we need to call pnfs_ld_read_done() */
-                       goto out;
-               }
-               count = eof - offset;
-       }
-
-       hdr->res.eof = (offset + count) >= eof;
-       _fix_verify_io_params(hdr->lseg, &hdr->args.pages,
-                             &hdr->args.pgbase,
-                             hdr->args.offset, hdr->args.count);
-
-       dprintk("%s: inode(%lx) offset 0x%llx count 0x%zx eof=%d\n",
-               __func__, inode->i_ino, offset, count, hdr->res.eof);
-
-       err = objio_read_pagelist(hdr);
- out:
-       if (unlikely(err)) {
-               hdr->pnfs_error = err;
-               dprintk("%s: Returned Error %d\n", __func__, err);
-               return PNFS_NOT_ATTEMPTED;
-       }
-       return PNFS_ATTEMPTED;
-}
-
-/* Function scheduled on rpc workqueue to call ->nfs_writelist_complete().
- * This is because the osd completion is called with ints-off from
- * the block layer
- */
-static void _rpc_write_complete(struct work_struct *work)
-{
-       struct rpc_task *task;
-       struct nfs_pgio_header *hdr;
-
-       dprintk("%s enter\n", __func__);
-       task = container_of(work, struct rpc_task, u.tk_work);
-       hdr = container_of(task, struct nfs_pgio_header, task);
-
-       pnfs_ld_write_done(hdr);
-}
-
-void
-objlayout_write_done(struct objlayout_io_res *oir, ssize_t status, bool sync)
-{
-       struct nfs_pgio_header *hdr = oir->rpcdata;
-
-       oir->status = hdr->task.tk_status = status;
-       if (status >= 0) {
-               hdr->res.count = status;
-               hdr->verf.committed = oir->committed;
-       } else {
-               hdr->pnfs_error = status;
-       }
-       objlayout_iodone(oir);
-       /* must not use oir after this point */
-
-       dprintk("%s: Return status %zd committed %d sync=%d\n", __func__,
-               status, hdr->verf.committed, sync);
-
-       if (sync)
-               pnfs_ld_write_done(hdr);
-       else {
-               INIT_WORK(&hdr->task.u.tk_work, _rpc_write_complete);
-               schedule_work(&hdr->task.u.tk_work);
-       }
-}
-
-/*
- * Perform sync or async writes.
- */
-enum pnfs_try_status
-objlayout_write_pagelist(struct nfs_pgio_header *hdr, int how)
-{
-       int err;
-
-       _fix_verify_io_params(hdr->lseg, &hdr->args.pages,
-                             &hdr->args.pgbase,
-                             hdr->args.offset, hdr->args.count);
-
-       err = objio_write_pagelist(hdr, how);
-       if (unlikely(err)) {
-               hdr->pnfs_error = err;
-               dprintk("%s: Returned Error %d\n", __func__, err);
-               return PNFS_NOT_ATTEMPTED;
-       }
-       return PNFS_ATTEMPTED;
-}
-
-void
-objlayout_encode_layoutcommit(struct pnfs_layout_hdr *pnfslay,
-                             struct xdr_stream *xdr,
-                             const struct nfs4_layoutcommit_args *args)
-{
-       struct objlayout *objlay = OBJLAYOUT(pnfslay);
-       struct pnfs_osd_layoutupdate lou;
-       __be32 *start;
-
-       dprintk("%s: Begin\n", __func__);
-
-       spin_lock(&objlay->lock);
-       lou.dsu_valid = (objlay->delta_space_valid == OBJ_DSU_VALID);
-       lou.dsu_delta = objlay->delta_space_used;
-       objlay->delta_space_used = 0;
-       objlay->delta_space_valid = OBJ_DSU_INIT;
-       lou.olu_ioerr_flag = !list_empty(&objlay->err_list);
-       spin_unlock(&objlay->lock);
-
-       start = xdr_reserve_space(xdr, 4);
-
-       BUG_ON(pnfs_osd_xdr_encode_layoutupdate(xdr, &lou));
-
-       *start = cpu_to_be32((xdr->p - start - 1) * 4);
-
-       dprintk("%s: Return delta_space_used %lld err %d\n", __func__,
-               lou.dsu_delta, lou.olu_ioerr_flag);
-}
-
-static int
-err_prio(u32 oer_errno)
-{
-       switch (oer_errno) {
-       case 0:
-               return 0;
-
-       case PNFS_OSD_ERR_RESOURCE:
-               return OSD_ERR_PRI_RESOURCE;
-       case PNFS_OSD_ERR_BAD_CRED:
-               return OSD_ERR_PRI_BAD_CRED;
-       case PNFS_OSD_ERR_NO_ACCESS:
-               return OSD_ERR_PRI_NO_ACCESS;
-       case PNFS_OSD_ERR_UNREACHABLE:
-               return OSD_ERR_PRI_UNREACHABLE;
-       case PNFS_OSD_ERR_NOT_FOUND:
-               return OSD_ERR_PRI_NOT_FOUND;
-       case PNFS_OSD_ERR_NO_SPACE:
-               return OSD_ERR_PRI_NO_SPACE;
-       default:
-               WARN_ON(1);
-               /* fallthrough */
-       case PNFS_OSD_ERR_EIO:
-               return OSD_ERR_PRI_EIO;
-       }
-}
-
-static void
-merge_ioerr(struct pnfs_osd_ioerr *dest_err,
-           const struct pnfs_osd_ioerr *src_err)
-{
-       u64 dest_end, src_end;
-
-       if (!dest_err->oer_errno) {
-               *dest_err = *src_err;
-               /* accumulated device must be blank */
-               memset(&dest_err->oer_component.oid_device_id, 0,
-                       sizeof(dest_err->oer_component.oid_device_id));
-
-               return;
-       }
-
-       if (dest_err->oer_component.oid_partition_id !=
-                               src_err->oer_component.oid_partition_id)
-               dest_err->oer_component.oid_partition_id = 0;
-
-       if (dest_err->oer_component.oid_object_id !=
-                               src_err->oer_component.oid_object_id)
-               dest_err->oer_component.oid_object_id = 0;
-
-       if (dest_err->oer_comp_offset > src_err->oer_comp_offset)
-               dest_err->oer_comp_offset = src_err->oer_comp_offset;
-
-       dest_end = end_offset(dest_err->oer_comp_offset,
-                             dest_err->oer_comp_length);
-       src_end =  end_offset(src_err->oer_comp_offset,
-                             src_err->oer_comp_length);
-       if (dest_end < src_end)
-               dest_end = src_end;
-
-       dest_err->oer_comp_length = dest_end - dest_err->oer_comp_offset;
-
-       if ((src_err->oer_iswrite == dest_err->oer_iswrite) &&
-           (err_prio(src_err->oer_errno) > err_prio(dest_err->oer_errno))) {
-                       dest_err->oer_errno = src_err->oer_errno;
-       } else if (src_err->oer_iswrite) {
-               dest_err->oer_iswrite = true;
-               dest_err->oer_errno = src_err->oer_errno;
-       }
-}
-
-static void
-encode_accumulated_error(struct objlayout *objlay, __be32 *p)
-{
-       struct objlayout_io_res *oir, *tmp;
-       struct pnfs_osd_ioerr accumulated_err = {.oer_errno = 0};
-
-       list_for_each_entry_safe(oir, tmp, &objlay->err_list, err_list) {
-               unsigned i;
-
-               for (i = 0; i < oir->num_comps; i++) {
-                       struct pnfs_osd_ioerr *ioerr = &oir->ioerrs[i];
-
-                       if (!ioerr->oer_errno)
-                               continue;
-
-                       printk(KERN_ERR "NFS: %s: err[%d]: errno=%d "
-                               "is_write=%d dev(%llx:%llx) par=0x%llx "
-                               "obj=0x%llx offset=0x%llx length=0x%llx\n",
-                               __func__, i, ioerr->oer_errno,
-                               ioerr->oer_iswrite,
-                               _DEVID_LO(&ioerr->oer_component.oid_device_id),
-                               _DEVID_HI(&ioerr->oer_component.oid_device_id),
-                               ioerr->oer_component.oid_partition_id,
-                               ioerr->oer_component.oid_object_id,
-                               ioerr->oer_comp_offset,
-                               ioerr->oer_comp_length);
-
-                       merge_ioerr(&accumulated_err, ioerr);
-               }
-               list_del(&oir->err_list);
-               objio_free_result(oir);
-       }
-
-       pnfs_osd_xdr_encode_ioerr(p, &accumulated_err);
-}
-
-void
-objlayout_encode_layoutreturn(struct xdr_stream *xdr,
-                             const struct nfs4_layoutreturn_args *args)
-{
-       struct pnfs_layout_hdr *pnfslay = args->layout;
-       struct objlayout *objlay = OBJLAYOUT(pnfslay);
-       struct objlayout_io_res *oir, *tmp;
-       __be32 *start;
-
-       dprintk("%s: Begin\n", __func__);
-       start = xdr_reserve_space(xdr, 4);
-       BUG_ON(!start);
-
-       spin_lock(&objlay->lock);
-
-       list_for_each_entry_safe(oir, tmp, &objlay->err_list, err_list) {
-               __be32 *last_xdr = NULL, *p;
-               unsigned i;
-               int res = 0;
-
-               for (i = 0; i < oir->num_comps; i++) {
-                       struct pnfs_osd_ioerr *ioerr = &oir->ioerrs[i];
-
-                       if (!ioerr->oer_errno)
-                               continue;
-
-                       dprintk("%s: err[%d]: errno=%d is_write=%d "
-                               "dev(%llx:%llx) par=0x%llx obj=0x%llx "
-                               "offset=0x%llx length=0x%llx\n",
-                               __func__, i, ioerr->oer_errno,
-                               ioerr->oer_iswrite,
-                               _DEVID_LO(&ioerr->oer_component.oid_device_id),
-                               _DEVID_HI(&ioerr->oer_component.oid_device_id),
-                               ioerr->oer_component.oid_partition_id,
-                               ioerr->oer_component.oid_object_id,
-                               ioerr->oer_comp_offset,
-                               ioerr->oer_comp_length);
-
-                       p = pnfs_osd_xdr_ioerr_reserve_space(xdr);
-                       if (unlikely(!p)) {
-                               res = -E2BIG;
-                               break; /* accumulated_error */
-                       }
-
-                       last_xdr = p;
-                       pnfs_osd_xdr_encode_ioerr(p, &oir->ioerrs[i]);
-               }
-
-               /* TODO: use xdr_write_pages */
-               if (unlikely(res)) {
-                       /* no space for even one error descriptor */
-                       BUG_ON(!last_xdr);
-
-                       /* we've encountered a situation with lots and lots of
-                        * errors and no space to encode them all. Use the last
-                        * available slot to report the union of all the
-                        * remaining errors.
-                        */
-                       encode_accumulated_error(objlay, last_xdr);
-                       goto loop_done;
-               }
-               list_del(&oir->err_list);
-               objio_free_result(oir);
-       }
-loop_done:
-       spin_unlock(&objlay->lock);
-
-       *start = cpu_to_be32((xdr->p - start - 1) * 4);
-       dprintk("%s: Return\n", __func__);
-}
-
-enum {
-       OBJLAYOUT_MAX_URI_LEN = 256, OBJLAYOUT_MAX_OSDNAME_LEN = 64,
-       OBJLAYOUT_MAX_SYSID_HEX_LEN = OSD_SYSTEMID_LEN * 2 + 1,
-       OSD_LOGIN_UPCALL_PATHLEN  = 256
-};
-
-static char osd_login_prog[OSD_LOGIN_UPCALL_PATHLEN] = "/sbin/osd_login";
-
-module_param_string(osd_login_prog, osd_login_prog, sizeof(osd_login_prog),
-                   0600);
-MODULE_PARM_DESC(osd_login_prog, "Path to the osd_login upcall program");
-
-struct __auto_login {
-       char uri[OBJLAYOUT_MAX_URI_LEN];
-       char osdname[OBJLAYOUT_MAX_OSDNAME_LEN];
-       char systemid_hex[OBJLAYOUT_MAX_SYSID_HEX_LEN];
-};
-
-static int __objlayout_upcall(struct __auto_login *login)
-{
-       static char *envp[] = { "HOME=/",
-               "TERM=linux",
-               "PATH=/sbin:/usr/sbin:/bin:/usr/bin",
-               NULL
-       };
-       char *argv[8];
-       int ret;
-
-       if (unlikely(!osd_login_prog[0])) {
-               dprintk("%s: osd_login_prog is disabled\n", __func__);
-               return -EACCES;
-       }
-
-       dprintk("%s uri: %s\n", __func__, login->uri);
-       dprintk("%s osdname %s\n", __func__, login->osdname);
-       dprintk("%s systemid_hex %s\n", __func__, login->systemid_hex);
-
-       argv[0] = (char *)osd_login_prog;
-       argv[1] = "-u";
-       argv[2] = login->uri;
-       argv[3] = "-o";
-       argv[4] = login->osdname;
-       argv[5] = "-s";
-       argv[6] = login->systemid_hex;
-       argv[7] = NULL;
-
-       ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC);
-       /*
-        * Disable the upcall mechanism if we're getting an ENOENT or
-        * EACCES error. The admin can re-enable it on the fly by using
-        * sysfs to set the objlayoutdriver.osd_login_prog module parameter once
-        * the problem has been fixed.
-        */
-       if (ret == -ENOENT || ret == -EACCES) {
-               printk(KERN_ERR "PNFS-OBJ: %s was not found please set "
-                       "objlayoutdriver.osd_login_prog kernel parameter!\n",
-                       osd_login_prog);
-               osd_login_prog[0] = '\0';
-       }
-       dprintk("%s %s return value: %d\n", __func__, osd_login_prog, ret);
-
-       return ret;
-}
-
-/* Assume dest is all zeros */
-static void __copy_nfsS_and_zero_terminate(struct nfs4_string s,
-                                          char *dest, int max_len,
-                                          const char *var_name)
-{
-       if (!s.len)
-               return;
-
-       if (s.len >= max_len) {
-               pr_warn_ratelimited(
-                       "objlayout_autologin: %s: s.len(%d) >= max_len(%d)",
-                       var_name, s.len, max_len);
-               s.len = max_len - 1; /* space for null terminator */
-       }
-
-       memcpy(dest, s.data, s.len);
-}
-
-/* Assume sysid is all zeros */
-static void _sysid_2_hex(struct nfs4_string s,
-                 char sysid[OBJLAYOUT_MAX_SYSID_HEX_LEN])
-{
-       int i;
-       char *cur;
-
-       if (!s.len)
-               return;
-
-       if (s.len != OSD_SYSTEMID_LEN) {
-               pr_warn_ratelimited(
-                   "objlayout_autologin: systemid_len(%d) != OSD_SYSTEMID_LEN",
-                   s.len);
-               if (s.len > OSD_SYSTEMID_LEN)
-                       s.len = OSD_SYSTEMID_LEN;
-       }
-
-       cur = sysid;
-       for (i = 0; i < s.len; i++)
-               cur = hex_byte_pack(cur, s.data[i]);
-}
-
-int objlayout_autologin(struct pnfs_osd_deviceaddr *deviceaddr)
-{
-       int rc;
-       struct __auto_login login;
-
-       if (!deviceaddr->oda_targetaddr.ota_netaddr.r_addr.len)
-               return -ENODEV;
-
-       memset(&login, 0, sizeof(login));
-       __copy_nfsS_and_zero_terminate(
-               deviceaddr->oda_targetaddr.ota_netaddr.r_addr,
-               login.uri, sizeof(login.uri), "URI");
-
-       __copy_nfsS_and_zero_terminate(
-               deviceaddr->oda_osdname,
-               login.osdname, sizeof(login.osdname), "OSDNAME");
-
-       _sysid_2_hex(deviceaddr->oda_systemid, login.systemid_hex);
-
-       rc = __objlayout_upcall(&login);
-       if (rc > 0) /* script returns positive values */
-               rc = -ENODEV;
-
-       return rc;
-}
diff --git a/fs/nfs/objlayout/objlayout.h b/fs/nfs/objlayout/objlayout.h
deleted file mode 100644 (file)
index fc94a58..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-/*
- *  Data types and function declerations for interfacing with the
- *  pNFS standard object layout driver.
- *
- *  Copyright (C) 2007 Panasas Inc. [year of first publication]
- *  All rights reserved.
- *
- *  Benny Halevy <bhalevy@panasas.com>
- *  Boaz Harrosh <ooo@electrozaur.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2
- *  See the file COPYING included with this distribution for more details.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions
- *  are met:
- *
- *  1. Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *  2. Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *  3. Neither the name of the Panasas company nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef _OBJLAYOUT_H
-#define _OBJLAYOUT_H
-
-#include <linux/nfs_fs.h>
-#include <linux/pnfs_osd_xdr.h>
-#include "../pnfs.h"
-
-/*
- * per-inode layout
- */
-struct objlayout {
-       struct pnfs_layout_hdr pnfs_layout;
-
-        /* for layout_commit */
-       enum osd_delta_space_valid_enum {
-               OBJ_DSU_INIT = 0,
-               OBJ_DSU_VALID,
-               OBJ_DSU_INVALID,
-       } delta_space_valid;
-       s64 delta_space_used;  /* consumed by write ops */
-
-        /* for layout_return */
-       spinlock_t lock;
-       struct list_head err_list;
-};
-
-static inline struct objlayout *
-OBJLAYOUT(struct pnfs_layout_hdr *lo)
-{
-       return container_of(lo, struct objlayout, pnfs_layout);
-}
-
-/*
- * per-I/O operation state
- * embedded in objects provider io_state data structure
- */
-struct objlayout_io_res {
-       struct objlayout *objlay;
-
-       void *rpcdata;
-       int status;             /* res */
-       int committed;          /* res */
-
-       /* Error reporting (layout_return) */
-       struct list_head err_list;
-       unsigned num_comps;
-       /* Pointer to array of error descriptors of size num_comps.
-        * It should contain as many entries as devices in the osd_layout
-        * that participate in the I/O. It is up to the io_engine to allocate
-        * needed space and set num_comps.
-        */
-       struct pnfs_osd_ioerr *ioerrs;
-};
-
-static inline
-void objlayout_init_ioerrs(struct objlayout_io_res *oir, unsigned num_comps,
-                       struct pnfs_osd_ioerr *ioerrs, void *rpcdata,
-                       struct pnfs_layout_hdr *pnfs_layout_type)
-{
-       oir->objlay = OBJLAYOUT(pnfs_layout_type);
-       oir->rpcdata = rpcdata;
-       INIT_LIST_HEAD(&oir->err_list);
-       oir->num_comps = num_comps;
-       oir->ioerrs = ioerrs;
-}
-
-/*
- * Raid engine I/O API
- */
-extern int objio_alloc_lseg(struct pnfs_layout_segment **outp,
-       struct pnfs_layout_hdr *pnfslay,
-       struct pnfs_layout_range *range,
-       struct xdr_stream *xdr,
-       gfp_t gfp_flags);
-extern void objio_free_lseg(struct pnfs_layout_segment *lseg);
-
-/* objio_free_result will free these @oir structs received from
- * objlayout_{read,write}_done
- */
-extern void objio_free_result(struct objlayout_io_res *oir);
-
-extern int objio_read_pagelist(struct nfs_pgio_header *rdata);
-extern int objio_write_pagelist(struct nfs_pgio_header *wdata, int how);
-
-/*
- * callback API
- */
-extern void objlayout_io_set_result(struct objlayout_io_res *oir,
-                       unsigned index, struct pnfs_osd_objid *pooid,
-                       int osd_error, u64 offset, u64 length, bool is_write);
-
-static inline void
-objlayout_add_delta_space_used(struct objlayout *objlay, s64 space_used)
-{
-       /* If one of the I/Os errored out and the delta_space_used was
-        * invalid we render the complete report as invalid. Protocol mandate
-        * the DSU be accurate or not reported.
-        */
-       spin_lock(&objlay->lock);
-       if (objlay->delta_space_valid != OBJ_DSU_INVALID) {
-               objlay->delta_space_valid = OBJ_DSU_VALID;
-               objlay->delta_space_used += space_used;
-       }
-       spin_unlock(&objlay->lock);
-}
-
-extern void objlayout_read_done(struct objlayout_io_res *oir,
-                               ssize_t status, bool sync);
-extern void objlayout_write_done(struct objlayout_io_res *oir,
-                                ssize_t status, bool sync);
-
-/*
- * exported generic objects function vectors
- */
-
-extern struct pnfs_layout_hdr *objlayout_alloc_layout_hdr(struct inode *, gfp_t gfp_flags);
-extern void objlayout_free_layout_hdr(struct pnfs_layout_hdr *);
-
-extern struct pnfs_layout_segment *objlayout_alloc_lseg(
-       struct pnfs_layout_hdr *,
-       struct nfs4_layoutget_res *,
-       gfp_t gfp_flags);
-extern void objlayout_free_lseg(struct pnfs_layout_segment *);
-
-extern enum pnfs_try_status objlayout_read_pagelist(
-       struct nfs_pgio_header *);
-
-extern enum pnfs_try_status objlayout_write_pagelist(
-       struct nfs_pgio_header *,
-       int how);
-
-extern void objlayout_encode_layoutcommit(
-       struct pnfs_layout_hdr *,
-       struct xdr_stream *,
-       const struct nfs4_layoutcommit_args *);
-
-extern void objlayout_encode_layoutreturn(
-       struct xdr_stream *,
-       const struct nfs4_layoutreturn_args *);
-
-extern int objlayout_autologin(struct pnfs_osd_deviceaddr *deviceaddr);
-
-#endif /* _OBJLAYOUT_H */
diff --git a/fs/nfs/objlayout/pnfs_osd_xdr_cli.c b/fs/nfs/objlayout/pnfs_osd_xdr_cli.c
deleted file mode 100644 (file)
index f093c7e..0000000
+++ /dev/null
@@ -1,415 +0,0 @@
-/*
- *  Object-Based pNFS Layout XDR layer
- *
- *  Copyright (C) 2007 Panasas Inc. [year of first publication]
- *  All rights reserved.
- *
- *  Benny Halevy <bhalevy@panasas.com>
- *  Boaz Harrosh <ooo@electrozaur.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License version 2
- *  See the file COPYING included with this distribution for more details.
- *
- *  Redistribution and use in source and binary forms, with or without
- *  modification, are permitted provided that the following conditions
- *  are met:
- *
- *  1. Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- *  2. Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- *  3. Neither the name of the Panasas company nor the names of its
- *     contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
- *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
- *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <linux/pnfs_osd_xdr.h>
-
-#define NFSDBG_FACILITY         NFSDBG_PNFS_LD
-
-/*
- * The following implementation is based on RFC5664
- */
-
-/*
- * struct pnfs_osd_objid {
- *     struct nfs4_deviceid    oid_device_id;
- *     u64                     oid_partition_id;
- *     u64                     oid_object_id;
- * }; // xdr size 32 bytes
- */
-static __be32 *
-_osd_xdr_decode_objid(__be32 *p, struct pnfs_osd_objid *objid)
-{
-       p = xdr_decode_opaque_fixed(p, objid->oid_device_id.data,
-                                   sizeof(objid->oid_device_id.data));
-
-       p = xdr_decode_hyper(p, &objid->oid_partition_id);
-       p = xdr_decode_hyper(p, &objid->oid_object_id);
-       return p;
-}
-/*
- * struct pnfs_osd_opaque_cred {
- *     u32 cred_len;
- *     void *cred;
- * }; // xdr size [variable]
- * The return pointers are from the xdr buffer
- */
-static int
-_osd_xdr_decode_opaque_cred(struct pnfs_osd_opaque_cred *opaque_cred,
-                           struct xdr_stream *xdr)
-{
-       __be32 *p = xdr_inline_decode(xdr, 1);
-
-       if (!p)
-               return -EINVAL;
-
-       opaque_cred->cred_len = be32_to_cpu(*p++);
-
-       p = xdr_inline_decode(xdr, opaque_cred->cred_len);
-       if (!p)
-               return -EINVAL;
-
-       opaque_cred->cred = p;
-       return 0;
-}
-
-/*
- * struct pnfs_osd_object_cred {
- *     struct pnfs_osd_objid           oc_object_id;
- *     u32                             oc_osd_version;
- *     u32                             oc_cap_key_sec;
- *     struct pnfs_osd_opaque_cred     oc_cap_key
- *     struct pnfs_osd_opaque_cred     oc_cap;
- * }; // xdr size 32 + 4 + 4 + [variable] + [variable]
- */
-static int
-_osd_xdr_decode_object_cred(struct pnfs_osd_object_cred *comp,
-                           struct xdr_stream *xdr)
-{
-       __be32 *p = xdr_inline_decode(xdr, 32 + 4 + 4);
-       int ret;
-
-       if (!p)
-               return -EIO;
-
-       p = _osd_xdr_decode_objid(p, &comp->oc_object_id);
-       comp->oc_osd_version = be32_to_cpup(p++);
-       comp->oc_cap_key_sec = be32_to_cpup(p);
-
-       ret = _osd_xdr_decode_opaque_cred(&comp->oc_cap_key, xdr);
-       if (unlikely(ret))
-               return ret;
-
-       ret = _osd_xdr_decode_opaque_cred(&comp->oc_cap, xdr);
-       return ret;
-}
-
-/*
- * struct pnfs_osd_data_map {
- *     u32     odm_num_comps;
- *     u64     odm_stripe_unit;
- *     u32     odm_group_width;
- *     u32     odm_group_depth;
- *     u32     odm_mirror_cnt;
- *     u32     odm_raid_algorithm;
- * }; // xdr size 4 + 8 + 4 + 4 + 4 + 4
- */
-static inline int
-_osd_data_map_xdr_sz(void)
-{
-       return 4 + 8 + 4 + 4 + 4 + 4;
-}
-
-static __be32 *
-_osd_xdr_decode_data_map(__be32 *p, struct pnfs_osd_data_map *data_map)
-{
-       data_map->odm_num_comps = be32_to_cpup(p++);
-       p = xdr_decode_hyper(p, &data_map->odm_stripe_unit);
-       data_map->odm_group_width = be32_to_cpup(p++);
-       data_map->odm_group_depth = be32_to_cpup(p++);
-       data_map->odm_mirror_cnt = be32_to_cpup(p++);
-       data_map->odm_raid_algorithm = be32_to_cpup(p++);
-       dprintk("%s: odm_num_comps=%u odm_stripe_unit=%llu odm_group_width=%u "
-               "odm_group_depth=%u odm_mirror_cnt=%u odm_raid_algorithm=%u\n",
-               __func__,
-               data_map->odm_num_comps,
-               (unsigned long long)data_map->odm_stripe_unit,
-               data_map->odm_group_width,
-               data_map->odm_group_depth,
-               data_map->odm_mirror_cnt,
-               data_map->odm_raid_algorithm);
-       return p;
-}
-
-int pnfs_osd_xdr_decode_layout_map(struct pnfs_osd_layout *layout,
-       struct pnfs_osd_xdr_decode_layout_iter *iter, struct xdr_stream *xdr)
-{
-       __be32 *p;
-
-       memset(iter, 0, sizeof(*iter));
-
-       p = xdr_inline_decode(xdr, _osd_data_map_xdr_sz() + 4 + 4);
-       if (unlikely(!p))
-               return -EINVAL;
-
-       p = _osd_xdr_decode_data_map(p, &layout->olo_map);
-       layout->olo_comps_index = be32_to_cpup(p++);
-       layout->olo_num_comps = be32_to_cpup(p++);
-       dprintk("%s: olo_comps_index=%d olo_num_comps=%d\n", __func__,
-               layout->olo_comps_index, layout->olo_num_comps);
-
-       iter->total_comps = layout->olo_num_comps;
-       return 0;
-}
-
-bool pnfs_osd_xdr_decode_layout_comp(struct pnfs_osd_object_cred *comp,
-       struct pnfs_osd_xdr_decode_layout_iter *iter, struct xdr_stream *xdr,
-       int *err)
-{
-       BUG_ON(iter->decoded_comps > iter->total_comps);
-       if (iter->decoded_comps == iter->total_comps)
-               return false;
-
-       *err = _osd_xdr_decode_object_cred(comp, xdr);
-       if (unlikely(*err)) {
-               dprintk("%s: _osd_xdr_decode_object_cred=>%d decoded_comps=%d "
-                       "total_comps=%d\n", __func__, *err,
-                       iter->decoded_comps, iter->total_comps);
-               return false; /* stop the loop */
-       }
-       dprintk("%s: dev(%llx:%llx) par=0x%llx obj=0x%llx "
-               "key_len=%u cap_len=%u\n",
-               __func__,
-               _DEVID_LO(&comp->oc_object_id.oid_device_id),
-               _DEVID_HI(&comp->oc_object_id.oid_device_id),
-               comp->oc_object_id.oid_partition_id,
-               comp->oc_object_id.oid_object_id,
-               comp->oc_cap_key.cred_len, comp->oc_cap.cred_len);
-
-       iter->decoded_comps++;
-       return true;
-}
-
-/*
- * Get Device Information Decoding
- *
- * Note: since Device Information is currently done synchronously, all
- *       variable strings fields are left inside the rpc buffer and are only
- *       pointed to by the pnfs_osd_deviceaddr members. So the read buffer
- *       should not be freed while the returned information is in use.
- */
-/*
- *struct nfs4_string {
- *     unsigned int len;
- *     char *data;
- *}; // size [variable]
- * NOTE: Returned string points to inside the XDR buffer
- */
-static __be32 *
-__read_u8_opaque(__be32 *p, struct nfs4_string *str)
-{
-       str->len = be32_to_cpup(p++);
-       str->data = (char *)p;
-
-       p += XDR_QUADLEN(str->len);
-       return p;
-}
-
-/*
- * struct pnfs_osd_targetid {
- *     u32                     oti_type;
- *     struct nfs4_string      oti_scsi_device_id;
- * };// size 4 + [variable]
- */
-static __be32 *
-__read_targetid(__be32 *p, struct pnfs_osd_targetid* targetid)
-{
-       u32 oti_type;
-
-       oti_type = be32_to_cpup(p++);
-       targetid->oti_type = oti_type;
-
-       switch (oti_type) {
-       case OBJ_TARGET_SCSI_NAME:
-       case OBJ_TARGET_SCSI_DEVICE_ID:
-               p = __read_u8_opaque(p, &targetid->oti_scsi_device_id);
-       }
-
-       return p;
-}
-
-/*
- * struct pnfs_osd_net_addr {
- *     struct nfs4_string      r_netid;
- *     struct nfs4_string      r_addr;
- * };
- */
-static __be32 *
-__read_net_addr(__be32 *p, struct pnfs_osd_net_addr* netaddr)
-{
-       p = __read_u8_opaque(p, &netaddr->r_netid);
-       p = __read_u8_opaque(p, &netaddr->r_addr);
-
-       return p;
-}
-
-/*
- * struct pnfs_osd_targetaddr {
- *     u32                             ota_available;
- *     struct pnfs_osd_net_addr        ota_netaddr;
- * };
- */
-static __be32 *
-__read_targetaddr(__be32 *p, struct pnfs_osd_targetaddr *targetaddr)
-{
-       u32 ota_available;
-
-       ota_available = be32_to_cpup(p++);
-       targetaddr->ota_available = ota_available;
-
-       if (ota_available)
-               p = __read_net_addr(p, &targetaddr->ota_netaddr);
-
-
-       return p;
-}
-
-/*
- * struct pnfs_osd_deviceaddr {
- *     struct pnfs_osd_targetid        oda_targetid;
- *     struct pnfs_osd_targetaddr      oda_targetaddr;
- *     u8                              oda_lun[8];
- *     struct nfs4_string              oda_systemid;
- *     struct pnfs_osd_object_cred     oda_root_obj_cred;
- *     struct nfs4_string              oda_osdname;
- * };
- */
-
-/* We need this version for the pnfs_osd_xdr_decode_deviceaddr which does
- * not have an xdr_stream
- */
-static __be32 *
-__read_opaque_cred(__be32 *p,
-                             struct pnfs_osd_opaque_cred *opaque_cred)
-{
-       opaque_cred->cred_len = be32_to_cpu(*p++);
-       opaque_cred->cred = p;
-       return p + XDR_QUADLEN(opaque_cred->cred_len);
-}
-
-static __be32 *
-__read_object_cred(__be32 *p, struct pnfs_osd_object_cred *comp)
-{
-       p = _osd_xdr_decode_objid(p, &comp->oc_object_id);
-       comp->oc_osd_version = be32_to_cpup(p++);
-       comp->oc_cap_key_sec = be32_to_cpup(p++);
-
-       p = __read_opaque_cred(p, &comp->oc_cap_key);
-       p = __read_opaque_cred(p, &comp->oc_cap);
-       return p;
-}
-
-void pnfs_osd_xdr_decode_deviceaddr(
-       struct pnfs_osd_deviceaddr *deviceaddr, __be32 *p)
-{
-       p = __read_targetid(p, &deviceaddr->oda_targetid);
-
-       p = __read_targetaddr(p, &deviceaddr->oda_targetaddr);
-
-       p = xdr_decode_opaque_fixed(p, deviceaddr->oda_lun,
-                                   sizeof(deviceaddr->oda_lun));
-
-       p = __read_u8_opaque(p, &deviceaddr->oda_systemid);
-
-       p = __read_object_cred(p, &deviceaddr->oda_root_obj_cred);
-
-       p = __read_u8_opaque(p, &deviceaddr->oda_osdname);
-
-       /* libosd likes this terminated in dbg. It's last, so no problems */
-       deviceaddr->oda_osdname.data[deviceaddr->oda_osdname.len] = 0;
-}
-
-/*
- * struct pnfs_osd_layoutupdate {
- *     u32     dsu_valid;
- *     s64     dsu_delta;
- *     u32     olu_ioerr_flag;
- * }; xdr size 4 + 8 + 4
- */
-int
-pnfs_osd_xdr_encode_layoutupdate(struct xdr_stream *xdr,
-                                struct pnfs_osd_layoutupdate *lou)
-{
-       __be32 *p = xdr_reserve_space(xdr,  4 + 8 + 4);
-
-       if (!p)
-               return -E2BIG;
-
-       *p++ = cpu_to_be32(lou->dsu_valid);
-       if (lou->dsu_valid)
-               p = xdr_encode_hyper(p, lou->dsu_delta);
-       *p++ = cpu_to_be32(lou->olu_ioerr_flag);
-       return 0;
-}
-
-/*
- * struct pnfs_osd_objid {
- *     struct nfs4_deviceid    oid_device_id;
- *     u64                     oid_partition_id;
- *     u64                     oid_object_id;
- * }; // xdr size 32 bytes
- */
-static inline __be32 *
-pnfs_osd_xdr_encode_objid(__be32 *p, struct pnfs_osd_objid *object_id)
-{
-       p = xdr_encode_opaque_fixed(p, &object_id->oid_device_id.data,
-                                   sizeof(object_id->oid_device_id.data));
-       p = xdr_encode_hyper(p, object_id->oid_partition_id);
-       p = xdr_encode_hyper(p, object_id->oid_object_id);
-
-       return p;
-}
-
-/*
- * struct pnfs_osd_ioerr {
- *     struct pnfs_osd_objid   oer_component;
- *     u64                     oer_comp_offset;
- *     u64                     oer_comp_length;
- *     u32                     oer_iswrite;
- *     u32                     oer_errno;
- * }; // xdr size 32 + 24 bytes
- */
-void pnfs_osd_xdr_encode_ioerr(__be32 *p, struct pnfs_osd_ioerr *ioerr)
-{
-       p = pnfs_osd_xdr_encode_objid(p, &ioerr->oer_component);
-       p = xdr_encode_hyper(p, ioerr->oer_comp_offset);
-       p = xdr_encode_hyper(p, ioerr->oer_comp_length);
-       *p++ = cpu_to_be32(ioerr->oer_iswrite);
-       *p   = cpu_to_be32(ioerr->oer_errno);
-}
-
-__be32 *pnfs_osd_xdr_ioerr_reserve_space(struct xdr_stream *xdr)
-{
-       __be32 *p;
-
-       p = xdr_reserve_space(xdr, 32 + 24);
-       if (unlikely(!p))
-               dprintk("%s: out of xdr space\n", __func__);
-
-       return p;
-}
index 6e629b856a00f2ebe52b4ba6badb356d49f380e6..ad92b401326c69a154b514b11764a2bc4a04a1cb 100644 (file)
 static struct kmem_cache *nfs_page_cachep;
 static const struct rpc_call_ops nfs_pgio_common_ops;
 
-static bool nfs_pgarray_set(struct nfs_page_array *p, unsigned int pagecount)
-{
-       p->npages = pagecount;
-       if (pagecount <= ARRAY_SIZE(p->page_array))
-               p->pagevec = p->page_array;
-       else {
-               p->pagevec = kcalloc(pagecount, sizeof(struct page *), GFP_KERNEL);
-               if (!p->pagevec)
-                       p->npages = 0;
-       }
-       return p->pagevec != NULL;
-}
-
 struct nfs_pgio_mirror *
 nfs_pgio_current_mirror(struct nfs_pageio_descriptor *desc)
 {
@@ -115,6 +102,35 @@ nfs_iocounter_wait(struct nfs_lock_context *l_ctx)
                        TASK_KILLABLE);
 }
 
+/**
+ * nfs_async_iocounter_wait - wait on a rpc_waitqueue for I/O
+ * to complete
+ * @task: the rpc_task that should wait
+ * @l_ctx: nfs_lock_context with io_counter to check
+ *
+ * Returns true if there is outstanding I/O to wait on and the
+ * task has been put to sleep.
+ */
+bool
+nfs_async_iocounter_wait(struct rpc_task *task, struct nfs_lock_context *l_ctx)
+{
+       struct inode *inode = d_inode(l_ctx->open_context->dentry);
+       bool ret = false;
+
+       if (atomic_read(&l_ctx->io_count) > 0) {
+               rpc_sleep_on(&NFS_SERVER(inode)->uoc_rpcwaitq, task, NULL);
+               ret = true;
+       }
+
+       if (atomic_read(&l_ctx->io_count) == 0) {
+               rpc_wake_up_queued_task(&NFS_SERVER(inode)->uoc_rpcwaitq, task);
+               ret = false;
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(nfs_async_iocounter_wait);
+
 /*
  * nfs_page_group_lock - lock the head of the page group
  * @req - request in group that is to be locked
@@ -398,8 +414,11 @@ static void nfs_clear_request(struct nfs_page *req)
                req->wb_page = NULL;
        }
        if (l_ctx != NULL) {
-               if (atomic_dec_and_test(&l_ctx->io_count))
+               if (atomic_dec_and_test(&l_ctx->io_count)) {
                        wake_up_atomic_t(&l_ctx->io_count);
+                       if (test_bit(NFS_CONTEXT_UNLOCK, &ctx->flags))
+                               rpc_wake_up(&NFS_SERVER(d_inode(ctx->dentry))->uoc_rpcwaitq);
+               }
                nfs_put_lock_context(l_ctx);
                req->wb_lock_context = NULL;
        }
@@ -677,7 +696,8 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
                     const struct nfs_pgio_completion_ops *compl_ops,
                     const struct nfs_rw_ops *rw_ops,
                     size_t bsize,
-                    int io_flags)
+                    int io_flags,
+                    gfp_t gfp_flags)
 {
        struct nfs_pgio_mirror *new;
        int i;
@@ -701,7 +721,7 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
                /* until we have a request, we don't have an lseg and no
                 * idea how many mirrors there will be */
                new = kcalloc(NFS_PAGEIO_DESCRIPTOR_MIRROR_MAX,
-                             sizeof(struct nfs_pgio_mirror), GFP_KERNEL);
+                             sizeof(struct nfs_pgio_mirror), gfp_flags);
                desc->pg_mirrors_dynamic = new;
                desc->pg_mirrors = new;
 
@@ -754,13 +774,24 @@ int nfs_generic_pgio(struct nfs_pageio_descriptor *desc,
                                *last_page;
        struct list_head *head = &mirror->pg_list;
        struct nfs_commit_info cinfo;
+       struct nfs_page_array *pg_array = &hdr->page_array;
        unsigned int pagecount, pageused;
+       gfp_t gfp_flags = GFP_KERNEL;
 
        pagecount = nfs_page_array_len(mirror->pg_base, mirror->pg_count);
-       if (!nfs_pgarray_set(&hdr->page_array, pagecount)) {
-               nfs_pgio_error(hdr);
-               desc->pg_error = -ENOMEM;
-               return desc->pg_error;
+
+       if (pagecount <= ARRAY_SIZE(pg_array->page_array))
+               pg_array->pagevec = pg_array->page_array;
+       else {
+               if (hdr->rw_mode == FMODE_WRITE)
+                       gfp_flags = GFP_NOIO;
+               pg_array->pagevec = kcalloc(pagecount, sizeof(struct page *), gfp_flags);
+               if (!pg_array->pagevec) {
+                       pg_array->npages = 0;
+                       nfs_pgio_error(hdr);
+                       desc->pg_error = -ENOMEM;
+                       return desc->pg_error;
+               }
        }
 
        nfs_init_cinfo(&cinfo, desc->pg_inode, desc->pg_dreq);
@@ -1256,8 +1287,10 @@ void nfs_pageio_cond_complete(struct nfs_pageio_descriptor *desc, pgoff_t index)
                mirror = &desc->pg_mirrors[midx];
                if (!list_empty(&mirror->pg_list)) {
                        prev = nfs_list_entry(mirror->pg_list.prev);
-                       if (index != prev->wb_index + 1)
-                               nfs_pageio_complete_mirror(desc, midx);
+                       if (index != prev->wb_index + 1) {
+                               nfs_pageio_complete(desc);
+                               break;
+                       }
                }
        }
 }
index dd042498ce7c67df24b4919c2e98dc8f48db13ca..adc6ec28d4b59d3181c76ca8f33a9fed25d68ce9 100644 (file)
@@ -322,9 +322,15 @@ pnfs_set_plh_return_info(struct pnfs_layout_hdr *lo, enum pnfs_iomode iomode,
 static void
 pnfs_clear_layoutreturn_info(struct pnfs_layout_hdr *lo)
 {
+       struct pnfs_layout_segment *lseg;
        lo->plh_return_iomode = 0;
        lo->plh_return_seq = 0;
        clear_bit(NFS_LAYOUT_RETURN_REQUESTED, &lo->plh_flags);
+       list_for_each_entry(lseg, &lo->plh_segs, pls_list) {
+               if (!test_bit(NFS_LSEG_LAYOUTRETURN, &lseg->pls_flags))
+                       continue;
+               pnfs_set_plh_return_info(lo, lseg->pls_range.iomode, 0);
+       }
 }
 
 static void pnfs_clear_layoutreturn_waitbit(struct pnfs_layout_hdr *lo)
@@ -367,9 +373,9 @@ pnfs_mark_layout_stateid_invalid(struct pnfs_layout_hdr *lo,
        struct pnfs_layout_segment *lseg, *next;
 
        set_bit(NFS_LAYOUT_INVALID_STID, &lo->plh_flags);
-       pnfs_clear_layoutreturn_info(lo);
        list_for_each_entry_safe(lseg, next, &lo->plh_segs, pls_list)
                pnfs_clear_lseg_state(lseg, lseg_list);
+       pnfs_clear_layoutreturn_info(lo);
        pnfs_free_returned_lsegs(lo, lseg_list, &range, 0);
        if (test_bit(NFS_LAYOUT_RETURN, &lo->plh_flags) &&
            !test_and_set_bit(NFS_LAYOUT_RETURN_LOCK, &lo->plh_flags))
@@ -563,7 +569,6 @@ pnfs_put_lseg_locked(struct pnfs_layout_segment *lseg)
                }
        }
 }
-EXPORT_SYMBOL_GPL(pnfs_put_lseg_locked);
 
 /*
  * is l2 fully contained in l1?
@@ -728,6 +733,7 @@ pnfs_destroy_layout(struct nfs_inode *nfsi)
                pnfs_layout_clear_fail_bit(lo, NFS_LAYOUT_RW_FAILED);
                spin_unlock(&nfsi->vfs_inode.i_lock);
                pnfs_free_lseg_list(&tmp_list);
+               nfs_commit_inode(&nfsi->vfs_inode, 0);
                pnfs_put_layout_hdr(lo);
        } else
                spin_unlock(&nfsi->vfs_inode.i_lock);
@@ -1209,7 +1215,6 @@ out:
        dprintk("<-- %s status: %d\n", __func__, status);
        return status;
 }
-EXPORT_SYMBOL_GPL(_pnfs_return_layout);
 
 int
 pnfs_commit_and_return_layout(struct inode *inode)
@@ -1991,6 +1996,8 @@ out_forget:
        spin_unlock(&ino->i_lock);
        lseg->pls_layout = lo;
        NFS_SERVER(ino)->pnfs_curr_ld->free_lseg(lseg);
+       if (!pnfs_layout_is_valid(lo))
+               nfs_commit_inode(ino, 0);
        return ERR_PTR(-EAGAIN);
 }
 
@@ -2051,9 +2058,11 @@ void pnfs_error_mark_layout_for_return(struct inode *inode,
        bool return_now = false;
 
        spin_lock(&inode->i_lock);
+       if (!pnfs_layout_is_valid(lo)) {
+               spin_unlock(&inode->i_lock);
+               return;
+       }
        pnfs_set_plh_return_info(lo, range.iomode, 0);
-       /* Block LAYOUTGET */
-       set_bit(NFS_LAYOUT_RETURN, &lo->plh_flags);
        /*
         * mark all matching lsegs so that we are sure to have no live
         * segments at hand when sending layoutreturn. See pnfs_put_lseg()
@@ -2074,11 +2083,23 @@ void pnfs_error_mark_layout_for_return(struct inode *inode,
 }
 EXPORT_SYMBOL_GPL(pnfs_error_mark_layout_for_return);
 
+void
+pnfs_generic_pg_check_layout(struct nfs_pageio_descriptor *pgio)
+{
+       if (pgio->pg_lseg == NULL ||
+           test_bit(NFS_LSEG_VALID, &pgio->pg_lseg->pls_flags))
+               return;
+       pnfs_put_lseg(pgio->pg_lseg);
+       pgio->pg_lseg = NULL;
+}
+EXPORT_SYMBOL_GPL(pnfs_generic_pg_check_layout);
+
 void
 pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *pgio, struct nfs_page *req)
 {
        u64 rd_size = req->wb_bytes;
 
+       pnfs_generic_pg_check_layout(pgio);
        if (pgio->pg_lseg == NULL) {
                if (pgio->pg_dreq == NULL)
                        rd_size = i_size_read(pgio->pg_inode) - req_offset(req);
@@ -2109,6 +2130,7 @@ void
 pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio,
                           struct nfs_page *req, u64 wb_size)
 {
+       pnfs_generic_pg_check_layout(pgio);
        if (pgio->pg_lseg == NULL) {
                pgio->pg_lseg = pnfs_update_layout(pgio->pg_inode,
                                                   req->wb_context,
@@ -2277,8 +2299,20 @@ pnfs_do_write(struct nfs_pageio_descriptor *desc,
        enum pnfs_try_status trypnfs;
 
        trypnfs = pnfs_try_to_write_data(hdr, call_ops, lseg, how);
-       if (trypnfs == PNFS_NOT_ATTEMPTED)
+       switch (trypnfs) {
+       case PNFS_NOT_ATTEMPTED:
                pnfs_write_through_mds(desc, hdr);
+       case PNFS_ATTEMPTED:
+               break;
+       case PNFS_TRY_AGAIN:
+               /* cleanup hdr and prepare to redo pnfs */
+               if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) {
+                       struct nfs_pgio_mirror *mirror = nfs_pgio_current_mirror(desc);
+                       list_splice_init(&hdr->pages, &mirror->pg_list);
+                       mirror->pg_recoalesce = 1;
+               }
+               hdr->mds_ops->rpc_release(hdr);
+       }
 }
 
 static void pnfs_writehdr_free(struct nfs_pgio_header *hdr)
@@ -2408,10 +2442,20 @@ pnfs_do_read(struct nfs_pageio_descriptor *desc, struct nfs_pgio_header *hdr)
        enum pnfs_try_status trypnfs;
 
        trypnfs = pnfs_try_to_read_data(hdr, call_ops, lseg);
-       if (trypnfs == PNFS_TRY_AGAIN)
-               pnfs_read_resend_pnfs(hdr);
-       if (trypnfs == PNFS_NOT_ATTEMPTED || hdr->task.tk_status)
+       switch (trypnfs) {
+       case PNFS_NOT_ATTEMPTED:
                pnfs_read_through_mds(desc, hdr);
+       case PNFS_ATTEMPTED:
+               break;
+       case PNFS_TRY_AGAIN:
+               /* cleanup hdr and prepare to redo pnfs */
+               if (!test_and_set_bit(NFS_IOHDR_REDO, &hdr->flags)) {
+                       struct nfs_pgio_mirror *mirror = nfs_pgio_current_mirror(desc);
+                       list_splice_init(&hdr->pages, &mirror->pg_list);
+                       mirror->pg_recoalesce = 1;
+               }
+               hdr->mds_ops->rpc_release(hdr);
+       }
 }
 
 static void pnfs_readhdr_free(struct nfs_pgio_header *hdr)
index 590e1e35781f0b737b5b277d76ab56092f8e3f3b..2d05b756a8d6504e79796d71eb5471a578d9ef5a 100644 (file)
@@ -173,14 +173,9 @@ struct pnfs_layoutdriver_type {
                        gfp_t gfp_flags);
 
        int (*prepare_layoutreturn) (struct nfs4_layoutreturn_args *);
-       void (*encode_layoutreturn) (struct xdr_stream *xdr,
-                                    const struct nfs4_layoutreturn_args *args);
 
        void (*cleanup_layoutcommit) (struct nfs4_layoutcommit_data *data);
        int (*prepare_layoutcommit) (struct nfs4_layoutcommit_args *args);
-       void (*encode_layoutcommit) (struct pnfs_layout_hdr *lo,
-                                    struct xdr_stream *xdr,
-                                    const struct nfs4_layoutcommit_args *args);
        int (*prepare_layoutstats) (struct nfs42_layoutstat_args *args);
 };
 
@@ -239,6 +234,7 @@ void pnfs_put_lseg_locked(struct pnfs_layout_segment *lseg);
 
 void set_pnfs_layoutdriver(struct nfs_server *, const struct nfs_fh *, struct nfs_fsinfo *);
 void unset_pnfs_layoutdriver(struct nfs_server *);
+void pnfs_generic_pg_check_layout(struct nfs_pageio_descriptor *pgio);
 void pnfs_generic_pg_init_read(struct nfs_pageio_descriptor *, struct nfs_page *);
 int pnfs_generic_pg_readpages(struct nfs_pageio_descriptor *desc);
 void pnfs_generic_pg_init_write(struct nfs_pageio_descriptor *pgio,
index 7250b95549ecc73bd1dbdae9ec909aac64f93a49..d40755a0984bbb0942e96aee388ed50fe7629a6e 100644 (file)
@@ -217,7 +217,14 @@ pnfs_generic_alloc_ds_commits(struct nfs_commit_info *cinfo,
        for (i = 0; i < fl_cinfo->nbuckets; i++, bucket++) {
                if (list_empty(&bucket->committing))
                        continue;
-               data = nfs_commitdata_alloc();
+               /*
+                * If the layout segment is invalid, then let
+                * pnfs_generic_retry_commit() clean up the bucket.
+                */
+               if (bucket->clseg && !pnfs_is_valid_lseg(bucket->clseg) &&
+                   !test_bit(NFS_LSEG_LAYOUTRETURN, &bucket->clseg->pls_flags))
+                       break;
+               data = nfs_commitdata_alloc(false);
                if (!data)
                        break;
                data->ds_commit_index = i;
@@ -283,16 +290,10 @@ pnfs_generic_commit_pagelist(struct inode *inode, struct list_head *mds_pages,
        unsigned int nreq = 0;
 
        if (!list_empty(mds_pages)) {
-               data = nfs_commitdata_alloc();
-               if (data != NULL) {
-                       data->ds_commit_index = -1;
-                       list_add(&data->pages, &list);
-                       nreq++;
-               } else {
-                       nfs_retry_commit(mds_pages, NULL, cinfo, 0);
-                       pnfs_generic_retry_commit(cinfo, 0);
-                       return -ENOMEM;
-               }
+               data = nfs_commitdata_alloc(true);
+               data->ds_commit_index = -1;
+               list_add(&data->pages, &list);
+               nreq++;
        }
 
        nreq += pnfs_generic_alloc_ds_commits(cinfo, &list);
@@ -619,7 +620,6 @@ void nfs4_pnfs_v3_ds_connect_unload(void)
                get_v3_ds_connect = NULL;
        }
 }
-EXPORT_SYMBOL_GPL(nfs4_pnfs_v3_ds_connect_unload);
 
 static int _nfs4_pnfs_v3_ds_connect(struct nfs_server *mds_srv,
                                 struct nfs4_pnfs_ds *ds,
index b7bca83039895b5692163d2a119f29c126ea5d83..9872cf676a50a7cfe945bfc5294602b4f67b5673 100644 (file)
@@ -638,7 +638,7 @@ nfs_proc_lock(struct file *filp, int cmd, struct file_lock *fl)
 {
        struct inode *inode = file_inode(filp);
 
-       return nlmclnt_proc(NFS_SERVER(inode)->nlm_host, cmd, fl);
+       return nlmclnt_proc(NFS_SERVER(inode)->nlm_host, cmd, fl, NULL);
 }
 
 /* Helper functions for NFS lock bounds checking */
index defc9233e9858c43a9438b2cf918a899b7f56afa..a8421d9dab6a125c4eb6b7ad9f074d8ce91a5a99 100644 (file)
@@ -35,7 +35,11 @@ static struct kmem_cache *nfs_rdata_cachep;
 
 static struct nfs_pgio_header *nfs_readhdr_alloc(void)
 {
-       return kmem_cache_zalloc(nfs_rdata_cachep, GFP_KERNEL);
+       struct nfs_pgio_header *p = kmem_cache_zalloc(nfs_rdata_cachep, GFP_KERNEL);
+
+       if (p)
+               p->rw_mode = FMODE_READ;
+       return p;
 }
 
 static void nfs_readhdr_free(struct nfs_pgio_header *rhdr)
@@ -64,7 +68,7 @@ void nfs_pageio_init_read(struct nfs_pageio_descriptor *pgio,
                pg_ops = server->pnfs_curr_ld->pg_read_ops;
 #endif
        nfs_pageio_init(pgio, inode, pg_ops, compl_ops, &nfs_rw_read_ops,
-                       server->rsize, 0);
+                       server->rsize, 0, GFP_KERNEL);
 }
 EXPORT_SYMBOL_GPL(nfs_pageio_init_read);
 
@@ -451,7 +455,6 @@ void nfs_destroy_readpagecache(void)
 }
 
 static const struct nfs_rw_ops nfs_rw_read_ops = {
-       .rw_mode                = FMODE_READ,
        .rw_alloc_header        = nfs_readhdr_alloc,
        .rw_free_header         = nfs_readhdr_free,
        .rw_done                = nfs_readpage_done,
index cc341fc7fd44212d508022c87e9023ba291cfc7d..db7ba542559e7def882448708bb5dc0d530a3416 100644 (file)
@@ -60,14 +60,28 @@ static mempool_t *nfs_wdata_mempool;
 static struct kmem_cache *nfs_cdata_cachep;
 static mempool_t *nfs_commit_mempool;
 
-struct nfs_commit_data *nfs_commitdata_alloc(void)
+struct nfs_commit_data *nfs_commitdata_alloc(bool never_fail)
 {
-       struct nfs_commit_data *p = mempool_alloc(nfs_commit_mempool, GFP_NOIO);
+       struct nfs_commit_data *p;
 
-       if (p) {
-               memset(p, 0, sizeof(*p));
-               INIT_LIST_HEAD(&p->pages);
+       if (never_fail)
+               p = mempool_alloc(nfs_commit_mempool, GFP_NOIO);
+       else {
+               /* It is OK to do some reclaim, not no safe to wait
+                * for anything to be returned to the pool.
+                * mempool_alloc() cannot handle that particular combination,
+                * so we need two separate attempts.
+                */
+               p = mempool_alloc(nfs_commit_mempool, GFP_NOWAIT);
+               if (!p)
+                       p = kmem_cache_alloc(nfs_cdata_cachep, GFP_NOIO |
+                                            __GFP_NOWARN | __GFP_NORETRY);
+               if (!p)
+                       return NULL;
        }
+
+       memset(p, 0, sizeof(*p));
+       INIT_LIST_HEAD(&p->pages);
        return p;
 }
 EXPORT_SYMBOL_GPL(nfs_commitdata_alloc);
@@ -82,8 +96,10 @@ static struct nfs_pgio_header *nfs_writehdr_alloc(void)
 {
        struct nfs_pgio_header *p = mempool_alloc(nfs_wdata_mempool, GFP_NOIO);
 
-       if (p)
+       if (p) {
                memset(p, 0, sizeof(*p));
+               p->rw_mode = FMODE_WRITE;
+       }
        return p;
 }
 
@@ -547,9 +563,21 @@ static void nfs_write_error_remove_page(struct nfs_page *req)
 {
        nfs_unlock_request(req);
        nfs_end_page_writeback(req);
-       nfs_release_request(req);
        generic_error_remove_page(page_file_mapping(req->wb_page),
                                  req->wb_page);
+       nfs_release_request(req);
+}
+
+static bool
+nfs_error_is_fatal_on_server(int err)
+{
+       switch (err) {
+       case 0:
+       case -ERESTARTSYS:
+       case -EINTR:
+               return false;
+       }
+       return nfs_error_is_fatal(err);
 }
 
 /*
@@ -557,8 +585,7 @@ static void nfs_write_error_remove_page(struct nfs_page *req)
  * May return an error if the user signalled nfs_wait_on_request().
  */
 static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
-                               struct page *page, bool nonblock,
-                               bool launder)
+                               struct page *page, bool nonblock)
 {
        struct nfs_page *req;
        int ret = 0;
@@ -574,19 +601,19 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
        WARN_ON_ONCE(test_bit(PG_CLEAN, &req->wb_flags));
 
        ret = 0;
+       /* If there is a fatal error that covers this write, just exit */
+       if (nfs_error_is_fatal_on_server(req->wb_context->error))
+               goto out_launder;
+
        if (!nfs_pageio_add_request(pgio, req)) {
                ret = pgio->pg_error;
                /*
-                * Remove the problematic req upon fatal errors
-                * in launder case, while other dirty pages can
-                * still be around until they get flushed.
+                * Remove the problematic req upon fatal errors on the server
                 */
                if (nfs_error_is_fatal(ret)) {
                        nfs_context_set_write_error(req->wb_context, ret);
-                       if (launder) {
-                               nfs_write_error_remove_page(req);
-                               goto out;
-                       }
+                       if (nfs_error_is_fatal_on_server(ret))
+                               goto out_launder;
                }
                nfs_redirty_request(req);
                ret = -EAGAIN;
@@ -595,16 +622,18 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
                                NFSIOS_WRITEPAGES, 1);
 out:
        return ret;
+out_launder:
+       nfs_write_error_remove_page(req);
+       return ret;
 }
 
 static int nfs_do_writepage(struct page *page, struct writeback_control *wbc,
-                           struct nfs_pageio_descriptor *pgio, bool launder)
+                           struct nfs_pageio_descriptor *pgio)
 {
        int ret;
 
        nfs_pageio_cond_complete(pgio, page_index(page));
-       ret = nfs_page_async_flush(pgio, page, wbc->sync_mode == WB_SYNC_NONE,
-                                  launder);
+       ret = nfs_page_async_flush(pgio, page, wbc->sync_mode == WB_SYNC_NONE);
        if (ret == -EAGAIN) {
                redirty_page_for_writepage(wbc, page);
                ret = 0;
@@ -616,8 +645,7 @@ static int nfs_do_writepage(struct page *page, struct writeback_control *wbc,
  * Write an mmapped page to the server.
  */
 static int nfs_writepage_locked(struct page *page,
-                               struct writeback_control *wbc,
-                               bool launder)
+                               struct writeback_control *wbc)
 {
        struct nfs_pageio_descriptor pgio;
        struct inode *inode = page_file_mapping(page)->host;
@@ -626,7 +654,7 @@ static int nfs_writepage_locked(struct page *page,
        nfs_inc_stats(inode, NFSIOS_VFSWRITEPAGE);
        nfs_pageio_init_write(&pgio, inode, 0,
                                false, &nfs_async_write_completion_ops);
-       err = nfs_do_writepage(page, wbc, &pgio, launder);
+       err = nfs_do_writepage(page, wbc, &pgio);
        nfs_pageio_complete(&pgio);
        if (err < 0)
                return err;
@@ -639,7 +667,7 @@ int nfs_writepage(struct page *page, struct writeback_control *wbc)
 {
        int ret;
 
-       ret = nfs_writepage_locked(page, wbc, false);
+       ret = nfs_writepage_locked(page, wbc);
        unlock_page(page);
        return ret;
 }
@@ -648,7 +676,7 @@ static int nfs_writepages_callback(struct page *page, struct writeback_control *
 {
        int ret;
 
-       ret = nfs_do_writepage(page, wbc, data, false);
+       ret = nfs_do_writepage(page, wbc, data);
        unlock_page(page);
        return ret;
 }
@@ -1367,7 +1395,7 @@ void nfs_pageio_init_write(struct nfs_pageio_descriptor *pgio,
                pg_ops = server->pnfs_curr_ld->pg_write_ops;
 #endif
        nfs_pageio_init(pgio, inode, pg_ops, compl_ops, &nfs_rw_write_ops,
-                       server->wsize, ioflags);
+                       server->wsize, ioflags, GFP_NOIO);
 }
 EXPORT_SYMBOL_GPL(nfs_pageio_init_write);
 
@@ -1704,50 +1732,14 @@ nfs_commit_list(struct inode *inode, struct list_head *head, int how,
        if (list_empty(head))
                return 0;
 
-       data = nfs_commitdata_alloc();
-
-       if (!data)
-               goto out_bad;
+       data = nfs_commitdata_alloc(true);
 
        /* Set up the argument struct */
        nfs_init_commit(data, head, NULL, cinfo);
        atomic_inc(&cinfo->mds->rpcs_out);
        return nfs_initiate_commit(NFS_CLIENT(inode), data, NFS_PROTO(inode),
                                   data->mds_ops, how, 0);
- out_bad:
-       nfs_retry_commit(head, NULL, cinfo, 0);
-       return -ENOMEM;
-}
-
-int nfs_commit_file(struct file *file, struct nfs_write_verifier *verf)
-{
-       struct inode *inode = file_inode(file);
-       struct nfs_open_context *open;
-       struct nfs_commit_info cinfo;
-       struct nfs_page *req;
-       int ret;
-
-       open = get_nfs_open_context(nfs_file_open_context(file));
-       req  = nfs_create_request(open, NULL, NULL, 0, i_size_read(inode));
-       if (IS_ERR(req)) {
-               ret = PTR_ERR(req);
-               goto out_put;
-       }
-
-       nfs_init_cinfo_from_inode(&cinfo, inode);
-
-       memcpy(&req->wb_verf, verf, sizeof(struct nfs_write_verifier));
-       nfs_request_add_commit_list(req, &cinfo);
-       ret = nfs_commit_inode(inode, FLUSH_SYNC);
-       if (ret > 0)
-               ret = 0;
-
-       nfs_free_request(req);
-out_put:
-       put_nfs_open_context(open);
-       return ret;
 }
-EXPORT_SYMBOL_GPL(nfs_commit_file);
 
 /*
  * COMMIT call returned
@@ -1985,7 +1977,7 @@ int nfs_wb_page_cancel(struct inode *inode, struct page *page)
 /*
  * Write back all requests on one page - we do this before reading it.
  */
-int nfs_wb_single_page(struct inode *inode, struct page *page, bool launder)
+int nfs_wb_page(struct inode *inode, struct page *page)
 {
        loff_t range_start = page_file_offset(page);
        loff_t range_end = range_start + (loff_t)(PAGE_SIZE - 1);
@@ -2002,7 +1994,7 @@ int nfs_wb_single_page(struct inode *inode, struct page *page, bool launder)
        for (;;) {
                wait_on_page_writeback(page);
                if (clear_page_dirty_for_io(page)) {
-                       ret = nfs_writepage_locked(page, &wbc, launder);
+                       ret = nfs_writepage_locked(page, &wbc);
                        if (ret < 0)
                                goto out_error;
                        continue;
@@ -2107,7 +2099,6 @@ void nfs_destroy_writepagecache(void)
 }
 
 static const struct nfs_rw_ops nfs_rw_write_ops = {
-       .rw_mode                = FMODE_WRITE,
        .rw_alloc_header        = nfs_writehdr_alloc,
        .rw_free_header         = nfs_writehdr_free,
        .rw_done                = nfs_writeback_done,
index 452334694a5d1f37cc480e5d1cf2873c4246019d..12feac6ee2fd461a46c7b06b7a0ed0359fb4dfd1 100644 (file)
@@ -334,8 +334,11 @@ nfs3svc_decode_readargs(struct svc_rqst *rqstp, __be32 *p,
        if (!p)
                return 0;
        p = xdr_decode_hyper(p, &args->offset);
-
        args->count = ntohl(*p++);
+
+       if (!xdr_argsize_check(rqstp, p))
+               return 0;
+
        len = min(args->count, max_blocksize);
 
        /* set up the kvec */
@@ -349,7 +352,7 @@ nfs3svc_decode_readargs(struct svc_rqst *rqstp, __be32 *p,
                v++;
        }
        args->vlen = v;
-       return xdr_argsize_check(rqstp, p);
+       return 1;
 }
 
 int
@@ -541,9 +544,11 @@ nfs3svc_decode_readlinkargs(struct svc_rqst *rqstp, __be32 *p,
        p = decode_fh(p, &args->fh);
        if (!p)
                return 0;
+       if (!xdr_argsize_check(rqstp, p))
+               return 0;
        args->buffer = page_address(*(rqstp->rq_next_page++));
 
-       return xdr_argsize_check(rqstp, p);
+       return 1;
 }
 
 int
@@ -569,10 +574,14 @@ nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p,
        args->verf   = p; p += 2;
        args->dircount = ~0;
        args->count  = ntohl(*p++);
+
+       if (!xdr_argsize_check(rqstp, p))
+               return 0;
+
        args->count  = min_t(u32, args->count, PAGE_SIZE);
        args->buffer = page_address(*(rqstp->rq_next_page++));
 
-       return xdr_argsize_check(rqstp, p);
+       return 1;
 }
 
 int
@@ -590,6 +599,9 @@ nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, __be32 *p,
        args->dircount = ntohl(*p++);
        args->count    = ntohl(*p++);
 
+       if (!xdr_argsize_check(rqstp, p))
+               return 0;
+
        len = args->count = min(args->count, max_blocksize);
        while (len > 0) {
                struct page *p = *(rqstp->rq_next_page++);
@@ -597,8 +609,7 @@ nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, __be32 *p,
                        args->buffer = page_address(p);
                len -= PAGE_SIZE;
        }
-
-       return xdr_argsize_check(rqstp, p);
+       return 1;
 }
 
 int
index d86031b6ad79301c8ca0ceec9c8b991dd5db70f1..c453a1998e003d3e900407b266f1a15de5d5d94b 100644 (file)
@@ -1259,7 +1259,8 @@ nfsd4_layout_verify(struct svc_export *exp, unsigned int layout_type)
                return NULL;
        }
 
-       if (!(exp->ex_layout_types & (1 << layout_type))) {
+       if (layout_type >= LAYOUT_TYPE_MAX ||
+           !(exp->ex_layout_types & (1 << layout_type))) {
                dprintk("%s: layout type %d not supported\n",
                        __func__, layout_type);
                return NULL;
index e9ef50addddb4489534bc07f138cd8c321d9193d..22002fb75a1827f2ca08bd1dcf23a775669fdd14 100644 (file)
@@ -1912,28 +1912,15 @@ static void copy_clid(struct nfs4_client *target, struct nfs4_client *source)
        target->cl_clientid.cl_id = source->cl_clientid.cl_id; 
 }
 
-int strdup_if_nonnull(char **target, char *source)
-{
-       if (source) {
-               *target = kstrdup(source, GFP_KERNEL);
-               if (!*target)
-                       return -ENOMEM;
-       } else
-               *target = NULL;
-       return 0;
-}
-
 static int copy_cred(struct svc_cred *target, struct svc_cred *source)
 {
-       int ret;
+       target->cr_principal = kstrdup(source->cr_principal, GFP_KERNEL);
+       target->cr_raw_principal = kstrdup(source->cr_raw_principal,
+                                                               GFP_KERNEL);
+       if ((source->cr_principal && ! target->cr_principal) ||
+           (source->cr_raw_principal && ! target->cr_raw_principal))
+               return -ENOMEM;
 
-       ret = strdup_if_nonnull(&target->cr_principal, source->cr_principal);
-       if (ret)
-               return ret;
-       ret = strdup_if_nonnull(&target->cr_raw_principal,
-                                       source->cr_raw_principal);
-       if (ret)
-               return ret;
        target->cr_flavor = source->cr_flavor;
        target->cr_uid = source->cr_uid;
        target->cr_gid = source->cr_gid;
index 33017d652b1da23165ff75ef0c8abb529ac55234..26780d53a6f9412ba50cf3b3711b32d53d061723 100644 (file)
@@ -2831,9 +2831,14 @@ out_acl:
        }
 #endif /* CONFIG_NFSD_PNFS */
        if (bmval2 & FATTR4_WORD2_SUPPATTR_EXCLCREAT) {
-               status = nfsd4_encode_bitmap(xdr, NFSD_SUPPATTR_EXCLCREAT_WORD0,
-                                                 NFSD_SUPPATTR_EXCLCREAT_WORD1,
-                                                 NFSD_SUPPATTR_EXCLCREAT_WORD2);
+               u32 supp[3];
+
+               memcpy(supp, nfsd_suppattrs[minorversion], sizeof(supp));
+               supp[0] &= NFSD_SUPPATTR_EXCLCREAT_WORD0;
+               supp[1] &= NFSD_SUPPATTR_EXCLCREAT_WORD1;
+               supp[2] &= NFSD_SUPPATTR_EXCLCREAT_WORD2;
+
+               status = nfsd4_encode_bitmap(xdr, supp[0], supp[1], supp[2]);
                if (status)
                        goto out;
        }
@@ -4119,8 +4124,7 @@ nfsd4_encode_getdeviceinfo(struct nfsd4_compoundres *resp, __be32 nfserr,
                struct nfsd4_getdeviceinfo *gdev)
 {
        struct xdr_stream *xdr = &resp->xdr;
-       const struct nfsd4_layout_ops *ops =
-               nfsd4_layout_ops[gdev->gd_layout_type];
+       const struct nfsd4_layout_ops *ops;
        u32 starting_len = xdr->buf->len, needed_len;
        __be32 *p;
 
@@ -4137,6 +4141,7 @@ nfsd4_encode_getdeviceinfo(struct nfsd4_compoundres *resp, __be32 nfserr,
 
        /* If maxcount is 0 then just update notifications */
        if (gdev->gd_maxcount != 0) {
+               ops = nfsd4_layout_ops[gdev->gd_layout_type];
                nfserr = ops->encode_getdeviceinfo(xdr, gdev);
                if (nfserr) {
                        /*
@@ -4189,8 +4194,7 @@ nfsd4_encode_layoutget(struct nfsd4_compoundres *resp, __be32 nfserr,
                struct nfsd4_layoutget *lgp)
 {
        struct xdr_stream *xdr = &resp->xdr;
-       const struct nfsd4_layout_ops *ops =
-               nfsd4_layout_ops[lgp->lg_layout_type];
+       const struct nfsd4_layout_ops *ops;
        __be32 *p;
 
        dprintk("%s: err %d\n", __func__, nfserr);
@@ -4213,6 +4217,7 @@ nfsd4_encode_layoutget(struct nfsd4_compoundres *resp, __be32 nfserr,
        *p++ = cpu_to_be32(lgp->lg_seg.iomode);
        *p++ = cpu_to_be32(lgp->lg_layout_type);
 
+       ops = nfsd4_layout_ops[lgp->lg_layout_type];
        nfserr = ops->encode_layoutget(xdr, lgp);
 out:
        kfree(lgp->lg_content);
index 8bf8f667a8cf2fe8359f74b41497bc9436ca0efb..6493df6b1bd5f192646d1f63b2230af840833651 100644 (file)
@@ -1146,7 +1146,7 @@ static ssize_t write_v4_end_grace(struct file *file, char *buf, size_t size)
 
 static int nfsd_fill_super(struct super_block * sb, void * data, int silent)
 {
-       static struct tree_descr nfsd_files[] = {
+       static const struct tree_descr nfsd_files[] = {
                [NFSD_List] = {"exports", &exports_nfsd_operations, S_IRUGO},
                [NFSD_Export_features] = {"export_features",
                                        &export_features_operations, S_IRUGO},
index de07ff625777820fefc98bfa56adea81962e8135..6a4947a3f4fa82be4118e4ed538a171118f4baa8 100644 (file)
@@ -257,6 +257,9 @@ nfssvc_decode_readargs(struct svc_rqst *rqstp, __be32 *p,
        len = args->count     = ntohl(*p++);
        p++; /* totalcount - unused */
 
+       if (!xdr_argsize_check(rqstp, p))
+               return 0;
+
        len = min_t(unsigned int, len, NFSSVC_MAXBLKSIZE_V2);
 
        /* set up somewhere to store response.
@@ -272,7 +275,7 @@ nfssvc_decode_readargs(struct svc_rqst *rqstp, __be32 *p,
                v++;
        }
        args->vlen = v;
-       return xdr_argsize_check(rqstp, p);
+       return 1;
 }
 
 int
@@ -362,9 +365,11 @@ nfssvc_decode_readlinkargs(struct svc_rqst *rqstp, __be32 *p, struct nfsd_readli
        p = decode_fh(p, &args->fh);
        if (!p)
                return 0;
+       if (!xdr_argsize_check(rqstp, p))
+               return 0;
        args->buffer = page_address(*(rqstp->rq_next_page++));
 
-       return xdr_argsize_check(rqstp, p);
+       return 1;
 }
 
 int
@@ -402,9 +407,11 @@ nfssvc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p,
        args->cookie = ntohl(*p++);
        args->count  = ntohl(*p++);
        args->count  = min_t(u32, args->count, PAGE_SIZE);
+       if (!xdr_argsize_check(rqstp, p))
+               return 0;
        args->buffer = page_address(*(rqstp->rq_next_page++));
 
-       return xdr_argsize_check(rqstp, p);
+       return 1;
 }
 
 /*
index 9aaf6ca7756998f9f872db91e7d1ef5f92351e8c..2be32955d7f27d285d0cba1dad39e88c885dc7e0 100644 (file)
@@ -94,6 +94,12 @@ nfsd_cross_mnt(struct svc_rqst *rqstp, struct dentry **dpp,
        err = follow_down(&path);
        if (err < 0)
                goto out;
+       if (path.mnt == exp->ex_path.mnt && path.dentry == dentry &&
+           nfsd_mountpoint(dentry, exp) == 2) {
+               /* This is only a mountpoint in some other namespace */
+               path_put(&path);
+               goto out;
+       }
 
        exp2 = rqst_exp_get_by_name(rqstp, &path);
        if (IS_ERR(exp2)) {
@@ -167,16 +173,26 @@ static int nfsd_lookup_parent(struct svc_rqst *rqstp, struct dentry *dparent, st
 /*
  * For nfsd purposes, we treat V4ROOT exports as though there was an
  * export at *every* directory.
+ * We return:
+ * '1' if this dentry *must* be an export point,
+ * '2' if it might be, if there is really a mount here, and
+ * '0' if there is no chance of an export point here.
  */
 int nfsd_mountpoint(struct dentry *dentry, struct svc_export *exp)
 {
-       if (d_mountpoint(dentry))
+       if (!d_inode(dentry))
+               return 0;
+       if (exp->ex_flags & NFSEXP_V4ROOT)
                return 1;
        if (nfsd4_is_junction(dentry))
                return 1;
-       if (!(exp->ex_flags & NFSEXP_V4ROOT))
-               return 0;
-       return d_inode(dentry) != NULL;
+       if (d_mountpoint(dentry))
+               /*
+                * Might only be a mountpoint in a different namespace,
+                * but we need to check.
+                */
+               return 2;
+       return 0;
 }
 
 __be32
index 323f492e0822dd3286365d5cdbe56c59ec2d5463..f3db56e83dd204279895751e8cd885f15c28b2f5 100644 (file)
--- a/fs/nsfs.c
+++ b/fs/nsfs.c
@@ -196,9 +196,11 @@ int ns_get_name(char *buf, size_t size, struct task_struct *task,
 {
        struct ns_common *ns;
        int res = -ENOENT;
+       const char *name;
        ns = ns_ops->get(task);
        if (ns) {
-               res = snprintf(buf, size, "%s:[%u]", ns_ops->name, ns->inum);
+               name = ns_ops->real_ns_name ? : ns_ops->name;
+               res = snprintf(buf, size, "%s:[%u]", name, ns->inum);
                ns_ops->put(ns);
        }
        return res;
index 4d23f729dcc6979e4d62ba9c7b3258b7adb37eb1..cd0c5be8d01247e8bab3f4e00e6f171803291881 100644 (file)
--- a/fs/open.c
+++ b/fs/open.c
@@ -193,7 +193,8 @@ static long do_sys_ftruncate(unsigned int fd, loff_t length, int small)
                goto out_putf;
 
        error = -EPERM;
-       if (IS_APPEND(inode))
+       /* Check IS_APPEND on real upper inode */
+       if (IS_APPEND(file_inode(f.file)))
                goto out_putf;
 
        sb_start_write(inode->i_sb);
@@ -459,20 +460,17 @@ out:
 SYSCALL_DEFINE1(fchdir, unsigned int, fd)
 {
        struct fd f = fdget_raw(fd);
-       struct inode *inode;
-       int error = -EBADF;
+       int error;
 
        error = -EBADF;
        if (!f.file)
                goto out;
 
-       inode = file_inode(f.file);
-
        error = -ENOTDIR;
-       if (!S_ISDIR(inode->i_mode))
+       if (!d_can_lookup(f.file->f_path.dentry))
                goto out_putf;
 
-       error = inode_permission(inode, MAY_EXEC | MAY_CHDIR);
+       error = inode_permission(file_inode(f.file), MAY_EXEC | MAY_CHDIR);
        if (!error)
                set_fs_pwd(current->fs, &f.file->f_path);
 out_putf:
@@ -900,6 +898,12 @@ static inline int build_open_flags(int flags, umode_t mode, struct open_flags *o
        int lookup_flags = 0;
        int acc_mode = ACC_MODE(flags);
 
+       /*
+        * Clear out all open flags we don't know about so that we don't report
+        * them in fcntl(F_GETFD) or similar interfaces.
+        */
+       flags &= VALID_OPEN_FLAGS;
+
        if (flags & (O_CREAT | __O_TMPFILE))
                op->mode = (mode & S_IALLUGO) | S_IFREG;
        else
index 906ea6c93260179c9c4947abe97c35750162c3e3..9008ab9fbd2ebe89d419c249455eb740c48a9eb1 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/namei.h>
 #include <linux/fdtable.h>
 #include <linux/ratelimit.h>
+#include <linux/exportfs.h>
 #include "overlayfs.h"
 #include "ovl_entry.h"
 
@@ -232,6 +233,79 @@ int ovl_set_attr(struct dentry *upperdentry, struct kstat *stat)
        return err;
 }
 
+static struct ovl_fh *ovl_encode_fh(struct dentry *lower, uuid_be *uuid)
+{
+       struct ovl_fh *fh;
+       int fh_type, fh_len, dwords;
+       void *buf;
+       int buflen = MAX_HANDLE_SZ;
+
+       buf = kmalloc(buflen, GFP_TEMPORARY);
+       if (!buf)
+               return ERR_PTR(-ENOMEM);
+
+       /*
+        * We encode a non-connectable file handle for non-dir, because we
+        * only need to find the lower inode number and we don't want to pay
+        * the price or reconnecting the dentry.
+        */
+       dwords = buflen >> 2;
+       fh_type = exportfs_encode_fh(lower, buf, &dwords, 0);
+       buflen = (dwords << 2);
+
+       fh = ERR_PTR(-EIO);
+       if (WARN_ON(fh_type < 0) ||
+           WARN_ON(buflen > MAX_HANDLE_SZ) ||
+           WARN_ON(fh_type == FILEID_INVALID))
+               goto out;
+
+       BUILD_BUG_ON(MAX_HANDLE_SZ + offsetof(struct ovl_fh, fid) > 255);
+       fh_len = offsetof(struct ovl_fh, fid) + buflen;
+       fh = kmalloc(fh_len, GFP_KERNEL);
+       if (!fh) {
+               fh = ERR_PTR(-ENOMEM);
+               goto out;
+       }
+
+       fh->version = OVL_FH_VERSION;
+       fh->magic = OVL_FH_MAGIC;
+       fh->type = fh_type;
+       fh->flags = OVL_FH_FLAG_CPU_ENDIAN;
+       fh->len = fh_len;
+       fh->uuid = *uuid;
+       memcpy(fh->fid, buf, buflen);
+
+out:
+       kfree(buf);
+       return fh;
+}
+
+static int ovl_set_origin(struct dentry *dentry, struct dentry *lower,
+                         struct dentry *upper)
+{
+       struct super_block *sb = lower->d_sb;
+       uuid_be *uuid = (uuid_be *) &sb->s_uuid;
+       const struct ovl_fh *fh = NULL;
+       int err;
+
+       /*
+        * When lower layer doesn't support export operations store a 'null' fh,
+        * so we can use the overlay.origin xattr to distignuish between a copy
+        * up and a pure upper inode.
+        */
+       if (sb->s_export_op && sb->s_export_op->fh_to_dentry &&
+           uuid_be_cmp(*uuid, NULL_UUID_BE)) {
+               fh = ovl_encode_fh(lower, uuid);
+               if (IS_ERR(fh))
+                       return PTR_ERR(fh);
+       }
+
+       err = ovl_do_setxattr(upper, OVL_XATTR_ORIGIN, fh, fh ? fh->len : 0, 0);
+       kfree(fh);
+
+       return err;
+}
+
 static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir,
                              struct dentry *dentry, struct path *lowerpath,
                              struct kstat *stat, const char *link,
@@ -316,6 +390,14 @@ static int ovl_copy_up_locked(struct dentry *workdir, struct dentry *upperdir,
        if (err)
                goto out_cleanup;
 
+       /*
+        * Store identifier of lower inode in upper inode xattr to
+        * allow lookup of the copy up origin inode.
+        */
+       err = ovl_set_origin(dentry, lowerpath->dentry, temp);
+       if (err)
+               goto out_cleanup;
+
        if (tmpfile)
                err = ovl_do_link(temp, udir, upper, true);
        else
index 6515796460dfe170fb33b109feb09c9ac0b17519..723b98b9069876d1656b74735dabcaf01484e26d 100644 (file)
@@ -138,36 +138,6 @@ static int ovl_set_opaque(struct dentry *dentry, struct dentry *upperdentry)
        return err;
 }
 
-static int ovl_dir_getattr(const struct path *path, struct kstat *stat,
-                          u32 request_mask, unsigned int flags)
-{
-       struct dentry *dentry = path->dentry;
-       int err;
-       enum ovl_path_type type;
-       struct path realpath;
-       const struct cred *old_cred;
-
-       type = ovl_path_real(dentry, &realpath);
-       old_cred = ovl_override_creds(dentry->d_sb);
-       err = vfs_getattr(&realpath, stat, request_mask, flags);
-       revert_creds(old_cred);
-       if (err)
-               return err;
-
-       stat->dev = dentry->d_sb->s_dev;
-       stat->ino = dentry->d_inode->i_ino;
-
-       /*
-        * It's probably not worth it to count subdirs to get the
-        * correct link count.  nlink=1 seems to pacify 'find' and
-        * other utilities.
-        */
-       if (OVL_TYPE_MERGE(type))
-               stat->nlink = 1;
-
-       return 0;
-}
-
 /* Common operations required to be done after creation of file on upper */
 static void ovl_instantiate(struct dentry *dentry, struct inode *inode,
                            struct dentry *newdentry, bool hardlink)
@@ -182,6 +152,9 @@ static void ovl_instantiate(struct dentry *dentry, struct inode *inode,
                inc_nlink(inode);
        }
        d_instantiate(dentry, inode);
+       /* Force lookup of new upper hardlink to find its lower */
+       if (hardlink)
+               d_drop(dentry);
 }
 
 static bool ovl_type_merge(struct dentry *dentry)
@@ -210,7 +183,7 @@ static int ovl_create_upper(struct dentry *dentry, struct inode *inode,
        if (err)
                goto out_dput;
 
-       if (ovl_type_merge(dentry->d_parent)) {
+       if (ovl_type_merge(dentry->d_parent) && d_is_dir(newdentry)) {
                /* Setting opaque here is just an optimization, allow to fail */
                ovl_set_opaque(dentry, newdentry);
        }
@@ -1070,7 +1043,7 @@ const struct inode_operations ovl_dir_inode_operations = {
        .create         = ovl_create,
        .mknod          = ovl_mknod,
        .permission     = ovl_permission,
-       .getattr        = ovl_dir_getattr,
+       .getattr        = ovl_getattr,
        .listxattr      = ovl_listxattr,
        .get_acl        = ovl_get_acl,
        .update_time    = ovl_update_time,
index f8fe6bf2036df3bd531132877101cb979c1feed0..ad9547f82da57fa4bd51eb5738cb8f02235e4455 100644 (file)
@@ -57,18 +57,78 @@ out:
        return err;
 }
 
-static int ovl_getattr(const struct path *path, struct kstat *stat,
-                      u32 request_mask, unsigned int flags)
+int ovl_getattr(const struct path *path, struct kstat *stat,
+               u32 request_mask, unsigned int flags)
 {
        struct dentry *dentry = path->dentry;
+       enum ovl_path_type type;
        struct path realpath;
        const struct cred *old_cred;
+       bool is_dir = S_ISDIR(dentry->d_inode->i_mode);
        int err;
 
-       ovl_path_real(dentry, &realpath);
+       type = ovl_path_real(dentry, &realpath);
        old_cred = ovl_override_creds(dentry->d_sb);
        err = vfs_getattr(&realpath, stat, request_mask, flags);
+       if (err)
+               goto out;
+
+       /*
+        * When all layers are on the same fs, all real inode number are
+        * unique, so we use the overlay st_dev, which is friendly to du -x.
+        *
+        * We also use st_ino of the copy up origin, if we know it.
+        * This guaranties constant st_dev/st_ino across copy up.
+        *
+        * If filesystem supports NFS export ops, this also guaranties
+        * persistent st_ino across mount cycle.
+        */
+       if (ovl_same_sb(dentry->d_sb)) {
+               if (OVL_TYPE_ORIGIN(type)) {
+                       struct kstat lowerstat;
+                       u32 lowermask = STATX_INO | (!is_dir ? STATX_NLINK : 0);
+
+                       ovl_path_lower(dentry, &realpath);
+                       err = vfs_getattr(&realpath, &lowerstat,
+                                         lowermask, flags);
+                       if (err)
+                               goto out;
+
+                       WARN_ON_ONCE(stat->dev != lowerstat.dev);
+                       /*
+                        * Lower hardlinks are broken on copy up to different
+                        * upper files, so we cannot use the lower origin st_ino
+                        * for those different files, even for the same fs case.
+                        */
+                       if (is_dir || lowerstat.nlink == 1)
+                               stat->ino = lowerstat.ino;
+               }
+               stat->dev = dentry->d_sb->s_dev;
+       } else if (is_dir) {
+               /*
+                * If not all layers are on the same fs the pair {real st_ino;
+                * overlay st_dev} is not unique, so use the non persistent
+                * overlay st_ino.
+                *
+                * Always use the overlay st_dev for directories, so 'find
+                * -xdev' will scan the entire overlay mount and won't cross the
+                * overlay mount boundaries.
+                */
+               stat->dev = dentry->d_sb->s_dev;
+               stat->ino = dentry->d_inode->i_ino;
+       }
+
+       /*
+        * It's probably not worth it to count subdirs to get the
+        * correct link count.  nlink=1 seems to pacify 'find' and
+        * other utilities.
+        */
+       if (is_dir && OVL_TYPE_MERGE(type))
+               stat->nlink = 1;
+
+out:
        revert_creds(old_cred);
+
        return err;
 }
 
@@ -303,6 +363,41 @@ static const struct inode_operations ovl_symlink_inode_operations = {
        .update_time    = ovl_update_time,
 };
 
+/*
+ * It is possible to stack overlayfs instance on top of another
+ * overlayfs instance as lower layer. We need to annonate the
+ * stackable i_mutex locks according to stack level of the super
+ * block instance. An overlayfs instance can never be in stack
+ * depth 0 (there is always a real fs below it).  An overlayfs
+ * inode lock will use the lockdep annotaion ovl_i_mutex_key[depth].
+ *
+ * For example, here is a snip from /proc/lockdep_chains after
+ * dir_iterate of nested overlayfs:
+ *
+ * [...] &ovl_i_mutex_dir_key[depth]   (stack_depth=2)
+ * [...] &ovl_i_mutex_dir_key[depth]#2 (stack_depth=1)
+ * [...] &type->i_mutex_dir_key        (stack_depth=0)
+ */
+#define OVL_MAX_NESTING FILESYSTEM_MAX_STACK_DEPTH
+
+static inline void ovl_lockdep_annotate_inode_mutex_key(struct inode *inode)
+{
+#ifdef CONFIG_LOCKDEP
+       static struct lock_class_key ovl_i_mutex_key[OVL_MAX_NESTING];
+       static struct lock_class_key ovl_i_mutex_dir_key[OVL_MAX_NESTING];
+
+       int depth = inode->i_sb->s_stack_depth - 1;
+
+       if (WARN_ON_ONCE(depth < 0 || depth >= OVL_MAX_NESTING))
+               depth = 0;
+
+       if (S_ISDIR(inode->i_mode))
+               lockdep_set_class(&inode->i_rwsem, &ovl_i_mutex_dir_key[depth]);
+       else
+               lockdep_set_class(&inode->i_rwsem, &ovl_i_mutex_key[depth]);
+#endif
+}
+
 static void ovl_fill_inode(struct inode *inode, umode_t mode, dev_t rdev)
 {
        inode->i_ino = get_next_ino();
@@ -312,6 +407,8 @@ static void ovl_fill_inode(struct inode *inode, umode_t mode, dev_t rdev)
        inode->i_acl = inode->i_default_acl = ACL_DONT_CACHE;
 #endif
 
+       ovl_lockdep_annotate_inode_mutex_key(inode);
+
        switch (mode & S_IFMT) {
        case S_IFREG:
                inode->i_op = &ovl_file_inode_operations;
index b8b077821fb03bea9d63b3bf3508039836409e1b..bad0f665a63521efde00b4c488d4ed2ba85a5b75 100644 (file)
@@ -12,6 +12,8 @@
 #include <linux/namei.h>
 #include <linux/xattr.h>
 #include <linux/ratelimit.h>
+#include <linux/mount.h>
+#include <linux/exportfs.h>
 #include "overlayfs.h"
 #include "ovl_entry.h"
 
@@ -81,6 +83,90 @@ invalid:
        goto err_free;
 }
 
+static int ovl_acceptable(void *ctx, struct dentry *dentry)
+{
+       return 1;
+}
+
+static struct dentry *ovl_get_origin(struct dentry *dentry,
+                                    struct vfsmount *mnt)
+{
+       int res;
+       struct ovl_fh *fh = NULL;
+       struct dentry *origin = NULL;
+       int bytes;
+
+       res = vfs_getxattr(dentry, OVL_XATTR_ORIGIN, NULL, 0);
+       if (res < 0) {
+               if (res == -ENODATA || res == -EOPNOTSUPP)
+                       return NULL;
+               goto fail;
+       }
+       /* Zero size value means "copied up but origin unknown" */
+       if (res == 0)
+               return NULL;
+
+       fh  = kzalloc(res, GFP_TEMPORARY);
+       if (!fh)
+               return ERR_PTR(-ENOMEM);
+
+       res = vfs_getxattr(dentry, OVL_XATTR_ORIGIN, fh, res);
+       if (res < 0)
+               goto fail;
+
+       if (res < sizeof(struct ovl_fh) || res < fh->len)
+               goto invalid;
+
+       if (fh->magic != OVL_FH_MAGIC)
+               goto invalid;
+
+       /* Treat larger version and unknown flags as "origin unknown" */
+       if (fh->version > OVL_FH_VERSION || fh->flags & ~OVL_FH_FLAG_ALL)
+               goto out;
+
+       /* Treat endianness mismatch as "origin unknown" */
+       if (!(fh->flags & OVL_FH_FLAG_ANY_ENDIAN) &&
+           (fh->flags & OVL_FH_FLAG_BIG_ENDIAN) != OVL_FH_FLAG_CPU_ENDIAN)
+               goto out;
+
+       bytes = (fh->len - offsetof(struct ovl_fh, fid));
+
+       /*
+        * Make sure that the stored uuid matches the uuid of the lower
+        * layer where file handle will be decoded.
+        */
+       if (uuid_be_cmp(fh->uuid, *(uuid_be *) &mnt->mnt_sb->s_uuid))
+               goto out;
+
+       origin = exportfs_decode_fh(mnt, (struct fid *)fh->fid,
+                                   bytes >> 2, (int)fh->type,
+                                   ovl_acceptable, NULL);
+       if (IS_ERR(origin)) {
+               /* Treat stale file handle as "origin unknown" */
+               if (origin == ERR_PTR(-ESTALE))
+                       origin = NULL;
+               goto out;
+       }
+
+       if (ovl_dentry_weird(origin) ||
+           ((d_inode(origin)->i_mode ^ d_inode(dentry)->i_mode) & S_IFMT)) {
+               dput(origin);
+               origin = NULL;
+               goto invalid;
+       }
+
+out:
+       kfree(fh);
+       return origin;
+
+fail:
+       pr_warn_ratelimited("overlayfs: failed to get origin (%i)\n", res);
+       goto out;
+invalid:
+       pr_warn_ratelimited("overlayfs: invalid origin (%*phN)\n", res, fh);
+       goto out;
+}
+
 static bool ovl_is_opaquedir(struct dentry *dentry)
 {
        int res;
@@ -192,6 +278,45 @@ static int ovl_lookup_layer(struct dentry *base, struct ovl_lookup_data *d,
        return 0;
 }
 
+
+static int ovl_check_origin(struct dentry *dentry, struct dentry *upperdentry,
+                           struct path **stackp, unsigned int *ctrp)
+{
+       struct super_block *same_sb = ovl_same_sb(dentry->d_sb);
+       struct ovl_entry *roe = dentry->d_sb->s_root->d_fsdata;
+       struct vfsmount *mnt;
+       struct dentry *origin;
+
+       if (!same_sb || !roe->numlower)
+               return 0;
+
+       /*
+       * Since all layers are on the same fs, we use the first layer for
+       * decoding the file handle.  We may get a disconnected dentry,
+       * which is fine, because we only need to hold the origin inode in
+       * cache and use its inode number.  We may even get a connected dentry,
+       * that is not under the first layer's root.  That is also fine for
+       * using it's inode number - it's the same as if we held a reference
+       * to a dentry in first layer that was moved under us.
+       */
+       mnt = roe->lowerstack[0].mnt;
+
+       origin = ovl_get_origin(upperdentry, mnt);
+       if (IS_ERR_OR_NULL(origin))
+               return PTR_ERR(origin);
+
+       BUG_ON(*stackp || *ctrp);
+       *stackp = kmalloc(sizeof(struct path), GFP_TEMPORARY);
+       if (!*stackp) {
+               dput(origin);
+               return -ENOMEM;
+       }
+       **stackp = (struct path) { .dentry = origin, .mnt = mnt };
+       *ctrp = 1;
+
+       return 0;
+}
+
 /*
  * Returns next layer in stack starting from top.
  * Returns -1 if this is the last layer.
@@ -220,6 +345,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
        const struct cred *old_cred;
        struct ovl_fs *ofs = dentry->d_sb->s_fs_info;
        struct ovl_entry *poe = dentry->d_parent->d_fsdata;
+       struct ovl_entry *roe = dentry->d_sb->s_root->d_fsdata;
        struct path *stack = NULL;
        struct dentry *upperdir, *upperdentry = NULL;
        unsigned int ctr = 0;
@@ -253,13 +379,20 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
                        err = -EREMOTE;
                        goto out;
                }
+               if (upperdentry && !d.is_dir) {
+                       BUG_ON(!d.stop || d.redirect);
+                       err = ovl_check_origin(dentry, upperdentry,
+                                              &stack, &ctr);
+                       if (err)
+                               goto out;
+               }
 
                if (d.redirect) {
                        upperredirect = kstrdup(d.redirect, GFP_KERNEL);
                        if (!upperredirect)
                                goto out_put_upper;
                        if (d.redirect[0] == '/')
-                               poe = dentry->d_sb->s_root->d_fsdata;
+                               poe = roe;
                }
                upperopaque = d.opaque;
        }
@@ -290,10 +423,8 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
                if (d.stop)
                        break;
 
-               if (d.redirect &&
-                   d.redirect[0] == '/' &&
-                   poe != dentry->d_sb->s_root->d_fsdata) {
-                       poe = dentry->d_sb->s_root->d_fsdata;
+               if (d.redirect && d.redirect[0] == '/' && poe != roe) {
+                       poe = roe;
 
                        /* Find the current layer on the root dentry */
                        for (i = 0; i < poe->numlower; i++)
index 741dc0b6931fe90fc62874989c93e659f7e7a4ef..caa36cb9c46de9838805dc40e21672217407d40e 100644 (file)
@@ -8,18 +8,56 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/uuid.h>
 
 enum ovl_path_type {
        __OVL_PATH_UPPER        = (1 << 0),
        __OVL_PATH_MERGE        = (1 << 1),
+       __OVL_PATH_ORIGIN       = (1 << 2),
 };
 
 #define OVL_TYPE_UPPER(type)   ((type) & __OVL_PATH_UPPER)
 #define OVL_TYPE_MERGE(type)   ((type) & __OVL_PATH_MERGE)
+#define OVL_TYPE_ORIGIN(type)  ((type) & __OVL_PATH_ORIGIN)
 
 #define OVL_XATTR_PREFIX XATTR_TRUSTED_PREFIX "overlay."
 #define OVL_XATTR_OPAQUE OVL_XATTR_PREFIX "opaque"
 #define OVL_XATTR_REDIRECT OVL_XATTR_PREFIX "redirect"
+#define OVL_XATTR_ORIGIN OVL_XATTR_PREFIX "origin"
+
+/*
+ * The tuple (fh,uuid) is a universal unique identifier for a copy up origin,
+ * where:
+ * origin.fh   - exported file handle of the lower file
+ * origin.uuid - uuid of the lower filesystem
+ */
+#define OVL_FH_VERSION 0
+#define OVL_FH_MAGIC   0xfb
+
+/* CPU byte order required for fid decoding:  */
+#define OVL_FH_FLAG_BIG_ENDIAN (1 << 0)
+#define OVL_FH_FLAG_ANY_ENDIAN (1 << 1)
+
+#define OVL_FH_FLAG_ALL (OVL_FH_FLAG_BIG_ENDIAN | OVL_FH_FLAG_ANY_ENDIAN)
+
+#if defined(__LITTLE_ENDIAN)
+#define OVL_FH_FLAG_CPU_ENDIAN 0
+#elif defined(__BIG_ENDIAN)
+#define OVL_FH_FLAG_CPU_ENDIAN OVL_FH_FLAG_BIG_ENDIAN
+#else
+#error Endianness not defined
+#endif
+
+/* On-disk and in-memeory format for redirect by file handle */
+struct ovl_fh {
+       u8 version;     /* 0 */
+       u8 magic;       /* 0xfb */
+       u8 len;         /* size of this header + size of fid */
+       u8 flags;       /* OVL_FH_FLAG_* */
+       u8 type;        /* fid_type of fid */
+       uuid_be uuid;   /* uuid of filesystem */
+       u8 fid[0];      /* file identifier */
+} __packed;
 
 #define OVL_ISUPPER_MASK 1UL
 
@@ -151,6 +189,7 @@ int ovl_want_write(struct dentry *dentry);
 void ovl_drop_write(struct dentry *dentry);
 struct dentry *ovl_workdir(struct dentry *dentry);
 const struct cred *ovl_override_creds(struct super_block *sb);
+struct super_block *ovl_same_sb(struct super_block *sb);
 struct ovl_entry *ovl_alloc_entry(unsigned int numlower);
 bool ovl_dentry_remote(struct dentry *dentry);
 bool ovl_dentry_weird(struct dentry *dentry);
@@ -197,6 +236,8 @@ void ovl_workdir_cleanup(struct inode *dir, struct vfsmount *mnt,
 
 /* inode.c */
 int ovl_setattr(struct dentry *dentry, struct iattr *attr);
+int ovl_getattr(const struct path *path, struct kstat *stat,
+               u32 request_mask, unsigned int flags);
 int ovl_permission(struct inode *inode, int mask);
 int ovl_xattr_set(struct dentry *dentry, const char *name, const void *value,
                  size_t size, int flags);
index 59614faa14c315fb8f6e5998f91bc7061f818bab..b2023ddb85323725b8bbfa687f31fc854c1ba5e9 100644 (file)
@@ -29,6 +29,8 @@ struct ovl_fs {
        const struct cred *creator_cred;
        bool tmpfile;
        wait_queue_head_t copyup_wq;
+       /* sb common to all layers */
+       struct super_block *same_sb;
 };
 
 /* private information held for every overlayfs dentry */
index c9e70d39c1ea1cafd730be5caaea6924a29e7c58..9828b7de89992e64a1900a277b58423dde7b992a 100644 (file)
@@ -49,11 +49,28 @@ static void ovl_dentry_release(struct dentry *dentry)
        }
 }
 
+static int ovl_check_append_only(struct inode *inode, int flag)
+{
+       /*
+        * This test was moot in vfs may_open() because overlay inode does
+        * not have the S_APPEND flag, so re-check on real upper inode
+        */
+       if (IS_APPEND(inode)) {
+               if  ((flag & O_ACCMODE) != O_RDONLY && !(flag & O_APPEND))
+                       return -EPERM;
+               if (flag & O_TRUNC)
+                       return -EPERM;
+       }
+
+       return 0;
+}
+
 static struct dentry *ovl_d_real(struct dentry *dentry,
                                 const struct inode *inode,
                                 unsigned int open_flags)
 {
        struct dentry *real;
+       int err;
 
        if (!d_is_reg(dentry)) {
                if (!inode || inode == d_inode(dentry))
@@ -65,15 +82,20 @@ static struct dentry *ovl_d_real(struct dentry *dentry,
                return dentry;
 
        if (open_flags) {
-               int err = ovl_open_maybe_copy_up(dentry, open_flags);
-
+               err = ovl_open_maybe_copy_up(dentry, open_flags);
                if (err)
                        return ERR_PTR(err);
        }
 
        real = ovl_dentry_upper(dentry);
-       if (real && (!inode || inode == d_inode(real)))
+       if (real && (!inode || inode == d_inode(real))) {
+               if (!inode) {
+                       err = ovl_check_append_only(d_inode(real), open_flags);
+                       if (err)
+                               return ERR_PTR(err);
+               }
                return real;
+       }
 
        real = ovl_dentry_lower(dentry);
        if (!real)
@@ -709,8 +731,8 @@ static const struct xattr_handler *ovl_xattr_handlers[] = {
 
 static int ovl_fill_super(struct super_block *sb, void *data, int silent)
 {
-       struct path upperpath = { NULL, NULL };
-       struct path workpath = { NULL, NULL };
+       struct path upperpath = { };
+       struct path workpath = { };
        struct dentry *root_dentry;
        struct inode *realinode;
        struct ovl_entry *oe;
@@ -892,11 +914,19 @@ static int ovl_fill_super(struct super_block *sb, void *data, int silent)
 
                ufs->lower_mnt[ufs->numlower] = mnt;
                ufs->numlower++;
+
+               /* Check if all lower layers are on same sb */
+               if (i == 0)
+                       ufs->same_sb = mnt->mnt_sb;
+               else if (ufs->same_sb != mnt->mnt_sb)
+                       ufs->same_sb = NULL;
        }
 
        /* If the upper fs is nonexistent, we mark overlayfs r/o too */
        if (!ufs->upper_mnt)
                sb->s_flags |= MS_RDONLY;
+       else if (ufs->upper_mnt->mnt_sb != ufs->same_sb)
+               ufs->same_sb = NULL;
 
        if (remote)
                sb->s_d_op = &ovl_reval_dentry_operations;
index 6e610a205e1556477ba80e512f1243629c193141..cfdea47313a10e22a9c06193e4cc422891badaae 100644 (file)
@@ -40,6 +40,13 @@ const struct cred *ovl_override_creds(struct super_block *sb)
        return override_creds(ofs->creator_cred);
 }
 
+struct super_block *ovl_same_sb(struct super_block *sb)
+{
+       struct ovl_fs *ofs = sb->s_fs_info;
+
+       return ofs->same_sb;
+}
+
 struct ovl_entry *ovl_alloc_entry(unsigned int numlower)
 {
        size_t size = offsetof(struct ovl_entry, lowerstack[numlower]);
@@ -75,11 +82,13 @@ enum ovl_path_type ovl_path_type(struct dentry *dentry)
                type = __OVL_PATH_UPPER;
 
                /*
-                * Non-dir dentry can hold lower dentry from previous
-                * location.
+                * Non-dir dentry can hold lower dentry of its copy up origin.
                 */
-               if (oe->numlower && d_is_dir(dentry))
-                       type |= __OVL_PATH_MERGE;
+               if (oe->numlower) {
+                       type |= __OVL_PATH_ORIGIN;
+                       if (d_is_dir(dentry))
+                               type |= __OVL_PATH_MERGE;
+               }
        } else {
                if (oe->numlower > 1)
                        type |= __OVL_PATH_MERGE;
@@ -100,7 +109,7 @@ void ovl_path_lower(struct dentry *dentry, struct path *path)
 {
        struct ovl_entry *oe = dentry->d_fsdata;
 
-       *path = oe->numlower ? oe->lowerstack[0] : (struct path) { NULL, NULL };
+       *path = oe->numlower ? oe->lowerstack[0] : (struct path) { };
 }
 
 enum ovl_path_type ovl_path_real(struct dentry *dentry, struct path *path)
index 9e3ac5c1178039ad16eb6476e62d542b38f5748b..45f6bf68fff3ed30df0f85d98c0f644c320a9bf7 100644 (file)
@@ -821,10 +821,7 @@ static ssize_t mem_rw(struct file *file, char __user *buf,
        if (!mmget_not_zero(mm))
                goto free;
 
-       /* Maybe we should limit FOLL_FORCE to actual ptrace users? */
-       flags = FOLL_FORCE;
-       if (write)
-               flags |= FOLL_WRITE;
+       flags = write ? FOLL_WRITE : 0;
 
        while (count > 0) {
                int this_len = min_t(int, count, PAGE_SIZE);
index 2cc7a8030275c1bc98a0da9adb870b33d99f5433..e250910cffc8fd54af942e8009da413ce76093ac 100644 (file)
@@ -58,7 +58,7 @@ static struct inode *proc_alloc_inode(struct super_block *sb)
        struct proc_inode *ei;
        struct inode *inode;
 
-       ei = (struct proc_inode *)kmem_cache_alloc(proc_inode_cachep, GFP_KERNEL);
+       ei = kmem_cache_alloc(proc_inode_cachep, GFP_KERNEL);
        if (!ei)
                return NULL;
        ei->pid = NULL;
index 766f0c637ad1b429c83749ce01a48f56b5863899..3803b24ca220a4dc6cd02b4637e7576a071a9f98 100644 (file)
@@ -23,6 +23,7 @@ static const struct proc_ns_operations *ns_entries[] = {
 #endif
 #ifdef CONFIG_PID_NS
        &pidns_operations,
+       &pidns_for_children_operations,
 #endif
 #ifdef CONFIG_USER_NS
        &userns_operations,
index 5523df7f17ef05818d2c444c682e66579c38742d..5cb022c8cd33f23b566721627dc25dd0263da3a8 100644 (file)
@@ -58,7 +58,7 @@ module_param_named(pmsg_size, ramoops_pmsg_size, ulong, 0400);
 MODULE_PARM_DESC(pmsg_size, "size of user space message log");
 
 static unsigned long long mem_address;
-module_param(mem_address, ullong, 0400);
+module_param_hw(mem_address, ullong, other, 0400);
 MODULE_PARM_DESC(mem_address,
                "start of reserved RAM used to store oops/panic logs");
 
index aca73dd739066477a8f4eb6293122cfe84f3f055..e3c558d1b78c02c711ae9868fe409d349127103f 100644 (file)
@@ -724,18 +724,18 @@ static void errcatch_print_vi(struct virtual_item *vi)
 }
 
 static struct item_operations errcatch_ops = {
-       errcatch_bytes_number,
-       errcatch_decrement_key,
-       errcatch_is_left_mergeable,
-       errcatch_print_item,
-       errcatch_check_item,
-
-       errcatch_create_vi,
-       errcatch_check_left,
-       errcatch_check_right,
-       errcatch_part_size,
-       errcatch_unit_num,
-       errcatch_print_vi
+       .bytes_number = errcatch_bytes_number,
+       .decrement_key = errcatch_decrement_key,
+       .is_left_mergeable = errcatch_is_left_mergeable,
+       .print_item = errcatch_print_item,
+       .check_item = errcatch_check_item,
+
+       .create_vi = errcatch_create_vi,
+       .check_left = errcatch_check_left,
+       .check_right = errcatch_check_right,
+       .part_size = errcatch_part_size,
+       .unit_num = errcatch_unit_num,
+       .print_vi = errcatch_print_vi
 };
 
 #if ! (TYPE_STAT_DATA == 0 && TYPE_INDIRECT == 1 && TYPE_DIRECT == 2 && TYPE_DIRENTRY == 3)
index bd4b2ccfd34680b1648570e7b20db235cb31a89c..d6c652a31e99d18d2d924af983c11504315af56f 100644 (file)
@@ -633,10 +633,7 @@ int core_sys_select(int n, fd_set __user *inp, fd_set __user *outp,
                        goto out_nofds;
 
                alloc_size = 6 * size;
-               bits = kmalloc(alloc_size, GFP_KERNEL|__GFP_NOWARN);
-               if (!bits && alloc_size > PAGE_SIZE)
-                       bits = vmalloc(alloc_size);
-
+               bits = kvmalloc(alloc_size, GFP_KERNEL);
                if (!bits)
                        goto out_nofds;
        }
index ca69fb99e41a8872d6d204d8fd8cffe7f08b3336..dc7c2be963ed4e2c2751313a44270b7655a45b4d 100644 (file)
@@ -25,21 +25,7 @@ static void seq_set_overflow(struct seq_file *m)
 
 static void *seq_buf_alloc(unsigned long size)
 {
-       void *buf;
-       gfp_t gfp = GFP_KERNEL;
-
-       /*
-        * For high order allocations, use __GFP_NORETRY to avoid oom-killing -
-        * it's better to fall back to vmalloc() than to kill things.  For small
-        * allocations, just use GFP_KERNEL which will oom kill, thus no need
-        * for vmalloc fallback.
-        */
-       if (size > PAGE_SIZE)
-               gfp |= __GFP_NORETRY | __GFP_NOWARN;
-       buf = kmalloc(size, gfp);
-       if (!buf && size > PAGE_SIZE)
-               buf = vmalloc(size);
-       return buf;
+       return kvmalloc(size, GFP_KERNEL);
 }
 
 /**
index 270221fcef42cc42fcfdbc098b587b571be65a12..7e3d71109f51334d2bb8c71a9d2419e6ca4eeb3f 100644 (file)
@@ -38,7 +38,7 @@ void signalfd_cleanup(struct sighand_struct *sighand)
        /*
         * The lockless check can race with remove_wait_queue() in progress,
         * but in this case its caller should run under rcu_read_lock() and
-        * sighand_cachep is SLAB_DESTROY_BY_RCU, we can safely return.
+        * sighand_cachep is SLAB_TYPESAFE_BY_RCU, we can safely return.
         */
        if (likely(!waitqueue_active(wqh)))
                return;
index 21d36d28473562d4a40f75134ae3916b11c8041c..328e89c2cf835d4ff3cec1572ae30a30621fa183 100644 (file)
@@ -266,7 +266,7 @@ static const struct super_operations tracefs_super_operations = {
 
 static int trace_fill_super(struct super_block *sb, void *data, int silent)
 {
-       static struct tree_descr trace_files[] = {{""}};
+       static const struct tree_descr trace_files[] = {{""}};
        struct tracefs_fs_info *fsi;
        int err;
 
index b0d0623c83ed88eae3afa31f079dfd2486767d07..83a961bf7280112f84a2567e2dd775f5679af3f3 100644 (file)
@@ -61,3 +61,16 @@ config UBIFS_FS_ENCRYPTION
          feature is similar to ecryptfs, but it is more memory
          efficient since it avoids caching the encrypted and
          decrypted pages in the page cache.
+
+config UBIFS_FS_SECURITY
+       bool "UBIFS Security Labels"
+       depends on UBIFS_FS
+       default y
+       help
+         Security labels provide an access control facility to support Linux
+         Security Models (LSMs) accepted by AppArmor, SELinux, Smack and TOMOYO
+         Linux. This option enables an extended attribute handler for file
+         security labels in the ubifs filesystem, so that it requires enabling
+         the extended attribute support in advance.
+
+         If you are not using a security module, say N.
index 718b749fa11aa8901544a1e6925a7486bbb357f5..7cd8a7b95299c2b096c93d0d0fbfd7838f8dff2c 100644 (file)
@@ -2391,8 +2391,8 @@ int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head)
                        ubifs_dump_node(c, sa->node);
                        return -EINVAL;
                }
-               if (sa->type != UBIFS_INO_NODE && sa->type != UBIFS_DENT_NODE &&
-                   sa->type != UBIFS_XENT_NODE) {
+               if (sb->type != UBIFS_INO_NODE && sb->type != UBIFS_DENT_NODE &&
+                   sb->type != UBIFS_XENT_NODE) {
                        ubifs_err(c, "bad node type %d", sb->type);
                        ubifs_dump_node(c, sb->node);
                        return -EINVAL;
index 8049851cac42ff50e3f1280e62b1845ab7a7720a..566079d9b402cdde6082260fca6e07f42f0064e8 100644 (file)
@@ -121,7 +121,7 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, struct inode *dir,
 
        inode_init_owner(inode, dir, mode);
        inode->i_mtime = inode->i_atime = inode->i_ctime =
-                        ubifs_current_time(inode);
+                        current_time(inode);
        inode->i_mapping->nrpages = 0;
 
        switch (mode & S_IFMT) {
@@ -766,7 +766,7 @@ static int ubifs_link(struct dentry *old_dentry, struct inode *dir,
 
        inc_nlink(inode);
        ihold(inode);
-       inode->i_ctime = ubifs_current_time(inode);
+       inode->i_ctime = current_time(inode);
        dir->i_size += sz_change;
        dir_ui->ui_size = dir->i_size;
        dir->i_mtime = dir->i_ctime = inode->i_ctime;
@@ -841,7 +841,7 @@ static int ubifs_unlink(struct inode *dir, struct dentry *dentry)
        }
 
        lock_2_inodes(dir, inode);
-       inode->i_ctime = ubifs_current_time(dir);
+       inode->i_ctime = current_time(dir);
        drop_nlink(inode);
        dir->i_size -= sz_change;
        dir_ui->ui_size = dir->i_size;
@@ -945,7 +945,7 @@ static int ubifs_rmdir(struct inode *dir, struct dentry *dentry)
        }
 
        lock_2_inodes(dir, inode);
-       inode->i_ctime = ubifs_current_time(dir);
+       inode->i_ctime = current_time(dir);
        clear_nlink(inode);
        drop_nlink(dir);
        dir->i_size -= sz_change;
@@ -1422,7 +1422,7 @@ static int do_rename(struct inode *old_dir, struct dentry *old_dentry,
         * Like most other Unix systems, set the @i_ctime for inodes on a
         * rename.
         */
-       time = ubifs_current_time(old_dir);
+       time = current_time(old_dir);
        old_inode->i_ctime = time;
 
        /* We must adjust parent link count when renaming directories */
@@ -1595,7 +1595,7 @@ static int ubifs_xrename(struct inode *old_dir, struct dentry *old_dentry,
 
        lock_4_inodes(old_dir, new_dir, NULL, NULL);
 
-       time = ubifs_current_time(old_dir);
+       time = current_time(old_dir);
        fst_inode->i_ctime = time;
        snd_inode->i_ctime = time;
        old_dir->i_mtime = old_dir->i_ctime = time;
index d9ae86f96df7b52255c259489b5343a7cd94faf8..2cda3d67e2d01c0e047a58c327a62e2778c9a117 100644 (file)
@@ -1196,7 +1196,7 @@ static int do_truncation(struct ubifs_info *c, struct inode *inode,
        mutex_lock(&ui->ui_mutex);
        ui->ui_size = inode->i_size;
        /* Truncation changes inode [mc]time */
-       inode->i_mtime = inode->i_ctime = ubifs_current_time(inode);
+       inode->i_mtime = inode->i_ctime = current_time(inode);
        /* Other attributes may be changed at the same time as well */
        do_attr_changes(inode, attr);
        err = ubifs_jnl_truncate(c, inode, old_size, new_size);
@@ -1243,7 +1243,7 @@ static int do_setattr(struct ubifs_info *c, struct inode *inode,
        mutex_lock(&ui->ui_mutex);
        if (attr->ia_valid & ATTR_SIZE) {
                /* Truncation changes inode [mc]time */
-               inode->i_mtime = inode->i_ctime = ubifs_current_time(inode);
+               inode->i_mtime = inode->i_ctime = current_time(inode);
                /* 'truncate_setsize()' changed @i_size, update @ui_size */
                ui->ui_size = inode->i_size;
        }
@@ -1420,7 +1420,7 @@ int ubifs_update_time(struct inode *inode, struct timespec *time,
  */
 static int update_mctime(struct inode *inode)
 {
-       struct timespec now = ubifs_current_time(inode);
+       struct timespec now = current_time(inode);
        struct ubifs_inode *ui = ubifs_inode(inode);
        struct ubifs_info *c = inode->i_sb->s_fs_info;
 
@@ -1434,7 +1434,7 @@ static int update_mctime(struct inode *inode)
                        return err;
 
                mutex_lock(&ui->ui_mutex);
-               inode->i_mtime = inode->i_ctime = ubifs_current_time(inode);
+               inode->i_mtime = inode->i_ctime = current_time(inode);
                release = ui->dirty;
                mark_inode_dirty_sync(inode);
                mutex_unlock(&ui->ui_mutex);
@@ -1511,7 +1511,7 @@ static int ubifs_vm_page_mkwrite(struct vm_fault *vmf)
        struct page *page = vmf->page;
        struct inode *inode = file_inode(vmf->vma->vm_file);
        struct ubifs_info *c = inode->i_sb->s_fs_info;
-       struct timespec now = ubifs_current_time(inode);
+       struct timespec now = current_time(inode);
        struct ubifs_budget_req req = { .new_page = 1 };
        int err, update_time;
 
@@ -1579,7 +1579,7 @@ static int ubifs_vm_page_mkwrite(struct vm_fault *vmf)
                struct ubifs_inode *ui = ubifs_inode(inode);
 
                mutex_lock(&ui->ui_mutex);
-               inode->i_mtime = inode->i_ctime = ubifs_current_time(inode);
+               inode->i_mtime = inode->i_ctime = current_time(inode);
                release = ui->dirty;
                mark_inode_dirty_sync(inode);
                mutex_unlock(&ui->ui_mutex);
index da519ba205f614fb7a5ea9d3eb72b4c58b4504e9..fdc311246807a4c3a018ff53e06f44614f5c6800 100644 (file)
@@ -53,7 +53,7 @@ void ubifs_set_inode_flags(struct inode *inode)
  * ioctl2ubifs - convert ioctl inode flags to UBIFS inode flags.
  * @ioctl_flags: flags to convert
  *
- * This function convert ioctl flags (@FS_COMPR_FL, etc) to UBIFS inode flags
+ * This function converts ioctl flags (@FS_COMPR_FL, etc) to UBIFS inode flags
  * (@UBIFS_COMPR_FL, etc).
  */
 static int ioctl2ubifs(int ioctl_flags)
@@ -78,8 +78,8 @@ static int ioctl2ubifs(int ioctl_flags)
  * ubifs2ioctl - convert UBIFS inode flags to ioctl inode flags.
  * @ubifs_flags: flags to convert
  *
- * This function convert UBIFS (@UBIFS_COMPR_FL, etc) to ioctl flags
- * (@FS_COMPR_FL, etc).
+ * This function converts UBIFS inode flags (@UBIFS_COMPR_FL, etc) to ioctl
+ * flags (@FS_COMPR_FL, etc).
  */
 static int ubifs2ioctl(int ubifs_flags)
 {
@@ -126,7 +126,7 @@ static int setflags(struct inode *inode, int flags)
 
        ui->flags = ioctl2ubifs(flags);
        ubifs_set_inode_flags(inode);
-       inode->i_ctime = ubifs_current_time(inode);
+       inode->i_ctime = current_time(inode);
        release = ui->dirty;
        mark_inode_dirty_sync(inode);
        mutex_unlock(&ui->ui_mutex);
index 8ece6ca58c0ba128f658ea0c42ddc7976d942314..caf83d68fb38c2918bf9d421b4a67cd8a96571b7 100644 (file)
@@ -224,16 +224,6 @@ static inline void *ubifs_idx_key(const struct ubifs_info *c,
        return (void *)((struct ubifs_branch *)idx->branches)->key;
 }
 
-/**
- * ubifs_current_time - round current time to time granularity.
- * @inode: inode
- */
-static inline struct timespec ubifs_current_time(struct inode *inode)
-{
-       return (inode->i_sb->s_time_gran < NSEC_PER_SEC) ?
-               current_fs_time(inode->i_sb) : CURRENT_TIME_SEC;
-}
-
 /**
  * ubifs_tnc_lookup - look up a file-system node.
  * @c: UBIFS file-system description object
index 586d59347fff00c4572af57bf6e487f6fa2932d8..3af4472061cc0139638efa80245516f27fe175b0 100644 (file)
@@ -442,7 +442,6 @@ static void clean_buf(const struct ubifs_info *c, void **buf, int lnum,
 {
        int empty_offs, pad_len;
 
-       lnum = lnum;
        dbg_rcvry("cleaning corruption at %d:%d", lnum, *offs);
 
        ubifs_assert(!(*offs & 7));
index 7f1ead29e7270a39374bef080035beaf42374820..8c25081a510969055405b95ed57e8d94ec556f44 100644 (file)
@@ -84,6 +84,8 @@ static int create_default_filesystem(struct ubifs_info *c)
        int min_leb_cnt = UBIFS_MIN_LEB_CNT;
        long long tmp64, main_bytes;
        __le64 tmp_le64;
+       __le32 tmp_le32;
+       struct timespec ts;
 
        /* Some functions called from here depend on the @c->key_len filed */
        c->key_len = UBIFS_SK_LEN;
@@ -298,13 +300,17 @@ static int create_default_filesystem(struct ubifs_info *c)
        ino->ch.node_type = UBIFS_INO_NODE;
        ino->creat_sqnum = cpu_to_le64(++c->max_sqnum);
        ino->nlink = cpu_to_le32(2);
-       tmp_le64 = cpu_to_le64(CURRENT_TIME_SEC.tv_sec);
+
+       ktime_get_real_ts(&ts);
+       ts = timespec_trunc(ts, DEFAULT_TIME_GRAN);
+       tmp_le64 = cpu_to_le64(ts.tv_sec);
        ino->atime_sec   = tmp_le64;
        ino->ctime_sec   = tmp_le64;
        ino->mtime_sec   = tmp_le64;
-       ino->atime_nsec  = 0;
-       ino->ctime_nsec  = 0;
-       ino->mtime_nsec  = 0;
+       tmp_le32 = cpu_to_le32(ts.tv_nsec);
+       ino->atime_nsec  = tmp_le32;
+       ino->ctime_nsec  = tmp_le32;
+       ino->mtime_nsec  = tmp_le32;
        ino->mode = cpu_to_le32(S_IFDIR | S_IRUGO | S_IWUSR | S_IXUGO);
        ino->size = cpu_to_le64(UBIFS_INO_NODE_SZ);
 
index 4da10a6d702a0330cbc223b535df7a2be2be3d52..298b4d89eee98b74440d84097d1789ba5de8a906 100644 (file)
@@ -1753,13 +1753,23 @@ int ubifs_check_dir_empty(struct inode *dir);
 /* xattr.c */
 extern const struct xattr_handler *ubifs_xattr_handlers[];
 ssize_t ubifs_listxattr(struct dentry *dentry, char *buffer, size_t size);
-int ubifs_init_security(struct inode *dentry, struct inode *inode,
-                       const struct qstr *qstr);
 int ubifs_xattr_set(struct inode *host, const char *name, const void *value,
                    size_t size, int flags);
 ssize_t ubifs_xattr_get(struct inode *host, const char *name, void *buf,
                        size_t size);
 
+#ifdef CONFIG_UBIFS_FS_SECURITY
+extern int ubifs_init_security(struct inode *dentry, struct inode *inode,
+                       const struct qstr *qstr);
+#else
+static inline int ubifs_init_security(struct inode *dentry,
+                       struct inode *inode, const struct qstr *qstr)
+{
+       return 0;
+}
+#endif
+
+
 /* super.c */
 struct inode *ubifs_iget(struct super_block *sb, unsigned long inum);
 
index efe00fcb8b750961918a7e2c98ee3d670968ca72..6c9e62c2ef559b2d6b3d3383436775795e927375 100644 (file)
@@ -152,7 +152,7 @@ static int create_xattr(struct ubifs_info *c, struct inode *host,
        ui->data_len = size;
 
        mutex_lock(&host_ui->ui_mutex);
-       host->i_ctime = ubifs_current_time(host);
+       host->i_ctime = current_time(host);
        host_ui->xattr_cnt += 1;
        host_ui->xattr_size += CALC_DENT_SIZE(fname_len(nm));
        host_ui->xattr_size += CALC_XATTR_BYTES(size);
@@ -234,7 +234,7 @@ static int change_xattr(struct ubifs_info *c, struct inode *host,
        mutex_unlock(&ui->ui_mutex);
 
        mutex_lock(&host_ui->ui_mutex);
-       host->i_ctime = ubifs_current_time(host);
+       host->i_ctime = current_time(host);
        host_ui->xattr_size -= CALC_XATTR_BYTES(old_size);
        host_ui->xattr_size += CALC_XATTR_BYTES(size);
 
@@ -488,7 +488,7 @@ static int remove_xattr(struct ubifs_info *c, struct inode *host,
                return err;
 
        mutex_lock(&host_ui->ui_mutex);
-       host->i_ctime = ubifs_current_time(host);
+       host->i_ctime = current_time(host);
        host_ui->xattr_cnt -= 1;
        host_ui->xattr_size -= CALC_DENT_SIZE(fname_len(nm));
        host_ui->xattr_size -= CALC_XATTR_BYTES(ui->data_len);
@@ -559,6 +559,7 @@ out_free:
        return err;
 }
 
+#ifdef CONFIG_UBIFS_FS_SECURITY
 static int init_xattrs(struct inode *inode, const struct xattr *xattr_array,
                      void *fs_info)
 {
@@ -599,6 +600,7 @@ int ubifs_init_security(struct inode *dentry, struct inode *inode,
        }
        return err;
 }
+#endif
 
 static int xattr_get(const struct xattr_handler *handler,
                           struct dentry *dentry, struct inode *inode,
@@ -639,15 +641,19 @@ static const struct xattr_handler ubifs_trusted_xattr_handler = {
        .set = xattr_set,
 };
 
+#ifdef CONFIG_UBIFS_FS_SECURITY
 static const struct xattr_handler ubifs_security_xattr_handler = {
        .prefix = XATTR_SECURITY_PREFIX,
        .get = xattr_get,
        .set = xattr_set,
 };
+#endif
 
 const struct xattr_handler *ubifs_xattr_handlers[] = {
        &ubifs_user_xattr_handler,
        &ubifs_trusted_xattr_handler,
+#ifdef CONFIG_UBIFS_FS_SECURITY
        &ubifs_security_xattr_handler,
+#endif
        NULL
 };
index 9774555b37217eba4c7fa5375e6df0c7cfa64ae8..d1dd8cc33179137988aedf9bb15098547906a561 100644 (file)
@@ -176,6 +176,7 @@ struct inode *ufs_new_inode(struct inode *dir, umode_t mode)
        struct ufs_cg_private_info * ucpi;
        struct ufs_cylinder_group * ucg;
        struct inode * inode;
+       struct timespec64 ts;
        unsigned cg, bit, i, j, start;
        struct ufs_inode_info *ufsi;
        int err = -ENOSPC;
@@ -323,8 +324,9 @@ cg_found:
                lock_buffer(bh);
                ufs2_inode = (struct ufs2_inode *)bh->b_data;
                ufs2_inode += ufs_inotofsbo(inode->i_ino);
-               ufs2_inode->ui_birthtime = cpu_to_fs64(sb, CURRENT_TIME.tv_sec);
-               ufs2_inode->ui_birthnsec = cpu_to_fs32(sb, CURRENT_TIME.tv_nsec);
+               ktime_get_real_ts64(&ts);
+               ufs2_inode->ui_birthtime = cpu_to_fs64(sb, ts.tv_sec);
+               ufs2_inode->ui_birthnsec = cpu_to_fs32(sb, ts.tv_nsec);
                mark_buffer_dirty(bh);
                unlock_buffer(bh);
                if (sb->s_flags & MS_SYNCHRONOUS)
index 7e3317cf4045523a7d0b17f102d51775808a8950..464c94bf65f9e55339ec9d4bc515ec990691deb7 100644 (file)
@@ -431,12 +431,9 @@ setxattr(struct dentry *d, const char __user *name, const void __user *value,
        if (size) {
                if (size > XATTR_SIZE_MAX)
                        return -E2BIG;
-               kvalue = kmalloc(size, GFP_KERNEL | __GFP_NOWARN);
-               if (!kvalue) {
-                       kvalue = vmalloc(size);
-                       if (!kvalue)
-                               return -ENOMEM;
-               }
+               kvalue = kvmalloc(size, GFP_KERNEL);
+               if (!kvalue)
+                       return -ENOMEM;
                if (copy_from_user(kvalue, value, size)) {
                        error = -EFAULT;
                        goto out;
@@ -528,12 +525,9 @@ getxattr(struct dentry *d, const char __user *name, void __user *value,
        if (size) {
                if (size > XATTR_SIZE_MAX)
                        size = XATTR_SIZE_MAX;
-               kvalue = kzalloc(size, GFP_KERNEL | __GFP_NOWARN);
-               if (!kvalue) {
-                       kvalue = vmalloc(size);
-                       if (!kvalue)
-                               return -ENOMEM;
-               }
+               kvalue = kvzalloc(size, GFP_KERNEL);
+               if (!kvalue)
+                       return -ENOMEM;
        }
 
        error = vfs_getxattr(d, kname, kvalue, size);
@@ -611,12 +605,9 @@ listxattr(struct dentry *d, char __user *list, size_t size)
        if (size) {
                if (size > XATTR_LIST_MAX)
                        size = XATTR_LIST_MAX;
-               klist = kmalloc(size, __GFP_NOWARN | GFP_KERNEL);
-               if (!klist) {
-                       klist = vmalloc(size);
-                       if (!klist)
-                               return -ENOMEM;
-               }
+               klist = kvmalloc(size, GFP_KERNEL);
+               if (!klist)
+                       return -ENOMEM;
        }
 
        error = vfs_listxattr(d, klist, size);
index 780fc8986dabd163058747e6b71e3aae90b7e67c..393b6849aeb31991ed43808ff213fb3cadba00d0 100644 (file)
@@ -67,7 +67,7 @@ kmem_zalloc_large(size_t size, xfs_km_flags_t flags)
                nofs_flag = memalloc_nofs_save();
 
        lflags = kmem_flags_convert(flags);
-       ptr = __vmalloc(size, lflags | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL);
+       ptr = __vmalloc(size, lflags | __GFP_ZERO, PAGE_KERNEL);
 
        if (flags & KM_NOFS)
                memalloc_nofs_restore(nofs_flag);
index a63f61c256bdc54f0a8ee6088702dbd5e91ee9aa..94e5bdf7304cff79c9ad7784013520776e3086f8 100644 (file)
@@ -1068,7 +1068,7 @@ xfs_file_iomap_begin(
        /* optionally associate a dax device with the iomap bdev */
        bdev = iomap->bdev;
        if (blk_queue_dax(bdev->bd_queue))
-               iomap->dax_dev = dax_get_by_host(bdev->bd_disk->disk_name);
+               iomap->dax_dev = fs_dax_get_by_host(bdev->bd_disk->disk_name);
        else
                iomap->dax_dev = NULL;
 
@@ -1149,7 +1149,7 @@ xfs_file_iomap_end(
        unsigned                flags,
        struct iomap            *iomap)
 {
-       put_dax(iomap->dax_dev);
+       fs_put_dax(iomap->dax_dev);
        if ((flags & IOMAP_WRITE) && iomap->type == IOMAP_DELALLOC)
                return xfs_file_iomap_end_delalloc(XFS_I(inode), offset,
                                length, written, iomap);
index 4a98762ec8b45f3c0dd021c04cb5bcf9a74e63bc..cd0b077deb354b6de5dda287cffaeb351e0e8cce 100644 (file)
@@ -3796,7 +3796,7 @@ xlog_recover_bud_pass2(
  * This routine is called when an inode create format structure is found in a
  * committed transaction in the log.  It's purpose is to initialise the inodes
  * being allocated on disk. This requires us to get inode cluster buffers that
- * match the range to be intialised, stamped with inode templates and written
+ * match the range to be initialised, stamped with inode templates and written
  * by delayed write so that subsequent modifications will hit the cached buffer
  * and only need writing out at the end of recovery.
  */
index 47d239dcf3f4d46cf73153fdfc9521692b1847bb..455a575f101db1f22b8c8c0aca247d627f82ea4c 100644 (file)
@@ -52,6 +52,7 @@
 #include "xfs_reflink.h"
 
 #include <linux/namei.h>
+#include <linux/dax.h>
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/mount.h>
diff --git a/include/Kbuild b/include/Kbuild
deleted file mode 100644 (file)
index bab1145..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-# Top-level Makefile calls into asm-$(ARCH)
-# List only non-arch directories below
index 07740072da55d9bc64794c5f7232be4d5e256bc0..6db3b4668b1a2b1e6c618d49565f96b1c4521021 100644 (file)
@@ -78,6 +78,7 @@
 #define ACPI_MAX_EXTPARSE_CACHE_DEPTH   96     /* Parse tree objects */
 #define ACPI_MAX_OBJECT_CACHE_DEPTH     96     /* Interpreter operand objects */
 #define ACPI_MAX_NAMESPACE_CACHE_DEPTH  96     /* Namespace objects */
+#define ACPI_MAX_COMMENT_CACHE_DEPTH    96     /* Comments for the -ca option */
 
 /*
  * Should the subsystem abort the loading of an ACPI table if the
index 2fc678e08d8dbcbe34578df6f8b923796d267ccf..197f3fffc9a7151ed61d0b960f5e452f6beccb5c 100644 (file)
@@ -577,7 +577,7 @@ struct acpi_pci_root {
 
 bool acpi_dma_supported(struct acpi_device *adev);
 enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev);
-void acpi_dma_configure(struct device *dev, enum dev_dma_attr attr);
+int acpi_dma_configure(struct device *dev, enum dev_dma_attr attr);
 void acpi_dma_deconfigure(struct device *dev);
 
 struct acpi_device *acpi_find_child_device(struct acpi_device *parent,
@@ -588,6 +588,15 @@ struct acpi_pci_root *acpi_pci_find_root(acpi_handle handle);
 int acpi_enable_wakeup_device_power(struct acpi_device *dev, int state);
 int acpi_disable_wakeup_device_power(struct acpi_device *dev);
 
+#ifdef CONFIG_X86
+bool acpi_device_always_present(struct acpi_device *adev);
+#else
+static inline bool acpi_device_always_present(struct acpi_device *adev)
+{
+       return false;
+}
+#endif
+
 #ifdef CONFIG_PM
 acpi_status acpi_add_pm_notifier(struct acpi_device *adev, struct device *dev,
                                 void (*work_func)(struct work_struct *work));
index 3795386ea7068a1e0a77801ee98e9a569c59f3e2..15c86ce4df537bec81aaf1e83e5961b0b9e5913f 100644 (file)
@@ -46,7 +46,7 @@
 
 /* Current ACPICA subsystem version in YYYYMMDD format */
 
-#define ACPI_CA_VERSION                 0x20170119
+#define ACPI_CA_VERSION                 0x20170303
 
 #include <acpi/acconfig.h>
 #include <acpi/actypes.h>
index 0ff3c64ce92452c4b89c6344f30b7737e4a6534b..faa9f2c0d5de8cd545bd1ea911b352fa74a0128d 100644 (file)
@@ -87,6 +87,7 @@
 #define ACPI_SIG_WDAT           "WDAT" /* Watchdog Action Table */
 #define ACPI_SIG_WDDT           "WDDT" /* Watchdog Timer Description Table */
 #define ACPI_SIG_WDRT           "WDRT" /* Watchdog Resource Table */
+#define ACPI_SIG_XXXX           "XXXX" /* Intermediate AML header for ASL/ASL+ converter */
 
 #ifdef ACPI_UNDEFINED_TABLES
 /*
@@ -783,6 +784,15 @@ struct acpi_iort_smmu {
 #define ACPI_IORT_SMMU_DVM_SUPPORTED    (1)
 #define ACPI_IORT_SMMU_COHERENT_WALK    (1<<1)
 
+/* Global interrupt format */
+
+struct acpi_iort_smmu_gsi {
+       u32 nsg_irpt;
+       u32 nsg_irpt_flags;
+       u32 nsg_cfg_irpt;
+       u32 nsg_cfg_irpt_flags;
+};
+
 struct acpi_iort_smmu_v3 {
        u64 base_address;       /* SMMUv3 base address */
        u32 flags;
diff --git a/include/asm-generic/Kbuild.asm b/include/asm-generic/Kbuild.asm
deleted file mode 100644 (file)
index d2ee86b..0000000
+++ /dev/null
@@ -1 +0,0 @@
-include include/uapi/asm-generic/Kbuild.asm
diff --git a/include/asm-generic/set_memory.h b/include/asm-generic/set_memory.h
new file mode 100644 (file)
index 0000000..83e81f8
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __ASM_SET_MEMORY_H
+#define __ASM_SET_MEMORY_H
+
+/*
+ * Functions to change memory attributes.
+ */
+int set_memory_ro(unsigned long addr, int numpages);
+int set_memory_rw(unsigned long addr, int numpages);
+int set_memory_x(unsigned long addr, int numpages);
+int set_memory_nx(unsigned long addr, int numpages);
+
+#endif
index 3558f4eb1a865792601882f67a6e35211b803278..314a0b9219c64704151ad50680bd89d133f1af57 100644 (file)
        IRQCHIP_OF_MATCH_TABLE()                                        \
        ACPI_PROBE_TABLE(irqchip)                                       \
        ACPI_PROBE_TABLE(clksrc)                                        \
-       ACPI_PROBE_TABLE(iort)                                          \
        EARLYCON_TABLE()
 
 #define INIT_TEXT                                                      \
index 70d4e221a3adb485ff7927c33737db23a127b577..d0f6cf2e5324411ac20d3f53515df0899a9601ed 100644 (file)
@@ -37,8 +37,7 @@ static __inline__ void *drm_calloc_large(size_t nmemb, size_t size)
        if (size * nmemb <= PAGE_SIZE)
            return kcalloc(nmemb, size, GFP_KERNEL);
 
-       return __vmalloc(size * nmemb,
-                        GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL);
+       return vzalloc(size * nmemb);
 }
 
 /* Modeled after cairo's malloc_ab, it's like calloc but without the zeroing. */
@@ -50,8 +49,7 @@ static __inline__ void *drm_malloc_ab(size_t nmemb, size_t size)
        if (size * nmemb <= PAGE_SIZE)
            return kmalloc(nmemb * size, GFP_KERNEL);
 
-       return __vmalloc(size * nmemb,
-                        GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL);
+       return vmalloc(size * nmemb);
 }
 
 static __inline__ void *drm_malloc_gfp(size_t nmemb, size_t size, gfp_t gfp)
@@ -69,8 +67,7 @@ static __inline__ void *drm_malloc_gfp(size_t nmemb, size_t size, gfp_t gfp)
                        return ptr;
        }
 
-       return __vmalloc(size * nmemb,
-                        gfp | __GFP_HIGHMEM, PAGE_KERNEL);
+       return __vmalloc(size * nmemb, gfp, PAGE_KERNEL);
 }
 
 static __inline void drm_free_large(void *ptr)
index 63f4c2c44a1f712c0cdf72c5d0d492ad7bbf70dd..3190e30b9398ca60037193daf59efd7006bf66ab 100644 (file)
@@ -10,6 +10,7 @@
 #define CLKID_FCLK_DIV2                4
 #define CLKID_FCLK_DIV3                5
 #define CLKID_FCLK_DIV4                6
+#define CLKID_GP0_PLL          9
 #define CLKID_CLK81            12
 #define CLKID_MPLL2            15
 #define CLKID_I2C              22
 #define CLKID_RNG0             25
 #define CLKID_SPI              34
 #define CLKID_ETH              36
+#define CLKID_AIU_GLUE         38
+#define CLKID_I2S_OUT          40
+#define CLKID_MIXER_IFACE      44
+#define CLKID_AIU              47
 #define CLKID_USB0             50
 #define CLKID_USB1             51
 #define CLKID_USB              55
 #define CLKID_USB0_DDR_BRIDGE  65
 #define CLKID_SANA             69
 #define CLKID_GCLK_VENCI_INT0  77
+#define CLKID_AOCLK_GATE       80
 #define CLKID_AO_I2C           93
 #define CLKID_SD_EMMC_A                94
 #define CLKID_SD_EMMC_B                95
 #define CLKID_SD_EMMC_C                96
 #define CLKID_SAR_ADC_CLK      97
 #define CLKID_SAR_ADC_SEL      98
+#define CLKID_MALI_0_SEL       100
+#define CLKID_MALI_0           102
+#define CLKID_MALI_1_SEL       103
+#define CLKID_MALI_1           105
+#define CLKID_MALI             106
 
 #endif /* __GXBB_CLKC_H */
index 6b03c84f42783635573307c053d63e9f0d3ee083..b8ba665aab7b3486ad39777acda4a4aa0a249a5d 100644 (file)
 #define HI6220_CS_DAPB         57
 #define HI6220_CS_ATB_DIV      58
 
-#define HI6220_SYS_NR_CLKS     59
+/* gate clock */
+#define HI6220_DAPB_CLK                59
+
+#define HI6220_SYS_NR_CLKS     60
 
 /* clk in Hi6220 media controller */
 /* gate clocks */
diff --git a/include/dt-bindings/clock/mt6797-clk.h b/include/dt-bindings/clock/mt6797-clk.h
new file mode 100644 (file)
index 0000000..2f25a5a
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 2017 MediaTek Inc.
+ * Author: Kevin Chen <kevin-cw.chen@mediatek.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_CLK_MT6797_H
+#define _DT_BINDINGS_CLK_MT6797_H
+
+/* TOPCKGEN */
+#define        CLK_TOP_MUX_ULPOSC_AXI_CK_MUX_PRE       1
+#define        CLK_TOP_MUX_ULPOSC_AXI_CK_MUX           2
+#define        CLK_TOP_MUX_AXI                         3
+#define        CLK_TOP_MUX_MEM                         4
+#define        CLK_TOP_MUX_DDRPHYCFG                   5
+#define        CLK_TOP_MUX_MM                          6
+#define        CLK_TOP_MUX_PWM                         7
+#define        CLK_TOP_MUX_VDEC                        8
+#define        CLK_TOP_MUX_VENC                        9
+#define        CLK_TOP_MUX_MFG                         10
+#define        CLK_TOP_MUX_CAMTG                       11
+#define        CLK_TOP_MUX_UART                        12
+#define        CLK_TOP_MUX_SPI                         13
+#define        CLK_TOP_MUX_ULPOSC_SPI_CK_MUX           14
+#define        CLK_TOP_MUX_USB20                       15
+#define        CLK_TOP_MUX_MSDC50_0_HCLK               16
+#define        CLK_TOP_MUX_MSDC50_0                    17
+#define        CLK_TOP_MUX_MSDC30_1                    18
+#define        CLK_TOP_MUX_MSDC30_2                    19
+#define        CLK_TOP_MUX_AUDIO                       20
+#define        CLK_TOP_MUX_AUD_INTBUS                  21
+#define        CLK_TOP_MUX_PMICSPI                     22
+#define        CLK_TOP_MUX_SCP                         23
+#define        CLK_TOP_MUX_ATB                         24
+#define        CLK_TOP_MUX_MJC                         25
+#define        CLK_TOP_MUX_DPI0                        26
+#define        CLK_TOP_MUX_AUD_1                       27
+#define        CLK_TOP_MUX_AUD_2                       28
+#define        CLK_TOP_MUX_SSUSB_TOP_SYS               29
+#define        CLK_TOP_MUX_SPM                         30
+#define        CLK_TOP_MUX_BSI_SPI                     31
+#define        CLK_TOP_MUX_AUDIO_H                     32
+#define        CLK_TOP_MUX_ANC_MD32                    33
+#define        CLK_TOP_MUX_MFG_52M                     34
+#define        CLK_TOP_SYSPLL_CK                       35
+#define        CLK_TOP_SYSPLL_D2                       36
+#define        CLK_TOP_SYSPLL1_D2                      37
+#define        CLK_TOP_SYSPLL1_D4                      38
+#define        CLK_TOP_SYSPLL1_D8                      39
+#define        CLK_TOP_SYSPLL1_D16                     40
+#define        CLK_TOP_SYSPLL_D3                       41
+#define        CLK_TOP_SYSPLL_D3_D3                    42
+#define        CLK_TOP_SYSPLL2_D2                      43
+#define        CLK_TOP_SYSPLL2_D4                      44
+#define        CLK_TOP_SYSPLL2_D8                      45
+#define        CLK_TOP_SYSPLL_D5                       46
+#define        CLK_TOP_SYSPLL3_D2                      47
+#define        CLK_TOP_SYSPLL3_D4                      48
+#define        CLK_TOP_SYSPLL_D7                       49
+#define        CLK_TOP_SYSPLL4_D2                      50
+#define        CLK_TOP_SYSPLL4_D4                      51
+#define        CLK_TOP_UNIVPLL_CK                      52
+#define        CLK_TOP_UNIVPLL_D7                      53
+#define        CLK_TOP_UNIVPLL_D26                     54
+#define        CLK_TOP_SSUSB_PHY_48M_CK                55
+#define        CLK_TOP_USB_PHY48M_CK                   56
+#define        CLK_TOP_UNIVPLL_D2                      57
+#define        CLK_TOP_UNIVPLL1_D2                     58
+#define        CLK_TOP_UNIVPLL1_D4                     59
+#define        CLK_TOP_UNIVPLL1_D8                     60
+#define        CLK_TOP_UNIVPLL_D3                      61
+#define        CLK_TOP_UNIVPLL2_D2                     62
+#define        CLK_TOP_UNIVPLL2_D4                     63
+#define        CLK_TOP_UNIVPLL2_D8                     64
+#define        CLK_TOP_UNIVPLL_D5                      65
+#define        CLK_TOP_UNIVPLL3_D2                     66
+#define        CLK_TOP_UNIVPLL3_D4                     67
+#define        CLK_TOP_UNIVPLL3_D8                     68
+#define        CLK_TOP_ULPOSC_CK_ORG                   69
+#define        CLK_TOP_ULPOSC_CK                       70
+#define        CLK_TOP_ULPOSC_D2                       71
+#define        CLK_TOP_ULPOSC_D3                       72
+#define        CLK_TOP_ULPOSC_D4                       73
+#define        CLK_TOP_ULPOSC_D8                       74
+#define        CLK_TOP_ULPOSC_D10                      75
+#define        CLK_TOP_APLL1_CK                        76
+#define        CLK_TOP_APLL2_CK                        77
+#define        CLK_TOP_MFGPLL_CK                       78
+#define        CLK_TOP_MFGPLL_D2                       79
+#define        CLK_TOP_IMGPLL_CK                       80
+#define        CLK_TOP_IMGPLL_D2                       81
+#define        CLK_TOP_IMGPLL_D4                       82
+#define        CLK_TOP_CODECPLL_CK                     83
+#define        CLK_TOP_CODECPLL_D2                     84
+#define        CLK_TOP_VDECPLL_CK                      85
+#define        CLK_TOP_TVDPLL_CK                       86
+#define        CLK_TOP_TVDPLL_D2                       87
+#define        CLK_TOP_TVDPLL_D4                       88
+#define        CLK_TOP_TVDPLL_D8                       89
+#define        CLK_TOP_TVDPLL_D16                      90
+#define        CLK_TOP_MSDCPLL_CK                      91
+#define        CLK_TOP_MSDCPLL_D2                      92
+#define        CLK_TOP_MSDCPLL_D4                      93
+#define        CLK_TOP_MSDCPLL_D8                      94
+#define        CLK_TOP_NR                              95
+
+/* APMIXED_SYS */
+#define CLK_APMIXED_MAINPLL                    1
+#define CLK_APMIXED_UNIVPLL                    2
+#define CLK_APMIXED_MFGPLL                     3
+#define CLK_APMIXED_MSDCPLL                    4
+#define CLK_APMIXED_IMGPLL                     5
+#define CLK_APMIXED_TVDPLL                     6
+#define CLK_APMIXED_CODECPLL                   7
+#define CLK_APMIXED_VDECPLL                    8
+#define CLK_APMIXED_APLL1                      9
+#define CLK_APMIXED_APLL2                      10
+#define CLK_APMIXED_NR                         11
+
+/* INFRA_SYS */
+#define        CLK_INFRA_PMIC_TMR                      1
+#define        CLK_INFRA_PMIC_AP                       2
+#define        CLK_INFRA_PMIC_MD                       3
+#define        CLK_INFRA_PMIC_CONN                     4
+#define        CLK_INFRA_SCP                           5
+#define        CLK_INFRA_SEJ                           6
+#define        CLK_INFRA_APXGPT                        7
+#define        CLK_INFRA_SEJ_13M                       8
+#define        CLK_INFRA_ICUSB                         9
+#define        CLK_INFRA_GCE                           10
+#define        CLK_INFRA_THERM                         11
+#define        CLK_INFRA_I2C0                          12
+#define        CLK_INFRA_I2C1                          13
+#define        CLK_INFRA_I2C2                          14
+#define        CLK_INFRA_I2C3                          15
+#define        CLK_INFRA_PWM_HCLK                      16
+#define        CLK_INFRA_PWM1                          17
+#define        CLK_INFRA_PWM2                          18
+#define        CLK_INFRA_PWM3                          19
+#define        CLK_INFRA_PWM4                          20
+#define        CLK_INFRA_PWM                           21
+#define        CLK_INFRA_UART0                         22
+#define        CLK_INFRA_UART1                         23
+#define        CLK_INFRA_UART2                         24
+#define        CLK_INFRA_UART3                         25
+#define        CLK_INFRA_MD2MD_CCIF_0                  26
+#define        CLK_INFRA_MD2MD_CCIF_1                  27
+#define        CLK_INFRA_MD2MD_CCIF_2                  28
+#define        CLK_INFRA_FHCTL                         29
+#define        CLK_INFRA_BTIF                          30
+#define        CLK_INFRA_MD2MD_CCIF_3                  31
+#define        CLK_INFRA_SPI                           32
+#define        CLK_INFRA_MSDC0                         33
+#define        CLK_INFRA_MD2MD_CCIF_4                  34
+#define        CLK_INFRA_MSDC1                         35
+#define        CLK_INFRA_MSDC2                         36
+#define        CLK_INFRA_MD2MD_CCIF_5                  37
+#define        CLK_INFRA_GCPU                          38
+#define        CLK_INFRA_TRNG                          39
+#define        CLK_INFRA_AUXADC                        40
+#define        CLK_INFRA_CPUM                          41
+#define        CLK_INFRA_AP_C2K_CCIF_0                 42
+#define        CLK_INFRA_AP_C2K_CCIF_1                 43
+#define        CLK_INFRA_CLDMA                         44
+#define        CLK_INFRA_DISP_PWM                      45
+#define        CLK_INFRA_AP_DMA                        46
+#define        CLK_INFRA_DEVICE_APC                    47
+#define        CLK_INFRA_L2C_SRAM                      48
+#define        CLK_INFRA_CCIF_AP                       49
+#define        CLK_INFRA_AUDIO                         50
+#define        CLK_INFRA_CCIF_MD                       51
+#define        CLK_INFRA_DRAMC_F26M                    52
+#define        CLK_INFRA_I2C4                          53
+#define        CLK_INFRA_I2C_APPM                      54
+#define        CLK_INFRA_I2C_GPUPM                     55
+#define        CLK_INFRA_I2C2_IMM                      56
+#define        CLK_INFRA_I2C2_ARB                      57
+#define        CLK_INFRA_I2C3_IMM                      58
+#define        CLK_INFRA_I2C3_ARB                      59
+#define        CLK_INFRA_I2C5                          60
+#define        CLK_INFRA_SYS_CIRQ                      61
+#define        CLK_INFRA_SPI1                          62
+#define        CLK_INFRA_DRAMC_B_F26M                  63
+#define        CLK_INFRA_ANC_MD32                      64
+#define        CLK_INFRA_ANC_MD32_32K                  65
+#define        CLK_INFRA_DVFS_SPM1                     66
+#define        CLK_INFRA_AES_TOP0                      67
+#define        CLK_INFRA_AES_TOP1                      68
+#define        CLK_INFRA_SSUSB_BUS                     69
+#define        CLK_INFRA_SPI2                          70
+#define        CLK_INFRA_SPI3                          71
+#define        CLK_INFRA_SPI4                          72
+#define        CLK_INFRA_SPI5                          73
+#define        CLK_INFRA_IRTX                          74
+#define        CLK_INFRA_SSUSB_SYS                     75
+#define        CLK_INFRA_SSUSB_REF                     76
+#define        CLK_INFRA_AUDIO_26M                     77
+#define        CLK_INFRA_AUDIO_26M_PAD_TOP             78
+#define        CLK_INFRA_MODEM_TEMP_SHARE              79
+#define        CLK_INFRA_VAD_WRAP_SOC                  80
+#define        CLK_INFRA_DRAMC_CONF                    81
+#define        CLK_INFRA_DRAMC_B_CONF                  82
+#define        CLK_INFRA_MFG_VCG                       83
+#define        CLK_INFRA_13M                           84
+#define        CLK_INFRA_NR                            85
+
+/* IMG_SYS */
+#define        CLK_IMG_FDVT                            1
+#define        CLK_IMG_DPE                             2
+#define        CLK_IMG_DIP                             3
+#define        CLK_IMG_LARB6                           4
+#define        CLK_IMG_NR                              5
+
+/* MM_SYS */
+#define        CLK_MM_SMI_COMMON                       1
+#define        CLK_MM_SMI_LARB0                        2
+#define        CLK_MM_SMI_LARB5                        3
+#define        CLK_MM_CAM_MDP                          4
+#define        CLK_MM_MDP_RDMA0                        5
+#define        CLK_MM_MDP_RDMA1                        6
+#define        CLK_MM_MDP_RSZ0                         7
+#define        CLK_MM_MDP_RSZ1                         8
+#define        CLK_MM_MDP_RSZ2                         9
+#define        CLK_MM_MDP_TDSHP                        10
+#define        CLK_MM_MDP_COLOR                        11
+#define        CLK_MM_MDP_WDMA                         12
+#define        CLK_MM_MDP_WROT0                        13
+#define        CLK_MM_MDP_WROT1                        14
+#define        CLK_MM_FAKE_ENG                         15
+#define        CLK_MM_DISP_OVL0                        16
+#define        CLK_MM_DISP_OVL1                        17
+#define        CLK_MM_DISP_OVL0_2L                     18
+#define        CLK_MM_DISP_OVL1_2L                     19
+#define        CLK_MM_DISP_RDMA0                       20
+#define        CLK_MM_DISP_RDMA1                       21
+#define        CLK_MM_DISP_WDMA0                       22
+#define        CLK_MM_DISP_WDMA1                       23
+#define        CLK_MM_DISP_COLOR                       24
+#define        CLK_MM_DISP_CCORR                       25
+#define        CLK_MM_DISP_AAL                         26
+#define        CLK_MM_DISP_GAMMA                       27
+#define        CLK_MM_DISP_OD                          28
+#define        CLK_MM_DISP_DITHER                      29
+#define        CLK_MM_DISP_UFOE                        30
+#define        CLK_MM_DISP_DSC                         31
+#define        CLK_MM_DISP_SPLIT                       32
+#define        CLK_MM_DSI0_MM_CLOCK                    33
+#define        CLK_MM_DSI1_MM_CLOCK                    34
+#define        CLK_MM_DPI_MM_CLOCK                     35
+#define        CLK_MM_DPI_INTERFACE_CLOCK              36
+#define        CLK_MM_LARB4_AXI_ASIF_MM_CLOCK          37
+#define        CLK_MM_LARB4_AXI_ASIF_MJC_CLOCK         38
+#define        CLK_MM_DISP_OVL0_MOUT_CLOCK             39
+#define        CLK_MM_FAKE_ENG2                        40
+#define        CLK_MM_DSI0_INTERFACE_CLOCK             41
+#define        CLK_MM_DSI1_INTERFACE_CLOCK             42
+#define        CLK_MM_NR                               43
+
+/* VDEC_SYS */
+#define        CLK_VDEC_CKEN_ENG                       1
+#define        CLK_VDEC_ACTIVE                         2
+#define        CLK_VDEC_CKEN                           3
+#define        CLK_VDEC_LARB1_CKEN                     4
+#define        CLK_VDEC_NR                             5
+
+/* VENC_SYS */
+#define        CLK_VENC_0                              1
+#define        CLK_VENC_1                              2
+#define        CLK_VENC_2                              3
+#define        CLK_VENC_3                              4
+#define        CLK_VENC_NR                             5
+
+#endif /* _DT_BINDINGS_CLK_MT6797_H */
index ce09915c298fd8179a3289ebac8b2fe101015649..bc256d31099a6eafa64f73078e87ca99b10ec0fa 100644 (file)
@@ -29,6 +29,9 @@
 #define R7S72100_CLK_OSTM0     1
 #define R7S72100_CLK_OSTM1     0
 
+/* MSTP6 */
+#define R7S72100_CLK_RTC       0
+
 /* MSTP7 */
 #define R7S72100_CLK_ETHER     4
 
@@ -49,7 +52,9 @@
 #define R7S72100_CLK_SPI4      3
 
 /* MSTP12 */
-#define R7S72100_CLK_SDHI0     3
-#define R7S72100_CLK_SDHI1     2
+#define R7S72100_CLK_SDHI00    3
+#define R7S72100_CLK_SDHI01    2
+#define R7S72100_CLK_SDHI10    1
+#define R7S72100_CLK_SDHI11    0
 
 #endif /* __DT_BINDINGS_CLOCK_R7S72100_H__ */
index dd11ecdf837e8e65da9e241ef55cdfe376722eb2..4b36681572570c15874e7027b5d987dd61ecaa3d 100644 (file)
@@ -54,6 +54,7 @@
 #define R8A73A4_CLK_IIC3       11
 #define R8A73A4_CLK_IIC4       10
 #define R8A73A4_CLK_IIC5       9
+#define R8A73A4_CLK_INTC_SYS   8
 #define R8A73A4_CLK_IRQC       7
 
 /* MSTP5 */
index fa5e8da809f2e802f3d440dca3d23f1ecb666e82..20641fa68e731ec0a49f3c44b24a8629fca30dd8 100644 (file)
@@ -82,6 +82,7 @@
 
 /* MSTP4 */
 #define R8A7790_CLK_IRQC               7
+#define R8A7790_CLK_INTC_SYS           8
 
 /* MSTP5 */
 #define R8A7790_CLK_AUDIO_DMAC1                1
index ffa11379b3f0ade901ff7d293695ca5f593cb066..adc50dc31ab3423e008efd9959655d2150749403 100644 (file)
@@ -72,6 +72,7 @@
 
 /* MSTP4 */
 #define R8A7791_CLK_IRQC               7
+#define R8A7791_CLK_INTC_SYS           8
 
 /* MSTP5 */
 #define R8A7791_CLK_AUDIO_DMAC1                1
index 9a8b392ceb000fc3eebbca97d659a877542c0625..5be90bc23bd7909788e658069f385f6ebec7fc7e 100644 (file)
@@ -17,7 +17,6 @@
 #define R8A7792_CLK_PLL3               3
 #define R8A7792_CLK_LB                 4
 #define R8A7792_CLK_QSPI               5
-#define R8A7792_CLK_Z                  6
 
 /* MSTP0 */
 #define R8A7792_CLK_MSIOF0             0
@@ -45,6 +44,7 @@
 
 /* MSTP4 */
 #define R8A7792_CLK_IRQC               7
+#define R8A7792_CLK_INTC_SYS           8
 
 /* MSTP5 */
 #define R8A7792_CLK_AUDIO_DMAC0                2
index efcbc594fe82e6837a73d575c215b826dcddca6d..7318d45d4e7e9888c41aa1fb66def087b4cb6ff4 100644 (file)
 
 /* MSTP4 */
 #define R8A7793_CLK_IRQC               7
+#define R8A7793_CLK_INTC_SYS           8
 
 /* MSTP5 */
-#define R8A7793_CLK_AUDIO_DMAC1         1
-#define R8A7793_CLK_AUDIO_DMAC0         2
+#define R8A7793_CLK_AUDIO_DMAC1                1
+#define R8A7793_CLK_AUDIO_DMAC0                2
 #define R8A7793_CLK_ADSP_MOD           6
 #define R8A7793_CLK_THERMAL            22
 #define R8A7793_CLK_PWM                        23
index 88e64846cf370ff4a32c8423b5d00833c8cb5a81..93e99c3ffc8dafebef94d0644cb15532c86ab1b4 100644 (file)
@@ -64,6 +64,7 @@
 
 /* MSTP4 */
 #define R8A7794_CLK_IRQC               7
+#define R8A7794_CLK_INTC_SYS           8
 
 /* MSTP5 */
 #define R8A7794_CLK_AUDIO_DMAC0                2
@@ -81,6 +82,7 @@
 #define R8A7794_CLK_SCIF2              19
 #define R8A7794_CLK_SCIF1              20
 #define R8A7794_CLK_SCIF0              21
+#define R8A7794_CLK_DU1                        23
 #define R8A7794_CLK_DU0                        24
 
 /* MSTP8 */
index e864aae0a2561c4bc3fac807c0edfc9d25b0a8dd..f047eaf261f34ac783b2187997894daffe552572 100644 (file)
 #define R8A7795_CLK_R                  45
 #define R8A7795_CLK_OSC                        46
 
+/* r8a7795 ES2.0 CPG Core Clocks */
+#define R8A7795_CLK_S0D2               47
+#define R8A7795_CLK_S0D3               48
+#define R8A7795_CLK_S0D6               49
+#define R8A7795_CLK_S0D8               50
+#define R8A7795_CLK_S0D12              51
+
 #endif /* __DT_BINDINGS_CLOCK_R8A7795_CPG_MSSR_H__ */
index ee702c8e4c091532480561cd5759a32f5fad8c01..d2b26a4b43ebde2eae06c6fd596895e5147adc76 100644 (file)
@@ -97,6 +97,7 @@
 #define SCLK_MAC2IO_SRC                99
 #define SCLK_MAC2IO            100
 #define SCLK_MAC2PHY           101
+#define SCLK_MAC2IO_EXT                102
 
 /* dclk gates */
 #define DCLK_LCDC              120
index 9c5dd9ba2f6cd9fa06c1870b7b0704a7eebff004..aeb83e581a11ec5af82df30cdcf167c3a45b964b 100644 (file)
 #define SCLK_I2S_8CH           82
 #define SCLK_SPDIF_8CH         83
 #define SCLK_I2S_2CH           84
-#define SCLK_TIMER0            85
-#define SCLK_TIMER1            86
-#define SCLK_TIMER2            87
-#define SCLK_TIMER3            88
-#define SCLK_TIMER4            89
-#define SCLK_TIMER5            90
-#define SCLK_TIMER6            91
+#define SCLK_TIMER00           85
+#define SCLK_TIMER01           86
+#define SCLK_TIMER02           87
+#define SCLK_TIMER03           88
+#define SCLK_TIMER04           89
+#define SCLK_TIMER05           90
 #define SCLK_OTGPHY0           93
 #define SCLK_OTG_ADP           96
 #define SCLK_HSICPHY480M       97
 #define SCLK_SFC               126
 #define SCLK_MAC               127
 #define SCLK_MACREF_OUT                128
+#define SCLK_TIMER10           133
+#define SCLK_TIMER11           134
+#define SCLK_TIMER12           135
+#define SCLK_TIMER13           136
+#define SCLK_TIMER14           137
+#define SCLK_TIMER15           138
 
 #define DCLK_VOP               190
 #define MCLK_CRYPTO            191
similarity index 97%
rename from include/dt-bindings/clock/rk1108-cru.h
rename to include/dt-bindings/clock/rv1108-cru.h
index 9350a5527a36c9dd05537b9f04792ebfbdb100ca..ae26f81059142867a009197e1c37c8e00d3dbd21 100644 (file)
@@ -13,8 +13,8 @@
  * GNU General Public License for more details.
  */
 
-#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RK1108_H
-#define _DT_BINDINGS_CLK_ROCKCHIP_RK1108_H
+#ifndef _DT_BINDINGS_CLK_ROCKCHIP_RV1108_H
+#define _DT_BINDINGS_CLK_ROCKCHIP_RV1108_H
 
 /* pll id */
 #define PLL_APLL                       0
 #define ARST_DSP_EDP_PERF              184
 #define ARST_DSP_EPP_PERF              185
 
-#endif /* _DT_BINDINGS_CLK_ROCKCHIP_RK1108_H */
+#endif /* _DT_BINDINGS_CLK_ROCKCHIP_RV1108_H */
index efb7ba2bd51510533006efe7f0c9f9dcb016e24c..c2afc41d69644af3d9f920a56341d62003630883 100644 (file)
@@ -91,7 +91,7 @@
 #define CLK_BUS_UART1          63
 #define CLK_BUS_UART2          64
 #define CLK_BUS_UART3          65
-#define CLK_BUS_SCR            66
+#define CLK_BUS_SCR0           66
 #define CLK_BUS_EPHY           67
 #define CLK_BUS_DBG            68
 
 
 #define CLK_GPU                        114
 
+/* New clocks imported in H5 */
+#define CLK_BUS_SCR1           115
+
 #endif /* _DT_BINDINGS_CLK_SUN8I_H3_H_ */
diff --git a/include/dt-bindings/clock/sun8i-r-ccu.h b/include/dt-bindings/clock/sun8i-r-ccu.h
new file mode 100644 (file)
index 0000000..779d20a
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2016 Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DT_BINDINGS_CLK_SUN8I_R_CCU_H_
+#define _DT_BINDINGS_CLK_SUN8I_R_CCU_H_
+
+#define CLK_AR100              0
+
+#define CLK_APB0_PIO           3
+#define CLK_APB0_IR            4
+#define CLK_APB0_TIMER         5
+#define CLK_APB0_RSB           6
+#define CLK_APB0_UART          7
+/* 8 is reserved for CLK_APB0_W1 on A31 */
+#define CLK_APB0_I2C           9
+#define CLK_APB0_TWD           10
+
+#define CLK_IR                 11
+
+#endif /* _DT_BINDINGS_CLK_SUN8I_R_CCU_H_ */
index 534c03f8ad72bc23675e0a4fe7761b2257f1b741..ed5ca218c8573e735ccb3fc96ebd9c0ad43dafc5 100644 (file)
 /* 133 */
 /* 134 */
 /* 135 */
-/* 136 */
+#define TEGRA114_CLK_CEC 136
 /* 137 */
 /* 138 */
 /* 139 */
index a2156090563f357ae6076a08639f14cb79469671..9352c7e2ce0ba6349b1d298b8356e2c04ba742fe 100644 (file)
 /* 133 */
 /* 134 */
 /* 135 */
-/* 136 */
+#define TEGRA124_CLK_CEC 136
 /* 137 */
 /* 138 */
 /* 139 */
index 35288b20f2c9cffcaebdf5075946b25dce6fad4b..46689cd3750bf11aed2115f4d34df9f1642ce265 100644 (file)
@@ -39,7 +39,7 @@
 /* 20 (register bit affects vi and vi_sensor) */
 /* 21 */
 #define TEGRA210_CLK_USBD 22
-#define TEGRA210_CLK_ISP 23
+#define TEGRA210_CLK_ISPA 23
 /* 24 */
 /* 25 */
 #define TEGRA210_CLK_DISP2 26
 /* 133 */
 /* 134 */
 /* 135 */
-/* 136 */
+#define TEGRA210_CLK_CEC 136
 /* 137 */
 /* 138 */
 /* 139 */
 #define TEGRA210_CLK_ENTROPY 149
 /* 150 */
 /* 151 */
-/* 152 */
+#define TEGRA210_CLK_DP2 152
 /* 153 */
 /* 154 */
 /* 155 (bit affects dfll_ref and dfll_soc) */
 #define TEGRA210_CLK_DBGAPB 185
 /* 186 */
 #define TEGRA210_CLK_PLL_P_OUT_ADSP 187
-/* 188 */
+/* 188 ((bit affects pll_a_out_adsp and pll_a_out0_out_adsp)*/
 #define TEGRA210_CLK_PLL_G_REF 189
 /* 190 */
 /* 191 */
 /* 196 */
 #define TEGRA210_CLK_DMIC3 197
 #define TEGRA210_CLK_APE 198
-/* 199 */
+#define TEGRA210_CLK_ADSP 199
 /* 200 */
 /* 201 */
 #define TEGRA210_CLK_MAUD 202
 /* 215 */
 /* 216 */
 /* 217 */
-/* 218 */
+#define TEGRA210_CLK_ADSP_NEON 218
 #define TEGRA210_CLK_NVENC 219
-/* 220 */
-/* 221 */
+#define TEGRA210_CLK_IQC2 220
+#define TEGRA210_CLK_IQC1 221
 #define TEGRA210_CLK_SOR_SAFE 222
 #define TEGRA210_CLK_PLL_P_OUT_CPU 223
 
 #define TEGRA210_CLK_PLL_RE_OUT1 319
 /* 320 */
 /* 321 */
-/* 322 */
-/* 323 */
-/* 324 */
+#define TEGRA210_CLK_ISP 322
+#define TEGRA210_CLK_PLL_A_OUT_ADSP 323
+#define TEGRA210_CLK_PLL_A_OUT0_OUT_ADSP 324
 /* 325 */
 /* 326 */
 /* 327 */
 #define TEGRA210_CLK_PLL_C_UD 364
 #define TEGRA210_CLK_SCLK_MUX 365
 
-#define TEGRA210_CLK_CLK_MAX 366
+#define TEGRA210_CLK_ACLK 370
+
+#define TEGRA210_CLK_DMIC1_SYNC_CLK 388
+#define TEGRA210_CLK_DMIC1_SYNC_CLK_MUX 389
+#define TEGRA210_CLK_DMIC2_SYNC_CLK 390
+#define TEGRA210_CLK_DMIC2_SYNC_CLK_MUX 391
+#define TEGRA210_CLK_DMIC3_SYNC_CLK 392
+#define TEGRA210_CLK_DMIC3_SYNC_CLK_MUX 393
+
+#define TEGRA210_CLK_CLK_MAX 394
 
 #endif /* _DT_BINDINGS_CLOCK_TEGRA210_CAR_H */
index 889e49ba0aa3de3f3b83ad27b1d0f4b12521a05a..7213354b9652c77f99fbd41a9a4c26d0bfb4662f 100644 (file)
 /* 133 */
 /* 134 */
 /* 135 */
-/* 136 */
+#define TEGRA30_CLK_CEC 136
 /* 137 */
 /* 138 */
 /* 139 */
diff --git a/include/dt-bindings/genpd/k2g.h b/include/dt-bindings/genpd/k2g.h
new file mode 100644 (file)
index 0000000..1f31f17
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * TI K2G SoC Device definitions
+ *
+ * Copyright (C) 2015-2017 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_GENPD_K2G_H
+#define _DT_BINDINGS_GENPD_K2G_H
+
+/* Documented in http://processors.wiki.ti.com/index.php/TISCI */
+
+#define K2G_DEV_PMMC0                  0x0000
+#define K2G_DEV_MLB0                   0x0001
+#define K2G_DEV_DSS0                   0x0002
+#define K2G_DEV_MCBSP0                 0x0003
+#define K2G_DEV_MCASP0                 0x0004
+#define K2G_DEV_MCASP1                 0x0005
+#define K2G_DEV_MCASP2                 0x0006
+#define K2G_DEV_DCAN0                  0x0008
+#define K2G_DEV_DCAN1                  0x0009
+#define K2G_DEV_EMIF0                  0x000a
+#define K2G_DEV_MMCHS0                 0x000b
+#define K2G_DEV_MMCHS1                 0x000c
+#define K2G_DEV_GPMC0                  0x000d
+#define K2G_DEV_ELM0                   0x000e
+#define K2G_DEV_SPI0                   0x0010
+#define K2G_DEV_SPI1                   0x0011
+#define K2G_DEV_SPI2                   0x0012
+#define K2G_DEV_SPI3                   0x0013
+#define K2G_DEV_ICSS0                  0x0014
+#define K2G_DEV_ICSS1                  0x0015
+#define K2G_DEV_USB0                   0x0016
+#define K2G_DEV_USB1                   0x0017
+#define K2G_DEV_NSS0                   0x0018
+#define K2G_DEV_PCIE0                  0x0019
+#define K2G_DEV_GPIO0                  0x001b
+#define K2G_DEV_GPIO1                  0x001c
+#define K2G_DEV_TIMER64_0              0x001d
+#define K2G_DEV_TIMER64_1              0x001e
+#define K2G_DEV_TIMER64_2              0x001f
+#define K2G_DEV_TIMER64_3              0x0020
+#define K2G_DEV_TIMER64_4              0x0021
+#define K2G_DEV_TIMER64_5              0x0022
+#define K2G_DEV_TIMER64_6              0x0023
+#define K2G_DEV_MSGMGR0                        0x0025
+#define K2G_DEV_BOOTCFG0               0x0026
+#define K2G_DEV_ARM_BOOTROM0           0x0027
+#define K2G_DEV_DSP_BOOTROM0           0x0029
+#define K2G_DEV_DEBUGSS0               0x002b
+#define K2G_DEV_UART0                  0x002c
+#define K2G_DEV_UART1                  0x002d
+#define K2G_DEV_UART2                  0x002e
+#define K2G_DEV_EHRPWM0                        0x002f
+#define K2G_DEV_EHRPWM1                        0x0030
+#define K2G_DEV_EHRPWM2                        0x0031
+#define K2G_DEV_EHRPWM3                        0x0032
+#define K2G_DEV_EHRPWM4                        0x0033
+#define K2G_DEV_EHRPWM5                        0x0034
+#define K2G_DEV_EQEP0                  0x0035
+#define K2G_DEV_EQEP1                  0x0036
+#define K2G_DEV_EQEP2                  0x0037
+#define K2G_DEV_ECAP0                  0x0038
+#define K2G_DEV_ECAP1                  0x0039
+#define K2G_DEV_I2C0                   0x003a
+#define K2G_DEV_I2C1                   0x003b
+#define K2G_DEV_I2C2                   0x003c
+#define K2G_DEV_EDMA0                  0x003f
+#define K2G_DEV_SEMAPHORE0             0x0040
+#define K2G_DEV_INTC0                  0x0041
+#define K2G_DEV_GIC0                   0x0042
+#define K2G_DEV_QSPI0                  0x0043
+#define K2G_DEV_ARM_64B_COUNTER0       0x0044
+#define K2G_DEV_TETRIS0                        0x0045
+#define K2G_DEV_CGEM0                  0x0046
+#define K2G_DEV_MSMC0                  0x0047
+#define K2G_DEV_CBASS0                 0x0049
+#define K2G_DEV_BOARD0                 0x004c
+#define K2G_DEV_EDMA1                  0x004f
+
+#endif
diff --git a/include/dt-bindings/mfd/stm32f7-rcc.h b/include/dt-bindings/mfd/stm32f7-rcc.h
new file mode 100644 (file)
index 0000000..e36cc69
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * This header provides constants for the STM32F7 RCC IP
+ */
+
+#ifndef _DT_BINDINGS_MFD_STM32F7_RCC_H
+#define _DT_BINDINGS_MFD_STM32F7_RCC_H
+
+/* AHB1 */
+#define STM32F7_RCC_AHB1_GPIOA         0
+#define STM32F7_RCC_AHB1_GPIOB         1
+#define STM32F7_RCC_AHB1_GPIOC         2
+#define STM32F7_RCC_AHB1_GPIOD         3
+#define STM32F7_RCC_AHB1_GPIOE         4
+#define STM32F7_RCC_AHB1_GPIOF         5
+#define STM32F7_RCC_AHB1_GPIOG         6
+#define STM32F7_RCC_AHB1_GPIOH         7
+#define STM32F7_RCC_AHB1_GPIOI         8
+#define STM32F7_RCC_AHB1_GPIOJ         9
+#define STM32F7_RCC_AHB1_GPIOK         10
+#define STM32F7_RCC_AHB1_CRC           12
+#define STM32F7_RCC_AHB1_BKPSRAM       18
+#define STM32F7_RCC_AHB1_DTCMRAM       20
+#define STM32F7_RCC_AHB1_DMA1          21
+#define STM32F7_RCC_AHB1_DMA2          22
+#define STM32F7_RCC_AHB1_DMA2D         23
+#define STM32F7_RCC_AHB1_ETHMAC                25
+#define STM32F7_RCC_AHB1_ETHMACTX      26
+#define STM32F7_RCC_AHB1_ETHMACRX      27
+#define STM32FF_RCC_AHB1_ETHMACPTP     28
+#define STM32F7_RCC_AHB1_OTGHS         29
+#define STM32F7_RCC_AHB1_OTGHSULPI     30
+
+#define STM32F7_AHB1_RESET(bit) (STM32F7_RCC_AHB1_##bit + (0x10 * 8))
+#define STM32F7_AHB1_CLOCK(bit) (STM32F7_RCC_AHB1_##bit)
+
+
+/* AHB2 */
+#define STM32F7_RCC_AHB2_DCMI          0
+#define STM32F7_RCC_AHB2_CRYP          4
+#define STM32F7_RCC_AHB2_HASH          5
+#define STM32F7_RCC_AHB2_RNG           6
+#define STM32F7_RCC_AHB2_OTGFS         7
+
+#define STM32F7_AHB2_RESET(bit)        (STM32F7_RCC_AHB2_##bit + (0x14 * 8))
+#define STM32F7_AHB2_CLOCK(bit)        (STM32F7_RCC_AHB2_##bit + 0x20)
+
+/* AHB3 */
+#define STM32F7_RCC_AHB3_FMC           0
+#define STM32F7_RCC_AHB3_QSPI          1
+
+#define STM32F7_AHB3_RESET(bit)        (STM32F7_RCC_AHB3_##bit + (0x18 * 8))
+#define STM32F7_AHB3_CLOCK(bit)        (STM32F7_RCC_AHB3_##bit + 0x40)
+
+/* APB1 */
+#define STM32F7_RCC_APB1_TIM2          0
+#define STM32F7_RCC_APB1_TIM3          1
+#define STM32F7_RCC_APB1_TIM4          2
+#define STM32F7_RCC_APB1_TIM5          3
+#define STM32F7_RCC_APB1_TIM6          4
+#define STM32F7_RCC_APB1_TIM7          5
+#define STM32F7_RCC_APB1_TIM12         6
+#define STM32F7_RCC_APB1_TIM13         7
+#define STM32F7_RCC_APB1_TIM14         8
+#define STM32F7_RCC_APB1_LPTIM1                9
+#define STM32F7_RCC_APB1_WWDG          11
+#define STM32F7_RCC_APB1_SPI2          14
+#define STM32F7_RCC_APB1_SPI3          15
+#define STM32F7_RCC_APB1_SPDIFRX       16
+#define STM32F7_RCC_APB1_UART2         17
+#define STM32F7_RCC_APB1_UART3         18
+#define STM32F7_RCC_APB1_UART4         19
+#define STM32F7_RCC_APB1_UART5         20
+#define STM32F7_RCC_APB1_I2C1          21
+#define STM32F7_RCC_APB1_I2C2          22
+#define STM32F7_RCC_APB1_I2C3          23
+#define STM32F7_RCC_APB1_I2C4          24
+#define STM32F7_RCC_APB1_CAN1          25
+#define STM32F7_RCC_APB1_CAN2          26
+#define STM32F7_RCC_APB1_CEC           27
+#define STM32F7_RCC_APB1_PWR           28
+#define STM32F7_RCC_APB1_DAC           29
+#define STM32F7_RCC_APB1_UART7         30
+#define STM32F7_RCC_APB1_UART8         31
+
+#define STM32F7_APB1_RESET(bit)        (STM32F7_RCC_APB1_##bit + (0x20 * 8))
+#define STM32F7_APB1_CLOCK(bit)        (STM32F7_RCC_APB1_##bit + 0x80)
+
+/* APB2 */
+#define STM32F7_RCC_APB2_TIM1          0
+#define STM32F7_RCC_APB2_TIM8          1
+#define STM32F7_RCC_APB2_USART1                4
+#define STM32F7_RCC_APB2_USART6                5
+#define STM32F7_RCC_APB2_ADC1          8
+#define STM32F7_RCC_APB2_ADC2          9
+#define STM32F7_RCC_APB2_ADC3          10
+#define STM32F7_RCC_APB2_SDMMC1                11
+#define STM32F7_RCC_APB2_SPI1          12
+#define STM32F7_RCC_APB2_SPI4          13
+#define STM32F7_RCC_APB2_SYSCFG                14
+#define STM32F7_RCC_APB2_TIM9          16
+#define STM32F7_RCC_APB2_TIM10         17
+#define STM32F7_RCC_APB2_TIM11         18
+#define STM32F7_RCC_APB2_SPI5          20
+#define STM32F7_RCC_APB2_SPI6          21
+#define STM32F7_RCC_APB2_SAI1          22
+#define STM32F7_RCC_APB2_SAI2          23
+#define STM32F7_RCC_APB2_LTDC          26
+
+#define STM32F7_APB2_RESET(bit)        (STM32F7_RCC_APB2_##bit + (0x24 * 8))
+#define STM32F7_APB2_CLOCK(bit)        (STM32F7_RCC_APB2_##bit + 0xA0)
+
+#endif /* _DT_BINDINGS_MFD_STM32F7_RCC_H */
index 38f1ea879ea136685f6a2b03d1087f0cdf8dd7ae..0359bfdc9119720e80f6e703f39ac30f0091fb12 100644 (file)
 #define DRIVE4_08MA    (4 << 4)
 #define DRIVE4_10MA    (6 << 4)
 
+/* drive strength definition for hi3660 */
+#define DRIVE6_MASK    (15 << 4)
+#define DRIVE6_04MA    (0 << 4)
+#define DRIVE6_12MA    (4 << 4)
+#define DRIVE6_19MA    (8 << 4)
+#define DRIVE6_27MA    (10 << 4)
+#define DRIVE6_32MA    (15 << 4)
+#define DRIVE7_02MA    (0 << 4)
+#define DRIVE7_04MA    (1 << 4)
+#define DRIVE7_06MA    (2 << 4)
+#define DRIVE7_08MA    (3 << 4)
+#define DRIVE7_10MA    (4 << 4)
+#define DRIVE7_12MA    (5 << 4)
+#define DRIVE7_14MA    (6 << 4)
+#define DRIVE7_16MA    (7 << 4)
 #endif
diff --git a/include/dt-bindings/power/imx7-power.h b/include/dt-bindings/power/imx7-power.h
new file mode 100644 (file)
index 0000000..3a181e4
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ *  Copyright (C) 2017 Impinj
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __DT_BINDINGS_IMX7_POWER_H__
+#define __DT_BINDINGS_IMX7_POWER_H__
+
+#define IMX7_POWER_DOMAIN_MIPI_PHY             0
+#define IMX7_POWER_DOMAIN_PCIE_PHY             1
+#define IMX7_POWER_DOMAIN_USB_HSIC_PHY         2
+
+#endif
index ee2e26ba605ef9a37801d1b2858506f8d17864cb..ad679eeda1370a9dec9dd21c0fae84c1cb53a150 100644 (file)
@@ -33,7 +33,7 @@
 #define R8A7795_PD_CA53_SCU            21
 #define R8A7795_PD_3DG_E               22
 #define R8A7795_PD_A3IR                        24
-#define R8A7795_PD_A2VC0               25
+#define R8A7795_PD_A2VC0               25      /* ES1.x only */
 #define R8A7795_PD_A2VC1               26
 
 /* Always-on power area */
similarity index 56%
rename from arch/nios2/include/asm/prom.h
rename to include/dt-bindings/reset/altr,rst-mgr-a10sr.h
index 75fffb42cfa5a275520cf448c7ed3283a1f9e722..9855925e5256a7b9d5ece637b605b8ff937ec99a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright Altera Corporation (C) <2015>. All rights reserved
+ *  Copyright Intel Corporation (C) 2017. All Rights Reserved
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
  *
  * You should have received a copy of the GNU General Public License along with
  * this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Reset binding definitions for Altera Arria10 MAX5 System Resource Chip
+ *
+ * Adapted from altr,rst-mgr-a10.h
  */
 
-#ifndef __ASM_NIOS2_PROM_H__
-#define __ASM_NIOS2_PROM_H__
+#ifndef _DT_BINDINGS_RESET_ALTR_RST_MGR_A10SR_H
+#define _DT_BINDINGS_RESET_ALTR_RST_MGR_A10SR_H
+
+/* Peripheral PHY resets */
+#define A10SR_RESET_ENET_HPS   0
+#define A10SR_RESET_PCIE       1
+#define A10SR_RESET_FILE       2
+#define A10SR_RESET_BQSPI      3
+#define A10SR_RESET_USB                4
 
-extern unsigned long __init of_early_console(void);
+#define A10SR_RESET_NUM                5
 
 #endif
diff --git a/include/dt-bindings/reset/imx7-reset.h b/include/dt-bindings/reset/imx7-reset.h
new file mode 100644 (file)
index 0000000..6394817
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2017 Impinj, Inc.
+ *
+ * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef DT_BINDING_RESET_IMX7_H
+#define DT_BINDING_RESET_IMX7_H
+
+#define IMX7_RESET_A7_CORE_POR_RESET0  0
+#define IMX7_RESET_A7_CORE_POR_RESET1  1
+#define IMX7_RESET_A7_CORE_RESET0      2
+#define IMX7_RESET_A7_CORE_RESET1      3
+#define IMX7_RESET_A7_DBG_RESET0       4
+#define IMX7_RESET_A7_DBG_RESET1       5
+#define IMX7_RESET_A7_ETM_RESET0       6
+#define IMX7_RESET_A7_ETM_RESET1       7
+#define IMX7_RESET_A7_SOC_DBG_RESET    8
+#define IMX7_RESET_A7_L2RESET          9
+#define IMX7_RESET_SW_M4C_RST          10
+#define IMX7_RESET_SW_M4P_RST          11
+#define IMX7_RESET_EIM_RST             12
+#define IMX7_RESET_HSICPHY_PORT_RST    13
+#define IMX7_RESET_USBPHY1_POR         14
+#define IMX7_RESET_USBPHY1_PORT_RST    15
+#define IMX7_RESET_USBPHY2_POR         16
+#define IMX7_RESET_USBPHY2_PORT_RST    17
+#define IMX7_RESET_MIPI_PHY_MRST       18
+#define IMX7_RESET_MIPI_PHY_SRST       19
+
+/*
+ * IMX7_RESET_PCIEPHY is a logical reset line combining PCIEPHY_BTN
+ * and PCIEPHY_G_RST
+ */
+#define IMX7_RESET_PCIEPHY             20
+#define IMX7_RESET_PCIEPHY_PERST       21
+
+/*
+ * IMX7_RESET_PCIE_CTRL_APPS_EN is not strictly a reset line, but it
+ * can be used to inhibit PCIe LTTSM, so, in a way, it can be thoguht
+ * of as one
+ */
+#define IMX7_RESET_PCIE_CTRL_APPS_EN   22
+#define IMX7_RESET_DDRC_PRST           23
+#define IMX7_RESET_DDRC_CORE_RST       24
+
+#define IMX7_RESET_NUM                 25
+
+#endif
+
index aaf03057f755c3657e779f24bb821c150a82f413..21deb547cfa404cdc544936dafbbe09b24a7ef4d 100644 (file)
 #define MT2701_HIFSYS_PCIE1_RST                        25
 #define MT2701_HIFSYS_PCIE2_RST                        26
 
+/* ETHSYS resets */
+#define MT2701_ETHSYS_SYS_RST                  0
+#define MT2701_ETHSYS_MCM_RST                  2
+#define MT2701_ETHSYS_FE_RST                   6
+#define MT2701_ETHSYS_GMAC_RST                 23
+#define MT2701_ETHSYS_PPE_RST                  31
+
 #endif  /* _DT_BINDINGS_RESET_CONTROLLER_MT2701 */
index 6b7af80c26ec610d5db90a19efc05022340911e1..484c2a22919d7270aeaed71ec0bf3151c38fb873 100644 (file)
@@ -98,6 +98,9 @@
 #define RST_BUS_UART1          50
 #define RST_BUS_UART2          51
 #define RST_BUS_UART3          52
-#define RST_BUS_SCR            53
+#define RST_BUS_SCR0           53
+
+/* New resets imported in H5 */
+#define RST_BUS_SCR1           54
 
 #endif /* _DT_BINDINGS_RST_SUN8I_H3_H_ */
diff --git a/include/dt-bindings/reset/sun8i-r-ccu.h b/include/dt-bindings/reset/sun8i-r-ccu.h
new file mode 100644 (file)
index 0000000..4ba64f3
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2016 Icenowy Zheng <icenowy@aosc.xyz>
+ *
+ * This file is dual-licensed: you can use it either under the terms
+ * of the GPL or the X11 license, at your option. Note that this dual
+ * licensing only applies to this file, and not this project as a
+ * whole.
+ *
+ *  a) This file is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License as
+ *     published by the Free Software Foundation; either version 2 of the
+ *     License, or (at your option) any later version.
+ *
+ *     This file is distributed in the hope that it will be useful,
+ *     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *     GNU General Public License for more details.
+ *
+ * Or, alternatively,
+ *
+ *  b) Permission is hereby granted, free of charge, to any person
+ *     obtaining a copy of this software and associated documentation
+ *     files (the "Software"), to deal in the Software without
+ *     restriction, including without limitation the rights to use,
+ *     copy, modify, merge, publish, distribute, sublicense, and/or
+ *     sell copies of the Software, and to permit persons to whom the
+ *     Software is furnished to do so, subject to the following
+ *     conditions:
+ *
+ *     The above copyright notice and this permission notice shall be
+ *     included in all copies or substantial portions of the Software.
+ *
+ *     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ *     EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ *     OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ *     NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ *     HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ *     WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ *     FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ *     OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _DT_BINDINGS_RST_SUN8I_R_CCU_H_
+#define _DT_BINDINGS_RST_SUN8I_R_CCU_H_
+
+#define RST_APB0_IR            0
+#define RST_APB0_TIMER         1
+#define RST_APB0_RSB           2
+#define RST_APB0_UART          3
+/* 4 is reserved for RST_APB0_W1 on A31 */
+#define RST_APB0_I2C           5
+
+#endif /* _DT_BINDINGS_RST_SUN8I_R_CCU_H_ */
diff --git a/include/dt-bindings/reset/tegra210-car.h b/include/dt-bindings/reset/tegra210-car.h
new file mode 100644 (file)
index 0000000..296ec6e
--- /dev/null
@@ -0,0 +1,13 @@
+/*
+ * This header provides Tegra210-specific constants for binding
+ * nvidia,tegra210-car.
+ */
+
+#ifndef _DT_BINDINGS_RESET_TEGRA210_CAR_H
+#define _DT_BINDINGS_RESET_TEGRA210_CAR_H
+
+#define TEGRA210_RESET(x)              (7 * 32 + (x))
+#define TEGRA210_RST_DFLL_DVCO         TEGRA210_RESET(0)
+#define TEGRA210_RST_ADSP              TEGRA210_RESET(1)
+
+#endif /* _DT_BINDINGS_RESET_TEGRA210_CAR_H */
index 581a59ea7e346a60d99539b6b9e8c30f975919d0..ef718586321ce0dea03aabe8b114beca9cb71a74 100644 (file)
@@ -148,7 +148,6 @@ struct vgic_its {
        gpa_t                   vgic_its_base;
 
        bool                    enabled;
-       bool                    initialized;
        struct vgic_io_device   iodev;
        struct kvm_device       *dev;
 
@@ -162,6 +161,9 @@ struct vgic_its {
        u32                     creadr;
        u32                     cwriter;
 
+       /* migration ABI revision in use */
+       u32                     abi_rev;
+
        /* Protects the device and collection lists */
        struct mutex            its_lock;
        struct list_head        device_list;
@@ -193,7 +195,10 @@ struct vgic_dist {
                /* either a GICv2 CPU interface */
                gpa_t                   vgic_cpu_base;
                /* or a number of GICv3 redistributor regions */
-               gpa_t                   vgic_redist_base;
+               struct {
+                       gpa_t           vgic_redist_base;
+                       gpa_t           vgic_redist_free_offset;
+               };
        };
 
        /* distributor enabled */
@@ -283,6 +288,7 @@ extern struct static_key_false vgic_v2_cpuif_trap;
 
 int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
 void kvm_vgic_early_init(struct kvm *kvm);
+int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu);
 int kvm_vgic_create(struct kvm *kvm, u32 type);
 void kvm_vgic_destroy(struct kvm *kvm);
 void kvm_vgic_vcpu_early_init(struct kvm_vcpu *vcpu);
index 0f9de30d725fc225e686ec95c5c73e5ccee9b572..137e4a3d89c5225dc6a9535265f13e874bdbb8eb 100644 (file)
@@ -770,8 +770,11 @@ static inline enum dev_dma_attr acpi_get_dma_attr(struct acpi_device *adev)
        return DEV_DMA_NOT_SUPPORTED;
 }
 
-static inline void acpi_dma_configure(struct device *dev,
-                                     enum dev_dma_attr attr) { }
+static inline int acpi_dma_configure(struct device *dev,
+                                    enum dev_dma_attr attr)
+{
+       return 0;
+}
 
 static inline void acpi_dma_deconfigure(struct device *dev) { }
 
index 26e25d85eb3ea495eaac548bedcc5e379c00dbb5..3ff9acea86161ae51fde3953de6bf27b8f5ebca0 100644 (file)
@@ -55,7 +55,4 @@ const struct iommu_ops *iort_iommu_configure(struct device *dev)
 { return NULL; }
 #endif
 
-#define IORT_ACPI_DECLARE(name, table_id, fn)          \
-       ACPI_DECLARE_PROBE_ENTRY(iort, name, table_id, 0, NULL, 0, fn)
-
 #endif /* __ACPI_IORT_H__ */
index 91b84a7f053933089e63224aea1f616809b8af57..580b5323a717bfe720919ffba7f093d8e389c957 100644 (file)
 #define PL080_SOFT_LSREQ                       (0x2C)
 
 #define PL080_CONFIG                           (0x30)
-#define PL080_CONFIG_M2_BE                     (1 << 2)
-#define PL080_CONFIG_M1_BE                     (1 << 1)
-#define PL080_CONFIG_ENABLE                    (1 << 0)
+#define PL080_CONFIG_M2_BE                     BIT(2)
+#define PL080_CONFIG_M1_BE                     BIT(1)
+#define PL080_CONFIG_ENABLE                    BIT(0)
 
 #define PL080_SYNC                             (0x34)
 
 /* Per channel configuration registers */
 
-#define PL080_Cx_STRIDE                                (0x20)
+/* Per channel configuration registers */
 #define PL080_Cx_BASE(x)                       ((0x100 + (x * 0x20)))
-#define PL080_Cx_SRC_ADDR(x)                   ((0x100 + (x * 0x20)))
-#define PL080_Cx_DST_ADDR(x)                   ((0x104 + (x * 0x20)))
-#define PL080_Cx_LLI(x)                                ((0x108 + (x * 0x20)))
-#define PL080_Cx_CONTROL(x)                    ((0x10C + (x * 0x20)))
-#define PL080_Cx_CONFIG(x)                     ((0x110 + (x * 0x20)))
-#define PL080S_Cx_CONTROL2(x)                  ((0x110 + (x * 0x20)))
-#define PL080S_Cx_CONFIG(x)                    ((0x114 + (x * 0x20)))
-
 #define PL080_CH_SRC_ADDR                      (0x00)
 #define PL080_CH_DST_ADDR                      (0x04)
 #define PL080_CH_LLI                           (0x08)
 
 #define PL080_LLI_ADDR_MASK                    (0x3fffffff << 2)
 #define PL080_LLI_ADDR_SHIFT                   (2)
-#define PL080_LLI_LM_AHB2                      (1 << 0)
+#define PL080_LLI_LM_AHB2                      BIT(0)
 
-#define PL080_CONTROL_TC_IRQ_EN                        (1 << 31)
+#define PL080_CONTROL_TC_IRQ_EN                        BIT(31)
 #define PL080_CONTROL_PROT_MASK                        (0x7 << 28)
 #define PL080_CONTROL_PROT_SHIFT               (28)
-#define PL080_CONTROL_PROT_CACHE               (1 << 30)
-#define PL080_CONTROL_PROT_BUFF                        (1 << 29)
-#define PL080_CONTROL_PROT_SYS                 (1 << 28)
-#define PL080_CONTROL_DST_INCR                 (1 << 27)
-#define PL080_CONTROL_SRC_INCR                 (1 << 26)
-#define PL080_CONTROL_DST_AHB2                 (1 << 25)
-#define PL080_CONTROL_SRC_AHB2                 (1 << 24)
+#define PL080_CONTROL_PROT_CACHE               BIT(30)
+#define PL080_CONTROL_PROT_BUFF                        BIT(29)
+#define PL080_CONTROL_PROT_SYS                 BIT(28)
+#define PL080_CONTROL_DST_INCR                 BIT(27)
+#define PL080_CONTROL_SRC_INCR                 BIT(26)
+#define PL080_CONTROL_DST_AHB2                 BIT(25)
+#define PL080_CONTROL_SRC_AHB2                 BIT(24)
 #define PL080_CONTROL_DWIDTH_MASK              (0x7 << 21)
 #define PL080_CONTROL_DWIDTH_SHIFT             (21)
 #define PL080_CONTROL_SWIDTH_MASK              (0x7 << 18)
 #define PL080_WIDTH_16BIT                      (0x1)
 #define PL080_WIDTH_32BIT                      (0x2)
 
-#define PL080N_CONFIG_ITPROT                   (1 << 20)
-#define PL080N_CONFIG_SECPROT                  (1 << 19)
-#define PL080_CONFIG_HALT                      (1 << 18)
-#define PL080_CONFIG_ACTIVE                    (1 << 17)  /* RO */
-#define PL080_CONFIG_LOCK                      (1 << 16)
-#define PL080_CONFIG_TC_IRQ_MASK               (1 << 15)
-#define PL080_CONFIG_ERR_IRQ_MASK              (1 << 14)
+#define PL080N_CONFIG_ITPROT                   BIT(20)
+#define PL080N_CONFIG_SECPROT                  BIT(19)
+#define PL080_CONFIG_HALT                      BIT(18)
+#define PL080_CONFIG_ACTIVE                    BIT(17)  /* RO */
+#define PL080_CONFIG_LOCK                      BIT(16)
+#define PL080_CONFIG_TC_IRQ_MASK               BIT(15)
+#define PL080_CONFIG_ERR_IRQ_MASK              BIT(14)
 #define PL080_CONFIG_FLOW_CONTROL_MASK         (0x7 << 11)
 #define PL080_CONFIG_FLOW_CONTROL_SHIFT                (11)
 #define PL080_CONFIG_DST_SEL_MASK              (0xf << 6)
 #define PL080_CONFIG_DST_SEL_SHIFT             (6)
 #define PL080_CONFIG_SRC_SEL_MASK              (0xf << 1)
 #define PL080_CONFIG_SRC_SEL_SHIFT             (1)
-#define PL080_CONFIG_ENABLE                    (1 << 0)
+#define PL080_CONFIG_ENABLE                    BIT(0)
 
 #define PL080_FLOW_MEM2MEM                     (0x0)
 #define PL080_FLOW_MEM2PER                     (0x1)
diff --git a/include/linux/amba/pl330.h b/include/linux/amba/pl330.h
deleted file mode 100644 (file)
index fe93758..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/* linux/include/linux/amba/pl330.h
- *
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *     Jaswinder Singh <jassi.brar@samsung.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
-
-#ifndef        __AMBA_PL330_H_
-#define        __AMBA_PL330_H_
-
-#include <linux/dmaengine.h>
-
-struct dma_pl330_platdata {
-       /*
-        * Number of valid peripherals connected to DMAC.
-        * This may be different from the value read from
-        * CR0, as the PL330 implementation might have 'holes'
-        * in the peri list or the peri could also be reached
-        * from another DMAC which the platform prefers.
-        */
-       u8 nr_valid_peri;
-       /* Array of valid peripherals */
-       u8 *peri_id;
-       /* Operational capabilities */
-       dma_cap_mask_t cap_mask;
-       /* Bytes to allocate for MC buffer */
-       unsigned mcbuf_sz;
-};
-
-extern bool pl330_filter(struct dma_chan *chan, void *param);
-#endif /* __AMBA_PL330_H_ */
index 9657f11d48a7547cbf63639c23f0de9bc07920c4..bca6a5e4ca3db3a6370b83621c80bb5ca876f27a 100644 (file)
@@ -80,7 +80,7 @@ struct pci_dev;
 #define  BCMA_CORE_PCI_MDIODATA_DEV_TX         0x1e    /* SERDES TX Dev */
 #define  BCMA_CORE_PCI_MDIODATA_DEV_RX         0x1f    /* SERDES RX Dev */
 #define BCMA_CORE_PCI_PCIEIND_ADDR             0x0130  /* indirect access to the internal register */
-#define BCMA_CORE_PCI_PCIEIND_DATA             0x0134  /* Data to/from the internal regsiter */
+#define BCMA_CORE_PCI_PCIEIND_DATA             0x0134  /* Data to/from the internal register */
 #define BCMA_CORE_PCI_CLKREQENCTRL             0x0138  /*  >= rev 6, Clkreq rdma control */
 #define BCMA_CORE_PCI_PCICFG0                  0x0400  /* PCI config space 0 (rev >= 8) */
 #define BCMA_CORE_PCI_PCICFG1                  0x0500  /* PCI config space 1 (rev >= 8) */
index b5d1e27631eef8f827093ef2d0749af3f8abf587..ab92c4ea138b7c665c45b765c0e1f8a4958339ca 100644 (file)
@@ -1947,8 +1947,6 @@ extern int __blkdev_driver_ioctl(struct block_device *, fmode_t, unsigned int,
 extern int bdev_read_page(struct block_device *, sector_t, struct page *);
 extern int bdev_write_page(struct block_device *, sector_t, struct page *,
                                                struct writeback_control *);
-extern int bdev_dax_supported(struct super_block *, int);
-int bdev_dax_pgoff(struct block_device *, sector_t, size_t, pgoff_t *pgoff);
 #else /* CONFIG_BLOCK */
 
 struct block_device;
index 5efb4db44e1ef3223d984296ccf1ca0737224d10..d5093b52b4855f5ec0fbd6d29df265da80945a68 100644 (file)
@@ -40,6 +40,9 @@ struct bpf_reg_state {
         */
        s64 min_value;
        u64 max_value;
+       u32 min_align;
+       u32 aux_off;
+       u32 aux_off_align;
 };
 
 enum bpf_stack_slot_type {
@@ -87,6 +90,7 @@ struct bpf_verifier_env {
        struct bpf_prog *prog;          /* eBPF program being verified */
        struct bpf_verifier_stack_elem *head; /* stack of verifier states to be processed */
        int stack_size;                 /* number of states to be processed */
+       bool strict_alignment;          /* perform strict pointer alignment checks */
        struct bpf_verifier_state cur_state; /* current verifier state */
        struct bpf_verifier_state_list **explored_states; /* search pruning optimization */
        const struct bpf_ext_analyzer_ops *analyzer_ops; /* external analyzer ops */
index 79591c3660cc1dc61e1e3f4b501c470161c41eb9..bd029e52ef5ee232f77ff28ef3a7b4ec391f1d71 100644 (file)
@@ -196,8 +196,6 @@ void ll_rw_block(int, int, int, struct buffer_head * bh[]);
 int sync_dirty_buffer(struct buffer_head *bh);
 int __sync_dirty_buffer(struct buffer_head *bh, int op_flags);
 void write_dirty_buffer(struct buffer_head *bh, int op_flags);
-int _submit_bh(int op, int op_flags, struct buffer_head *bh,
-              unsigned long bio_flags);
 int submit_bh(int, int, struct buffer_head *);
 void write_boundary_block(struct block_device *bdev,
                        sector_t bblock, unsigned blocksize);
index ae2f66833762cd7d63bd77eafb9aed13b6ab2308..fd8b2953c78f85539104fd3741e82a9f37e1e1b5 100644 (file)
@@ -105,8 +105,10 @@ static inline u64 ceph_sanitize_features(u64 features)
  */
 #define CEPH_FEATURES_SUPPORTED_DEFAULT                \
        (CEPH_FEATURE_NOSRCADDR |               \
+        CEPH_FEATURE_FLOCK |                   \
         CEPH_FEATURE_SUBSCRIBE2 |              \
         CEPH_FEATURE_RECONNECT_SEQ |           \
+        CEPH_FEATURE_DIRLAYOUTHASH |           \
         CEPH_FEATURE_PGID64 |                  \
         CEPH_FEATURE_PGPOOL3 |                 \
         CEPH_FEATURE_OSDENC |                  \
@@ -114,11 +116,13 @@ static inline u64 ceph_sanitize_features(u64 features)
         CEPH_FEATURE_MSG_AUTH |                \
         CEPH_FEATURE_CRUSH_TUNABLES2 |         \
         CEPH_FEATURE_REPLY_CREATE_INODE |      \
+        CEPH_FEATURE_MDSENC |                  \
         CEPH_FEATURE_OSDHASHPSPOOL |           \
         CEPH_FEATURE_OSD_CACHEPOOL |           \
         CEPH_FEATURE_CRUSH_V2 |                \
         CEPH_FEATURE_EXPORT_PEER |             \
         CEPH_FEATURE_OSDMAP_ENC |              \
+        CEPH_FEATURE_MDS_INLINE_DATA |         \
         CEPH_FEATURE_CRUSH_TUNABLES3 |         \
         CEPH_FEATURE_OSD_PRIMARY_AFFINITY |    \
         CEPH_FEATURE_MSGR_KEEPALIVE2 |         \
index f4b2ee18f38cbd51d2ded16380e15da7697d9f89..ad078ebe25d6beaad4a80cc906be78c3dd26c06e 100644 (file)
@@ -365,6 +365,19 @@ extern const char *ceph_mds_op_name(int op);
 #define CEPH_READDIR_FRAG_END          (1<<0)
 #define CEPH_READDIR_FRAG_COMPLETE     (1<<8)
 #define CEPH_READDIR_HASH_ORDER                (1<<9)
+#define CEPH_READDIR_OFFSET_HASH       (1<<10)
+
+/*
+ * open request flags
+ */
+#define CEPH_O_RDONLY          00000000
+#define CEPH_O_WRONLY          00000001
+#define CEPH_O_RDWR            00000002
+#define CEPH_O_CREAT           00000100
+#define CEPH_O_EXCL            00000200
+#define CEPH_O_TRUNC           00001000
+#define CEPH_O_DIRECTORY       00200000
+#define CEPH_O_NOFOLLOW                00400000
 
 union ceph_mds_request_args {
        struct {
@@ -384,6 +397,7 @@ union ceph_mds_request_args {
                __le32 max_entries;          /* how many dentries to grab */
                __le32 max_bytes;
                __le16 flags;
+               __le32 offset_hash;
        } __attribute__ ((packed)) readdir;
        struct {
                __le32 mode;
index 84884d8d4710bc568b1590e2ede3775c863e63a1..0594d3bba774c5a78c0bc7e4fde5fbd741bd1c17 100644 (file)
@@ -37,6 +37,11 @@ int ceph_cls_break_lock(struct ceph_osd_client *osdc,
                        struct ceph_object_locator *oloc,
                        char *lock_name, char *cookie,
                        struct ceph_entity_name *locker);
+int ceph_cls_set_cookie(struct ceph_osd_client *osdc,
+                       struct ceph_object_id *oid,
+                       struct ceph_object_locator *oloc,
+                       char *lock_name, u8 type, char *old_cookie,
+                       char *tag, char *new_cookie);
 
 void ceph_free_lockers(struct ceph_locker *lockers, u32 num_lockers);
 
index 88cd5dc8e238a2fa7e8c66a034a8e5b0ae248f21..3229ae6c78469019f0eb747c4e09a10137e26b0f 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/wait.h>
 #include <linux/writeback.h>
 #include <linux/slab.h>
+#include <linux/refcount.h>
 
 #include <linux/ceph/types.h>
 #include <linux/ceph/messenger.h>
@@ -161,7 +162,7 @@ struct ceph_client {
  * dirtied.
  */
 struct ceph_snap_context {
-       atomic_t nref;
+       refcount_t nref;
        u64 seq;
        u32 num_snaps;
        u64 snaps[];
@@ -262,10 +263,7 @@ int ceph_print_client_options(struct seq_file *m, struct ceph_client *client);
 extern void ceph_destroy_options(struct ceph_options *opt);
 extern int ceph_compare_options(struct ceph_options *new_opt,
                                struct ceph_client *client);
-extern struct ceph_client *ceph_create_client(struct ceph_options *opt,
-                                             void *private,
-                                             u64 supported_features,
-                                             u64 required_features);
+struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private);
 struct ceph_entity_addr *ceph_client_addr(struct ceph_client *client);
 u64 ceph_client_gid(struct ceph_client *client);
 extern void ceph_destroy_client(struct ceph_client *client);
index 8ed5dc505fbb2e0672efd81089d1e35caf8e062c..d5f783f3226a8deb43f9336e7fe3c1b955b0e137 100644 (file)
@@ -25,6 +25,7 @@ struct ceph_mdsmap {
        u32 m_session_autoclose;        /* seconds */
        u64 m_max_file_size;
        u32 m_max_mds;                  /* size of m_addr, m_state arrays */
+       int m_num_mds;
        struct ceph_mds_info *m_info;
 
        /* which object pools file data can be stored in */
@@ -40,7 +41,7 @@ struct ceph_mdsmap {
 static inline struct ceph_entity_addr *
 ceph_mdsmap_get_addr(struct ceph_mdsmap *m, int w)
 {
-       if (w >= m->m_max_mds)
+       if (w >= m->m_num_mds)
                return NULL;
        return &m->m_info[w].addr;
 }
@@ -48,14 +49,14 @@ ceph_mdsmap_get_addr(struct ceph_mdsmap *m, int w)
 static inline int ceph_mdsmap_get_state(struct ceph_mdsmap *m, int w)
 {
        BUG_ON(w < 0);
-       if (w >= m->m_max_mds)
+       if (w >= m->m_num_mds)
                return CEPH_MDS_STATE_DNE;
        return m->m_info[w].state;
 }
 
 static inline bool ceph_mdsmap_is_laggy(struct ceph_mdsmap *m, int w)
 {
-       if (w >= 0 && w < m->m_max_mds)
+       if (w >= 0 && w < m->m_num_mds)
                return m->m_info[w].laggy;
        return false;
 }
index c125b5d9e13ceddacd921286f19133607835dee1..85650b415e73ff38487a6b2e6be7253466411a14 100644 (file)
@@ -5,6 +5,7 @@
 #include <linux/kref.h>
 #include <linux/mempool.h>
 #include <linux/rbtree.h>
+#include <linux/refcount.h>
 
 #include <linux/ceph/types.h>
 #include <linux/ceph/osdmap.h>
@@ -27,7 +28,7 @@ typedef void (*ceph_osdc_callback_t)(struct ceph_osd_request *);
 
 /* a given osd we're communicating with */
 struct ceph_osd {
-       atomic_t o_ref;
+       refcount_t o_ref;
        struct ceph_osd_client *o_osdc;
        int o_osd;
        int o_incarnation;
@@ -186,12 +187,12 @@ struct ceph_osd_request {
        struct timespec r_mtime;              /* ditto */
        u64 r_data_offset;                    /* ditto */
        bool r_linger;                        /* don't resend on failure */
+       bool r_abort_on_full;                 /* return ENOSPC when full */
 
        /* internal */
        unsigned long r_stamp;                /* jiffies, send or check time */
        unsigned long r_start_stamp;          /* jiffies */
        int r_attempts;
-       struct ceph_eversion r_replay_version; /* aka reassert_version */
        u32 r_last_force_resend;
        u32 r_map_dne_bound;
 
@@ -266,6 +267,7 @@ struct ceph_osd_client {
        struct rb_root         osds;          /* osds */
        struct list_head       osd_lru;       /* idle osds */
        spinlock_t             osd_lru_lock;
+       u32                    epoch_barrier;
        struct ceph_osd        homeless_osd;
        atomic64_t             last_tid;      /* tid of last request */
        u64                    last_linger_id;
@@ -304,6 +306,7 @@ extern void ceph_osdc_handle_reply(struct ceph_osd_client *osdc,
                                   struct ceph_msg *msg);
 extern void ceph_osdc_handle_map(struct ceph_osd_client *osdc,
                                 struct ceph_msg *msg);
+void ceph_osdc_update_epoch_barrier(struct ceph_osd_client *osdc, u32 eb);
 
 extern void osd_req_op_init(struct ceph_osd_request *osd_req,
                            unsigned int which, u16 opcode, u32 flags);
index 13d71fe18b0cf54f6097242fd08b9a30c6c48bbe..75a7db21457de5e6fce1e75cfca3749ff539057c 100644 (file)
@@ -2,7 +2,7 @@
 #define __FS_CEPH_PAGELIST_H
 
 #include <asm/byteorder.h>
-#include <linux/atomic.h>
+#include <linux/refcount.h>
 #include <linux/list.h>
 #include <linux/types.h>
 
@@ -13,7 +13,7 @@ struct ceph_pagelist {
        size_t room;
        struct list_head free_list;
        size_t num_pages_free;
-       atomic_t refcnt;
+       refcount_t refcnt;
 };
 
 struct ceph_pagelist_cursor {
@@ -30,7 +30,7 @@ static inline void ceph_pagelist_init(struct ceph_pagelist *pl)
        pl->room = 0;
        INIT_LIST_HEAD(&pl->free_list);
        pl->num_pages_free = 0;
-       atomic_set(&pl->refcnt, 1);
+       refcount_set(&pl->refcnt, 1);
 }
 
 extern void ceph_pagelist_release(struct ceph_pagelist *pl);
index 7007a5f480802ebcad8951b113f976801981a063..d23c9cf26993b5f4518710c2495f426cb48abf85 100644 (file)
@@ -125,5 +125,8 @@ extern void tegra210_xusb_pll_hw_control_enable(void);
 extern void tegra210_xusb_pll_hw_sequence_start(void);
 extern void tegra210_sata_pll_hw_control_enable(void);
 extern void tegra210_sata_pll_hw_sequence_start(void);
+extern void tegra210_set_sata_pll_seq_sw(bool state);
+extern void tegra210_put_utmipll_in_iddq(void);
+extern void tegra210_put_utmipll_out_iddq(void);
 
 #endif /* __LINUX_CLK_TEGRA_H_ */
index 6110fe09ed18c289881e63d3b8e1ecb62dfb08c9..d18da839b81013b0624bfcddb11451460e39bee9 100644 (file)
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 
+/**
+ * struct clk_omap_reg - OMAP register declaration
+ * @offset: offset from the master IP module base address
+ * @index: index of the master IP module
+ */
+struct clk_omap_reg {
+       void __iomem *ptr;
+       u16 offset;
+       u8 index;
+       u8 flags;
+};
+
 /**
  * struct dpll_data - DPLL registers and integration data
  * @mult_div1_reg: register containing the DPLL M and N bitfields
  * can be placed into read-only space.
  */
 struct dpll_data {
-       void __iomem            *mult_div1_reg;
+       struct clk_omap_reg     mult_div1_reg;
        u32                     mult_mask;
        u32                     div1_mask;
        struct clk_hw           *clk_bypass;
        struct clk_hw           *clk_ref;
-       void __iomem            *control_reg;
+       struct clk_omap_reg     control_reg;
        u32                     enable_mask;
        unsigned long           last_rounded_rate;
        u16                     last_rounded_m;
@@ -84,8 +96,8 @@ struct dpll_data {
        u16                     max_divider;
        unsigned long           max_rate;
        u8                      modes;
-       void __iomem            *autoidle_reg;
-       void __iomem            *idlest_reg;
+       struct clk_omap_reg     autoidle_reg;
+       struct clk_omap_reg     idlest_reg;
        u32                     autoidle_mask;
        u32                     freqsel_mask;
        u32                     idlest_mask;
@@ -113,10 +125,10 @@ struct clk_hw_omap;
  */
 struct clk_hw_omap_ops {
        void    (*find_idlest)(struct clk_hw_omap *oclk,
-                              void __iomem **idlest_reg,
+                              struct clk_omap_reg *idlest_reg,
                               u8 *idlest_bit, u8 *idlest_val);
        void    (*find_companion)(struct clk_hw_omap *oclk,
-                                 void __iomem **other_reg,
+                                 struct clk_omap_reg *other_reg,
                                  u8 *other_bit);
        void    (*allow_idle)(struct clk_hw_omap *oclk);
        void    (*deny_idle)(struct clk_hw_omap *oclk);
@@ -129,8 +141,6 @@ struct clk_hw_omap_ops {
  * @enable_bit: bitshift to write to enable/disable the clock (see @enable_reg)
  * @flags: see "struct clk.flags possibilities" above
  * @clksel_reg: for clksel clks, register va containing src/divisor select
- * @clksel_mask: bitmask in @clksel_reg for the src/divisor selector
- * @clksel: for clksel clks, pointer to struct clksel for this clock
  * @dpll_data: for DPLLs, pointer to struct dpll_data for this clock
  * @clkdm_name: clockdomain name that this clock is contained in
  * @clkdm: pointer to struct clockdomain, resolved from @clkdm_name at runtime
@@ -141,12 +151,10 @@ struct clk_hw_omap {
        struct list_head        node;
        unsigned long           fixed_rate;
        u8                      fixed_div;
-       void __iomem            *enable_reg;
+       struct clk_omap_reg     enable_reg;
        u8                      enable_bit;
        u8                      flags;
-       void __iomem            *clksel_reg;
-       u32                     clksel_mask;
-       const struct clksel     *clksel;
+       struct clk_omap_reg     clksel_reg;
        struct dpll_data        *dpll_data;
        const char              *clkdm_name;
        struct clockdomain      *clkdm;
@@ -172,7 +180,6 @@ struct clk_hw_omap {
  *     should be used.  This is a temporary solution - a better approach
  *     would be to associate clock type-specific data with the clock,
  *     similar to the struct dpll_data approach.
- * MEMMAP_ADDRESSING: Use memmap addressing to access clock registers.
  */
 #define ENABLE_REG_32BIT       (1 << 0)        /* Use 32-bit access */
 #define CLOCK_IDLE_CONTROL     (1 << 1)
@@ -180,7 +187,6 @@ struct clk_hw_omap {
 #define ENABLE_ON_INIT         (1 << 3)        /* Enable upon framework init */
 #define INVERT_ENABLE          (1 << 4)        /* 0 enables, 1 disables */
 #define CLOCK_CLKOUTX2         (1 << 5)
-#define MEMMAP_ADDRESSING      (1 << 6)
 
 /* CM_CLKEN_PLL*.EN* bit values - not all are available for every DPLL */
 #define DPLL_LOW_POWER_STOP    0x1
@@ -201,22 +207,13 @@ enum {
        CLK_MAX_MEMMAPS
 };
 
-/**
- * struct clk_omap_reg - OMAP register declaration
- * @offset: offset from the master IP module base address
- * @index: index of the master IP module
- */
-struct clk_omap_reg {
-       u16 offset;
-       u16 index;
-};
-
 /**
  * struct ti_clk_ll_ops - low-level ops for clocks
  * @clk_readl: pointer to register read function
  * @clk_writel: pointer to register write function
  * @clkdm_clk_enable: pointer to clockdomain enable function
  * @clkdm_clk_disable: pointer to clockdomain disable function
+ * @clkdm_lookup: pointer to clockdomain lookup function
  * @cm_wait_module_ready: pointer to CM module wait ready function
  * @cm_split_idlest_reg: pointer to CM module function to split idlest reg
  *
@@ -227,20 +224,20 @@ struct clk_omap_reg {
  * operations not provided directly by clock drivers.
  */
 struct ti_clk_ll_ops {
-       u32     (*clk_readl)(void __iomem *reg);
-       void    (*clk_writel)(u32 val, void __iomem *reg);
+       u32     (*clk_readl)(const struct clk_omap_reg *reg);
+       void    (*clk_writel)(u32 val, const struct clk_omap_reg *reg);
        int     (*clkdm_clk_enable)(struct clockdomain *clkdm, struct clk *clk);
        int     (*clkdm_clk_disable)(struct clockdomain *clkdm,
                                     struct clk *clk);
+       struct clockdomain * (*clkdm_lookup)(const char *name);
        int     (*cm_wait_module_ready)(u8 part, s16 prcm_mod, u16 idlest_reg,
                                        u8 idlest_shift);
-       int     (*cm_split_idlest_reg)(void __iomem *idlest_reg, s16 *prcm_inst,
-                                      u8 *idlest_reg_id);
+       int     (*cm_split_idlest_reg)(struct clk_omap_reg *idlest_reg,
+                                      s16 *prcm_inst, u8 *idlest_reg_id);
 };
 
 #define to_clk_hw_omap(_hw) container_of(_hw, struct clk_hw_omap, hw)
 
-void omap2_init_clk_clkdm(struct clk_hw *clk);
 int omap2_clk_disable_autoidle_all(void);
 int omap2_clk_enable_autoidle_all(void);
 int omap2_clk_allow_idle(struct clk *clk);
index 5949d185558990daed3b4c76bbdfdad20fb34608..b8920a031a3e357d71101905e3396ba245160781 100644 (file)
@@ -212,4 +212,6 @@ extern bool vgacon_text_force(void);
 static inline bool vgacon_text_force(void) { return false; }
 #endif
 
+extern void console_init(void);
+
 #endif /* _LINUX_CONSOLE_H */
index 1a675604b17dfc5cc0357136e1b1eb93e53a5f1d..2404ad238c0b8c0309e8c1480339a19967968edf 100644 (file)
@@ -40,9 +40,9 @@ extern int nr_cpu_ids;
 #ifdef CONFIG_CPUMASK_OFFSTACK
 /* Assuming NR_CPUS is huge, a runtime limit is more efficient.  Also,
  * not all bits may be allocated. */
-#define nr_cpumask_bits        nr_cpu_ids
+#define nr_cpumask_bits        ((unsigned int)nr_cpu_ids)
 #else
-#define nr_cpumask_bits        NR_CPUS
+#define nr_cpumask_bits        ((unsigned int)NR_CPUS)
 #endif
 
 /*
diff --git a/include/linux/crash_core.h b/include/linux/crash_core.h
new file mode 100644 (file)
index 0000000..541a197
--- /dev/null
@@ -0,0 +1,69 @@
+#ifndef LINUX_CRASH_CORE_H
+#define LINUX_CRASH_CORE_H
+
+#include <linux/linkage.h>
+#include <linux/elfcore.h>
+#include <linux/elf.h>
+
+#define CRASH_CORE_NOTE_NAME      "CORE"
+#define CRASH_CORE_NOTE_HEAD_BYTES ALIGN(sizeof(struct elf_note), 4)
+#define CRASH_CORE_NOTE_NAME_BYTES ALIGN(sizeof(CRASH_CORE_NOTE_NAME), 4)
+#define CRASH_CORE_NOTE_DESC_BYTES ALIGN(sizeof(struct elf_prstatus), 4)
+
+#define CRASH_CORE_NOTE_BYTES     ((CRASH_CORE_NOTE_HEAD_BYTES * 2) +  \
+                                    CRASH_CORE_NOTE_NAME_BYTES +       \
+                                    CRASH_CORE_NOTE_DESC_BYTES)
+
+#define VMCOREINFO_BYTES          (4096)
+#define VMCOREINFO_NOTE_NAME      "VMCOREINFO"
+#define VMCOREINFO_NOTE_NAME_BYTES ALIGN(sizeof(VMCOREINFO_NOTE_NAME), 4)
+#define VMCOREINFO_NOTE_SIZE      ((CRASH_CORE_NOTE_HEAD_BYTES * 2) +  \
+                                    VMCOREINFO_NOTE_NAME_BYTES +       \
+                                    VMCOREINFO_BYTES)
+
+typedef u32 note_buf_t[CRASH_CORE_NOTE_BYTES/4];
+
+void crash_save_vmcoreinfo(void);
+void arch_crash_save_vmcoreinfo(void);
+__printf(1, 2)
+void vmcoreinfo_append_str(const char *fmt, ...);
+phys_addr_t paddr_vmcoreinfo_note(void);
+
+#define VMCOREINFO_OSRELEASE(value) \
+       vmcoreinfo_append_str("OSRELEASE=%s\n", value)
+#define VMCOREINFO_PAGESIZE(value) \
+       vmcoreinfo_append_str("PAGESIZE=%ld\n", value)
+#define VMCOREINFO_SYMBOL(name) \
+       vmcoreinfo_append_str("SYMBOL(%s)=%lx\n", #name, (unsigned long)&name)
+#define VMCOREINFO_SIZE(name) \
+       vmcoreinfo_append_str("SIZE(%s)=%lu\n", #name, \
+                             (unsigned long)sizeof(name))
+#define VMCOREINFO_STRUCT_SIZE(name) \
+       vmcoreinfo_append_str("SIZE(%s)=%lu\n", #name, \
+                             (unsigned long)sizeof(struct name))
+#define VMCOREINFO_OFFSET(name, field) \
+       vmcoreinfo_append_str("OFFSET(%s.%s)=%lu\n", #name, #field, \
+                             (unsigned long)offsetof(struct name, field))
+#define VMCOREINFO_LENGTH(name, value) \
+       vmcoreinfo_append_str("LENGTH(%s)=%lu\n", #name, (unsigned long)value)
+#define VMCOREINFO_NUMBER(name) \
+       vmcoreinfo_append_str("NUMBER(%s)=%ld\n", #name, (long)name)
+#define VMCOREINFO_CONFIG(name) \
+       vmcoreinfo_append_str("CONFIG_%s=y\n", #name)
+
+extern u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4];
+extern size_t vmcoreinfo_size;
+extern size_t vmcoreinfo_max_size;
+
+Elf_Word *append_elf_note(Elf_Word *buf, char *name, unsigned int type,
+                         void *data, size_t data_len);
+void final_note(Elf_Word *buf);
+
+int __init parse_crashkernel(char *cmdline, unsigned long long system_ram,
+               unsigned long long *crash_size, unsigned long long *crash_base);
+int parse_crashkernel_high(char *cmdline, unsigned long long system_ram,
+               unsigned long long *crash_size, unsigned long long *crash_base);
+int parse_crashkernel_low(char *cmdline, unsigned long long system_ram,
+               unsigned long long *crash_size, unsigned long long *crash_base);
+
+#endif /* LINUX_CRASH_CORE_H */
index d3158e74a59effa5d9e7fe36e4631e63bc622066..5ec1f6c47716d6fe7c750456cef81cc0e321b1bc 100644 (file)
@@ -18,12 +18,58 @@ struct dax_operations {
                        void **, pfn_t *);
 };
 
+#if IS_ENABLED(CONFIG_DAX)
+struct dax_device *dax_get_by_host(const char *host);
+void put_dax(struct dax_device *dax_dev);
+#else
+static inline struct dax_device *dax_get_by_host(const char *host)
+{
+       return NULL;
+}
+
+static inline void put_dax(struct dax_device *dax_dev)
+{
+}
+#endif
+
+int bdev_dax_pgoff(struct block_device *, sector_t, size_t, pgoff_t *pgoff);
+#if IS_ENABLED(CONFIG_FS_DAX)
+int __bdev_dax_supported(struct super_block *sb, int blocksize);
+static inline int bdev_dax_supported(struct super_block *sb, int blocksize)
+{
+       return __bdev_dax_supported(sb, blocksize);
+}
+
+static inline struct dax_device *fs_dax_get_by_host(const char *host)
+{
+       return dax_get_by_host(host);
+}
+
+static inline void fs_put_dax(struct dax_device *dax_dev)
+{
+       put_dax(dax_dev);
+}
+
+#else
+static inline int bdev_dax_supported(struct super_block *sb, int blocksize)
+{
+       return -EOPNOTSUPP;
+}
+
+static inline struct dax_device *fs_dax_get_by_host(const char *host)
+{
+       return NULL;
+}
+
+static inline void fs_put_dax(struct dax_device *dax_dev)
+{
+}
+#endif
+
 int dax_read_lock(void);
 void dax_read_unlock(int id);
-struct dax_device *dax_get_by_host(const char *host);
 struct dax_device *alloc_dax(void *private, const char *host,
                const struct dax_operations *ops);
-void put_dax(struct dax_device *dax_dev);
 bool dax_alive(struct dax_device *dax_dev);
 void kill_dax(struct dax_device *dax_dev);
 void *dax_get_private(struct dax_device *dax_dev);
@@ -63,7 +109,6 @@ ssize_t dax_iomap_rw(struct kiocb *iocb, struct iov_iter *iter,
 int dax_iomap_fault(struct vm_fault *vmf, enum page_entry_size pe_size,
                    const struct iomap_ops *ops);
 int dax_delete_mapping_entry(struct address_space *mapping, pgoff_t index);
-int dax_invalidate_mapping_entry(struct address_space *mapping, pgoff_t index);
 int dax_invalidate_mapping_entry_sync(struct address_space *mapping,
                                      pgoff_t index);
 void dax_wake_mapping_entry_waiter(struct address_space *mapping,
index c35d0c0e0ada7a4e99363d217a86fc4cad8dafaf..4635f95000a4c50bff074ac5bb2f174985f7477a 100644 (file)
  *                     If get_dynamic_power() is NULL, then the
  *                     dynamic power is calculated as
  *                     @dyn_power_coeff * frequency * voltage^2
+ * @get_real_power:    When this is set, the framework uses it to ask the
+ *                     device driver for the actual power.
+ *                     Some devices have more sophisticated methods
+ *                     (like power counters) to approximate the actual power
+ *                     that they use.
+ *                     This function provides more accurate data to the
+ *                     thermal governor. When the driver does not provide
+ *                     such function, framework just uses pre-calculated
+ *                     table and scale the power by 'utilization'
+ *                     (based on 'busy_time' and 'total_time' taken from
+ *                     devfreq 'last_status').
+ *                     The value returned by this function must be lower
+ *                     or equal than the maximum power value
+ *                     for the current state
+ *                     (which can be found in power_table[state]).
+ *                     When this interface is used, the power_table holds
+ *                     max total (static + dynamic) power value for each OPP.
  */
 struct devfreq_cooling_power {
        unsigned long (*get_static_power)(struct devfreq *devfreq,
@@ -41,6 +58,8 @@ struct devfreq_cooling_power {
        unsigned long (*get_dynamic_power)(struct devfreq *devfreq,
                                           unsigned long freq,
                                           unsigned long voltage);
+       int (*get_real_power)(struct devfreq *df, u32 *power,
+                             unsigned long freq, unsigned long voltage);
        unsigned long dyn_power_coeff;
 };
 
index 6048fa404e571165b40a7964cb1408f413bba9f0..a5195a7d6f77e40d23d29ba2793c7b393f4eb0bb 100644 (file)
@@ -229,7 +229,7 @@ static inline struct dma_fence *dma_fence_get_rcu(struct dma_fence *fence)
  *
  * Function returns NULL if no refcount could be obtained, or the fence.
  * This function handles acquiring a reference to a fence that may be
- * reallocated within the RCU grace period (such as with SLAB_DESTROY_BY_RCU),
+ * reallocated within the RCU grace period (such as with SLAB_TYPESAFE_BY_RCU),
  * so long as the caller is using RCU on the pointer to the fence.
  *
  * An alternative mechanism is to employ a seqlock to protect a bunch of
@@ -257,7 +257,7 @@ dma_fence_get_rcu_safe(struct dma_fence * __rcu *fencep)
                 * have successfully acquire a reference to it. If it no
                 * longer matches, we are holding a reference to some other
                 * reallocated pointer. This is possible if the allocator
-                * is using a freelist like SLAB_DESTROY_BY_RCU where the
+                * is using a freelist like SLAB_TYPESAFE_BY_RCU where the
                 * fence remains valid for the RCU grace period, but it
                 * may be reallocated. When using such allocators, we are
                 * responsible for ensuring the reference we get is to
index 5725c94b1f121ece268c0fd8558cb94770c2c9cd..4eac2670bfa1a016679971f36ad698fe1d9f6a4e 100644 (file)
@@ -20,6 +20,7 @@
 #include <asm/errno.h>
 
 #ifdef CONFIG_IOMMU_DMA
+#include <linux/dma-mapping.h>
 #include <linux/iommu.h>
 #include <linux/msi.h>
 
@@ -71,6 +72,7 @@ int iommu_dma_mapping_error(struct device *dev, dma_addr_t dma_addr);
 
 /* The DMA API isn't _quite_ the whole story, though... */
 void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg);
+void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list);
 
 #else
 
@@ -100,6 +102,10 @@ static inline void iommu_dma_map_msi_msg(int irq, struct msi_msg *msg)
 {
 }
 
+static inline void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list)
+{
+}
+
 #endif /* CONFIG_IOMMU_DMA */
 #endif /* __KERNEL__ */
 #endif /* __DMA_IOMMU_H */
index 0977317c6835c2526428f61c12fcfab976650b99..4f3eecedca2d7c75c683cc2f08d64be9ac95118d 100644 (file)
@@ -728,6 +728,18 @@ dma_mark_declared_memory_occupied(struct device *dev,
 }
 #endif /* CONFIG_HAVE_GENERIC_DMA_COHERENT */
 
+#ifdef CONFIG_HAS_DMA
+int dma_configure(struct device *dev);
+void dma_deconfigure(struct device *dev);
+#else
+static inline int dma_configure(struct device *dev)
+{
+       return 0;
+}
+
+static inline void dma_deconfigure(struct device *dev) {}
+#endif
+
 /*
  * Managed DMA API
  */
index 187c102997226d4107f2dd703413c105e980e39f..90884072fa73254f5da8bb2091c6c3d2bded2f20 100644 (file)
@@ -39,6 +39,7 @@ extern int iommu_calculate_agaw(struct intel_iommu *iommu);
 extern int iommu_calculate_max_sagaw(struct intel_iommu *iommu);
 extern int dmar_disabled;
 extern int intel_iommu_enabled;
+extern int intel_iommu_tboot_noforce;
 #else
 static inline int iommu_calculate_agaw(struct intel_iommu *iommu)
 {
index 20fa8d8ae31335744c4566eb8b6305997b44db8b..ba069e8f4f7873b002da2d632d81520eb2a662fd 100644 (file)
@@ -29,6 +29,7 @@ extern Elf32_Dyn _DYNAMIC [];
 #define elf_note       elf32_note
 #define elf_addr_t     Elf32_Off
 #define Elf_Half       Elf32_Half
+#define Elf_Word       Elf32_Word
 
 #else
 
@@ -39,6 +40,7 @@ extern Elf64_Dyn _DYNAMIC [];
 #define elf_note       elf64_note
 #define elf_addr_t     Elf64_Off
 #define Elf_Half       Elf64_Half
+#define Elf_Word       Elf64_Word
 
 #endif
 
index 76ce329e656d1eaca5a6d6792f97d3c067fa37c6..1b48d9c9a5613cc1b619444e2046c36dcfeda872 100644 (file)
@@ -3,6 +3,12 @@
 
 #include <uapi/linux/fcntl.h>
 
+/* list of all valid flags for the open/openat flags argument: */
+#define VALID_OPEN_FLAGS \
+       (O_RDONLY | O_WRONLY | O_RDWR | O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC | \
+        O_APPEND | O_NDELAY | O_NONBLOCK | O_NDELAY | __O_SYNC | O_DSYNC | \
+        FASYNC | O_DIRECT | O_LARGEFILE | O_DIRECTORY | O_NOFOLLOW | \
+        O_NOATIME | O_CLOEXEC | O_PATH | __O_TMPFILE)
 
 #ifndef force_o_largefile
 #define force_o_largefile() (BITS_PER_LONG != 32)
index 9a7786db14fa5307dff297487d2fb50245ddc60f..56197f82af45fb0f7cf492961fe1eb1956105735 100644 (file)
@@ -19,7 +19,9 @@
 
 #include <net/sch_generic.h>
 
-#include <asm/cacheflush.h>
+#ifdef CONFIG_ARCH_HAS_SET_MEMORY
+#include <asm/set_memory.h>
+#endif
 
 #include <uapi/linux/filter.h>
 #include <uapi/linux/bpf.h>
index 8e953c6f394ae58ef5902c2ae4fd44fd5f3c1173..37a5eaea69dde299a18855ffc99b1227513b25da 100644 (file)
@@ -25,7 +25,7 @@ int meson_sm_call(unsigned int cmd_index, u32 *ret, u32 arg0, u32 arg1,
                  u32 arg2, u32 arg3, u32 arg4);
 int meson_sm_call_write(void *buffer, unsigned int b_size, unsigned int cmd_index,
                        u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4);
-int meson_sm_call_read(void *buffer, unsigned int cmd_index, u32 arg0, u32 arg1,
-                      u32 arg2, u32 arg3, u32 arg4);
+int meson_sm_call_read(void *buffer, unsigned int bsize, unsigned int cmd_index,
+                      u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4);
 
 #endif /* _MESON_SM_FW_H_ */
index 5d62d2c47939a7d4d17ca5a76be91729c91f198c..803e5a9b265422d2c2034678331b6d4dd353d1de 100644 (file)
@@ -29,7 +29,6 @@
 #include <linux/lockdep.h>
 #include <linux/percpu-rwsem.h>
 #include <linux/workqueue.h>
-#include <linux/percpu-rwsem.h>
 #include <linux/delayed_call.h>
 
 #include <asm/byteorder.h>
@@ -250,9 +249,8 @@ enum positive_aop_returns {
        AOP_TRUNCATED_PAGE      = 0x80001,
 };
 
-#define AOP_FLAG_UNINTERRUPTIBLE       0x0001 /* will not do a short write */
-#define AOP_FLAG_CONT_EXPAND           0x0002 /* called from cont_expand */
-#define AOP_FLAG_NOFS                  0x0004 /* used by filesystem to direct
+#define AOP_FLAG_CONT_EXPAND           0x0001 /* called from cont_expand */
+#define AOP_FLAG_NOFS                  0x0002 /* used by filesystem to direct
                                                * helper code (eg buffer layer)
                                                * to clear GFP_FS from alloc */
 
@@ -911,6 +909,8 @@ static inline struct file *get_file(struct file *f)
 #define FL_OFDLCK      1024    /* lock is "owned" by struct file */
 #define FL_LAYOUT      2048    /* outstanding pNFS layout */
 
+#define FL_CLOSE_POSIX (FL_POSIX | FL_CLOSE)
+
 /*
  * Special return value from posix_lock_file() and vfs_lock_file() for
  * asynchronous locking.
@@ -1431,7 +1431,6 @@ static inline void i_gid_write(struct inode *inode, gid_t gid)
        inode->i_gid = make_kgid(inode->i_sb->s_user_ns, gid);
 }
 
-extern struct timespec current_fs_time(struct super_block *sb);
 extern struct timespec current_time(struct inode *inode);
 
 /*
@@ -2926,17 +2925,19 @@ extern int vfs_statx_fd(unsigned int, struct kstat *, u32, unsigned int);
 
 static inline int vfs_stat(const char __user *filename, struct kstat *stat)
 {
-       return vfs_statx(AT_FDCWD, filename, 0, stat, STATX_BASIC_STATS);
+       return vfs_statx(AT_FDCWD, filename, AT_NO_AUTOMOUNT,
+                        stat, STATX_BASIC_STATS);
 }
 static inline int vfs_lstat(const char __user *name, struct kstat *stat)
 {
-       return vfs_statx(AT_FDCWD, name, AT_SYMLINK_NOFOLLOW,
+       return vfs_statx(AT_FDCWD, name, AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT,
                         stat, STATX_BASIC_STATS);
 }
 static inline int vfs_fstatat(int dfd, const char __user *filename,
                              struct kstat *stat, int flags)
 {
-       return vfs_statx(dfd, filename, flags, stat, STATX_BASIC_STATS);
+       return vfs_statx(dfd, filename, flags | AT_NO_AUTOMOUNT,
+                        stat, STATX_BASIC_STATS);
 }
 static inline int vfs_fstat(int fd, struct kstat *stat)
 {
@@ -3001,9 +3002,10 @@ extern const struct file_operations simple_dir_operations;
 extern const struct inode_operations simple_dir_inode_operations;
 extern void make_empty_dir_inode(struct inode *inode);
 extern bool is_empty_dir_inode(struct inode *inode);
-struct tree_descr { char *name; const struct file_operations *ops; int mode; };
+struct tree_descr { const char *name; const struct file_operations *ops; int mode; };
 struct dentry *d_alloc_name(struct dentry *, const char *);
-extern int simple_fill_super(struct super_block *, unsigned long, struct tree_descr *);
+extern int simple_fill_super(struct super_block *, unsigned long,
+                            const struct tree_descr *);
 extern int simple_pin_fs(struct file_system_type *, struct vfsmount **mount, int *count);
 extern void simple_release_fs(struct vfsmount **mount, int *count);
 
index 6d2a63e4ea52e20a659239008795ebaf5f069787..473f088aabeac7b3899c155c778628e389e4d3fe 100644 (file)
@@ -72,7 +72,7 @@ ftrace_func_t ftrace_ops_get_func(struct ftrace_ops *ops);
  * CONTROL, SAVE_REGS, SAVE_REGS_IF_SUPPORTED, RECURSION_SAFE, STUB and
  * IPMODIFY are a kind of attribute flags which can be set only before
  * registering the ftrace_ops, and can not be modified while registered.
- * Changing those attribute flags after regsitering ftrace_ops will
+ * Changing those attribute flags after registering ftrace_ops will
  * cause unexpected results.
  *
  * ENABLED - set/unset when ftrace_ops is registered/unregistered
index c573a52ae440e83894709328820bacb79391d15c..485a5b48f0380460fa0b46243e34aa6c83796c07 100644 (file)
@@ -30,6 +30,8 @@
 #include <linux/mmu_notifier.h>
 #include <linux/list.h>
 #include <linux/iommu.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
+
 #include <asm/cacheflush.h>
 #include <asm/iommu.h>
 
 
 #define OFFSET_STRIDE          (9)
 
-#ifdef CONFIG_64BIT
 #define dmar_readq(a) readq(a)
 #define dmar_writeq(a,v) writeq(v,a)
-#else
-static inline u64 dmar_readq(void __iomem *addr)
-{
-       u32 lo, hi;
-       lo = readl(addr);
-       hi = readl(addr + 4);
-       return (((u64) hi) << 32) + lo;
-}
-
-static inline void dmar_writeq(void __iomem *addr, u64 val)
-{
-       writel((u32)val, addr);
-       writel((u32)(val >> 32), addr + 4);
-}
-#endif
 
 #define DMAR_VER_MAJOR(v)              (((v) & 0xf0) >> 4)
 #define DMAR_VER_MINOR(v)              ((v) & 0x0f)
index 53144e78a3691d2d0ea46b48319c5af337f0fda2..a6fba4804672858b87430b81c0af52378bd7ed89 100644 (file)
@@ -155,7 +155,7 @@ extern int __must_check
 request_percpu_irq(unsigned int irq, irq_handler_t handler,
                   const char *devname, void __percpu *percpu_dev_id);
 
-extern void free_irq(unsigned int, void *);
+extern const void *free_irq(unsigned int, void *);
 extern void free_percpu_irq(unsigned int, void __percpu *);
 
 struct device;
index 82ef36eac8a16a8fc2b7b021f345910ac04b04b4..2195d9ea4aaae0c054f04aab2da7cff851d2b997 100644 (file)
@@ -90,6 +90,27 @@ void devm_memunmap(struct device *dev, void *addr);
 
 void *__devm_memremap_pages(struct device *dev, struct resource *res);
 
+#ifdef CONFIG_PCI
+/*
+ * The PCI specifications (Rev 3.0, 3.2.5 "Transaction Ordering and
+ * Posting") mandate non-posted configuration transactions. There is
+ * no ioremap API in the kernel that can guarantee non-posted write
+ * semantics across arches so provide a default implementation for
+ * mapping PCI config space that defaults to ioremap_nocache(); arches
+ * should override it if they have memory mapping implementations that
+ * guarantee non-posted writes semantics to make the memory mapping
+ * compliant with the PCI specification.
+ */
+#ifndef pci_remap_cfgspace
+#define pci_remap_cfgspace pci_remap_cfgspace
+static inline void __iomem *pci_remap_cfgspace(phys_addr_t offset,
+                                              size_t size)
+{
+       return ioremap_nocache(offset, size);
+}
+#endif
+#endif
+
 /*
  * Some systems do not have legacy ISA devices.
  * /dev/port is not a valid interface on these systems.
index 2e4de0deee531adbd7c1cd8ff1d25e0d0eb98d47..2cb54adc4a334aa3f3a1732c35eaf9749d64b9e8 100644 (file)
 #ifndef __LINUX_IOMMU_H
 #define __LINUX_IOMMU_H
 
+#include <linux/scatterlist.h>
+#include <linux/device.h>
+#include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/err.h>
 #include <linux/of.h>
-#include <linux/types.h>
-#include <linux/scatterlist.h>
-#include <trace/events/iommu.h>
 
 #define IOMMU_READ     (1 << 0)
 #define IOMMU_WRITE    (1 << 1)
 #define IOMMU_NOEXEC   (1 << 3)
 #define IOMMU_MMIO     (1 << 4) /* e.g. things like MSI doorbells */
 /*
- * This is to make the IOMMU API setup privileged
- * mapppings accessible by the master only at higher
- * privileged execution level and inaccessible at
- * less privileged levels.
+ * Where the bus hardware includes a privilege level as part of its access type
+ * markings, and certain devices are capable of issuing transactions marked as
+ * either 'supervisor' or 'user', the IOMMU_PRIV flag requests that the other
+ * given permission flags only apply to accesses at the higher privilege level,
+ * and that unprivileged transactions should have as little access as possible.
+ * This would usually imply the same permissions as kernel mappings on the CPU,
+ * if the IOMMU page table format is equivalent.
  */
 #define IOMMU_PRIV     (1 << 5)
 
@@ -336,46 +339,9 @@ extern int iommu_domain_window_enable(struct iommu_domain *domain, u32 wnd_nr,
                                      phys_addr_t offset, u64 size,
                                      int prot);
 extern void iommu_domain_window_disable(struct iommu_domain *domain, u32 wnd_nr);
-/**
- * report_iommu_fault() - report about an IOMMU fault to the IOMMU framework
- * @domain: the iommu domain where the fault has happened
- * @dev: the device where the fault has happened
- * @iova: the faulting address
- * @flags: mmu fault flags (e.g. IOMMU_FAULT_READ/IOMMU_FAULT_WRITE/...)
- *
- * This function should be called by the low-level IOMMU implementations
- * whenever IOMMU faults happen, to allow high-level users, that are
- * interested in such events, to know about them.
- *
- * This event may be useful for several possible use cases:
- * - mere logging of the event
- * - dynamic TLB/PTE loading
- * - if restarting of the faulting device is required
- *
- * Returns 0 on success and an appropriate error code otherwise (if dynamic
- * PTE/TLB loading will one day be supported, implementations will be able
- * to tell whether it succeeded or not according to this return value).
- *
- * Specifically, -ENOSYS is returned if a fault handler isn't installed
- * (though fault handlers can also return -ENOSYS, in case they want to
- * elicit the default behavior of the IOMMU drivers).
- */
-static inline int report_iommu_fault(struct iommu_domain *domain,
-               struct device *dev, unsigned long iova, int flags)
-{
-       int ret = -ENOSYS;
-
-       /*
-        * if upper layers showed interest and installed a fault handler,
-        * invoke it.
-        */
-       if (domain->handler)
-               ret = domain->handler(domain, dev, iova, flags,
-                                               domain->handler_token);
 
-       trace_io_page_fault(dev, iova, flags);
-       return ret;
-}
+extern int report_iommu_fault(struct iommu_domain *domain, struct device *dev,
+                             unsigned long iova, int flags);
 
 static inline size_t iommu_map_sg(struct iommu_domain *domain,
                                  unsigned long iova, struct scatterlist *sg,
index 9d84942ae2e577835a338b8a352f9c93eabe148b..71fd92d81b266edf1781c542de550159bc33949a 100644 (file)
@@ -8,8 +8,7 @@
 #define IPCMNI 32768  /* <= MAX_INT limit for ipc arrays (including sysctl changes) */
 
 /* used by in-kernel data structures */
-struct kern_ipc_perm
-{
+struct kern_ipc_perm {
        spinlock_t      lock;
        bool            deleted;
        int             id;
@@ -18,9 +17,9 @@ struct kern_ipc_perm
        kgid_t          gid;
        kuid_t          cuid;
        kgid_t          cgid;
-       umode_t         mode; 
+       umode_t         mode;
        unsigned long   seq;
        void            *security;
-};
+} ____cacheline_aligned_in_smp;
 
 #endif /* _LINUX_IPC_H */
index 97cbca19430d82aa2b4c835db1edf2d6620517ba..fffb91202bc9366a523002cc61fc074d12f84725 100644 (file)
 #define GIC_BASER_SHAREABILITY(reg, type)                              \
        (GIC_BASER_##type << reg##_SHAREABILITY_SHIFT)
 
+/* encode a size field of width @w containing @n - 1 units */
+#define GIC_ENCODE_SZ(n, w) (((unsigned long)(n) - 1) & GENMASK_ULL(((w) - 1), 0))
+
 #define GICR_PROPBASER_SHAREABILITY_SHIFT              (10)
 #define GICR_PROPBASER_INNER_CACHEABILITY_SHIFT                (7)
 #define GICR_PROPBASER_OUTER_CACHEABILITY_SHIFT                (56)
 #define GICR_PROPBASER_RaWaWb  GIC_BASER_CACHEABILITY(GICR_PROPBASER, INNER, RaWaWb)
 
 #define GICR_PROPBASER_IDBITS_MASK                     (0x1f)
+#define GICR_PROPBASER_ADDRESS(x)      ((x) & GENMASK_ULL(51, 12))
+#define GICR_PENDBASER_ADDRESS(x)      ((x) & GENMASK_ULL(51, 16))
 
 #define GICR_PENDBASER_SHAREABILITY_SHIFT              (10)
 #define GICR_PENDBASER_INNER_CACHEABILITY_SHIFT                (7)
 #define GITS_CTLR_QUIESCENT            (1U << 31)
 
 #define GITS_TYPER_PLPIS               (1UL << 0)
+#define GITS_TYPER_ITT_ENTRY_SIZE_SHIFT        4
 #define GITS_TYPER_IDBITS_SHIFT                8
 #define GITS_TYPER_DEVBITS_SHIFT       13
 #define GITS_TYPER_DEVBITS(r)          ((((r) >> GITS_TYPER_DEVBITS_SHIFT) & 0x1f) + 1)
 #define GITS_TYPER_PTA                 (1UL << 19)
 #define GITS_TYPER_HWCOLLCNT_SHIFT     24
 
+#define GITS_IIDR_REV_SHIFT            12
+#define GITS_IIDR_REV_MASK             (0xf << GITS_IIDR_REV_SHIFT)
+#define GITS_IIDR_REV(r)               (((r) >> GITS_IIDR_REV_SHIFT) & 0xf)
+#define GITS_IIDR_PRODUCTID_SHIFT      24
+
 #define GITS_CBASER_VALID                      (1ULL << 63)
 #define GITS_CBASER_SHAREABILITY_SHIFT         (10)
 #define GITS_CBASER_INNER_CACHEABILITY_SHIFT   (59)
 #define GITS_BASER_TYPE(r)             (((r) >> GITS_BASER_TYPE_SHIFT) & 7)
 #define GITS_BASER_ENTRY_SIZE_SHIFT            (48)
 #define GITS_BASER_ENTRY_SIZE(r)       ((((r) >> GITS_BASER_ENTRY_SIZE_SHIFT) & 0x1f) + 1)
+#define GITS_BASER_ENTRY_SIZE_MASK     GENMASK_ULL(52, 48)
 #define GITS_BASER_SHAREABILITY_SHIFT  (10)
 #define GITS_BASER_InnerShareable                                      \
        GIC_BASER_SHAREABILITY(GITS_BASER, InnerShareable)
 #define E_ITS_INT_UNMAPPED_INTERRUPT           0x010307
 #define E_ITS_CLEAR_UNMAPPED_INTERRUPT         0x010507
 #define E_ITS_MAPD_DEVICE_OOR                  0x010801
+#define E_ITS_MAPD_ITTSIZE_OOR                 0x010802
 #define E_ITS_MAPC_PROCNUM_OOR                 0x010902
 #define E_ITS_MAPC_COLLECTION_OOR              0x010903
 #define E_ITS_MAPTI_UNMAPPED_DEVICE            0x010a04
+#define E_ITS_MAPTI_ID_OOR                     0x010a05
 #define E_ITS_MAPTI_PHYSICALID_OOR             0x010a06
 #define E_ITS_INV_UNMAPPED_INTERRUPT           0x010c07
 #define E_ITS_INVALL_UNMAPPED_COLLECTION       0x010d09
index 624215cebee5235a3375549f62e026b3c7e41f74..36872fbb815d72203e14582e3dab6ba5051ee8a7 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _LINUX_JIFFIES_H
 #define _LINUX_JIFFIES_H
 
+#include <linux/cache.h>
 #include <linux/math64.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
@@ -63,19 +64,13 @@ extern int register_refined_jiffies(long clock_tick_rate);
 /* TICK_USEC is the time between ticks in usec assuming fake USER_HZ */
 #define TICK_USEC ((1000000UL + USER_HZ/2) / USER_HZ)
 
-/* some arch's have a small-data section that can be accessed register-relative
- * but that can only take up to, say, 4-byte variables. jiffies being part of
- * an 8-byte variable may not be correctly accessed unless we force the issue
- */
-#define __jiffy_data  __attribute__((section(".data")))
-
 /*
  * The 64-bit value is not atomic - you MUST NOT read it
  * without sampling the sequence number in jiffies_lock.
  * get_jiffies_64() will do this for you as appropriate.
  */
-extern u64 __jiffy_data jiffies_64;
-extern unsigned long volatile __jiffy_data jiffies;
+extern u64 __cacheline_aligned_in_smp jiffies_64;
+extern unsigned long volatile __cacheline_aligned_in_smp jiffies;
 
 #if (BITS_PER_LONG < 64)
 u64 get_jiffies_64(void);
index 22a72198c14b7e338f4f10ed334f7c73be8cfcae..4e80f3a9ad58abc815926b701a8fbc83c153b5a9 100644 (file)
@@ -2,14 +2,14 @@
 #define __LINUX_KBUILD_H
 
 #define DEFINE(sym, val) \
-        asm volatile("\n->" #sym " %0 " #val : : "i" (val))
+       asm volatile("\n.ascii \"->" #sym " %0 " #val "\"" : : "i" (val))
 
-#define BLANK() asm volatile("\n->" : : )
+#define BLANK() asm volatile("\n.ascii \"->\"" : : )
 
 #define OFFSET(sym, str, mem) \
        DEFINE(sym, offsetof(struct str, mem))
 
 #define COMMENT(x) \
-       asm volatile("\n->#" x)
+       asm volatile("\n.ascii \"->#" x "\"")
 
 #endif
index d419d0e51fe55172e5cc5b42bb4c8c2fd9694141..c9481ebcbc0cab09429bde237f21e41cc7dcb061 100644 (file)
 
 #if !defined(__ASSEMBLY__)
 
+#include <linux/crash_core.h>
 #include <asm/io.h>
 
 #include <uapi/linux/kexec.h>
 
 #ifdef CONFIG_KEXEC_CORE
 #include <linux/list.h>
-#include <linux/linkage.h>
 #include <linux/compat.h>
 #include <linux/ioport.h>
-#include <linux/elfcore.h>
-#include <linux/elf.h>
 #include <linux/module.h>
 #include <asm/kexec.h>
 
 #define KEXEC_CRASH_MEM_ALIGN PAGE_SIZE
 #endif
 
-#define KEXEC_NOTE_HEAD_BYTES ALIGN(sizeof(struct elf_note), 4)
-#define KEXEC_CORE_NOTE_NAME "CORE"
-#define KEXEC_CORE_NOTE_NAME_BYTES ALIGN(sizeof(KEXEC_CORE_NOTE_NAME), 4)
-#define KEXEC_CORE_NOTE_DESC_BYTES ALIGN(sizeof(struct elf_prstatus), 4)
+#define KEXEC_CORE_NOTE_NAME   CRASH_CORE_NOTE_NAME
+
 /*
  * The per-cpu notes area is a list of notes terminated by a "NULL"
  * note header.  For kdump, the code in vmcore.c runs in the context
  * of the second kernel to combine them into one note.
  */
 #ifndef KEXEC_NOTE_BYTES
-#define KEXEC_NOTE_BYTES ( (KEXEC_NOTE_HEAD_BYTES * 2) +               \
-                           KEXEC_CORE_NOTE_NAME_BYTES +                \
-                           KEXEC_CORE_NOTE_DESC_BYTES )
+#define KEXEC_NOTE_BYTES       CRASH_CORE_NOTE_BYTES
 #endif
 
 /*
@@ -256,33 +250,6 @@ extern void crash_kexec(struct pt_regs *);
 int kexec_should_crash(struct task_struct *);
 int kexec_crash_loaded(void);
 void crash_save_cpu(struct pt_regs *regs, int cpu);
-void crash_save_vmcoreinfo(void);
-void arch_crash_save_vmcoreinfo(void);
-__printf(1, 2)
-void vmcoreinfo_append_str(const char *fmt, ...);
-phys_addr_t paddr_vmcoreinfo_note(void);
-
-#define VMCOREINFO_OSRELEASE(value) \
-       vmcoreinfo_append_str("OSRELEASE=%s\n", value)
-#define VMCOREINFO_PAGESIZE(value) \
-       vmcoreinfo_append_str("PAGESIZE=%ld\n", value)
-#define VMCOREINFO_SYMBOL(name) \
-       vmcoreinfo_append_str("SYMBOL(%s)=%lx\n", #name, (unsigned long)&name)
-#define VMCOREINFO_SIZE(name) \
-       vmcoreinfo_append_str("SIZE(%s)=%lu\n", #name, \
-                             (unsigned long)sizeof(name))
-#define VMCOREINFO_STRUCT_SIZE(name) \
-       vmcoreinfo_append_str("SIZE(%s)=%lu\n", #name, \
-                             (unsigned long)sizeof(struct name))
-#define VMCOREINFO_OFFSET(name, field) \
-       vmcoreinfo_append_str("OFFSET(%s.%s)=%lu\n", #name, #field, \
-                             (unsigned long)offsetof(struct name, field))
-#define VMCOREINFO_LENGTH(name, value) \
-       vmcoreinfo_append_str("LENGTH(%s)=%lu\n", #name, (unsigned long)value)
-#define VMCOREINFO_NUMBER(name) \
-       vmcoreinfo_append_str("NUMBER(%s)=%ld\n", #name, (long)name)
-#define VMCOREINFO_CONFIG(name) \
-       vmcoreinfo_append_str("CONFIG_%s=y\n", #name)
 
 extern struct kimage *kexec_image;
 extern struct kimage *kexec_crash_image;
@@ -303,31 +270,15 @@ extern int kexec_load_disabled;
 #define KEXEC_FILE_FLAGS       (KEXEC_FILE_UNLOAD | KEXEC_FILE_ON_CRASH | \
                                 KEXEC_FILE_NO_INITRAMFS)
 
-#define VMCOREINFO_BYTES           (4096)
-#define VMCOREINFO_NOTE_NAME       "VMCOREINFO"
-#define VMCOREINFO_NOTE_NAME_BYTES ALIGN(sizeof(VMCOREINFO_NOTE_NAME), 4)
-#define VMCOREINFO_NOTE_SIZE       (KEXEC_NOTE_HEAD_BYTES*2 + VMCOREINFO_BYTES \
-                                   + VMCOREINFO_NOTE_NAME_BYTES)
-
 /* Location of a reserved region to hold the crash kernel.
  */
 extern struct resource crashk_res;
 extern struct resource crashk_low_res;
-typedef u32 note_buf_t[KEXEC_NOTE_BYTES/4];
 extern note_buf_t __percpu *crash_notes;
-extern u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4];
-extern size_t vmcoreinfo_size;
-extern size_t vmcoreinfo_max_size;
 
 /* flag to track if kexec reboot is in progress */
 extern bool kexec_in_progress;
 
-int __init parse_crashkernel(char *cmdline, unsigned long long system_ram,
-               unsigned long long *crash_size, unsigned long long *crash_base);
-int parse_crashkernel_high(char *cmdline, unsigned long long system_ram,
-               unsigned long long *crash_size, unsigned long long *crash_base);
-int parse_crashkernel_low(char *cmdline, unsigned long long system_ram,
-               unsigned long long *crash_size, unsigned long long *crash_base);
 int crash_shrink_memory(unsigned long new_size);
 size_t crash_get_memory_size(void);
 void crash_free_reserved_phys_range(unsigned long begin, unsigned long end);
index f4156f88f5575dceb23a78807a12e5fde037c701..29220724bf1cb43df4cc6840f4016fe7ba30d54c 100644 (file)
@@ -66,8 +66,6 @@ static inline void kref_get(struct kref *kref)
  */
 static inline int kref_put(struct kref *kref, void (*release)(struct kref *kref))
 {
-       WARN_ON(release == NULL);
-
        if (refcount_dec_and_test(&kref->refcount)) {
                release(kref);
                return 1;
@@ -79,8 +77,6 @@ static inline int kref_put_mutex(struct kref *kref,
                                 void (*release)(struct kref *kref),
                                 struct mutex *lock)
 {
-       WARN_ON(release == NULL);
-
        if (refcount_dec_and_mutex_lock(&kref->refcount, lock)) {
                release(kref);
                return 1;
@@ -92,8 +88,6 @@ static inline int kref_put_lock(struct kref *kref,
                                void (*release)(struct kref *kref),
                                spinlock_t *lock)
 {
-       WARN_ON(release == NULL);
-
        if (refcount_dec_and_lock(&kref->refcount, lock)) {
                release(kref);
                return 1;
index 3727afdf614d57c1a333082b0250b9057e2dd6cd..8c0664309815ff95b0308b379e863125866f31f6 100644 (file)
@@ -384,8 +384,6 @@ struct kvm {
        struct mutex slots_lock;
        struct mm_struct *mm; /* userspace tied to this vm */
        struct kvm_memslots *memslots[KVM_ADDRESS_SPACE_NUM];
-       struct srcu_struct srcu;
-       struct srcu_struct irq_srcu;
        struct kvm_vcpu *vcpus[KVM_MAX_VCPUS];
 
        /*
@@ -438,6 +436,8 @@ struct kvm {
        struct list_head devices;
        struct dentry *debugfs_dentry;
        struct kvm_stat_data **debugfs_stat_data;
+       struct srcu_struct srcu;
+       struct srcu_struct irq_srcu;
 };
 
 #define kvm_err(fmt, ...) \
@@ -499,6 +499,17 @@ static inline struct kvm_vcpu *kvm_get_vcpu_by_id(struct kvm *kvm, int id)
        return NULL;
 }
 
+static inline int kvm_vcpu_get_idx(struct kvm_vcpu *vcpu)
+{
+       struct kvm_vcpu *tmp;
+       int idx;
+
+       kvm_for_each_vcpu(idx, tmp, vcpu->kvm)
+               if (tmp == vcpu)
+                       return idx;
+       BUG();
+}
+
 #define kvm_for_each_memslot(memslot, slots)   \
        for (memslot = &slots->memslots[0];     \
              memslot < slots->memslots + KVM_MEM_SLOTS_NUM && memslot->npages;\
@@ -776,8 +787,6 @@ void kvm_arch_check_processor_compat(void *rtn);
 int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu);
 int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu);
 
-void *kvm_kvzalloc(unsigned long size);
-
 #ifndef __KVM_HAVE_ARCH_VM_ALLOC
 static inline struct kvm *kvm_arch_alloc_vm(void)
 {
@@ -1169,7 +1178,6 @@ int kvm_register_device_ops(struct kvm_device_ops *ops, u32 type);
 void kvm_unregister_device_ops(u32 type);
 
 extern struct kvm_device_ops kvm_mpic_ops;
-extern struct kvm_device_ops kvm_xics_ops;
 extern struct kvm_device_ops kvm_arm_vgic_v2_ops;
 extern struct kvm_device_ops kvm_arm_vgic_v3_ops;
 
index 140edab644462051f23d813514fe9a60404aa0e7..05728396a1a18f701f5bba8075be5301e6a89e4e 100644 (file)
@@ -18,6 +18,7 @@
 
 /* Dummy declarations */
 struct svc_rqst;
+struct rpc_task;
 
 /*
  * This is the set of functions for lockd->nfsd communication
@@ -43,6 +44,7 @@ struct nlmclnt_initdata {
        u32                     nfs_version;
        int                     noresvport;
        struct net              *net;
+       const struct nlmclnt_operations *nlmclnt_ops;
 };
 
 /*
@@ -52,8 +54,26 @@ struct nlmclnt_initdata {
 extern struct nlm_host *nlmclnt_init(const struct nlmclnt_initdata *nlm_init);
 extern void    nlmclnt_done(struct nlm_host *host);
 
-extern int     nlmclnt_proc(struct nlm_host *host, int cmd,
-                                       struct file_lock *fl);
+/*
+ * NLM client operations provide a means to modify RPC processing of NLM
+ * requests.  Callbacks receive a pointer to data passed into the call to
+ * nlmclnt_proc().
+ */
+struct nlmclnt_operations {
+       /* Called on successful allocation of nlm_rqst, use for allocation or
+        * reference counting. */
+       void (*nlmclnt_alloc_call)(void *);
+
+       /* Called in rpc_task_prepare for unlock.  A return value of true
+        * indicates the callback has put the task to sleep on a waitqueue
+        * and NLM should not call rpc_call_start(). */
+       bool (*nlmclnt_unlock_prepare)(struct rpc_task*, void *);
+
+       /* Called when the nlm_rqst is freed, callbacks should clean up here */
+       void (*nlmclnt_release_call)(void *);
+};
+
+extern int     nlmclnt_proc(struct nlm_host *host, int cmd, struct file_lock *fl, void *data);
 extern int     lockd_up(struct net *net);
 extern void    lockd_down(struct net *net);
 
index b37dee3acaba4c152fc2c0c928f4f312c74cc778..41f7b6a04d6914841a155d4734d308f6b4cc8d00 100644 (file)
@@ -69,6 +69,7 @@ struct nlm_host {
        char                    *h_addrbuf;     /* address eyecatcher */
        struct net              *net;           /* host net */
        char                    nodename[UNX_MAXNODENAME + 1];
+       const struct nlmclnt_operations *h_nlmclnt_ops; /* Callback ops for NLM users */
 };
 
 /*
@@ -142,6 +143,7 @@ struct nlm_rqst {
        struct nlm_block *      a_block;
        unsigned int            a_retries;      /* Retry count */
        u8                      a_owner[NLMCLNT_OHSIZE];
+       void *  a_callback_data; /* sent to nlmclnt_operations callbacks */
 };
 
 /*
index 4585d6105d68af19f72f1fd90663b670d45a8f8e..abbd52466573f9994ea25eab5e6d2b12c00f564e 100644 (file)
@@ -44,4 +44,8 @@
 
 #define IMX7D_GPR5_CSI_MUX_CONTROL_MIPI                (0x1 << 4)
 
+#define IMX7D_GPR12_PCIE_PHY_REFCLK_SEL                BIT(5)
+
+#define IMX7D_GPR22_PCIE_PHY_PLL_LOCKED                BIT(31)
+
 #endif /* __LINUX_IMX7_IOMUXC_GPR_H */
index 74b765ce48ab45652a9bb1e820c3c489cd159622..d5bed0875d309ce95025dbcab502f51815ca431b 100644 (file)
@@ -108,7 +108,7 @@ enum {
        MLX4_MFUNC_EQE_MASK     = (MLX4_MFUNC_MAX_EQES - 1)
 };
 
-/* Driver supports 3 diffrent device methods to manage traffic steering:
+/* Driver supports 3 different device methods to manage traffic steering:
  *     -device managed - High level API for ib and eth flow steering. FW is
  *                       managing flow steering tables.
  *     - B0 steering mode - Common low level API for ib and (if supported) eth.
index 3fece51dcf136f7694d1202b95a0f90914b938df..bcdf739ee41a2cf38fe537e48172e9ca9053e3b9 100644 (file)
@@ -892,12 +892,7 @@ static inline u16 cmdif_rev(struct mlx5_core_dev *dev)
 
 static inline void *mlx5_vzalloc(unsigned long size)
 {
-       void *rtn;
-
-       rtn = kzalloc(size, GFP_KERNEL | __GFP_NOWARN);
-       if (!rtn)
-               rtn = vzalloc(size);
-       return rtn;
+       return kvzalloc(size, GFP_KERNEL);
 }
 
 static inline u32 mlx5_base_mkey(const u32 key)
@@ -1102,6 +1097,25 @@ struct net_device *mlx5_lag_get_roce_netdev(struct mlx5_core_dev *dev);
 struct mlx5_uars_page *mlx5_get_uars_page(struct mlx5_core_dev *mdev);
 void mlx5_put_uars_page(struct mlx5_core_dev *mdev, struct mlx5_uars_page *up);
 
+#ifndef CONFIG_MLX5_CORE_IPOIB
+static inline
+struct net_device *mlx5_rdma_netdev_alloc(struct mlx5_core_dev *mdev,
+                                         struct ib_device *ibdev,
+                                         const char *name,
+                                         void (*setup)(struct net_device *))
+{
+       return ERR_PTR(-EOPNOTSUPP);
+}
+
+static inline void mlx5_rdma_netdev_free(struct net_device *netdev) {}
+#else
+struct net_device *mlx5_rdma_netdev_alloc(struct mlx5_core_dev *mdev,
+                                         struct ib_device *ibdev,
+                                         const char *name,
+                                         void (*setup)(struct net_device *));
+void mlx5_rdma_netdev_free(struct net_device *netdev);
+#endif /* CONFIG_MLX5_CORE_IPOIB */
+
 struct mlx5_profile {
        u64     mask;
        u8      log_max_qp;
index 1b166d2e19c57829279faa20a88796fabb5d3f5e..b25e7baa273e8d9db99fb1e2f33e3086ea875e89 100644 (file)
@@ -109,7 +109,6 @@ struct mlx5_flow_table_attr {
        int max_fte;
        u32 level;
        u32 flags;
-       u32 underlay_qpn;
 };
 
 struct mlx5_flow_table *
@@ -167,4 +166,7 @@ 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);
 void mlx5_fc_query_cached(struct mlx5_fc *counter,
                          u64 *bytes, u64 *packets, u64 *lastuse);
+int mlx5_fs_add_rx_underlay_qpn(struct mlx5_core_dev *dev, u32 underlay_qpn);
+int mlx5_fs_remove_rx_underlay_qpn(struct mlx5_core_dev *dev, u32 underlay_qpn);
+
 #endif
index 5d22e69f51ea6ff5f7d3fffef5239fd84bf60d6c..7cb17c6b97de38b1e8d55ca6d8c90b8415a9c3fa 100644 (file)
@@ -518,6 +518,28 @@ static inline int is_vmalloc_or_module_addr(const void *x)
 }
 #endif
 
+extern void *kvmalloc_node(size_t size, gfp_t flags, int node);
+static inline void *kvmalloc(size_t size, gfp_t flags)
+{
+       return kvmalloc_node(size, flags, NUMA_NO_NODE);
+}
+static inline void *kvzalloc_node(size_t size, gfp_t flags, int node)
+{
+       return kvmalloc_node(size, flags | __GFP_ZERO, node);
+}
+static inline void *kvzalloc(size_t size, gfp_t flags)
+{
+       return kvmalloc(size, flags | __GFP_ZERO);
+}
+
+static inline void *kvmalloc_array(size_t n, size_t size, gfp_t flags)
+{
+       if (size != 0 && n > SIZE_MAX / size)
+               return NULL;
+
+       return kvmalloc(n * size, flags);
+}
+
 extern void kvfree(const void *addr);
 
 static inline atomic_t *compound_mapcount_ptr(struct page *page)
index e0c3c5e3d8a0e507c2703716ec4f5ef9b2bdd6dd..ebaccd4e7d8cdc5f5ef13fed1475a8b202d93628 100644 (file)
@@ -74,6 +74,11 @@ extern char * const migratetype_names[MIGRATE_TYPES];
 #  define is_migrate_cma_page(_page) false
 #endif
 
+static inline bool is_migrate_movable(int mt)
+{
+       return is_migrate_cma(mt) || mt == MIGRATE_MOVABLE;
+}
+
 #define for_each_migratetype_order(order, type) \
        for (order = 0; order < MAX_ORDER; order++) \
                for (type = 0; type < MIGRATE_TYPES; type++)
index 8850fcaf50dba05d9440b958c5d95cd9330e727a..566fda587fcf7a76af1c6a01e84ce33336606f3f 100644 (file)
@@ -428,6 +428,16 @@ struct i2c_device_id {
        kernel_ulong_t driver_data;     /* Data private to the driver */
 };
 
+/* pci_epf */
+
+#define PCI_EPF_NAME_SIZE      20
+#define PCI_EPF_MODULE_PREFIX  "pci_epf:"
+
+struct pci_epf_device_id {
+       char name[PCI_EPF_NAME_SIZE];
+       kernel_ulong_t driver_data;
+};
+
 /* spi */
 
 #define SPI_NAME_SIZE  32
index 52666d90ca9452251c539383ecc7b038ba9afbea..6be1949ebcdff2dd2dcb5270618c7a56a42fdc40 100644 (file)
@@ -60,9 +60,11 @@ struct kernel_param_ops {
  * Flags available for kernel_param
  *
  * UNSAFE - the parameter is dangerous and setting it will taint the kernel
+ * HWPARAM - Hardware param not permitted in lockdown mode
  */
 enum {
-       KERNEL_PARAM_FL_UNSAFE = (1 << 0)
+       KERNEL_PARAM_FL_UNSAFE  = (1 << 0),
+       KERNEL_PARAM_FL_HWPARAM = (1 << 1),
 };
 
 struct kernel_param {
@@ -451,6 +453,67 @@ extern int param_set_bint(const char *val, const struct kernel_param *kp);
                            perm, -1, 0);                               \
        __MODULE_PARM_TYPE(name, "array of " #type)
 
+enum hwparam_type {
+       hwparam_ioport,         /* Module parameter configures an I/O port */
+       hwparam_iomem,          /* Module parameter configures an I/O mem address */
+       hwparam_ioport_or_iomem, /* Module parameter could be either, depending on other option */
+       hwparam_irq,            /* Module parameter configures an I/O port */
+       hwparam_dma,            /* Module parameter configures a DMA channel */
+       hwparam_dma_addr,       /* Module parameter configures a DMA buffer address */
+       hwparam_other,          /* Module parameter configures some other value */
+};
+
+/**
+ * module_param_hw_named - A parameter representing a hw parameters
+ * @name: a valid C identifier which is the parameter name.
+ * @value: the actual lvalue to alter.
+ * @type: the type of the parameter
+ * @hwtype: what the value represents (enum hwparam_type)
+ * @perm: visibility in sysfs.
+ *
+ * Usually it's a good idea to have variable names and user-exposed names the
+ * same, but that's harder if the variable must be non-static or is inside a
+ * structure.  This allows exposure under a different name.
+ */
+#define module_param_hw_named(name, value, type, hwtype, perm)         \
+       param_check_##type(name, &(value));                             \
+       __module_param_call(MODULE_PARAM_PREFIX, name,                  \
+                           &param_ops_##type, &value,                  \
+                           perm, -1,                                   \
+                           KERNEL_PARAM_FL_HWPARAM | (hwparam_##hwtype & 0));  \
+       __MODULE_PARM_TYPE(name, #type)
+
+#define module_param_hw(name, type, hwtype, perm)              \
+       module_param_hw_named(name, name, type, hwtype, perm)
+
+/**
+ * module_param_hw_array - A parameter representing an array of hw parameters
+ * @name: the name of the array variable
+ * @type: the type, as per module_param()
+ * @hwtype: what the value represents (enum hwparam_type)
+ * @nump: optional pointer filled in with the number written
+ * @perm: visibility in sysfs
+ *
+ * Input and output are as comma-separated values.  Commas inside values
+ * don't work properly (eg. an array of charp).
+ *
+ * ARRAY_SIZE(@name) is used to determine the number of elements in the
+ * array, so the definition must be visible.
+ */
+#define module_param_hw_array(name, type, hwtype, nump, perm)          \
+       param_check_##type(name, &(name)[0]);                           \
+       static const struct kparam_array __param_arr_##name             \
+       = { .max = ARRAY_SIZE(name), .num = nump,                       \
+           .ops = &param_ops_##type,                                   \
+           .elemsize = sizeof(name[0]), .elem = name };                \
+       __module_param_call(MODULE_PARAM_PREFIX, name,                  \
+                           &param_array_ops,                           \
+                           .arr = &__param_arr_##name,                 \
+                           perm, -1,                                   \
+                           KERNEL_PARAM_FL_HWPARAM | (hwparam_##hwtype & 0));  \
+       __MODULE_PARM_TYPE(name, "array of " #type)
+
+
 extern const struct kernel_param_ops param_array_ops;
 
 extern const struct kernel_param_ops param_ops_string;
index 79b176eca04a18c0c49c98a693e6ebe35e3eeee3..f8a2ef239c60adf6ce49f5ebcdbf576db0bd434d 100644 (file)
@@ -388,7 +388,7 @@ static inline void mtd_set_of_node(struct mtd_info *mtd,
 
 static inline struct device_node *mtd_get_of_node(struct mtd_info *mtd)
 {
-       return mtd->dev.of_node;
+       return dev_of_node(&mtd->dev);
 }
 
 static inline int mtd_oobavail(struct mtd_info *mtd, struct mtd_oob_ops *ops)
index 9591e0fbe5bd76a1c47e2deb4292469e0a2cf8e6..8f67b15816836a1127fddae062c1ad76774e4534 100644 (file)
@@ -366,26 +366,6 @@ struct onfi_ext_param_page {
         */
 } __packed;
 
-struct nand_onfi_vendor_micron {
-       u8 two_plane_read;
-       u8 read_cache;
-       u8 read_unique_id;
-       u8 dq_imped;
-       u8 dq_imped_num_settings;
-       u8 dq_imped_feat_addr;
-       u8 rb_pulldown_strength;
-       u8 rb_pulldown_strength_feat_addr;
-       u8 rb_pulldown_strength_num_settings;
-       u8 otp_mode;
-       u8 otp_page_start;
-       u8 otp_data_prot_addr;
-       u8 otp_num_pages;
-       u8 otp_feat_addr;
-       u8 read_retry_options;
-       u8 reserved[72];
-       u8 param_revision;
-} __packed;
-
 struct jedec_ecc_info {
        u8 ecc_bits;
        u8 codeword_size;
@@ -464,6 +444,17 @@ struct nand_jedec_params {
        __le16 crc;
 } __packed;
 
+/**
+ * struct nand_id - NAND id structure
+ * @data: buffer containing the id bytes. Currently 8 bytes large, but can
+ *       be extended if required.
+ * @len: ID length.
+ */
+struct nand_id {
+       u8 data[8];
+       int len;
+};
+
 /**
  * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independent devices
  * @lock:               protection lock
@@ -525,7 +516,7 @@ static inline void nand_hw_control_init(struct nand_hw_control *nfc)
  *                     out-of-band data).
  * @read_page: function to read a page according to the ECC generator
  *             requirements; returns maximum number of bitflips corrected in
- *             any single ECC step, 0 if bitflips uncorrectable, -EIO hw error
+ *             any single ECC step, -EIO hw error
  * @read_subpage:      function to read parts of the page covered by ECC;
  *                     returns same as read_page()
  * @write_subpage:     function to write parts of the page covered by ECC.
@@ -720,6 +711,20 @@ nand_get_sdr_timings(const struct nand_data_interface *conf)
        return &conf->timings.sdr;
 }
 
+/**
+ * struct nand_manufacturer_ops - NAND Manufacturer operations
+ * @detect: detect the NAND memory organization and capabilities
+ * @init: initialize all vendor specific fields (like the ->read_retry()
+ *       implementation) if any.
+ * @cleanup: the ->init() function may have allocated resources, ->cleanup()
+ *          is here to let vendor specific code release those resources.
+ */
+struct nand_manufacturer_ops {
+       void (*detect)(struct nand_chip *chip);
+       int (*init)(struct nand_chip *chip);
+       void (*cleanup)(struct nand_chip *chip);
+};
+
 /**
  * struct nand_chip - NAND Private Flash Chip Data
  * @mtd:               MTD device registered to the MTD framework
@@ -750,6 +755,7 @@ nand_get_sdr_timings(const struct nand_data_interface *conf)
  *                     setting the read-retry mode. Mostly needed for MLC NAND.
  * @ecc:               [BOARDSPECIFIC] ECC control structure
  * @buffers:           buffer structure for read/write
+ * @buf_align:         minimum buffer alignment required by a platform
  * @hwcontrol:         platform-specific hardware control structure
  * @erase:             [REPLACEABLE] erase function
  * @scan_bbt:          [REPLACEABLE] function to scan bad block table
@@ -793,6 +799,7 @@ nand_get_sdr_timings(const struct nand_data_interface *conf)
  * @pagebuf_bitflips:  [INTERN] holds the bitflip count for the page which is
  *                     currently in data_buf.
  * @subpagesize:       [INTERN] holds the subpagesize
+ * @id:                        [INTERN] holds NAND ID
  * @onfi_version:      [INTERN] holds the chip ONFI version (BCD encoded),
  *                     non 0 if ONFI supported.
  * @jedec_version:     [INTERN] holds the chip JEDEC version (BCD encoded),
@@ -822,7 +829,7 @@ nand_get_sdr_timings(const struct nand_data_interface *conf)
  * @errstat:           [OPTIONAL] hardware specific function to perform
  *                     additional error status checks (determine if errors are
  *                     correctable).
- * @write_page:                [REPLACEABLE] High-level page write function
+ * @manufacturer:      [INTERN] Contains manufacturer information
  */
 
 struct nand_chip {
@@ -847,9 +854,6 @@ struct nand_chip {
        int (*scan_bbt)(struct mtd_info *mtd);
        int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state,
                        int status, int page);
-       int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
-                       uint32_t offset, int data_len, const uint8_t *buf,
-                       int oob_required, int page, int cached, int raw);
        int (*onfi_set_features)(struct mtd_info *mtd, struct nand_chip *chip,
                        int feature_addr, uint8_t *subfeature_para);
        int (*onfi_get_features)(struct mtd_info *mtd, struct nand_chip *chip,
@@ -881,6 +885,7 @@ struct nand_chip {
        int badblockpos;
        int badblockbits;
 
+       struct nand_id id;
        int onfi_version;
        int jedec_version;
        union {
@@ -901,6 +906,7 @@ struct nand_chip {
 
        struct nand_ecc_ctrl ecc;
        struct nand_buffers *buffers;
+       unsigned long buf_align;
        struct nand_hw_control hwcontrol;
 
        uint8_t *bbt;
@@ -910,6 +916,11 @@ struct nand_chip {
        struct nand_bbt_descr *badblock_pattern;
 
        void *priv;
+
+       struct {
+               const struct nand_manufacturer *desc;
+               void *priv;
+       } manufacturer;
 };
 
 extern const struct mtd_ooblayout_ops nand_ooblayout_sp_ops;
@@ -946,6 +957,17 @@ static inline void nand_set_controller_data(struct nand_chip *chip, void *priv)
        chip->priv = priv;
 }
 
+static inline void nand_set_manufacturer_data(struct nand_chip *chip,
+                                             void *priv)
+{
+       chip->manufacturer.priv = priv;
+}
+
+static inline void *nand_get_manufacturer_data(struct nand_chip *chip)
+{
+       return chip->manufacturer.priv;
+}
+
 /*
  * NAND Flash Manufacturer ID Codes
  */
@@ -1049,17 +1071,33 @@ struct nand_flash_dev {
 };
 
 /**
- * struct nand_manufacturers - NAND Flash Manufacturer ID Structure
+ * struct nand_manufacturer - NAND Flash Manufacturer structure
  * @name:      Manufacturer name
  * @id:                manufacturer ID code of device.
+ * @ops:       manufacturer operations
 */
-struct nand_manufacturers {
+struct nand_manufacturer {
        int id;
        char *name;
+       const struct nand_manufacturer_ops *ops;
 };
 
+const struct nand_manufacturer *nand_get_manufacturer(u8 id);
+
+static inline const char *
+nand_manufacturer_name(const struct nand_manufacturer *manufacturer)
+{
+       return manufacturer ? manufacturer->name : "Unknown";
+}
+
 extern struct nand_flash_dev nand_flash_ids[];
-extern struct nand_manufacturers nand_manuf_ids[];
+
+extern const struct nand_manufacturer_ops toshiba_nand_manuf_ops;
+extern const struct nand_manufacturer_ops samsung_nand_manuf_ops;
+extern const struct nand_manufacturer_ops hynix_nand_manuf_ops;
+extern const struct nand_manufacturer_ops micron_nand_manuf_ops;
+extern const struct nand_manufacturer_ops amd_nand_manuf_ops;
+extern const struct nand_manufacturer_ops macronix_nand_manuf_ops;
 
 int nand_default_bbt(struct mtd_info *mtd);
 int nand_markbad_bbt(struct mtd_info *mtd, loff_t offs);
@@ -1226,4 +1264,6 @@ int nand_reset(struct nand_chip *chip, int chipnr);
 /* Free resources held by the NAND device */
 void nand_cleanup(struct nand_chip *chip);
 
+/* Default extended ID decoding function */
+void nand_decode_ext_id(struct nand_chip *chip);
 #endif /* __LINUX_MTD_NAND_H */
index f29abda31e6dc8b32376a86c6c52e9e9ca6da0a0..8b4794e83196db62997ef5aea81886c3ad800bbd 100644 (file)
@@ -44,6 +44,7 @@ enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT, LAST_BIND};
 #define LOOKUP_JUMPED          0x1000
 #define LOOKUP_ROOT            0x2000
 #define LOOKUP_EMPTY           0x4000
+#define LOOKUP_DOWN            0x8000
 
 extern int path_pts(struct path *path);
 
index fa66aeed441a5882a1dcad4ad7a8c89faca1abf3..194b8e002ea74d9e0cef5ec184cf23833c0b6215 100644 (file)
@@ -48,7 +48,7 @@ struct nd_namespace_common {
        struct device dev;
        struct device *claim;
        int (*rw_bytes)(struct nd_namespace_common *, resource_size_t offset,
-                       void *buf, size_t size, int rw);
+                       void *buf, size_t size, int rw, unsigned long flags);
 };
 
 static inline struct nd_namespace_common *to_ndns(struct device *dev)
@@ -134,9 +134,10 @@ static inline struct nd_namespace_blk *to_nd_namespace_blk(const struct device *
  * @buf is up-to-date upon return from this routine.
  */
 static inline int nvdimm_read_bytes(struct nd_namespace_common *ndns,
-               resource_size_t offset, void *buf, size_t size)
+               resource_size_t offset, void *buf, size_t size,
+               unsigned long flags)
 {
-       return ndns->rw_bytes(ndns, offset, buf, size, READ);
+       return ndns->rw_bytes(ndns, offset, buf, size, READ, flags);
 }
 
 /**
@@ -152,9 +153,10 @@ static inline int nvdimm_read_bytes(struct nd_namespace_common *ndns,
  * to media is handled internal to the @ndns driver, if at all.
  */
 static inline int nvdimm_write_bytes(struct nd_namespace_common *ndns,
-               resource_size_t offset, void *buf, size_t size)
+               resource_size_t offset, void *buf, size_t size,
+               unsigned long flags)
 {
-       return ndns->rw_bytes(ndns, offset, buf, size, WRITE);
+       return ndns->rw_bytes(ndns, offset, buf, size, WRITE, flags);
 }
 
 #define MODULE_ALIAS_ND_DEVICE(type) \
index 9c23bd2efb56393e7c616d42d427101c3f5f51d2..3f39d27decf4d72e734734edec4403b00ca95657 100644 (file)
@@ -3296,11 +3296,15 @@ int dev_get_phys_port_id(struct net_device *dev,
 int dev_get_phys_port_name(struct net_device *dev,
                           char *name, size_t len);
 int dev_change_proto_down(struct net_device *dev, bool proto_down);
-int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
-                     int fd, u32 flags);
 struct sk_buff *validate_xmit_skb_list(struct sk_buff *skb, struct net_device *dev);
 struct sk_buff *dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev,
                                    struct netdev_queue *txq, int *ret);
+
+typedef int (*xdp_op_t)(struct net_device *dev, struct netdev_xdp *xdp);
+int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
+                     int fd, u32 flags);
+bool __dev_xdp_attached(struct net_device *dev, xdp_op_t xdp_op);
+
 int __dev_forward_skb(struct net_device *dev, struct sk_buff *skb);
 int dev_forward_skb(struct net_device *dev, struct sk_buff *skb);
 bool is_skb_forwardable(const struct net_device *dev,
index 287f341610864f745e44fb4cbfb4ad44a26f4ea5..bb0eb2c9acca7d19ddf14c65480a9ee27715c561 100644 (file)
@@ -76,6 +76,7 @@ struct nfs_open_context {
 #define NFS_CONTEXT_ERROR_WRITE                (0)
 #define NFS_CONTEXT_RESEND_WRITES      (1)
 #define NFS_CONTEXT_BAD                        (2)
+#define NFS_CONTEXT_UNLOCK     (3)
        int error;
 
        struct list_head list;
@@ -499,24 +500,12 @@ extern int  nfs_updatepage(struct file *, struct page *, unsigned int, unsigned
  */
 extern int nfs_sync_inode(struct inode *inode);
 extern int nfs_wb_all(struct inode *inode);
-extern int nfs_wb_single_page(struct inode *inode, struct page *page, bool launder);
+extern int nfs_wb_page(struct inode *inode, struct page *page);
 extern int nfs_wb_page_cancel(struct inode *inode, struct page* page);
 extern int  nfs_commit_inode(struct inode *, int);
-extern struct nfs_commit_data *nfs_commitdata_alloc(void);
+extern struct nfs_commit_data *nfs_commitdata_alloc(bool never_fail);
 extern void nfs_commit_free(struct nfs_commit_data *data);
 
-static inline int
-nfs_wb_launder_page(struct inode *inode, struct page *page)
-{
-       return nfs_wb_single_page(inode, page, true);
-}
-
-static inline int
-nfs_wb_page(struct inode *inode, struct page *page)
-{
-       return nfs_wb_single_page(inode, page, false);
-}
-
 static inline int
 nfs_have_writebacks(struct inode *inode)
 {
index e1502c55741ef805eb2fcc2c2dadfc07d2b0d0dc..e418a1096662c387f1b96e834d90983c22e5106f 100644 (file)
@@ -221,6 +221,7 @@ struct nfs_server {
        u32                     mountd_version;
        unsigned short          mountd_port;
        unsigned short          mountd_protocol;
+       struct rpc_wait_queue   uoc_rpcwaitq;
 };
 
 /* Server capabilities */
index 957049f72290d4b6c328845535c664aea4afc7c0..247cc3d3498f241b19f57b486685986b81d95e56 100644 (file)
@@ -64,7 +64,6 @@ struct nfs_pageio_ops {
 };
 
 struct nfs_rw_ops {
-       const fmode_t rw_mode;
        struct nfs_pgio_header *(*rw_alloc_header)(void);
        void (*rw_free_header)(struct nfs_pgio_header *);
        int  (*rw_done)(struct rpc_task *, struct nfs_pgio_header *,
@@ -124,7 +123,8 @@ extern      void nfs_pageio_init(struct nfs_pageio_descriptor *desc,
                             const struct nfs_pgio_completion_ops *compl_ops,
                             const struct nfs_rw_ops *rw_ops,
                             size_t bsize,
-                            int how);
+                            int how,
+                            gfp_t gfp_flags);
 extern int nfs_pageio_add_request(struct nfs_pageio_descriptor *,
                                   struct nfs_page *);
 extern  int nfs_pageio_resend(struct nfs_pageio_descriptor *,
@@ -141,6 +141,7 @@ extern int nfs_page_group_lock(struct nfs_page *, bool);
 extern void nfs_page_group_lock_wait(struct nfs_page *);
 extern void nfs_page_group_unlock(struct nfs_page *);
 extern bool nfs_page_group_sync_on_bit(struct nfs_page *, unsigned int);
+extern bool nfs_async_iocounter_wait(struct rpc_task *, struct nfs_lock_context *);
 
 /*
  * Lock the page of an asynchronous request
index 348f7c158084b8de71c2a0a2f6941b0db7bf2c3b..b28c83475ee8e9106c5f567551e4307156dfe465 100644 (file)
@@ -1383,6 +1383,7 @@ struct nfs42_copy_res {
        struct nfs42_write_res          write_res;
        bool                            consecutive;
        bool                            synchronous;
+       struct nfs_commitres            commit_res;
 };
 
 struct nfs42_seek_args {
@@ -1427,6 +1428,7 @@ struct nfs_pgio_header {
        struct list_head        pages;
        struct nfs_page         *req;
        struct nfs_writeverf    verf;           /* Used for writes */
+       fmode_t                 rw_mode;
        struct pnfs_layout_segment *lseg;
        loff_t                  io_start;
        const struct rpc_call_ops *mds_ops;
@@ -1550,6 +1552,7 @@ struct nfs_rpc_ops {
        const struct inode_operations *dir_inode_ops;
        const struct inode_operations *file_inode_ops;
        const struct file_operations *file_ops;
+       const struct nlmclnt_operations *nlmclnt_ops;
 
        int     (*getroot) (struct nfs_server *, struct nfs_fh *,
                            struct nfs_fsinfo *);
index 169ea0bd8eb4e72549331f4a181dec50ae3c1946..b4ad8b4f85065dae43ab10be81ac27851b4802e7 100644 (file)
@@ -54,7 +54,8 @@ static inline struct device_node *of_cpu_device_node_get(int cpu)
        return of_node_get(cpu_dev->of_node);
 }
 
-void of_dma_configure(struct device *dev, struct device_node *np);
+int of_dma_configure(struct device *dev, struct device_node *np);
+void of_dma_deconfigure(struct device *dev);
 #else /* CONFIG_OF */
 
 static inline int of_driver_match_device(struct device *dev,
@@ -102,7 +103,12 @@ static inline struct device_node *of_cpu_device_node_get(int cpu)
 {
        return NULL;
 }
-static inline void of_dma_configure(struct device *dev, struct device_node *np)
+
+static inline int of_dma_configure(struct device *dev, struct device_node *np)
+{
+       return 0;
+}
+static inline void of_dma_deconfigure(struct device *dev)
 {}
 #endif /* CONFIG_OF */
 
index 271b3fdf00709e2752115e0d371cfa397791eec4..1dfbfd0d8040cb56820e43f51fc9bf58b7d117e8 100644 (file)
@@ -54,6 +54,11 @@ extern char __dtb_end[];
 extern int of_scan_flat_dt(int (*it)(unsigned long node, const char *uname,
                                     int depth, void *data),
                           void *data);
+extern int of_scan_flat_dt_subnodes(unsigned long node,
+                                   int (*it)(unsigned long node,
+                                             const char *uname,
+                                             void *data),
+                                   void *data);
 extern int of_get_flat_dt_subnode_by_name(unsigned long node,
                                          const char *uname);
 extern const void *of_get_flat_dt_prop(unsigned long node, const char *name,
@@ -62,6 +67,7 @@ extern int of_flat_dt_is_compatible(unsigned long node, const char *name);
 extern int of_flat_dt_match(unsigned long node, const char *const *matches);
 extern unsigned long of_get_flat_dt_root(void);
 extern int of_get_flat_dt_size(void);
+extern uint32_t of_get_flat_dt_phandle(unsigned long node);
 
 extern int early_init_dt_scan_chosen(unsigned long node, const char *uname,
                                     int depth, void *data);
index ec6b11deb77357444757691ec87d71d94b1b8953..1e0deb8e849458ca179c1df4734bb24f0e4cd748 100644 (file)
@@ -8,7 +8,7 @@
 #include <linux/ioport.h>
 #include <linux/of.h>
 
-typedef int const (*of_irq_init_cb_t)(struct device_node *, struct device_node *);
+typedef int (*of_irq_init_cb_t)(struct device_node *, struct device_node *);
 
 /*
  * Workarounds only applied to 32bit powermac machines
index 0e0974eceb803b64cee8f8f67a7bde55d58f8f4a..518c8d20647a560bf2f679b62b80364b040ba9ae 100644 (file)
@@ -85,15 +85,4 @@ static inline int of_pci_get_host_bridge_resources(struct device_node *dev,
 }
 #endif
 
-#if defined(CONFIG_OF) && defined(CONFIG_PCI_MSI)
-int of_pci_msi_chip_add(struct msi_controller *chip);
-void of_pci_msi_chip_remove(struct msi_controller *chip);
-struct msi_controller *of_pci_find_msi_chip_by_node(struct device_node *of_node);
-#else
-static inline int of_pci_msi_chip_add(struct msi_controller *chip) { return -EINVAL; }
-static inline void of_pci_msi_chip_remove(struct msi_controller *chip) { }
-static inline struct msi_controller *
-of_pci_find_msi_chip_by_node(struct device_node *of_node) { return NULL; }
-#endif
-
 #endif
index 047d64706f2a298157cf0d54305aa8e49f6f7837..d4cd2014fa6f5a18f03f1b0babfccb21fa3ac55f 100644 (file)
@@ -33,10 +33,7 @@ bool has_unmovable_pages(struct zone *zone, struct page *page, int count,
                         bool skip_hwpoisoned_pages);
 void set_pageblock_migratetype(struct page *page, int migratetype);
 int move_freepages_block(struct zone *zone, struct page *page,
-                               int migratetype);
-int move_freepages(struct zone *zone,
-                         struct page *start_page, struct page *end_page,
-                         int migratetype);
+                               int migratetype, int *num_movable);
 
 /*
  * Changes migrate type in [start_pfn, end_pfn) to be MIGRATE_ISOLATE.
index f0d2b94512701ccdb6c77d5b37c7ff4f49ea1d3e..809c2f1873ac2a04c6ebb262407196302d00ea46 100644 (file)
@@ -16,6 +16,7 @@
 #ifndef DRIVERS_PCI_ECAM_H
 #define DRIVERS_PCI_ECAM_H
 
+#include <linux/pci.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 
@@ -68,7 +69,7 @@ extern struct pci_ecam_ops xgene_v1_pcie_ecam_ops; /* APM X-Gene PCIe v1 */
 extern struct pci_ecam_ops xgene_v2_pcie_ecam_ops; /* APM X-Gene PCIe v2.x */
 #endif
 
-#ifdef CONFIG_PCI_HOST_GENERIC
+#ifdef CONFIG_PCI_HOST_COMMON
 /* for DT-based PCI controllers that support ECAM */
 int pci_host_common_probe(struct platform_device *pdev,
                          struct pci_ecam_ops *ops);
diff --git a/include/linux/pci-ep-cfs.h b/include/linux/pci-ep-cfs.h
new file mode 100644 (file)
index 0000000..263b89e
--- /dev/null
@@ -0,0 +1,41 @@
+/**
+ * PCI Endpoint ConfigFS header file
+ *
+ * Copyright (C) 2017 Texas Instruments
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 of
+ * the License as published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_PCI_EP_CFS_H
+#define __LINUX_PCI_EP_CFS_H
+
+#include <linux/configfs.h>
+
+#ifdef CONFIG_PCI_ENDPOINT_CONFIGFS
+struct config_group *pci_ep_cfs_add_epc_group(const char *name);
+void pci_ep_cfs_remove_epc_group(struct config_group *group);
+struct config_group *pci_ep_cfs_add_epf_group(const char *name);
+void pci_ep_cfs_remove_epf_group(struct config_group *group);
+#else
+static inline struct config_group *pci_ep_cfs_add_epc_group(const char *name)
+{
+       return 0;
+}
+
+static inline void pci_ep_cfs_remove_epc_group(struct config_group *group)
+{
+}
+
+static inline struct config_group *pci_ep_cfs_add_epf_group(const char *name)
+{
+       return 0;
+}
+
+static inline void pci_ep_cfs_remove_epf_group(struct config_group *group)
+{
+}
+#endif
+#endif /* __LINUX_PCI_EP_CFS_H */
diff --git a/include/linux/pci-epc.h b/include/linux/pci-epc.h
new file mode 100644 (file)
index 0000000..af5edbf
--- /dev/null
@@ -0,0 +1,144 @@
+/**
+ * PCI Endpoint *Controller* (EPC) header file
+ *
+ * Copyright (C) 2017 Texas Instruments
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 of
+ * the License as published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_PCI_EPC_H
+#define __LINUX_PCI_EPC_H
+
+#include <linux/pci-epf.h>
+
+struct pci_epc;
+
+enum pci_epc_irq_type {
+       PCI_EPC_IRQ_UNKNOWN,
+       PCI_EPC_IRQ_LEGACY,
+       PCI_EPC_IRQ_MSI,
+};
+
+/**
+ * struct pci_epc_ops - set of function pointers for performing EPC operations
+ * @write_header: ops to populate configuration space header
+ * @set_bar: ops to configure the BAR
+ * @clear_bar: ops to reset the BAR
+ * @map_addr: ops to map CPU address to PCI address
+ * @unmap_addr: ops to unmap CPU address and PCI address
+ * @set_msi: ops to set the requested number of MSI interrupts in the MSI
+ *          capability register
+ * @get_msi: ops to get the number of MSI interrupts allocated by the RC from
+ *          the MSI capability register
+ * @raise_irq: ops to raise a legacy or MSI interrupt
+ * @start: ops to start the PCI link
+ * @stop: ops to stop the PCI link
+ * @owner: the module owner containing the ops
+ */
+struct pci_epc_ops {
+       int     (*write_header)(struct pci_epc *pci_epc,
+                               struct pci_epf_header *hdr);
+       int     (*set_bar)(struct pci_epc *epc, enum pci_barno bar,
+                          dma_addr_t bar_phys, size_t size, int flags);
+       void    (*clear_bar)(struct pci_epc *epc, enum pci_barno bar);
+       int     (*map_addr)(struct pci_epc *epc, phys_addr_t addr,
+                           u64 pci_addr, size_t size);
+       void    (*unmap_addr)(struct pci_epc *epc, phys_addr_t addr);
+       int     (*set_msi)(struct pci_epc *epc, u8 interrupts);
+       int     (*get_msi)(struct pci_epc *epc);
+       int     (*raise_irq)(struct pci_epc *pci_epc,
+                            enum pci_epc_irq_type type, u8 interrupt_num);
+       int     (*start)(struct pci_epc *epc);
+       void    (*stop)(struct pci_epc *epc);
+       struct module *owner;
+};
+
+/**
+ * struct pci_epc_mem - address space of the endpoint controller
+ * @phys_base: physical base address of the PCI address space
+ * @size: the size of the PCI address space
+ * @bitmap: bitmap to manage the PCI address space
+ * @pages: number of bits representing the address region
+ */
+struct pci_epc_mem {
+       phys_addr_t     phys_base;
+       size_t          size;
+       unsigned long   *bitmap;
+       int             pages;
+};
+
+/**
+ * struct pci_epc - represents the PCI EPC device
+ * @dev: PCI EPC device
+ * @pci_epf: list of endpoint functions present in this EPC device
+ * @ops: function pointers for performing endpoint operations
+ * @mem: address space of the endpoint controller
+ * @max_functions: max number of functions that can be configured in this EPC
+ * @group: configfs group representing the PCI EPC device
+ * @lock: spinlock to protect pci_epc ops
+ */
+struct pci_epc {
+       struct device                   dev;
+       struct list_head                pci_epf;
+       const struct pci_epc_ops        *ops;
+       struct pci_epc_mem              *mem;
+       u8                              max_functions;
+       struct config_group             *group;
+       /* spinlock to protect against concurrent access of EP controller */
+       spinlock_t                      lock;
+};
+
+#define to_pci_epc(device) container_of((device), struct pci_epc, dev)
+
+#define pci_epc_create(dev, ops)    \
+               __pci_epc_create((dev), (ops), THIS_MODULE)
+#define devm_pci_epc_create(dev, ops)    \
+               __devm_pci_epc_create((dev), (ops), THIS_MODULE)
+
+static inline void epc_set_drvdata(struct pci_epc *epc, void *data)
+{
+       dev_set_drvdata(&epc->dev, data);
+}
+
+static inline void *epc_get_drvdata(struct pci_epc *epc)
+{
+       return dev_get_drvdata(&epc->dev);
+}
+
+struct pci_epc *
+__devm_pci_epc_create(struct device *dev, const struct pci_epc_ops *ops,
+                     struct module *owner);
+struct pci_epc *
+__pci_epc_create(struct device *dev, const struct pci_epc_ops *ops,
+                struct module *owner);
+void devm_pci_epc_destroy(struct device *dev, struct pci_epc *epc);
+void pci_epc_destroy(struct pci_epc *epc);
+int pci_epc_add_epf(struct pci_epc *epc, struct pci_epf *epf);
+void pci_epc_linkup(struct pci_epc *epc);
+void pci_epc_remove_epf(struct pci_epc *epc, struct pci_epf *epf);
+int pci_epc_write_header(struct pci_epc *epc, struct pci_epf_header *hdr);
+int pci_epc_set_bar(struct pci_epc *epc, enum pci_barno bar,
+                   dma_addr_t bar_phys, size_t size, int flags);
+void pci_epc_clear_bar(struct pci_epc *epc, int bar);
+int pci_epc_map_addr(struct pci_epc *epc, phys_addr_t phys_addr,
+                    u64 pci_addr, size_t size);
+void pci_epc_unmap_addr(struct pci_epc *epc, phys_addr_t phys_addr);
+int pci_epc_set_msi(struct pci_epc *epc, u8 interrupts);
+int pci_epc_get_msi(struct pci_epc *epc);
+int pci_epc_raise_irq(struct pci_epc *epc, enum pci_epc_irq_type type,
+                     u8 interrupt_num);
+int pci_epc_start(struct pci_epc *epc);
+void pci_epc_stop(struct pci_epc *epc);
+struct pci_epc *pci_epc_get(const char *epc_name);
+void pci_epc_put(struct pci_epc *epc);
+
+int pci_epc_mem_init(struct pci_epc *epc, phys_addr_t phys_addr, size_t size);
+void pci_epc_mem_exit(struct pci_epc *epc);
+void __iomem *pci_epc_mem_alloc_addr(struct pci_epc *epc,
+                                    phys_addr_t *phys_addr, size_t size);
+void pci_epc_mem_free_addr(struct pci_epc *epc, phys_addr_t phys_addr,
+                          void __iomem *virt_addr, size_t size);
+#endif /* __LINUX_PCI_EPC_H */
diff --git a/include/linux/pci-epf.h b/include/linux/pci-epf.h
new file mode 100644 (file)
index 0000000..0d529cb
--- /dev/null
@@ -0,0 +1,162 @@
+/**
+ * PCI Endpoint *Function* (EPF) header file
+ *
+ * Copyright (C) 2017 Texas Instruments
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 of
+ * the License as published by the Free Software Foundation.
+ */
+
+#ifndef __LINUX_PCI_EPF_H
+#define __LINUX_PCI_EPF_H
+
+#include <linux/device.h>
+#include <linux/mod_devicetable.h>
+
+struct pci_epf;
+
+enum pci_interrupt_pin {
+       PCI_INTERRUPT_UNKNOWN,
+       PCI_INTERRUPT_INTA,
+       PCI_INTERRUPT_INTB,
+       PCI_INTERRUPT_INTC,
+       PCI_INTERRUPT_INTD,
+};
+
+enum pci_barno {
+       BAR_0,
+       BAR_1,
+       BAR_2,
+       BAR_3,
+       BAR_4,
+       BAR_5,
+};
+
+/**
+ * struct pci_epf_header - represents standard configuration header
+ * @vendorid: identifies device manufacturer
+ * @deviceid: identifies a particular device
+ * @revid: specifies a device-specific revision identifier
+ * @progif_code: identifies a specific register-level programming interface
+ * @subclass_code: identifies more specifically the function of the device
+ * @baseclass_code: broadly classifies the type of function the device performs
+ * @cache_line_size: specifies the system cacheline size in units of DWORDs
+ * @subsys_vendor_id: vendor of the add-in card or subsystem
+ * @subsys_id: id specific to vendor
+ * @interrupt_pin: interrupt pin the device (or device function) uses
+ */
+struct pci_epf_header {
+       u16     vendorid;
+       u16     deviceid;
+       u8      revid;
+       u8      progif_code;
+       u8      subclass_code;
+       u8      baseclass_code;
+       u8      cache_line_size;
+       u16     subsys_vendor_id;
+       u16     subsys_id;
+       enum pci_interrupt_pin interrupt_pin;
+};
+
+/**
+ * struct pci_epf_ops - set of function pointers for performing EPF operations
+ * @bind: ops to perform when a EPC device has been bound to EPF device
+ * @unbind: ops to perform when a binding has been lost between a EPC device
+ *         and EPF device
+ * @linkup: ops to perform when the EPC device has established a connection with
+ *         a host system
+ */
+struct pci_epf_ops {
+       int     (*bind)(struct pci_epf *epf);
+       void    (*unbind)(struct pci_epf *epf);
+       void    (*linkup)(struct pci_epf *epf);
+};
+
+/**
+ * struct pci_epf_driver - represents the PCI EPF driver
+ * @probe: ops to perform when a new EPF device has been bound to the EPF driver
+ * @remove: ops to perform when the binding between the EPF device and EPF
+ *         driver is broken
+ * @driver: PCI EPF driver
+ * @ops: set of function pointers for performing EPF operations
+ * @owner: the owner of the module that registers the PCI EPF driver
+ * @group: configfs group corresponding to the PCI EPF driver
+ * @id_table: identifies EPF devices for probing
+ */
+struct pci_epf_driver {
+       int     (*probe)(struct pci_epf *epf);
+       int     (*remove)(struct pci_epf *epf);
+
+       struct device_driver    driver;
+       struct pci_epf_ops      *ops;
+       struct module           *owner;
+       struct config_group     *group;
+       const struct pci_epf_device_id  *id_table;
+};
+
+#define to_pci_epf_driver(drv) (container_of((drv), struct pci_epf_driver, \
+                               driver))
+
+/**
+ * struct pci_epf_bar - represents the BAR of EPF device
+ * @phys_addr: physical address that should be mapped to the BAR
+ * @size: the size of the address space present in BAR
+ */
+struct pci_epf_bar {
+       dma_addr_t      phys_addr;
+       size_t          size;
+};
+
+/**
+ * struct pci_epf - represents the PCI EPF device
+ * @dev: the PCI EPF device
+ * @name: the name of the PCI EPF device
+ * @header: represents standard configuration header
+ * @bar: represents the BAR of EPF device
+ * @msi_interrupts: number of MSI interrupts required by this function
+ * @func_no: unique function number within this endpoint device
+ * @epc: the EPC device to which this EPF device is bound
+ * @driver: the EPF driver to which this EPF device is bound
+ * @list: to add pci_epf as a list of PCI endpoint functions to pci_epc
+ */
+struct pci_epf {
+       struct device           dev;
+       const char              *name;
+       struct pci_epf_header   *header;
+       struct pci_epf_bar      bar[6];
+       u8                      msi_interrupts;
+       u8                      func_no;
+
+       struct pci_epc          *epc;
+       struct pci_epf_driver   *driver;
+       struct list_head        list;
+};
+
+#define to_pci_epf(epf_dev) container_of((epf_dev), struct pci_epf, dev)
+
+#define pci_epf_register_driver(driver)    \
+               __pci_epf_register_driver((driver), THIS_MODULE)
+
+static inline void epf_set_drvdata(struct pci_epf *epf, void *data)
+{
+       dev_set_drvdata(&epf->dev, data);
+}
+
+static inline void *epf_get_drvdata(struct pci_epf *epf)
+{
+       return dev_get_drvdata(&epf->dev);
+}
+
+struct pci_epf *pci_epf_create(const char *name);
+void pci_epf_destroy(struct pci_epf *epf);
+int __pci_epf_register_driver(struct pci_epf_driver *driver,
+                             struct module *owner);
+void pci_epf_unregister_driver(struct pci_epf_driver *driver);
+void *pci_epf_alloc_space(struct pci_epf *epf, size_t size, enum pci_barno bar);
+void pci_epf_free_space(struct pci_epf *epf, void *addr, enum pci_barno bar);
+int pci_epf_bind(struct pci_epf *epf);
+void pci_epf_unbind(struct pci_epf *epf);
+void pci_epf_linkup(struct pci_epf *epf);
+#endif /* __LINUX_PCI_EPF_H */
index f27be8432e82b3a76c1fa58e30321cd48a28b91c..33c2b0b77429d09aaa31cb9735458db5762e08a7 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/kobject.h>
 #include <linux/atomic.h>
 #include <linux/device.h>
+#include <linux/interrupt.h>
 #include <linux/io.h>
 #include <linux/resource_ext.h>
 #include <uapi/linux/pci.h>
@@ -178,6 +179,10 @@ enum pci_dev_flags {
        PCI_DEV_FLAGS_NO_PM_RESET = (__force pci_dev_flags_t) (1 << 7),
        /* Get VPD from function 0 VPD */
        PCI_DEV_FLAGS_VPD_REF_F0 = (__force pci_dev_flags_t) (1 << 8),
+       /* a non-root bridge where translation occurs, stop alias search here */
+       PCI_DEV_FLAGS_BRIDGE_XLATE_ROOT = (__force pci_dev_flags_t) (1 << 9),
+       /* Do not use FLR even if device advertises PCI_AF_CAP */
+       PCI_DEV_FLAGS_NO_FLR_RESET = (__force pci_dev_flags_t) (1 << 10),
 };
 
 enum pci_irq_reroute_variant {
@@ -397,6 +402,8 @@ struct pci_dev {
        phys_addr_t rom; /* Physical address of ROM if it's not from the BAR */
        size_t romlen; /* Length of ROM if it's not from the BAR */
        char *driver_override; /* Driver name to force a match */
+
+       unsigned long priv_flags; /* Private flags for the pci driver */
 };
 
 static inline struct pci_dev *pci_physfn(struct pci_dev *dev)
@@ -941,32 +948,12 @@ int pci_generic_config_write32(struct pci_bus *bus, unsigned int devfn,
 
 struct pci_ops *pci_bus_set_ops(struct pci_bus *bus, struct pci_ops *ops);
 
-static inline int pci_read_config_byte(const struct pci_dev *dev, int where, u8 *val)
-{
-       return pci_bus_read_config_byte(dev->bus, dev->devfn, where, val);
-}
-static inline int pci_read_config_word(const struct pci_dev *dev, int where, u16 *val)
-{
-       return pci_bus_read_config_word(dev->bus, dev->devfn, where, val);
-}
-static inline int pci_read_config_dword(const struct pci_dev *dev, int where,
-                                       u32 *val)
-{
-       return pci_bus_read_config_dword(dev->bus, dev->devfn, where, val);
-}
-static inline int pci_write_config_byte(const struct pci_dev *dev, int where, u8 val)
-{
-       return pci_bus_write_config_byte(dev->bus, dev->devfn, where, val);
-}
-static inline int pci_write_config_word(const struct pci_dev *dev, int where, u16 val)
-{
-       return pci_bus_write_config_word(dev->bus, dev->devfn, where, val);
-}
-static inline int pci_write_config_dword(const struct pci_dev *dev, int where,
-                                        u32 val)
-{
-       return pci_bus_write_config_dword(dev->bus, dev->devfn, where, val);
-}
+int pci_read_config_byte(const struct pci_dev *dev, int where, u8 *val);
+int pci_read_config_word(const struct pci_dev *dev, int where, u16 *val);
+int pci_read_config_dword(const struct pci_dev *dev, int where, u32 *val);
+int pci_write_config_byte(const struct pci_dev *dev, int where, u8 val);
+int pci_write_config_word(const struct pci_dev *dev, int where, u16 val);
+int pci_write_config_dword(const struct pci_dev *dev, int where, u32 val);
 
 int pcie_capability_read_word(struct pci_dev *dev, int pos, u16 *val);
 int pcie_capability_read_dword(struct pci_dev *dev, int pos, u32 *val);
@@ -1053,6 +1040,7 @@ int pcie_get_mps(struct pci_dev *dev);
 int pcie_set_mps(struct pci_dev *dev, int mps);
 int pcie_get_minimum_link(struct pci_dev *dev, enum pci_bus_speed *speed,
                          enum pcie_link_width *width);
+void pcie_flr(struct pci_dev *dev);
 int __pci_reset_function(struct pci_dev *dev);
 int __pci_reset_function_locked(struct pci_dev *dev);
 int pci_reset_function(struct pci_dev *dev);
@@ -1073,6 +1061,11 @@ int pci_select_bars(struct pci_dev *dev, unsigned long flags);
 bool pci_device_is_present(struct pci_dev *pdev);
 void pci_ignore_hotplug(struct pci_dev *dev);
 
+int __printf(6, 7) pci_request_irq(struct pci_dev *dev, unsigned int nr,
+               irq_handler_t handler, irq_handler_t thread_fn, void *dev_id,
+               const char *fmt, ...);
+void pci_free_irq(struct pci_dev *dev, unsigned int nr, void *dev_id);
+
 /* ROM control related routines */
 int pci_enable_rom(struct pci_dev *pdev);
 void pci_disable_rom(struct pci_dev *pdev);
@@ -1200,6 +1193,11 @@ unsigned long pci_address_to_pio(phys_addr_t addr);
 phys_addr_t pci_pio_to_address(unsigned long pio);
 int pci_remap_iospace(const struct resource *res, phys_addr_t phys_addr);
 void pci_unmap_iospace(struct resource *res);
+void __iomem *devm_pci_remap_cfgspace(struct device *dev,
+                                     resource_size_t offset,
+                                     resource_size_t size);
+void __iomem *devm_pci_remap_cfg_resource(struct device *dev,
+                                         struct resource *res);
 
 static inline pci_bus_addr_t pci_bus_address(struct pci_dev *pdev, int bar)
 {
@@ -1298,10 +1296,8 @@ struct msix_entry {
 
 #ifdef CONFIG_PCI_MSI
 int pci_msi_vec_count(struct pci_dev *dev);
-void pci_msi_shutdown(struct pci_dev *dev);
 void pci_disable_msi(struct pci_dev *dev);
 int pci_msix_vec_count(struct pci_dev *dev);
-void pci_msix_shutdown(struct pci_dev *dev);
 void pci_disable_msix(struct pci_dev *dev);
 void pci_restore_msi_state(struct pci_dev *dev);
 int pci_msi_enabled(void);
@@ -1327,10 +1323,8 @@ int pci_irq_get_node(struct pci_dev *pdev, int vec);
 
 #else
 static inline int pci_msi_vec_count(struct pci_dev *dev) { return -ENOSYS; }
-static inline void pci_msi_shutdown(struct pci_dev *dev) { }
 static inline void pci_disable_msi(struct pci_dev *dev) { }
 static inline int pci_msix_vec_count(struct pci_dev *dev) { return -ENOSYS; }
-static inline void pci_msix_shutdown(struct pci_dev *dev) { }
 static inline void pci_disable_msix(struct pci_dev *dev) { }
 static inline void pci_restore_msi_state(struct pci_dev *dev) { }
 static inline int pci_msi_enabled(void) { return 0; }
@@ -1623,6 +1617,36 @@ static inline int pci_get_new_domain_nr(void) { return -ENOSYS; }
 
 #include <asm/pci.h>
 
+/* These two functions provide almost identical functionality. Depennding
+ * on the architecture, one will be implemented as a wrapper around the
+ * other (in drivers/pci/mmap.c).
+ *
+ * pci_mmap_resource_range() maps a specific BAR, and vm->vm_pgoff
+ * is expected to be an offset within that region.
+ *
+ * pci_mmap_page_range() is the legacy architecture-specific interface,
+ * which accepts a "user visible" resource address converted by
+ * pci_resource_to_user(), as used in the legacy mmap() interface in
+ * /proc/bus/pci/.
+ */
+int pci_mmap_resource_range(struct pci_dev *dev, int bar,
+                           struct vm_area_struct *vma,
+                           enum pci_mmap_state mmap_state, int write_combine);
+int pci_mmap_page_range(struct pci_dev *pdev, int bar,
+                       struct vm_area_struct *vma,
+                       enum pci_mmap_state mmap_state, int write_combine);
+
+#ifndef arch_can_pci_mmap_wc
+#define arch_can_pci_mmap_wc()         0
+#endif
+
+#ifndef arch_can_pci_mmap_io
+#define arch_can_pci_mmap_io()         0
+#define pci_iobar_pfn(pdev, bar, vma) (-EINVAL)
+#else
+int pci_iobar_pfn(struct pci_dev *pdev, int bar, struct vm_area_struct *vma);
+#endif
+
 #ifndef pci_root_bus_fwnode
 #define pci_root_bus_fwnode(bus)       NULL
 #endif
index a4f77feecbb00f84fac0295a2b2745928e9e0472..5f6b71d15393a4d6df153589cee33e42d42ebb26 100644 (file)
 #define PCI_DEVICE_ID_TI_X620          0xac8d
 #define PCI_DEVICE_ID_TI_X420          0xac8e
 #define PCI_DEVICE_ID_TI_XX20_FM       0xac8f
+#define PCI_DEVICE_ID_TI_DRA74x                0xb500
+#define PCI_DEVICE_ID_TI_DRA72x                0xb501
 
 #define PCI_VENDOR_ID_SONY             0x104d
 
index 0496d171700a767b13b89e8e73c50b043fcf6c64..e8b12dbf617024f488f078f746e87ce32eec839a 100644 (file)
 
 #include <linux/platform_device.h>
 
-#define MMU_REG_SIZE           256
-
-/**
- * struct iommu_arch_data - omap iommu private data
- * @name: name of the iommu device
- * @iommu_dev: handle of the iommu device
- *
- * This is an omap iommu private data object, which binds an iommu user
- * to its iommu device. This object should be placed at the iommu user's
- * dev_archdata so generic IOMMU API can be used without having to
- * utilize omap-specific plumbing anymore.
- */
-struct omap_iommu_arch_data {
-       const char *name;
-       struct omap_iommu *iommu_dev;
-};
-
 struct iommu_platform_data {
-       const char *name;
        const char *reset_name;
-       int nr_tlb_entries;
-
        int (*assert_reset)(struct platform_device *pdev, const char *name);
        int (*deassert_reset)(struct platform_device *pdev, const char *name);
 };
index a5c0a71ec9147692f6a4dc995b71375f977bb71c..cf9348b376ac50f99944c5bc0762afb3e0b65daf 100644 (file)
@@ -50,6 +50,7 @@
 struct imx_fb_videomode {
        struct fb_videomode mode;
        u32 pcr;
+       bool aus_mode;
        unsigned char   bpp;
 };
 
index 9b6abe6325875ce91a353d64fa2f53a52a77f583..b7803a251044a0eb89142b7a32452bef61f2594b 100644 (file)
@@ -118,6 +118,7 @@ struct generic_pm_domain_data {
        struct pm_domain_data base;
        struct gpd_timing_data td;
        struct notifier_block nb;
+       void *data;
 };
 
 #ifdef CONFIG_PM_GENERIC_DOMAINS
index a3447932df1ff0a00f417c847052a83a407f4631..4c2cba7ec1d44edec6881ed7ac1e80ee27312c44 100644 (file)
@@ -106,8 +106,8 @@ extern void __pm_stay_awake(struct wakeup_source *ws);
 extern void pm_stay_awake(struct device *dev);
 extern void __pm_relax(struct wakeup_source *ws);
 extern void pm_relax(struct device *dev);
-extern void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec);
-extern void pm_wakeup_event(struct device *dev, unsigned int msec);
+extern void pm_wakeup_ws_event(struct wakeup_source *ws, unsigned int msec, bool hard);
+extern void pm_wakeup_dev_event(struct device *dev, unsigned int msec, bool hard);
 
 #else /* !CONFIG_PM_SLEEP */
 
@@ -182,9 +182,11 @@ static inline void __pm_relax(struct wakeup_source *ws) {}
 
 static inline void pm_relax(struct device *dev) {}
 
-static inline void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec) {}
+static inline void pm_wakeup_ws_event(struct wakeup_source *ws,
+                                     unsigned int msec, bool hard) {}
 
-static inline void pm_wakeup_event(struct device *dev, unsigned int msec) {}
+static inline void pm_wakeup_dev_event(struct device *dev, unsigned int msec,
+                                      bool hard) {}
 
 #endif /* !CONFIG_PM_SLEEP */
 
@@ -201,4 +203,19 @@ static inline void wakeup_source_trash(struct wakeup_source *ws)
        wakeup_source_drop(ws);
 }
 
+static inline void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec)
+{
+       return pm_wakeup_ws_event(ws, msec, false);
+}
+
+static inline void pm_wakeup_event(struct device *dev, unsigned int msec)
+{
+       return pm_wakeup_dev_event(dev, msec, false);
+}
+
+static inline void pm_wakeup_hard_event(struct device *dev)
+{
+       return pm_wakeup_dev_event(dev, 0, true);
+}
+
 #endif /* _LINUX_PM_WAKEUP_H */
index 522757ac9cd4d9975a5fe8bbbf144efb54551cd4..a7ed29baf44a6ce6c4ee01ba381655884090d6f2 100644 (file)
 #define __MAX17042_BATTERY_H_
 
 #define MAX17042_STATUS_BattAbsent     (1 << 3)
-#define MAX17042_BATTERY_FULL  (100)
+#define MAX17042_BATTERY_FULL          (95)   /* Recommend. FullSOCThr value */
 #define MAX17042_DEFAULT_SNS_RESISTOR  (10000)
+#define MAX17042_DEFAULT_VMIN          (3000)
+#define MAX17042_DEFAULT_VMAX          (4500) /* LiHV cell max */
+#define MAX17042_DEFAULT_TEMP_MIN      (0)    /* For sys without temp sensor */
+#define MAX17042_DEFAULT_TEMP_MAX      (700)  /* 70 degrees Celcius */
+
+/* Consider RepCap which is less then 10 units below FullCAP full */
+#define MAX17042_FULL_THRESHOLD                10
 
 #define MAX17042_CHARACTERIZATION_DATA_SIZE 48
 
index 571257e0f53dc669c4f59df19923bd50dfd31a59..e10f274683222358f892096c3bda5fbf7e896015 100644 (file)
@@ -198,7 +198,7 @@ extern void wake_up_klogd(void);
 
 char *log_buf_addr_get(void);
 u32 log_buf_len_get(void);
-void log_buf_kexec_setup(void);
+void log_buf_vmcoreinfo_setup(void);
 void __init setup_log_buf(int early);
 __printf(1, 2) void dump_stack_set_arch_desc(const char *fmt, ...);
 void dump_stack_print_info(const char *log_lvl);
@@ -246,7 +246,7 @@ static inline u32 log_buf_len_get(void)
        return 0;
 }
 
-static inline void log_buf_kexec_setup(void)
+static inline void log_buf_vmcoreinfo_setup(void)
 {
 }
 
index 12cb8bd81d2d12b734c83059fb0b0759ee0c92c3..58ab28d81fc2ecd4f78f37a81ac07a56d984f2e5 100644 (file)
@@ -14,6 +14,7 @@ struct inode;
 
 struct proc_ns_operations {
        const char *name;
+       const char *real_ns_name;
        int type;
        struct ns_common *(*get)(struct task_struct *task);
        void (*put)(struct ns_common *ns);
@@ -26,6 +27,7 @@ extern const struct proc_ns_operations netns_operations;
 extern const struct proc_ns_operations utsns_operations;
 extern const struct proc_ns_operations ipcns_operations;
 extern const struct proc_ns_operations pidns_operations;
+extern const struct proc_ns_operations pidns_for_children_operations;
 extern const struct proc_ns_operations userns_operations;
 extern const struct proc_ns_operations mntns_operations;
 extern const struct proc_ns_operations cgroupns_operations;
index 6c70444da3b9d3e5c31f04193b96986ff0e4b04b..6b2e0dd88569b13c66ef445609b2f12419fdd3ac 100644 (file)
 struct ptr_ring {
        int producer ____cacheline_aligned_in_smp;
        spinlock_t producer_lock;
-       int consumer ____cacheline_aligned_in_smp;
+       int consumer_head ____cacheline_aligned_in_smp; /* next valid entry */
+       int consumer_tail; /* next entry to invalidate */
        spinlock_t consumer_lock;
        /* Shared consumer/producer data */
        /* Read-only by both the producer and the consumer */
        int size ____cacheline_aligned_in_smp; /* max entries in queue */
+       int batch; /* number of entries to consume in a batch */
        void **queue;
 };
 
@@ -170,7 +172,7 @@ static inline int ptr_ring_produce_bh(struct ptr_ring *r, void *ptr)
 static inline void *__ptr_ring_peek(struct ptr_ring *r)
 {
        if (likely(r->size))
-               return r->queue[r->consumer];
+               return r->queue[r->consumer_head];
        return NULL;
 }
 
@@ -231,9 +233,38 @@ static inline bool ptr_ring_empty_bh(struct ptr_ring *r)
 /* Must only be called after __ptr_ring_peek returned !NULL */
 static inline void __ptr_ring_discard_one(struct ptr_ring *r)
 {
-       r->queue[r->consumer++] = NULL;
-       if (unlikely(r->consumer >= r->size))
-               r->consumer = 0;
+       /* Fundamentally, what we want to do is update consumer
+        * index and zero out the entry so producer can reuse it.
+        * Doing it naively at each consume would be as simple as:
+        *       r->queue[r->consumer++] = NULL;
+        *       if (unlikely(r->consumer >= r->size))
+        *               r->consumer = 0;
+        * but that is suboptimal when the ring is full as producer is writing
+        * out new entries in the same cache line.  Defer these updates until a
+        * batch of entries has been consumed.
+        */
+       int head = r->consumer_head++;
+
+       /* Once we have processed enough entries invalidate them in
+        * the ring all at once so producer can reuse their space in the ring.
+        * We also do this when we reach end of the ring - not mandatory
+        * but helps keep the implementation simple.
+        */
+       if (unlikely(r->consumer_head - r->consumer_tail >= r->batch ||
+                    r->consumer_head >= r->size)) {
+               /* Zero out entries in the reverse order: this way we touch the
+                * cache line that producer might currently be reading the last;
+                * producer won't make progress and touch other cache lines
+                * besides the first one until we write out all entries.
+                */
+               while (likely(head >= r->consumer_tail))
+                       r->queue[head--] = NULL;
+               r->consumer_tail = r->consumer_head;
+       }
+       if (unlikely(r->consumer_head >= r->size)) {
+               r->consumer_head = 0;
+               r->consumer_tail = 0;
+       }
 }
 
 static inline void *__ptr_ring_consume(struct ptr_ring *r)
@@ -345,14 +376,27 @@ static inline void **__ptr_ring_init_queue_alloc(int size, gfp_t gfp)
        return kzalloc(ALIGN(size * sizeof(void *), SMP_CACHE_BYTES), gfp);
 }
 
+static inline void __ptr_ring_set_size(struct ptr_ring *r, int size)
+{
+       r->size = size;
+       r->batch = SMP_CACHE_BYTES * 2 / sizeof(*(r->queue));
+       /* We need to set batch at least to 1 to make logic
+        * in __ptr_ring_discard_one work correctly.
+        * Batching too much (because ring is small) would cause a lot of
+        * burstiness. Needs tuning, for now disable batching.
+        */
+       if (r->batch > r->size / 2 || !r->batch)
+               r->batch = 1;
+}
+
 static inline int ptr_ring_init(struct ptr_ring *r, int size, gfp_t gfp)
 {
        r->queue = __ptr_ring_init_queue_alloc(size, gfp);
        if (!r->queue)
                return -ENOMEM;
 
-       r->size = size;
-       r->producer = r->consumer = 0;
+       __ptr_ring_set_size(r, size);
+       r->producer = r->consumer_head = r->consumer_tail = 0;
        spin_lock_init(&r->producer_lock);
        spin_lock_init(&r->consumer_lock);
 
@@ -373,9 +417,10 @@ static inline void **__ptr_ring_swap_queue(struct ptr_ring *r, void **queue,
                else if (destroy)
                        destroy(ptr);
 
-       r->size = size;
+       __ptr_ring_set_size(r, size);
        r->producer = producer;
-       r->consumer = 0;
+       r->consumer_head = 0;
+       r->consumer_tail = 0;
        old = r->queue;
        r->queue = queue;
 
index d32f6f1a5225f38de2ff8456a09b236028eb1de5..e5380471c2cd2a42edb8d0bbeb231d8b7320ddf0 100644 (file)
@@ -40,6 +40,9 @@ extern int qcom_scm_pas_shutdown(u32 peripheral);
 extern void qcom_scm_cpu_power_down(u32 flags);
 extern u32 qcom_scm_get_version(void);
 extern int qcom_scm_set_remote_state(u32 state, u32 id);
+extern int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare);
+extern int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size);
+extern int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare);
 #else
 static inline
 int qcom_scm_set_cold_boot_addr(void *entry, const cpumask_t *cpus)
@@ -67,5 +70,8 @@ static inline void qcom_scm_cpu_power_down(u32 flags) {}
 static inline u32 qcom_scm_get_version(void) { return 0; }
 static inline u32
 qcom_scm_set_remote_state(u32 state,u32 id) { return -ENODEV; }
+static inline int qcom_scm_restore_sec_cfg(u32 device_id, u32 spare) { return -ENODEV; }
+static inline int qcom_scm_iommu_secure_ptbl_size(u32 spare, size_t *size) { return -ENODEV; }
+static inline int qcom_scm_iommu_secure_ptbl_init(u64 addr, u32 size, u32 spare) { return -ENODEV; }
 #endif
 #endif
diff --git a/include/linux/rcu_node_tree.h b/include/linux/rcu_node_tree.h
new file mode 100644 (file)
index 0000000..4b766b6
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * RCU node combining tree definitions.  These are used to compute
+ * global attributes while avoiding common-case global contention.  A key
+ * property that these computations rely on is a tournament-style approach
+ * where only one of the tasks contending a lower level in the tree need
+ * advance to the next higher level.  If properly configured, this allows
+ * unlimited scalability while maintaining a constant level of contention
+ * on the root node.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you can access it online at
+ * http://www.gnu.org/licenses/gpl-2.0.html.
+ *
+ * Copyright IBM Corporation, 2017
+ *
+ * Author: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+ */
+
+#ifndef __LINUX_RCU_NODE_TREE_H
+#define __LINUX_RCU_NODE_TREE_H
+
+/*
+ * Define shape of hierarchy based on NR_CPUS, CONFIG_RCU_FANOUT, and
+ * CONFIG_RCU_FANOUT_LEAF.
+ * In theory, it should be possible to add more levels straightforwardly.
+ * In practice, this did work well going from three levels to four.
+ * Of course, your mileage may vary.
+ */
+
+#ifdef CONFIG_RCU_FANOUT
+#define RCU_FANOUT CONFIG_RCU_FANOUT
+#else /* #ifdef CONFIG_RCU_FANOUT */
+# ifdef CONFIG_64BIT
+# define RCU_FANOUT 64
+# else
+# define RCU_FANOUT 32
+# endif
+#endif /* #else #ifdef CONFIG_RCU_FANOUT */
+
+#ifdef CONFIG_RCU_FANOUT_LEAF
+#define RCU_FANOUT_LEAF CONFIG_RCU_FANOUT_LEAF
+#else /* #ifdef CONFIG_RCU_FANOUT_LEAF */
+#define RCU_FANOUT_LEAF 16
+#endif /* #else #ifdef CONFIG_RCU_FANOUT_LEAF */
+
+#define RCU_FANOUT_1         (RCU_FANOUT_LEAF)
+#define RCU_FANOUT_2         (RCU_FANOUT_1 * RCU_FANOUT)
+#define RCU_FANOUT_3         (RCU_FANOUT_2 * RCU_FANOUT)
+#define RCU_FANOUT_4         (RCU_FANOUT_3 * RCU_FANOUT)
+
+#if NR_CPUS <= RCU_FANOUT_1
+#  define RCU_NUM_LVLS       1
+#  define NUM_RCU_LVL_0              1
+#  define NUM_RCU_NODES              NUM_RCU_LVL_0
+#  define NUM_RCU_LVL_INIT    { NUM_RCU_LVL_0 }
+#  define RCU_NODE_NAME_INIT  { "rcu_node_0" }
+#  define RCU_FQS_NAME_INIT   { "rcu_node_fqs_0" }
+#elif NR_CPUS <= RCU_FANOUT_2
+#  define RCU_NUM_LVLS       2
+#  define NUM_RCU_LVL_0              1
+#  define NUM_RCU_LVL_1              DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_1)
+#  define NUM_RCU_NODES              (NUM_RCU_LVL_0 + NUM_RCU_LVL_1)
+#  define NUM_RCU_LVL_INIT    { NUM_RCU_LVL_0, NUM_RCU_LVL_1 }
+#  define RCU_NODE_NAME_INIT  { "rcu_node_0", "rcu_node_1" }
+#  define RCU_FQS_NAME_INIT   { "rcu_node_fqs_0", "rcu_node_fqs_1" }
+#elif NR_CPUS <= RCU_FANOUT_3
+#  define RCU_NUM_LVLS       3
+#  define NUM_RCU_LVL_0              1
+#  define NUM_RCU_LVL_1              DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_2)
+#  define NUM_RCU_LVL_2              DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_1)
+#  define NUM_RCU_NODES              (NUM_RCU_LVL_0 + NUM_RCU_LVL_1 + NUM_RCU_LVL_2)
+#  define NUM_RCU_LVL_INIT    { NUM_RCU_LVL_0, NUM_RCU_LVL_1, NUM_RCU_LVL_2 }
+#  define RCU_NODE_NAME_INIT  { "rcu_node_0", "rcu_node_1", "rcu_node_2" }
+#  define RCU_FQS_NAME_INIT   { "rcu_node_fqs_0", "rcu_node_fqs_1", "rcu_node_fqs_2" }
+#elif NR_CPUS <= RCU_FANOUT_4
+#  define RCU_NUM_LVLS       4
+#  define NUM_RCU_LVL_0              1
+#  define NUM_RCU_LVL_1              DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_3)
+#  define NUM_RCU_LVL_2              DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_2)
+#  define NUM_RCU_LVL_3              DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_1)
+#  define NUM_RCU_NODES              (NUM_RCU_LVL_0 + NUM_RCU_LVL_1 + NUM_RCU_LVL_2 + NUM_RCU_LVL_3)
+#  define NUM_RCU_LVL_INIT    { NUM_RCU_LVL_0, NUM_RCU_LVL_1, NUM_RCU_LVL_2, NUM_RCU_LVL_3 }
+#  define RCU_NODE_NAME_INIT  { "rcu_node_0", "rcu_node_1", "rcu_node_2", "rcu_node_3" }
+#  define RCU_FQS_NAME_INIT   { "rcu_node_fqs_0", "rcu_node_fqs_1", "rcu_node_fqs_2", "rcu_node_fqs_3" }
+#else
+# error "CONFIG_RCU_FANOUT insufficient for NR_CPUS"
+#endif /* #if (NR_CPUS) <= RCU_FANOUT_1 */
+
+#endif /* __LINUX_RCU_NODE_TREE_H */
diff --git a/include/linux/rcu_segcblist.h b/include/linux/rcu_segcblist.h
new file mode 100644 (file)
index 0000000..ba4d262
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * RCU segmented callback lists
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you can access it online at
+ * http://www.gnu.org/licenses/gpl-2.0.html.
+ *
+ * Copyright IBM Corporation, 2017
+ *
+ * Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+ */
+
+#ifndef __INCLUDE_LINUX_RCU_SEGCBLIST_H
+#define __INCLUDE_LINUX_RCU_SEGCBLIST_H
+
+/* Simple unsegmented callback lists. */
+struct rcu_cblist {
+       struct rcu_head *head;
+       struct rcu_head **tail;
+       long len;
+       long len_lazy;
+};
+
+#define RCU_CBLIST_INITIALIZER(n) { .head = NULL, .tail = &n.head }
+
+/* Complicated segmented callback lists.  ;-) */
+
+/*
+ * Index values for segments in rcu_segcblist structure.
+ *
+ * The segments are as follows:
+ *
+ * [head, *tails[RCU_DONE_TAIL]):
+ *     Callbacks whose grace period has elapsed, and thus can be invoked.
+ * [*tails[RCU_DONE_TAIL], *tails[RCU_WAIT_TAIL]):
+ *     Callbacks waiting for the current GP from the current CPU's viewpoint.
+ * [*tails[RCU_WAIT_TAIL], *tails[RCU_NEXT_READY_TAIL]):
+ *     Callbacks that arrived before the next GP started, again from
+ *     the current CPU's viewpoint.  These can be handled by the next GP.
+ * [*tails[RCU_NEXT_READY_TAIL], *tails[RCU_NEXT_TAIL]):
+ *     Callbacks that might have arrived after the next GP started.
+ *     There is some uncertainty as to when a given GP starts and
+ *     ends, but a CPU knows the exact times if it is the one starting
+ *     or ending the GP.  Other CPUs know that the previous GP ends
+ *     before the next one starts.
+ *
+ * Note that RCU_WAIT_TAIL cannot be empty unless RCU_NEXT_READY_TAIL is also
+ * empty.
+ *
+ * The ->gp_seq[] array contains the grace-period number at which the
+ * corresponding segment of callbacks will be ready to invoke.  A given
+ * element of this array is meaningful only when the corresponding segment
+ * is non-empty, and it is never valid for RCU_DONE_TAIL (whose callbacks
+ * are already ready to invoke) or for RCU_NEXT_TAIL (whose callbacks have
+ * not yet been assigned a grace-period number).
+ */
+#define RCU_DONE_TAIL          0       /* Also RCU_WAIT head. */
+#define RCU_WAIT_TAIL          1       /* Also RCU_NEXT_READY head. */
+#define RCU_NEXT_READY_TAIL    2       /* Also RCU_NEXT head. */
+#define RCU_NEXT_TAIL          3
+#define RCU_CBLIST_NSEGS       4
+
+struct rcu_segcblist {
+       struct rcu_head *head;
+       struct rcu_head **tails[RCU_CBLIST_NSEGS];
+       unsigned long gp_seq[RCU_CBLIST_NSEGS];
+       long len;
+       long len_lazy;
+};
+
+#define RCU_SEGCBLIST_INITIALIZER(n) \
+{ \
+       .head = NULL, \
+       .tails[RCU_DONE_TAIL] = &n.head, \
+       .tails[RCU_WAIT_TAIL] = &n.head, \
+       .tails[RCU_NEXT_READY_TAIL] = &n.head, \
+       .tails[RCU_NEXT_TAIL] = &n.head, \
+}
+
+#endif /* __INCLUDE_LINUX_RCU_SEGCBLIST_H */
index 4f7a9561b8c415d069505dab632b922903d87d2e..b1fd8bf85fdc430eaaa2195cd6dc18417bb64585 100644 (file)
@@ -509,7 +509,8 @@ static inline void hlist_add_tail_rcu(struct hlist_node *n,
 {
        struct hlist_node *i, *last = NULL;
 
-       for (i = hlist_first_rcu(h); i; i = hlist_next_rcu(i))
+       /* Note: write side code, so rcu accessors are not needed. */
+       for (i = h->first; i; i = i->next)
                last = i;
 
        if (last) {
index dea8f17b2fe3af3452faa2f068bfb62db4108b95..e1e5d002fdb93a537110b68886656caf6c049fc4 100644 (file)
@@ -368,15 +368,20 @@ static inline void rcu_init_nohz(void)
 #ifdef CONFIG_TASKS_RCU
 #define TASKS_RCU(x) x
 extern struct srcu_struct tasks_rcu_exit_srcu;
-#define rcu_note_voluntary_context_switch(t) \
+#define rcu_note_voluntary_context_switch_lite(t) \
        do { \
-               rcu_all_qs(); \
                if (READ_ONCE((t)->rcu_tasks_holdout)) \
                        WRITE_ONCE((t)->rcu_tasks_holdout, false); \
        } while (0)
+#define rcu_note_voluntary_context_switch(t) \
+       do { \
+               rcu_all_qs(); \
+               rcu_note_voluntary_context_switch_lite(t); \
+       } while (0)
 #else /* #ifdef CONFIG_TASKS_RCU */
 #define TASKS_RCU(x) do { } while (0)
-#define rcu_note_voluntary_context_switch(t)   rcu_all_qs()
+#define rcu_note_voluntary_context_switch_lite(t)      do { } while (0)
+#define rcu_note_voluntary_context_switch(t)           rcu_all_qs()
 #endif /* #else #ifdef CONFIG_TASKS_RCU */
 
 /**
@@ -1132,11 +1137,11 @@ do { \
  * if the UNLOCK and LOCK are executed by the same CPU or if the
  * UNLOCK and LOCK operate on the same lock variable.
  */
-#ifdef CONFIG_PPC
+#ifdef CONFIG_ARCH_WEAK_RELEASE_ACQUIRE
 #define smp_mb__after_unlock_lock()    smp_mb()  /* Full ordering for lock. */
-#else /* #ifdef CONFIG_PPC */
+#else /* #ifdef CONFIG_ARCH_WEAK_RELEASE_ACQUIRE */
 #define smp_mb__after_unlock_lock()    do { } while (0)
-#endif /* #else #ifdef CONFIG_PPC */
+#endif /* #else #ifdef CONFIG_ARCH_WEAK_RELEASE_ACQUIRE */
 
 
 #endif /* __LINUX_RCUPDATE_H */
index b452953e21c8ae0b311a29d2af46a2a4d3036ce7..74d9c3a1feeec494b693501c6ec976c9dd487186 100644 (file)
@@ -33,6 +33,11 @@ static inline int rcu_dynticks_snap(struct rcu_dynticks *rdtp)
        return 0;
 }
 
+static inline bool rcu_eqs_special_set(int cpu)
+{
+       return false;  /* Never flag non-existent other CPUs! */
+}
+
 static inline unsigned long get_state_synchronize_rcu(void)
 {
        return 0;
@@ -87,10 +92,11 @@ static inline void kfree_call_rcu(struct rcu_head *head,
        call_rcu(head, func);
 }
 
-static inline void rcu_note_context_switch(void)
-{
-       rcu_sched_qs();
-}
+#define rcu_note_context_switch(preempt) \
+       do { \
+               rcu_sched_qs(); \
+               rcu_note_voluntary_context_switch_lite(current); \
+       } while (0)
 
 /*
  * Take advantage of the fact that there is only one CPU, which
@@ -212,14 +218,14 @@ static inline void exit_rcu(void)
 {
 }
 
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
+#if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_SRCU)
 extern int rcu_scheduler_active __read_mostly;
 void rcu_scheduler_starting(void);
-#else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
+#else /* #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_SRCU) */
 static inline void rcu_scheduler_starting(void)
 {
 }
-#endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */
+#endif /* #else #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_SRCU) */
 
 #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE)
 
@@ -237,6 +243,10 @@ static inline bool rcu_is_watching(void)
 
 #endif /* #else defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_RCU_TRACE) */
 
+static inline void rcu_request_urgent_qs_task(struct task_struct *t)
+{
+}
+
 static inline void rcu_all_qs(void)
 {
        barrier(); /* Avoid RCU read-side critical sections leaking across. */
index 63a4e4cf40a54315705cec804c8f065bdcf2cdbb..0bacb6b2af6973681b3724a9e4d4311daf730c30 100644 (file)
@@ -30,7 +30,7 @@
 #ifndef __LINUX_RCUTREE_H
 #define __LINUX_RCUTREE_H
 
-void rcu_note_context_switch(void);
+void rcu_note_context_switch(bool preempt);
 int rcu_needs_cpu(u64 basem, u64 *nextevt);
 void rcu_cpu_stall_reset(void);
 
@@ -41,7 +41,7 @@ void rcu_cpu_stall_reset(void);
  */
 static inline void rcu_virt_note_context_switch(int cpu)
 {
-       rcu_note_context_switch();
+       rcu_note_context_switch(false);
 }
 
 void synchronize_rcu_bh(void);
@@ -108,6 +108,7 @@ void rcu_scheduler_starting(void);
 extern int rcu_scheduler_active __read_mostly;
 
 bool rcu_is_watching(void);
+void rcu_request_urgent_qs_task(struct task_struct *t);
 
 void rcu_all_qs(void);
 
index 9daabe138c9905fea8d596281afabdd3a206fa78..2b24a6974847664165bb323aa00c8fae6f3506b0 100644 (file)
@@ -191,4 +191,16 @@ static inline void memalloc_nofs_restore(unsigned int flags)
        current->flags = (current->flags & ~PF_MEMALLOC_NOFS) | flags;
 }
 
+static inline unsigned int memalloc_noreclaim_save(void)
+{
+       unsigned int flags = current->flags & PF_MEMALLOC;
+       current->flags |= PF_MEMALLOC;
+       return flags;
+}
+
+static inline void memalloc_noreclaim_restore(unsigned int flags)
+{
+       current->flags = (current->flags & ~PF_MEMALLOC) | flags;
+}
+
 #endif /* _LINUX_SCHED_MM_H */
index 4fc222f8755d82113deba19eea85e8c47a844818..9edec926e9d968a3900ec0f683b039a6cf6f6ef7 100644 (file)
@@ -10,8 +10,7 @@ struct task_struct;
 
 /* One sem_array data structure for each set of semaphores in the system. */
 struct sem_array {
-       struct kern_ipc_perm    ____cacheline_aligned_in_smp
-                               sem_perm;       /* permissions .. see ipc.h */
+       struct kern_ipc_perm    sem_perm;       /* permissions .. see ipc.h */
        time_t                  sem_ctime;      /* last change time */
        struct sem              *sem_base;      /* ptr to first semaphore in array */
        struct list_head        pending_alter;  /* pending operations */
index 37395b8eb8f1e39fb8166c6d215d6abe8e056690..cda76c6506ca411c42c5e1cdf6d287263d97dde6 100644 (file)
@@ -41,12 +41,16 @@ struct serdev_device_ops {
  * @nr:                Device number on serdev bus.
  * @ctrl:      serdev controller managing this device.
  * @ops:       Device operations.
+ * @write_comp Completion used by serdev_device_write() internally
+ * @write_lock Lock to serialize access when writing data
  */
 struct serdev_device {
        struct device dev;
        int nr;
        struct serdev_controller *ctrl;
        const struct serdev_device_ops *ops;
+       struct completion write_comp;
+       struct mutex write_lock;
 };
 
 static inline struct serdev_device *to_serdev_device(struct device *d)
@@ -170,7 +174,7 @@ static inline void serdev_controller_write_wakeup(struct serdev_controller *ctrl
        if (!serdev || !serdev->ops->write_wakeup)
                return;
 
-       serdev->ops->write_wakeup(ctrl->serdev);
+       serdev->ops->write_wakeup(serdev);
 }
 
 static inline int serdev_controller_receive_buf(struct serdev_controller *ctrl,
@@ -182,7 +186,7 @@ static inline int serdev_controller_receive_buf(struct serdev_controller *ctrl,
        if (!serdev || !serdev->ops->receive_buf)
                return -EINVAL;
 
-       return serdev->ops->receive_buf(ctrl->serdev, data, count);
+       return serdev->ops->receive_buf(serdev, data, count);
 }
 
 #if IS_ENABLED(CONFIG_SERIAL_DEV_BUS)
@@ -194,7 +198,8 @@ void serdev_device_set_flow_control(struct serdev_device *, bool);
 void serdev_device_wait_until_sent(struct serdev_device *, long);
 int serdev_device_get_tiocm(struct serdev_device *);
 int serdev_device_set_tiocm(struct serdev_device *, int, int);
-int serdev_device_write_buf(struct serdev_device *, const unsigned char *, size_t);
+void serdev_device_write_wakeup(struct serdev_device *);
+int serdev_device_write(struct serdev_device *, const unsigned char *, size_t, unsigned long);
 void serdev_device_write_flush(struct serdev_device *);
 int serdev_device_write_room(struct serdev_device *);
 
@@ -240,7 +245,8 @@ static inline int serdev_device_set_tiocm(struct serdev_device *serdev, int set,
 {
        return -ENOTSUPP;
 }
-static inline int serdev_device_write_buf(struct serdev_device *sdev, const unsigned char *buf, size_t count)
+static inline int serdev_device_write(struct serdev_device *sdev, const unsigned char *buf,
+                                     size_t count, unsigned long timeout)
 {
        return -ENODEV;
 }
@@ -306,4 +312,11 @@ static inline struct device *serdev_tty_port_register(struct tty_port *port,
 static inline void serdev_tty_port_unregister(struct tty_port *port) {}
 #endif /* CONFIG_SERIAL_DEV_CTRL_TTYPORT */
 
+static inline int serdev_device_write_buf(struct serdev_device *serdev,
+                                         const unsigned char *data,
+                                         size_t count)
+{
+       return serdev_device_write(serdev, data, count, 0);
+}
+
 #endif /*_LINUX_SERDEV_H */
index 58484fb35cc869b63fe0a1dec5fa39f1b9eace84..64d892f1e5cd833bd30003e6f64c99da3a73f5f7 100644 (file)
@@ -247,6 +247,7 @@ struct uart_port {
        unsigned char           suspended;
        unsigned char           irq_wake;
        unsigned char           unused[2];
+       const char              *name;                  /* port name */
        struct attribute_group  *attr_group;            /* port specific attributes */
        const struct attribute_group **tty_groups;      /* all attributes (serial core use only) */
        struct serial_rs485     rs485;
index 3c37a8c5192159c88c892779ffa71c17d23b7736..04a7f7993e678d6454b6efaa608db3b88ea78eec 100644 (file)
@@ -28,7 +28,7 @@
 #define SLAB_STORE_USER                0x00010000UL    /* DEBUG: Store the last owner for bug hunting */
 #define SLAB_PANIC             0x00040000UL    /* Panic if kmem_cache_create() fails */
 /*
- * SLAB_DESTROY_BY_RCU - **WARNING** READ THIS!
+ * SLAB_TYPESAFE_BY_RCU - **WARNING** READ THIS!
  *
  * This delays freeing the SLAB page by a grace period, it does _NOT_
  * delay object freeing. This means that if you do kmem_cache_free()
  *
  * rcu_read_lock before reading the address, then rcu_read_unlock after
  * taking the spinlock within the structure expected at that address.
+ *
+ * Note that SLAB_TYPESAFE_BY_RCU was originally named SLAB_DESTROY_BY_RCU.
  */
-#define SLAB_DESTROY_BY_RCU    0x00080000UL    /* Defer freeing slabs to RCU */
+#define SLAB_TYPESAFE_BY_RCU   0x00080000UL    /* Defer freeing slabs to RCU */
 #define SLAB_MEM_SPREAD                0x00100000UL    /* Spread some memory over cpuset */
 #define SLAB_TRACE             0x00200000UL    /* Trace allocations and frees */
 
index a18e0783946b66eccba6a5b5faf77f2662d0a51a..787e7ad53d45f61cb045c047c610996de1141a7a 100644 (file)
@@ -1,6 +1,11 @@
 #ifndef __LINUX_SOC_RENESAS_RCAR_RST_H__
 #define __LINUX_SOC_RENESAS_RCAR_RST_H__
 
+#if defined(CONFIG_ARCH_RCAR_GEN1) || defined(CONFIG_ARCH_RCAR_GEN2) || \
+    defined(CONFIG_ARCH_R8A7795) || defined(CONFIG_ARCH_R8A7796)
 int rcar_rst_read_mode_pins(u32 *mode);
+#else
+static inline int rcar_rst_read_mode_pins(u32 *mode) { return -ENODEV; }
+#endif
 
 #endif /* __LINUX_SOC_RENESAS_RCAR_RST_H__ */
index a598cf3ac70ca686ca60c77dbdfb986a554993af..167ad8831aafe092a53f87b982acb45748973337 100644 (file)
@@ -22,7 +22,7 @@
  *        Lai Jiangshan <laijs@cn.fujitsu.com>
  *
  * For detailed explanation of Read-Copy Update mechanism see -
- *             Documentation/RCU/ *.txt
+ *             Documentation/RCU/ *.txt
  *
  */
 
 #include <linux/mutex.h>
 #include <linux/rcupdate.h>
 #include <linux/workqueue.h>
+#include <linux/rcu_segcblist.h>
 
-struct srcu_array {
-       unsigned long lock_count[2];
-       unsigned long unlock_count[2];
-};
-
-struct rcu_batch {
-       struct rcu_head *head, **tail;
-};
-
-#define RCU_BATCH_INIT(name) { NULL, &(name.head) }
-
-struct srcu_struct {
-       unsigned long completed;
-       struct srcu_array __percpu *per_cpu_ref;
-       spinlock_t queue_lock; /* protect ->batch_queue, ->running */
-       bool running;
-       /* callbacks just queued */
-       struct rcu_batch batch_queue;
-       /* callbacks try to do the first check_zero */
-       struct rcu_batch batch_check0;
-       /* callbacks done with the first check_zero and the flip */
-       struct rcu_batch batch_check1;
-       struct rcu_batch batch_done;
-       struct delayed_work work;
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-       struct lockdep_map dep_map;
-#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
-};
+struct srcu_struct;
 
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 
@@ -82,46 +56,15 @@ int init_srcu_struct(struct srcu_struct *sp);
 #define __SRCU_DEP_MAP_INIT(srcu_name)
 #endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */
 
-void process_srcu(struct work_struct *work);
-
-#define __SRCU_STRUCT_INIT(name)                                       \
-       {                                                               \
-               .completed = -300,                                      \
-               .per_cpu_ref = &name##_srcu_array,                      \
-               .queue_lock = __SPIN_LOCK_UNLOCKED(name.queue_lock),    \
-               .running = false,                                       \
-               .batch_queue = RCU_BATCH_INIT(name.batch_queue),        \
-               .batch_check0 = RCU_BATCH_INIT(name.batch_check0),      \
-               .batch_check1 = RCU_BATCH_INIT(name.batch_check1),      \
-               .batch_done = RCU_BATCH_INIT(name.batch_done),          \
-               .work = __DELAYED_WORK_INITIALIZER(name.work, process_srcu, 0),\
-               __SRCU_DEP_MAP_INIT(name)                               \
-       }
-
-/*
- * Define and initialize a srcu struct at build time.
- * Do -not- call init_srcu_struct() nor cleanup_srcu_struct() on it.
- *
- * Note that although DEFINE_STATIC_SRCU() hides the name from other
- * files, the per-CPU variable rules nevertheless require that the
- * chosen name be globally unique.  These rules also prohibit use of
- * DEFINE_STATIC_SRCU() within a function.  If these rules are too
- * restrictive, declare the srcu_struct manually.  For example, in
- * each file:
- *
- *     static struct srcu_struct my_srcu;
- *
- * Then, before the first use of each my_srcu, manually initialize it:
- *
- *     init_srcu_struct(&my_srcu);
- *
- * See include/linux/percpu-defs.h for the rules on per-CPU variables.
- */
-#define __DEFINE_SRCU(name, is_static)                                 \
-       static DEFINE_PER_CPU(struct srcu_array, name##_srcu_array);\
-       is_static struct srcu_struct name = __SRCU_STRUCT_INIT(name)
-#define DEFINE_SRCU(name)              __DEFINE_SRCU(name, /* not static */)
-#define DEFINE_STATIC_SRCU(name)       __DEFINE_SRCU(name, static)
+#ifdef CONFIG_TINY_SRCU
+#include <linux/srcutiny.h>
+#elif defined(CONFIG_TREE_SRCU)
+#include <linux/srcutree.h>
+#elif defined(CONFIG_CLASSIC_SRCU)
+#include <linux/srcuclassic.h>
+#else
+#error "Unknown SRCU implementation specified to kernel configuration"
+#endif
 
 /**
  * call_srcu() - Queue a callback for invocation after an SRCU grace period
@@ -147,9 +90,6 @@ void cleanup_srcu_struct(struct srcu_struct *sp);
 int __srcu_read_lock(struct srcu_struct *sp) __acquires(sp);
 void __srcu_read_unlock(struct srcu_struct *sp, int idx) __releases(sp);
 void synchronize_srcu(struct srcu_struct *sp);
-void synchronize_srcu_expedited(struct srcu_struct *sp);
-unsigned long srcu_batches_completed(struct srcu_struct *sp);
-void srcu_barrier(struct srcu_struct *sp);
 
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 
diff --git a/include/linux/srcuclassic.h b/include/linux/srcuclassic.h
new file mode 100644 (file)
index 0000000..5753f73
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * Sleepable Read-Copy Update mechanism for mutual exclusion,
+ *     classic v4.11 variant.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you can access it online at
+ * http://www.gnu.org/licenses/gpl-2.0.html.
+ *
+ * Copyright (C) IBM Corporation, 2017
+ *
+ * Author: Paul McKenney <paulmck@us.ibm.com>
+ */
+
+#ifndef _LINUX_SRCU_CLASSIC_H
+#define _LINUX_SRCU_CLASSIC_H
+
+struct srcu_array {
+       unsigned long lock_count[2];
+       unsigned long unlock_count[2];
+};
+
+struct rcu_batch {
+       struct rcu_head *head, **tail;
+};
+
+#define RCU_BATCH_INIT(name) { NULL, &(name.head) }
+
+struct srcu_struct {
+       unsigned long completed;
+       struct srcu_array __percpu *per_cpu_ref;
+       spinlock_t queue_lock; /* protect ->batch_queue, ->running */
+       bool running;
+       /* callbacks just queued */
+       struct rcu_batch batch_queue;
+       /* callbacks try to do the first check_zero */
+       struct rcu_batch batch_check0;
+       /* callbacks done with the first check_zero and the flip */
+       struct rcu_batch batch_check1;
+       struct rcu_batch batch_done;
+       struct delayed_work work;
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+       struct lockdep_map dep_map;
+#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
+};
+
+void process_srcu(struct work_struct *work);
+
+#define __SRCU_STRUCT_INIT(name)                                       \
+       {                                                               \
+               .completed = -300,                                      \
+               .per_cpu_ref = &name##_srcu_array,                      \
+               .queue_lock = __SPIN_LOCK_UNLOCKED(name.queue_lock),    \
+               .running = false,                                       \
+               .batch_queue = RCU_BATCH_INIT(name.batch_queue),        \
+               .batch_check0 = RCU_BATCH_INIT(name.batch_check0),      \
+               .batch_check1 = RCU_BATCH_INIT(name.batch_check1),      \
+               .batch_done = RCU_BATCH_INIT(name.batch_done),          \
+               .work = __DELAYED_WORK_INITIALIZER(name.work, process_srcu, 0),\
+               __SRCU_DEP_MAP_INIT(name)                               \
+       }
+
+/*
+ * Define and initialize a srcu struct at build time.
+ * Do -not- call init_srcu_struct() nor cleanup_srcu_struct() on it.
+ *
+ * Note that although DEFINE_STATIC_SRCU() hides the name from other
+ * files, the per-CPU variable rules nevertheless require that the
+ * chosen name be globally unique.  These rules also prohibit use of
+ * DEFINE_STATIC_SRCU() within a function.  If these rules are too
+ * restrictive, declare the srcu_struct manually.  For example, in
+ * each file:
+ *
+ *     static struct srcu_struct my_srcu;
+ *
+ * Then, before the first use of each my_srcu, manually initialize it:
+ *
+ *     init_srcu_struct(&my_srcu);
+ *
+ * See include/linux/percpu-defs.h for the rules on per-CPU variables.
+ */
+#define __DEFINE_SRCU(name, is_static)                                 \
+       static DEFINE_PER_CPU(struct srcu_array, name##_srcu_array);\
+       is_static struct srcu_struct name = __SRCU_STRUCT_INIT(name)
+#define DEFINE_SRCU(name)              __DEFINE_SRCU(name, /* not static */)
+#define DEFINE_STATIC_SRCU(name)       __DEFINE_SRCU(name, static)
+
+void synchronize_srcu_expedited(struct srcu_struct *sp);
+void srcu_barrier(struct srcu_struct *sp);
+unsigned long srcu_batches_completed(struct srcu_struct *sp);
+
+static inline void srcutorture_get_gp_data(enum rcutorture_type test_type,
+                                          struct srcu_struct *sp, int *flags,
+                                          unsigned long *gpnum,
+                                          unsigned long *completed)
+{
+       if (test_type != SRCU_FLAVOR)
+               return;
+       *flags = 0;
+       *completed = sp->completed;
+       *gpnum = *completed;
+       if (sp->batch_queue.head || sp->batch_check0.head || sp->batch_check0.head)
+               (*gpnum)++;
+}
+
+#endif
diff --git a/include/linux/srcutiny.h b/include/linux/srcutiny.h
new file mode 100644 (file)
index 0000000..42311ee
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Sleepable Read-Copy Update mechanism for mutual exclusion,
+ *     tiny variant.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you can access it online at
+ * http://www.gnu.org/licenses/gpl-2.0.html.
+ *
+ * Copyright (C) IBM Corporation, 2017
+ *
+ * Author: Paul McKenney <paulmck@us.ibm.com>
+ */
+
+#ifndef _LINUX_SRCU_TINY_H
+#define _LINUX_SRCU_TINY_H
+
+#include <linux/swait.h>
+
+struct srcu_struct {
+       int srcu_lock_nesting[2];       /* srcu_read_lock() nesting depth. */
+       struct swait_queue_head srcu_wq;
+                                       /* Last srcu_read_unlock() wakes GP. */
+       unsigned long srcu_gp_seq;      /* GP seq # for callback tagging. */
+       struct rcu_segcblist srcu_cblist;
+                                       /* Pending SRCU callbacks. */
+       int srcu_idx;                   /* Current reader array element. */
+       bool srcu_gp_running;           /* GP workqueue running? */
+       bool srcu_gp_waiting;           /* GP waiting for readers? */
+       struct work_struct srcu_work;   /* For driving grace periods. */
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+       struct lockdep_map dep_map;
+#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
+};
+
+void srcu_drive_gp(struct work_struct *wp);
+
+#define __SRCU_STRUCT_INIT(name)                                       \
+{                                                                      \
+       .srcu_wq = __SWAIT_QUEUE_HEAD_INITIALIZER(name.srcu_wq),        \
+       .srcu_cblist = RCU_SEGCBLIST_INITIALIZER(name.srcu_cblist),     \
+       .srcu_work = __WORK_INITIALIZER(name.srcu_work, srcu_drive_gp), \
+       __SRCU_DEP_MAP_INIT(name)                                       \
+}
+
+/*
+ * This odd _STATIC_ arrangement is needed for API compatibility with
+ * Tree SRCU, which needs some per-CPU data.
+ */
+#define DEFINE_SRCU(name) \
+       struct srcu_struct name = __SRCU_STRUCT_INIT(name)
+#define DEFINE_STATIC_SRCU(name) \
+       static struct srcu_struct name = __SRCU_STRUCT_INIT(name)
+
+void synchronize_srcu(struct srcu_struct *sp);
+
+static inline void synchronize_srcu_expedited(struct srcu_struct *sp)
+{
+       synchronize_srcu(sp);
+}
+
+static inline void srcu_barrier(struct srcu_struct *sp)
+{
+       synchronize_srcu(sp);
+}
+
+static inline unsigned long srcu_batches_completed(struct srcu_struct *sp)
+{
+       return 0;
+}
+
+static inline void srcutorture_get_gp_data(enum rcutorture_type test_type,
+                                          struct srcu_struct *sp, int *flags,
+                                          unsigned long *gpnum,
+                                          unsigned long *completed)
+{
+       if (test_type != SRCU_FLAVOR)
+               return;
+       *flags = 0;
+       *completed = sp->srcu_gp_seq;
+       *gpnum = *completed;
+}
+
+#endif
diff --git a/include/linux/srcutree.h b/include/linux/srcutree.h
new file mode 100644 (file)
index 0000000..32e86d8
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * Sleepable Read-Copy Update mechanism for mutual exclusion,
+ *     tree variant.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you can access it online at
+ * http://www.gnu.org/licenses/gpl-2.0.html.
+ *
+ * Copyright (C) IBM Corporation, 2017
+ *
+ * Author: Paul McKenney <paulmck@us.ibm.com>
+ */
+
+#ifndef _LINUX_SRCU_TREE_H
+#define _LINUX_SRCU_TREE_H
+
+#include <linux/rcu_node_tree.h>
+#include <linux/completion.h>
+
+struct srcu_node;
+struct srcu_struct;
+
+/*
+ * Per-CPU structure feeding into leaf srcu_node, similar in function
+ * to rcu_node.
+ */
+struct srcu_data {
+       /* Read-side state. */
+       unsigned long srcu_lock_count[2];       /* Locks per CPU. */
+       unsigned long srcu_unlock_count[2];     /* Unlocks per CPU. */
+
+       /* Update-side state. */
+       spinlock_t lock ____cacheline_internodealigned_in_smp;
+       struct rcu_segcblist srcu_cblist;       /* List of callbacks.*/
+       unsigned long srcu_gp_seq_needed;       /* Furthest future GP needed. */
+       unsigned long srcu_gp_seq_needed_exp;   /* Furthest future exp GP. */
+       bool srcu_cblist_invoking;              /* Invoking these CBs? */
+       struct delayed_work work;               /* Context for CB invoking. */
+       struct rcu_head srcu_barrier_head;      /* For srcu_barrier() use. */
+       struct srcu_node *mynode;               /* Leaf srcu_node. */
+       unsigned long grpmask;                  /* Mask for leaf srcu_node */
+                                               /*  ->srcu_data_have_cbs[]. */
+       int cpu;
+       struct srcu_struct *sp;
+};
+
+/*
+ * Node in SRCU combining tree, similar in function to rcu_data.
+ */
+struct srcu_node {
+       spinlock_t lock;
+       unsigned long srcu_have_cbs[4];         /* GP seq for children */
+                                               /*  having CBs, but only */
+                                               /*  is > ->srcu_gq_seq. */
+       unsigned long srcu_data_have_cbs[4];    /* Which srcu_data structs */
+                                               /*  have CBs for given GP? */
+       unsigned long srcu_gp_seq_needed_exp;   /* Furthest future exp GP. */
+       struct srcu_node *srcu_parent;          /* Next up in tree. */
+       int grplo;                              /* Least CPU for node. */
+       int grphi;                              /* Biggest CPU for node. */
+};
+
+/*
+ * Per-SRCU-domain structure, similar in function to rcu_state.
+ */
+struct srcu_struct {
+       struct srcu_node node[NUM_RCU_NODES];   /* Combining tree. */
+       struct srcu_node *level[RCU_NUM_LVLS + 1];
+                                               /* First node at each level. */
+       struct mutex srcu_cb_mutex;             /* Serialize CB preparation. */
+       spinlock_t gp_lock;                     /* protect ->srcu_cblist */
+       struct mutex srcu_gp_mutex;             /* Serialize GP work. */
+       unsigned int srcu_idx;                  /* Current rdr array element. */
+       unsigned long srcu_gp_seq;              /* Grace-period seq #. */
+       unsigned long srcu_gp_seq_needed;       /* Latest gp_seq needed. */
+       unsigned long srcu_gp_seq_needed_exp;   /* Furthest future exp GP. */
+       unsigned long srcu_last_gp_end;         /* Last GP end timestamp (ns) */
+       struct srcu_data __percpu *sda;         /* Per-CPU srcu_data array. */
+       unsigned long srcu_barrier_seq;         /* srcu_barrier seq #. */
+       struct mutex srcu_barrier_mutex;        /* Serialize barrier ops. */
+       struct completion srcu_barrier_completion;
+                                               /* Awaken barrier rq at end. */
+       atomic_t srcu_barrier_cpu_cnt;          /* # CPUs not yet posting a */
+                                               /*  callback for the barrier */
+                                               /*  operation. */
+       struct delayed_work work;
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+       struct lockdep_map dep_map;
+#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
+};
+
+/* Values for state variable (bottom bits of ->srcu_gp_seq). */
+#define SRCU_STATE_IDLE                0
+#define SRCU_STATE_SCAN1       1
+#define SRCU_STATE_SCAN2       2
+
+void process_srcu(struct work_struct *work);
+
+#define __SRCU_STRUCT_INIT(name)                                       \
+       {                                                               \
+               .sda = &name##_srcu_data,                               \
+               .gp_lock = __SPIN_LOCK_UNLOCKED(name.gp_lock),          \
+               .srcu_gp_seq_needed = 0 - 1,                            \
+               __SRCU_DEP_MAP_INIT(name)                               \
+       }
+
+/*
+ * Define and initialize a srcu struct at build time.
+ * Do -not- call init_srcu_struct() nor cleanup_srcu_struct() on it.
+ *
+ * Note that although DEFINE_STATIC_SRCU() hides the name from other
+ * files, the per-CPU variable rules nevertheless require that the
+ * chosen name be globally unique.  These rules also prohibit use of
+ * DEFINE_STATIC_SRCU() within a function.  If these rules are too
+ * restrictive, declare the srcu_struct manually.  For example, in
+ * each file:
+ *
+ *     static struct srcu_struct my_srcu;
+ *
+ * Then, before the first use of each my_srcu, manually initialize it:
+ *
+ *     init_srcu_struct(&my_srcu);
+ *
+ * See include/linux/percpu-defs.h for the rules on per-CPU variables.
+ */
+#define __DEFINE_SRCU(name, is_static)                                 \
+       static DEFINE_PER_CPU(struct srcu_data, name##_srcu_data);\
+       is_static struct srcu_struct name = __SRCU_STRUCT_INIT(name)
+#define DEFINE_SRCU(name)              __DEFINE_SRCU(name, /* not static */)
+#define DEFINE_STATIC_SRCU(name)       __DEFINE_SRCU(name, static)
+
+void synchronize_srcu_expedited(struct srcu_struct *sp);
+void srcu_barrier(struct srcu_struct *sp);
+unsigned long srcu_batches_completed(struct srcu_struct *sp);
+
+void srcutorture_get_gp_data(enum rcutorture_type test_type,
+                            struct srcu_struct *sp, int *flags,
+                            unsigned long *gpnum, unsigned long *completed);
+
+#endif
index 245fc59b73247d744682c128bfcae1270e146c26..b7e85b341a54f5498e8a2095f3aef84cf5a0fe63 100644 (file)
@@ -143,6 +143,9 @@ enum rpcrdma_proc {
 #define rdma_done      cpu_to_be32(RDMA_DONE)
 #define rdma_error     cpu_to_be32(RDMA_ERROR)
 
+#define err_vers       cpu_to_be32(ERR_VERS)
+#define err_chunk      cpu_to_be32(ERR_CHUNK)
+
 /*
  * Private extension to RPC-over-RDMA Version One.
  * Message passed during RDMA-CM connection set-up.
index e770abeed32d7117c4f2d363f9d7370a60d2c55f..94631026f79c56f022976a85dcde92379507e87c 100644 (file)
@@ -336,8 +336,7 @@ xdr_argsize_check(struct svc_rqst *rqstp, __be32 *p)
 {
        char *cp = (char *)p;
        struct kvec *vec = &rqstp->rq_arg.head[0];
-       return cp >= (char*)vec->iov_base
-               && cp <= (char*)vec->iov_base + vec->iov_len;
+       return cp == (char *)vec->iov_base + vec->iov_len;
 }
 
 static inline int
@@ -474,6 +473,7 @@ void                   svc_pool_map_put(void);
 struct svc_serv *  svc_create_pooled(struct svc_program *, unsigned int,
                        struct svc_serv_ops *);
 int               svc_set_num_threads(struct svc_serv *, struct svc_pool *, int);
+int               svc_set_num_threads_sync(struct svc_serv *, struct svc_pool *, int);
 int               svc_pool_stats_open(struct svc_serv *serv, struct file *file);
 void              svc_destroy(struct svc_serv *);
 void              svc_shutdown_net(struct svc_serv *, struct net *);
index b105f73e3ca26355b2ee8b32651b48526a945899..f3787d800ba46b7cdae49e19584fe64cbdff2ef3 100644 (file)
 #include <rdma/rdma_cm.h>
 #define SVCRDMA_DEBUG
 
+/* Default and maximum inline threshold sizes */
+enum {
+       RPCRDMA_DEF_INLINE_THRESH = 4096,
+       RPCRDMA_MAX_INLINE_THRESH = 65536
+};
+
 /* RPC/RDMA parameters and stats */
 extern unsigned int svcrdma_ord;
 extern unsigned int svcrdma_max_requests;
@@ -85,27 +91,11 @@ struct svc_rdma_op_ctxt {
        enum dma_data_direction direction;
        int count;
        unsigned int mapped_sges;
-       struct ib_sge sge[RPCSVC_MAXPAGES];
+       struct ib_send_wr send_wr;
+       struct ib_sge sge[1 + RPCRDMA_MAX_INLINE_THRESH / PAGE_SIZE];
        struct page *pages[RPCSVC_MAXPAGES];
 };
 
-/*
- * NFS_ requests are mapped on the client side by the chunk lists in
- * the RPCRDMA header. During the fetching of the RPC from the client
- * and the writing of the reply to the client, the memory in the
- * client and the memory in the server must be mapped as contiguous
- * vaddr/len for access by the hardware. These data strucures keep
- * these mappings.
- *
- * For an RDMA_WRITE, the 'sge' maps the RPC REPLY. For RDMA_READ, the
- * 'sge' in the svc_rdma_req_map maps the server side RPC reply and the
- * 'ch' field maps the read-list of the RPCRDMA header to the 'sge'
- * mapping of the reply.
- */
-struct svc_rdma_chunk_sge {
-       int start;              /* sge no for this chunk */
-       int count;              /* sge count for this chunk */
-};
 struct svc_rdma_fastreg_mr {
        struct ib_mr *mr;
        struct scatterlist *sg;
@@ -114,15 +104,7 @@ struct svc_rdma_fastreg_mr {
        enum dma_data_direction direction;
        struct list_head frmr_list;
 };
-struct svc_rdma_req_map {
-       struct list_head free;
-       unsigned long count;
-       union {
-               struct kvec sge[RPCSVC_MAXPAGES];
-               struct svc_rdma_chunk_sge ch[RPCSVC_MAXPAGES];
-               unsigned long lkey[RPCSVC_MAXPAGES];
-       };
-};
+
 #define RDMACTXT_F_LAST_CTXT   2
 
 #define        SVCRDMA_DEVCAP_FAST_REG         1       /* fast mr registration */
@@ -144,14 +126,15 @@ struct svcxprt_rdma {
        u32                  sc_max_requests;   /* Max requests */
        u32                  sc_max_bc_requests;/* Backward credits */
        int                  sc_max_req_size;   /* Size of each RQ WR buf */
+       u8                   sc_port_num;
 
        struct ib_pd         *sc_pd;
 
        spinlock_t           sc_ctxt_lock;
        struct list_head     sc_ctxts;
        int                  sc_ctxt_used;
-       spinlock_t           sc_map_lock;
-       struct list_head     sc_maps;
+       spinlock_t           sc_rw_ctxt_lock;
+       struct list_head     sc_rw_ctxts;
 
        struct list_head     sc_rq_dto_q;
        spinlock_t           sc_rq_dto_lock;
@@ -181,9 +164,7 @@ struct svcxprt_rdma {
 /* The default ORD value is based on two outstanding full-size writes with a
  * page size of 4k, or 32k * 2 ops / 4k = 16 outstanding RDMA_READ.  */
 #define RPCRDMA_ORD             (64/4)
-#define RPCRDMA_SQ_DEPTH_MULT   8
 #define RPCRDMA_MAX_REQUESTS    32
-#define RPCRDMA_MAX_REQ_SIZE    4096
 
 /* Typical ULP usage of BC requests is NFSv4.1 backchannel. Our
  * current NFSv4.1 implementation supports one backchannel slot.
@@ -201,19 +182,11 @@ static inline void svc_rdma_count_mappings(struct svcxprt_rdma *rdma,
 
 /* svc_rdma_backchannel.c */
 extern int svc_rdma_handle_bc_reply(struct rpc_xprt *xprt,
-                                   struct rpcrdma_msg *rmsgp,
+                                   __be32 *rdma_resp,
                                    struct xdr_buf *rcvbuf);
 
 /* svc_rdma_marshal.c */
 extern int svc_rdma_xdr_decode_req(struct xdr_buf *);
-extern int svc_rdma_xdr_encode_error(struct svcxprt_rdma *,
-                                    struct rpcrdma_msg *,
-                                    enum rpcrdma_errcode, __be32 *);
-extern void svc_rdma_xdr_encode_write_list(struct rpcrdma_msg *, int);
-extern void svc_rdma_xdr_encode_reply_array(struct rpcrdma_write_array *, int);
-extern void svc_rdma_xdr_encode_array_chunk(struct rpcrdma_write_array *, int,
-                                           __be32, __be64, u32);
-extern unsigned int svc_rdma_xdr_get_reply_hdr_len(__be32 *rdma_resp);
 
 /* svc_rdma_recvfrom.c */
 extern int svc_rdma_recvfrom(struct svc_rqst *);
@@ -224,16 +197,25 @@ extern int rdma_read_chunk_frmr(struct svcxprt_rdma *, struct svc_rqst *,
                                struct svc_rdma_op_ctxt *, int *, u32 *,
                                u32, u32, u64, bool);
 
+/* svc_rdma_rw.c */
+extern void svc_rdma_destroy_rw_ctxts(struct svcxprt_rdma *rdma);
+extern int svc_rdma_send_write_chunk(struct svcxprt_rdma *rdma,
+                                    __be32 *wr_ch, struct xdr_buf *xdr);
+extern int svc_rdma_send_reply_chunk(struct svcxprt_rdma *rdma,
+                                    __be32 *rp_ch, bool writelist,
+                                    struct xdr_buf *xdr);
+
 /* svc_rdma_sendto.c */
-extern int svc_rdma_map_xdr(struct svcxprt_rdma *, struct xdr_buf *,
-                           struct svc_rdma_req_map *, bool);
+extern int svc_rdma_map_reply_hdr(struct svcxprt_rdma *rdma,
+                                 struct svc_rdma_op_ctxt *ctxt,
+                                 __be32 *rdma_resp, unsigned int len);
+extern int svc_rdma_post_send_wr(struct svcxprt_rdma *rdma,
+                                struct svc_rdma_op_ctxt *ctxt,
+                                int num_sge, u32 inv_rkey);
 extern int svc_rdma_sendto(struct svc_rqst *);
-extern void svc_rdma_send_error(struct svcxprt_rdma *, struct rpcrdma_msg *,
-                               int);
 
 /* svc_rdma_transport.c */
 extern void svc_rdma_wc_send(struct ib_cq *, struct ib_wc *);
-extern void svc_rdma_wc_write(struct ib_cq *, struct ib_wc *);
 extern void svc_rdma_wc_reg(struct ib_cq *, struct ib_wc *);
 extern void svc_rdma_wc_read(struct ib_cq *, struct ib_wc *);
 extern void svc_rdma_wc_inv(struct ib_cq *, struct ib_wc *);
@@ -244,9 +226,6 @@ extern int svc_rdma_create_listen(struct svc_serv *, int, struct sockaddr *);
 extern struct svc_rdma_op_ctxt *svc_rdma_get_context(struct svcxprt_rdma *);
 extern void svc_rdma_put_context(struct svc_rdma_op_ctxt *, int);
 extern void svc_rdma_unmap_dma(struct svc_rdma_op_ctxt *ctxt);
-extern struct svc_rdma_req_map *svc_rdma_get_req_map(struct svcxprt_rdma *);
-extern void svc_rdma_put_req_map(struct svcxprt_rdma *,
-                                struct svc_rdma_req_map *);
 extern struct svc_rdma_fastreg_mr *svc_rdma_get_frmr(struct svcxprt_rdma *);
 extern void svc_rdma_put_frmr(struct svcxprt_rdma *,
                              struct svc_rdma_fastreg_mr *);
index d9718378a8bee0b327d08c2e80a6fd3b5490b967..0b1cf32edfd7ba1c456252124e23c68450d5bcc3 100644 (file)
@@ -189,6 +189,8 @@ struct platform_suspend_ops {
 struct platform_freeze_ops {
        int (*begin)(void);
        int (*prepare)(void);
+       void (*wake)(void);
+       void (*sync)(void);
        void (*restore)(void);
        void (*end)(void);
 };
@@ -428,7 +430,8 @@ extern unsigned int pm_wakeup_irq;
 
 extern bool pm_wakeup_pending(void);
 extern void pm_system_wakeup(void);
-extern void pm_wakeup_clear(void);
+extern void pm_system_cancel_wakeup(void);
+extern void pm_wakeup_clear(bool reset);
 extern void pm_system_irq_wakeup(unsigned int irq_number);
 extern bool pm_get_wakeup_count(unsigned int *count, bool block);
 extern bool pm_save_wakeup_count(unsigned int count);
@@ -478,7 +481,7 @@ static inline int unregister_pm_notifier(struct notifier_block *nb)
 
 static inline bool pm_wakeup_pending(void) { return false; }
 static inline void pm_system_wakeup(void) {}
-static inline void pm_wakeup_clear(void) {}
+static inline void pm_wakeup_clear(bool reset) {}
 static inline void pm_system_irq_wakeup(unsigned int irq_number) {}
 
 static inline void lock_system_sleep(void) {}
diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h
new file mode 100644 (file)
index 0000000..0f175b8
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2015-2016, Linaro Limited
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __TEE_DRV_H
+#define __TEE_DRV_H
+
+#include <linux/types.h>
+#include <linux/idr.h>
+#include <linux/list.h>
+#include <linux/tee.h>
+
+/*
+ * The file describes the API provided by the generic TEE driver to the
+ * specific TEE driver.
+ */
+
+#define TEE_SHM_MAPPED         0x1     /* Memory mapped by the kernel */
+#define TEE_SHM_DMA_BUF                0x2     /* Memory with dma-buf handle */
+
+struct tee_device;
+struct tee_shm;
+struct tee_shm_pool;
+
+/**
+ * struct tee_context - driver specific context on file pointer data
+ * @teedev:    pointer to this drivers struct tee_device
+ * @list_shm:  List of shared memory object owned by this context
+ * @data:      driver specific context data, managed by the driver
+ */
+struct tee_context {
+       struct tee_device *teedev;
+       struct list_head list_shm;
+       void *data;
+};
+
+struct tee_param_memref {
+       size_t shm_offs;
+       size_t size;
+       struct tee_shm *shm;
+};
+
+struct tee_param_value {
+       u64 a;
+       u64 b;
+       u64 c;
+};
+
+struct tee_param {
+       u64 attr;
+       union {
+               struct tee_param_memref memref;
+               struct tee_param_value value;
+       } u;
+};
+
+/**
+ * struct tee_driver_ops - driver operations vtable
+ * @get_version:       returns version of driver
+ * @open:              called when the device file is opened
+ * @release:           release this open file
+ * @open_session:      open a new session
+ * @close_session:     close a session
+ * @invoke_func:       invoke a trusted function
+ * @cancel_req:                request cancel of an ongoing invoke or open
+ * @supp_revc:         called for supplicant to get a command
+ * @supp_send:         called for supplicant to send a response
+ */
+struct tee_driver_ops {
+       void (*get_version)(struct tee_device *teedev,
+                           struct tee_ioctl_version_data *vers);
+       int (*open)(struct tee_context *ctx);
+       void (*release)(struct tee_context *ctx);
+       int (*open_session)(struct tee_context *ctx,
+                           struct tee_ioctl_open_session_arg *arg,
+                           struct tee_param *param);
+       int (*close_session)(struct tee_context *ctx, u32 session);
+       int (*invoke_func)(struct tee_context *ctx,
+                          struct tee_ioctl_invoke_arg *arg,
+                          struct tee_param *param);
+       int (*cancel_req)(struct tee_context *ctx, u32 cancel_id, u32 session);
+       int (*supp_recv)(struct tee_context *ctx, u32 *func, u32 *num_params,
+                        struct tee_param *param);
+       int (*supp_send)(struct tee_context *ctx, u32 ret, u32 num_params,
+                        struct tee_param *param);
+};
+
+/**
+ * struct tee_desc - Describes the TEE driver to the subsystem
+ * @name:      name of driver
+ * @ops:       driver operations vtable
+ * @owner:     module providing the driver
+ * @flags:     Extra properties of driver, defined by TEE_DESC_* below
+ */
+#define TEE_DESC_PRIVILEGED    0x1
+struct tee_desc {
+       const char *name;
+       const struct tee_driver_ops *ops;
+       struct module *owner;
+       u32 flags;
+};
+
+/**
+ * tee_device_alloc() - Allocate a new struct tee_device instance
+ * @teedesc:   Descriptor for this driver
+ * @dev:       Parent device for this device
+ * @pool:      Shared memory pool, NULL if not used
+ * @driver_data: Private driver data for this device
+ *
+ * Allocates a new struct tee_device instance. The device is
+ * removed by tee_device_unregister().
+ *
+ * @returns a pointer to a 'struct tee_device' or an ERR_PTR on failure
+ */
+struct tee_device *tee_device_alloc(const struct tee_desc *teedesc,
+                                   struct device *dev,
+                                   struct tee_shm_pool *pool,
+                                   void *driver_data);
+
+/**
+ * tee_device_register() - Registers a TEE device
+ * @teedev:    Device to register
+ *
+ * tee_device_unregister() need to be called to remove the @teedev if
+ * this function fails.
+ *
+ * @returns < 0 on failure
+ */
+int tee_device_register(struct tee_device *teedev);
+
+/**
+ * tee_device_unregister() - Removes a TEE device
+ * @teedev:    Device to unregister
+ *
+ * This function should be called to remove the @teedev even if
+ * tee_device_register() hasn't been called yet. Does nothing if
+ * @teedev is NULL.
+ */
+void tee_device_unregister(struct tee_device *teedev);
+
+/**
+ * struct tee_shm_pool_mem_info - holds information needed to create a shared
+ * memory pool
+ * @vaddr:     Virtual address of start of pool
+ * @paddr:     Physical address of start of pool
+ * @size:      Size in bytes of the pool
+ */
+struct tee_shm_pool_mem_info {
+       unsigned long vaddr;
+       phys_addr_t paddr;
+       size_t size;
+};
+
+/**
+ * tee_shm_pool_alloc_res_mem() - Create a shared memory pool from reserved
+ * memory range
+ * @priv_info:  Information for driver private shared memory pool
+ * @dmabuf_info: Information for dma-buf shared memory pool
+ *
+ * Start and end of pools will must be page aligned.
+ *
+ * Allocation with the flag TEE_SHM_DMA_BUF set will use the range supplied
+ * in @dmabuf, others will use the range provided by @priv.
+ *
+ * @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure.
+ */
+struct tee_shm_pool *
+tee_shm_pool_alloc_res_mem(struct tee_shm_pool_mem_info *priv_info,
+                          struct tee_shm_pool_mem_info *dmabuf_info);
+
+/**
+ * tee_shm_pool_free() - Free a shared memory pool
+ * @pool:      The shared memory pool to free
+ *
+ * The must be no remaining shared memory allocated from this pool when
+ * this function is called.
+ */
+void tee_shm_pool_free(struct tee_shm_pool *pool);
+
+/**
+ * tee_get_drvdata() - Return driver_data pointer
+ * @returns the driver_data pointer supplied to tee_register().
+ */
+void *tee_get_drvdata(struct tee_device *teedev);
+
+/**
+ * tee_shm_alloc() - Allocate shared memory
+ * @ctx:       Context that allocates the shared memory
+ * @size:      Requested size of shared memory
+ * @flags:     Flags setting properties for the requested shared memory.
+ *
+ * Memory allocated as global shared memory is automatically freed when the
+ * TEE file pointer is closed. The @flags field uses the bits defined by
+ * TEE_SHM_* above. TEE_SHM_MAPPED must currently always be set. If
+ * TEE_SHM_DMA_BUF global shared memory will be allocated and associated
+ * with a dma-buf handle, else driver private memory.
+ *
+ * @returns a pointer to 'struct tee_shm'
+ */
+struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags);
+
+/**
+ * tee_shm_free() - Free shared memory
+ * @shm:       Handle to shared memory to free
+ */
+void tee_shm_free(struct tee_shm *shm);
+
+/**
+ * tee_shm_put() - Decrease reference count on a shared memory handle
+ * @shm:       Shared memory handle
+ */
+void tee_shm_put(struct tee_shm *shm);
+
+/**
+ * tee_shm_va2pa() - Get physical address of a virtual address
+ * @shm:       Shared memory handle
+ * @va:                Virtual address to tranlsate
+ * @pa:                Returned physical address
+ * @returns 0 on success and < 0 on failure
+ */
+int tee_shm_va2pa(struct tee_shm *shm, void *va, phys_addr_t *pa);
+
+/**
+ * tee_shm_pa2va() - Get virtual address of a physical address
+ * @shm:       Shared memory handle
+ * @pa:                Physical address to tranlsate
+ * @va:                Returned virtual address
+ * @returns 0 on success and < 0 on failure
+ */
+int tee_shm_pa2va(struct tee_shm *shm, phys_addr_t pa, void **va);
+
+/**
+ * tee_shm_get_va() - Get virtual address of a shared memory plus an offset
+ * @shm:       Shared memory handle
+ * @offs:      Offset from start of this shared memory
+ * @returns virtual address of the shared memory + offs if offs is within
+ *     the bounds of this shared memory, else an ERR_PTR
+ */
+void *tee_shm_get_va(struct tee_shm *shm, size_t offs);
+
+/**
+ * tee_shm_get_pa() - Get physical address of a shared memory plus an offset
+ * @shm:       Shared memory handle
+ * @offs:      Offset from start of this shared memory
+ * @pa:                Physical address to return
+ * @returns 0 if offs is within the bounds of this shared memory, else an
+ *     error code.
+ */
+int tee_shm_get_pa(struct tee_shm *shm, size_t offs, phys_addr_t *pa);
+
+/**
+ * tee_shm_get_id() - Get id of a shared memory object
+ * @shm:       Shared memory handle
+ * @returns id
+ */
+int tee_shm_get_id(struct tee_shm *shm);
+
+/**
+ * tee_shm_get_from_id() - Find shared memory object and increase reference
+ * count
+ * @ctx:       Context owning the shared memory
+ * @id:                Id of shared memory object
+ * @returns a pointer to 'struct tee_shm' on success or an ERR_PTR on failure
+ */
+struct tee_shm *tee_shm_get_from_id(struct tee_context *ctx, int id);
+
+#endif /*__TEE_DRV_H*/
index 23f0f5ce30909d7349a354086980e2ca9988744c..c0543f5f25de471594330d84d605c6f20ef4c565 100644 (file)
@@ -151,9 +151,6 @@ static inline bool timespec_inject_offset_valid(const struct timespec *ts)
        return true;
 }
 
-#define CURRENT_TIME           (current_kernel_time())
-#define CURRENT_TIME_SEC       ((struct timespec) { get_seconds(), 0 })
-
 /* Some architectures do not supply their own clocksource.
  * This is mainly the case in architectures that get their
  * inter-tick times by reading the counter on their interval
index 1017e904c0a3f90507183570b0897199b4ace563..d07cd2105a6c6a3bdcac20c918622c7ad4ea0840 100644 (file)
@@ -390,7 +390,6 @@ static inline bool tty_throttled(struct tty_struct *tty)
 }
 
 #ifdef CONFIG_TTY
-extern void console_init(void);
 extern void tty_kref_put(struct tty_struct *tty);
 extern struct pid *tty_get_pgrp(struct tty_struct *tty);
 extern void tty_vhangup_self(void);
@@ -402,8 +401,6 @@ extern struct tty_struct *get_current_tty(void);
 extern int __init tty_init(void);
 extern const char *tty_name(const struct tty_struct *tty);
 #else
-static inline void console_init(void)
-{ }
 static inline void tty_kref_put(struct tty_struct *tty)
 { }
 static inline struct pid *tty_get_pgrp(struct tty_struct *tty)
@@ -478,9 +475,13 @@ extern int tty_do_resize(struct tty_struct *tty, struct winsize *ws);
 extern int is_current_pgrp_orphaned(void);
 extern void tty_hangup(struct tty_struct *tty);
 extern void tty_vhangup(struct tty_struct *tty);
+extern void tty_vhangup_session(struct tty_struct *tty);
 extern int tty_hung_up_p(struct file *filp);
 extern void do_SAK(struct tty_struct *tty);
 extern void __do_SAK(struct tty_struct *tty);
+extern void tty_open_proc_set_tty(struct file *filp, struct tty_struct *tty);
+extern int tty_signal_session_leader(struct tty_struct *tty, int exit_session);
+extern void session_clear_tty(struct pid *session);
 extern void no_tty(void);
 extern void tty_buffer_free_all(struct tty_port *port);
 extern void tty_buffer_flush(struct tty_struct *tty, struct tty_ldisc *ld);
@@ -528,6 +529,8 @@ extern void tty_ldisc_flush(struct tty_struct *tty);
 extern long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
 extern int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
                        unsigned int cmd, unsigned long arg);
+extern long tty_jobctrl_ioctl(struct tty_struct *tty, struct tty_struct *real_tty,
+                             struct file *file, unsigned int cmd, unsigned long arg);
 extern int tty_perform_flush(struct tty_struct *tty, unsigned long arg);
 extern void tty_default_fops(struct file_operations *fops);
 extern struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx);
@@ -669,7 +672,11 @@ extern int tty_ldisc_receive_buf(struct tty_ldisc *ld, const unsigned char *p,
 
 /* n_tty.c */
 extern void n_tty_inherit_ops(struct tty_ldisc_ops *ops);
+#ifdef CONFIG_TTY
 extern void __init n_tty_init(void);
+#else
+static inline void n_tty_init(void) { }
+#endif
 
 /* tty_audit.c */
 #ifdef CONFIG_AUDIT
index 1e7bd24848fcb54cae26bdd10597f6ea80afd46f..258099a4ed82b1b3dd8199b7c905491c935a73a7 100644 (file)
@@ -209,7 +209,7 @@ struct ustat {
  * naturally due ABI requirements, but some architectures (like CRIS) have
  * weird ABI and we need to ask it explicitly.
  *
- * The alignment is required to guarantee that bits 0 and 1 of @next will be
+ * The alignment is required to guarantee that bit 0 of @next will be
  * clear under normal conditions -- as long as we use call_rcu(),
  * call_rcu_bh(), call_rcu_sched(), or call_srcu() to queue callback.
  *
index e0cbfb09e60f042d09b983ed596d309e1add654d..201418d5e15c2b92dc7d7bc73b54f469eb488a35 100644 (file)
@@ -203,7 +203,6 @@ static __always_inline void pagefault_disabled_inc(void)
 static __always_inline void pagefault_disabled_dec(void)
 {
        current->pagefault_disabled--;
-       WARN_ON(current->pagefault_disabled < 0);
 }
 
 /*
index 7edfbdb55a995d436bf9e999ce202d0ca0bf2550..28b0e965360ff1822a22252b1ecaaab52ca8ab2d 100644 (file)
@@ -44,6 +44,12 @@ int virtqueue_add_inbuf(struct virtqueue *vq,
                        void *data,
                        gfp_t gfp);
 
+int virtqueue_add_inbuf_ctx(struct virtqueue *vq,
+                           struct scatterlist sg[], unsigned int num,
+                           void *data,
+                           void *ctx,
+                           gfp_t gfp);
+
 int virtqueue_add_sgs(struct virtqueue *vq,
                      struct scatterlist *sgs[],
                      unsigned int out_sgs,
@@ -59,6 +65,9 @@ bool virtqueue_notify(struct virtqueue *vq);
 
 void *virtqueue_get_buf(struct virtqueue *vq, unsigned int *len);
 
+void *virtqueue_get_buf_ctx(struct virtqueue *vq, unsigned int *len,
+                           void **ctx);
+
 void virtqueue_disable_cb(struct virtqueue *vq);
 
 bool virtqueue_enable_cb(struct virtqueue *vq);
@@ -156,9 +165,13 @@ int virtio_device_restore(struct virtio_device *dev);
  * @feature_table_legacy: same as feature_table but when working in legacy mode.
  * @feature_table_size_legacy: number of entries in feature table legacy array.
  * @probe: the function to call when a device is found.  Returns 0 or -errno.
+ * @scan: optional function to call after successful probe; intended
+ *    for virtio-scsi to invoke a scan.
  * @remove: the function to call when a device is removed.
  * @config_changed: optional function to call when the device configuration
  *    changes; may be called in interrupt context.
+ * @freeze: optional function to call during suspend/hibernation.
+ * @restore: optional function to call on resume.
  */
 struct virtio_driver {
        struct device_driver driver;
index 8355bab175e1d8fb27ac9e0860465ba8afc36076..0133d8a12ccd468514a72fdf8eff64aa7d69551d 100644 (file)
@@ -72,7 +72,8 @@ struct virtio_config_ops {
        void (*reset)(struct virtio_device *vdev);
        int (*find_vqs)(struct virtio_device *, unsigned nvqs,
                        struct virtqueue *vqs[], vq_callback_t *callbacks[],
-                       const char * const names[], struct irq_affinity *desc);
+                       const char * const names[], const bool *ctx,
+                       struct irq_affinity *desc);
        void (*del_vqs)(struct virtio_device *);
        u64 (*get_features)(struct virtio_device *vdev);
        int (*finalize_features)(struct virtio_device *vdev);
@@ -173,12 +174,32 @@ struct virtqueue *virtio_find_single_vq(struct virtio_device *vdev,
        vq_callback_t *callbacks[] = { c };
        const char *names[] = { n };
        struct virtqueue *vq;
-       int err = vdev->config->find_vqs(vdev, 1, &vq, callbacks, names, NULL);
+       int err = vdev->config->find_vqs(vdev, 1, &vq, callbacks, names, NULL,
+                                        NULL);
        if (err < 0)
                return ERR_PTR(err);
        return vq;
 }
 
+static inline
+int virtio_find_vqs(struct virtio_device *vdev, unsigned nvqs,
+                       struct virtqueue *vqs[], vq_callback_t *callbacks[],
+                       const char * const names[],
+                       struct irq_affinity *desc)
+{
+       return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, NULL, desc);
+}
+
+static inline
+int virtio_find_vqs_ctx(struct virtio_device *vdev, unsigned nvqs,
+                       struct virtqueue *vqs[], vq_callback_t *callbacks[],
+                       const char * const names[], const bool *ctx,
+                       struct irq_affinity *desc)
+{
+       return vdev->config->find_vqs(vdev, nvqs, vqs, callbacks, names, ctx,
+                                     desc);
+}
+
 /**
  * virtio_device_ready - enable vq use in probe function
  * @vdev: the device
index e8d36938f09a56cfe4729c17b0ee8175b4991bbe..270cfa81830ee4a69bca0c4ccf914a7a94e5b3e1 100644 (file)
@@ -71,6 +71,7 @@ struct virtqueue *vring_create_virtqueue(unsigned int index,
                                         struct virtio_device *vdev,
                                         bool weak_barriers,
                                         bool may_reduce_num,
+                                        bool ctx,
                                         bool (*notify)(struct virtqueue *vq),
                                         void (*callback)(struct virtqueue *vq),
                                         const char *name);
@@ -80,6 +81,7 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index,
                                        struct vring vring,
                                        struct virtio_device *vdev,
                                        bool weak_barriers,
+                                       bool ctx,
                                        bool (*notify)(struct virtqueue *),
                                        void (*callback)(struct virtqueue *),
                                        const char *name);
@@ -93,6 +95,7 @@ struct virtqueue *vring_new_virtqueue(unsigned int index,
                                      unsigned int vring_align,
                                      struct virtio_device *vdev,
                                      bool weak_barriers,
+                                     bool ctx,
                                      void *pages,
                                      bool (*notify)(struct virtqueue *vq),
                                      void (*callback)(struct virtqueue *vq),
index d68edffbf142cec5f8987a7907b6f2e76cefdfd7..2d92dd002abdaf823d1676be3c1ed5315d18342b 100644 (file)
@@ -80,6 +80,17 @@ extern void *__vmalloc_node_range(unsigned long size, unsigned long align,
                        unsigned long start, unsigned long end, gfp_t gfp_mask,
                        pgprot_t prot, unsigned long vm_flags, int node,
                        const void *caller);
+#ifndef CONFIG_MMU
+extern void *__vmalloc_node_flags(unsigned long size, int node, gfp_t flags);
+static inline void *__vmalloc_node_flags_caller(unsigned long size, int node,
+                                               gfp_t flags, void *caller)
+{
+       return __vmalloc_node_flags(size, node, flags);
+}
+#else
+extern void *__vmalloc_node_flags_caller(unsigned long size,
+                                        int node, gfp_t flags, void *caller);
+#endif
 
 extern void vfree(const void *addr);
 extern void vfree_atomic(const void *addr);
index 2452e6449532fcdd196c493cb1c0d8b32bdb6a43..b43a4eec3ceca4f798bf7513ecd4aa999535c6e7 100644 (file)
@@ -20,6 +20,8 @@
 #define ADDRCONF_TIMER_FUZZ            (HZ / 4)
 #define ADDRCONF_TIMER_FUZZ_MAX                (HZ)
 
+#define ADDRCONF_NOTIFY_PRIORITY       0
+
 #include <linux/in.h>
 #include <linux/in6.h>
 
index 15d6599b8bc6e2f20c3a8705a0c606bba48515f9..b083e6cbae8cb33f3c9d9078bab5468cd80d31f1 100644 (file)
@@ -1666,7 +1666,7 @@ struct cfg80211_bss_select_adjust {
  *     (others are filtered out).
  *     If ommited, all results are passed.
  * @n_match_sets: number of match sets
- * @results_wk: worker for processing results notification.
+ * @report_results: indicates that results were reported for this request
  * @wiphy: the wiphy this was for
  * @dev: the interface
  * @scan_start: start time of the scheduled scan
index 4d05a9443344a54499e666ae2732fc320052d02b..76ed24a201eb9075672e8d2f55fffe5ae147923d 100644 (file)
@@ -1141,7 +1141,6 @@ enum mac80211_rx_flags {
  * enum mac80211_rx_encoding_flags - MCS & bandwidth flags
  *
  * @RX_ENC_FLAG_SHORTPRE: Short preamble was used for this frame
- * @RX_ENC_FLAG_40MHZ: HT40 (40 MHz) was used
  * @RX_ENC_FLAG_SHORT_GI: Short guard interval was used
  * @RX_ENC_FLAG_HT_GF: This frame was received in a HT-greenfield transmission,
  *     if the driver fills this value it should add
@@ -1153,7 +1152,6 @@ enum mac80211_rx_flags {
  */
 enum mac80211_rx_encoding_flags {
        RX_ENC_FLAG_SHORTPRE            = BIT(0),
-       RX_ENC_FLAG_40MHZ               = BIT(1),
        RX_ENC_FLAG_SHORT_GI            = BIT(2),
        RX_ENC_FLAG_HT_GF               = BIT(3),
        RX_ENC_FLAG_STBC_MASK           = BIT(4) | BIT(5),
index fe236b3429f0d8caeb1adc367b5b4a20591c848b..b94006f6fbdde0d78fe33b9c2d86159e291c30cf 100644 (file)
@@ -6,10 +6,12 @@
 u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport);
 u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
                               __be16 dport);
-u32 secure_tcp_seq_and_tsoff(__be32 saddr, __be32 daddr,
-                            __be16 sport, __be16 dport, u32 *tsoff);
-u32 secure_tcpv6_seq_and_tsoff(const __be32 *saddr, const __be32 *daddr,
-                              __be16 sport, __be16 dport, u32 *tsoff);
+u32 secure_tcp_seq(__be32 saddr, __be32 daddr,
+                  __be16 sport, __be16 dport);
+u32 secure_tcp_ts_off(__be32 saddr, __be32 daddr);
+u32 secure_tcpv6_seq(const __be32 *saddr, const __be32 *daddr,
+                    __be16 sport, __be16 dport);
+u32 secure_tcpv6_ts_off(const __be32 *saddr, const __be32 *daddr);
 u64 secure_dccp_sequence_number(__be32 saddr, __be32 daddr,
                                __be16 sport, __be16 dport);
 u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr,
index 66349e49d468646ce724485bb8e74952825f0d6c..f33e3d134e0b7f66329f2122d7acc8b396c1787b 100644 (file)
@@ -995,7 +995,7 @@ struct smc_hashinfo;
 struct module;
 
 /*
- * caches using SLAB_DESTROY_BY_RCU should let .next pointer from nulls nodes
+ * caches using SLAB_TYPESAFE_BY_RCU should let .next pointer from nulls nodes
  * un-modified. Special care is taken when initializing object to zero.
  */
 static inline void sk_prot_clear_nulls(struct sock *sk, int size)
index 270e5cc43c99e7030e95af218095cf9f283950bc..38a7427ae902e35973a8b7fa0e95ff602ede0e87 100644 (file)
@@ -470,7 +470,7 @@ void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb);
 /* From syncookies.c */
 struct sock *tcp_get_cookie_sock(struct sock *sk, struct sk_buff *skb,
                                 struct request_sock *req,
-                                struct dst_entry *dst);
+                                struct dst_entry *dst, u32 tsoff);
 int __cookie_v4_check(const struct iphdr *iph, const struct tcphdr *th,
                      u32 cookie);
 struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb);
@@ -1234,10 +1234,12 @@ void tcp_cwnd_restart(struct sock *sk, s32 delta);
 
 static inline void tcp_slow_start_after_idle_check(struct sock *sk)
 {
+       const struct tcp_congestion_ops *ca_ops = inet_csk(sk)->icsk_ca_ops;
        struct tcp_sock *tp = tcp_sk(sk);
        s32 delta;
 
-       if (!sysctl_tcp_slow_start_after_idle || tp->packets_out)
+       if (!sysctl_tcp_slow_start_after_idle || tp->packets_out ||
+           ca_ops->cong_control)
                return;
        delta = tcp_time_stamp - tp->lsndtime;
        if (delta > inet_csk(sk)->icsk_rto)
@@ -1822,7 +1824,8 @@ struct tcp_request_sock_ops {
 #endif
        struct dst_entry *(*route_req)(const struct sock *sk, struct flowi *fl,
                                       const struct request_sock *req);
-       __u32 (*init_seq_tsoff)(const struct sk_buff *skb, u32 *tsoff);
+       u32 (*init_seq)(const struct sk_buff *skb);
+       u32 (*init_ts_off)(const struct sk_buff *skb);
        int (*send_synack)(const struct sock *sk, struct dst_entry *dst,
                           struct flowi *fl, struct request_sock *req,
                           struct tcp_fastopen_cookie *foc,
index c383aa4edbf0c27980ef7aad22ff160c72b41bbd..6d30a01d281d4faa824129cb3921dbc3a77e7da3 100644 (file)
@@ -298,10 +298,10 @@ void x25_check_rbuf(struct sock *);
 
 /* sysctl_net_x25.c */
 #ifdef CONFIG_SYSCTL
-void x25_register_sysctl(void);
+int x25_register_sysctl(void);
 void x25_unregister_sysctl(void);
 #else
-static inline void x25_register_sysctl(void) {};
+static inline int x25_register_sysctl(void) { return 0; };
 static inline void x25_unregister_sysctl(void) {};
 #endif /* CONFIG_SYSCTL */
 
index f0cb4906478ab1713f376555c21af3c1eff12d07..ba8314ec576844ddb7148364617a768c81acd90f 100644 (file)
@@ -62,6 +62,7 @@
 #include <linux/mmu_notifier.h>
 #include <linux/uaccess.h>
 #include <linux/cgroup_rdma.h>
+#include <uapi/rdma/ib_user_verbs.h>
 
 extern struct workqueue_struct *ib_wq;
 extern struct workqueue_struct *ib_comp_wq;
@@ -1889,8 +1890,6 @@ enum ib_mad_result {
        IB_MAD_RESULT_CONSUMED = 1 << 2  /* Packet consumed: stop processing */
 };
 
-#define IB_DEVICE_NAME_MAX 64
-
 struct ib_port_cache {
        struct ib_pkey_cache  *pkey;
        struct ib_gid_table   *gid;
index 1d8141a88d3cbce74491f4b81ca823137312b59d..be6472e5b06bd1ed1117e928e9b3d44748dfbfeb 100644 (file)
@@ -324,6 +324,7 @@ struct rvt_qp {
        u8 r_state;             /* opcode of last packet received */
        u8 r_flags;
        u8 r_head_ack_queue;    /* index into s_ack_queue[] */
+       u8 r_adefered;          /* defered ack count */
 
        struct list_head rspwait;       /* link for waiting to respond */
 
diff --git a/include/scsi/fc/Kbuild b/include/scsi/fc/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
index 6ba66e01f6df33e37bee7f90c773e432ce75fc91..ce78ec8e367da1a34d75136339d9b7e2a088abdf 100644 (file)
 #define WRITE_16              0x8a
 #define READ_ATTRIBUTE        0x8c
 #define WRITE_ATTRIBUTE              0x8d
+#define WRITE_VERIFY_16              0x8e
 #define VERIFY_16            0x8f
 #define SYNCHRONIZE_CACHE_16  0x91
 #define WRITE_SAME_16        0x93
index c76ef30b05ba38ff517972125282c33ecc41b8eb..7baaabd5ec2ced0bf227691bdfea94ba9c53a0e4 100644 (file)
@@ -464,25 +464,6 @@ struct qe_immap {
 } __attribute__ ((packed));
 
 extern struct qe_immap __iomem *qe_immr;
-extern phys_addr_t get_qe_base(void);
-
-/*
- * Returns the offset within the QE address space of the given pointer.
- *
- * Note that the QE does not support 36-bit physical addresses, so if
- * get_qe_base() returns a number above 4GB, the caller will probably fail.
- */
-static inline phys_addr_t immrbar_virt_to_phys(void *address)
-{
-       void *q = (void *)qe_immr;
-
-       /* Is it a MURAM address? */
-       if ((address >= q) && (address < (q + QE_IMMAP_SIZE)))
-               return get_qe_base() + (address - q);
-
-       /* It's an address returned by kmalloc */
-       return virt_to_phys(address);
-}
 
 #endif /* __KERNEL__ */
 #endif /* _ASM_POWERPC_IMMAP_QE_H */
index 70339d7958c02c2d8690509a5b62ef8a844bb7ff..0cd4c11479b1f4c4385c294295fdea4a7d82daa1 100644 (file)
@@ -243,6 +243,7 @@ static inline int qe_alive_during_sleep(void)
 #define qe_muram_free cpm_muram_free
 #define qe_muram_addr cpm_muram_addr
 #define qe_muram_offset cpm_muram_offset
+#define qe_muram_dma cpm_muram_dma
 
 #define qe_setbits32(_addr, _v) iowrite32be(ioread32be(_addr) |  (_v), (_addr))
 #define qe_clrbits32(_addr, _v) iowrite32be(ioread32be(_addr) & ~(_v), (_addr))
similarity index 77%
rename from arch/arm/mach-tegra/flowctrl.h
rename to include/soc/tegra/flowctrl.h
index 73a9c5016c1ab1ae9414887eb3fdfa16a1b32293..8f86aea4024b2f41ad9f28b9cbf39d397940dbac 100644 (file)
@@ -1,7 +1,5 @@
 /*
- * arch/arm/mach-tegra/flowctrl.h
- *
- * functions and macros to control the flowcontroller
+ * Functions and macros to control the flowcontroller
  *
  * Copyright (c) 2010-2012, NVIDIA Corporation. All rights reserved.
  *
@@ -18,8 +16,8 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef __MACH_TEGRA_FLOWCTRL_H
-#define __MACH_TEGRA_FLOWCTRL_H
+#ifndef __SOC_TEGRA_FLOWCTRL_H__
+#define __SOC_TEGRA_FLOWCTRL_H__
 
 #define FLOW_CTRL_HALT_CPU0_EVENTS     0x0
 #define FLOW_CTRL_WAITEVENT            (2 << 29)
 #define TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP       (0xF << 8)
 
 #ifndef __ASSEMBLY__
+#ifdef CONFIG_SOC_TEGRA_FLOWCTRL
 u32 flowctrl_read_cpu_csr(unsigned int cpuid);
 void flowctrl_write_cpu_csr(unsigned int cpuid, u32 value);
 void flowctrl_write_cpu_halt(unsigned int cpuid, u32 value);
 
 void flowctrl_cpu_suspend_enter(unsigned int cpuid);
 void flowctrl_cpu_suspend_exit(unsigned int cpuid);
+#else
+static inline u32 flowctrl_read_cpu_csr(unsigned int cpuid)
+{
+       return 0;
+}
+
+static inline void flowctrl_write_cpu_csr(unsigned int cpuid, u32 value)
+{
+}
+
+static inline void flowctrl_write_cpu_halt(unsigned int cpuid, u32 value) {}
 
-void tegra_flowctrl_init(void);
-#endif
+static inline void flowctrl_cpu_suspend_enter(unsigned int cpuid)
+{
+}
 
-#endif
+static inline void flowctrl_cpu_suspend_exit(unsigned int cpuid)
+{
+}
+#endif /* CONFIG_SOC_TEGRA_FLOWCTRL */
+#endif /* __ASSEMBLY */
+#endif /* __SOC_TEGRA_FLOWCTRL_H__ */
index 2f271d1b9cea6fdc9bb1678077eab3222ea3bf92..1c3982bc558fb1d98ec3c90f6663c1a8189dca8e 100644 (file)
 struct clk;
 struct reset_control;
 
-#ifdef CONFIG_PM_SLEEP
-enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void);
-void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode);
-void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode);
-#endif /* CONFIG_PM_SLEEP */
-
 #ifdef CONFIG_SMP
 bool tegra_pmc_cpu_is_powered(unsigned int cpuid);
 int tegra_pmc_cpu_power_on(unsigned int cpuid);
@@ -144,7 +138,7 @@ enum tegra_io_pad_voltage {
        TEGRA_IO_PAD_3300000UV,
 };
 
-#ifdef CONFIG_ARCH_TEGRA
+#ifdef CONFIG_SOC_TEGRA_PMC
 int tegra_powergate_is_powered(unsigned int id);
 int tegra_powergate_power_on(unsigned int id);
 int tegra_powergate_power_off(unsigned int id);
@@ -163,6 +157,11 @@ int tegra_io_pad_get_voltage(enum tegra_io_pad id);
 /* deprecated, use tegra_io_pad_power_{enable,disable}() instead */
 int tegra_io_rail_power_on(unsigned int id);
 int tegra_io_rail_power_off(unsigned int id);
+
+enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void);
+void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode);
+void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode);
+
 #else
 static inline int tegra_powergate_is_powered(unsigned int id)
 {
@@ -221,6 +220,20 @@ static inline int tegra_io_rail_power_off(unsigned int id)
 {
        return -ENOSYS;
 }
-#endif /* CONFIG_ARCH_TEGRA */
+
+static inline enum tegra_suspend_mode tegra_pmc_get_suspend_mode(void)
+{
+       return TEGRA_SUSPEND_NONE;
+}
+
+static inline void tegra_pmc_set_suspend_mode(enum tegra_suspend_mode mode)
+{
+}
+
+static inline void tegra_pmc_enter_suspend_mode(enum tegra_suspend_mode mode)
+{
+}
+
+#endif /* CONFIG_SOC_TEGRA_PMC */
 
 #endif /* __SOC_TEGRA_PMC_H__ */
index 1b0f447ce850f015e64dd27e47751fe945cbb2ec..e475531565fdfb6808de54bf9b4c84de7a501584 100644 (file)
@@ -10,6 +10,7 @@
  * backend module.
  */
 #define TRANSPORT_FLAG_PASSTHROUGH_ALUA                0x2
+#define TRANSPORT_FLAG_PASSTHROUGH_PGR          0x4
 
 struct request_queue;
 struct scatterlist;
index ccfad0e9c2cdbd68f13c809c7ed6414b2c0c97c1..0c1dce2ac6f0239a90d3e86bff2afd3b0f318128 100644 (file)
@@ -664,6 +664,7 @@ struct se_dev_attrib {
        int             pi_prot_format;
        enum target_prot_type pi_prot_type;
        enum target_prot_type hw_pi_prot_type;
+       int             pi_prot_verify;
        int             enforce_pr_isids;
        int             force_pr_aptpl;
        int             is_nonrot;
index a3c3cab643a9528dd5f8ad50dfac29b53384f1db..e37973526153a83c2d96169b77e507525c53cc53 100644 (file)
@@ -12,6 +12,7 @@ struct btrfs_root;
 struct btrfs_fs_info;
 struct btrfs_inode;
 struct extent_map;
+struct btrfs_file_extent_item;
 struct btrfs_ordered_extent;
 struct btrfs_delayed_ref_node;
 struct btrfs_delayed_tree_ref;
@@ -24,6 +25,7 @@ struct extent_buffer;
 struct btrfs_work;
 struct __btrfs_workqueue;
 struct btrfs_qgroup_extent_record;
+struct btrfs_qgroup;
 
 #define show_ref_type(type)                                            \
        __print_symbolic(type,                                          \
@@ -54,6 +56,12 @@ struct btrfs_qgroup_extent_record;
              (obj >= BTRFS_ROOT_TREE_OBJECTID &&                       \
               obj <= BTRFS_QUOTA_TREE_OBJECTID)) ? __show_root_type(obj) : "-"
 
+#define show_fi_type(type)                                             \
+       __print_symbolic(type,                                          \
+                { BTRFS_FILE_EXTENT_INLINE,    "INLINE" },             \
+                { BTRFS_FILE_EXTENT_REG,       "REG"    },             \
+                { BTRFS_FILE_EXTENT_PREALLOC,  "PREALLOC"})
+
 #define BTRFS_GROUP_FLAGS      \
        { BTRFS_BLOCK_GROUP_DATA,       "DATA"},        \
        { BTRFS_BLOCK_GROUP_SYSTEM,     "SYSTEM"},      \
@@ -213,7 +221,7 @@ TRACE_EVENT_CONDITION(btrfs_get_extent,
                __entry->block_start    = map->block_start;
                __entry->block_len      = map->block_len;
                __entry->flags          = map->flags;
-               __entry->refs           = atomic_read(&map->refs);
+               __entry->refs           = refcount_read(&map->refs);
                __entry->compress_type  = map->compress_type;
        ),
 
@@ -232,6 +240,138 @@ TRACE_EVENT_CONDITION(btrfs_get_extent,
                  __entry->refs, __entry->compress_type)
 );
 
+/* file extent item */
+DECLARE_EVENT_CLASS(btrfs__file_extent_item_regular,
+
+       TP_PROTO(struct btrfs_inode *bi, struct extent_buffer *l,
+                struct btrfs_file_extent_item *fi, u64 start),
+
+       TP_ARGS(bi, l, fi, start),
+
+       TP_STRUCT__entry_btrfs(
+               __field(        u64,    root_obj        )
+               __field(        u64,    ino             )
+               __field(        loff_t, isize           )
+               __field(        u64,    disk_isize      )
+               __field(        u64,    num_bytes       )
+               __field(        u64,    ram_bytes       )
+               __field(        u64,    disk_bytenr     )
+               __field(        u64,    disk_num_bytes  )
+               __field(        u64,    extent_offset   )
+               __field(        u8,     extent_type     )
+               __field(        u8,     compression     )
+               __field(        u64,    extent_start    )
+               __field(        u64,    extent_end      )
+       ),
+
+       TP_fast_assign_btrfs(bi->root->fs_info,
+               __entry->root_obj       = bi->root->objectid;
+               __entry->ino            = btrfs_ino(bi);
+               __entry->isize          = bi->vfs_inode.i_size;
+               __entry->disk_isize     = bi->disk_i_size;
+               __entry->num_bytes      = btrfs_file_extent_num_bytes(l, fi);
+               __entry->ram_bytes      = btrfs_file_extent_ram_bytes(l, fi);
+               __entry->disk_bytenr    = btrfs_file_extent_disk_bytenr(l, fi);
+               __entry->disk_num_bytes = btrfs_file_extent_disk_num_bytes(l, fi);
+               __entry->extent_offset  = btrfs_file_extent_offset(l, fi);
+               __entry->extent_type    = btrfs_file_extent_type(l, fi);
+               __entry->compression    = btrfs_file_extent_compression(l, fi);
+               __entry->extent_start   = start;
+               __entry->extent_end     = (start + __entry->num_bytes);
+       ),
+
+       TP_printk_btrfs(
+               "root=%llu(%s) inode=%llu size=%llu disk_isize=%llu "
+               "file extent range=[%llu %llu] "
+               "(num_bytes=%llu ram_bytes=%llu disk_bytenr=%llu "
+               "disk_num_bytes=%llu extent_offset=%llu type=%s "
+               "compression=%u",
+               show_root_type(__entry->root_obj), __entry->ino,
+               __entry->isize,
+               __entry->disk_isize, __entry->extent_start,
+               __entry->extent_end, __entry->num_bytes, __entry->ram_bytes,
+               __entry->disk_bytenr, __entry->disk_num_bytes,
+               __entry->extent_offset, show_fi_type(__entry->extent_type),
+               __entry->compression)
+);
+
+DECLARE_EVENT_CLASS(
+       btrfs__file_extent_item_inline,
+
+       TP_PROTO(struct btrfs_inode *bi, struct extent_buffer *l,
+                struct btrfs_file_extent_item *fi, int slot, u64 start),
+
+       TP_ARGS(bi, l, fi, slot,  start),
+
+       TP_STRUCT__entry_btrfs(
+               __field(        u64,    root_obj        )
+               __field(        u64,    ino             )
+               __field(        loff_t, isize           )
+               __field(        u64,    disk_isize      )
+               __field(        u8,     extent_type     )
+               __field(        u8,     compression     )
+               __field(        u64,    extent_start    )
+               __field(        u64,    extent_end      )
+       ),
+
+       TP_fast_assign_btrfs(
+               bi->root->fs_info,
+               __entry->root_obj       = bi->root->objectid;
+               __entry->ino            = btrfs_ino(bi);
+               __entry->isize          = bi->vfs_inode.i_size;
+               __entry->disk_isize     = bi->disk_i_size;
+               __entry->extent_type    = btrfs_file_extent_type(l, fi);
+               __entry->compression    = btrfs_file_extent_compression(l, fi);
+               __entry->extent_start   = start;
+               __entry->extent_end     = (start + btrfs_file_extent_inline_len(l, slot, fi));
+       ),
+
+       TP_printk_btrfs(
+               "root=%llu(%s) inode=%llu size=%llu disk_isize=%llu "
+               "file extent range=[%llu %llu] "
+               "extent_type=%s compression=%u",
+               show_root_type(__entry->root_obj), __entry->ino, __entry->isize,
+               __entry->disk_isize, __entry->extent_start,
+               __entry->extent_end, show_fi_type(__entry->extent_type),
+               __entry->compression)
+);
+
+DEFINE_EVENT(
+       btrfs__file_extent_item_regular, btrfs_get_extent_show_fi_regular,
+
+       TP_PROTO(struct btrfs_inode *bi, struct extent_buffer *l,
+                struct btrfs_file_extent_item *fi, u64 start),
+
+       TP_ARGS(bi, l, fi, start)
+);
+
+DEFINE_EVENT(
+       btrfs__file_extent_item_regular, btrfs_truncate_show_fi_regular,
+
+       TP_PROTO(struct btrfs_inode *bi, struct extent_buffer *l,
+                struct btrfs_file_extent_item *fi, u64 start),
+
+       TP_ARGS(bi, l, fi, start)
+);
+
+DEFINE_EVENT(
+       btrfs__file_extent_item_inline, btrfs_get_extent_show_fi_inline,
+
+       TP_PROTO(struct btrfs_inode *bi, struct extent_buffer *l,
+                struct btrfs_file_extent_item *fi, int slot, u64 start),
+
+       TP_ARGS(bi, l, fi, slot, start)
+);
+
+DEFINE_EVENT(
+       btrfs__file_extent_item_inline, btrfs_truncate_show_fi_inline,
+
+       TP_PROTO(struct btrfs_inode *bi, struct extent_buffer *l,
+                struct btrfs_file_extent_item *fi, int slot, u64 start),
+
+       TP_ARGS(bi, l, fi, slot, start)
+);
+
 #define show_ordered_flags(flags)                                         \
        __print_flags(flags, "|",                                          \
                { (1 << BTRFS_ORDERED_IO_DONE),         "IO_DONE"       }, \
@@ -275,7 +415,7 @@ DECLARE_EVENT_CLASS(btrfs__ordered_extent,
                __entry->bytes_left     = ordered->bytes_left;
                __entry->flags          = ordered->flags;
                __entry->compress_type  = ordered->compress_type;
-               __entry->refs           = atomic_read(&ordered->refs);
+               __entry->refs           = refcount_read(&ordered->refs);
                __entry->root_objectid  =
                                BTRFS_I(inode)->root->root_key.objectid;
                __entry->truncated_len  = ordered->truncated_len;
@@ -1475,6 +1615,49 @@ TRACE_EVENT(qgroup_update_counters,
                  __entry->cur_new_count)
 );
 
+TRACE_EVENT(qgroup_update_reserve,
+
+       TP_PROTO(struct btrfs_fs_info *fs_info, struct btrfs_qgroup *qgroup,
+                s64 diff),
+
+       TP_ARGS(fs_info, qgroup, diff),
+
+       TP_STRUCT__entry_btrfs(
+               __field(        u64,    qgid                    )
+               __field(        u64,    cur_reserved            )
+               __field(        s64,    diff                    )
+       ),
+
+       TP_fast_assign_btrfs(fs_info,
+               __entry->qgid           = qgroup->qgroupid;
+               __entry->cur_reserved   = qgroup->reserved;
+               __entry->diff           = diff;
+       ),
+
+       TP_printk_btrfs("qgid=%llu cur_reserved=%llu diff=%lld",
+               __entry->qgid, __entry->cur_reserved, __entry->diff)
+);
+
+TRACE_EVENT(qgroup_meta_reserve,
+
+       TP_PROTO(struct btrfs_root *root, s64 diff),
+
+       TP_ARGS(root, diff),
+
+       TP_STRUCT__entry_btrfs(
+               __field(        u64,    refroot                 )
+               __field(        s64,    diff                    )
+       ),
+
+       TP_fast_assign_btrfs(root->fs_info,
+               __entry->refroot        = root->objectid;
+               __entry->diff           = diff;
+       ),
+
+       TP_printk_btrfs("refroot=%llu(%s) diff=%lld",
+               show_root_type(__entry->refroot), __entry->diff)
+);
+
 #endif /* _TRACE_BTRFS_H */
 
 /* This part must be outside protection */
index c566ddc87f73e5885841204d5ae7d160374545a6..08bb3ed18dcc213dbbdcfad0832a83a8fbb2ed4e 100644 (file)
@@ -150,6 +150,136 @@ DEFINE_EVENT(dax_pmd_insert_mapping_class, name, \
 DEFINE_PMD_INSERT_MAPPING_EVENT(dax_pmd_insert_mapping);
 DEFINE_PMD_INSERT_MAPPING_EVENT(dax_pmd_insert_mapping_fallback);
 
+DECLARE_EVENT_CLASS(dax_pte_fault_class,
+       TP_PROTO(struct inode *inode, struct vm_fault *vmf, int result),
+       TP_ARGS(inode, vmf, result),
+       TP_STRUCT__entry(
+               __field(unsigned long, ino)
+               __field(unsigned long, vm_flags)
+               __field(unsigned long, address)
+               __field(pgoff_t, pgoff)
+               __field(dev_t, dev)
+               __field(unsigned int, flags)
+               __field(int, result)
+       ),
+       TP_fast_assign(
+               __entry->dev = inode->i_sb->s_dev;
+               __entry->ino = inode->i_ino;
+               __entry->vm_flags = vmf->vma->vm_flags;
+               __entry->address = vmf->address;
+               __entry->flags = vmf->flags;
+               __entry->pgoff = vmf->pgoff;
+               __entry->result = result;
+       ),
+       TP_printk("dev %d:%d ino %#lx %s %s address %#lx pgoff %#lx %s",
+               MAJOR(__entry->dev),
+               MINOR(__entry->dev),
+               __entry->ino,
+               __entry->vm_flags & VM_SHARED ? "shared" : "private",
+               __print_flags(__entry->flags, "|", FAULT_FLAG_TRACE),
+               __entry->address,
+               __entry->pgoff,
+               __print_flags(__entry->result, "|", VM_FAULT_RESULT_TRACE)
+       )
+)
+
+#define DEFINE_PTE_FAULT_EVENT(name) \
+DEFINE_EVENT(dax_pte_fault_class, name, \
+       TP_PROTO(struct inode *inode, struct vm_fault *vmf, int result), \
+       TP_ARGS(inode, vmf, result))
+
+DEFINE_PTE_FAULT_EVENT(dax_pte_fault);
+DEFINE_PTE_FAULT_EVENT(dax_pte_fault_done);
+DEFINE_PTE_FAULT_EVENT(dax_pfn_mkwrite_no_entry);
+DEFINE_PTE_FAULT_EVENT(dax_pfn_mkwrite);
+DEFINE_PTE_FAULT_EVENT(dax_load_hole);
+
+TRACE_EVENT(dax_insert_mapping,
+       TP_PROTO(struct inode *inode, struct vm_fault *vmf, void *radix_entry),
+       TP_ARGS(inode, vmf, radix_entry),
+       TP_STRUCT__entry(
+               __field(unsigned long, ino)
+               __field(unsigned long, vm_flags)
+               __field(unsigned long, address)
+               __field(void *, radix_entry)
+               __field(dev_t, dev)
+               __field(int, write)
+       ),
+       TP_fast_assign(
+               __entry->dev = inode->i_sb->s_dev;
+               __entry->ino = inode->i_ino;
+               __entry->vm_flags = vmf->vma->vm_flags;
+               __entry->address = vmf->address;
+               __entry->write = vmf->flags & FAULT_FLAG_WRITE;
+               __entry->radix_entry = radix_entry;
+       ),
+       TP_printk("dev %d:%d ino %#lx %s %s address %#lx radix_entry %#lx",
+               MAJOR(__entry->dev),
+               MINOR(__entry->dev),
+               __entry->ino,
+               __entry->vm_flags & VM_SHARED ? "shared" : "private",
+               __entry->write ? "write" : "read",
+               __entry->address,
+               (unsigned long)__entry->radix_entry
+       )
+)
+
+DECLARE_EVENT_CLASS(dax_writeback_range_class,
+       TP_PROTO(struct inode *inode, pgoff_t start_index, pgoff_t end_index),
+       TP_ARGS(inode, start_index, end_index),
+       TP_STRUCT__entry(
+               __field(unsigned long, ino)
+               __field(pgoff_t, start_index)
+               __field(pgoff_t, end_index)
+               __field(dev_t, dev)
+       ),
+       TP_fast_assign(
+               __entry->dev = inode->i_sb->s_dev;
+               __entry->ino = inode->i_ino;
+               __entry->start_index = start_index;
+               __entry->end_index = end_index;
+       ),
+       TP_printk("dev %d:%d ino %#lx pgoff %#lx-%#lx",
+               MAJOR(__entry->dev),
+               MINOR(__entry->dev),
+               __entry->ino,
+               __entry->start_index,
+               __entry->end_index
+       )
+)
+
+#define DEFINE_WRITEBACK_RANGE_EVENT(name) \
+DEFINE_EVENT(dax_writeback_range_class, name, \
+       TP_PROTO(struct inode *inode, pgoff_t start_index, pgoff_t end_index),\
+       TP_ARGS(inode, start_index, end_index))
+
+DEFINE_WRITEBACK_RANGE_EVENT(dax_writeback_range);
+DEFINE_WRITEBACK_RANGE_EVENT(dax_writeback_range_done);
+
+TRACE_EVENT(dax_writeback_one,
+       TP_PROTO(struct inode *inode, pgoff_t pgoff, pgoff_t pglen),
+       TP_ARGS(inode, pgoff, pglen),
+       TP_STRUCT__entry(
+               __field(unsigned long, ino)
+               __field(pgoff_t, pgoff)
+               __field(pgoff_t, pglen)
+               __field(dev_t, dev)
+       ),
+       TP_fast_assign(
+               __entry->dev = inode->i_sb->s_dev;
+               __entry->ino = inode->i_ino;
+               __entry->pgoff = pgoff;
+               __entry->pglen = pglen;
+       ),
+       TP_printk("dev %d:%d ino %#lx pgoff %#lx pglen %#lx",
+               MAJOR(__entry->dev),
+               MINOR(__entry->dev),
+               __entry->ino,
+               __entry->pgoff,
+               __entry->pglen
+       )
+)
+
 #endif /* _TRACE_FS_DAX_H */
 
 /* This part must be outside protection */
index 2c7befb10f13e3b0175385e501e40ddedaab9094..99254ed89212b0036c7afecb1fcd318d6cac3b8b 100644 (file)
@@ -11,7 +11,6 @@
 #define _TRACE_IOMMU_H
 
 #include <linux/tracepoint.h>
-#include <linux/pci.h>
 
 struct device;
 
index 2b4a8ff72d0dd54647255f6f8dc5ec8b61981872..6cde5b3514c2793cbaaffd3420c7217feafbad7a 100644 (file)
@@ -151,9 +151,9 @@ TRACE_EVENT(thermal_power_cpu_limit,
 TRACE_EVENT(thermal_power_devfreq_get_power,
        TP_PROTO(struct thermal_cooling_device *cdev,
                 struct devfreq_dev_status *status, unsigned long freq,
-               u32 dynamic_power, u32 static_power),
+               u32 dynamic_power, u32 static_power, u32 power),
 
-       TP_ARGS(cdev, status,  freq, dynamic_power, static_power),
+       TP_ARGS(cdev, status,  freq, dynamic_power, static_power, power),
 
        TP_STRUCT__entry(
                __string(type,         cdev->type    )
@@ -161,6 +161,7 @@ TRACE_EVENT(thermal_power_devfreq_get_power,
                __field(u32,           load          )
                __field(u32,           dynamic_power )
                __field(u32,           static_power  )
+               __field(u32,           power)
        ),
 
        TP_fast_assign(
@@ -169,11 +170,13 @@ TRACE_EVENT(thermal_power_devfreq_get_power,
                __entry->load = (100 * status->busy_time) / status->total_time;
                __entry->dynamic_power = dynamic_power;
                __entry->static_power = static_power;
+               __entry->power = power;
        ),
 
-       TP_printk("type=%s freq=%lu load=%u dynamic_power=%u static_power=%u",
+       TP_printk("type=%s freq=%lu load=%u dynamic_power=%u static_power=%u power=%u",
                __get_str(type), __entry->freq,
-               __entry->load, __entry->dynamic_power, __entry->static_power)
+               __entry->load, __entry->dynamic_power, __entry->static_power,
+               __entry->power)
 );
 
 TRACE_EVENT(thermal_power_devfreq_limit,
diff --git a/include/uapi/Kbuild b/include/uapi/Kbuild
deleted file mode 100644 (file)
index 245aa6e..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-# UAPI Header export list
-# Top-level Makefile calls into asm-$(ARCH)
-# List only non-arch directories below
-
-
-header-y += asm-generic/
-header-y += linux/
-header-y += sound/
-header-y += mtd/
-header-y += rdma/
-header-y += video/
-header-y += drm/
-header-y += xen/
-header-y += scsi/
-header-y += misc/
diff --git a/include/uapi/asm-generic/Kbuild b/include/uapi/asm-generic/Kbuild
deleted file mode 100644 (file)
index b73de7b..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-# UAPI Header export list
-header-y += auxvec.h
-header-y += bitsperlong.h
-header-y += errno-base.h
-header-y += errno.h
-header-y += fcntl.h
-header-y += int-l64.h
-header-y += int-ll64.h
-header-y += ioctl.h
-header-y += ioctls.h
-header-y += ipcbuf.h
-header-y += kvm_para.h
-header-y += mman-common.h
-header-y += mman.h
-header-y += msgbuf.h
-header-y += param.h
-header-y += poll.h
-header-y += posix_types.h
-header-y += resource.h
-header-y += sembuf.h
-header-y += setup.h
-header-y += shmbuf.h
-header-y += shmparam.h
-header-y += siginfo.h
-header-y += signal-defs.h
-header-y += signal.h
-header-y += socket.h
-header-y += sockios.h
-header-y += stat.h
-header-y += statfs.h
-header-y += swab.h
-header-y += termbits.h
-header-y += termios.h
-header-y += types.h
-header-y += ucontext.h
-header-y += unistd.h
index fcd50b759217615088767688661c4ece3259b5cf..21381449d98a88f0b5f68942b307128a4269926a 100644 (file)
@@ -1,49 +1,33 @@
-#
-# Headers that are optional in usr/include/asm/
-#
-opt-header += kvm.h
-opt-header += kvm_para.h
-opt-header += a.out.h
-
 #
 # Headers that are mandatory in usr/include/asm/
 #
-header-y += auxvec.h
-header-y += bitsperlong.h
-header-y += byteorder.h
-header-y += errno.h
-header-y += fcntl.h
-header-y += ioctl.h
-header-y += ioctls.h
-header-y += ipcbuf.h
-header-y += mman.h
-header-y += msgbuf.h
-header-y += param.h
-header-y += poll.h
-header-y += posix_types.h
-header-y += ptrace.h
-header-y += resource.h
-header-y += sembuf.h
-header-y += setup.h
-header-y += shmbuf.h
-header-y += sigcontext.h
-header-y += siginfo.h
-header-y += signal.h
-header-y += socket.h
-header-y += sockios.h
-header-y += stat.h
-header-y += statfs.h
-header-y += swab.h
-header-y += termbits.h
-header-y += termios.h
-header-y += types.h
-header-y += unistd.h
-
-header-y += $(foreach hdr,$(opt-header), \
-             $(if \
-               $(wildcard \
-                       $(srctree)/arch/$(SRCARCH)/include/uapi/asm/$(hdr) \
-                       $(srctree)/arch/$(SRCARCH)/include/asm/$(hdr) \
-               ), \
-               $(hdr) \
-               ))
+mandatory-y += auxvec.h
+mandatory-y += bitsperlong.h
+mandatory-y += byteorder.h
+mandatory-y += errno.h
+mandatory-y += fcntl.h
+mandatory-y += ioctl.h
+mandatory-y += ioctls.h
+mandatory-y += ipcbuf.h
+mandatory-y += mman.h
+mandatory-y += msgbuf.h
+mandatory-y += param.h
+mandatory-y += poll.h
+mandatory-y += posix_types.h
+mandatory-y += ptrace.h
+mandatory-y += resource.h
+mandatory-y += sembuf.h
+mandatory-y += setup.h
+mandatory-y += shmbuf.h
+mandatory-y += sigcontext.h
+mandatory-y += siginfo.h
+mandatory-y += signal.h
+mandatory-y += socket.h
+mandatory-y += sockios.h
+mandatory-y += stat.h
+mandatory-y += statfs.h
+mandatory-y += swab.h
+mandatory-y += termbits.h
+mandatory-y += termios.h
+mandatory-y += types.h
+mandatory-y += unistd.h
diff --git a/include/uapi/drm/Kbuild b/include/uapi/drm/Kbuild
deleted file mode 100644 (file)
index c97addd..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-# UAPI Header export list
-header-y += drm.h
-header-y += drm_fourcc.h
-header-y += drm_mode.h
-header-y += drm_sarea.h
-header-y += amdgpu_drm.h
-header-y += exynos_drm.h
-header-y += i810_drm.h
-header-y += i915_drm.h
-header-y += mga_drm.h
-header-y += nouveau_drm.h
-header-y += omap_drm.h
-header-y += qxl_drm.h
-header-y += r128_drm.h
-header-y += radeon_drm.h
-header-y += savage_drm.h
-header-y += sis_drm.h
-header-y += tegra_drm.h
-header-y += via_drm.h
-header-y += vmwgfx_drm.h
-header-y += msm_drm.h
-header-y += vc4_drm.h
-header-y += virtgpu_drm.h
index 516a9f2857307fd672557e2761692fd1b9fbbbb2..6c249e5cfb09d4d74cfe7c18aea7a46208273487 100644 (file)
@@ -295,7 +295,10 @@ union drm_amdgpu_gem_wait_idle {
 };
 
 struct drm_amdgpu_wait_cs_in {
-       /** Command submission handle */
+       /* Command submission handle
+         * handle equals 0 means none to wait for
+         * handle equals ~0ull means wait for the latest sequence number
+         */
        __u64 handle;
        /** Absolute timeout to wait */
        __u64 timeout;
@@ -764,6 +767,25 @@ struct drm_amdgpu_info_device {
        __u64 cntl_sb_buf_gpu_addr;
        /* NGG Parameter Cache */
        __u64 param_buf_gpu_addr;
+       __u32 prim_buf_size;
+       __u32 pos_buf_size;
+       __u32 cntl_sb_buf_size;
+       __u32 param_buf_size;
+       /* wavefront size*/
+       __u32 wave_front_size;
+       /* shader visible vgprs*/
+       __u32 num_shader_visible_vgprs;
+       /* CU per shader array*/
+       __u32 num_cu_per_sh;
+       /* number of tcc blocks*/
+       __u32 num_tcc_blocks;
+       /* gs vgt table depth*/
+       __u32 gs_vgt_table_depth;
+       /* gs primitive buffer depth*/
+       __u32 gs_prim_buffer_depth;
+       /* max gs wavefront per vgt*/
+       __u32 max_gs_waves_per_vgt;
+       __u32 _pad1;
 };
 
 struct drm_amdgpu_info_hw_ip {
index 6b0e2758585f83b186a253c9f7b7ca492754c6d0..ca2787d9bf0f87598dc827faf40baf7e92403fba 100644 (file)
 # UAPI Header export list
-header-y += android/
-header-y += byteorder/
-header-y += can/
-header-y += caif/
-header-y += dvb/
-header-y += hdlc/
-header-y += hsi/
-header-y += iio/
-header-y += isdn/
-header-y += mmc/
-header-y += nfsd/
-header-y += raid/
-header-y += spi/
-header-y += sunrpc/
-header-y += tc_act/
-header-y += tc_ematch/
-header-y += netfilter/
-header-y += netfilter_arp/
-header-y += netfilter_bridge/
-header-y += netfilter_ipv4/
-header-y += netfilter_ipv6/
-header-y += usb/
-header-y += wimax/
 
-genhdr-y += version.h
-
-ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/uapi/asm/a.out.h \
-                 $(srctree)/arch/$(SRCARCH)/include/asm/a.out.h),)
-header-y += a.out.h
+ifeq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/uapi/asm/a.out.h),)
+no-export-headers += a.out.h
 endif
 
-header-y += acct.h
-header-y += adb.h
-header-y += adfs_fs.h
-header-y += affs_hardblocks.h
-header-y += agpgart.h
-header-y += aio_abi.h
-header-y += am437x-vpfe.h
-header-y += apm_bios.h
-header-y += arcfb.h
-header-y += atalk.h
-header-y += atmapi.h
-header-y += atmarp.h
-header-y += atmbr2684.h
-header-y += atmclip.h
-header-y += atmdev.h
-header-y += atm_eni.h
-header-y += atm.h
-header-y += atm_he.h
-header-y += atm_idt77105.h
-header-y += atmioc.h
-header-y += atmlec.h
-header-y += atmmpc.h
-header-y += atm_nicstar.h
-header-y += atmppp.h
-header-y += atmsap.h
-header-y += atmsvc.h
-header-y += atm_tcp.h
-header-y += atm_zatm.h
-header-y += audit.h
-header-y += auto_fs4.h
-header-y += auto_fs.h
-header-y += auxvec.h
-header-y += ax25.h
-header-y += b1lli.h
-header-y += batman_adv.h
-header-y += baycom.h
-header-y += bcm933xx_hcs.h
-header-y += bfs_fs.h
-header-y += binfmts.h
-header-y += blkpg.h
-header-y += blktrace_api.h
-header-y += blkzoned.h
-header-y += bpf_common.h
-header-y += bpf_perf_event.h
-header-y += bpf.h
-header-y += bpqether.h
-header-y += bsg.h
-header-y += bt-bmc.h
-header-y += btrfs.h
-header-y += can.h
-header-y += capability.h
-header-y += capi.h
-header-y += cciss_defs.h
-header-y += cciss_ioctl.h
-header-y += cdrom.h
-header-y += cec.h
-header-y += cec-funcs.h
-header-y += cgroupstats.h
-header-y += chio.h
-header-y += cm4000_cs.h
-header-y += cn_proc.h
-header-y += coda.h
-header-y += coda_psdev.h
-header-y += coff.h
-header-y += connector.h
-header-y += const.h
-header-y += cramfs_fs.h
-header-y += cuda.h
-header-y += cyclades.h
-header-y += cycx_cfm.h
-header-y += dcbnl.h
-header-y += dccp.h
-header-y += devlink.h
-header-y += dlmconstants.h
-header-y += dlm_device.h
-header-y += dlm.h
-header-y += dlm_netlink.h
-header-y += dlm_plock.h
-header-y += dm-ioctl.h
-header-y += dm-log-userspace.h
-header-y += dma-buf.h
-header-y += dn.h
-header-y += dqblk_xfs.h
-header-y += edd.h
-header-y += efs_fs_sb.h
-header-y += elfcore.h
-header-y += elf-em.h
-header-y += elf-fdpic.h
-header-y += elf.h
-header-y += errno.h
-header-y += errqueue.h
-header-y += ethtool.h
-header-y += eventpoll.h
-header-y += fadvise.h
-header-y += falloc.h
-header-y += fanotify.h
-header-y += fb.h
-header-y += fcntl.h
-header-y += fd.h
-header-y += fdreg.h
-header-y += fib_rules.h
-header-y += fiemap.h
-header-y += filter.h
-header-y += firewire-cdev.h
-header-y += firewire-constants.h
-header-y += flat.h
-header-y += fou.h
-header-y += fs.h
-header-y += fsl_hypervisor.h
-header-y += fuse.h
-header-y += futex.h
-header-y += gameport.h
-header-y += genetlink.h
-header-y += gen_stats.h
-header-y += gfs2_ondisk.h
-header-y += gigaset_dev.h
-header-y += gpio.h
-header-y += gsmmux.h
-header-y += gtp.h
-header-y += hdlcdrv.h
-header-y += hdlc.h
-header-y += hdreg.h
-header-y += hiddev.h
-header-y += hid.h
-header-y += hidraw.h
-header-y += hpet.h
-header-y += hsr_netlink.h
-header-y += hyperv.h
-header-y += hysdn_if.h
-header-y += i2c-dev.h
-header-y += i2c.h
-header-y += i2o-dev.h
-header-y += i8k.h
-header-y += icmp.h
-header-y += icmpv6.h
-header-y += if_addr.h
-header-y += if_addrlabel.h
-header-y += if_alg.h
-header-y += if_arcnet.h
-header-y += if_arp.h
-header-y += if_bonding.h
-header-y += if_bridge.h
-header-y += if_cablemodem.h
-header-y += if_eql.h
-header-y += if_ether.h
-header-y += if_fc.h
-header-y += if_fddi.h
-header-y += if_frad.h
-header-y += if.h
-header-y += if_hippi.h
-header-y += if_infiniband.h
-header-y += if_link.h
-header-y += if_ltalk.h
-header-y += if_macsec.h
-header-y += if_packet.h
-header-y += if_phonet.h
-header-y += if_plip.h
-header-y += if_ppp.h
-header-y += if_pppol2tp.h
-header-y += if_pppox.h
-header-y += if_slip.h
-header-y += if_team.h
-header-y += if_tun.h
-header-y += if_tunnel.h
-header-y += if_vlan.h
-header-y += if_x25.h
-header-y += ife.h
-header-y += igmp.h
-header-y += ila.h
-header-y += in6.h
-header-y += inet_diag.h
-header-y += in.h
-header-y += inotify.h
-header-y += input.h
-header-y += input-event-codes.h
-header-y += in_route.h
-header-y += ioctl.h
-header-y += ip6_tunnel.h
-header-y += ipc.h
-header-y += ip.h
-header-y += ipmi.h
-header-y += ipmi_msgdefs.h
-header-y += ipsec.h
-header-y += ipv6.h
-header-y += ipv6_route.h
-header-y += ip_vs.h
-header-y += ipx.h
-header-y += irda.h
-header-y += irqnr.h
-header-y += isdn_divertif.h
-header-y += isdn.h
-header-y += isdnif.h
-header-y += isdn_ppp.h
-header-y += iso_fs.h
-header-y += ivtvfb.h
-header-y += ivtv.h
-header-y += ixjuser.h
-header-y += jffs2.h
-header-y += joystick.h
-header-y += kcmp.h
-header-y += kdev_t.h
-header-y += kd.h
-header-y += kernelcapi.h
-header-y += kernel.h
-header-y += kernel-page-flags.h
-header-y += kexec.h
-header-y += keyboard.h
-header-y += keyctl.h
-
-ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/uapi/asm/kvm.h \
-                 $(srctree)/arch/$(SRCARCH)/include/asm/kvm.h),)
-header-y += kvm.h
+ifeq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/uapi/asm/kvm.h),)
+no-export-headers += kvm.h
 endif
 
-
-ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/uapi/asm/kvm_para.h \
-                 $(srctree)/arch/$(SRCARCH)/include/asm/kvm_para.h),)
-header-y += kvm_para.h
+ifeq ($(wildcard $(srctree)/arch/$(SRCARCH)/include/uapi/asm/kvm_para.h),)
+no-export-headers += kvm_para.h
 endif
-
-header-y += hw_breakpoint.h
-header-y += l2tp.h
-header-y += libc-compat.h
-header-y += lirc.h
-header-y += limits.h
-header-y += llc.h
-header-y += loop.h
-header-y += lp.h
-header-y += lwtunnel.h
-header-y += magic.h
-header-y += major.h
-header-y += map_to_7segment.h
-header-y += matroxfb.h
-header-y += mdio.h
-header-y += media.h
-header-y += media-bus-format.h
-header-y += mei.h
-header-y += membarrier.h
-header-y += memfd.h
-header-y += mempolicy.h
-header-y += meye.h
-header-y += mic_common.h
-header-y += mic_ioctl.h
-header-y += mii.h
-header-y += minix_fs.h
-header-y += mman.h
-header-y += mmtimer.h
-header-y += mpls.h
-header-y += mpls_iptunnel.h
-header-y += mqueue.h
-header-y += mroute6.h
-header-y += mroute.h
-header-y += msdos_fs.h
-header-y += msg.h
-header-y += mtio.h
-header-y += nbd.h
-header-y += ncp_fs.h
-header-y += ncp.h
-header-y += ncp_mount.h
-header-y += ncp_no.h
-header-y += ndctl.h
-header-y += neighbour.h
-header-y += netconf.h
-header-y += netdevice.h
-header-y += net_dropmon.h
-header-y += netfilter_arp.h
-header-y += netfilter_bridge.h
-header-y += netfilter_decnet.h
-header-y += netfilter.h
-header-y += netfilter_ipv4.h
-header-y += netfilter_ipv6.h
-header-y += net.h
-header-y += netlink_diag.h
-header-y += netlink.h
-header-y += netrom.h
-header-y += net_namespace.h
-header-y += net_tstamp.h
-header-y += nfc.h
-header-y += psample.h
-header-y += nfs2.h
-header-y += nfs3.h
-header-y += nfs4.h
-header-y += nfs4_mount.h
-header-y += nfsacl.h
-header-y += nfs_fs.h
-header-y += nfs.h
-header-y += nfs_idmap.h
-header-y += nfs_mount.h
-header-y += nl80211.h
-header-y += n_r3964.h
-header-y += nubus.h
-header-y += nvme_ioctl.h
-header-y += nvram.h
-header-y += omap3isp.h
-header-y += omapfb.h
-header-y += oom.h
-header-y += openvswitch.h
-header-y += packet_diag.h
-header-y += param.h
-header-y += parport.h
-header-y += patchkey.h
-header-y += pci.h
-header-y += pci_regs.h
-header-y += perf_event.h
-header-y += personality.h
-header-y += pfkeyv2.h
-header-y += pg.h
-header-y += phantom.h
-header-y += phonet.h
-header-y += pktcdvd.h
-header-y += pkt_cls.h
-header-y += pkt_sched.h
-header-y += pmu.h
-header-y += poll.h
-header-y += posix_acl.h
-header-y += posix_acl_xattr.h
-header-y += posix_types.h
-header-y += ppdev.h
-header-y += ppp-comp.h
-header-y += ppp_defs.h
-header-y += ppp-ioctl.h
-header-y += pps.h
-header-y += prctl.h
-header-y += psci.h
-header-y += ptp_clock.h
-header-y += ptrace.h
-header-y += qnx4_fs.h
-header-y += qnxtypes.h
-header-y += quota.h
-header-y += radeonfb.h
-header-y += random.h
-header-y += raw.h
-header-y += rds.h
-header-y += reboot.h
-header-y += reiserfs_fs.h
-header-y += reiserfs_xattr.h
-header-y += resource.h
-header-y += rfkill.h
-header-y += rio_cm_cdev.h
-header-y += rio_mport_cdev.h
-header-y += romfs_fs.h
-header-y += rose.h
-header-y += route.h
-header-y += rtc.h
-header-y += rtnetlink.h
-header-y += scc.h
-header-y += sched.h
-header-y += scif_ioctl.h
-header-y += screen_info.h
-header-y += sctp.h
-header-y += sdla.h
-header-y += seccomp.h
-header-y += securebits.h
-header-y += seg6_genl.h
-header-y += seg6.h
-header-y += seg6_hmac.h
-header-y += seg6_iptunnel.h
-header-y += selinux_netlink.h
-header-y += sem.h
-header-y += serial_core.h
-header-y += serial.h
-header-y += serial_reg.h
-header-y += serio.h
-header-y += shm.h
-header-y += signalfd.h
-header-y += signal.h
-header-y += smiapp.h
-header-y += snmp.h
-header-y += sock_diag.h
-header-y += socket.h
-header-y += sockios.h
-header-y += sonet.h
-header-y += sonypi.h
-header-y += soundcard.h
-header-y += sound.h
-header-y += stat.h
-header-y += stddef.h
-header-y += string.h
-header-y += suspend_ioctls.h
-header-y += swab.h
-header-y += synclink.h
-header-y += sync_file.h
-header-y += sysctl.h
-header-y += sysinfo.h
-header-y += target_core_user.h
-header-y += taskstats.h
-header-y += tcp.h
-header-y += tcp_metrics.h
-header-y += telephony.h
-header-y += termios.h
-header-y += thermal.h
-header-y += time.h
-header-y += timerfd.h
-header-y += times.h
-header-y += timex.h
-header-y += tiocl.h
-header-y += tipc_config.h
-header-y += tipc_netlink.h
-header-y += tipc.h
-header-y += toshiba.h
-header-y += tty_flags.h
-header-y += tty.h
-header-y += types.h
-header-y += udf_fs_i.h
-header-y += udp.h
-header-y += uhid.h
-header-y += uinput.h
-header-y += uio.h
-header-y += uleds.h
-header-y += ultrasound.h
-header-y += un.h
-header-y += unistd.h
-header-y += unix_diag.h
-header-y += usbdevice_fs.h
-header-y += usbip.h
-header-y += userio.h
-header-y += utime.h
-header-y += utsname.h
-header-y += uuid.h
-header-y += uvcvideo.h
-header-y += v4l2-common.h
-header-y += v4l2-controls.h
-header-y += v4l2-dv-timings.h
-header-y += v4l2-mediabus.h
-header-y += v4l2-subdev.h
-header-y += veth.h
-header-y += vfio.h
-header-y += vhost.h
-header-y += videodev2.h
-header-y += virtio_9p.h
-header-y += virtio_balloon.h
-header-y += virtio_blk.h
-header-y += virtio_config.h
-header-y += virtio_console.h
-header-y += virtio_gpu.h
-header-y += virtio_ids.h
-header-y += virtio_input.h
-header-y += virtio_mmio.h
-header-y += virtio_net.h
-header-y += virtio_pci.h
-header-y += virtio_ring.h
-header-y += virtio_rng.h
-header-y += virtio_scsi.h
-header-y += virtio_types.h
-header-y += virtio_vsock.h
-header-y += virtio_crypto.h
-header-y += vm_sockets.h
-header-y += vsockmon.h
-header-y += vt.h
-header-y += vtpm_proxy.h
-header-y += wait.h
-header-y += wanrouter.h
-header-y += watchdog.h
-header-y += wimax.h
-header-y += wireless.h
-header-y += x25.h
-header-y += xattr.h
-header-y += xfrm.h
-header-y += xilinx-v4l2-controls.h
-header-y += zorro.h
-header-y += zorro_ids.h
-header-y += userfaultfd.h
diff --git a/include/uapi/linux/android/Kbuild b/include/uapi/linux/android/Kbuild
deleted file mode 100644 (file)
index ca011ee..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-# UAPI Header export list
-header-y += binder.h
index 22b6ad31c706dae59544286faea5808d7b303342..e3bb0635e94ae238481fece501d33b9b6c0ed937 100644 (file)
@@ -5,7 +5,7 @@
  * Bcache on disk data structures
  */
 
-#include <asm/types.h>
+#include <linux/types.h>
 
 #define BITMASK(name, type, field, offset, size)               \
 static inline __u64 name(const type *k)                                \
index 945a1f5f63c546c5521da5254a80664344ebd0ad..94dfa9def355f7f52805bba5ade3a32c304f989a 100644 (file)
@@ -132,6 +132,13 @@ enum bpf_attach_type {
  */
 #define BPF_F_ALLOW_OVERRIDE   (1U << 0)
 
+/* If BPF_F_STRICT_ALIGNMENT is used in BPF_PROG_LOAD command, the
+ * verifier will perform strict alignment checking as if the kernel
+ * has been built with CONFIG_EFFICIENT_UNALIGNED_ACCESS not set,
+ * and NET_IP_ALIGN defined to 2.
+ */
+#define BPF_F_STRICT_ALIGNMENT (1U << 0)
+
 #define BPF_PSEUDO_MAP_FD      1
 
 /* flags for BPF_MAP_UPDATE_ELEM command */
@@ -177,6 +184,7 @@ union bpf_attr {
                __u32           log_size;       /* size of user buffer */
                __aligned_u64   log_buf;        /* user supplied buffer */
                __u32           kern_version;   /* checked when prog_type=kprobe */
+               __u32           prog_flags;
        };
 
        struct { /* anonymous struct used by BPF_OBJ_* commands */
index dcfc3a5a9cb1d20f29bbac00c6ef315006e9d208..a456e5309238bbd78466abee16a0da6ab0248e50 100644 (file)
@@ -291,10 +291,10 @@ struct btrfs_ioctl_feature_flags {
 struct btrfs_balance_args {
        __u64 profiles;
        union {
-               __le64 usage;
+               __u64 usage;
                struct {
-                       __le32 usage_min;
-                       __le32 usage_max;
+                       __u32 usage_min;
+                       __u32 usage_max;
                };
        };
        __u64 devid;
@@ -324,8 +324,8 @@ struct btrfs_balance_args {
         * Process chunks that cross stripes_min..stripes_max devices,
         * BTRFS_BALANCE_ARGS_STRIPES_RANGE
         */
-       __le32 stripes_min;
-       __le32 stripes_max;
+       __u32 stripes_min;
+       __u32 stripes_max;
 
        __u64 unused[6];
 } __attribute__ ((__packed__));
index d5ad15a106a707c13fa77c5733ea96b8e750a5c8..10689e1fdf11d1e232bb3e9dc572a693542dd7b3 100644 (file)
@@ -1,6 +1,9 @@
 #ifndef _BTRFS_CTREE_H_
 #define _BTRFS_CTREE_H_
 
+#include <linux/btrfs.h>
+#include <linux/types.h>
+
 /*
  * This header contains the structure definitions and constants used
  * by file system objects that can be retrieved using
diff --git a/include/uapi/linux/byteorder/Kbuild b/include/uapi/linux/byteorder/Kbuild
deleted file mode 100644 (file)
index 619225b..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# UAPI Header export list
-header-y += big_endian.h
-header-y += little_endian.h
diff --git a/include/uapi/linux/caif/Kbuild b/include/uapi/linux/caif/Kbuild
deleted file mode 100644 (file)
index 4339661..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# UAPI Header export list
-header-y += caif_socket.h
-header-y += if_caif.h
diff --git a/include/uapi/linux/can/Kbuild b/include/uapi/linux/can/Kbuild
deleted file mode 100644 (file)
index 21c91bf..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# UAPI Header export list
-header-y += bcm.h
-header-y += error.h
-header-y += gw.h
-header-y += netlink.h
-header-y += raw.h
index b4def5c630e7552cf188280add26ebd16b367b4f..fdcbb3c29083bb58531f8992bbdd47d5fa0fc23b 100644 (file)
@@ -18,6 +18,8 @@
  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#include <linux/types.h>
+
 /* Netlink configuration messages.  */
 enum {
        CRYPTO_MSG_BASE = 0x10,
diff --git a/include/uapi/linux/dvb/Kbuild b/include/uapi/linux/dvb/Kbuild
deleted file mode 100644 (file)
index d40942c..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-# UAPI Header export list
-header-y += audio.h
-header-y += ca.h
-header-y += dmx.h
-header-y += frontend.h
-header-y += net.h
-header-y += osd.h
-header-y += version.h
-header-y += video.h
index 176b6cb1008dcd53615defd63d3930963107c2d0..b5280db9ef6a8c27f92ee89ffd0432df525e5039 100644 (file)
@@ -419,7 +419,7 @@ typedef struct elf64_shdr {
 #define NT_METAG_CBUF  0x500           /* Metag catch buffer registers */
 #define NT_METAG_RPIPE 0x501           /* Metag read pipeline state */
 #define NT_METAG_TLS   0x502           /* Metag TLS pointer */
-
+#define NT_ARC_V2      0x600           /* ARCv2 accumulator/extra registers */
 
 /* Note header in a PT_NOTE section */
 typedef struct elf32_note {
index 5f4ea28eabe4bf65dcd7f2a5501cf89a7e1c5760..d179d7767f519829a50395f47749360f88cd3d2d 100644 (file)
@@ -1494,6 +1494,7 @@ enum ethtool_link_mode_bit_indices {
 #define SPEED_2500             2500
 #define SPEED_5000             5000
 #define SPEED_10000            10000
+#define SPEED_14000            14000
 #define SPEED_20000            20000
 #define SPEED_25000            25000
 #define SPEED_40000            40000
diff --git a/include/uapi/linux/hdlc/Kbuild b/include/uapi/linux/hdlc/Kbuild
deleted file mode 100644 (file)
index 8c1d2cb..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-# UAPI Header export list
-header-y += ioctl.h
diff --git a/include/uapi/linux/hsi/Kbuild b/include/uapi/linux/hsi/Kbuild
deleted file mode 100644 (file)
index a16a005..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-# UAPI Header export list
-header-y += hsi_char.h cs-protocol.h
index 8e56ac70e0d1a3536a43aff83370e5b3bd5bb0b4..15ac20382ababeecafe2a336aa59a45e50d879e6 100644 (file)
@@ -888,9 +888,18 @@ enum {
 /* XDP section */
 
 #define XDP_FLAGS_UPDATE_IF_NOEXIST    (1U << 0)
-#define XDP_FLAGS_SKB_MODE             (2U << 0)
+#define XDP_FLAGS_SKB_MODE             (1U << 1)
+#define XDP_FLAGS_DRV_MODE             (1U << 2)
 #define XDP_FLAGS_MASK                 (XDP_FLAGS_UPDATE_IF_NOEXIST | \
-                                        XDP_FLAGS_SKB_MODE)
+                                        XDP_FLAGS_SKB_MODE | \
+                                        XDP_FLAGS_DRV_MODE)
+
+/* These are stored into IFLA_XDP_ATTACHED on dump. */
+enum {
+       XDP_ATTACHED_NONE = 0,
+       XDP_ATTACHED_DRV,
+       XDP_ATTACHED_SKB,
+};
 
 enum {
        IFLA_XDP_UNSPEC,
diff --git a/include/uapi/linux/iio/Kbuild b/include/uapi/linux/iio/Kbuild
deleted file mode 100644 (file)
index 86f76d8..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# UAPI Header export list
-header-y += events.h
-header-y += types.h
index 7b26a62e570734219a9a493c75c9abb909ceef1a..b9095a27a08a55fdf2e029178e1ce472637bd877 100644 (file)
@@ -355,7 +355,7 @@ struct ipmi_cmdspec {
 #define IPMICTL_REGISTER_FOR_CMD       _IOR(IPMI_IOC_MAGIC, 14,        \
                                             struct ipmi_cmdspec)
 /*
- * Unregister a regsitered command.  error values:
+ * Unregister a registered command.  error values:
  *  - EFAULT - an address supplied was invalid.
  *  - ENOENT - The netfn/cmd was not found registered for this user.
  */
diff --git a/include/uapi/linux/isdn/Kbuild b/include/uapi/linux/isdn/Kbuild
deleted file mode 100644 (file)
index 89e5285..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-# UAPI Header export list
-header-y += capicmd.h
diff --git a/include/uapi/linux/mmc/Kbuild b/include/uapi/linux/mmc/Kbuild
deleted file mode 100644 (file)
index 8c1d2cb..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-# UAPI Header export list
-header-y += ioctl.h
diff --git a/include/uapi/linux/netfilter/Kbuild b/include/uapi/linux/netfilter/Kbuild
deleted file mode 100644 (file)
index 03f194a..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-# UAPI Header export list
-header-y += ipset/
-header-y += nf_conntrack_common.h
-header-y += nf_conntrack_ftp.h
-header-y += nf_conntrack_sctp.h
-header-y += nf_conntrack_tcp.h
-header-y += nf_conntrack_tuple_common.h
-header-y += nf_log.h
-header-y += nf_tables.h
-header-y += nf_tables_compat.h
-header-y += nf_nat.h
-header-y += nfnetlink.h
-header-y += nfnetlink_acct.h
-header-y += nfnetlink_compat.h
-header-y += nfnetlink_conntrack.h
-header-y += nfnetlink_cthelper.h
-header-y += nfnetlink_cttimeout.h
-header-y += nfnetlink_log.h
-header-y += nfnetlink_queue.h
-header-y += x_tables.h
-header-y += xt_AUDIT.h
-header-y += xt_CHECKSUM.h
-header-y += xt_CLASSIFY.h
-header-y += xt_CONNMARK.h
-header-y += xt_CONNSECMARK.h
-header-y += xt_CT.h
-header-y += xt_DSCP.h
-header-y += xt_HMARK.h
-header-y += xt_IDLETIMER.h
-header-y += xt_LED.h
-header-y += xt_LOG.h
-header-y += xt_MARK.h
-header-y += xt_NFLOG.h
-header-y += xt_NFQUEUE.h
-header-y += xt_RATEEST.h
-header-y += xt_SECMARK.h
-header-y += xt_SYNPROXY.h
-header-y += xt_TCPMSS.h
-header-y += xt_TCPOPTSTRIP.h
-header-y += xt_TEE.h
-header-y += xt_TPROXY.h
-header-y += xt_addrtype.h
-header-y += xt_bpf.h
-header-y += xt_cgroup.h
-header-y += xt_cluster.h
-header-y += xt_comment.h
-header-y += xt_connbytes.h
-header-y += xt_connlabel.h
-header-y += xt_connlimit.h
-header-y += xt_connmark.h
-header-y += xt_conntrack.h
-header-y += xt_cpu.h
-header-y += xt_dccp.h
-header-y += xt_devgroup.h
-header-y += xt_dscp.h
-header-y += xt_ecn.h
-header-y += xt_esp.h
-header-y += xt_hashlimit.h
-header-y += xt_helper.h
-header-y += xt_ipcomp.h
-header-y += xt_iprange.h
-header-y += xt_ipvs.h
-header-y += xt_l2tp.h
-header-y += xt_length.h
-header-y += xt_limit.h
-header-y += xt_mac.h
-header-y += xt_mark.h
-header-y += xt_multiport.h
-header-y += xt_nfacct.h
-header-y += xt_osf.h
-header-y += xt_owner.h
-header-y += xt_physdev.h
-header-y += xt_pkttype.h
-header-y += xt_policy.h
-header-y += xt_quota.h
-header-y += xt_rateest.h
-header-y += xt_realm.h
-header-y += xt_recent.h
-header-y += xt_rpfilter.h
-header-y += xt_sctp.h
-header-y += xt_set.h
-header-y += xt_socket.h
-header-y += xt_state.h
-header-y += xt_statistic.h
-header-y += xt_string.h
-header-y += xt_tcpmss.h
-header-y += xt_tcpudp.h
-header-y += xt_time.h
-header-y += xt_u32.h
diff --git a/include/uapi/linux/netfilter/ipset/Kbuild b/include/uapi/linux/netfilter/ipset/Kbuild
deleted file mode 100644 (file)
index d268042..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-# UAPI Header export list
-header-y += ip_set.h
-header-y += ip_set_bitmap.h
-header-y += ip_set_hash.h
-header-y += ip_set_list.h
diff --git a/include/uapi/linux/netfilter_arp/Kbuild b/include/uapi/linux/netfilter_arp/Kbuild
deleted file mode 100644 (file)
index 62d5637..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# UAPI Header export list
-header-y += arp_tables.h
-header-y += arpt_mangle.h
diff --git a/include/uapi/linux/netfilter_bridge/Kbuild b/include/uapi/linux/netfilter_bridge/Kbuild
deleted file mode 100644 (file)
index 0fbad8e..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-# UAPI Header export list
-header-y += ebt_802_3.h
-header-y += ebt_among.h
-header-y += ebt_arp.h
-header-y += ebt_arpreply.h
-header-y += ebt_ip.h
-header-y += ebt_ip6.h
-header-y += ebt_limit.h
-header-y += ebt_log.h
-header-y += ebt_mark_m.h
-header-y += ebt_mark_t.h
-header-y += ebt_nat.h
-header-y += ebt_nflog.h
-header-y += ebt_pkttype.h
-header-y += ebt_redirect.h
-header-y += ebt_stp.h
-header-y += ebt_vlan.h
-header-y += ebtables.h
diff --git a/include/uapi/linux/netfilter_ipv4/Kbuild b/include/uapi/linux/netfilter_ipv4/Kbuild
deleted file mode 100644 (file)
index ecb291d..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-# UAPI Header export list
-header-y += ip_tables.h
-header-y += ipt_CLUSTERIP.h
-header-y += ipt_ECN.h
-header-y += ipt_LOG.h
-header-y += ipt_REJECT.h
-header-y += ipt_TTL.h
-header-y += ipt_ah.h
-header-y += ipt_ecn.h
-header-y += ipt_ttl.h
diff --git a/include/uapi/linux/netfilter_ipv6/Kbuild b/include/uapi/linux/netfilter_ipv6/Kbuild
deleted file mode 100644 (file)
index 75a668c..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-# UAPI Header export list
-header-y += ip6_tables.h
-header-y += ip6t_HL.h
-header-y += ip6t_LOG.h
-header-y += ip6t_NPT.h
-header-y += ip6t_REJECT.h
-header-y += ip6t_ah.h
-header-y += ip6t_frag.h
-header-y += ip6t_hl.h
-header-y += ip6t_ipv6header.h
-header-y += ip6t_mh.h
-header-y += ip6t_opts.h
-header-y += ip6t_rt.h
diff --git a/include/uapi/linux/nfsd/Kbuild b/include/uapi/linux/nfsd/Kbuild
deleted file mode 100644 (file)
index c11bc40..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# UAPI Header export list
-header-y += cld.h
-header-y += debug.h
-header-y += export.h
-header-y += nfsfh.h
-header-y += stats.h
index f14a9ab06f1f705677a797883bf26a431f1b9c65..ec260274be0ced9fd057cb2d3f78c9c7b6b622e9 100644 (file)
@@ -22,6 +22,8 @@
 #ifndef _NFSD_CLD_H
 #define _NFSD_CLD_H
 
+#include <linux/types.h>
+
 /* latest upcall version available */
 #define CLD_UPCALL_VERSION 1
 
@@ -37,18 +39,18 @@ enum cld_command {
 
 /* representation of long-form NFSv4 client ID */
 struct cld_name {
-       uint16_t        cn_len;                         /* length of cm_id */
+       __u16           cn_len;                         /* length of cm_id */
        unsigned char   cn_id[NFS4_OPAQUE_LIMIT];       /* client-provided */
 } __attribute__((packed));
 
 /* message struct for communication with userspace */
 struct cld_msg {
-       uint8_t         cm_vers;                /* upcall version */
-       uint8_t         cm_cmd;                 /* upcall command */
-       int16_t         cm_status;              /* return code */
-       uint32_t        cm_xid;                 /* transaction id */
+       __u8            cm_vers;                /* upcall version */
+       __u8            cm_cmd;                 /* upcall command */
+       __s16           cm_status;              /* return code */
+       __u32           cm_xid;                 /* transaction id */
        union {
-               int64_t         cm_gracetime;   /* grace period start time */
+               __s64           cm_gracetime;   /* grace period start time */
                struct cld_name cm_name;
        } __attribute__((packed)) cm_u;
 } __attribute__((packed));
index 18a26c16bd808204c5155af45ba5686a1d8795dd..d56bb005100949516c0ab59e964bf1c135899bb2 100644 (file)
 #define PCI_SUBSYSTEM_ID       0x2e
 #define PCI_ROM_ADDRESS                0x30    /* Bits 31..11 are address, 10..1 reserved */
 #define  PCI_ROM_ADDRESS_ENABLE        0x01
-#define PCI_ROM_ADDRESS_MASK   (~0x7ffUL)
+#define PCI_ROM_ADDRESS_MASK   (~0x7ffU)
 
 #define PCI_CAPABILITY_LIST    0x34    /* Offset of first capability list entry */
 
diff --git a/include/uapi/linux/pcitest.h b/include/uapi/linux/pcitest.h
new file mode 100644 (file)
index 0000000..a6aa10c
--- /dev/null
@@ -0,0 +1,19 @@
+/**
+ * pcitest.h - PCI test uapi defines
+ *
+ * Copyright (C) 2017 Texas Instruments
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ */
+
+#ifndef __UAPI_LINUX_PCITEST_H
+#define __UAPI_LINUX_PCITEST_H
+
+#define PCITEST_BAR            _IO('P', 0x1)
+#define PCITEST_LEGACY_IRQ     _IO('P', 0x2)
+#define PCITEST_MSI            _IOW('P', 0x3, int)
+#define PCITEST_WRITE          _IOW('P', 0x4, unsigned long)
+#define PCITEST_READ           _IOW('P', 0x5, unsigned long)
+#define PCITEST_COPY           _IOW('P', 0x6, unsigned long)
+
+#endif /* __UAPI_LINUX_PCITEST_H */
index 57d7c0f916b6f8307d318bb2f949da7723ae0cf8..645ef3cf3dd08a7d0494cfb509a30c42c3b053c2 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef _UAPI_PR_H
 #define _UAPI_PR_H
 
+#include <linux/types.h>
+
 enum pr_type {
        PR_WRITE_EXCLUSIVE              = 1,
        PR_EXCLUSIVE_ACCESS             = 2,
index 66c0748d26e2b3e9412424bad66011b23ec0f876..9d76c566f66e83b67d4abdc295731031e2362377 100644 (file)
@@ -2,6 +2,7 @@
 #define _LINUX_QRTR_H
 
 #include <linux/socket.h>
+#include <linux/types.h>
 
 struct sockaddr_qrtr {
        __kernel_sa_family_t sq_family;
diff --git a/include/uapi/linux/raid/Kbuild b/include/uapi/linux/raid/Kbuild
deleted file mode 100644 (file)
index e2c3d25..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# UAPI Header export list
-header-y += md_p.h
-header-y += md_u.h
index 0063919fea344664ee657913ffdb1a49c9158a25..87712bfaa9dd00d431cbc1953da0462a52d7e119 100644 (file)
@@ -3,7 +3,7 @@
 
 #include <linux/types.h>
 #include <linux/inet_diag.h>
-#include <rdma/ib_verbs.h>
+#include <rdma/ib_user_verbs.h>
 
 /* Request structure */
 struct smc_diag_req {
diff --git a/include/uapi/linux/spi/Kbuild b/include/uapi/linux/spi/Kbuild
deleted file mode 100644 (file)
index 0cc747e..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-# UAPI Header export list
-header-y += spidev.h
diff --git a/include/uapi/linux/sunrpc/Kbuild b/include/uapi/linux/sunrpc/Kbuild
deleted file mode 100644 (file)
index 8e02e47..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-# UAPI Header export list
-header-y += debug.h
diff --git a/include/uapi/linux/switchtec_ioctl.h b/include/uapi/linux/switchtec_ioctl.h
new file mode 100644 (file)
index 0000000..3e824e1
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Microsemi Switchtec PCIe Driver
+ * Copyright (c) 2017, Microsemi Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ */
+
+#ifndef _UAPI_LINUX_SWITCHTEC_IOCTL_H
+#define _UAPI_LINUX_SWITCHTEC_IOCTL_H
+
+#include <linux/types.h>
+
+#define SWITCHTEC_IOCTL_PART_CFG0      0
+#define SWITCHTEC_IOCTL_PART_CFG1      1
+#define SWITCHTEC_IOCTL_PART_IMG0      2
+#define SWITCHTEC_IOCTL_PART_IMG1      3
+#define SWITCHTEC_IOCTL_PART_NVLOG     4
+#define SWITCHTEC_IOCTL_PART_VENDOR0   5
+#define SWITCHTEC_IOCTL_PART_VENDOR1   6
+#define SWITCHTEC_IOCTL_PART_VENDOR2   7
+#define SWITCHTEC_IOCTL_PART_VENDOR3   8
+#define SWITCHTEC_IOCTL_PART_VENDOR4   9
+#define SWITCHTEC_IOCTL_PART_VENDOR5   10
+#define SWITCHTEC_IOCTL_PART_VENDOR6   11
+#define SWITCHTEC_IOCTL_PART_VENDOR7   12
+#define SWITCHTEC_IOCTL_NUM_PARTITIONS 13
+
+struct switchtec_ioctl_flash_info {
+       __u64 flash_length;
+       __u32 num_partitions;
+       __u32 padding;
+};
+
+struct switchtec_ioctl_flash_part_info {
+       __u32 flash_partition;
+       __u32 address;
+       __u32 length;
+       __u32 active;
+};
+
+struct switchtec_ioctl_event_summary {
+       __u64 global;
+       __u64 part_bitmap;
+       __u32 local_part;
+       __u32 padding;
+       __u32 part[48];
+       __u32 pff[48];
+};
+
+#define SWITCHTEC_IOCTL_EVENT_STACK_ERROR              0
+#define SWITCHTEC_IOCTL_EVENT_PPU_ERROR                        1
+#define SWITCHTEC_IOCTL_EVENT_ISP_ERROR                        2
+#define SWITCHTEC_IOCTL_EVENT_SYS_RESET                        3
+#define SWITCHTEC_IOCTL_EVENT_FW_EXC                   4
+#define SWITCHTEC_IOCTL_EVENT_FW_NMI                   5
+#define SWITCHTEC_IOCTL_EVENT_FW_NON_FATAL             6
+#define SWITCHTEC_IOCTL_EVENT_FW_FATAL                 7
+#define SWITCHTEC_IOCTL_EVENT_TWI_MRPC_COMP            8
+#define SWITCHTEC_IOCTL_EVENT_TWI_MRPC_COMP_ASYNC      9
+#define SWITCHTEC_IOCTL_EVENT_CLI_MRPC_COMP            10
+#define SWITCHTEC_IOCTL_EVENT_CLI_MRPC_COMP_ASYNC      11
+#define SWITCHTEC_IOCTL_EVENT_GPIO_INT                 12
+#define SWITCHTEC_IOCTL_EVENT_PART_RESET               13
+#define SWITCHTEC_IOCTL_EVENT_MRPC_COMP                        14
+#define SWITCHTEC_IOCTL_EVENT_MRPC_COMP_ASYNC          15
+#define SWITCHTEC_IOCTL_EVENT_DYN_PART_BIND_COMP       16
+#define SWITCHTEC_IOCTL_EVENT_AER_IN_P2P               17
+#define SWITCHTEC_IOCTL_EVENT_AER_IN_VEP               18
+#define SWITCHTEC_IOCTL_EVENT_DPC                      19
+#define SWITCHTEC_IOCTL_EVENT_CTS                      20
+#define SWITCHTEC_IOCTL_EVENT_HOTPLUG                  21
+#define SWITCHTEC_IOCTL_EVENT_IER                      22
+#define SWITCHTEC_IOCTL_EVENT_THRESH                   23
+#define SWITCHTEC_IOCTL_EVENT_POWER_MGMT               24
+#define SWITCHTEC_IOCTL_EVENT_TLP_THROTTLING           25
+#define SWITCHTEC_IOCTL_EVENT_FORCE_SPEED              26
+#define SWITCHTEC_IOCTL_EVENT_CREDIT_TIMEOUT           27
+#define SWITCHTEC_IOCTL_EVENT_LINK_STATE               28
+#define SWITCHTEC_IOCTL_MAX_EVENTS                     29
+
+#define SWITCHTEC_IOCTL_EVENT_LOCAL_PART_IDX -1
+#define SWITCHTEC_IOCTL_EVENT_IDX_ALL -2
+
+#define SWITCHTEC_IOCTL_EVENT_FLAG_CLEAR     (1 << 0)
+#define SWITCHTEC_IOCTL_EVENT_FLAG_EN_POLL   (1 << 1)
+#define SWITCHTEC_IOCTL_EVENT_FLAG_EN_LOG    (1 << 2)
+#define SWITCHTEC_IOCTL_EVENT_FLAG_EN_CLI    (1 << 3)
+#define SWITCHTEC_IOCTL_EVENT_FLAG_EN_FATAL  (1 << 4)
+#define SWITCHTEC_IOCTL_EVENT_FLAG_DIS_POLL  (1 << 5)
+#define SWITCHTEC_IOCTL_EVENT_FLAG_DIS_LOG   (1 << 6)
+#define SWITCHTEC_IOCTL_EVENT_FLAG_DIS_CLI   (1 << 7)
+#define SWITCHTEC_IOCTL_EVENT_FLAG_DIS_FATAL (1 << 8)
+#define SWITCHTEC_IOCTL_EVENT_FLAG_UNUSED    (~0x1ff)
+
+struct switchtec_ioctl_event_ctl {
+       __u32 event_id;
+       __s32 index;
+       __u32 flags;
+       __u32 occurred;
+       __u32 count;
+       __u32 data[5];
+};
+
+#define SWITCHTEC_IOCTL_PFF_VEP 100
+struct switchtec_ioctl_pff_port {
+       __u32 pff;
+       __u32 partition;
+       __u32 port;
+};
+
+#define SWITCHTEC_IOCTL_FLASH_INFO \
+       _IOR('W', 0x40, struct switchtec_ioctl_flash_info)
+#define SWITCHTEC_IOCTL_FLASH_PART_INFO \
+       _IOWR('W', 0x41, struct switchtec_ioctl_flash_part_info)
+#define SWITCHTEC_IOCTL_EVENT_SUMMARY \
+       _IOR('W', 0x42, struct switchtec_ioctl_event_summary)
+#define SWITCHTEC_IOCTL_EVENT_CTL \
+       _IOWR('W', 0x43, struct switchtec_ioctl_event_ctl)
+#define SWITCHTEC_IOCTL_PFF_TO_PORT \
+       _IOWR('W', 0x44, struct switchtec_ioctl_pff_port)
+#define SWITCHTEC_IOCTL_PORT_TO_PFF \
+       _IOWR('W', 0x45, struct switchtec_ioctl_pff_port)
+
+#endif
diff --git a/include/uapi/linux/tc_act/Kbuild b/include/uapi/linux/tc_act/Kbuild
deleted file mode 100644 (file)
index ba62ddf..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-# UAPI Header export list
-header-y += tc_csum.h
-header-y += tc_defact.h
-header-y += tc_gact.h
-header-y += tc_ipt.h
-header-y += tc_mirred.h
-header-y += tc_sample.h
-header-y += tc_nat.h
-header-y += tc_pedit.h
-header-y += tc_skbedit.h
-header-y += tc_vlan.h
-header-y += tc_bpf.h
-header-y += tc_connmark.h
-header-y += tc_ife.h
-header-y += tc_tunnel_key.h
-header-y += tc_skbmod.h
diff --git a/include/uapi/linux/tc_ematch/Kbuild b/include/uapi/linux/tc_ematch/Kbuild
deleted file mode 100644 (file)
index 53fca39..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-# UAPI Header export list
-header-y += tc_em_cmp.h
-header-y += tc_em_meta.h
-header-y += tc_em_nbyte.h
-header-y += tc_em_text.h
diff --git a/include/uapi/linux/tee.h b/include/uapi/linux/tee.h
new file mode 100644 (file)
index 0000000..370d884
--- /dev/null
@@ -0,0 +1,346 @@
+/*
+ * Copyright (c) 2015-2016, Linaro Limited
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __TEE_H
+#define __TEE_H
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+/*
+ * This file describes the API provided by a TEE driver to user space.
+ *
+ * Each TEE driver defines a TEE specific protocol which is used for the
+ * data passed back and forth using TEE_IOC_CMD.
+ */
+
+/* Helpers to make the ioctl defines */
+#define TEE_IOC_MAGIC  0xa4
+#define TEE_IOC_BASE   0
+
+/* Flags relating to shared memory */
+#define TEE_IOCTL_SHM_MAPPED   0x1     /* memory mapped in normal world */
+#define TEE_IOCTL_SHM_DMA_BUF  0x2     /* dma-buf handle on shared memory */
+
+#define TEE_MAX_ARG_SIZE       1024
+
+#define TEE_GEN_CAP_GP         (1 << 0)/* GlobalPlatform compliant TEE */
+
+/*
+ * TEE Implementation ID
+ */
+#define TEE_IMPL_ID_OPTEE      1
+
+/*
+ * OP-TEE specific capabilities
+ */
+#define TEE_OPTEE_CAP_TZ       (1 << 0)
+
+/**
+ * struct tee_ioctl_version_data - TEE version
+ * @impl_id:   [out] TEE implementation id
+ * @impl_caps: [out] Implementation specific capabilities
+ * @gen_caps:  [out] Generic capabilities, defined by TEE_GEN_CAPS_* above
+ *
+ * Identifies the TEE implementation, @impl_id is one of TEE_IMPL_ID_* above.
+ * @impl_caps is implementation specific, for example TEE_OPTEE_CAP_*
+ * is valid when @impl_id == TEE_IMPL_ID_OPTEE.
+ */
+struct tee_ioctl_version_data {
+       __u32 impl_id;
+       __u32 impl_caps;
+       __u32 gen_caps;
+};
+
+/**
+ * TEE_IOC_VERSION - query version of TEE
+ *
+ * Takes a tee_ioctl_version_data struct and returns with the TEE version
+ * data filled in.
+ */
+#define TEE_IOC_VERSION                _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 0, \
+                                    struct tee_ioctl_version_data)
+
+/**
+ * struct tee_ioctl_shm_alloc_data - Shared memory allocate argument
+ * @size:      [in/out] Size of shared memory to allocate
+ * @flags:     [in/out] Flags to/from allocation.
+ * @id:                [out] Identifier of the shared memory
+ *
+ * The flags field should currently be zero as input. Updated by the call
+ * with actual flags as defined by TEE_IOCTL_SHM_* above.
+ * This structure is used as argument for TEE_IOC_SHM_ALLOC below.
+ */
+struct tee_ioctl_shm_alloc_data {
+       __u64 size;
+       __u32 flags;
+       __s32 id;
+};
+
+/**
+ * TEE_IOC_SHM_ALLOC - allocate shared memory
+ *
+ * Allocates shared memory between the user space process and secure OS.
+ *
+ * Returns a file descriptor on success or < 0 on failure
+ *
+ * The returned file descriptor is used to map the shared memory into user
+ * space. The shared memory is freed when the descriptor is closed and the
+ * memory is unmapped.
+ */
+#define TEE_IOC_SHM_ALLOC      _IOWR(TEE_IOC_MAGIC, TEE_IOC_BASE + 1, \
+                                    struct tee_ioctl_shm_alloc_data)
+
+/**
+ * struct tee_ioctl_buf_data - Variable sized buffer
+ * @buf_ptr:   [in] A __user pointer to a buffer
+ * @buf_len:   [in] Length of the buffer above
+ *
+ * Used as argument for TEE_IOC_OPEN_SESSION, TEE_IOC_INVOKE,
+ * TEE_IOC_SUPPL_RECV, and TEE_IOC_SUPPL_SEND below.
+ */
+struct tee_ioctl_buf_data {
+       __u64 buf_ptr;
+       __u64 buf_len;
+};
+
+/*
+ * Attributes for struct tee_ioctl_param, selects field in the union
+ */
+#define TEE_IOCTL_PARAM_ATTR_TYPE_NONE         0       /* parameter not used */
+
+/*
+ * These defines value parameters (struct tee_ioctl_param_value)
+ */
+#define TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INPUT  1
+#define TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_OUTPUT 2
+#define TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT  3       /* input and output */
+
+/*
+ * These defines shared memory reference parameters (struct
+ * tee_ioctl_param_memref)
+ */
+#define TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT 5
+#define TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT        6
+#define TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT 7       /* input and output */
+
+/*
+ * Mask for the type part of the attribute, leaves room for more types
+ */
+#define TEE_IOCTL_PARAM_ATTR_TYPE_MASK         0xff
+
+/*
+ * Matches TEEC_LOGIN_* in GP TEE Client API
+ * Are only defined for GP compliant TEEs
+ */
+#define TEE_IOCTL_LOGIN_PUBLIC                 0
+#define TEE_IOCTL_LOGIN_USER                   1
+#define TEE_IOCTL_LOGIN_GROUP                  2
+#define TEE_IOCTL_LOGIN_APPLICATION            4
+#define TEE_IOCTL_LOGIN_USER_APPLICATION       5
+#define TEE_IOCTL_LOGIN_GROUP_APPLICATION      6
+
+/**
+ * struct tee_ioctl_param - parameter
+ * @attr: attributes
+ * @a: if a memref, offset into the shared memory object, else a value parameter
+ * @b: if a memref, size of the buffer, else a value parameter
+ * @c: if a memref, shared memory identifier, else a value parameter
+ *
+ * @attr & TEE_PARAM_ATTR_TYPE_MASK indicates if memref or value is used in
+ * the union. TEE_PARAM_ATTR_TYPE_VALUE_* indicates value and
+ * TEE_PARAM_ATTR_TYPE_MEMREF_* indicates memref. TEE_PARAM_ATTR_TYPE_NONE
+ * indicates that none of the members are used.
+ *
+ * Shared memory is allocated with TEE_IOC_SHM_ALLOC which returns an
+ * identifier representing the shared memory object. A memref can reference
+ * a part of a shared memory by specifying an offset (@a) and size (@b) of
+ * the object. To supply the entire shared memory object set the offset
+ * (@a) to 0 and size (@b) to the previously returned size of the object.
+ */
+struct tee_ioctl_param {
+       __u64 attr;
+       __u64 a;
+       __u64 b;
+       __u64 c;
+};
+
+#define TEE_IOCTL_UUID_LEN             16
+
+/**
+ * struct tee_ioctl_open_session_arg - Open session argument
+ * @uuid:      [in] UUID of the Trusted Application
+ * @clnt_uuid: [in] UUID of client
+ * @clnt_login:        [in] Login class of client, TEE_IOCTL_LOGIN_* above
+ * @cancel_id: [in] Cancellation id, a unique value to identify this request
+ * @session:   [out] Session id
+ * @ret:       [out] return value
+ * @ret_origin [out] origin of the return value
+ * @num_params [in] number of parameters following this struct
+ */
+struct tee_ioctl_open_session_arg {
+       __u8 uuid[TEE_IOCTL_UUID_LEN];
+       __u8 clnt_uuid[TEE_IOCTL_UUID_LEN];
+       __u32 clnt_login;
+       __u32 cancel_id;
+       __u32 session;
+       __u32 ret;
+       __u32 ret_origin;
+       __u32 num_params;
+       /* num_params tells the actual number of element in params */
+       struct tee_ioctl_param params[];
+};
+
+/**
+ * TEE_IOC_OPEN_SESSION - opens a session to a Trusted Application
+ *
+ * Takes a struct tee_ioctl_buf_data which contains a struct
+ * tee_ioctl_open_session_arg followed by any array of struct
+ * tee_ioctl_param
+ */
+#define TEE_IOC_OPEN_SESSION   _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 2, \
+                                    struct tee_ioctl_buf_data)
+
+/**
+ * struct tee_ioctl_invoke_func_arg - Invokes a function in a Trusted
+ * Application
+ * @func:      [in] Trusted Application function, specific to the TA
+ * @session:   [in] Session id
+ * @cancel_id: [in] Cancellation id, a unique value to identify this request
+ * @ret:       [out] return value
+ * @ret_origin [out] origin of the return value
+ * @num_params [in] number of parameters following this struct
+ */
+struct tee_ioctl_invoke_arg {
+       __u32 func;
+       __u32 session;
+       __u32 cancel_id;
+       __u32 ret;
+       __u32 ret_origin;
+       __u32 num_params;
+       /* num_params tells the actual number of element in params */
+       struct tee_ioctl_param params[];
+};
+
+/**
+ * TEE_IOC_INVOKE - Invokes a function in a Trusted Application
+ *
+ * Takes a struct tee_ioctl_buf_data which contains a struct
+ * tee_invoke_func_arg followed by any array of struct tee_param
+ */
+#define TEE_IOC_INVOKE         _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 3, \
+                                    struct tee_ioctl_buf_data)
+
+/**
+ * struct tee_ioctl_cancel_arg - Cancels an open session or invoke ioctl
+ * @cancel_id: [in] Cancellation id, a unique value to identify this request
+ * @session:   [in] Session id, if the session is opened, else set to 0
+ */
+struct tee_ioctl_cancel_arg {
+       __u32 cancel_id;
+       __u32 session;
+};
+
+/**
+ * TEE_IOC_CANCEL - Cancels an open session or invoke
+ */
+#define TEE_IOC_CANCEL         _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 4, \
+                                    struct tee_ioctl_cancel_arg)
+
+/**
+ * struct tee_ioctl_close_session_arg - Closes an open session
+ * @session:   [in] Session id
+ */
+struct tee_ioctl_close_session_arg {
+       __u32 session;
+};
+
+/**
+ * TEE_IOC_CLOSE_SESSION - Closes a session
+ */
+#define TEE_IOC_CLOSE_SESSION  _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 5, \
+                                    struct tee_ioctl_close_session_arg)
+
+/**
+ * struct tee_iocl_supp_recv_arg - Receive a request for a supplicant function
+ * @func:      [in] supplicant function
+ * @num_params [in/out] number of parameters following this struct
+ *
+ * @num_params is the number of params that tee-supplicant has room to
+ * receive when input, @num_params is the number of actual params
+ * tee-supplicant receives when output.
+ */
+struct tee_iocl_supp_recv_arg {
+       __u32 func;
+       __u32 num_params;
+       /* num_params tells the actual number of element in params */
+       struct tee_ioctl_param params[];
+};
+
+/**
+ * TEE_IOC_SUPPL_RECV - Receive a request for a supplicant function
+ *
+ * Takes a struct tee_ioctl_buf_data which contains a struct
+ * tee_iocl_supp_recv_arg followed by any array of struct tee_param
+ */
+#define TEE_IOC_SUPPL_RECV     _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 6, \
+                                    struct tee_ioctl_buf_data)
+
+/**
+ * struct tee_iocl_supp_send_arg - Send a response to a received request
+ * @ret:       [out] return value
+ * @num_params [in] number of parameters following this struct
+ */
+struct tee_iocl_supp_send_arg {
+       __u32 ret;
+       __u32 num_params;
+       /* num_params tells the actual number of element in params */
+       struct tee_ioctl_param params[];
+};
+
+/**
+ * TEE_IOC_SUPPL_SEND - Receive a request for a supplicant function
+ *
+ * Takes a struct tee_ioctl_buf_data which contains a struct
+ * tee_iocl_supp_send_arg followed by any array of struct tee_param
+ */
+#define TEE_IOC_SUPPL_SEND     _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 7, \
+                                    struct tee_ioctl_buf_data)
+
+/*
+ * Five syscalls are used when communicating with the TEE driver.
+ * open(): opens the device associated with the driver
+ * ioctl(): as described above operating on the file descriptor from open()
+ * close(): two cases
+ *   - closes the device file descriptor
+ *   - closes a file descriptor connected to allocated shared memory
+ * mmap(): maps shared memory into user space using information from struct
+ *        tee_ioctl_shm_alloc_data
+ * munmap(): unmaps previously shared memory
+ */
+
+#endif /*__TEE_H*/
diff --git a/include/uapi/linux/usb/Kbuild b/include/uapi/linux/usb/Kbuild
deleted file mode 100644 (file)
index 4cc4d6e..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-# UAPI Header export list
-header-y += audio.h
-header-y += cdc.h
-header-y += cdc-wdm.h
-header-y += ch11.h
-header-y += ch9.h
-header-y += functionfs.h
-header-y += g_printer.h
-header-y += gadgetfs.h
-header-y += midi.h
-header-y += tmc.h
-header-y += video.h
diff --git a/include/uapi/linux/wimax/Kbuild b/include/uapi/linux/wimax/Kbuild
deleted file mode 100644 (file)
index 1c97be4..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-# UAPI Header export list
-header-y += i2400m.h
diff --git a/include/uapi/misc/Kbuild b/include/uapi/misc/Kbuild
deleted file mode 100644 (file)
index e96cae7..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-# misc Header export list
-header-y += cxl.h
diff --git a/include/uapi/mtd/Kbuild b/include/uapi/mtd/Kbuild
deleted file mode 100644 (file)
index 5a691e1..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# UAPI Header export list
-header-y += inftl-user.h
-header-y += mtd-abi.h
-header-y += mtd-user.h
-header-y += nftl-user.h
-header-y += ubi-user.h
diff --git a/include/uapi/rdma/Kbuild b/include/uapi/rdma/Kbuild
deleted file mode 100644 (file)
index 1e0af1f..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-# UAPI Header export list
-header-y += ib_user_cm.h
-header-y += rdma_user_ioctl.h
-header-y += ib_user_mad.h
-header-y += ib_user_sa.h
-header-y += ib_user_verbs.h
-header-y += rdma_netlink.h
-header-y += rdma_user_cm.h
-header-y += hfi/
-header-y += rdma_user_rxe.h
-header-y += cxgb3-abi.h
-header-y += cxgb4-abi.h
-header-y += mlx4-abi.h
-header-y += mlx5-abi.h
-header-y += mthca-abi.h
-header-y += nes-abi.h
-header-y += ocrdma-abi.h
-header-y += hns-abi.h
-header-y += vmw_pvrdma-abi.h
-header-y += qedr-abi.h
index e2c8a3f0ccecb6f8cceb4a516f3927f4709d8ca0..74018bd18d7216fd0b34cc4d57d06c8138f18881 100644 (file)
@@ -39,6 +39,8 @@
 #ifndef __BNXT_RE_UVERBS_ABI_H__
 #define __BNXT_RE_UVERBS_ABI_H__
 
+#include <linux/types.h>
+
 #define BNXT_RE_ABI_VERSION    1
 
 struct bnxt_re_uctx_resp {
diff --git a/include/uapi/rdma/hfi/Kbuild b/include/uapi/rdma/hfi/Kbuild
deleted file mode 100644 (file)
index b65b0b3..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# UAPI Header export list
-header-y += hfi1_user.h
-header-y += hfi1_ioctl.h
index 477d629f539dba306abfa39fca75f52ec7a692ac..270c350bedc6c4911ff0763275fc034e90b2a018 100644 (file)
@@ -1135,4 +1135,6 @@ struct ib_uverbs_ex_destroy_rwq_ind_table  {
        __u32 ind_tbl_handle;
 };
 
+#define IB_DEVICE_NAME_MAX 64
+
 #endif /* IB_USER_VERBS_H */
diff --git a/include/uapi/scsi/Kbuild b/include/uapi/scsi/Kbuild
deleted file mode 100644 (file)
index d791e0a..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-# UAPI Header export list
-header-y += fc/
-header-y += scsi_bsg_fc.h
-header-y += scsi_netlink.h
-header-y += scsi_netlink_fc.h
-header-y += cxlflash_ioctl.h
diff --git a/include/uapi/scsi/fc/Kbuild b/include/uapi/scsi/fc/Kbuild
deleted file mode 100644 (file)
index 5ead9fa..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-# UAPI Header export list
-header-y += fc_els.h
-header-y += fc_fs.h
-header-y += fc_gs.h
-header-y += fc_ns.h
diff --git a/include/uapi/sound/Kbuild b/include/uapi/sound/Kbuild
deleted file mode 100644 (file)
index 9578d8b..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-# UAPI Header export list
-header-y += asequencer.h
-header-y += asoc.h
-header-y += asound.h
-header-y += asound_fm.h
-header-y += compress_offload.h
-header-y += compress_params.h
-header-y += emu10k1.h
-header-y += firewire.h
-header-y += hdsp.h
-header-y += hdspm.h
-header-y += sb16_csp.h
-header-y += sfnt_info.h
-header-y += tlv.h
-header-y += usb_stream.h
-header-y += snd_sst_tokens.h
diff --git a/include/uapi/video/Kbuild b/include/uapi/video/Kbuild
deleted file mode 100644 (file)
index ac7203b..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-# UAPI Header export list
-header-y += edid.h
-header-y += sisfb.h
-header-y += uvesafb.h
diff --git a/include/uapi/xen/Kbuild b/include/uapi/xen/Kbuild
deleted file mode 100644 (file)
index 5c45962..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-# UAPI Header export list
-header-y += evtchn.h
-header-y += gntalloc.h
-header-y += gntdev.h
-header-y += privcmd.h
diff --git a/include/video/Kbuild b/include/video/Kbuild
deleted file mode 100644 (file)
index e69de29..0000000
index a92f27da4a272ec873707bc4b7a68e46a4340b86..1d3475fc94967a58904627d80e8461a3721ddbb0 100644 (file)
@@ -521,11 +521,41 @@ config RCU_EXPERT
 
 config SRCU
        bool
+       default y
        help
          This option selects the sleepable version of RCU. This version
          permits arbitrary sleeping or blocking within RCU read-side critical
          sections.
 
+config CLASSIC_SRCU
+       bool "Use v4.11 classic SRCU implementation"
+       default n
+       depends on RCU_EXPERT && SRCU
+       help
+         This option selects the traditional well-tested classic SRCU
+         implementation from v4.11, as might be desired for enterprise
+         Linux distributions.  Without this option, the shiny new
+         Tiny SRCU and Tree SRCU implementations are used instead.
+         At some point, it is hoped that Tiny SRCU and Tree SRCU
+         will accumulate enough test time and confidence to allow
+         Classic SRCU to be dropped entirely.
+
+         Say Y if you need a rock-solid SRCU.
+
+         Say N if you would like help test Tree SRCU.
+
+config TINY_SRCU
+       bool
+       default y if SRCU && TINY_RCU && !CLASSIC_SRCU
+       help
+         This option selects the single-CPU non-preemptible version of SRCU.
+
+config TREE_SRCU
+       bool
+       default y if SRCU && !TINY_RCU && !CLASSIC_SRCU
+       help
+         This option selects the full-fledged version of SRCU.
+
 config TASKS_RCU
        bool
        default n
@@ -543,6 +573,9 @@ config RCU_STALL_COMMON
          the tiny variants to disable RCU CPU stall warnings, while
          making these warnings mandatory for the tree variants.
 
+config RCU_NEED_SEGCBLIST
+       def_bool ( TREE_RCU || PREEMPT_RCU || TINY_SRCU || TREE_SRCU )
+
 config CONTEXT_TRACKING
        bool
 
@@ -612,11 +645,17 @@ config RCU_FANOUT_LEAF
          initialization.  These systems tend to run CPU-bound, and thus
          are not helped by synchronized interrupts, and thus tend to
          skew them, which reduces lock contention enough that large
-         leaf-level fanouts work well.
+         leaf-level fanouts work well.  That said, setting leaf-level
+         fanout to a large number will likely cause problematic
+         lock contention on the leaf-level rcu_node structures unless
+         you boot with the skew_tick kernel parameter.
 
          Select a specific number if testing RCU itself.
 
-         Select the maximum permissible value for large systems.
+         Select the maximum permissible value for large systems, but
+         please understand that you may also need to set the skew_tick
+         kernel boot parameter to avoid contention on the rcu_node
+         structure's locks.
 
          Take the default if unsure.
 
index 067af1d9e8b620bfac146dae57d0a0f690b33475..282d65bfd6741e51c7f341c9c4fda65a492936c6 100644 (file)
@@ -19,29 +19,15 @@ static inline int create_dev(char *name, dev_t dev)
        return sys_mknod(name, S_IFBLK|0600, new_encode_dev(dev));
 }
 
-#if BITS_PER_LONG == 32
 static inline u32 bstat(char *name)
 {
-       struct stat64 stat;
-       if (sys_stat64(name, &stat) != 0)
+       struct kstat stat;
+       if (vfs_stat(name, &stat) != 0)
                return 0;
-       if (!S_ISBLK(stat.st_mode))
+       if (!S_ISBLK(stat.mode))
                return 0;
-       if (stat.st_rdev != (u32)stat.st_rdev)
-               return 0;
-       return stat.st_rdev;
-}
-#else
-static inline u32 bstat(char *name)
-{
-       struct stat stat;
-       if (sys_newstat(name, &stat) != 0)
-               return 0;
-       if (!S_ISBLK(stat.st_mode))
-               return 0;
-       return stat.st_rdev;
+       return stat.rdev;
 }
-#endif
 
 #ifdef CONFIG_BLK_DEV_RAM
 
index 8daf7ac6c7e2ca77ebc9f97c6bcabc33f186cd5b..8a532050043f5f804f06ddbf980e54965c9055de 100644 (file)
@@ -312,10 +312,10 @@ static int __init maybe_link(void)
 
 static void __init clean_path(char *path, umode_t fmode)
 {
-       struct stat st;
+       struct kstat st;
 
-       if (!sys_newlstat(path, &st) && (st.st_mode ^ fmode) & S_IFMT) {
-               if (S_ISDIR(st.st_mode))
+       if (!vfs_lstat(path, &st) && (st.mode ^ fmode) & S_IFMT) {
+               if (S_ISDIR(st.mode))
                        sys_rmdir(path);
                else
                        sys_unlink(path);
@@ -581,13 +581,13 @@ static void __init clean_rootfs(void)
        num = sys_getdents64(fd, dirp, BUF_SIZE);
        while (num > 0) {
                while (num > 0) {
-                       struct stat st;
+                       struct kstat st;
                        int ret;
 
-                       ret = sys_newlstat(dirp->d_name, &st);
+                       ret = vfs_lstat(dirp->d_name, &st);
                        WARN_ON_ONCE(ret);
                        if (!ret) {
-                               if (S_ISDIR(st.st_mode))
+                               if (S_ISDIR(st.mode))
                                        sys_rmdir(dirp->d_name);
                                else
                                        sys_unlink(dirp->d_name);
@@ -613,7 +613,7 @@ static int __init populate_rootfs(void)
        if (err)
                panic("%s", err); /* Failed to decompress INTERNAL initramfs */
        /* If available load the bootloader supplied initrd */
-       if (initrd_start) {
+       if (initrd_start && !IS_ENABLED(CONFIG_INITRAMFS_FORCE)) {
 #ifdef CONFIG_BLK_DEV_RAM
                int fd;
                printk(KERN_INFO "Trying to unpack rootfs image as initramfs...\n");
index cc48053bb39febfb6261fb337ed4a63ca018d200..f866510472d7a263f03bc21b7a158e5b288185f9 100644 (file)
@@ -27,7 +27,7 @@
 #include <linux/initrd.h>
 #include <linux/bootmem.h>
 #include <linux/acpi.h>
-#include <linux/tty.h>
+#include <linux/console.h>
 #include <linux/nmi.h>
 #include <linux/percpu.h>
 #include <linux/kmod.h>
index 481d2a9c298ab14916543a040d4f45b9b69764e0..34c4344e8d4b2f00206208f1d2c8d48e85dd0e48 100644 (file)
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -1095,11 +1095,11 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg,
              ulong *raddr, unsigned long shmlba)
 {
        struct shmid_kernel *shp;
-       unsigned long addr;
+       unsigned long addr = (unsigned long)shmaddr;
        unsigned long size;
        struct file *file;
        int    err;
-       unsigned long flags;
+       unsigned long flags = MAP_SHARED;
        unsigned long prot;
        int acc_mode;
        struct ipc_namespace *ns;
@@ -1111,7 +1111,8 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg,
        err = -EINVAL;
        if (shmid < 0)
                goto out;
-       else if ((addr = (ulong)shmaddr)) {
+
+       if (addr) {
                if (addr & (shmlba - 1)) {
                        /*
                         * Round down to the nearest multiple of shmlba.
@@ -1126,13 +1127,10 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg,
 #endif
                                        goto out;
                }
-               flags = MAP_SHARED | MAP_FIXED;
-       } else {
-               if ((shmflg & SHM_REMAP))
-                       goto out;
 
-               flags = MAP_SHARED;
-       }
+               flags |= MAP_FIXED;
+       } else if ((shmflg & SHM_REMAP))
+               goto out;
 
        if (shmflg & SHM_RDONLY) {
                prot = PROT_READ;
index 3459a16a9df9f5f5403b6dc63a1c591550dafb1b..caec7b1bfaa335f3d6df017eb9b0ad24058edd9c 100644 (file)
@@ -403,12 +403,7 @@ void ipc_rmid(struct ipc_ids *ids, struct kern_ipc_perm *ipcp)
  */
 void *ipc_alloc(int size)
 {
-       void *out;
-       if (size > PAGE_SIZE)
-               out = vmalloc(size);
-       else
-               out = kmalloc(size, GFP_KERNEL);
-       return out;
+       return kvmalloc(size, GFP_KERNEL);
 }
 
 /**
index b302b4731d16547a88e4ddc6db21e130ae821113..72aa080f91f04bd9256f1df714186033294b19b9 100644 (file)
@@ -59,6 +59,7 @@ obj-$(CONFIG_MODULES) += module.o
 obj-$(CONFIG_MODULE_SIG) += module_signing.o
 obj-$(CONFIG_KALLSYMS) += kallsyms.o
 obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
+obj-$(CONFIG_CRASH_CORE) += crash_core.o
 obj-$(CONFIG_KEXEC_CORE) += kexec_core.o
 obj-$(CONFIG_KEXEC) += kexec.o
 obj-$(CONFIG_KEXEC_FILE) += kexec_file.o
index 6f81e0f5a0faa2f7df85ae1771f9dfde48e59651..dedf367f59bba529ded5603d61782bccb80782cb 100644 (file)
@@ -76,8 +76,7 @@ void *bpf_internal_load_pointer_neg_helper(const struct sk_buff *skb, int k, uns
 
 struct bpf_prog *bpf_prog_alloc(unsigned int size, gfp_t gfp_extra_flags)
 {
-       gfp_t gfp_flags = GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO |
-                         gfp_extra_flags;
+       gfp_t gfp_flags = GFP_KERNEL | __GFP_ZERO | gfp_extra_flags;
        struct bpf_prog_aux *aux;
        struct bpf_prog *fp;
 
@@ -107,8 +106,7 @@ EXPORT_SYMBOL_GPL(bpf_prog_alloc);
 struct bpf_prog *bpf_prog_realloc(struct bpf_prog *fp_old, unsigned int size,
                                  gfp_t gfp_extra_flags)
 {
-       gfp_t gfp_flags = GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO |
-                         gfp_extra_flags;
+       gfp_t gfp_flags = GFP_KERNEL | __GFP_ZERO | gfp_extra_flags;
        struct bpf_prog *fp;
        u32 pages, delta;
        int ret;
@@ -655,8 +653,7 @@ out:
 static struct bpf_prog *bpf_prog_clone_create(struct bpf_prog *fp_other,
                                              gfp_t gfp_extra_flags)
 {
-       gfp_t gfp_flags = GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO |
-                         gfp_extra_flags;
+       gfp_t gfp_flags = GFP_KERNEL | __GFP_ZERO | gfp_extra_flags;
        struct bpf_prog *fp;
 
        fp = __vmalloc(fp_other->pages * PAGE_SIZE, gfp_flags, PAGE_KERNEL);
index fddcae801724be149b73794ab42f9f177ecf4f56..9bbd33497d3d0846de8ebd7b74828e5566045e68 100644 (file)
@@ -429,7 +429,7 @@ static int bpf_parse_options(char *data, struct bpf_mount_opts *opts)
 
 static int bpf_fill_super(struct super_block *sb, void *data, int silent)
 {
-       static struct tree_descr bpf_rfiles[] = { { "" } };
+       static const struct tree_descr bpf_rfiles[] = { { "" } };
        struct bpf_mount_opts opts;
        struct inode *inode;
        int ret;
index 13642c73dca0b4c4461099f3a2774d8ec733160e..265a0d854e3358c5c714af9cc3ab2bae8a4754b4 100644 (file)
@@ -67,8 +67,7 @@ void *bpf_map_area_alloc(size_t size)
                        return area;
        }
 
-       return __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM | flags,
-                        PAGE_KERNEL);
+       return __vmalloc(size, GFP_KERNEL | flags, PAGE_KERNEL);
 }
 
 void bpf_map_area_free(void *area)
@@ -784,7 +783,7 @@ struct bpf_prog *bpf_prog_get_type(u32 ufd, enum bpf_prog_type type)
 EXPORT_SYMBOL_GPL(bpf_prog_get_type);
 
 /* last field in 'union bpf_attr' used by this command */
-#define        BPF_PROG_LOAD_LAST_FIELD kern_version
+#define        BPF_PROG_LOAD_LAST_FIELD prog_flags
 
 static int bpf_prog_load(union bpf_attr *attr)
 {
@@ -797,6 +796,9 @@ static int bpf_prog_load(union bpf_attr *attr)
        if (CHECK_ATTR(BPF_PROG_LOAD))
                return -EINVAL;
 
+       if (attr->prog_flags & ~BPF_F_STRICT_ALIGNMENT)
+               return -EINVAL;
+
        /* copy eBPF program license from user space */
        if (strncpy_from_user(license, u64_to_user_ptr(attr->license),
                              sizeof(license) - 1) < 0)
index c2ff608c1984ed3f7e5031d5f9fbcfe479f7fc67..1eddb713b815c3820dd996b4d34770e4c784ab71 100644 (file)
@@ -140,7 +140,7 @@ struct bpf_verifier_stack_elem {
        struct bpf_verifier_stack_elem *next;
 };
 
-#define BPF_COMPLEXITY_LIMIT_INSNS     65536
+#define BPF_COMPLEXITY_LIMIT_INSNS     98304
 #define BPF_COMPLEXITY_LIMIT_STACK     1024
 
 #define BPF_MAP_PTR_POISON ((void *)0xeB9F + POISON_POINTER_DELTA)
@@ -241,6 +241,12 @@ static void print_verifier_state(struct bpf_verifier_state *state)
                if (reg->max_value != BPF_REGISTER_MAX_RANGE)
                        verbose(",max_value=%llu",
                                (unsigned long long)reg->max_value);
+               if (reg->min_align)
+                       verbose(",min_align=%u", reg->min_align);
+               if (reg->aux_off)
+                       verbose(",aux_off=%u", reg->aux_off);
+               if (reg->aux_off_align)
+                       verbose(",aux_off_align=%u", reg->aux_off_align);
        }
        for (i = 0; i < MAX_BPF_STACK; i += BPF_REG_SIZE) {
                if (state->stack_slot_type[i] == STACK_SPILL)
@@ -298,7 +304,8 @@ static const char *const bpf_jmp_string[16] = {
        [BPF_EXIT >> 4] = "exit",
 };
 
-static void print_bpf_insn(struct bpf_insn *insn)
+static void print_bpf_insn(const struct bpf_verifier_env *env,
+                          const struct bpf_insn *insn)
 {
        u8 class = BPF_CLASS(insn->code);
 
@@ -362,9 +369,19 @@ static void print_bpf_insn(struct bpf_insn *insn)
                                insn->code,
                                bpf_ldst_string[BPF_SIZE(insn->code) >> 3],
                                insn->src_reg, insn->imm);
-               } else if (BPF_MODE(insn->code) == BPF_IMM) {
-                       verbose("(%02x) r%d = 0x%x\n",
-                               insn->code, insn->dst_reg, insn->imm);
+               } else if (BPF_MODE(insn->code) == BPF_IMM &&
+                          BPF_SIZE(insn->code) == BPF_DW) {
+                       /* At this point, we already made sure that the second
+                        * part of the ldimm64 insn is accessible.
+                        */
+                       u64 imm = ((u64)(insn + 1)->imm << 32) | (u32)insn->imm;
+                       bool map_ptr = insn->src_reg == BPF_PSEUDO_MAP_FD;
+
+                       if (map_ptr && !env->allow_ptr_leaks)
+                               imm = 0;
+
+                       verbose("(%02x) r%d = 0x%llx\n", insn->code,
+                               insn->dst_reg, (unsigned long long)imm);
                } else {
                        verbose("BUG_ld_%02x\n", insn->code);
                        return;
@@ -455,6 +472,9 @@ static void init_reg_state(struct bpf_reg_state *regs)
                regs[i].imm = 0;
                regs[i].min_value = BPF_REGISTER_MIN_RANGE;
                regs[i].max_value = BPF_REGISTER_MAX_RANGE;
+               regs[i].min_align = 0;
+               regs[i].aux_off = 0;
+               regs[i].aux_off_align = 0;
        }
 
        /* frame pointer */
@@ -481,6 +501,7 @@ static void reset_reg_range_values(struct bpf_reg_state *regs, u32 regno)
 {
        regs[regno].min_value = BPF_REGISTER_MIN_RANGE;
        regs[regno].max_value = BPF_REGISTER_MAX_RANGE;
+       regs[regno].min_align = 0;
 }
 
 static void mark_reg_unknown_value_and_range(struct bpf_reg_state *regs,
@@ -768,17 +789,33 @@ static bool is_pointer_value(struct bpf_verifier_env *env, int regno)
 }
 
 static int check_pkt_ptr_alignment(const struct bpf_reg_state *reg,
-                                  int off, int size)
+                                  int off, int size, bool strict)
 {
-       if (reg->id && size != 1) {
-               verbose("Unknown alignment. Only byte-sized access allowed in packet access.\n");
-               return -EACCES;
+       int ip_align;
+       int reg_off;
+
+       /* Byte size accesses are always allowed. */
+       if (!strict || size == 1)
+               return 0;
+
+       reg_off = reg->off;
+       if (reg->id) {
+               if (reg->aux_off_align % size) {
+                       verbose("Packet access is only %u byte aligned, %d byte access not allowed\n",
+                               reg->aux_off_align, size);
+                       return -EACCES;
+               }
+               reg_off += reg->aux_off;
        }
 
-       /* skb->data is NET_IP_ALIGN-ed */
-       if ((NET_IP_ALIGN + reg->off + off) % size != 0) {
+       /* skb->data is NET_IP_ALIGN-ed, but for strict alignment checking
+        * we force this to 2 which is universally what architectures use
+        * when they don't set CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS.
+        */
+       ip_align = strict ? 2 : NET_IP_ALIGN;
+       if ((ip_align + reg_off + off) % size != 0) {
                verbose("misaligned packet access off %d+%d+%d size %d\n",
-                       NET_IP_ALIGN, reg->off, off, size);
+                       ip_align, reg_off, off, size);
                return -EACCES;
        }
 
@@ -786,9 +823,9 @@ static int check_pkt_ptr_alignment(const struct bpf_reg_state *reg,
 }
 
 static int check_val_ptr_alignment(const struct bpf_reg_state *reg,
-                                  int size)
+                                  int size, bool strict)
 {
-       if (size != 1) {
+       if (strict && size != 1) {
                verbose("Unknown alignment. Only byte-sized access allowed in value access.\n");
                return -EACCES;
        }
@@ -796,16 +833,20 @@ static int check_val_ptr_alignment(const struct bpf_reg_state *reg,
        return 0;
 }
 
-static int check_ptr_alignment(const struct bpf_reg_state *reg,
+static int check_ptr_alignment(struct bpf_verifier_env *env,
+                              const struct bpf_reg_state *reg,
                               int off, int size)
 {
+       bool strict = env->strict_alignment;
+
+       if (!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS))
+               strict = true;
+
        switch (reg->type) {
        case PTR_TO_PACKET:
-               return IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) ? 0 :
-                      check_pkt_ptr_alignment(reg, off, size);
+               return check_pkt_ptr_alignment(reg, off, size, strict);
        case PTR_TO_MAP_VALUE_ADJ:
-               return IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) ? 0 :
-                      check_val_ptr_alignment(reg, size);
+               return check_val_ptr_alignment(reg, size, strict);
        default:
                if (off % size != 0) {
                        verbose("misaligned access off %d size %d\n",
@@ -838,7 +879,7 @@ static int check_mem_access(struct bpf_verifier_env *env, u32 regno, int off,
        if (size < 0)
                return size;
 
-       err = check_ptr_alignment(reg, off, size);
+       err = check_ptr_alignment(env, reg, off, size);
        if (err)
                return err;
 
@@ -872,6 +913,8 @@ static int check_mem_access(struct bpf_verifier_env *env, u32 regno, int off,
                                                         value_regno);
                        /* note that reg.[id|off|range] == 0 */
                        state->regs[value_regno].type = reg_type;
+                       state->regs[value_regno].aux_off = 0;
+                       state->regs[value_regno].aux_off_align = 0;
                }
 
        } else if (reg->type == FRAME_PTR || reg->type == PTR_TO_STACK) {
@@ -1444,6 +1487,8 @@ add_imm:
                 */
                dst_reg->off += imm;
        } else {
+               bool had_id;
+
                if (src_reg->type == PTR_TO_PACKET) {
                        /* R6=pkt(id=0,off=0,r=62) R7=imm22; r7 += r6 */
                        tmp_reg = *dst_reg;  /* save r7 state */
@@ -1477,14 +1522,23 @@ add_imm:
                                src_reg->imm);
                        return -EACCES;
                }
+
+               had_id = (dst_reg->id != 0);
+
                /* dst_reg stays as pkt_ptr type and since some positive
                 * integer value was added to the pointer, increment its 'id'
                 */
                dst_reg->id = ++env->id_gen;
 
-               /* something was added to pkt_ptr, set range and off to zero */
+               /* something was added to pkt_ptr, set range to zero */
+               dst_reg->aux_off += dst_reg->off;
                dst_reg->off = 0;
                dst_reg->range = 0;
+               if (had_id)
+                       dst_reg->aux_off_align = min(dst_reg->aux_off_align,
+                                                    src_reg->min_align);
+               else
+                       dst_reg->aux_off_align = src_reg->min_align;
        }
        return 0;
 }
@@ -1658,6 +1712,13 @@ static void check_reg_overflow(struct bpf_reg_state *reg)
                reg->min_value = BPF_REGISTER_MIN_RANGE;
 }
 
+static u32 calc_align(u32 imm)
+{
+       if (!imm)
+               return 1U << 31;
+       return imm - ((imm - 1) & imm);
+}
+
 static void adjust_reg_min_max_vals(struct bpf_verifier_env *env,
                                    struct bpf_insn *insn)
 {
@@ -1665,8 +1726,10 @@ static void adjust_reg_min_max_vals(struct bpf_verifier_env *env,
        s64 min_val = BPF_REGISTER_MIN_RANGE;
        u64 max_val = BPF_REGISTER_MAX_RANGE;
        u8 opcode = BPF_OP(insn->code);
+       u32 dst_align, src_align;
 
        dst_reg = &regs[insn->dst_reg];
+       src_align = 0;
        if (BPF_SRC(insn->code) == BPF_X) {
                check_reg_overflow(&regs[insn->src_reg]);
                min_val = regs[insn->src_reg].min_value;
@@ -1682,12 +1745,18 @@ static void adjust_reg_min_max_vals(struct bpf_verifier_env *env,
                    regs[insn->src_reg].type != UNKNOWN_VALUE) {
                        min_val = BPF_REGISTER_MIN_RANGE;
                        max_val = BPF_REGISTER_MAX_RANGE;
+                       src_align = 0;
+               } else {
+                       src_align = regs[insn->src_reg].min_align;
                }
        } else if (insn->imm < BPF_REGISTER_MAX_RANGE &&
                   (s64)insn->imm > BPF_REGISTER_MIN_RANGE) {
                min_val = max_val = insn->imm;
+               src_align = calc_align(insn->imm);
        }
 
+       dst_align = dst_reg->min_align;
+
        /* We don't know anything about what was done to this register, mark it
         * as unknown.
         */
@@ -1712,18 +1781,21 @@ static void adjust_reg_min_max_vals(struct bpf_verifier_env *env,
                        dst_reg->min_value += min_val;
                if (dst_reg->max_value != BPF_REGISTER_MAX_RANGE)
                        dst_reg->max_value += max_val;
+               dst_reg->min_align = min(src_align, dst_align);
                break;
        case BPF_SUB:
                if (dst_reg->min_value != BPF_REGISTER_MIN_RANGE)
                        dst_reg->min_value -= min_val;
                if (dst_reg->max_value != BPF_REGISTER_MAX_RANGE)
                        dst_reg->max_value -= max_val;
+               dst_reg->min_align = min(src_align, dst_align);
                break;
        case BPF_MUL:
                if (dst_reg->min_value != BPF_REGISTER_MIN_RANGE)
                        dst_reg->min_value *= min_val;
                if (dst_reg->max_value != BPF_REGISTER_MAX_RANGE)
                        dst_reg->max_value *= max_val;
+               dst_reg->min_align = max(src_align, dst_align);
                break;
        case BPF_AND:
                /* Disallow AND'ing of negative numbers, ain't nobody got time
@@ -1735,17 +1807,23 @@ static void adjust_reg_min_max_vals(struct bpf_verifier_env *env,
                else
                        dst_reg->min_value = 0;
                dst_reg->max_value = max_val;
+               dst_reg->min_align = max(src_align, dst_align);
                break;
        case BPF_LSH:
                /* Gotta have special overflow logic here, if we're shifting
                 * more than MAX_RANGE then just assume we have an invalid
                 * range.
                 */
-               if (min_val > ilog2(BPF_REGISTER_MAX_RANGE))
+               if (min_val > ilog2(BPF_REGISTER_MAX_RANGE)) {
                        dst_reg->min_value = BPF_REGISTER_MIN_RANGE;
-               else if (dst_reg->min_value != BPF_REGISTER_MIN_RANGE)
-                       dst_reg->min_value <<= min_val;
-
+                       dst_reg->min_align = 1;
+               } else {
+                       if (dst_reg->min_value != BPF_REGISTER_MIN_RANGE)
+                               dst_reg->min_value <<= min_val;
+                       if (!dst_reg->min_align)
+                               dst_reg->min_align = 1;
+                       dst_reg->min_align <<= min_val;
+               }
                if (max_val > ilog2(BPF_REGISTER_MAX_RANGE))
                        dst_reg->max_value = BPF_REGISTER_MAX_RANGE;
                else if (dst_reg->max_value != BPF_REGISTER_MAX_RANGE)
@@ -1755,11 +1833,19 @@ static void adjust_reg_min_max_vals(struct bpf_verifier_env *env,
                /* RSH by a negative number is undefined, and the BPF_RSH is an
                 * unsigned shift, so make the appropriate casts.
                 */
-               if (min_val < 0 || dst_reg->min_value < 0)
+               if (min_val < 0 || dst_reg->min_value < 0) {
                        dst_reg->min_value = BPF_REGISTER_MIN_RANGE;
-               else
+               } else {
                        dst_reg->min_value =
                                (u64)(dst_reg->min_value) >> min_val;
+               }
+               if (min_val < 0) {
+                       dst_reg->min_align = 1;
+               } else {
+                       dst_reg->min_align >>= (u64) min_val;
+                       if (!dst_reg->min_align)
+                               dst_reg->min_align = 1;
+               }
                if (dst_reg->max_value != BPF_REGISTER_MAX_RANGE)
                        dst_reg->max_value >>= max_val;
                break;
@@ -1861,6 +1947,7 @@ static int check_alu_op(struct bpf_verifier_env *env, struct bpf_insn *insn)
                        regs[insn->dst_reg].imm = insn->imm;
                        regs[insn->dst_reg].max_value = insn->imm;
                        regs[insn->dst_reg].min_value = insn->imm;
+                       regs[insn->dst_reg].min_align = calc_align(insn->imm);
                }
 
        } else if (opcode > BPF_END) {
@@ -2553,6 +2640,7 @@ peek_stack:
                                env->explored_states[t + 1] = STATE_LIST_MARK;
                } else {
                        /* conditional jump with two edges */
+                       env->explored_states[t] = STATE_LIST_MARK;
                        ret = push_insn(t, t + 1, FALLTHROUGH, env);
                        if (ret == 1)
                                goto peek_stack;
@@ -2711,6 +2799,12 @@ static bool states_equal(struct bpf_verifier_env *env,
                     rcur->type != NOT_INIT))
                        continue;
 
+               /* Don't care about the reg->id in this case. */
+               if (rold->type == PTR_TO_MAP_VALUE_OR_NULL &&
+                   rcur->type == PTR_TO_MAP_VALUE_OR_NULL &&
+                   rold->map_ptr == rcur->map_ptr)
+                       continue;
+
                if (rold->type == PTR_TO_PACKET && rcur->type == PTR_TO_PACKET &&
                    compare_ptrs_to_packet(rold, rcur))
                        continue;
@@ -2845,15 +2939,22 @@ static int do_check(struct bpf_verifier_env *env)
                        goto process_bpf_exit;
                }
 
-               if (log_level && do_print_state) {
-                       verbose("\nfrom %d to %d:", prev_insn_idx, insn_idx);
+               if (need_resched())
+                       cond_resched();
+
+               if (log_level > 1 || (log_level && do_print_state)) {
+                       if (log_level > 1)
+                               verbose("%d:", insn_idx);
+                       else
+                               verbose("\nfrom %d to %d:",
+                                       prev_insn_idx, insn_idx);
                        print_verifier_state(&env->cur_state);
                        do_print_state = false;
                }
 
                if (log_level) {
                        verbose("%d: ", insn_idx);
-                       print_bpf_insn(insn);
+                       print_bpf_insn(env, insn);
                }
 
                err = ext_analyzer_insn_hook(env, insn_idx, prev_insn_idx);
@@ -3483,6 +3584,10 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr)
        } else {
                log_level = 0;
        }
+       if (attr->prog_flags & BPF_F_STRICT_ALIGNMENT)
+               env->strict_alignment = true;
+       else
+               env->strict_alignment = false;
 
        ret = replace_map_fd_with_map_ptr(env);
        if (ret < 0)
@@ -3588,6 +3693,7 @@ int bpf_analyzer(struct bpf_prog *prog, const struct bpf_ext_analyzer_ops *ops,
        mutex_lock(&bpf_verifier_lock);
 
        log_level = 0;
+       env->strict_alignment = false;
 
        env->explored_states = kcalloc(env->prog->len,
                                       sizeof(struct bpf_verifier_state_list *),
diff --git a/kernel/crash_core.c b/kernel/crash_core.c
new file mode 100644 (file)
index 0000000..fcbd568
--- /dev/null
@@ -0,0 +1,439 @@
+/*
+ * crash.c - kernel crash support code.
+ * Copyright (C) 2002-2004 Eric Biederman  <ebiederm@xmission.com>
+ *
+ * This source code is licensed under the GNU General Public License,
+ * Version 2.  See the file COPYING for more details.
+ */
+
+#include <linux/crash_core.h>
+#include <linux/utsname.h>
+#include <linux/vmalloc.h>
+
+#include <asm/page.h>
+#include <asm/sections.h>
+
+/* vmcoreinfo stuff */
+static unsigned char vmcoreinfo_data[VMCOREINFO_BYTES];
+u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4];
+size_t vmcoreinfo_size;
+size_t vmcoreinfo_max_size = sizeof(vmcoreinfo_data);
+
+/*
+ * parsing the "crashkernel" commandline
+ *
+ * this code is intended to be called from architecture specific code
+ */
+
+
+/*
+ * This function parses command lines in the format
+ *
+ *   crashkernel=ramsize-range:size[,...][@offset]
+ *
+ * The function returns 0 on success and -EINVAL on failure.
+ */
+static int __init parse_crashkernel_mem(char *cmdline,
+                                       unsigned long long system_ram,
+                                       unsigned long long *crash_size,
+                                       unsigned long long *crash_base)
+{
+       char *cur = cmdline, *tmp;
+
+       /* for each entry of the comma-separated list */
+       do {
+               unsigned long long start, end = ULLONG_MAX, size;
+
+               /* get the start of the range */
+               start = memparse(cur, &tmp);
+               if (cur == tmp) {
+                       pr_warn("crashkernel: Memory value expected\n");
+                       return -EINVAL;
+               }
+               cur = tmp;
+               if (*cur != '-') {
+                       pr_warn("crashkernel: '-' expected\n");
+                       return -EINVAL;
+               }
+               cur++;
+
+               /* if no ':' is here, than we read the end */
+               if (*cur != ':') {
+                       end = memparse(cur, &tmp);
+                       if (cur == tmp) {
+                               pr_warn("crashkernel: Memory value expected\n");
+                               return -EINVAL;
+                       }
+                       cur = tmp;
+                       if (end <= start) {
+                               pr_warn("crashkernel: end <= start\n");
+                               return -EINVAL;
+                       }
+               }
+
+               if (*cur != ':') {
+                       pr_warn("crashkernel: ':' expected\n");
+                       return -EINVAL;
+               }
+               cur++;
+
+               size = memparse(cur, &tmp);
+               if (cur == tmp) {
+                       pr_warn("Memory value expected\n");
+                       return -EINVAL;
+               }
+               cur = tmp;
+               if (size >= system_ram) {
+                       pr_warn("crashkernel: invalid size\n");
+                       return -EINVAL;
+               }
+
+               /* match ? */
+               if (system_ram >= start && system_ram < end) {
+                       *crash_size = size;
+                       break;
+               }
+       } while (*cur++ == ',');
+
+       if (*crash_size > 0) {
+               while (*cur && *cur != ' ' && *cur != '@')
+                       cur++;
+               if (*cur == '@') {
+                       cur++;
+                       *crash_base = memparse(cur, &tmp);
+                       if (cur == tmp) {
+                               pr_warn("Memory value expected after '@'\n");
+                               return -EINVAL;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+/*
+ * That function parses "simple" (old) crashkernel command lines like
+ *
+ *     crashkernel=size[@offset]
+ *
+ * It returns 0 on success and -EINVAL on failure.
+ */
+static int __init parse_crashkernel_simple(char *cmdline,
+                                          unsigned long long *crash_size,
+                                          unsigned long long *crash_base)
+{
+       char *cur = cmdline;
+
+       *crash_size = memparse(cmdline, &cur);
+       if (cmdline == cur) {
+               pr_warn("crashkernel: memory value expected\n");
+               return -EINVAL;
+       }
+
+       if (*cur == '@')
+               *crash_base = memparse(cur+1, &cur);
+       else if (*cur != ' ' && *cur != '\0') {
+               pr_warn("crashkernel: unrecognized char: %c\n", *cur);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+#define SUFFIX_HIGH 0
+#define SUFFIX_LOW  1
+#define SUFFIX_NULL 2
+static __initdata char *suffix_tbl[] = {
+       [SUFFIX_HIGH] = ",high",
+       [SUFFIX_LOW]  = ",low",
+       [SUFFIX_NULL] = NULL,
+};
+
+/*
+ * That function parses "suffix"  crashkernel command lines like
+ *
+ *     crashkernel=size,[high|low]
+ *
+ * It returns 0 on success and -EINVAL on failure.
+ */
+static int __init parse_crashkernel_suffix(char *cmdline,
+                                          unsigned long long   *crash_size,
+                                          const char *suffix)
+{
+       char *cur = cmdline;
+
+       *crash_size = memparse(cmdline, &cur);
+       if (cmdline == cur) {
+               pr_warn("crashkernel: memory value expected\n");
+               return -EINVAL;
+       }
+
+       /* check with suffix */
+       if (strncmp(cur, suffix, strlen(suffix))) {
+               pr_warn("crashkernel: unrecognized char: %c\n", *cur);
+               return -EINVAL;
+       }
+       cur += strlen(suffix);
+       if (*cur != ' ' && *cur != '\0') {
+               pr_warn("crashkernel: unrecognized char: %c\n", *cur);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static __init char *get_last_crashkernel(char *cmdline,
+                            const char *name,
+                            const char *suffix)
+{
+       char *p = cmdline, *ck_cmdline = NULL;
+
+       /* find crashkernel and use the last one if there are more */
+       p = strstr(p, name);
+       while (p) {
+               char *end_p = strchr(p, ' ');
+               char *q;
+
+               if (!end_p)
+                       end_p = p + strlen(p);
+
+               if (!suffix) {
+                       int i;
+
+                       /* skip the one with any known suffix */
+                       for (i = 0; suffix_tbl[i]; i++) {
+                               q = end_p - strlen(suffix_tbl[i]);
+                               if (!strncmp(q, suffix_tbl[i],
+                                            strlen(suffix_tbl[i])))
+                                       goto next;
+                       }
+                       ck_cmdline = p;
+               } else {
+                       q = end_p - strlen(suffix);
+                       if (!strncmp(q, suffix, strlen(suffix)))
+                               ck_cmdline = p;
+               }
+next:
+               p = strstr(p+1, name);
+       }
+
+       if (!ck_cmdline)
+               return NULL;
+
+       return ck_cmdline;
+}
+
+static int __init __parse_crashkernel(char *cmdline,
+                            unsigned long long system_ram,
+                            unsigned long long *crash_size,
+                            unsigned long long *crash_base,
+                            const char *name,
+                            const char *suffix)
+{
+       char    *first_colon, *first_space;
+       char    *ck_cmdline;
+
+       BUG_ON(!crash_size || !crash_base);
+       *crash_size = 0;
+       *crash_base = 0;
+
+       ck_cmdline = get_last_crashkernel(cmdline, name, suffix);
+
+       if (!ck_cmdline)
+               return -EINVAL;
+
+       ck_cmdline += strlen(name);
+
+       if (suffix)
+               return parse_crashkernel_suffix(ck_cmdline, crash_size,
+                               suffix);
+       /*
+        * if the commandline contains a ':', then that's the extended
+        * syntax -- if not, it must be the classic syntax
+        */
+       first_colon = strchr(ck_cmdline, ':');
+       first_space = strchr(ck_cmdline, ' ');
+       if (first_colon && (!first_space || first_colon < first_space))
+               return parse_crashkernel_mem(ck_cmdline, system_ram,
+                               crash_size, crash_base);
+
+       return parse_crashkernel_simple(ck_cmdline, crash_size, crash_base);
+}
+
+/*
+ * That function is the entry point for command line parsing and should be
+ * called from the arch-specific code.
+ */
+int __init parse_crashkernel(char *cmdline,
+                            unsigned long long system_ram,
+                            unsigned long long *crash_size,
+                            unsigned long long *crash_base)
+{
+       return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base,
+                                       "crashkernel=", NULL);
+}
+
+int __init parse_crashkernel_high(char *cmdline,
+                            unsigned long long system_ram,
+                            unsigned long long *crash_size,
+                            unsigned long long *crash_base)
+{
+       return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base,
+                               "crashkernel=", suffix_tbl[SUFFIX_HIGH]);
+}
+
+int __init parse_crashkernel_low(char *cmdline,
+                            unsigned long long system_ram,
+                            unsigned long long *crash_size,
+                            unsigned long long *crash_base)
+{
+       return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base,
+                               "crashkernel=", suffix_tbl[SUFFIX_LOW]);
+}
+
+Elf_Word *append_elf_note(Elf_Word *buf, char *name, unsigned int type,
+                         void *data, size_t data_len)
+{
+       struct elf_note *note = (struct elf_note *)buf;
+
+       note->n_namesz = strlen(name) + 1;
+       note->n_descsz = data_len;
+       note->n_type   = type;
+       buf += DIV_ROUND_UP(sizeof(*note), sizeof(Elf_Word));
+       memcpy(buf, name, note->n_namesz);
+       buf += DIV_ROUND_UP(note->n_namesz, sizeof(Elf_Word));
+       memcpy(buf, data, data_len);
+       buf += DIV_ROUND_UP(data_len, sizeof(Elf_Word));
+
+       return buf;
+}
+
+void final_note(Elf_Word *buf)
+{
+       memset(buf, 0, sizeof(struct elf_note));
+}
+
+static void update_vmcoreinfo_note(void)
+{
+       u32 *buf = vmcoreinfo_note;
+
+       if (!vmcoreinfo_size)
+               return;
+       buf = append_elf_note(buf, VMCOREINFO_NOTE_NAME, 0, vmcoreinfo_data,
+                             vmcoreinfo_size);
+       final_note(buf);
+}
+
+void crash_save_vmcoreinfo(void)
+{
+       vmcoreinfo_append_str("CRASHTIME=%ld\n", get_seconds());
+       update_vmcoreinfo_note();
+}
+
+void vmcoreinfo_append_str(const char *fmt, ...)
+{
+       va_list args;
+       char buf[0x50];
+       size_t r;
+
+       va_start(args, fmt);
+       r = vscnprintf(buf, sizeof(buf), fmt, args);
+       va_end(args);
+
+       r = min(r, vmcoreinfo_max_size - vmcoreinfo_size);
+
+       memcpy(&vmcoreinfo_data[vmcoreinfo_size], buf, r);
+
+       vmcoreinfo_size += r;
+}
+
+/*
+ * provide an empty default implementation here -- architecture
+ * code may override this
+ */
+void __weak arch_crash_save_vmcoreinfo(void)
+{}
+
+phys_addr_t __weak paddr_vmcoreinfo_note(void)
+{
+       return __pa_symbol((unsigned long)(char *)&vmcoreinfo_note);
+}
+
+static int __init crash_save_vmcoreinfo_init(void)
+{
+       VMCOREINFO_OSRELEASE(init_uts_ns.name.release);
+       VMCOREINFO_PAGESIZE(PAGE_SIZE);
+
+       VMCOREINFO_SYMBOL(init_uts_ns);
+       VMCOREINFO_SYMBOL(node_online_map);
+#ifdef CONFIG_MMU
+       VMCOREINFO_SYMBOL(swapper_pg_dir);
+#endif
+       VMCOREINFO_SYMBOL(_stext);
+       VMCOREINFO_SYMBOL(vmap_area_list);
+
+#ifndef CONFIG_NEED_MULTIPLE_NODES
+       VMCOREINFO_SYMBOL(mem_map);
+       VMCOREINFO_SYMBOL(contig_page_data);
+#endif
+#ifdef CONFIG_SPARSEMEM
+       VMCOREINFO_SYMBOL(mem_section);
+       VMCOREINFO_LENGTH(mem_section, NR_SECTION_ROOTS);
+       VMCOREINFO_STRUCT_SIZE(mem_section);
+       VMCOREINFO_OFFSET(mem_section, section_mem_map);
+#endif
+       VMCOREINFO_STRUCT_SIZE(page);
+       VMCOREINFO_STRUCT_SIZE(pglist_data);
+       VMCOREINFO_STRUCT_SIZE(zone);
+       VMCOREINFO_STRUCT_SIZE(free_area);
+       VMCOREINFO_STRUCT_SIZE(list_head);
+       VMCOREINFO_SIZE(nodemask_t);
+       VMCOREINFO_OFFSET(page, flags);
+       VMCOREINFO_OFFSET(page, _refcount);
+       VMCOREINFO_OFFSET(page, mapping);
+       VMCOREINFO_OFFSET(page, lru);
+       VMCOREINFO_OFFSET(page, _mapcount);
+       VMCOREINFO_OFFSET(page, private);
+       VMCOREINFO_OFFSET(page, compound_dtor);
+       VMCOREINFO_OFFSET(page, compound_order);
+       VMCOREINFO_OFFSET(page, compound_head);
+       VMCOREINFO_OFFSET(pglist_data, node_zones);
+       VMCOREINFO_OFFSET(pglist_data, nr_zones);
+#ifdef CONFIG_FLAT_NODE_MEM_MAP
+       VMCOREINFO_OFFSET(pglist_data, node_mem_map);
+#endif
+       VMCOREINFO_OFFSET(pglist_data, node_start_pfn);
+       VMCOREINFO_OFFSET(pglist_data, node_spanned_pages);
+       VMCOREINFO_OFFSET(pglist_data, node_id);
+       VMCOREINFO_OFFSET(zone, free_area);
+       VMCOREINFO_OFFSET(zone, vm_stat);
+       VMCOREINFO_OFFSET(zone, spanned_pages);
+       VMCOREINFO_OFFSET(free_area, free_list);
+       VMCOREINFO_OFFSET(list_head, next);
+       VMCOREINFO_OFFSET(list_head, prev);
+       VMCOREINFO_OFFSET(vmap_area, va_start);
+       VMCOREINFO_OFFSET(vmap_area, list);
+       VMCOREINFO_LENGTH(zone.free_area, MAX_ORDER);
+       log_buf_vmcoreinfo_setup();
+       VMCOREINFO_LENGTH(free_area.free_list, MIGRATE_TYPES);
+       VMCOREINFO_NUMBER(NR_FREE_PAGES);
+       VMCOREINFO_NUMBER(PG_lru);
+       VMCOREINFO_NUMBER(PG_private);
+       VMCOREINFO_NUMBER(PG_swapcache);
+       VMCOREINFO_NUMBER(PG_slab);
+#ifdef CONFIG_MEMORY_FAILURE
+       VMCOREINFO_NUMBER(PG_hwpoison);
+#endif
+       VMCOREINFO_NUMBER(PG_head_mask);
+       VMCOREINFO_NUMBER(PAGE_BUDDY_MAPCOUNT_VALUE);
+#ifdef CONFIG_HUGETLB_PAGE
+       VMCOREINFO_NUMBER(HUGETLB_PAGE_DTOR);
+#endif
+
+       arch_crash_save_vmcoreinfo();
+       update_vmcoreinfo_note();
+
+       return 0;
+}
+
+subsys_initcall(crash_save_vmcoreinfo_init);
index c04917cad1bfdc50fe4f00b08eaa58c9e7e7692e..1b2be63c85282fdb6f910e145853f97c23d8efb4 100644 (file)
@@ -229,12 +229,18 @@ get_perf_callchain(struct pt_regs *regs, u32 init_nr, bool kernel, bool user,
                }
 
                if (regs) {
+                       mm_segment_t fs;
+
                        if (crosstask)
                                goto exit_put;
 
                        if (add_mark)
                                perf_callchain_store_context(&ctx, PERF_CONTEXT_USER);
+
+                       fs = get_fs();
+                       set_fs(USER_DS);
                        perf_callchain_user(&ctx, regs);
+                       set_fs(fs);
                }
        }
 
index dd5a371c392a7fab7330dbe456a48296b4614b98..aa1076c5e4a9f3a5d9e6f58fef1c6f34e332de8c 100644 (file)
@@ -179,6 +179,24 @@ void __weak arch_release_thread_stack(unsigned long *stack)
  */
 #define NR_CACHED_STACKS 2
 static DEFINE_PER_CPU(struct vm_struct *, cached_stacks[NR_CACHED_STACKS]);
+
+static int free_vm_stack_cache(unsigned int cpu)
+{
+       struct vm_struct **cached_vm_stacks = per_cpu_ptr(cached_stacks, cpu);
+       int i;
+
+       for (i = 0; i < NR_CACHED_STACKS; i++) {
+               struct vm_struct *vm_stack = cached_vm_stacks[i];
+
+               if (!vm_stack)
+                       continue;
+
+               vfree(vm_stack->addr);
+               cached_vm_stacks[i] = NULL;
+       }
+
+       return 0;
+}
 #endif
 
 static unsigned long *alloc_thread_stack_node(struct task_struct *tsk, int node)
@@ -203,7 +221,7 @@ static unsigned long *alloc_thread_stack_node(struct task_struct *tsk, int node)
 
        stack = __vmalloc_node_range(THREAD_SIZE, THREAD_SIZE,
                                     VMALLOC_START, VMALLOC_END,
-                                    THREADINFO_GFP | __GFP_HIGHMEM,
+                                    THREADINFO_GFP,
                                     PAGE_KERNEL,
                                     0, node, __builtin_return_address(0));
 
@@ -467,6 +485,11 @@ void __init fork_init(void)
        for (i = 0; i < UCOUNT_COUNTS; i++) {
                init_user_ns.ucount_max[i] = max_threads/2;
        }
+
+#ifdef CONFIG_VMAP_STACK
+       cpuhp_setup_state(CPUHP_BP_PREPARE_DYN, "fork:vm_stack_cache",
+                         NULL, free_vm_stack_cache);
+#endif
 }
 
 int __weak arch_dup_task_struct(struct task_struct *dst,
@@ -537,7 +560,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig, int node)
        set_task_stack_end_magic(tsk);
 
 #ifdef CONFIG_CC_STACKPROTECTOR
-       tsk->stack_canary = get_random_int();
+       tsk->stack_canary = get_random_long();
 #endif
 
        /*
@@ -1314,7 +1337,7 @@ void __cleanup_sighand(struct sighand_struct *sighand)
        if (atomic_dec_and_test(&sighand->count)) {
                signalfd_cleanup(sighand);
                /*
-                * sighand_cachep is SLAB_DESTROY_BY_RCU so we can free it
+                * sighand_cachep is SLAB_TYPESAFE_BY_RCU so we can free it
                 * without an RCU grace period, see __lock_task_sighand().
                 */
                kmem_cache_free(sighand_cachep, sighand);
@@ -1822,11 +1845,13 @@ static __latent_entropy struct task_struct *copy_process(
        */
        recalc_sigpending();
        if (signal_pending(current)) {
-               spin_unlock(&current->sighand->siglock);
-               write_unlock_irq(&tasklist_lock);
                retval = -ERESTARTNOINTR;
                goto bad_fork_cancel_cgroup;
        }
+       if (unlikely(!(ns_of_pid(pid)->nr_hashed & PIDNS_HASH_ADDING))) {
+               retval = -ENOMEM;
+               goto bad_fork_cancel_cgroup;
+       }
 
        if (likely(p->pid)) {
                ptrace_init_task(p, (clone_flags & CLONE_PTRACE) || trace);
@@ -1884,6 +1909,8 @@ static __latent_entropy struct task_struct *copy_process(
        return p;
 
 bad_fork_cancel_cgroup:
+       spin_unlock(&current->sighand->siglock);
+       write_unlock_irq(&tasklist_lock);
        cgroup_cancel_fork(p);
 bad_fork_free_pid:
        cgroup_threadgroup_change_end(current);
@@ -2153,7 +2180,7 @@ void __init proc_caches_init(void)
 {
        sighand_cachep = kmem_cache_create("sighand_cache",
                        sizeof(struct sighand_struct), 0,
-                       SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_DESTROY_BY_RCU|
+                       SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_TYPESAFE_BY_RCU|
                        SLAB_NOTRACK|SLAB_ACCOUNT, sighand_ctor);
        signal_cachep = kmem_cache_create("signal_cache",
                        sizeof(struct signal_struct), 0,
index 2f9df37940a0f5a489efc4eaa6afc1ccaa35ad68..c51a49c9be7064d30638d7ae184a4fcbc2136ec7 100644 (file)
@@ -98,6 +98,12 @@ void __gcov_merge_icall_topn(gcov_type *counters, unsigned int n_counters)
 }
 EXPORT_SYMBOL(__gcov_merge_icall_topn);
 
+void __gcov_exit(void)
+{
+       /* Unused. */
+}
+EXPORT_SYMBOL(__gcov_exit);
+
 /**
  * gcov_enable_events - enable event reporting through gcov_event()
  *
index 6a5c239c7669c5ad8e01565be5a6fd38ae7d4452..46a18e72bce614c804fbe958f0a6b4d00d11027a 100644 (file)
@@ -18,7 +18,9 @@
 #include <linux/vmalloc.h>
 #include "gcov.h"
 
-#if (__GNUC__ > 5) || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1)
+#if (__GNUC__ >= 7)
+#define GCOV_COUNTERS                  9
+#elif (__GNUC__ > 5) || (__GNUC__ == 5 && __GNUC_MINOR__ >= 1)
 #define GCOV_COUNTERS                  10
 #elif __GNUC__ == 4 && __GNUC_MINOR__ >= 9
 #define GCOV_COUNTERS                  9
index 8dd7a61b7115e8808408cd2cb911d224a9528297..d09727692a2af1801fb82982d4a08daee5c86d62 100644 (file)
@@ -18,7 +18,7 @@ struct group_info *groups_alloc(int gidsetsize)
        len = sizeof(struct group_info) + sizeof(kgid_t) * gidsetsize;
        gi = kmalloc(len, GFP_KERNEL_ACCOUNT|__GFP_NOWARN|__GFP_NORETRY);
        if (!gi)
-               gi = __vmalloc(len, GFP_KERNEL_ACCOUNT|__GFP_HIGHMEM, PAGE_KERNEL);
+               gi = __vmalloc(len, GFP_KERNEL_ACCOUNT, PAGE_KERNEL);
        if (!gi)
                return NULL;
 
index f0f8e2a8496feafbb0f9589a6d8159779b9effe0..751593ed7c0b0b9cc9bf74735fb9bd5d7e100be2 100644 (file)
@@ -43,6 +43,7 @@ unsigned long __read_mostly sysctl_hung_task_timeout_secs = CONFIG_DEFAULT_HUNG_
 int __read_mostly sysctl_hung_task_warnings = 10;
 
 static int __read_mostly did_panic;
+static bool hung_task_show_lock;
 
 static struct task_struct *watchdog_task;
 
@@ -120,12 +121,14 @@ static void check_hung_task(struct task_struct *t, unsigned long timeout)
                pr_err("\"echo 0 > /proc/sys/kernel/hung_task_timeout_secs\""
                        " disables this message.\n");
                sched_show_task(t);
-               debug_show_all_locks();
+               hung_task_show_lock = true;
        }
 
        touch_nmi_watchdog();
 
        if (sysctl_hung_task_panic) {
+               if (hung_task_show_lock)
+                       debug_show_all_locks();
                trigger_all_cpu_backtrace();
                panic("hung_task: blocked tasks");
        }
@@ -172,6 +175,7 @@ static void check_hung_uninterruptible_tasks(unsigned long timeout)
        if (test_taint(TAINT_DIE) || did_panic)
                return;
 
+       hung_task_show_lock = false;
        rcu_read_lock();
        for_each_process_thread(g, t) {
                if (!max_count--)
@@ -187,6 +191,8 @@ static void check_hung_uninterruptible_tasks(unsigned long timeout)
        }
  unlock:
        rcu_read_unlock();
+       if (hung_task_show_lock)
+               debug_show_all_locks();
 }
 
 static long hung_timeout_jiffies(unsigned long last_checked,
index ae1c90f203814e8f42819eb5b1aae70eeb834a8a..070be980c37a57d91f86099d2be1b81db80176bc 100644 (file)
@@ -1559,7 +1559,7 @@ void remove_irq(unsigned int irq, struct irqaction *act)
        struct irq_desc *desc = irq_to_desc(irq);
 
        if (desc && !WARN_ON(irq_settings_is_per_cpu_devid(desc)))
-           __free_irq(irq, act->dev_id);
+               __free_irq(irq, act->dev_id);
 }
 EXPORT_SYMBOL_GPL(remove_irq);
 
@@ -1576,20 +1576,27 @@ EXPORT_SYMBOL_GPL(remove_irq);
  *     have completed.
  *
  *     This function must not be called from interrupt context.
+ *
+ *     Returns the devname argument passed to request_irq.
  */
-void free_irq(unsigned int irq, void *dev_id)
+const void *free_irq(unsigned int irq, void *dev_id)
 {
        struct irq_desc *desc = irq_to_desc(irq);
+       struct irqaction *action;
+       const char *devname;
 
        if (!desc || WARN_ON(irq_settings_is_per_cpu_devid(desc)))
-               return;
+               return NULL;
 
 #ifdef CONFIG_SMP
        if (WARN_ON(desc->affinity_notify))
                desc->affinity_notify = NULL;
 #endif
 
-       kfree(__free_irq(irq, dev_id));
+       action = __free_irq(irq, dev_id);
+       devname = action->name;
+       kfree(action);
+       return devname;
 }
 EXPORT_SYMBOL(free_irq);
 
index 85e5546cd791cc31261cd6deb8aea933bb41c008..cd771993f96f4a7ff23592f1abaea22c71444fda 100644 (file)
@@ -60,15 +60,8 @@ void notrace __sanitizer_cov_trace_pc(void)
        /*
         * We are interested in code coverage as a function of a syscall inputs,
         * so we ignore code executed in interrupts.
-        * The checks for whether we are in an interrupt are open-coded, because
-        * 1. We can't use in_interrupt() here, since it also returns true
-        *    when we are inside local_bh_disable() section.
-        * 2. We don't want to use (in_irq() | in_serving_softirq() | in_nmi()),
-        *    since that leads to slower generated code (three separate tests,
-        *    one for each of the flags).
         */
-       if (!t || (preempt_count() & (HARDIRQ_MASK | SOFTIRQ_OFFSET
-                                                       | NMI_MASK)))
+       if (!t || !in_task())
                return;
        mode = READ_ONCE(t->kcov_mode);
        if (mode == KCOV_MODE_TRACE) {
index bfe62d5b38722251681f7257788cd14533fe4362..ae1a3ba24df56958bb48f30ddde85ae6ae833fdf 100644 (file)
@@ -51,12 +51,6 @@ DEFINE_MUTEX(kexec_mutex);
 /* Per cpu memory for storing cpu states in case of system crash. */
 note_buf_t __percpu *crash_notes;
 
-/* vmcoreinfo stuff */
-static unsigned char vmcoreinfo_data[VMCOREINFO_BYTES];
-u32 vmcoreinfo_note[VMCOREINFO_NOTE_SIZE/4];
-size_t vmcoreinfo_size;
-size_t vmcoreinfo_max_size = sizeof(vmcoreinfo_data);
-
 /* Flag to indicate we are going to kexec a new kernel */
 bool kexec_in_progress = false;
 
@@ -996,34 +990,6 @@ unlock:
        return ret;
 }
 
-static u32 *append_elf_note(u32 *buf, char *name, unsigned type, void *data,
-                           size_t data_len)
-{
-       struct elf_note note;
-
-       note.n_namesz = strlen(name) + 1;
-       note.n_descsz = data_len;
-       note.n_type   = type;
-       memcpy(buf, &note, sizeof(note));
-       buf += (sizeof(note) + 3)/4;
-       memcpy(buf, name, note.n_namesz);
-       buf += (note.n_namesz + 3)/4;
-       memcpy(buf, data, note.n_descsz);
-       buf += (note.n_descsz + 3)/4;
-
-       return buf;
-}
-
-static void final_note(u32 *buf)
-{
-       struct elf_note note;
-
-       note.n_namesz = 0;
-       note.n_descsz = 0;
-       note.n_type   = 0;
-       memcpy(buf, &note, sizeof(note));
-}
-
 void crash_save_cpu(struct pt_regs *regs, int cpu)
 {
        struct elf_prstatus prstatus;
@@ -1084,403 +1050,6 @@ static int __init crash_notes_memory_init(void)
 subsys_initcall(crash_notes_memory_init);
 
 
-/*
- * parsing the "crashkernel" commandline
- *
- * this code is intended to be called from architecture specific code
- */
-
-
-/*
- * This function parses command lines in the format
- *
- *   crashkernel=ramsize-range:size[,...][@offset]
- *
- * The function returns 0 on success and -EINVAL on failure.
- */
-static int __init parse_crashkernel_mem(char *cmdline,
-                                       unsigned long long system_ram,
-                                       unsigned long long *crash_size,
-                                       unsigned long long *crash_base)
-{
-       char *cur = cmdline, *tmp;
-
-       /* for each entry of the comma-separated list */
-       do {
-               unsigned long long start, end = ULLONG_MAX, size;
-
-               /* get the start of the range */
-               start = memparse(cur, &tmp);
-               if (cur == tmp) {
-                       pr_warn("crashkernel: Memory value expected\n");
-                       return -EINVAL;
-               }
-               cur = tmp;
-               if (*cur != '-') {
-                       pr_warn("crashkernel: '-' expected\n");
-                       return -EINVAL;
-               }
-               cur++;
-
-               /* if no ':' is here, than we read the end */
-               if (*cur != ':') {
-                       end = memparse(cur, &tmp);
-                       if (cur == tmp) {
-                               pr_warn("crashkernel: Memory value expected\n");
-                               return -EINVAL;
-                       }
-                       cur = tmp;
-                       if (end <= start) {
-                               pr_warn("crashkernel: end <= start\n");
-                               return -EINVAL;
-                       }
-               }
-
-               if (*cur != ':') {
-                       pr_warn("crashkernel: ':' expected\n");
-                       return -EINVAL;
-               }
-               cur++;
-
-               size = memparse(cur, &tmp);
-               if (cur == tmp) {
-                       pr_warn("Memory value expected\n");
-                       return -EINVAL;
-               }
-               cur = tmp;
-               if (size >= system_ram) {
-                       pr_warn("crashkernel: invalid size\n");
-                       return -EINVAL;
-               }
-
-               /* match ? */
-               if (system_ram >= start && system_ram < end) {
-                       *crash_size = size;
-                       break;
-               }
-       } while (*cur++ == ',');
-
-       if (*crash_size > 0) {
-               while (*cur && *cur != ' ' && *cur != '@')
-                       cur++;
-               if (*cur == '@') {
-                       cur++;
-                       *crash_base = memparse(cur, &tmp);
-                       if (cur == tmp) {
-                               pr_warn("Memory value expected after '@'\n");
-                               return -EINVAL;
-                       }
-               }
-       }
-
-       return 0;
-}
-
-/*
- * That function parses "simple" (old) crashkernel command lines like
- *
- *     crashkernel=size[@offset]
- *
- * It returns 0 on success and -EINVAL on failure.
- */
-static int __init parse_crashkernel_simple(char *cmdline,
-                                          unsigned long long *crash_size,
-                                          unsigned long long *crash_base)
-{
-       char *cur = cmdline;
-
-       *crash_size = memparse(cmdline, &cur);
-       if (cmdline == cur) {
-               pr_warn("crashkernel: memory value expected\n");
-               return -EINVAL;
-       }
-
-       if (*cur == '@')
-               *crash_base = memparse(cur+1, &cur);
-       else if (*cur != ' ' && *cur != '\0') {
-               pr_warn("crashkernel: unrecognized char: %c\n", *cur);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-#define SUFFIX_HIGH 0
-#define SUFFIX_LOW  1
-#define SUFFIX_NULL 2
-static __initdata char *suffix_tbl[] = {
-       [SUFFIX_HIGH] = ",high",
-       [SUFFIX_LOW]  = ",low",
-       [SUFFIX_NULL] = NULL,
-};
-
-/*
- * That function parses "suffix"  crashkernel command lines like
- *
- *     crashkernel=size,[high|low]
- *
- * It returns 0 on success and -EINVAL on failure.
- */
-static int __init parse_crashkernel_suffix(char *cmdline,
-                                          unsigned long long   *crash_size,
-                                          const char *suffix)
-{
-       char *cur = cmdline;
-
-       *crash_size = memparse(cmdline, &cur);
-       if (cmdline == cur) {
-               pr_warn("crashkernel: memory value expected\n");
-               return -EINVAL;
-       }
-
-       /* check with suffix */
-       if (strncmp(cur, suffix, strlen(suffix))) {
-               pr_warn("crashkernel: unrecognized char: %c\n", *cur);
-               return -EINVAL;
-       }
-       cur += strlen(suffix);
-       if (*cur != ' ' && *cur != '\0') {
-               pr_warn("crashkernel: unrecognized char: %c\n", *cur);
-               return -EINVAL;
-       }
-
-       return 0;
-}
-
-static __init char *get_last_crashkernel(char *cmdline,
-                            const char *name,
-                            const char *suffix)
-{
-       char *p = cmdline, *ck_cmdline = NULL;
-
-       /* find crashkernel and use the last one if there are more */
-       p = strstr(p, name);
-       while (p) {
-               char *end_p = strchr(p, ' ');
-               char *q;
-
-               if (!end_p)
-                       end_p = p + strlen(p);
-
-               if (!suffix) {
-                       int i;
-
-                       /* skip the one with any known suffix */
-                       for (i = 0; suffix_tbl[i]; i++) {
-                               q = end_p - strlen(suffix_tbl[i]);
-                               if (!strncmp(q, suffix_tbl[i],
-                                            strlen(suffix_tbl[i])))
-                                       goto next;
-                       }
-                       ck_cmdline = p;
-               } else {
-                       q = end_p - strlen(suffix);
-                       if (!strncmp(q, suffix, strlen(suffix)))
-                               ck_cmdline = p;
-               }
-next:
-               p = strstr(p+1, name);
-       }
-
-       if (!ck_cmdline)
-               return NULL;
-
-       return ck_cmdline;
-}
-
-static int __init __parse_crashkernel(char *cmdline,
-                            unsigned long long system_ram,
-                            unsigned long long *crash_size,
-                            unsigned long long *crash_base,
-                            const char *name,
-                            const char *suffix)
-{
-       char    *first_colon, *first_space;
-       char    *ck_cmdline;
-
-       BUG_ON(!crash_size || !crash_base);
-       *crash_size = 0;
-       *crash_base = 0;
-
-       ck_cmdline = get_last_crashkernel(cmdline, name, suffix);
-
-       if (!ck_cmdline)
-               return -EINVAL;
-
-       ck_cmdline += strlen(name);
-
-       if (suffix)
-               return parse_crashkernel_suffix(ck_cmdline, crash_size,
-                               suffix);
-       /*
-        * if the commandline contains a ':', then that's the extended
-        * syntax -- if not, it must be the classic syntax
-        */
-       first_colon = strchr(ck_cmdline, ':');
-       first_space = strchr(ck_cmdline, ' ');
-       if (first_colon && (!first_space || first_colon < first_space))
-               return parse_crashkernel_mem(ck_cmdline, system_ram,
-                               crash_size, crash_base);
-
-       return parse_crashkernel_simple(ck_cmdline, crash_size, crash_base);
-}
-
-/*
- * That function is the entry point for command line parsing and should be
- * called from the arch-specific code.
- */
-int __init parse_crashkernel(char *cmdline,
-                            unsigned long long system_ram,
-                            unsigned long long *crash_size,
-                            unsigned long long *crash_base)
-{
-       return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base,
-                                       "crashkernel=", NULL);
-}
-
-int __init parse_crashkernel_high(char *cmdline,
-                            unsigned long long system_ram,
-                            unsigned long long *crash_size,
-                            unsigned long long *crash_base)
-{
-       return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base,
-                               "crashkernel=", suffix_tbl[SUFFIX_HIGH]);
-}
-
-int __init parse_crashkernel_low(char *cmdline,
-                            unsigned long long system_ram,
-                            unsigned long long *crash_size,
-                            unsigned long long *crash_base)
-{
-       return __parse_crashkernel(cmdline, system_ram, crash_size, crash_base,
-                               "crashkernel=", suffix_tbl[SUFFIX_LOW]);
-}
-
-static void update_vmcoreinfo_note(void)
-{
-       u32 *buf = vmcoreinfo_note;
-
-       if (!vmcoreinfo_size)
-               return;
-       buf = append_elf_note(buf, VMCOREINFO_NOTE_NAME, 0, vmcoreinfo_data,
-                             vmcoreinfo_size);
-       final_note(buf);
-}
-
-void crash_save_vmcoreinfo(void)
-{
-       vmcoreinfo_append_str("CRASHTIME=%ld\n", get_seconds());
-       update_vmcoreinfo_note();
-}
-
-void vmcoreinfo_append_str(const char *fmt, ...)
-{
-       va_list args;
-       char buf[0x50];
-       size_t r;
-
-       va_start(args, fmt);
-       r = vscnprintf(buf, sizeof(buf), fmt, args);
-       va_end(args);
-
-       r = min(r, vmcoreinfo_max_size - vmcoreinfo_size);
-
-       memcpy(&vmcoreinfo_data[vmcoreinfo_size], buf, r);
-
-       vmcoreinfo_size += r;
-}
-
-/*
- * provide an empty default implementation here -- architecture
- * code may override this
- */
-void __weak arch_crash_save_vmcoreinfo(void)
-{}
-
-phys_addr_t __weak paddr_vmcoreinfo_note(void)
-{
-       return __pa_symbol((unsigned long)(char *)&vmcoreinfo_note);
-}
-
-static int __init crash_save_vmcoreinfo_init(void)
-{
-       VMCOREINFO_OSRELEASE(init_uts_ns.name.release);
-       VMCOREINFO_PAGESIZE(PAGE_SIZE);
-
-       VMCOREINFO_SYMBOL(init_uts_ns);
-       VMCOREINFO_SYMBOL(node_online_map);
-#ifdef CONFIG_MMU
-       VMCOREINFO_SYMBOL(swapper_pg_dir);
-#endif
-       VMCOREINFO_SYMBOL(_stext);
-       VMCOREINFO_SYMBOL(vmap_area_list);
-
-#ifndef CONFIG_NEED_MULTIPLE_NODES
-       VMCOREINFO_SYMBOL(mem_map);
-       VMCOREINFO_SYMBOL(contig_page_data);
-#endif
-#ifdef CONFIG_SPARSEMEM
-       VMCOREINFO_SYMBOL(mem_section);
-       VMCOREINFO_LENGTH(mem_section, NR_SECTION_ROOTS);
-       VMCOREINFO_STRUCT_SIZE(mem_section);
-       VMCOREINFO_OFFSET(mem_section, section_mem_map);
-#endif
-       VMCOREINFO_STRUCT_SIZE(page);
-       VMCOREINFO_STRUCT_SIZE(pglist_data);
-       VMCOREINFO_STRUCT_SIZE(zone);
-       VMCOREINFO_STRUCT_SIZE(free_area);
-       VMCOREINFO_STRUCT_SIZE(list_head);
-       VMCOREINFO_SIZE(nodemask_t);
-       VMCOREINFO_OFFSET(page, flags);
-       VMCOREINFO_OFFSET(page, _refcount);
-       VMCOREINFO_OFFSET(page, mapping);
-       VMCOREINFO_OFFSET(page, lru);
-       VMCOREINFO_OFFSET(page, _mapcount);
-       VMCOREINFO_OFFSET(page, private);
-       VMCOREINFO_OFFSET(page, compound_dtor);
-       VMCOREINFO_OFFSET(page, compound_order);
-       VMCOREINFO_OFFSET(page, compound_head);
-       VMCOREINFO_OFFSET(pglist_data, node_zones);
-       VMCOREINFO_OFFSET(pglist_data, nr_zones);
-#ifdef CONFIG_FLAT_NODE_MEM_MAP
-       VMCOREINFO_OFFSET(pglist_data, node_mem_map);
-#endif
-       VMCOREINFO_OFFSET(pglist_data, node_start_pfn);
-       VMCOREINFO_OFFSET(pglist_data, node_spanned_pages);
-       VMCOREINFO_OFFSET(pglist_data, node_id);
-       VMCOREINFO_OFFSET(zone, free_area);
-       VMCOREINFO_OFFSET(zone, vm_stat);
-       VMCOREINFO_OFFSET(zone, spanned_pages);
-       VMCOREINFO_OFFSET(free_area, free_list);
-       VMCOREINFO_OFFSET(list_head, next);
-       VMCOREINFO_OFFSET(list_head, prev);
-       VMCOREINFO_OFFSET(vmap_area, va_start);
-       VMCOREINFO_OFFSET(vmap_area, list);
-       VMCOREINFO_LENGTH(zone.free_area, MAX_ORDER);
-       log_buf_kexec_setup();
-       VMCOREINFO_LENGTH(free_area.free_list, MIGRATE_TYPES);
-       VMCOREINFO_NUMBER(NR_FREE_PAGES);
-       VMCOREINFO_NUMBER(PG_lru);
-       VMCOREINFO_NUMBER(PG_private);
-       VMCOREINFO_NUMBER(PG_swapcache);
-       VMCOREINFO_NUMBER(PG_slab);
-#ifdef CONFIG_MEMORY_FAILURE
-       VMCOREINFO_NUMBER(PG_hwpoison);
-#endif
-       VMCOREINFO_NUMBER(PG_head_mask);
-       VMCOREINFO_NUMBER(PAGE_BUDDY_MAPCOUNT_VALUE);
-#ifdef CONFIG_HUGETLB_PAGE
-       VMCOREINFO_NUMBER(HUGETLB_PAGE_DTOR);
-#endif
-
-       arch_crash_save_vmcoreinfo();
-       update_vmcoreinfo_note();
-
-       return 0;
-}
-
-subsys_initcall(crash_save_vmcoreinfo_init);
-
 /*
  * Move into place and start executing a preloaded standalone
  * executable.  If nothing was preloaded return an error.
index 0999679d6f26706350cca88f42b970a1306f7037..23cd70651238383ac0b112acf4827ebd1b1ad399 100644 (file)
@@ -125,6 +125,10 @@ static ssize_t kexec_crash_size_store(struct kobject *kobj,
 }
 KERNEL_ATTR_RW(kexec_crash_size);
 
+#endif /* CONFIG_KEXEC_CORE */
+
+#ifdef CONFIG_CRASH_CORE
+
 static ssize_t vmcoreinfo_show(struct kobject *kobj,
                               struct kobj_attribute *attr, char *buf)
 {
@@ -134,7 +138,7 @@ static ssize_t vmcoreinfo_show(struct kobject *kobj,
 }
 KERNEL_ATTR_RO(vmcoreinfo);
 
-#endif /* CONFIG_KEXEC_CORE */
+#endif /* CONFIG_CRASH_CORE */
 
 /* whether file capabilities are enabled */
 static ssize_t fscaps_show(struct kobject *kobj,
@@ -219,6 +223,8 @@ static struct attribute * kernel_attrs[] = {
        &kexec_loaded_attr.attr,
        &kexec_crash_loaded_attr.attr,
        &kexec_crash_size_attr.attr,
+#endif
+#ifdef CONFIG_CRASH_CORE
        &vmcoreinfo_attr.attr,
 #endif
 #ifndef CONFIG_TINY_RCU
index 0a1b3c748478313dded15665692550a7264516ae..c0e31bfee25c2ab0cfefef14b9e24e2ce8a5c523 100644 (file)
@@ -1158,10 +1158,10 @@ print_circular_bug_header(struct lock_list *entry, unsigned int depth,
                return 0;
 
        printk("\n");
-       printk("======================================================\n");
-       printk("[ INFO: possible circular locking dependency detected ]\n");
+       pr_warn("======================================================\n");
+       pr_warn("WARNING: possible circular locking dependency detected\n");
        print_kernel_ident();
-       printk("-------------------------------------------------------\n");
+       pr_warn("------------------------------------------------------\n");
        printk("%s/%d is trying to acquire lock:\n",
                curr->comm, task_pid_nr(curr));
        print_lock(check_src);
@@ -1496,11 +1496,11 @@ print_bad_irq_dependency(struct task_struct *curr,
                return 0;
 
        printk("\n");
-       printk("======================================================\n");
-       printk("[ INFO: %s-safe -> %s-unsafe lock order detected ]\n",
+       pr_warn("=====================================================\n");
+       pr_warn("WARNING: %s-safe -> %s-unsafe lock order detected\n",
                irqclass, irqclass);
        print_kernel_ident();
-       printk("------------------------------------------------------\n");
+       pr_warn("-----------------------------------------------------\n");
        printk("%s/%d [HC%u[%lu]:SC%u[%lu]:HE%u:SE%u] is trying to acquire:\n",
                curr->comm, task_pid_nr(curr),
                curr->hardirq_context, hardirq_count() >> HARDIRQ_SHIFT,
@@ -1725,10 +1725,10 @@ print_deadlock_bug(struct task_struct *curr, struct held_lock *prev,
                return 0;
 
        printk("\n");
-       printk("=============================================\n");
-       printk("[ INFO: possible recursive locking detected ]\n");
+       pr_warn("============================================\n");
+       pr_warn("WARNING: possible recursive locking detected\n");
        print_kernel_ident();
-       printk("---------------------------------------------\n");
+       pr_warn("--------------------------------------------\n");
        printk("%s/%d is trying to acquire lock:\n",
                curr->comm, task_pid_nr(curr));
        print_lock(next);
@@ -2075,10 +2075,10 @@ static void print_collision(struct task_struct *curr,
                        struct lock_chain *chain)
 {
        printk("\n");
-       printk("======================\n");
-       printk("[chain_key collision ]\n");
+       pr_warn("============================\n");
+       pr_warn("WARNING: chain_key collision\n");
        print_kernel_ident();
-       printk("----------------------\n");
+       pr_warn("----------------------------\n");
        printk("%s/%d: ", current->comm, task_pid_nr(current));
        printk("Hash chain already cached but the contents don't match!\n");
 
@@ -2374,10 +2374,10 @@ print_usage_bug(struct task_struct *curr, struct held_lock *this,
                return 0;
 
        printk("\n");
-       printk("=================================\n");
-       printk("[ INFO: inconsistent lock state ]\n");
+       pr_warn("================================\n");
+       pr_warn("WARNING: inconsistent lock state\n");
        print_kernel_ident();
-       printk("---------------------------------\n");
+       pr_warn("--------------------------------\n");
 
        printk("inconsistent {%s} -> {%s} usage.\n",
                usage_str[prev_bit], usage_str[new_bit]);
@@ -2439,10 +2439,10 @@ print_irq_inversion_bug(struct task_struct *curr,
                return 0;
 
        printk("\n");
-       printk("=========================================================\n");
-       printk("[ INFO: possible irq lock inversion dependency detected ]\n");
+       pr_warn("========================================================\n");
+       pr_warn("WARNING: possible irq lock inversion dependency detected\n");
        print_kernel_ident();
-       printk("---------------------------------------------------------\n");
+       pr_warn("--------------------------------------------------------\n");
        printk("%s/%d just changed the state of lock:\n",
                curr->comm, task_pid_nr(curr));
        print_lock(this);
@@ -3190,10 +3190,10 @@ print_lock_nested_lock_not_held(struct task_struct *curr,
                return 0;
 
        printk("\n");
-       printk("==================================\n");
-       printk("[ BUG: Nested lock was not taken ]\n");
+       pr_warn("==================================\n");
+       pr_warn("WARNING: Nested lock was not taken\n");
        print_kernel_ident();
-       printk("----------------------------------\n");
+       pr_warn("----------------------------------\n");
 
        printk("%s/%d is trying to lock:\n", curr->comm, task_pid_nr(curr));
        print_lock(hlock);
@@ -3403,10 +3403,10 @@ print_unlock_imbalance_bug(struct task_struct *curr, struct lockdep_map *lock,
                return 0;
 
        printk("\n");
-       printk("=====================================\n");
-       printk("[ BUG: bad unlock balance detected! ]\n");
+       pr_warn("=====================================\n");
+       pr_warn("WARNING: bad unlock balance detected!\n");
        print_kernel_ident();
-       printk("-------------------------------------\n");
+       pr_warn("-------------------------------------\n");
        printk("%s/%d is trying to release lock (",
                curr->comm, task_pid_nr(curr));
        print_lockdep_cache(lock);
@@ -3975,10 +3975,10 @@ print_lock_contention_bug(struct task_struct *curr, struct lockdep_map *lock,
                return 0;
 
        printk("\n");
-       printk("=================================\n");
-       printk("[ BUG: bad contention detected! ]\n");
+       pr_warn("=================================\n");
+       pr_warn("WARNING: bad contention detected!\n");
        print_kernel_ident();
-       printk("---------------------------------\n");
+       pr_warn("---------------------------------\n");
        printk("%s/%d is trying to contend lock (",
                curr->comm, task_pid_nr(curr));
        print_lockdep_cache(lock);
@@ -4319,10 +4319,10 @@ print_freed_lock_bug(struct task_struct *curr, const void *mem_from,
                return;
 
        printk("\n");
-       printk("=========================\n");
-       printk("[ BUG: held lock freed! ]\n");
+       pr_warn("=========================\n");
+       pr_warn("WARNING: held lock freed!\n");
        print_kernel_ident();
-       printk("-------------------------\n");
+       pr_warn("-------------------------\n");
        printk("%s/%d is freeing memory %p-%p, with a lock still held there!\n",
                curr->comm, task_pid_nr(curr), mem_from, mem_to-1);
        print_lock(hlock);
@@ -4377,11 +4377,11 @@ static void print_held_locks_bug(void)
                return;
 
        printk("\n");
-       printk("=====================================\n");
-       printk("[ BUG: %s/%d still has locks held! ]\n",
+       pr_warn("====================================\n");
+       pr_warn("WARNING: %s/%d still has locks held!\n",
               current->comm, task_pid_nr(current));
        print_kernel_ident();
-       printk("-------------------------------------\n");
+       pr_warn("------------------------------------\n");
        lockdep_print_held_locks(current);
        printk("\nstack backtrace:\n");
        dump_stack();
@@ -4446,7 +4446,7 @@ retry:
        } while_each_thread(g, p);
 
        printk("\n");
-       printk("=============================================\n\n");
+       pr_warn("=============================================\n\n");
 
        if (unlock)
                read_unlock(&tasklist_lock);
@@ -4476,10 +4476,10 @@ asmlinkage __visible void lockdep_sys_exit(void)
                if (!debug_locks_off())
                        return;
                printk("\n");
-               printk("================================================\n");
-               printk("[ BUG: lock held when returning to user space! ]\n");
+               pr_warn("================================================\n");
+               pr_warn("WARNING: lock held when returning to user space!\n");
                print_kernel_ident();
-               printk("------------------------------------------------\n");
+               pr_warn("------------------------------------------------\n");
                printk("%s/%d is leaving the kernel with locks still held!\n",
                                curr->comm, curr->pid);
                lockdep_print_held_locks(curr);
@@ -4496,13 +4496,13 @@ void lockdep_rcu_suspicious(const char *file, const int line, const char *s)
 #endif /* #ifdef CONFIG_PROVE_RCU_REPEATEDLY */
        /* Note: the following can be executed concurrently, so be careful. */
        printk("\n");
-       pr_err("===============================\n");
-       pr_err("[ ERR: suspicious RCU usage.  ]\n");
+       pr_warn("=============================\n");
+       pr_warn("WARNING: suspicious RCU usage\n");
        print_kernel_ident();
-       pr_err("-------------------------------\n");
-       pr_err("%s:%d %s!\n", file, line, s);
-       pr_err("\nother info that might help us debug this:\n\n");
-       pr_err("\n%srcu_scheduler_active = %d, debug_locks = %d\n",
+       pr_warn("-----------------------------\n");
+       printk("%s:%d %s!\n", file, line, s);
+       printk("\nother info that might help us debug this:\n\n");
+       printk("\n%srcu_scheduler_active = %d, debug_locks = %d\n",
               !rcu_lockdep_current_cpu_online()
                        ? "RCU used illegally from offline CPU!\n"
                        : !rcu_is_watching()
index 32fe775a2eafa3eacb97f462143c1def667e2d75..58e366ad36f4e9bf87bf487966a91130feb4f7d7 100644 (file)
@@ -102,10 +102,11 @@ void debug_rt_mutex_print_deadlock(struct rt_mutex_waiter *waiter)
                return;
        }
 
-       printk("\n============================================\n");
-       printk(  "[ BUG: circular locking deadlock detected! ]\n");
-       printk("%s\n", print_tainted());
-       printk(  "--------------------------------------------\n");
+       pr_warn("\n");
+       pr_warn("============================================\n");
+       pr_warn("WARNING: circular locking deadlock detected!\n");
+       pr_warn("%s\n", print_tainted());
+       pr_warn("--------------------------------------------\n");
        printk("%s/%d is deadlocking current task %s/%d\n\n",
               task->comm, task_pid_nr(task),
               current->comm, task_pid_nr(current));
index f37308b733d845526918588d2948673925e7ac5b..4a3665f8f8372aab68b658c24c30678806823eee 100644 (file)
@@ -49,6 +49,9 @@
 #include <linux/rculist.h>
 #include <linux/uaccess.h>
 #include <asm/cacheflush.h>
+#ifdef CONFIG_STRICT_MODULE_RWX
+#include <asm/set_memory.h>
+#endif
 #include <asm/mmu_context.h>
 #include <linux/license.h>
 #include <asm/sections.h>
@@ -2864,7 +2867,7 @@ static int copy_module_from_user(const void __user *umod, unsigned long len,
 
        /* Suck in entire file: we'll want most of it. */
        info->hdr = __vmalloc(info->len,
-                       GFP_KERNEL | __GFP_HIGHMEM | __GFP_NOWARN, PAGE_KERNEL);
+                       GFP_KERNEL | __GFP_NOWARN, PAGE_KERNEL);
        if (!info->hdr)
                return -ENOMEM;
 
index 0143ac0ddceb9c79a2c686e6b10b7265b7b5d925..fd1cde1e45760df67a6cc54fa97959061660ab3f 100644 (file)
@@ -321,8 +321,10 @@ struct pid *alloc_pid(struct pid_namespace *ns)
        }
 
        if (unlikely(is_child_reaper(pid))) {
-               if (pid_ns_prepare_proc(ns))
+               if (pid_ns_prepare_proc(ns)) {
+                       disable_pid_allocation(ns);
                        goto out_free;
+               }
        }
 
        get_pid_ns(ns);
index de461aa0bf9acc933254d34ae2ced925f45eefbc..74a5a7255b4d9cb473cc7708d851c64402cca942 100644 (file)
@@ -277,7 +277,7 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns)
         * if reparented.
         */
        for (;;) {
-               set_current_state(TASK_UNINTERRUPTIBLE);
+               set_current_state(TASK_INTERRUPTIBLE);
                if (pid_ns->nr_hashed == init_pids)
                        break;
                schedule();
@@ -374,6 +374,29 @@ static struct ns_common *pidns_get(struct task_struct *task)
        return ns ? &ns->ns : NULL;
 }
 
+static struct ns_common *pidns_for_children_get(struct task_struct *task)
+{
+       struct pid_namespace *ns = NULL;
+
+       task_lock(task);
+       if (task->nsproxy) {
+               ns = task->nsproxy->pid_ns_for_children;
+               get_pid_ns(ns);
+       }
+       task_unlock(task);
+
+       if (ns) {
+               read_lock(&tasklist_lock);
+               if (!ns->child_reaper) {
+                       put_pid_ns(ns);
+                       ns = NULL;
+               }
+               read_unlock(&tasklist_lock);
+       }
+
+       return ns ? &ns->ns : NULL;
+}
+
 static void pidns_put(struct ns_common *ns)
 {
        put_pid_ns(to_pid_ns(ns));
@@ -443,6 +466,17 @@ const struct proc_ns_operations pidns_operations = {
        .get_parent     = pidns_get_parent,
 };
 
+const struct proc_ns_operations pidns_for_children_operations = {
+       .name           = "pid_for_children",
+       .real_ns_name   = "pid",
+       .type           = CLONE_NEWPID,
+       .get            = pidns_for_children_get,
+       .put            = pidns_put,
+       .install        = pidns_install,
+       .owner          = pidns_owner,
+       .get_parent     = pidns_get_parent,
+};
+
 static __init int pid_namespaces_init(void)
 {
        pid_ns_cachep = KMEM_CACHE(pid_namespace, SLAB_PANIC);
index c7209f060eeb7c8672cf8f07ba9c83ac6c9460ac..78672d324a6ef95394ad72a0b0ba29c7d1155d5d 100644 (file)
@@ -132,7 +132,7 @@ int freeze_processes(void)
        if (!pm_freezing)
                atomic_inc(&system_freezing_cnt);
 
-       pm_wakeup_clear();
+       pm_wakeup_clear(true);
        pr_info("Freezing user space processes ... ");
        pm_freezing = true;
        error = try_to_freeze_tasks(true);
index d79a38de425a0d642834adb5e8ac68ba237db93d..3b1e0f3ad07fa69d9524bcb72d1c6d0bab1a9ad8 100644 (file)
@@ -36,6 +36,9 @@
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
 #include <asm/io.h>
+#ifdef CONFIG_STRICT_KERNEL_RWX
+#include <asm/set_memory.h>
+#endif
 
 #include "power.h"
 
index 15e6baef5c73f90b6817c0b1c4e871ea40e30318..c0248c74d6d4cef6dbf09f485f36686862c29094 100644 (file)
@@ -72,6 +72,8 @@ static void freeze_begin(void)
 
 static void freeze_enter(void)
 {
+       trace_suspend_resume(TPS("machine_suspend"), PM_SUSPEND_FREEZE, true);
+
        spin_lock_irq(&suspend_freeze_lock);
        if (pm_wakeup_pending())
                goto out;
@@ -98,6 +100,27 @@ static void freeze_enter(void)
  out:
        suspend_freeze_state = FREEZE_STATE_NONE;
        spin_unlock_irq(&suspend_freeze_lock);
+
+       trace_suspend_resume(TPS("machine_suspend"), PM_SUSPEND_FREEZE, false);
+}
+
+static void s2idle_loop(void)
+{
+       do {
+               freeze_enter();
+
+               if (freeze_ops && freeze_ops->wake)
+                       freeze_ops->wake();
+
+               dpm_resume_noirq(PMSG_RESUME);
+               if (freeze_ops && freeze_ops->sync)
+                       freeze_ops->sync();
+
+               if (pm_wakeup_pending())
+                       break;
+
+               pm_wakeup_clear(false);
+       } while (!dpm_suspend_noirq(PMSG_SUSPEND));
 }
 
 void freeze_wake(void)
@@ -371,10 +394,8 @@ static int suspend_enter(suspend_state_t state, bool *wakeup)
         * all the devices are suspended.
         */
        if (state == PM_SUSPEND_FREEZE) {
-               trace_suspend_resume(TPS("machine_suspend"), state, true);
-               freeze_enter();
-               trace_suspend_resume(TPS("machine_suspend"), state, false);
-               goto Platform_wake;
+               s2idle_loop();
+               goto Platform_early_resume;
        }
 
        error = disable_nonboot_cpus();
index d5760c42f042f4accfb65de23784bcaa877d9b00..61d41ca418441a15945b376964f6f3ed07ac84b8 100644 (file)
@@ -2,12 +2,13 @@
 
 #include <linux/kernel.h>
 #include <linux/console.h>
+#include <linux/errno.h>
 #include <linux/string.h>
 
 #include "console_cmdline.h"
 #include "braille.h"
 
-char *_braille_console_setup(char **str, char **brl_options)
+int _braille_console_setup(char **str, char **brl_options)
 {
        if (!strncmp(*str, "brl,", 4)) {
                *brl_options = "";
@@ -15,14 +16,14 @@ char *_braille_console_setup(char **str, char **brl_options)
        } else if (!strncmp(*str, "brl=", 4)) {
                *brl_options = *str + 4;
                *str = strchr(*brl_options, ',');
-               if (!*str)
+               if (!*str) {
                        pr_err("need port name after brl=\n");
-               else
-                       *((*str)++) = 0;
-       } else
-               return NULL;
+                       return -EINVAL;
+               }
+               *((*str)++) = 0;
+       }
 
-       return *str;
+       return 0;
 }
 
 int
index 769d771145c881cd78f43c035ea0866adb96b9b9..749a6756843a08e2a5f2a9ae4fa984658b43a65b 100644 (file)
@@ -9,7 +9,14 @@ braille_set_options(struct console_cmdline *c, char *brl_options)
        c->brl_options = brl_options;
 }
 
-char *
+/*
+ * Setup console according to braille options.
+ * Return -EINVAL on syntax error, 0 on success (or no braille option was
+ * actually given).
+ * Modifies str to point to the serial options
+ * Sets brl_options to the parsed braille options.
+ */
+int
 _braille_console_setup(char **str, char **brl_options);
 
 int
@@ -25,10 +32,10 @@ braille_set_options(struct console_cmdline *c, char *brl_options)
 {
 }
 
-static inline char *
+static inline int
 _braille_console_setup(char **str, char **brl_options)
 {
-       return NULL;
+       return 0;
 }
 
 static inline int
index 779479ac9f57bc4feb4276f14d677b88e1b06969..a1aecf44ab07c70ab9f33d455646559313926344 100644 (file)
@@ -32,7 +32,7 @@
 #include <linux/bootmem.h>
 #include <linux/memblock.h>
 #include <linux/syscalls.h>
-#include <linux/kexec.h>
+#include <linux/crash_core.h>
 #include <linux/kdb.h>
 #include <linux/ratelimit.h>
 #include <linux/kmsg_dump.h>
@@ -1002,7 +1002,7 @@ const struct file_operations kmsg_fops = {
        .release = devkmsg_release,
 };
 
-#ifdef CONFIG_KEXEC_CORE
+#ifdef CONFIG_CRASH_CORE
 /*
  * This appends the listed symbols to /proc/vmcore
  *
@@ -1011,7 +1011,7 @@ const struct file_operations kmsg_fops = {
  * symbols are specifically used so that utilities can access and extract the
  * dmesg log from a vmcore file after a crash.
  */
-void log_buf_kexec_setup(void)
+void log_buf_vmcoreinfo_setup(void)
 {
        VMCOREINFO_SYMBOL(log_buf);
        VMCOREINFO_SYMBOL(log_buf_len);
@@ -2641,6 +2641,30 @@ int unregister_console(struct console *console)
 }
 EXPORT_SYMBOL(unregister_console);
 
+/*
+ * Initialize the console device. This is called *early*, so
+ * we can't necessarily depend on lots of kernel help here.
+ * Just do some early initializations, and do the complex setup
+ * later.
+ */
+void __init console_init(void)
+{
+       initcall_t *call;
+
+       /* Setup the default TTY line discipline. */
+       n_tty_init();
+
+       /*
+        * set up the console device so that later boot sequences can
+        * inform about problems etc..
+        */
+       call = __con_initcall_start;
+       while (call < __con_initcall_end) {
+               (*call)();
+               call++;
+       }
+}
+
 /*
  * Some boot consoles access data that is in the init section and which will
  * be discarded after the initcalls have been run. To make sure that no code
index 18dfc485225c3954ccf29a8743bc636f10db7d41..23803c7d51804debb62b91934cdba42f305c70d3 100644 (file)
@@ -3,10 +3,13 @@
 KCOV_INSTRUMENT := n
 
 obj-y += update.o sync.o
-obj-$(CONFIG_SRCU) += srcu.o
+obj-$(CONFIG_CLASSIC_SRCU) += srcu.o
+obj-$(CONFIG_TREE_SRCU) += srcutree.o
+obj-$(CONFIG_TINY_SRCU) += srcutiny.o
 obj-$(CONFIG_RCU_TORTURE_TEST) += rcutorture.o
 obj-$(CONFIG_RCU_PERF_TEST) += rcuperf.o
 obj-$(CONFIG_TREE_RCU) += tree.o
 obj-$(CONFIG_PREEMPT_RCU) += tree.o
 obj-$(CONFIG_TREE_RCU_TRACE) += tree_trace.o
 obj-$(CONFIG_TINY_RCU) += tiny.o
+obj-$(CONFIG_RCU_NEED_SEGCBLIST) += rcu_segcblist.o
index 0d6ff3e471be6c1597e0e78fb90d07eb0ce9c546..73e16ec4054b83d163f58d6786df4e5fb6a00ae4 100644 (file)
 #define DYNTICK_TASK_EXIT_IDLE    (DYNTICK_TASK_NEST_VALUE + \
                                    DYNTICK_TASK_FLAG)
 
+
+/*
+ * Grace-period counter management.
+ */
+
+#define RCU_SEQ_CTR_SHIFT      2
+#define RCU_SEQ_STATE_MASK     ((1 << RCU_SEQ_CTR_SHIFT) - 1)
+
+/*
+ * Return the counter portion of a sequence number previously returned
+ * by rcu_seq_snap() or rcu_seq_current().
+ */
+static inline unsigned long rcu_seq_ctr(unsigned long s)
+{
+       return s >> RCU_SEQ_CTR_SHIFT;
+}
+
+/*
+ * Return the state portion of a sequence number previously returned
+ * by rcu_seq_snap() or rcu_seq_current().
+ */
+static inline int rcu_seq_state(unsigned long s)
+{
+       return s & RCU_SEQ_STATE_MASK;
+}
+
+/*
+ * Set the state portion of the pointed-to sequence number.
+ * The caller is responsible for preventing conflicting updates.
+ */
+static inline void rcu_seq_set_state(unsigned long *sp, int newstate)
+{
+       WARN_ON_ONCE(newstate & ~RCU_SEQ_STATE_MASK);
+       WRITE_ONCE(*sp, (*sp & ~RCU_SEQ_STATE_MASK) + newstate);
+}
+
+/* Adjust sequence number for start of update-side operation. */
+static inline void rcu_seq_start(unsigned long *sp)
+{
+       WRITE_ONCE(*sp, *sp + 1);
+       smp_mb(); /* Ensure update-side operation after counter increment. */
+       WARN_ON_ONCE(rcu_seq_state(*sp) != 1);
+}
+
+/* Adjust sequence number for end of update-side operation. */
+static inline void rcu_seq_end(unsigned long *sp)
+{
+       smp_mb(); /* Ensure update-side operation before counter increment. */
+       WARN_ON_ONCE(!rcu_seq_state(*sp));
+       WRITE_ONCE(*sp, (*sp | RCU_SEQ_STATE_MASK) + 1);
+}
+
+/* Take a snapshot of the update side's sequence number. */
+static inline unsigned long rcu_seq_snap(unsigned long *sp)
+{
+       unsigned long s;
+
+       s = (READ_ONCE(*sp) + 2 * RCU_SEQ_STATE_MASK + 1) & ~RCU_SEQ_STATE_MASK;
+       smp_mb(); /* Above access must not bleed into critical section. */
+       return s;
+}
+
+/* Return the current value the update side's sequence number, no ordering. */
+static inline unsigned long rcu_seq_current(unsigned long *sp)
+{
+       return READ_ONCE(*sp);
+}
+
+/*
+ * Given a snapshot from rcu_seq_snap(), determine whether or not a
+ * full update-side operation has occurred.
+ */
+static inline bool rcu_seq_done(unsigned long *sp, unsigned long s)
+{
+       return ULONG_CMP_GE(READ_ONCE(*sp), s);
+}
+
 /*
  * debug_rcu_head_queue()/debug_rcu_head_unqueue() are used internally
  * by call_rcu() and rcu callback execution, and are therefore not part of the
@@ -109,12 +186,12 @@ static inline bool __rcu_reclaim(const char *rn, struct rcu_head *head)
 
        rcu_lock_acquire(&rcu_callback_map);
        if (__is_kfree_rcu_offset(offset)) {
-               RCU_TRACE(trace_rcu_invoke_kfree_callback(rn, head, offset));
+               RCU_TRACE(trace_rcu_invoke_kfree_callback(rn, head, offset);)
                kfree((void *)head - offset);
                rcu_lock_release(&rcu_callback_map);
                return true;
        } else {
-               RCU_TRACE(trace_rcu_invoke_callback(rn, head));
+               RCU_TRACE(trace_rcu_invoke_callback(rn, head);)
                head->func(head);
                rcu_lock_release(&rcu_callback_map);
                return false;
@@ -144,4 +221,76 @@ void rcu_test_sync_prims(void);
  */
 extern void resched_cpu(int cpu);
 
+#if defined(SRCU) || !defined(TINY_RCU)
+
+#include <linux/rcu_node_tree.h>
+
+extern int rcu_num_lvls;
+extern int num_rcu_lvl[];
+extern int rcu_num_nodes;
+static bool rcu_fanout_exact;
+static int rcu_fanout_leaf;
+
+/*
+ * Compute the per-level fanout, either using the exact fanout specified
+ * or balancing the tree, depending on the rcu_fanout_exact boot parameter.
+ */
+static inline void rcu_init_levelspread(int *levelspread, const int *levelcnt)
+{
+       int i;
+
+       if (rcu_fanout_exact) {
+               levelspread[rcu_num_lvls - 1] = rcu_fanout_leaf;
+               for (i = rcu_num_lvls - 2; i >= 0; i--)
+                       levelspread[i] = RCU_FANOUT;
+       } else {
+               int ccur;
+               int cprv;
+
+               cprv = nr_cpu_ids;
+               for (i = rcu_num_lvls - 1; i >= 0; i--) {
+                       ccur = levelcnt[i];
+                       levelspread[i] = (cprv + ccur - 1) / ccur;
+                       cprv = ccur;
+               }
+       }
+}
+
+/*
+ * Do a full breadth-first scan of the rcu_node structures for the
+ * specified rcu_state structure.
+ */
+#define rcu_for_each_node_breadth_first(rsp, rnp) \
+       for ((rnp) = &(rsp)->node[0]; \
+            (rnp) < &(rsp)->node[rcu_num_nodes]; (rnp)++)
+
+/*
+ * Do a breadth-first scan of the non-leaf rcu_node structures for the
+ * specified rcu_state structure.  Note that if there is a singleton
+ * rcu_node tree with but one rcu_node structure, this loop is a no-op.
+ */
+#define rcu_for_each_nonleaf_node_breadth_first(rsp, rnp) \
+       for ((rnp) = &(rsp)->node[0]; \
+            (rnp) < (rsp)->level[rcu_num_lvls - 1]; (rnp)++)
+
+/*
+ * Scan the leaves of the rcu_node hierarchy for the specified rcu_state
+ * structure.  Note that if there is a singleton rcu_node tree with but
+ * one rcu_node structure, this loop -will- visit the rcu_node structure.
+ * It is still a leaf node, even if it is also the root node.
+ */
+#define rcu_for_each_leaf_node(rsp, rnp) \
+       for ((rnp) = (rsp)->level[rcu_num_lvls - 1]; \
+            (rnp) < &(rsp)->node[rcu_num_nodes]; (rnp)++)
+
+/*
+ * Iterate over all possible CPUs in a leaf RCU node.
+ */
+#define for_each_leaf_node_possible_cpu(rnp, cpu) \
+       for ((cpu) = cpumask_next(rnp->grplo - 1, cpu_possible_mask); \
+            cpu <= rnp->grphi; \
+            cpu = cpumask_next((cpu), cpu_possible_mask))
+
+#endif /* #if defined(SRCU) || !defined(TINY_RCU) */
+
 #endif /* __LINUX_RCU_H */
diff --git a/kernel/rcu/rcu_segcblist.c b/kernel/rcu/rcu_segcblist.c
new file mode 100644 (file)
index 0000000..2b62a38
--- /dev/null
@@ -0,0 +1,505 @@
+/*
+ * RCU segmented callback lists, function definitions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you can access it online at
+ * http://www.gnu.org/licenses/gpl-2.0.html.
+ *
+ * Copyright IBM Corporation, 2017
+ *
+ * Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+
+#include "rcu_segcblist.h"
+
+/* Initialize simple callback list. */
+void rcu_cblist_init(struct rcu_cblist *rclp)
+{
+       rclp->head = NULL;
+       rclp->tail = &rclp->head;
+       rclp->len = 0;
+       rclp->len_lazy = 0;
+}
+
+/*
+ * Debug function to actually count the number of callbacks.
+ * If the number exceeds the limit specified, return -1.
+ */
+long rcu_cblist_count_cbs(struct rcu_cblist *rclp, long lim)
+{
+       int cnt = 0;
+       struct rcu_head **rhpp = &rclp->head;
+
+       for (;;) {
+               if (!*rhpp)
+                       return cnt;
+               if (++cnt > lim)
+                       return -1;
+               rhpp = &(*rhpp)->next;
+       }
+}
+
+/*
+ * Dequeue the oldest rcu_head structure from the specified callback
+ * list.  This function assumes that the callback is non-lazy, but
+ * the caller can later invoke rcu_cblist_dequeued_lazy() if it
+ * finds otherwise (and if it cares about laziness).  This allows
+ * different users to have different ways of determining laziness.
+ */
+struct rcu_head *rcu_cblist_dequeue(struct rcu_cblist *rclp)
+{
+       struct rcu_head *rhp;
+
+       rhp = rclp->head;
+       if (!rhp)
+               return NULL;
+       rclp->len--;
+       rclp->head = rhp->next;
+       if (!rclp->head)
+               rclp->tail = &rclp->head;
+       return rhp;
+}
+
+/*
+ * Initialize an rcu_segcblist structure.
+ */
+void rcu_segcblist_init(struct rcu_segcblist *rsclp)
+{
+       int i;
+
+       BUILD_BUG_ON(RCU_NEXT_TAIL + 1 != ARRAY_SIZE(rsclp->gp_seq));
+       BUILD_BUG_ON(ARRAY_SIZE(rsclp->tails) != ARRAY_SIZE(rsclp->gp_seq));
+       rsclp->head = NULL;
+       for (i = 0; i < RCU_CBLIST_NSEGS; i++)
+               rsclp->tails[i] = &rsclp->head;
+       rsclp->len = 0;
+       rsclp->len_lazy = 0;
+}
+
+/*
+ * Disable the specified rcu_segcblist structure, so that callbacks can
+ * no longer be posted to it.  This structure must be empty.
+ */
+void rcu_segcblist_disable(struct rcu_segcblist *rsclp)
+{
+       WARN_ON_ONCE(!rcu_segcblist_empty(rsclp));
+       WARN_ON_ONCE(rcu_segcblist_n_cbs(rsclp));
+       WARN_ON_ONCE(rcu_segcblist_n_lazy_cbs(rsclp));
+       rsclp->tails[RCU_NEXT_TAIL] = NULL;
+}
+
+/*
+ * Is the specified segment of the specified rcu_segcblist structure
+ * empty of callbacks?
+ */
+bool rcu_segcblist_segempty(struct rcu_segcblist *rsclp, int seg)
+{
+       if (seg == RCU_DONE_TAIL)
+               return &rsclp->head == rsclp->tails[RCU_DONE_TAIL];
+       return rsclp->tails[seg - 1] == rsclp->tails[seg];
+}
+
+/*
+ * Does the specified rcu_segcblist structure contain callbacks that
+ * are ready to be invoked?
+ */
+bool rcu_segcblist_ready_cbs(struct rcu_segcblist *rsclp)
+{
+       return rcu_segcblist_is_enabled(rsclp) &&
+              &rsclp->head != rsclp->tails[RCU_DONE_TAIL];
+}
+
+/*
+ * Does the specified rcu_segcblist structure contain callbacks that
+ * are still pending, that is, not yet ready to be invoked?
+ */
+bool rcu_segcblist_pend_cbs(struct rcu_segcblist *rsclp)
+{
+       return rcu_segcblist_is_enabled(rsclp) &&
+              !rcu_segcblist_restempty(rsclp, RCU_DONE_TAIL);
+}
+
+/*
+ * Dequeue and return the first ready-to-invoke callback.  If there
+ * are no ready-to-invoke callbacks, return NULL.  Disables interrupts
+ * to avoid interference.  Does not protect from interference from other
+ * CPUs or tasks.
+ */
+struct rcu_head *rcu_segcblist_dequeue(struct rcu_segcblist *rsclp)
+{
+       unsigned long flags;
+       int i;
+       struct rcu_head *rhp;
+
+       local_irq_save(flags);
+       if (!rcu_segcblist_ready_cbs(rsclp)) {
+               local_irq_restore(flags);
+               return NULL;
+       }
+       rhp = rsclp->head;
+       BUG_ON(!rhp);
+       rsclp->head = rhp->next;
+       for (i = RCU_DONE_TAIL; i < RCU_CBLIST_NSEGS; i++) {
+               if (rsclp->tails[i] != &rhp->next)
+                       break;
+               rsclp->tails[i] = &rsclp->head;
+       }
+       smp_mb(); /* Dequeue before decrement for rcu_barrier(). */
+       WRITE_ONCE(rsclp->len, rsclp->len - 1);
+       local_irq_restore(flags);
+       return rhp;
+}
+
+/*
+ * Account for the fact that a previously dequeued callback turned out
+ * to be marked as lazy.
+ */
+void rcu_segcblist_dequeued_lazy(struct rcu_segcblist *rsclp)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       rsclp->len_lazy--;
+       local_irq_restore(flags);
+}
+
+/*
+ * Return a pointer to the first callback in the specified rcu_segcblist
+ * structure.  This is useful for diagnostics.
+ */
+struct rcu_head *rcu_segcblist_first_cb(struct rcu_segcblist *rsclp)
+{
+       if (rcu_segcblist_is_enabled(rsclp))
+               return rsclp->head;
+       return NULL;
+}
+
+/*
+ * Return a pointer to the first pending callback in the specified
+ * rcu_segcblist structure.  This is useful just after posting a given
+ * callback -- if that callback is the first pending callback, then
+ * you cannot rely on someone else having already started up the required
+ * grace period.
+ */
+struct rcu_head *rcu_segcblist_first_pend_cb(struct rcu_segcblist *rsclp)
+{
+       if (rcu_segcblist_is_enabled(rsclp))
+               return *rsclp->tails[RCU_DONE_TAIL];
+       return NULL;
+}
+
+/*
+ * Does the specified rcu_segcblist structure contain callbacks that
+ * have not yet been processed beyond having been posted, that is,
+ * does it contain callbacks in its last segment?
+ */
+bool rcu_segcblist_new_cbs(struct rcu_segcblist *rsclp)
+{
+       return rcu_segcblist_is_enabled(rsclp) &&
+              !rcu_segcblist_restempty(rsclp, RCU_NEXT_READY_TAIL);
+}
+
+/*
+ * Enqueue the specified callback onto the specified rcu_segcblist
+ * structure, updating accounting as needed.  Note that the ->len
+ * field may be accessed locklessly, hence the WRITE_ONCE().
+ * The ->len field is used by rcu_barrier() and friends to determine
+ * if it must post a callback on this structure, and it is OK
+ * for rcu_barrier() to sometimes post callbacks needlessly, but
+ * absolutely not OK for it to ever miss posting a callback.
+ */
+void rcu_segcblist_enqueue(struct rcu_segcblist *rsclp,
+                          struct rcu_head *rhp, bool lazy)
+{
+       WRITE_ONCE(rsclp->len, rsclp->len + 1); /* ->len sampled locklessly. */
+       if (lazy)
+               rsclp->len_lazy++;
+       smp_mb(); /* Ensure counts are updated before callback is enqueued. */
+       rhp->next = NULL;
+       *rsclp->tails[RCU_NEXT_TAIL] = rhp;
+       rsclp->tails[RCU_NEXT_TAIL] = &rhp->next;
+}
+
+/*
+ * Entrain the specified callback onto the specified rcu_segcblist at
+ * the end of the last non-empty segment.  If the entire rcu_segcblist
+ * is empty, make no change, but return false.
+ *
+ * This is intended for use by rcu_barrier()-like primitives, -not-
+ * for normal grace-period use.  IMPORTANT:  The callback you enqueue
+ * will wait for all prior callbacks, NOT necessarily for a grace
+ * period.  You have been warned.
+ */
+bool rcu_segcblist_entrain(struct rcu_segcblist *rsclp,
+                          struct rcu_head *rhp, bool lazy)
+{
+       int i;
+
+       if (rcu_segcblist_n_cbs(rsclp) == 0)
+               return false;
+       WRITE_ONCE(rsclp->len, rsclp->len + 1);
+       if (lazy)
+               rsclp->len_lazy++;
+       smp_mb(); /* Ensure counts are updated before callback is entrained. */
+       rhp->next = NULL;
+       for (i = RCU_NEXT_TAIL; i > RCU_DONE_TAIL; i--)
+               if (rsclp->tails[i] != rsclp->tails[i - 1])
+                       break;
+       *rsclp->tails[i] = rhp;
+       for (; i <= RCU_NEXT_TAIL; i++)
+               rsclp->tails[i] = &rhp->next;
+       return true;
+}
+
+/*
+ * Extract only the counts from the specified rcu_segcblist structure,
+ * and place them in the specified rcu_cblist structure.  This function
+ * supports both callback orphaning and invocation, hence the separation
+ * of counts and callbacks.  (Callbacks ready for invocation must be
+ * orphaned and adopted separately from pending callbacks, but counts
+ * apply to all callbacks.  Locking must be used to make sure that
+ * both orphaned-callbacks lists are consistent.)
+ */
+void rcu_segcblist_extract_count(struct rcu_segcblist *rsclp,
+                                              struct rcu_cblist *rclp)
+{
+       rclp->len_lazy += rsclp->len_lazy;
+       rclp->len += rsclp->len;
+       rsclp->len_lazy = 0;
+       WRITE_ONCE(rsclp->len, 0); /* ->len sampled locklessly. */
+}
+
+/*
+ * Extract only those callbacks ready to be invoked from the specified
+ * rcu_segcblist structure and place them in the specified rcu_cblist
+ * structure.
+ */
+void rcu_segcblist_extract_done_cbs(struct rcu_segcblist *rsclp,
+                                   struct rcu_cblist *rclp)
+{
+       int i;
+
+       if (!rcu_segcblist_ready_cbs(rsclp))
+               return; /* Nothing to do. */
+       *rclp->tail = rsclp->head;
+       rsclp->head = *rsclp->tails[RCU_DONE_TAIL];
+       *rsclp->tails[RCU_DONE_TAIL] = NULL;
+       rclp->tail = rsclp->tails[RCU_DONE_TAIL];
+       for (i = RCU_CBLIST_NSEGS - 1; i >= RCU_DONE_TAIL; i--)
+               if (rsclp->tails[i] == rsclp->tails[RCU_DONE_TAIL])
+                       rsclp->tails[i] = &rsclp->head;
+}
+
+/*
+ * Extract only those callbacks still pending (not yet ready to be
+ * invoked) from the specified rcu_segcblist structure and place them in
+ * the specified rcu_cblist structure.  Note that this loses information
+ * about any callbacks that might have been partway done waiting for
+ * their grace period.  Too bad!  They will have to start over.
+ */
+void rcu_segcblist_extract_pend_cbs(struct rcu_segcblist *rsclp,
+                                   struct rcu_cblist *rclp)
+{
+       int i;
+
+       if (!rcu_segcblist_pend_cbs(rsclp))
+               return; /* Nothing to do. */
+       *rclp->tail = *rsclp->tails[RCU_DONE_TAIL];
+       rclp->tail = rsclp->tails[RCU_NEXT_TAIL];
+       *rsclp->tails[RCU_DONE_TAIL] = NULL;
+       for (i = RCU_DONE_TAIL + 1; i < RCU_CBLIST_NSEGS; i++)
+               rsclp->tails[i] = rsclp->tails[RCU_DONE_TAIL];
+}
+
+/*
+ * Insert counts from the specified rcu_cblist structure in the
+ * specified rcu_segcblist structure.
+ */
+void rcu_segcblist_insert_count(struct rcu_segcblist *rsclp,
+                               struct rcu_cblist *rclp)
+{
+       rsclp->len_lazy += rclp->len_lazy;
+       /* ->len sampled locklessly. */
+       WRITE_ONCE(rsclp->len, rsclp->len + rclp->len);
+       rclp->len_lazy = 0;
+       rclp->len = 0;
+}
+
+/*
+ * Move callbacks from the specified rcu_cblist to the beginning of the
+ * done-callbacks segment of the specified rcu_segcblist.
+ */
+void rcu_segcblist_insert_done_cbs(struct rcu_segcblist *rsclp,
+                                  struct rcu_cblist *rclp)
+{
+       int i;
+
+       if (!rclp->head)
+               return; /* No callbacks to move. */
+       *rclp->tail = rsclp->head;
+       rsclp->head = rclp->head;
+       for (i = RCU_DONE_TAIL; i < RCU_CBLIST_NSEGS; i++)
+               if (&rsclp->head == rsclp->tails[i])
+                       rsclp->tails[i] = rclp->tail;
+               else
+                       break;
+       rclp->head = NULL;
+       rclp->tail = &rclp->head;
+}
+
+/*
+ * Move callbacks from the specified rcu_cblist to the end of the
+ * new-callbacks segment of the specified rcu_segcblist.
+ */
+void rcu_segcblist_insert_pend_cbs(struct rcu_segcblist *rsclp,
+                                  struct rcu_cblist *rclp)
+{
+       if (!rclp->head)
+               return; /* Nothing to do. */
+       *rsclp->tails[RCU_NEXT_TAIL] = rclp->head;
+       rsclp->tails[RCU_NEXT_TAIL] = rclp->tail;
+       rclp->head = NULL;
+       rclp->tail = &rclp->head;
+}
+
+/*
+ * Advance the callbacks in the specified rcu_segcblist structure based
+ * on the current value passed in for the grace-period counter.
+ */
+void rcu_segcblist_advance(struct rcu_segcblist *rsclp, unsigned long seq)
+{
+       int i, j;
+
+       WARN_ON_ONCE(!rcu_segcblist_is_enabled(rsclp));
+       if (rcu_segcblist_restempty(rsclp, RCU_DONE_TAIL))
+               return;
+
+       /*
+        * Find all callbacks whose ->gp_seq numbers indicate that they
+        * are ready to invoke, and put them into the RCU_DONE_TAIL segment.
+        */
+       for (i = RCU_WAIT_TAIL; i < RCU_NEXT_TAIL; i++) {
+               if (ULONG_CMP_LT(seq, rsclp->gp_seq[i]))
+                       break;
+               rsclp->tails[RCU_DONE_TAIL] = rsclp->tails[i];
+       }
+
+       /* If no callbacks moved, nothing more need be done. */
+       if (i == RCU_WAIT_TAIL)
+               return;
+
+       /* Clean up tail pointers that might have been misordered above. */
+       for (j = RCU_WAIT_TAIL; j < i; j++)
+               rsclp->tails[j] = rsclp->tails[RCU_DONE_TAIL];
+
+       /*
+        * Callbacks moved, so clean up the misordered ->tails[] pointers
+        * that now point into the middle of the list of ready-to-invoke
+        * callbacks.  The overall effect is to copy down the later pointers
+        * into the gap that was created by the now-ready segments.
+        */
+       for (j = RCU_WAIT_TAIL; i < RCU_NEXT_TAIL; i++, j++) {
+               if (rsclp->tails[j] == rsclp->tails[RCU_NEXT_TAIL])
+                       break;  /* No more callbacks. */
+               rsclp->tails[j] = rsclp->tails[i];
+               rsclp->gp_seq[j] = rsclp->gp_seq[i];
+       }
+}
+
+/*
+ * "Accelerate" callbacks based on more-accurate grace-period information.
+ * The reason for this is that RCU does not synchronize the beginnings and
+ * ends of grace periods, and that callbacks are posted locally.  This in
+ * turn means that the callbacks must be labelled conservatively early
+ * on, as getting exact information would degrade both performance and
+ * scalability.  When more accurate grace-period information becomes
+ * available, previously posted callbacks can be "accelerated", marking
+ * them to complete at the end of the earlier grace period.
+ *
+ * This function operates on an rcu_segcblist structure, and also the
+ * grace-period sequence number seq at which new callbacks would become
+ * ready to invoke.  Returns true if there are callbacks that won't be
+ * ready to invoke until seq, false otherwise.
+ */
+bool rcu_segcblist_accelerate(struct rcu_segcblist *rsclp, unsigned long seq)
+{
+       int i;
+
+       WARN_ON_ONCE(!rcu_segcblist_is_enabled(rsclp));
+       if (rcu_segcblist_restempty(rsclp, RCU_DONE_TAIL))
+               return false;
+
+       /*
+        * Find the segment preceding the oldest segment of callbacks
+        * whose ->gp_seq[] completion is at or after that passed in via
+        * "seq", skipping any empty segments.  This oldest segment, along
+        * with any later segments, can be merged in with any newly arrived
+        * callbacks in the RCU_NEXT_TAIL segment, and assigned "seq"
+        * as their ->gp_seq[] grace-period completion sequence number.
+        */
+       for (i = RCU_NEXT_READY_TAIL; i > RCU_DONE_TAIL; i--)
+               if (rsclp->tails[i] != rsclp->tails[i - 1] &&
+                   ULONG_CMP_LT(rsclp->gp_seq[i], seq))
+                       break;
+
+       /*
+        * If all the segments contain callbacks that correspond to
+        * earlier grace-period sequence numbers than "seq", leave.
+        * Assuming that the rcu_segcblist structure has enough
+        * segments in its arrays, this can only happen if some of
+        * the non-done segments contain callbacks that really are
+        * ready to invoke.  This situation will get straightened
+        * out by the next call to rcu_segcblist_advance().
+        *
+        * Also advance to the oldest segment of callbacks whose
+        * ->gp_seq[] completion is at or after that passed in via "seq",
+        * skipping any empty segments.
+        */
+       if (++i >= RCU_NEXT_TAIL)
+               return false;
+
+       /*
+        * Merge all later callbacks, including newly arrived callbacks,
+        * into the segment located by the for-loop above.  Assign "seq"
+        * as the ->gp_seq[] value in order to correctly handle the case
+        * where there were no pending callbacks in the rcu_segcblist
+        * structure other than in the RCU_NEXT_TAIL segment.
+        */
+       for (; i < RCU_NEXT_TAIL; i++) {
+               rsclp->tails[i] = rsclp->tails[RCU_NEXT_TAIL];
+               rsclp->gp_seq[i] = seq;
+       }
+       return true;
+}
+
+/*
+ * Scan the specified rcu_segcblist structure for callbacks that need
+ * a grace period later than the one specified by "seq".  We don't look
+ * at the RCU_DONE_TAIL or RCU_NEXT_TAIL segments because they don't
+ * have a grace-period sequence number.
+ */
+bool rcu_segcblist_future_gp_needed(struct rcu_segcblist *rsclp,
+                                   unsigned long seq)
+{
+       int i;
+
+       for (i = RCU_WAIT_TAIL; i < RCU_NEXT_TAIL; i++)
+               if (rsclp->tails[i - 1] != rsclp->tails[i] &&
+                   ULONG_CMP_LT(seq, rsclp->gp_seq[i]))
+                       return true;
+       return false;
+}
diff --git a/kernel/rcu/rcu_segcblist.h b/kernel/rcu/rcu_segcblist.h
new file mode 100644 (file)
index 0000000..6e36e36
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * RCU segmented callback lists, internal-to-rcu header file
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you can access it online at
+ * http://www.gnu.org/licenses/gpl-2.0.html.
+ *
+ * Copyright IBM Corporation, 2017
+ *
+ * Authors: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+ */
+
+#include <linux/rcu_segcblist.h>
+
+/*
+ * Account for the fact that a previously dequeued callback turned out
+ * to be marked as lazy.
+ */
+static inline void rcu_cblist_dequeued_lazy(struct rcu_cblist *rclp)
+{
+       rclp->len_lazy--;
+}
+
+/*
+ * Interim function to return rcu_cblist head pointer.  Longer term, the
+ * rcu_cblist will be used more pervasively, removing the need for this
+ * function.
+ */
+static inline struct rcu_head *rcu_cblist_head(struct rcu_cblist *rclp)
+{
+       return rclp->head;
+}
+
+/*
+ * Interim function to return rcu_cblist head pointer.  Longer term, the
+ * rcu_cblist will be used more pervasively, removing the need for this
+ * function.
+ */
+static inline struct rcu_head **rcu_cblist_tail(struct rcu_cblist *rclp)
+{
+       WARN_ON_ONCE(!rclp->head);
+       return rclp->tail;
+}
+
+void rcu_cblist_init(struct rcu_cblist *rclp);
+long rcu_cblist_count_cbs(struct rcu_cblist *rclp, long lim);
+struct rcu_head *rcu_cblist_dequeue(struct rcu_cblist *rclp);
+
+/*
+ * Is the specified rcu_segcblist structure empty?
+ *
+ * But careful!  The fact that the ->head field is NULL does not
+ * necessarily imply that there are no callbacks associated with
+ * this structure.  When callbacks are being invoked, they are
+ * removed as a group.  If callback invocation must be preempted,
+ * the remaining callbacks will be added back to the list.  Either
+ * way, the counts are updated later.
+ *
+ * So it is often the case that rcu_segcblist_n_cbs() should be used
+ * instead.
+ */
+static inline bool rcu_segcblist_empty(struct rcu_segcblist *rsclp)
+{
+       return !rsclp->head;
+}
+
+/* Return number of callbacks in segmented callback list. */
+static inline long rcu_segcblist_n_cbs(struct rcu_segcblist *rsclp)
+{
+       return READ_ONCE(rsclp->len);
+}
+
+/* Return number of lazy callbacks in segmented callback list. */
+static inline long rcu_segcblist_n_lazy_cbs(struct rcu_segcblist *rsclp)
+{
+       return rsclp->len_lazy;
+}
+
+/* Return number of lazy callbacks in segmented callback list. */
+static inline long rcu_segcblist_n_nonlazy_cbs(struct rcu_segcblist *rsclp)
+{
+       return rsclp->len - rsclp->len_lazy;
+}
+
+/*
+ * Is the specified rcu_segcblist enabled, for example, not corresponding
+ * to an offline or callback-offloaded CPU?
+ */
+static inline bool rcu_segcblist_is_enabled(struct rcu_segcblist *rsclp)
+{
+       return !!rsclp->tails[RCU_NEXT_TAIL];
+}
+
+/*
+ * Are all segments following the specified segment of the specified
+ * rcu_segcblist structure empty of callbacks?  (The specified
+ * segment might well contain callbacks.)
+ */
+static inline bool rcu_segcblist_restempty(struct rcu_segcblist *rsclp, int seg)
+{
+       return !*rsclp->tails[seg];
+}
+
+/*
+ * Interim function to return rcu_segcblist head pointer.  Longer term, the
+ * rcu_segcblist will be used more pervasively, removing the need for this
+ * function.
+ */
+static inline struct rcu_head *rcu_segcblist_head(struct rcu_segcblist *rsclp)
+{
+       return rsclp->head;
+}
+
+/*
+ * Interim function to return rcu_segcblist head pointer.  Longer term, the
+ * rcu_segcblist will be used more pervasively, removing the need for this
+ * function.
+ */
+static inline struct rcu_head **rcu_segcblist_tail(struct rcu_segcblist *rsclp)
+{
+       WARN_ON_ONCE(rcu_segcblist_empty(rsclp));
+       return rsclp->tails[RCU_NEXT_TAIL];
+}
+
+void rcu_segcblist_init(struct rcu_segcblist *rsclp);
+void rcu_segcblist_disable(struct rcu_segcblist *rsclp);
+bool rcu_segcblist_segempty(struct rcu_segcblist *rsclp, int seg);
+bool rcu_segcblist_ready_cbs(struct rcu_segcblist *rsclp);
+bool rcu_segcblist_pend_cbs(struct rcu_segcblist *rsclp);
+struct rcu_head *rcu_segcblist_dequeue(struct rcu_segcblist *rsclp);
+void rcu_segcblist_dequeued_lazy(struct rcu_segcblist *rsclp);
+struct rcu_head *rcu_segcblist_first_cb(struct rcu_segcblist *rsclp);
+struct rcu_head *rcu_segcblist_first_pend_cb(struct rcu_segcblist *rsclp);
+bool rcu_segcblist_new_cbs(struct rcu_segcblist *rsclp);
+void rcu_segcblist_enqueue(struct rcu_segcblist *rsclp,
+                          struct rcu_head *rhp, bool lazy);
+bool rcu_segcblist_entrain(struct rcu_segcblist *rsclp,
+                          struct rcu_head *rhp, bool lazy);
+void rcu_segcblist_extract_count(struct rcu_segcblist *rsclp,
+                                struct rcu_cblist *rclp);
+void rcu_segcblist_extract_done_cbs(struct rcu_segcblist *rsclp,
+                                   struct rcu_cblist *rclp);
+void rcu_segcblist_extract_pend_cbs(struct rcu_segcblist *rsclp,
+                                   struct rcu_cblist *rclp);
+void rcu_segcblist_insert_count(struct rcu_segcblist *rsclp,
+                               struct rcu_cblist *rclp);
+void rcu_segcblist_insert_done_cbs(struct rcu_segcblist *rsclp,
+                                  struct rcu_cblist *rclp);
+void rcu_segcblist_insert_pend_cbs(struct rcu_segcblist *rsclp,
+                                  struct rcu_cblist *rclp);
+void rcu_segcblist_advance(struct rcu_segcblist *rsclp, unsigned long seq);
+bool rcu_segcblist_accelerate(struct rcu_segcblist *rsclp, unsigned long seq);
+bool rcu_segcblist_future_gp_needed(struct rcu_segcblist *rsclp,
+                                   unsigned long seq);
index cccc417a813502f8bc0f6d0af930b25d3d1b4f52..ae6e574d4cf5c3fbdd8ab9a56009981cec9935a1 100644 (file)
@@ -559,19 +559,34 @@ static void srcu_torture_barrier(void)
 
 static void srcu_torture_stats(void)
 {
-       int cpu;
-       int idx = srcu_ctlp->completed & 0x1;
+       int __maybe_unused cpu;
+       int idx;
 
-       pr_alert("%s%s per-CPU(idx=%d):",
+#if defined(CONFIG_TREE_SRCU) || defined(CONFIG_CLASSIC_SRCU)
+#ifdef CONFIG_TREE_SRCU
+       idx = srcu_ctlp->srcu_idx & 0x1;
+#else /* #ifdef CONFIG_TREE_SRCU */
+       idx = srcu_ctlp->completed & 0x1;
+#endif /* #else #ifdef CONFIG_TREE_SRCU */
+       pr_alert("%s%s Tree SRCU per-CPU(idx=%d):",
                 torture_type, TORTURE_FLAG, idx);
        for_each_possible_cpu(cpu) {
                unsigned long l0, l1;
                unsigned long u0, u1;
                long c0, c1;
-               struct srcu_array *counts = per_cpu_ptr(srcu_ctlp->per_cpu_ref, cpu);
+#ifdef CONFIG_TREE_SRCU
+               struct srcu_data *counts;
 
+               counts = per_cpu_ptr(srcu_ctlp->sda, cpu);
+               u0 = counts->srcu_unlock_count[!idx];
+               u1 = counts->srcu_unlock_count[idx];
+#else /* #ifdef CONFIG_TREE_SRCU */
+               struct srcu_array *counts;
+
+               counts = per_cpu_ptr(srcu_ctlp->per_cpu_ref, cpu);
                u0 = counts->unlock_count[!idx];
                u1 = counts->unlock_count[idx];
+#endif /* #else #ifdef CONFIG_TREE_SRCU */
 
                /*
                 * Make sure that a lock is always counted if the corresponding
@@ -579,14 +594,26 @@ static void srcu_torture_stats(void)
                 */
                smp_rmb();
 
+#ifdef CONFIG_TREE_SRCU
+               l0 = counts->srcu_lock_count[!idx];
+               l1 = counts->srcu_lock_count[idx];
+#else /* #ifdef CONFIG_TREE_SRCU */
                l0 = counts->lock_count[!idx];
                l1 = counts->lock_count[idx];
+#endif /* #else #ifdef CONFIG_TREE_SRCU */
 
                c0 = l0 - u0;
                c1 = l1 - u1;
                pr_cont(" %d(%ld,%ld)", cpu, c0, c1);
        }
        pr_cont("\n");
+#elif defined(CONFIG_TINY_SRCU)
+       idx = READ_ONCE(srcu_ctlp->srcu_idx) & 0x1;
+       pr_alert("%s%s Tiny SRCU per-CPU(idx=%d): (%d,%d)\n",
+                torture_type, TORTURE_FLAG, idx,
+                READ_ONCE(srcu_ctlp->srcu_lock_nesting[!idx]),
+                READ_ONCE(srcu_ctlp->srcu_lock_nesting[idx]));
+#endif
 }
 
 static void srcu_torture_synchronize_expedited(void)
@@ -1333,12 +1360,14 @@ rcu_torture_stats_print(void)
                cur_ops->stats();
        if (rtcv_snap == rcu_torture_current_version &&
            rcu_torture_current != NULL) {
-               int __maybe_unused flags;
-               unsigned long __maybe_unused gpnum;
-               unsigned long __maybe_unused completed;
+               int __maybe_unused flags = 0;
+               unsigned long __maybe_unused gpnum = 0;
+               unsigned long __maybe_unused completed = 0;
 
                rcutorture_get_gp_data(cur_ops->ttype,
                                       &flags, &gpnum, &completed);
+               srcutorture_get_gp_data(cur_ops->ttype, srcu_ctlp,
+                                       &flags, &gpnum, &completed);
                wtp = READ_ONCE(writer_task);
                pr_alert("??? Writer stall state %s(%d) g%lu c%lu f%#x ->state %#lx\n",
                         rcu_torture_writer_state_getname(),
index ef3bcfb15b39ec4815275077d3e79825db740a27..584d8a983883584dfa87ff0e36cf01465506c199 100644 (file)
@@ -22,7 +22,7 @@
  *        Lai Jiangshan <laijs@cn.fujitsu.com>
  *
  * For detailed explanation of Read-Copy Update mechanism see -
- *             Documentation/RCU/ *.txt
+ *             Documentation/RCU/ *.txt
  *
  */
 
@@ -243,8 +243,14 @@ static bool srcu_readers_active(struct srcu_struct *sp)
  * cleanup_srcu_struct - deconstruct a sleep-RCU structure
  * @sp: structure to clean up.
  *
- * Must invoke this after you are finished using a given srcu_struct that
- * was initialized via init_srcu_struct(), else you leak memory.
+ * Must invoke this only after you are finished using a given srcu_struct
+ * that was initialized via init_srcu_struct().  This code does some
+ * probabalistic checking, spotting late uses of srcu_read_lock(),
+ * synchronize_srcu(), synchronize_srcu_expedited(), and call_srcu().
+ * If any such late uses are detected, the per-CPU memory associated with
+ * the srcu_struct is simply leaked and WARN_ON() is invoked.  If the
+ * caller frees the srcu_struct itself, a use-after-free crash will likely
+ * ensue, but at least there will be a warning printed.
  */
 void cleanup_srcu_struct(struct srcu_struct *sp)
 {
diff --git a/kernel/rcu/srcutiny.c b/kernel/rcu/srcutiny.c
new file mode 100644 (file)
index 0000000..36e1f82
--- /dev/null
@@ -0,0 +1,216 @@
+/*
+ * Sleepable Read-Copy Update mechanism for mutual exclusion,
+ *     tiny version for non-preemptible single-CPU use.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you can access it online at
+ * http://www.gnu.org/licenses/gpl-2.0.html.
+ *
+ * Copyright (C) IBM Corporation, 2017
+ *
+ * Author: Paul McKenney <paulmck@us.ibm.com>
+ */
+
+#include <linux/export.h>
+#include <linux/mutex.h>
+#include <linux/preempt.h>
+#include <linux/rcupdate_wait.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/srcu.h>
+
+#include <linux/rcu_node_tree.h>
+#include "rcu_segcblist.h"
+#include "rcu.h"
+
+static int init_srcu_struct_fields(struct srcu_struct *sp)
+{
+       sp->srcu_lock_nesting[0] = 0;
+       sp->srcu_lock_nesting[1] = 0;
+       init_swait_queue_head(&sp->srcu_wq);
+       sp->srcu_gp_seq = 0;
+       rcu_segcblist_init(&sp->srcu_cblist);
+       sp->srcu_gp_running = false;
+       sp->srcu_gp_waiting = false;
+       sp->srcu_idx = 0;
+       INIT_WORK(&sp->srcu_work, srcu_drive_gp);
+       return 0;
+}
+
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+
+int __init_srcu_struct(struct srcu_struct *sp, const char *name,
+                      struct lock_class_key *key)
+{
+       /* Don't re-initialize a lock while it is held. */
+       debug_check_no_locks_freed((void *)sp, sizeof(*sp));
+       lockdep_init_map(&sp->dep_map, name, key, 0);
+       return init_srcu_struct_fields(sp);
+}
+EXPORT_SYMBOL_GPL(__init_srcu_struct);
+
+#else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
+
+/*
+ * init_srcu_struct - initialize a sleep-RCU structure
+ * @sp: structure to initialize.
+ *
+ * Must invoke this on a given srcu_struct before passing that srcu_struct
+ * to any other function.  Each srcu_struct represents a separate domain
+ * of SRCU protection.
+ */
+int init_srcu_struct(struct srcu_struct *sp)
+{
+       return init_srcu_struct_fields(sp);
+}
+EXPORT_SYMBOL_GPL(init_srcu_struct);
+
+#endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */
+
+/*
+ * cleanup_srcu_struct - deconstruct a sleep-RCU structure
+ * @sp: structure to clean up.
+ *
+ * Must invoke this after you are finished using a given srcu_struct that
+ * was initialized via init_srcu_struct(), else you leak memory.
+ */
+void cleanup_srcu_struct(struct srcu_struct *sp)
+{
+       WARN_ON(sp->srcu_lock_nesting[0] || sp->srcu_lock_nesting[1]);
+       flush_work(&sp->srcu_work);
+       WARN_ON(rcu_seq_state(sp->srcu_gp_seq));
+       WARN_ON(sp->srcu_gp_running);
+       WARN_ON(sp->srcu_gp_waiting);
+       WARN_ON(!rcu_segcblist_empty(&sp->srcu_cblist));
+}
+EXPORT_SYMBOL_GPL(cleanup_srcu_struct);
+
+/*
+ * Counts the new reader in the appropriate per-CPU element of the
+ * srcu_struct.  Must be called from process context.
+ * Returns an index that must be passed to the matching srcu_read_unlock().
+ */
+int __srcu_read_lock(struct srcu_struct *sp)
+{
+       int idx;
+
+       idx = READ_ONCE(sp->srcu_idx);
+       WRITE_ONCE(sp->srcu_lock_nesting[idx], sp->srcu_lock_nesting[idx] + 1);
+       return idx;
+}
+EXPORT_SYMBOL_GPL(__srcu_read_lock);
+
+/*
+ * Removes the count for the old reader from the appropriate element of
+ * the srcu_struct.  Must be called from process context.
+ */
+void __srcu_read_unlock(struct srcu_struct *sp, int idx)
+{
+       int newval = sp->srcu_lock_nesting[idx] - 1;
+
+       WRITE_ONCE(sp->srcu_lock_nesting[idx], newval);
+       if (!newval && READ_ONCE(sp->srcu_gp_waiting))
+               swake_up(&sp->srcu_wq);
+}
+EXPORT_SYMBOL_GPL(__srcu_read_unlock);
+
+/*
+ * Workqueue handler to drive one grace period and invoke any callbacks
+ * that become ready as a result.  Single-CPU and !PREEMPT operation
+ * means that we get away with murder on synchronization.  ;-)
+ */
+void srcu_drive_gp(struct work_struct *wp)
+{
+       int idx;
+       struct rcu_cblist ready_cbs;
+       struct srcu_struct *sp;
+       struct rcu_head *rhp;
+
+       sp = container_of(wp, struct srcu_struct, srcu_work);
+       if (sp->srcu_gp_running || rcu_segcblist_empty(&sp->srcu_cblist))
+               return; /* Already running or nothing to do. */
+
+       /* Tag recently arrived callbacks and wait for readers. */
+       WRITE_ONCE(sp->srcu_gp_running, true);
+       rcu_segcblist_accelerate(&sp->srcu_cblist,
+                                rcu_seq_snap(&sp->srcu_gp_seq));
+       rcu_seq_start(&sp->srcu_gp_seq);
+       idx = sp->srcu_idx;
+       WRITE_ONCE(sp->srcu_idx, !sp->srcu_idx);
+       WRITE_ONCE(sp->srcu_gp_waiting, true);  /* srcu_read_unlock() wakes! */
+       swait_event(sp->srcu_wq, !READ_ONCE(sp->srcu_lock_nesting[idx]));
+       WRITE_ONCE(sp->srcu_gp_waiting, false); /* srcu_read_unlock() cheap. */
+       rcu_seq_end(&sp->srcu_gp_seq);
+
+       /* Update callback list based on GP, and invoke ready callbacks. */
+       rcu_segcblist_advance(&sp->srcu_cblist,
+                             rcu_seq_current(&sp->srcu_gp_seq));
+       if (rcu_segcblist_ready_cbs(&sp->srcu_cblist)) {
+               rcu_cblist_init(&ready_cbs);
+               local_irq_disable();
+               rcu_segcblist_extract_done_cbs(&sp->srcu_cblist, &ready_cbs);
+               local_irq_enable();
+               rhp = rcu_cblist_dequeue(&ready_cbs);
+               for (; rhp != NULL; rhp = rcu_cblist_dequeue(&ready_cbs)) {
+                       local_bh_disable();
+                       rhp->func(rhp);
+                       local_bh_enable();
+               }
+               local_irq_disable();
+               rcu_segcblist_insert_count(&sp->srcu_cblist, &ready_cbs);
+               local_irq_enable();
+       }
+       WRITE_ONCE(sp->srcu_gp_running, false);
+
+       /*
+        * If more callbacks, reschedule ourselves.  This can race with
+        * a call_srcu() at interrupt level, but the ->srcu_gp_running
+        * checks will straighten that out.
+        */
+       if (!rcu_segcblist_empty(&sp->srcu_cblist))
+               schedule_work(&sp->srcu_work);
+}
+EXPORT_SYMBOL_GPL(srcu_drive_gp);
+
+/*
+ * Enqueue an SRCU callback on the specified srcu_struct structure,
+ * initiating grace-period processing if it is not already running.
+ */
+void call_srcu(struct srcu_struct *sp, struct rcu_head *head,
+              rcu_callback_t func)
+{
+       unsigned long flags;
+
+       head->func = func;
+       local_irq_save(flags);
+       rcu_segcblist_enqueue(&sp->srcu_cblist, head, false);
+       local_irq_restore(flags);
+       if (!READ_ONCE(sp->srcu_gp_running))
+               schedule_work(&sp->srcu_work);
+}
+EXPORT_SYMBOL_GPL(call_srcu);
+
+/*
+ * synchronize_srcu - wait for prior SRCU read-side critical-section completion
+ */
+void synchronize_srcu(struct srcu_struct *sp)
+{
+       struct rcu_synchronize rs;
+
+       init_rcu_head_on_stack(&rs.head);
+       init_completion(&rs.completion);
+       call_srcu(sp, &rs.head, wakeme_after_rcu);
+       wait_for_completion(&rs.completion);
+       destroy_rcu_head_on_stack(&rs.head);
+}
+EXPORT_SYMBOL_GPL(synchronize_srcu);
diff --git a/kernel/rcu/srcutree.c b/kernel/rcu/srcutree.c
new file mode 100644 (file)
index 0000000..3ae8474
--- /dev/null
@@ -0,0 +1,1155 @@
+/*
+ * Sleepable Read-Copy Update mechanism for mutual exclusion.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, you can access it online at
+ * http://www.gnu.org/licenses/gpl-2.0.html.
+ *
+ * Copyright (C) IBM Corporation, 2006
+ * Copyright (C) Fujitsu, 2012
+ *
+ * Author: Paul McKenney <paulmck@us.ibm.com>
+ *        Lai Jiangshan <laijs@cn.fujitsu.com>
+ *
+ * For detailed explanation of Read-Copy Update mechanism see -
+ *             Documentation/RCU/ *.txt
+ *
+ */
+
+#include <linux/export.h>
+#include <linux/mutex.h>
+#include <linux/percpu.h>
+#include <linux/preempt.h>
+#include <linux/rcupdate_wait.h>
+#include <linux/sched.h>
+#include <linux/smp.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/srcu.h>
+
+#include "rcu.h"
+#include "rcu_segcblist.h"
+
+ulong exp_holdoff = 25 * 1000; /* Holdoff (ns) for auto-expediting. */
+module_param(exp_holdoff, ulong, 0444);
+
+static void srcu_invoke_callbacks(struct work_struct *work);
+static void srcu_reschedule(struct srcu_struct *sp, unsigned long delay);
+
+/*
+ * Initialize SRCU combining tree.  Note that statically allocated
+ * srcu_struct structures might already have srcu_read_lock() and
+ * srcu_read_unlock() running against them.  So if the is_static parameter
+ * is set, don't initialize ->srcu_lock_count[] and ->srcu_unlock_count[].
+ */
+static void init_srcu_struct_nodes(struct srcu_struct *sp, bool is_static)
+{
+       int cpu;
+       int i;
+       int level = 0;
+       int levelspread[RCU_NUM_LVLS];
+       struct srcu_data *sdp;
+       struct srcu_node *snp;
+       struct srcu_node *snp_first;
+
+       /* Work out the overall tree geometry. */
+       sp->level[0] = &sp->node[0];
+       for (i = 1; i < rcu_num_lvls; i++)
+               sp->level[i] = sp->level[i - 1] + num_rcu_lvl[i - 1];
+       rcu_init_levelspread(levelspread, num_rcu_lvl);
+
+       /* Each pass through this loop initializes one srcu_node structure. */
+       rcu_for_each_node_breadth_first(sp, snp) {
+               spin_lock_init(&snp->lock);
+               WARN_ON_ONCE(ARRAY_SIZE(snp->srcu_have_cbs) !=
+                            ARRAY_SIZE(snp->srcu_data_have_cbs));
+               for (i = 0; i < ARRAY_SIZE(snp->srcu_have_cbs); i++) {
+                       snp->srcu_have_cbs[i] = 0;
+                       snp->srcu_data_have_cbs[i] = 0;
+               }
+               snp->srcu_gp_seq_needed_exp = 0;
+               snp->grplo = -1;
+               snp->grphi = -1;
+               if (snp == &sp->node[0]) {
+                       /* Root node, special case. */
+                       snp->srcu_parent = NULL;
+                       continue;
+               }
+
+               /* Non-root node. */
+               if (snp == sp->level[level + 1])
+                       level++;
+               snp->srcu_parent = sp->level[level - 1] +
+                                  (snp - sp->level[level]) /
+                                  levelspread[level - 1];
+       }
+
+       /*
+        * Initialize the per-CPU srcu_data array, which feeds into the
+        * leaves of the srcu_node tree.
+        */
+       WARN_ON_ONCE(ARRAY_SIZE(sdp->srcu_lock_count) !=
+                    ARRAY_SIZE(sdp->srcu_unlock_count));
+       level = rcu_num_lvls - 1;
+       snp_first = sp->level[level];
+       for_each_possible_cpu(cpu) {
+               sdp = per_cpu_ptr(sp->sda, cpu);
+               spin_lock_init(&sdp->lock);
+               rcu_segcblist_init(&sdp->srcu_cblist);
+               sdp->srcu_cblist_invoking = false;
+               sdp->srcu_gp_seq_needed = sp->srcu_gp_seq;
+               sdp->srcu_gp_seq_needed_exp = sp->srcu_gp_seq;
+               sdp->mynode = &snp_first[cpu / levelspread[level]];
+               for (snp = sdp->mynode; snp != NULL; snp = snp->srcu_parent) {
+                       if (snp->grplo < 0)
+                               snp->grplo = cpu;
+                       snp->grphi = cpu;
+               }
+               sdp->cpu = cpu;
+               INIT_DELAYED_WORK(&sdp->work, srcu_invoke_callbacks);
+               sdp->sp = sp;
+               sdp->grpmask = 1 << (cpu - sdp->mynode->grplo);
+               if (is_static)
+                       continue;
+
+               /* Dynamically allocated, better be no srcu_read_locks()! */
+               for (i = 0; i < ARRAY_SIZE(sdp->srcu_lock_count); i++) {
+                       sdp->srcu_lock_count[i] = 0;
+                       sdp->srcu_unlock_count[i] = 0;
+               }
+       }
+}
+
+/*
+ * Initialize non-compile-time initialized fields, including the
+ * associated srcu_node and srcu_data structures.  The is_static
+ * parameter is passed through to init_srcu_struct_nodes(), and
+ * also tells us that ->sda has already been wired up to srcu_data.
+ */
+static int init_srcu_struct_fields(struct srcu_struct *sp, bool is_static)
+{
+       mutex_init(&sp->srcu_cb_mutex);
+       mutex_init(&sp->srcu_gp_mutex);
+       sp->srcu_idx = 0;
+       sp->srcu_gp_seq = 0;
+       sp->srcu_barrier_seq = 0;
+       mutex_init(&sp->srcu_barrier_mutex);
+       atomic_set(&sp->srcu_barrier_cpu_cnt, 0);
+       INIT_DELAYED_WORK(&sp->work, process_srcu);
+       if (!is_static)
+               sp->sda = alloc_percpu(struct srcu_data);
+       init_srcu_struct_nodes(sp, is_static);
+       sp->srcu_gp_seq_needed_exp = 0;
+       sp->srcu_last_gp_end = ktime_get_mono_fast_ns();
+       smp_store_release(&sp->srcu_gp_seq_needed, 0); /* Init done. */
+       return sp->sda ? 0 : -ENOMEM;
+}
+
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+
+int __init_srcu_struct(struct srcu_struct *sp, const char *name,
+                      struct lock_class_key *key)
+{
+       /* Don't re-initialize a lock while it is held. */
+       debug_check_no_locks_freed((void *)sp, sizeof(*sp));
+       lockdep_init_map(&sp->dep_map, name, key, 0);
+       spin_lock_init(&sp->gp_lock);
+       return init_srcu_struct_fields(sp, false);
+}
+EXPORT_SYMBOL_GPL(__init_srcu_struct);
+
+#else /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
+
+/**
+ * init_srcu_struct - initialize a sleep-RCU structure
+ * @sp: structure to initialize.
+ *
+ * Must invoke this on a given srcu_struct before passing that srcu_struct
+ * to any other function.  Each srcu_struct represents a separate domain
+ * of SRCU protection.
+ */
+int init_srcu_struct(struct srcu_struct *sp)
+{
+       spin_lock_init(&sp->gp_lock);
+       return init_srcu_struct_fields(sp, false);
+}
+EXPORT_SYMBOL_GPL(init_srcu_struct);
+
+#endif /* #else #ifdef CONFIG_DEBUG_LOCK_ALLOC */
+
+/*
+ * First-use initialization of statically allocated srcu_struct
+ * structure.  Wiring up the combining tree is more than can be
+ * done with compile-time initialization, so this check is added
+ * to each update-side SRCU primitive.  Use ->gp_lock, which -is-
+ * compile-time initialized, to resolve races involving multiple
+ * CPUs trying to garner first-use privileges.
+ */
+static void check_init_srcu_struct(struct srcu_struct *sp)
+{
+       unsigned long flags;
+
+       WARN_ON_ONCE(rcu_scheduler_active == RCU_SCHEDULER_INIT);
+       /* The smp_load_acquire() pairs with the smp_store_release(). */
+       if (!rcu_seq_state(smp_load_acquire(&sp->srcu_gp_seq_needed))) /*^^^*/
+               return; /* Already initialized. */
+       spin_lock_irqsave(&sp->gp_lock, flags);
+       if (!rcu_seq_state(sp->srcu_gp_seq_needed)) {
+               spin_unlock_irqrestore(&sp->gp_lock, flags);
+               return;
+       }
+       init_srcu_struct_fields(sp, true);
+       spin_unlock_irqrestore(&sp->gp_lock, flags);
+}
+
+/*
+ * Returns approximate total of the readers' ->srcu_lock_count[] values
+ * for the rank of per-CPU counters specified by idx.
+ */
+static unsigned long srcu_readers_lock_idx(struct srcu_struct *sp, int idx)
+{
+       int cpu;
+       unsigned long sum = 0;
+
+       for_each_possible_cpu(cpu) {
+               struct srcu_data *cpuc = per_cpu_ptr(sp->sda, cpu);
+
+               sum += READ_ONCE(cpuc->srcu_lock_count[idx]);
+       }
+       return sum;
+}
+
+/*
+ * Returns approximate total of the readers' ->srcu_unlock_count[] values
+ * for the rank of per-CPU counters specified by idx.
+ */
+static unsigned long srcu_readers_unlock_idx(struct srcu_struct *sp, int idx)
+{
+       int cpu;
+       unsigned long sum = 0;
+
+       for_each_possible_cpu(cpu) {
+               struct srcu_data *cpuc = per_cpu_ptr(sp->sda, cpu);
+
+               sum += READ_ONCE(cpuc->srcu_unlock_count[idx]);
+       }
+       return sum;
+}
+
+/*
+ * Return true if the number of pre-existing readers is determined to
+ * be zero.
+ */
+static bool srcu_readers_active_idx_check(struct srcu_struct *sp, int idx)
+{
+       unsigned long unlocks;
+
+       unlocks = srcu_readers_unlock_idx(sp, idx);
+
+       /*
+        * Make sure that a lock is always counted if the corresponding
+        * unlock is counted. Needs to be a smp_mb() as the read side may
+        * contain a read from a variable that is written to before the
+        * synchronize_srcu() in the write side. In this case smp_mb()s
+        * A and B act like the store buffering pattern.
+        *
+        * This smp_mb() also pairs with smp_mb() C to prevent accesses
+        * after the synchronize_srcu() from being executed before the
+        * grace period ends.
+        */
+       smp_mb(); /* A */
+
+       /*
+        * If the locks are the same as the unlocks, then there must have
+        * been no readers on this index at some time in between. This does
+        * not mean that there are no more readers, as one could have read
+        * the current index but not have incremented the lock counter yet.
+        *
+        * Possible bug: There is no guarantee that there haven't been
+        * ULONG_MAX increments of ->srcu_lock_count[] since the unlocks were
+        * counted, meaning that this could return true even if there are
+        * still active readers.  Since there are no memory barriers around
+        * srcu_flip(), the CPU is not required to increment ->srcu_idx
+        * before running srcu_readers_unlock_idx(), which means that there
+        * could be an arbitrarily large number of critical sections that
+        * execute after srcu_readers_unlock_idx() but use the old value
+        * of ->srcu_idx.
+        */
+       return srcu_readers_lock_idx(sp, idx) == unlocks;
+}
+
+/**
+ * srcu_readers_active - returns true if there are readers. and false
+ *                       otherwise
+ * @sp: which srcu_struct to count active readers (holding srcu_read_lock).
+ *
+ * Note that this is not an atomic primitive, and can therefore suffer
+ * severe errors when invoked on an active srcu_struct.  That said, it
+ * can be useful as an error check at cleanup time.
+ */
+static bool srcu_readers_active(struct srcu_struct *sp)
+{
+       int cpu;
+       unsigned long sum = 0;
+
+       for_each_possible_cpu(cpu) {
+               struct srcu_data *cpuc = per_cpu_ptr(sp->sda, cpu);
+
+               sum += READ_ONCE(cpuc->srcu_lock_count[0]);
+               sum += READ_ONCE(cpuc->srcu_lock_count[1]);
+               sum -= READ_ONCE(cpuc->srcu_unlock_count[0]);
+               sum -= READ_ONCE(cpuc->srcu_unlock_count[1]);
+       }
+       return sum;
+}
+
+#define SRCU_INTERVAL          1
+
+/*
+ * Return grace-period delay, zero if there are expedited grace
+ * periods pending, SRCU_INTERVAL otherwise.
+ */
+static unsigned long srcu_get_delay(struct srcu_struct *sp)
+{
+       if (ULONG_CMP_LT(READ_ONCE(sp->srcu_gp_seq),
+                        READ_ONCE(sp->srcu_gp_seq_needed_exp)))
+               return 0;
+       return SRCU_INTERVAL;
+}
+
+/**
+ * cleanup_srcu_struct - deconstruct a sleep-RCU structure
+ * @sp: structure to clean up.
+ *
+ * Must invoke this after you are finished using a given srcu_struct that
+ * was initialized via init_srcu_struct(), else you leak memory.
+ */
+void cleanup_srcu_struct(struct srcu_struct *sp)
+{
+       int cpu;
+
+       if (WARN_ON(!srcu_get_delay(sp)))
+               return; /* Leakage unless caller handles error. */
+       if (WARN_ON(srcu_readers_active(sp)))
+               return; /* Leakage unless caller handles error. */
+       flush_delayed_work(&sp->work);
+       for_each_possible_cpu(cpu)
+               flush_delayed_work(&per_cpu_ptr(sp->sda, cpu)->work);
+       if (WARN_ON(rcu_seq_state(READ_ONCE(sp->srcu_gp_seq)) != SRCU_STATE_IDLE) ||
+           WARN_ON(srcu_readers_active(sp))) {
+               pr_info("cleanup_srcu_struct: Active srcu_struct %p state: %d\n", sp, rcu_seq_state(READ_ONCE(sp->srcu_gp_seq)));
+               return; /* Caller forgot to stop doing call_srcu()? */
+       }
+       free_percpu(sp->sda);
+       sp->sda = NULL;
+}
+EXPORT_SYMBOL_GPL(cleanup_srcu_struct);
+
+/*
+ * Counts the new reader in the appropriate per-CPU element of the
+ * srcu_struct.  Must be called from process context.
+ * Returns an index that must be passed to the matching srcu_read_unlock().
+ */
+int __srcu_read_lock(struct srcu_struct *sp)
+{
+       int idx;
+
+       idx = READ_ONCE(sp->srcu_idx) & 0x1;
+       __this_cpu_inc(sp->sda->srcu_lock_count[idx]);
+       smp_mb(); /* B */  /* Avoid leaking the critical section. */
+       return idx;
+}
+EXPORT_SYMBOL_GPL(__srcu_read_lock);
+
+/*
+ * Removes the count for the old reader from the appropriate per-CPU
+ * element of the srcu_struct.  Note that this may well be a different
+ * CPU than that which was incremented by the corresponding srcu_read_lock().
+ * Must be called from process context.
+ */
+void __srcu_read_unlock(struct srcu_struct *sp, int idx)
+{
+       smp_mb(); /* C */  /* Avoid leaking the critical section. */
+       this_cpu_inc(sp->sda->srcu_unlock_count[idx]);
+}
+EXPORT_SYMBOL_GPL(__srcu_read_unlock);
+
+/*
+ * We use an adaptive strategy for synchronize_srcu() and especially for
+ * synchronize_srcu_expedited().  We spin for a fixed time period
+ * (defined below) to allow SRCU readers to exit their read-side critical
+ * sections.  If there are still some readers after a few microseconds,
+ * we repeatedly block for 1-millisecond time periods.
+ */
+#define SRCU_RETRY_CHECK_DELAY         5
+
+/*
+ * Start an SRCU grace period.
+ */
+static void srcu_gp_start(struct srcu_struct *sp)
+{
+       struct srcu_data *sdp = this_cpu_ptr(sp->sda);
+       int state;
+
+       RCU_LOCKDEP_WARN(!lockdep_is_held(&sp->gp_lock),
+                        "Invoked srcu_gp_start() without ->gp_lock!");
+       WARN_ON_ONCE(ULONG_CMP_GE(sp->srcu_gp_seq, sp->srcu_gp_seq_needed));
+       rcu_segcblist_advance(&sdp->srcu_cblist,
+                             rcu_seq_current(&sp->srcu_gp_seq));
+       (void)rcu_segcblist_accelerate(&sdp->srcu_cblist,
+                                      rcu_seq_snap(&sp->srcu_gp_seq));
+       smp_mb(); /* Order prior store to ->srcu_gp_seq_needed vs. GP start. */
+       rcu_seq_start(&sp->srcu_gp_seq);
+       state = rcu_seq_state(READ_ONCE(sp->srcu_gp_seq));
+       WARN_ON_ONCE(state != SRCU_STATE_SCAN1);
+}
+
+/*
+ * Track online CPUs to guide callback workqueue placement.
+ */
+DEFINE_PER_CPU(bool, srcu_online);
+
+void srcu_online_cpu(unsigned int cpu)
+{
+       WRITE_ONCE(per_cpu(srcu_online, cpu), true);
+}
+
+void srcu_offline_cpu(unsigned int cpu)
+{
+       WRITE_ONCE(per_cpu(srcu_online, cpu), false);
+}
+
+/*
+ * Place the workqueue handler on the specified CPU if online, otherwise
+ * just run it whereever.  This is useful for placing workqueue handlers
+ * that are to invoke the specified CPU's callbacks.
+ */
+static bool srcu_queue_delayed_work_on(int cpu, struct workqueue_struct *wq,
+                                      struct delayed_work *dwork,
+                                      unsigned long delay)
+{
+       bool ret;
+
+       preempt_disable();
+       if (READ_ONCE(per_cpu(srcu_online, cpu)))
+               ret = queue_delayed_work_on(cpu, wq, dwork, delay);
+       else
+               ret = queue_delayed_work(wq, dwork, delay);
+       preempt_enable();
+       return ret;
+}
+
+/*
+ * Schedule callback invocation for the specified srcu_data structure,
+ * if possible, on the corresponding CPU.
+ */
+static void srcu_schedule_cbs_sdp(struct srcu_data *sdp, unsigned long delay)
+{
+       srcu_queue_delayed_work_on(sdp->cpu, system_power_efficient_wq,
+                                  &sdp->work, delay);
+}
+
+/*
+ * Schedule callback invocation for all srcu_data structures associated
+ * with the specified srcu_node structure that have callbacks for the
+ * just-completed grace period, the one corresponding to idx.  If possible,
+ * schedule this invocation on the corresponding CPUs.
+ */
+static void srcu_schedule_cbs_snp(struct srcu_struct *sp, struct srcu_node *snp,
+                                 unsigned long mask, unsigned long delay)
+{
+       int cpu;
+
+       for (cpu = snp->grplo; cpu <= snp->grphi; cpu++) {
+               if (!(mask & (1 << (cpu - snp->grplo))))
+                       continue;
+               srcu_schedule_cbs_sdp(per_cpu_ptr(sp->sda, cpu), delay);
+       }
+}
+
+/*
+ * Note the end of an SRCU grace period.  Initiates callback invocation
+ * and starts a new grace period if needed.
+ *
+ * The ->srcu_cb_mutex acquisition does not protect any data, but
+ * instead prevents more than one grace period from starting while we
+ * are initiating callback invocation.  This allows the ->srcu_have_cbs[]
+ * array to have a finite number of elements.
+ */
+static void srcu_gp_end(struct srcu_struct *sp)
+{
+       unsigned long cbdelay;
+       bool cbs;
+       unsigned long gpseq;
+       int idx;
+       int idxnext;
+       unsigned long mask;
+       struct srcu_node *snp;
+
+       /* Prevent more than one additional grace period. */
+       mutex_lock(&sp->srcu_cb_mutex);
+
+       /* End the current grace period. */
+       spin_lock_irq(&sp->gp_lock);
+       idx = rcu_seq_state(sp->srcu_gp_seq);
+       WARN_ON_ONCE(idx != SRCU_STATE_SCAN2);
+       cbdelay = srcu_get_delay(sp);
+       sp->srcu_last_gp_end = ktime_get_mono_fast_ns();
+       rcu_seq_end(&sp->srcu_gp_seq);
+       gpseq = rcu_seq_current(&sp->srcu_gp_seq);
+       if (ULONG_CMP_LT(sp->srcu_gp_seq_needed_exp, gpseq))
+               sp->srcu_gp_seq_needed_exp = gpseq;
+       spin_unlock_irq(&sp->gp_lock);
+       mutex_unlock(&sp->srcu_gp_mutex);
+       /* A new grace period can start at this point.  But only one. */
+
+       /* Initiate callback invocation as needed. */
+       idx = rcu_seq_ctr(gpseq) % ARRAY_SIZE(snp->srcu_have_cbs);
+       idxnext = (idx + 1) % ARRAY_SIZE(snp->srcu_have_cbs);
+       rcu_for_each_node_breadth_first(sp, snp) {
+               spin_lock_irq(&snp->lock);
+               cbs = false;
+               if (snp >= sp->level[rcu_num_lvls - 1])
+                       cbs = snp->srcu_have_cbs[idx] == gpseq;
+               snp->srcu_have_cbs[idx] = gpseq;
+               rcu_seq_set_state(&snp->srcu_have_cbs[idx], 1);
+               if (ULONG_CMP_LT(snp->srcu_gp_seq_needed_exp, gpseq))
+                       snp->srcu_gp_seq_needed_exp = gpseq;
+               mask = snp->srcu_data_have_cbs[idx];
+               snp->srcu_data_have_cbs[idx] = 0;
+               spin_unlock_irq(&snp->lock);
+               if (cbs) {
+                       smp_mb(); /* GP end before CB invocation. */
+                       srcu_schedule_cbs_snp(sp, snp, mask, cbdelay);
+               }
+       }
+
+       /* Callback initiation done, allow grace periods after next. */
+       mutex_unlock(&sp->srcu_cb_mutex);
+
+       /* Start a new grace period if needed. */
+       spin_lock_irq(&sp->gp_lock);
+       gpseq = rcu_seq_current(&sp->srcu_gp_seq);
+       if (!rcu_seq_state(gpseq) &&
+           ULONG_CMP_LT(gpseq, sp->srcu_gp_seq_needed)) {
+               srcu_gp_start(sp);
+               spin_unlock_irq(&sp->gp_lock);
+               /* Throttle expedited grace periods: Should be rare! */
+               srcu_reschedule(sp, rcu_seq_ctr(gpseq) & 0x3ff
+                                   ? 0 : SRCU_INTERVAL);
+       } else {
+               spin_unlock_irq(&sp->gp_lock);
+       }
+}
+
+/*
+ * Funnel-locking scheme to scalably mediate many concurrent expedited
+ * grace-period requests.  This function is invoked for the first known
+ * expedited request for a grace period that has already been requested,
+ * but without expediting.  To start a completely new grace period,
+ * whether expedited or not, use srcu_funnel_gp_start() instead.
+ */
+static void srcu_funnel_exp_start(struct srcu_struct *sp, struct srcu_node *snp,
+                                 unsigned long s)
+{
+       unsigned long flags;
+
+       for (; snp != NULL; snp = snp->srcu_parent) {
+               if (rcu_seq_done(&sp->srcu_gp_seq, s) ||
+                   ULONG_CMP_GE(READ_ONCE(snp->srcu_gp_seq_needed_exp), s))
+                       return;
+               spin_lock_irqsave(&snp->lock, flags);
+               if (ULONG_CMP_GE(snp->srcu_gp_seq_needed_exp, s)) {
+                       spin_unlock_irqrestore(&snp->lock, flags);
+                       return;
+               }
+               WRITE_ONCE(snp->srcu_gp_seq_needed_exp, s);
+               spin_unlock_irqrestore(&snp->lock, flags);
+       }
+       spin_lock_irqsave(&sp->gp_lock, flags);
+       if (!ULONG_CMP_LT(sp->srcu_gp_seq_needed_exp, s))
+               sp->srcu_gp_seq_needed_exp = s;
+       spin_unlock_irqrestore(&sp->gp_lock, flags);
+}
+
+/*
+ * Funnel-locking scheme to scalably mediate many concurrent grace-period
+ * requests.  The winner has to do the work of actually starting grace
+ * period s.  Losers must either ensure that their desired grace-period
+ * number is recorded on at least their leaf srcu_node structure, or they
+ * must take steps to invoke their own callbacks.
+ */
+static void srcu_funnel_gp_start(struct srcu_struct *sp, struct srcu_data *sdp,
+                                unsigned long s, bool do_norm)
+{
+       unsigned long flags;
+       int idx = rcu_seq_ctr(s) % ARRAY_SIZE(sdp->mynode->srcu_have_cbs);
+       struct srcu_node *snp = sdp->mynode;
+       unsigned long snp_seq;
+
+       /* Each pass through the loop does one level of the srcu_node tree. */
+       for (; snp != NULL; snp = snp->srcu_parent) {
+               if (rcu_seq_done(&sp->srcu_gp_seq, s) && snp != sdp->mynode)
+                       return; /* GP already done and CBs recorded. */
+               spin_lock_irqsave(&snp->lock, flags);
+               if (ULONG_CMP_GE(snp->srcu_have_cbs[idx], s)) {
+                       snp_seq = snp->srcu_have_cbs[idx];
+                       if (snp == sdp->mynode && snp_seq == s)
+                               snp->srcu_data_have_cbs[idx] |= sdp->grpmask;
+                       spin_unlock_irqrestore(&snp->lock, flags);
+                       if (snp == sdp->mynode && snp_seq != s) {
+                               smp_mb(); /* CBs after GP! */
+                               srcu_schedule_cbs_sdp(sdp, do_norm
+                                                          ? SRCU_INTERVAL
+                                                          : 0);
+                               return;
+                       }
+                       if (!do_norm)
+                               srcu_funnel_exp_start(sp, snp, s);
+                       return;
+               }
+               snp->srcu_have_cbs[idx] = s;
+               if (snp == sdp->mynode)
+                       snp->srcu_data_have_cbs[idx] |= sdp->grpmask;
+               if (!do_norm && ULONG_CMP_LT(snp->srcu_gp_seq_needed_exp, s))
+                       snp->srcu_gp_seq_needed_exp = s;
+               spin_unlock_irqrestore(&snp->lock, flags);
+       }
+
+       /* Top of tree, must ensure the grace period will be started. */
+       spin_lock_irqsave(&sp->gp_lock, flags);
+       if (ULONG_CMP_LT(sp->srcu_gp_seq_needed, s)) {
+               /*
+                * Record need for grace period s.  Pair with load
+                * acquire setting up for initialization.
+                */
+               smp_store_release(&sp->srcu_gp_seq_needed, s); /*^^^*/
+       }
+       if (!do_norm && ULONG_CMP_LT(sp->srcu_gp_seq_needed_exp, s))
+               sp->srcu_gp_seq_needed_exp = s;
+
+       /* If grace period not already done and none in progress, start it. */
+       if (!rcu_seq_done(&sp->srcu_gp_seq, s) &&
+           rcu_seq_state(sp->srcu_gp_seq) == SRCU_STATE_IDLE) {
+               WARN_ON_ONCE(ULONG_CMP_GE(sp->srcu_gp_seq, sp->srcu_gp_seq_needed));
+               srcu_gp_start(sp);
+               queue_delayed_work(system_power_efficient_wq, &sp->work,
+                                  srcu_get_delay(sp));
+       }
+       spin_unlock_irqrestore(&sp->gp_lock, flags);
+}
+
+/*
+ * Wait until all readers counted by array index idx complete, but
+ * loop an additional time if there is an expedited grace period pending.
+ * The caller must ensure that ->srcu_idx is not changed while checking.
+ */
+static bool try_check_zero(struct srcu_struct *sp, int idx, int trycount)
+{
+       for (;;) {
+               if (srcu_readers_active_idx_check(sp, idx))
+                       return true;
+               if (--trycount + !srcu_get_delay(sp) <= 0)
+                       return false;
+               udelay(SRCU_RETRY_CHECK_DELAY);
+       }
+}
+
+/*
+ * Increment the ->srcu_idx counter so that future SRCU readers will
+ * use the other rank of the ->srcu_(un)lock_count[] arrays.  This allows
+ * us to wait for pre-existing readers in a starvation-free manner.
+ */
+static void srcu_flip(struct srcu_struct *sp)
+{
+       WRITE_ONCE(sp->srcu_idx, sp->srcu_idx + 1);
+
+       /*
+        * Ensure that if the updater misses an __srcu_read_unlock()
+        * increment, that task's next __srcu_read_lock() will see the
+        * above counter update.  Note that both this memory barrier
+        * and the one in srcu_readers_active_idx_check() provide the
+        * guarantee for __srcu_read_lock().
+        */
+       smp_mb(); /* D */  /* Pairs with C. */
+}
+
+/*
+ * If SRCU is likely idle, return true, otherwise return false.
+ *
+ * Note that it is OK for several current from-idle requests for a new
+ * grace period from idle to specify expediting because they will all end
+ * up requesting the same grace period anyhow.  So no loss.
+ *
+ * Note also that if any CPU (including the current one) is still invoking
+ * callbacks, this function will nevertheless say "idle".  This is not
+ * ideal, but the overhead of checking all CPUs' callback lists is even
+ * less ideal, especially on large systems.  Furthermore, the wakeup
+ * can happen before the callback is fully removed, so we have no choice
+ * but to accept this type of error.
+ *
+ * This function is also subject to counter-wrap errors, but let's face
+ * it, if this function was preempted for enough time for the counters
+ * to wrap, it really doesn't matter whether or not we expedite the grace
+ * period.  The extra overhead of a needlessly expedited grace period is
+ * negligible when amoritized over that time period, and the extra latency
+ * of a needlessly non-expedited grace period is similarly negligible.
+ */
+static bool srcu_might_be_idle(struct srcu_struct *sp)
+{
+       unsigned long curseq;
+       unsigned long flags;
+       struct srcu_data *sdp;
+       unsigned long t;
+
+       /* If the local srcu_data structure has callbacks, not idle.  */
+       local_irq_save(flags);
+       sdp = this_cpu_ptr(sp->sda);
+       if (rcu_segcblist_pend_cbs(&sdp->srcu_cblist)) {
+               local_irq_restore(flags);
+               return false; /* Callbacks already present, so not idle. */
+       }
+       local_irq_restore(flags);
+
+       /*
+        * No local callbacks, so probabalistically probe global state.
+        * Exact information would require acquiring locks, which would
+        * kill scalability, hence the probabalistic nature of the probe.
+        */
+
+       /* First, see if enough time has passed since the last GP. */
+       t = ktime_get_mono_fast_ns();
+       if (exp_holdoff == 0 ||
+           time_in_range_open(t, sp->srcu_last_gp_end,
+                              sp->srcu_last_gp_end + exp_holdoff))
+               return false; /* Too soon after last GP. */
+
+       /* Next, check for probable idleness. */
+       curseq = rcu_seq_current(&sp->srcu_gp_seq);
+       smp_mb(); /* Order ->srcu_gp_seq with ->srcu_gp_seq_needed. */
+       if (ULONG_CMP_LT(curseq, READ_ONCE(sp->srcu_gp_seq_needed)))
+               return false; /* Grace period in progress, so not idle. */
+       smp_mb(); /* Order ->srcu_gp_seq with prior access. */
+       if (curseq != rcu_seq_current(&sp->srcu_gp_seq))
+               return false; /* GP # changed, so not idle. */
+       return true; /* With reasonable probability, idle! */
+}
+
+/*
+ * Enqueue an SRCU callback on the srcu_data structure associated with
+ * the current CPU and the specified srcu_struct structure, initiating
+ * grace-period processing if it is not already running.
+ *
+ * Note that all CPUs must agree that the grace period extended beyond
+ * all pre-existing SRCU read-side critical section.  On systems with
+ * more than one CPU, this means that when "func()" is invoked, each CPU
+ * is guaranteed to have executed a full memory barrier since the end of
+ * its last corresponding SRCU read-side critical section whose beginning
+ * preceded the call to call_rcu().  It also means that each CPU executing
+ * an SRCU read-side critical section that continues beyond the start of
+ * "func()" must have executed a memory barrier after the call_rcu()
+ * but before the beginning of that SRCU read-side critical section.
+ * Note that these guarantees include CPUs that are offline, idle, or
+ * executing in user mode, as well as CPUs that are executing in the kernel.
+ *
+ * Furthermore, if CPU A invoked call_rcu() and CPU B invoked the
+ * resulting SRCU callback function "func()", then both CPU A and CPU
+ * B are guaranteed to execute a full memory barrier during the time
+ * interval between the call to call_rcu() and the invocation of "func()".
+ * This guarantee applies even if CPU A and CPU B are the same CPU (but
+ * again only if the system has more than one CPU).
+ *
+ * Of course, these guarantees apply only for invocations of call_srcu(),
+ * srcu_read_lock(), and srcu_read_unlock() that are all passed the same
+ * srcu_struct structure.
+ */
+void __call_srcu(struct srcu_struct *sp, struct rcu_head *rhp,
+                rcu_callback_t func, bool do_norm)
+{
+       unsigned long flags;
+       bool needexp = false;
+       bool needgp = false;
+       unsigned long s;
+       struct srcu_data *sdp;
+
+       check_init_srcu_struct(sp);
+       rhp->func = func;
+       local_irq_save(flags);
+       sdp = this_cpu_ptr(sp->sda);
+       spin_lock(&sdp->lock);
+       rcu_segcblist_enqueue(&sdp->srcu_cblist, rhp, false);
+       rcu_segcblist_advance(&sdp->srcu_cblist,
+                             rcu_seq_current(&sp->srcu_gp_seq));
+       s = rcu_seq_snap(&sp->srcu_gp_seq);
+       (void)rcu_segcblist_accelerate(&sdp->srcu_cblist, s);
+       if (ULONG_CMP_LT(sdp->srcu_gp_seq_needed, s)) {
+               sdp->srcu_gp_seq_needed = s;
+               needgp = true;
+       }
+       if (!do_norm && ULONG_CMP_LT(sdp->srcu_gp_seq_needed_exp, s)) {
+               sdp->srcu_gp_seq_needed_exp = s;
+               needexp = true;
+       }
+       spin_unlock_irqrestore(&sdp->lock, flags);
+       if (needgp)
+               srcu_funnel_gp_start(sp, sdp, s, do_norm);
+       else if (needexp)
+               srcu_funnel_exp_start(sp, sdp->mynode, s);
+}
+
+void call_srcu(struct srcu_struct *sp, struct rcu_head *rhp,
+              rcu_callback_t func)
+{
+       __call_srcu(sp, rhp, func, true);
+}
+EXPORT_SYMBOL_GPL(call_srcu);
+
+/*
+ * Helper function for synchronize_srcu() and synchronize_srcu_expedited().
+ */
+static void __synchronize_srcu(struct srcu_struct *sp, bool do_norm)
+{
+       struct rcu_synchronize rcu;
+
+       RCU_LOCKDEP_WARN(lock_is_held(&sp->dep_map) ||
+                        lock_is_held(&rcu_bh_lock_map) ||
+                        lock_is_held(&rcu_lock_map) ||
+                        lock_is_held(&rcu_sched_lock_map),
+                        "Illegal synchronize_srcu() in same-type SRCU (or in RCU) read-side critical section");
+
+       if (rcu_scheduler_active == RCU_SCHEDULER_INACTIVE)
+               return;
+       might_sleep();
+       check_init_srcu_struct(sp);
+       init_completion(&rcu.completion);
+       init_rcu_head_on_stack(&rcu.head);
+       __call_srcu(sp, &rcu.head, wakeme_after_rcu, do_norm);
+       wait_for_completion(&rcu.completion);
+       destroy_rcu_head_on_stack(&rcu.head);
+}
+
+/**
+ * synchronize_srcu_expedited - Brute-force SRCU grace period
+ * @sp: srcu_struct with which to synchronize.
+ *
+ * Wait for an SRCU grace period to elapse, but be more aggressive about
+ * spinning rather than blocking when waiting.
+ *
+ * Note that synchronize_srcu_expedited() has the same deadlock and
+ * memory-ordering properties as does synchronize_srcu().
+ */
+void synchronize_srcu_expedited(struct srcu_struct *sp)
+{
+       __synchronize_srcu(sp, rcu_gp_is_normal());
+}
+EXPORT_SYMBOL_GPL(synchronize_srcu_expedited);
+
+/**
+ * synchronize_srcu - wait for prior SRCU read-side critical-section completion
+ * @sp: srcu_struct with which to synchronize.
+ *
+ * Wait for the count to drain to zero of both indexes. To avoid the
+ * possible starvation of synchronize_srcu(), it waits for the count of
+ * the index=((->srcu_idx & 1) ^ 1) to drain to zero at first,
+ * and then flip the srcu_idx and wait for the count of the other index.
+ *
+ * Can block; must be called from process context.
+ *
+ * Note that it is illegal to call synchronize_srcu() from the corresponding
+ * SRCU read-side critical section; doing so will result in deadlock.
+ * However, it is perfectly legal to call synchronize_srcu() on one
+ * srcu_struct from some other srcu_struct's read-side critical section,
+ * as long as the resulting graph of srcu_structs is acyclic.
+ *
+ * There are memory-ordering constraints implied by synchronize_srcu().
+ * On systems with more than one CPU, when synchronize_srcu() returns,
+ * each CPU is guaranteed to have executed a full memory barrier since
+ * the end of its last corresponding SRCU-sched read-side critical section
+ * whose beginning preceded the call to synchronize_srcu().  In addition,
+ * each CPU having an SRCU read-side critical section that extends beyond
+ * the return from synchronize_srcu() is guaranteed to have executed a
+ * full memory barrier after the beginning of synchronize_srcu() and before
+ * the beginning of that SRCU read-side critical section.  Note that these
+ * guarantees include CPUs that are offline, idle, or executing in user mode,
+ * as well as CPUs that are executing in the kernel.
+ *
+ * Furthermore, if CPU A invoked synchronize_srcu(), which returned
+ * to its caller on CPU B, then both CPU A and CPU B are guaranteed
+ * to have executed a full memory barrier during the execution of
+ * synchronize_srcu().  This guarantee applies even if CPU A and CPU B
+ * are the same CPU, but again only if the system has more than one CPU.
+ *
+ * Of course, these memory-ordering guarantees apply only when
+ * synchronize_srcu(), srcu_read_lock(), and srcu_read_unlock() are
+ * passed the same srcu_struct structure.
+ *
+ * If SRCU is likely idle, expedite the first request.  This semantic
+ * was provided by Classic SRCU, and is relied upon by its users, so TREE
+ * SRCU must also provide it.  Note that detecting idleness is heuristic
+ * and subject to both false positives and negatives.
+ */
+void synchronize_srcu(struct srcu_struct *sp)
+{
+       if (srcu_might_be_idle(sp) || rcu_gp_is_expedited())
+               synchronize_srcu_expedited(sp);
+       else
+               __synchronize_srcu(sp, true);
+}
+EXPORT_SYMBOL_GPL(synchronize_srcu);
+
+/*
+ * Callback function for srcu_barrier() use.
+ */
+static void srcu_barrier_cb(struct rcu_head *rhp)
+{
+       struct srcu_data *sdp;
+       struct srcu_struct *sp;
+
+       sdp = container_of(rhp, struct srcu_data, srcu_barrier_head);
+       sp = sdp->sp;
+       if (atomic_dec_and_test(&sp->srcu_barrier_cpu_cnt))
+               complete(&sp->srcu_barrier_completion);
+}
+
+/**
+ * srcu_barrier - Wait until all in-flight call_srcu() callbacks complete.
+ * @sp: srcu_struct on which to wait for in-flight callbacks.
+ */
+void srcu_barrier(struct srcu_struct *sp)
+{
+       int cpu;
+       struct srcu_data *sdp;
+       unsigned long s = rcu_seq_snap(&sp->srcu_barrier_seq);
+
+       check_init_srcu_struct(sp);
+       mutex_lock(&sp->srcu_barrier_mutex);
+       if (rcu_seq_done(&sp->srcu_barrier_seq, s)) {
+               smp_mb(); /* Force ordering following return. */
+               mutex_unlock(&sp->srcu_barrier_mutex);
+               return; /* Someone else did our work for us. */
+       }
+       rcu_seq_start(&sp->srcu_barrier_seq);
+       init_completion(&sp->srcu_barrier_completion);
+
+       /* Initial count prevents reaching zero until all CBs are posted. */
+       atomic_set(&sp->srcu_barrier_cpu_cnt, 1);
+
+       /*
+        * Each pass through this loop enqueues a callback, but only
+        * on CPUs already having callbacks enqueued.  Note that if
+        * a CPU already has callbacks enqueue, it must have already
+        * registered the need for a future grace period, so all we
+        * need do is enqueue a callback that will use the same
+        * grace period as the last callback already in the queue.
+        */
+       for_each_possible_cpu(cpu) {
+               sdp = per_cpu_ptr(sp->sda, cpu);
+               spin_lock_irq(&sdp->lock);
+               atomic_inc(&sp->srcu_barrier_cpu_cnt);
+               sdp->srcu_barrier_head.func = srcu_barrier_cb;
+               if (!rcu_segcblist_entrain(&sdp->srcu_cblist,
+                                          &sdp->srcu_barrier_head, 0))
+                       atomic_dec(&sp->srcu_barrier_cpu_cnt);
+               spin_unlock_irq(&sdp->lock);
+       }
+
+       /* Remove the initial count, at which point reaching zero can happen. */
+       if (atomic_dec_and_test(&sp->srcu_barrier_cpu_cnt))
+               complete(&sp->srcu_barrier_completion);
+       wait_for_completion(&sp->srcu_barrier_completion);
+
+       rcu_seq_end(&sp->srcu_barrier_seq);
+       mutex_unlock(&sp->srcu_barrier_mutex);
+}
+EXPORT_SYMBOL_GPL(srcu_barrier);
+
+/**
+ * srcu_batches_completed - return batches completed.
+ * @sp: srcu_struct on which to report batch completion.
+ *
+ * Report the number of batches, correlated with, but not necessarily
+ * precisely the same as, the number of grace periods that have elapsed.
+ */
+unsigned long srcu_batches_completed(struct srcu_struct *sp)
+{
+       return sp->srcu_idx;
+}
+EXPORT_SYMBOL_GPL(srcu_batches_completed);
+
+/*
+ * Core SRCU state machine.  Push state bits of ->srcu_gp_seq
+ * to SRCU_STATE_SCAN2, and invoke srcu_gp_end() when scan has
+ * completed in that state.
+ */
+static void srcu_advance_state(struct srcu_struct *sp)
+{
+       int idx;
+
+       mutex_lock(&sp->srcu_gp_mutex);
+
+       /*
+        * Because readers might be delayed for an extended period after
+        * fetching ->srcu_idx for their index, at any point in time there
+        * might well be readers using both idx=0 and idx=1.  We therefore
+        * need to wait for readers to clear from both index values before
+        * invoking a callback.
+        *
+        * The load-acquire ensures that we see the accesses performed
+        * by the prior grace period.
+        */
+       idx = rcu_seq_state(smp_load_acquire(&sp->srcu_gp_seq)); /* ^^^ */
+       if (idx == SRCU_STATE_IDLE) {
+               spin_lock_irq(&sp->gp_lock);
+               if (ULONG_CMP_GE(sp->srcu_gp_seq, sp->srcu_gp_seq_needed)) {
+                       WARN_ON_ONCE(rcu_seq_state(sp->srcu_gp_seq));
+                       spin_unlock_irq(&sp->gp_lock);
+                       mutex_unlock(&sp->srcu_gp_mutex);
+                       return;
+               }
+               idx = rcu_seq_state(READ_ONCE(sp->srcu_gp_seq));
+               if (idx == SRCU_STATE_IDLE)
+                       srcu_gp_start(sp);
+               spin_unlock_irq(&sp->gp_lock);
+               if (idx != SRCU_STATE_IDLE) {
+                       mutex_unlock(&sp->srcu_gp_mutex);
+                       return; /* Someone else started the grace period. */
+               }
+       }
+
+       if (rcu_seq_state(READ_ONCE(sp->srcu_gp_seq)) == SRCU_STATE_SCAN1) {
+               idx = 1 ^ (sp->srcu_idx & 1);
+               if (!try_check_zero(sp, idx, 1)) {
+                       mutex_unlock(&sp->srcu_gp_mutex);
+                       return; /* readers present, retry later. */
+               }
+               srcu_flip(sp);
+               rcu_seq_set_state(&sp->srcu_gp_seq, SRCU_STATE_SCAN2);
+       }
+
+       if (rcu_seq_state(READ_ONCE(sp->srcu_gp_seq)) == SRCU_STATE_SCAN2) {
+
+               /*
+                * SRCU read-side critical sections are normally short,
+                * so check at least twice in quick succession after a flip.
+                */
+               idx = 1 ^ (sp->srcu_idx & 1);
+               if (!try_check_zero(sp, idx, 2)) {
+                       mutex_unlock(&sp->srcu_gp_mutex);
+                       return; /* readers present, retry later. */
+               }
+               srcu_gp_end(sp);  /* Releases ->srcu_gp_mutex. */
+       }
+}
+
+/*
+ * Invoke a limited number of SRCU callbacks that have passed through
+ * their grace period.  If there are more to do, SRCU will reschedule
+ * the workqueue.  Note that needed memory barriers have been executed
+ * in this task's context by srcu_readers_active_idx_check().
+ */
+static void srcu_invoke_callbacks(struct work_struct *work)
+{
+       bool more;
+       struct rcu_cblist ready_cbs;
+       struct rcu_head *rhp;
+       struct srcu_data *sdp;
+       struct srcu_struct *sp;
+
+       sdp = container_of(work, struct srcu_data, work.work);
+       sp = sdp->sp;
+       rcu_cblist_init(&ready_cbs);
+       spin_lock_irq(&sdp->lock);
+       smp_mb(); /* Old grace periods before callback invocation! */
+       rcu_segcblist_advance(&sdp->srcu_cblist,
+                             rcu_seq_current(&sp->srcu_gp_seq));
+       if (sdp->srcu_cblist_invoking ||
+           !rcu_segcblist_ready_cbs(&sdp->srcu_cblist)) {
+               spin_unlock_irq(&sdp->lock);
+               return;  /* Someone else on the job or nothing to do. */
+       }
+
+       /* We are on the job!  Extract and invoke ready callbacks. */
+       sdp->srcu_cblist_invoking = true;
+       rcu_segcblist_extract_done_cbs(&sdp->srcu_cblist, &ready_cbs);
+       spin_unlock_irq(&sdp->lock);
+       rhp = rcu_cblist_dequeue(&ready_cbs);
+       for (; rhp != NULL; rhp = rcu_cblist_dequeue(&ready_cbs)) {
+               local_bh_disable();
+               rhp->func(rhp);
+               local_bh_enable();
+       }
+
+       /*
+        * Update counts, accelerate new callbacks, and if needed,
+        * schedule another round of callback invocation.
+        */
+       spin_lock_irq(&sdp->lock);
+       rcu_segcblist_insert_count(&sdp->srcu_cblist, &ready_cbs);
+       (void)rcu_segcblist_accelerate(&sdp->srcu_cblist,
+                                      rcu_seq_snap(&sp->srcu_gp_seq));
+       sdp->srcu_cblist_invoking = false;
+       more = rcu_segcblist_ready_cbs(&sdp->srcu_cblist);
+       spin_unlock_irq(&sdp->lock);
+       if (more)
+               srcu_schedule_cbs_sdp(sdp, 0);
+}
+
+/*
+ * Finished one round of SRCU grace period.  Start another if there are
+ * more SRCU callbacks queued, otherwise put SRCU into not-running state.
+ */
+static void srcu_reschedule(struct srcu_struct *sp, unsigned long delay)
+{
+       bool pushgp = true;
+
+       spin_lock_irq(&sp->gp_lock);
+       if (ULONG_CMP_GE(sp->srcu_gp_seq, sp->srcu_gp_seq_needed)) {
+               if (!WARN_ON_ONCE(rcu_seq_state(sp->srcu_gp_seq))) {
+                       /* All requests fulfilled, time to go idle. */
+                       pushgp = false;
+               }
+       } else if (!rcu_seq_state(sp->srcu_gp_seq)) {
+               /* Outstanding request and no GP.  Start one. */
+               srcu_gp_start(sp);
+       }
+       spin_unlock_irq(&sp->gp_lock);
+
+       if (pushgp)
+               queue_delayed_work(system_power_efficient_wq, &sp->work, delay);
+}
+
+/*
+ * This is the work-queue function that handles SRCU grace periods.
+ */
+void process_srcu(struct work_struct *work)
+{
+       struct srcu_struct *sp;
+
+       sp = container_of(work, struct srcu_struct, work.work);
+
+       srcu_advance_state(sp);
+       srcu_reschedule(sp, srcu_get_delay(sp));
+}
+EXPORT_SYMBOL_GPL(process_srcu);
+
+void srcutorture_get_gp_data(enum rcutorture_type test_type,
+                            struct srcu_struct *sp, int *flags,
+                            unsigned long *gpnum, unsigned long *completed)
+{
+       if (test_type != SRCU_FLAVOR)
+               return;
+       *flags = 0;
+       *completed = rcu_seq_ctr(sp->srcu_gp_seq);
+       *gpnum = rcu_seq_ctr(sp->srcu_gp_seq_needed);
+}
+EXPORT_SYMBOL_GPL(srcutorture_get_gp_data);
index 6ad330dbbae2ec3fa4f74fdc1cc1a2ff1154bc9d..e5385731e39109d9a27a47d123ac44908402fcce 100644 (file)
@@ -79,7 +79,7 @@ EXPORT_SYMBOL(__rcu_is_watching);
  */
 static int rcu_qsctr_help(struct rcu_ctrlblk *rcp)
 {
-       RCU_TRACE(reset_cpu_stall_ticks(rcp));
+       RCU_TRACE(reset_cpu_stall_ticks(rcp);)
        if (rcp->donetail != rcp->curtail) {
                rcp->donetail = rcp->curtail;
                return 1;
@@ -125,7 +125,7 @@ void rcu_bh_qs(void)
  */
 void rcu_check_callbacks(int user)
 {
-       RCU_TRACE(check_cpu_stalls());
+       RCU_TRACE(check_cpu_stalls();)
        if (user)
                rcu_sched_qs();
        else if (!in_softirq())
@@ -143,7 +143,7 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp)
        const char *rn = NULL;
        struct rcu_head *next, *list;
        unsigned long flags;
-       RCU_TRACE(int cb_count = 0);
+       RCU_TRACE(int cb_count = 0;)
 
        /* Move the ready-to-invoke callbacks to a local list. */
        local_irq_save(flags);
@@ -152,7 +152,7 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp)
                local_irq_restore(flags);
                return;
        }
-       RCU_TRACE(trace_rcu_batch_start(rcp->name, 0, rcp->qlen, -1));
+       RCU_TRACE(trace_rcu_batch_start(rcp->name, 0, rcp->qlen, -1);)
        list = rcp->rcucblist;
        rcp->rcucblist = *rcp->donetail;
        *rcp->donetail = NULL;
@@ -162,7 +162,7 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp)
        local_irq_restore(flags);
 
        /* Invoke the callbacks on the local list. */
-       RCU_TRACE(rn = rcp->name);
+       RCU_TRACE(rn = rcp->name;)
        while (list) {
                next = list->next;
                prefetch(next);
@@ -171,9 +171,9 @@ static void __rcu_process_callbacks(struct rcu_ctrlblk *rcp)
                __rcu_reclaim(rn, list);
                local_bh_enable();
                list = next;
-               RCU_TRACE(cb_count++);
+               RCU_TRACE(cb_count++;)
        }
-       RCU_TRACE(rcu_trace_sub_qlen(rcp, cb_count));
+       RCU_TRACE(rcu_trace_sub_qlen(rcp, cb_count);)
        RCU_TRACE(trace_rcu_batch_end(rcp->name,
                                      cb_count, 0, need_resched(),
                                      is_idle_task(current),
@@ -221,7 +221,7 @@ static void __call_rcu(struct rcu_head *head,
        local_irq_save(flags);
        *rcp->curtail = head;
        rcp->curtail = &head->next;
-       RCU_TRACE(rcp->qlen++);
+       RCU_TRACE(rcp->qlen++;)
        local_irq_restore(flags);
 
        if (unlikely(is_idle_task(current))) {
@@ -254,8 +254,8 @@ EXPORT_SYMBOL_GPL(call_rcu_bh);
 void __init rcu_init(void)
 {
        open_softirq(RCU_SOFTIRQ, rcu_process_callbacks);
-       RCU_TRACE(reset_cpu_stall_ticks(&rcu_sched_ctrlblk));
-       RCU_TRACE(reset_cpu_stall_ticks(&rcu_bh_ctrlblk));
+       RCU_TRACE(reset_cpu_stall_ticks(&rcu_sched_ctrlblk);)
+       RCU_TRACE(reset_cpu_stall_ticks(&rcu_bh_ctrlblk);)
 
        rcu_early_boot_tests();
 }
index c64b827ecbca19656395e873ca06da0c92a6298e..371034e77f87c8c6a7942495284ec3c1331dad18 100644 (file)
@@ -52,7 +52,7 @@ static struct rcu_ctrlblk rcu_bh_ctrlblk = {
        RCU_TRACE(.name = "rcu_bh")
 };
 
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
+#if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_SRCU)
 #include <linux/kernel_stat.h>
 
 int rcu_scheduler_active __read_mostly;
@@ -65,15 +65,16 @@ EXPORT_SYMBOL_GPL(rcu_scheduler_active);
  * to RCU_SCHEDULER_RUNNING, skipping the RCU_SCHEDULER_INIT stage.
  * The reason for this is that Tiny RCU does not need kthreads, so does
  * not have to care about the fact that the scheduler is half-initialized
- * at a certain phase of the boot process.
+ * at a certain phase of the boot process.  Unless SRCU is in the mix.
  */
 void __init rcu_scheduler_starting(void)
 {
        WARN_ON(nr_context_switches() > 0);
-       rcu_scheduler_active = RCU_SCHEDULER_RUNNING;
+       rcu_scheduler_active = IS_ENABLED(CONFIG_SRCU)
+               ? RCU_SCHEDULER_INIT : RCU_SCHEDULER_RUNNING;
 }
 
-#endif /* #ifdef CONFIG_DEBUG_LOCK_ALLOC */
+#endif /* #if defined(CONFIG_DEBUG_LOCK_ALLOC) || defined(CONFIG_SRCU) */
 
 #ifdef CONFIG_RCU_TRACE
 
@@ -162,8 +163,8 @@ static void reset_cpu_stall_ticks(struct rcu_ctrlblk *rcp)
 
 static void check_cpu_stalls(void)
 {
-       RCU_TRACE(check_cpu_stall(&rcu_bh_ctrlblk));
-       RCU_TRACE(check_cpu_stall(&rcu_sched_ctrlblk));
+       RCU_TRACE(check_cpu_stall(&rcu_bh_ctrlblk);)
+       RCU_TRACE(check_cpu_stall(&rcu_sched_ctrlblk);)
 }
 
 #endif /* #ifdef CONFIG_RCU_TRACE */
index a6dcf3bd244f0b4b94ab3670a7c0ffe1670a2af0..e354e475e645ff4f0fab186913a274e931da0db3 100644 (file)
@@ -98,8 +98,8 @@ struct rcu_state sname##_state = { \
        .gpnum = 0UL - 300UL, \
        .completed = 0UL - 300UL, \
        .orphan_lock = __RAW_SPIN_LOCK_UNLOCKED(&sname##_state.orphan_lock), \
-       .orphan_nxttail = &sname##_state.orphan_nxtlist, \
-       .orphan_donetail = &sname##_state.orphan_donelist, \
+       .orphan_pend = RCU_CBLIST_INITIALIZER(sname##_state.orphan_pend), \
+       .orphan_done = RCU_CBLIST_INITIALIZER(sname##_state.orphan_done), \
        .barrier_mutex = __MUTEX_INITIALIZER(sname##_state.barrier_mutex), \
        .name = RCU_STATE_NAME(sname), \
        .abbr = sabbr, \
@@ -124,7 +124,7 @@ static int rcu_fanout_leaf = RCU_FANOUT_LEAF;
 module_param(rcu_fanout_leaf, int, 0444);
 int rcu_num_lvls __read_mostly = RCU_NUM_LVLS;
 /* Number of rcu_nodes at specified level. */
-static int num_rcu_lvl[] = NUM_RCU_LVL_INIT;
+int num_rcu_lvl[] = NUM_RCU_LVL_INIT;
 int rcu_num_nodes __read_mostly = NUM_RCU_NODES; /* Total # rcu_nodes in use. */
 /* panic() on RCU Stall sysctl. */
 int sysctl_panic_on_rcu_stall __read_mostly;
@@ -200,7 +200,7 @@ static const int gp_cleanup_delay;
 
 /*
  * Number of grace periods between delays, normalized by the duration of
- * the delay.  The longer the the delay, the more the grace periods between
+ * the delay.  The longer the delay, the more the grace periods between
  * each delay.  The reason for this normalization is that it means that,
  * for non-zero delays, the overall slowdown of grace periods is constant
  * regardless of the duration of the delay.  This arrangement balances
@@ -273,11 +273,19 @@ void rcu_bh_qs(void)
        }
 }
 
-static DEFINE_PER_CPU(int, rcu_sched_qs_mask);
+/*
+ * Steal a bit from the bottom of ->dynticks for idle entry/exit
+ * control.  Initially this is for TLB flushing.
+ */
+#define RCU_DYNTICK_CTRL_MASK 0x1
+#define RCU_DYNTICK_CTRL_CTR  (RCU_DYNTICK_CTRL_MASK + 1)
+#ifndef rcu_eqs_special_exit
+#define rcu_eqs_special_exit() do { } while (0)
+#endif
 
 static DEFINE_PER_CPU(struct rcu_dynticks, rcu_dynticks) = {
        .dynticks_nesting = DYNTICK_TASK_EXIT_IDLE,
-       .dynticks = ATOMIC_INIT(1),
+       .dynticks = ATOMIC_INIT(RCU_DYNTICK_CTRL_CTR),
 #ifdef CONFIG_NO_HZ_FULL_SYSIDLE
        .dynticks_idle_nesting = DYNTICK_TASK_NEST_VALUE,
        .dynticks_idle = ATOMIC_INIT(1),
@@ -305,15 +313,20 @@ bool rcu_irq_enter_disabled(void)
 static void rcu_dynticks_eqs_enter(void)
 {
        struct rcu_dynticks *rdtp = this_cpu_ptr(&rcu_dynticks);
-       int special;
+       int seq;
 
        /*
-        * CPUs seeing atomic_inc_return() must see prior RCU read-side
+        * CPUs seeing atomic_add_return() must see prior RCU read-side
         * critical sections, and we also must force ordering with the
         * next idle sojourn.
         */
-       special = atomic_inc_return(&rdtp->dynticks);
-       WARN_ON_ONCE(IS_ENABLED(CONFIG_RCU_EQS_DEBUG) && special & 0x1);
+       seq = atomic_add_return(RCU_DYNTICK_CTRL_CTR, &rdtp->dynticks);
+       /* Better be in an extended quiescent state! */
+       WARN_ON_ONCE(IS_ENABLED(CONFIG_RCU_EQS_DEBUG) &&
+                    (seq & RCU_DYNTICK_CTRL_CTR));
+       /* Better not have special action (TLB flush) pending! */
+       WARN_ON_ONCE(IS_ENABLED(CONFIG_RCU_EQS_DEBUG) &&
+                    (seq & RCU_DYNTICK_CTRL_MASK));
 }
 
 /*
@@ -323,15 +336,22 @@ static void rcu_dynticks_eqs_enter(void)
 static void rcu_dynticks_eqs_exit(void)
 {
        struct rcu_dynticks *rdtp = this_cpu_ptr(&rcu_dynticks);
-       int special;
+       int seq;
 
        /*
-        * CPUs seeing atomic_inc_return() must see prior idle sojourns,
+        * CPUs seeing atomic_add_return() must see prior idle sojourns,
         * and we also must force ordering with the next RCU read-side
         * critical section.
         */
-       special = atomic_inc_return(&rdtp->dynticks);
-       WARN_ON_ONCE(IS_ENABLED(CONFIG_RCU_EQS_DEBUG) && !(special & 0x1));
+       seq = atomic_add_return(RCU_DYNTICK_CTRL_CTR, &rdtp->dynticks);
+       WARN_ON_ONCE(IS_ENABLED(CONFIG_RCU_EQS_DEBUG) &&
+                    !(seq & RCU_DYNTICK_CTRL_CTR));
+       if (seq & RCU_DYNTICK_CTRL_MASK) {
+               atomic_andnot(RCU_DYNTICK_CTRL_MASK, &rdtp->dynticks);
+               smp_mb__after_atomic(); /* _exit after clearing mask. */
+               /* Prefer duplicate flushes to losing a flush. */
+               rcu_eqs_special_exit();
+       }
 }
 
 /*
@@ -348,9 +368,9 @@ static void rcu_dynticks_eqs_online(void)
 {
        struct rcu_dynticks *rdtp = this_cpu_ptr(&rcu_dynticks);
 
-       if (atomic_read(&rdtp->dynticks) & 0x1)
+       if (atomic_read(&rdtp->dynticks) & RCU_DYNTICK_CTRL_CTR)
                return;
-       atomic_add(0x1, &rdtp->dynticks);
+       atomic_add(RCU_DYNTICK_CTRL_CTR, &rdtp->dynticks);
 }
 
 /*
@@ -362,7 +382,7 @@ bool rcu_dynticks_curr_cpu_in_eqs(void)
 {
        struct rcu_dynticks *rdtp = this_cpu_ptr(&rcu_dynticks);
 
-       return !(atomic_read(&rdtp->dynticks) & 0x1);
+       return !(atomic_read(&rdtp->dynticks) & RCU_DYNTICK_CTRL_CTR);
 }
 
 /*
@@ -373,7 +393,7 @@ int rcu_dynticks_snap(struct rcu_dynticks *rdtp)
 {
        int snap = atomic_add_return(0, &rdtp->dynticks);
 
-       return snap;
+       return snap & ~RCU_DYNTICK_CTRL_MASK;
 }
 
 /*
@@ -382,7 +402,7 @@ int rcu_dynticks_snap(struct rcu_dynticks *rdtp)
  */
 static bool rcu_dynticks_in_eqs(int snap)
 {
-       return !(snap & 0x1);
+       return !(snap & RCU_DYNTICK_CTRL_CTR);
 }
 
 /*
@@ -402,14 +422,34 @@ static bool rcu_dynticks_in_eqs_since(struct rcu_dynticks *rdtp, int snap)
 static void rcu_dynticks_momentary_idle(void)
 {
        struct rcu_dynticks *rdtp = this_cpu_ptr(&rcu_dynticks);
-       int special = atomic_add_return(2, &rdtp->dynticks);
+       int special = atomic_add_return(2 * RCU_DYNTICK_CTRL_CTR,
+                                       &rdtp->dynticks);
 
        /* It is illegal to call this from idle state. */
-       WARN_ON_ONCE(!(special & 0x1));
+       WARN_ON_ONCE(!(special & RCU_DYNTICK_CTRL_CTR));
 }
 
-DEFINE_PER_CPU_SHARED_ALIGNED(unsigned long, rcu_qs_ctr);
-EXPORT_PER_CPU_SYMBOL_GPL(rcu_qs_ctr);
+/*
+ * Set the special (bottom) bit of the specified CPU so that it
+ * will take special action (such as flushing its TLB) on the
+ * next exit from an extended quiescent state.  Returns true if
+ * the bit was successfully set, or false if the CPU was not in
+ * an extended quiescent state.
+ */
+bool rcu_eqs_special_set(int cpu)
+{
+       int old;
+       int new;
+       struct rcu_dynticks *rdtp = &per_cpu(rcu_dynticks, cpu);
+
+       do {
+               old = atomic_read(&rdtp->dynticks);
+               if (old & RCU_DYNTICK_CTRL_CTR)
+                       return false;
+               new = old | RCU_DYNTICK_CTRL_MASK;
+       } while (atomic_cmpxchg(&rdtp->dynticks, old, new) != old);
+       return true;
+}
 
 /*
  * Let the RCU core know that this CPU has gone through the scheduler,
@@ -418,44 +458,14 @@ EXPORT_PER_CPU_SYMBOL_GPL(rcu_qs_ctr);
  * memory barriers to let the RCU core know about it, regardless of what
  * this CPU might (or might not) do in the near future.
  *
- * We inform the RCU core by emulating a zero-duration dyntick-idle
- * period, which we in turn do by incrementing the ->dynticks counter
- * by two.
+ * We inform the RCU core by emulating a zero-duration dyntick-idle period.
  *
  * The caller must have disabled interrupts.
  */
 static void rcu_momentary_dyntick_idle(void)
 {
-       struct rcu_data *rdp;
-       int resched_mask;
-       struct rcu_state *rsp;
-
-       /*
-        * Yes, we can lose flag-setting operations.  This is OK, because
-        * the flag will be set again after some delay.
-        */
-       resched_mask = raw_cpu_read(rcu_sched_qs_mask);
-       raw_cpu_write(rcu_sched_qs_mask, 0);
-
-       /* Find the flavor that needs a quiescent state. */
-       for_each_rcu_flavor(rsp) {
-               rdp = raw_cpu_ptr(rsp->rda);
-               if (!(resched_mask & rsp->flavor_mask))
-                       continue;
-               smp_mb(); /* rcu_sched_qs_mask before cond_resched_completed. */
-               if (READ_ONCE(rdp->mynode->completed) !=
-                   READ_ONCE(rdp->cond_resched_completed))
-                       continue;
-
-               /*
-                * Pretend to be momentarily idle for the quiescent state.
-                * This allows the grace-period kthread to record the
-                * quiescent state, with no need for this CPU to do anything
-                * further.
-                */
-               rcu_dynticks_momentary_idle();
-               break;
-       }
+       raw_cpu_write(rcu_dynticks.rcu_need_heavy_qs, false);
+       rcu_dynticks_momentary_idle();
 }
 
 /*
@@ -463,14 +473,22 @@ static void rcu_momentary_dyntick_idle(void)
  * and requires special handling for preemptible RCU.
  * The caller must have disabled interrupts.
  */
-void rcu_note_context_switch(void)
+void rcu_note_context_switch(bool preempt)
 {
        barrier(); /* Avoid RCU read-side critical sections leaking down. */
        trace_rcu_utilization(TPS("Start context switch"));
        rcu_sched_qs();
        rcu_preempt_note_context_switch();
-       if (unlikely(raw_cpu_read(rcu_sched_qs_mask)))
+       /* Load rcu_urgent_qs before other flags. */
+       if (!smp_load_acquire(this_cpu_ptr(&rcu_dynticks.rcu_urgent_qs)))
+               goto out;
+       this_cpu_write(rcu_dynticks.rcu_urgent_qs, false);
+       if (unlikely(raw_cpu_read(rcu_dynticks.rcu_need_heavy_qs)))
                rcu_momentary_dyntick_idle();
+       this_cpu_inc(rcu_dynticks.rcu_qs_ctr);
+       if (!preempt)
+               rcu_note_voluntary_context_switch_lite(current);
+out:
        trace_rcu_utilization(TPS("End context switch"));
        barrier(); /* Avoid RCU read-side critical sections leaking up. */
 }
@@ -493,29 +511,26 @@ void rcu_all_qs(void)
 {
        unsigned long flags;
 
+       if (!raw_cpu_read(rcu_dynticks.rcu_urgent_qs))
+               return;
+       preempt_disable();
+       /* Load rcu_urgent_qs before other flags. */
+       if (!smp_load_acquire(this_cpu_ptr(&rcu_dynticks.rcu_urgent_qs))) {
+               preempt_enable();
+               return;
+       }
+       this_cpu_write(rcu_dynticks.rcu_urgent_qs, false);
        barrier(); /* Avoid RCU read-side critical sections leaking down. */
-       if (unlikely(raw_cpu_read(rcu_sched_qs_mask))) {
+       if (unlikely(raw_cpu_read(rcu_dynticks.rcu_need_heavy_qs))) {
                local_irq_save(flags);
                rcu_momentary_dyntick_idle();
                local_irq_restore(flags);
        }
-       if (unlikely(raw_cpu_read(rcu_sched_data.cpu_no_qs.b.exp))) {
-               /*
-                * Yes, we just checked a per-CPU variable with preemption
-                * enabled, so we might be migrated to some other CPU at
-                * this point.  That is OK because in that case, the
-                * migration will supply the needed quiescent state.
-                * We might end up needlessly disabling preemption and
-                * invoking rcu_sched_qs() on the destination CPU, but
-                * the probability and cost are both quite low, so this
-                * should not be a problem in practice.
-                */
-               preempt_disable();
+       if (unlikely(raw_cpu_read(rcu_sched_data.cpu_no_qs.b.exp)))
                rcu_sched_qs();
-               preempt_enable();
-       }
-       this_cpu_inc(rcu_qs_ctr);
+       this_cpu_inc(rcu_dynticks.rcu_qs_ctr);
        barrier(); /* Avoid RCU read-side critical sections leaking up. */
+       preempt_enable();
 }
 EXPORT_SYMBOL_GPL(rcu_all_qs);
 
@@ -704,15 +719,11 @@ void rcutorture_get_gp_data(enum rcutorture_type test_type, int *flags,
        default:
                break;
        }
-       if (rsp != NULL) {
-               *flags = READ_ONCE(rsp->gp_flags);
-               *gpnum = READ_ONCE(rsp->gpnum);
-               *completed = READ_ONCE(rsp->completed);
+       if (rsp == NULL)
                return;
-       }
-       *flags = 0;
-       *gpnum = 0;
-       *completed = 0;
+       *flags = READ_ONCE(rsp->gp_flags);
+       *gpnum = READ_ONCE(rsp->gpnum);
+       *completed = READ_ONCE(rsp->completed);
 }
 EXPORT_SYMBOL_GPL(rcutorture_get_gp_data);
 
@@ -727,16 +738,6 @@ void rcutorture_record_progress(unsigned long vernum)
 }
 EXPORT_SYMBOL_GPL(rcutorture_record_progress);
 
-/*
- * Does the CPU have callbacks ready to be invoked?
- */
-static int
-cpu_has_callbacks_ready_to_invoke(struct rcu_data *rdp)
-{
-       return &rdp->nxtlist != rdp->nxttail[RCU_DONE_TAIL] &&
-              rdp->nxttail[RCU_NEXT_TAIL] != NULL;
-}
-
 /*
  * Return the root node of the specified rcu_state structure.
  */
@@ -767,21 +768,17 @@ static int rcu_future_needs_gp(struct rcu_state *rsp)
 static bool
 cpu_needs_another_gp(struct rcu_state *rsp, struct rcu_data *rdp)
 {
-       int i;
-
        if (rcu_gp_in_progress(rsp))
                return false;  /* No, a grace period is already in progress. */
        if (rcu_future_needs_gp(rsp))
                return true;  /* Yes, a no-CBs CPU needs one. */
-       if (!rdp->nxttail[RCU_NEXT_TAIL])
+       if (!rcu_segcblist_is_enabled(&rdp->cblist))
                return false;  /* No, this is a no-CBs (or offline) CPU. */
-       if (*rdp->nxttail[RCU_NEXT_READY_TAIL])
+       if (!rcu_segcblist_restempty(&rdp->cblist, RCU_NEXT_READY_TAIL))
                return true;  /* Yes, CPU has newly registered callbacks. */
-       for (i = RCU_WAIT_TAIL; i < RCU_NEXT_TAIL; i++)
-               if (rdp->nxttail[i - 1] != rdp->nxttail[i] &&
-                   ULONG_CMP_LT(READ_ONCE(rsp->completed),
-                                rdp->nxtcompleted[i]))
-                       return true;  /* Yes, CBs for future grace period. */
+       if (rcu_segcblist_future_gp_needed(&rdp->cblist,
+                                          READ_ONCE(rsp->completed)))
+               return true;  /* Yes, CBs for future grace period. */
        return false; /* No grace period needed. */
 }
 
@@ -1162,6 +1159,24 @@ bool notrace rcu_is_watching(void)
 }
 EXPORT_SYMBOL_GPL(rcu_is_watching);
 
+/*
+ * If a holdout task is actually running, request an urgent quiescent
+ * state from its CPU.  This is unsynchronized, so migrations can cause
+ * the request to go to the wrong CPU.  Which is OK, all that will happen
+ * is that the CPU's next context switch will be a bit slower and next
+ * time around this task will generate another request.
+ */
+void rcu_request_urgent_qs_task(struct task_struct *t)
+{
+       int cpu;
+
+       barrier();
+       cpu = task_cpu(t);
+       if (!task_curr(t))
+               return; /* This task is not running on that CPU. */
+       smp_store_release(per_cpu_ptr(&rcu_dynticks.rcu_urgent_qs, cpu), true);
+}
+
 #if defined(CONFIG_PROVE_RCU) && defined(CONFIG_HOTPLUG_CPU)
 
 /*
@@ -1247,7 +1262,8 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp,
                                    bool *isidle, unsigned long *maxj)
 {
        unsigned long jtsq;
-       int *rcrmp;
+       bool *rnhqp;
+       bool *ruqp;
        unsigned long rjtsc;
        struct rcu_node *rnp;
 
@@ -1283,11 +1299,15 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp,
         * might not be the case for nohz_full CPUs looping in the kernel.
         */
        rnp = rdp->mynode;
+       ruqp = per_cpu_ptr(&rcu_dynticks.rcu_urgent_qs, rdp->cpu);
        if (time_after(jiffies, rdp->rsp->gp_start + jtsq) &&
-           READ_ONCE(rdp->rcu_qs_ctr_snap) != per_cpu(rcu_qs_ctr, rdp->cpu) &&
+           READ_ONCE(rdp->rcu_qs_ctr_snap) != per_cpu(rcu_dynticks.rcu_qs_ctr, rdp->cpu) &&
            READ_ONCE(rdp->gpnum) == rnp->gpnum && !rdp->gpwrap) {
                trace_rcu_fqs(rdp->rsp->name, rdp->gpnum, rdp->cpu, TPS("rqc"));
                return 1;
+       } else {
+               /* Load rcu_qs_ctr before store to rcu_urgent_qs. */
+               smp_store_release(ruqp, true);
        }
 
        /* Check for the CPU being offline. */
@@ -1304,7 +1324,7 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp,
         * in-kernel CPU-bound tasks cannot advance grace periods.
         * So if the grace period is old enough, make the CPU pay attention.
         * Note that the unsynchronized assignments to the per-CPU
-        * rcu_sched_qs_mask variable are safe.  Yes, setting of
+        * rcu_need_heavy_qs variable are safe.  Yes, setting of
         * bits can be lost, but they will be set again on the next
         * force-quiescent-state pass.  So lost bit sets do not result
         * in incorrect behavior, merely in a grace period lasting
@@ -1318,16 +1338,13 @@ static int rcu_implicit_dynticks_qs(struct rcu_data *rdp,
         * is set too high, we override with half of the RCU CPU stall
         * warning delay.
         */
-       rcrmp = &per_cpu(rcu_sched_qs_mask, rdp->cpu);
-       if (time_after(jiffies, rdp->rsp->gp_start + jtsq) ||
-           time_after(jiffies, rdp->rsp->jiffies_resched)) {
-               if (!(READ_ONCE(*rcrmp) & rdp->rsp->flavor_mask)) {
-                       WRITE_ONCE(rdp->cond_resched_completed,
-                                  READ_ONCE(rdp->mynode->completed));
-                       smp_mb(); /* ->cond_resched_completed before *rcrmp. */
-                       WRITE_ONCE(*rcrmp,
-                                  READ_ONCE(*rcrmp) + rdp->rsp->flavor_mask);
-               }
+       rnhqp = &per_cpu(rcu_dynticks.rcu_need_heavy_qs, rdp->cpu);
+       if (!READ_ONCE(*rnhqp) &&
+           (time_after(jiffies, rdp->rsp->gp_start + jtsq) ||
+            time_after(jiffies, rdp->rsp->jiffies_resched))) {
+               WRITE_ONCE(*rnhqp, true);
+               /* Store rcu_need_heavy_qs before rcu_urgent_qs. */
+               smp_store_release(ruqp, true);
                rdp->rsp->jiffies_resched += 5; /* Re-enable beating. */
        }
 
@@ -1487,7 +1504,8 @@ static void print_other_cpu_stall(struct rcu_state *rsp, unsigned long gpnum)
 
        print_cpu_stall_info_end();
        for_each_possible_cpu(cpu)
-               totqlen += per_cpu_ptr(rsp->rda, cpu)->qlen;
+               totqlen += rcu_segcblist_n_cbs(&per_cpu_ptr(rsp->rda,
+                                                           cpu)->cblist);
        pr_cont("(detected by %d, t=%ld jiffies, g=%ld, c=%ld, q=%lu)\n",
               smp_processor_id(), (long)(jiffies - rsp->gp_start),
               (long)rsp->gpnum, (long)rsp->completed, totqlen);
@@ -1541,7 +1559,8 @@ static void print_cpu_stall(struct rcu_state *rsp)
        print_cpu_stall_info(rsp, smp_processor_id());
        print_cpu_stall_info_end();
        for_each_possible_cpu(cpu)
-               totqlen += per_cpu_ptr(rsp->rda, cpu)->qlen;
+               totqlen += rcu_segcblist_n_cbs(&per_cpu_ptr(rsp->rda,
+                                                           cpu)->cblist);
        pr_cont(" (t=%lu jiffies g=%ld c=%ld q=%lu)\n",
                jiffies - rsp->gp_start,
                (long)rsp->gpnum, (long)rsp->completed, totqlen);
@@ -1643,30 +1662,6 @@ void rcu_cpu_stall_reset(void)
                WRITE_ONCE(rsp->jiffies_stall, jiffies + ULONG_MAX / 2);
 }
 
-/*
- * Initialize the specified rcu_data structure's default callback list
- * to empty.  The default callback list is the one that is not used by
- * no-callbacks CPUs.
- */
-static void init_default_callback_list(struct rcu_data *rdp)
-{
-       int i;
-
-       rdp->nxtlist = NULL;
-       for (i = 0; i < RCU_NEXT_SIZE; i++)
-               rdp->nxttail[i] = &rdp->nxtlist;
-}
-
-/*
- * Initialize the specified rcu_data structure's callback list to empty.
- */
-static void init_callback_list(struct rcu_data *rdp)
-{
-       if (init_nocb_callback_list(rdp))
-               return;
-       init_default_callback_list(rdp);
-}
-
 /*
  * Determine the value that ->completed will have at the end of the
  * next subsequent grace period.  This is used to tag callbacks so that
@@ -1721,7 +1716,6 @@ rcu_start_future_gp(struct rcu_node *rnp, struct rcu_data *rdp,
                    unsigned long *c_out)
 {
        unsigned long c;
-       int i;
        bool ret = false;
        struct rcu_node *rnp_root = rcu_get_root(rdp->rsp);
 
@@ -1767,13 +1761,11 @@ rcu_start_future_gp(struct rcu_node *rnp, struct rcu_data *rdp,
        /*
         * Get a new grace-period number.  If there really is no grace
         * period in progress, it will be smaller than the one we obtained
-        * earlier.  Adjust callbacks as needed.  Note that even no-CBs
-        * CPUs have a ->nxtcompleted[] array, so no no-CBs checks needed.
+        * earlier.  Adjust callbacks as needed.
         */
        c = rcu_cbs_completed(rdp->rsp, rnp_root);
-       for (i = RCU_DONE_TAIL; i < RCU_NEXT_TAIL; i++)
-               if (ULONG_CMP_LT(c, rdp->nxtcompleted[i]))
-                       rdp->nxtcompleted[i] = c;
+       if (!rcu_is_nocb_cpu(rdp->cpu))
+               (void)rcu_segcblist_accelerate(&rdp->cblist, c);
 
        /*
         * If the needed for the required grace period is already
@@ -1805,9 +1797,7 @@ out:
 
 /*
  * Clean up any old requests for the just-ended grace period.  Also return
- * whether any additional grace periods have been requested.  Also invoke
- * rcu_nocb_gp_cleanup() in order to wake up any no-callbacks kthreads
- * waiting for this grace period to complete.
+ * whether any additional grace periods have been requested.
  */
 static int rcu_future_gp_cleanup(struct rcu_state *rsp, struct rcu_node *rnp)
 {
@@ -1853,57 +1843,27 @@ static void rcu_gp_kthread_wake(struct rcu_state *rsp)
 static bool rcu_accelerate_cbs(struct rcu_state *rsp, struct rcu_node *rnp,
                               struct rcu_data *rdp)
 {
-       unsigned long c;
-       int i;
-       bool ret;
-
-       /* If the CPU has no callbacks, nothing to do. */
-       if (!rdp->nxttail[RCU_NEXT_TAIL] || !*rdp->nxttail[RCU_DONE_TAIL])
-               return false;
-
-       /*
-        * Starting from the sublist containing the callbacks most
-        * recently assigned a ->completed number and working down, find the
-        * first sublist that is not assignable to an upcoming grace period.
-        * Such a sublist has something in it (first two tests) and has
-        * a ->completed number assigned that will complete sooner than
-        * the ->completed number for newly arrived callbacks (last test).
-        *
-        * The key point is that any later sublist can be assigned the
-        * same ->completed number as the newly arrived callbacks, which
-        * means that the callbacks in any of these later sublist can be
-        * grouped into a single sublist, whether or not they have already
-        * been assigned a ->completed number.
-        */
-       c = rcu_cbs_completed(rsp, rnp);
-       for (i = RCU_NEXT_TAIL - 1; i > RCU_DONE_TAIL; i--)
-               if (rdp->nxttail[i] != rdp->nxttail[i - 1] &&
-                   !ULONG_CMP_GE(rdp->nxtcompleted[i], c))
-                       break;
+       bool ret = false;
 
-       /*
-        * If there are no sublist for unassigned callbacks, leave.
-        * At the same time, advance "i" one sublist, so that "i" will
-        * index into the sublist where all the remaining callbacks should
-        * be grouped into.
-        */
-       if (++i >= RCU_NEXT_TAIL)
+       /* If no pending (not yet ready to invoke) callbacks, nothing to do. */
+       if (!rcu_segcblist_pend_cbs(&rdp->cblist))
                return false;
 
        /*
-        * Assign all subsequent callbacks' ->completed number to the next
-        * full grace period and group them all in the sublist initially
-        * indexed by "i".
+        * Callbacks are often registered with incomplete grace-period
+        * information.  Something about the fact that getting exact
+        * information requires acquiring a global lock...  RCU therefore
+        * makes a conservative estimate of the grace period number at which
+        * a given callback will become ready to invoke.        The following
+        * code checks this estimate and improves it when possible, thus
+        * accelerating callback invocation to an earlier grace-period
+        * number.
         */
-       for (; i <= RCU_NEXT_TAIL; i++) {
-               rdp->nxttail[i] = rdp->nxttail[RCU_NEXT_TAIL];
-               rdp->nxtcompleted[i] = c;
-       }
-       /* Record any needed additional grace periods. */
-       ret = rcu_start_future_gp(rnp, rdp, NULL);
+       if (rcu_segcblist_accelerate(&rdp->cblist, rcu_cbs_completed(rsp, rnp)))
+               ret = rcu_start_future_gp(rnp, rdp, NULL);
 
        /* Trace depending on how much we were able to accelerate. */
-       if (!*rdp->nxttail[RCU_WAIT_TAIL])
+       if (rcu_segcblist_restempty(&rdp->cblist, RCU_WAIT_TAIL))
                trace_rcu_grace_period(rsp->name, rdp->gpnum, TPS("AccWaitCB"));
        else
                trace_rcu_grace_period(rsp->name, rdp->gpnum, TPS("AccReadyCB"));
@@ -1923,32 +1883,15 @@ static bool rcu_accelerate_cbs(struct rcu_state *rsp, struct rcu_node *rnp,
 static bool rcu_advance_cbs(struct rcu_state *rsp, struct rcu_node *rnp,
                            struct rcu_data *rdp)
 {
-       int i, j;
-
-       /* If the CPU has no callbacks, nothing to do. */
-       if (!rdp->nxttail[RCU_NEXT_TAIL] || !*rdp->nxttail[RCU_DONE_TAIL])
+       /* If no pending (not yet ready to invoke) callbacks, nothing to do. */
+       if (!rcu_segcblist_pend_cbs(&rdp->cblist))
                return false;
 
        /*
         * Find all callbacks whose ->completed numbers indicate that they
         * are ready to invoke, and put them into the RCU_DONE_TAIL sublist.
         */
-       for (i = RCU_WAIT_TAIL; i < RCU_NEXT_TAIL; i++) {
-               if (ULONG_CMP_LT(rnp->completed, rdp->nxtcompleted[i]))
-                       break;
-               rdp->nxttail[RCU_DONE_TAIL] = rdp->nxttail[i];
-       }
-       /* Clean up any sublist tail pointers that were misordered above. */
-       for (j = RCU_WAIT_TAIL; j < i; j++)
-               rdp->nxttail[j] = rdp->nxttail[RCU_DONE_TAIL];
-
-       /* Copy down callbacks to fill in empty sublists. */
-       for (j = RCU_WAIT_TAIL; i < RCU_NEXT_TAIL; i++, j++) {
-               if (rdp->nxttail[j] == rdp->nxttail[RCU_NEXT_TAIL])
-                       break;
-               rdp->nxttail[j] = rdp->nxttail[i];
-               rdp->nxtcompleted[j] = rdp->nxtcompleted[i];
-       }
+       rcu_segcblist_advance(&rdp->cblist, rnp->completed);
 
        /* Classify any remaining callbacks. */
        return rcu_accelerate_cbs(rsp, rnp, rdp);
@@ -1993,7 +1936,7 @@ static bool __note_gp_changes(struct rcu_state *rsp, struct rcu_node *rnp,
                trace_rcu_grace_period(rsp->name, rdp->gpnum, TPS("cpustart"));
                need_gp = !!(rnp->qsmask & rdp->grpmask);
                rdp->cpu_no_qs.b.norm = need_gp;
-               rdp->rcu_qs_ctr_snap = __this_cpu_read(rcu_qs_ctr);
+               rdp->rcu_qs_ctr_snap = __this_cpu_read(rcu_dynticks.rcu_qs_ctr);
                rdp->core_needs_qs = need_gp;
                zero_cpu_stall_ticks(rdp);
                WRITE_ONCE(rdp->gpwrap, false);
@@ -2591,7 +2534,7 @@ rcu_report_qs_rdp(int cpu, struct rcu_state *rsp, struct rcu_data *rdp)
                 * within the current grace period.
                 */
                rdp->cpu_no_qs.b.norm = true;   /* need qs for new gp. */
-               rdp->rcu_qs_ctr_snap = __this_cpu_read(rcu_qs_ctr);
+               rdp->rcu_qs_ctr_snap = __this_cpu_read(rcu_dynticks.rcu_qs_ctr);
                raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
                return;
        }
@@ -2665,13 +2608,8 @@ rcu_send_cbs_to_orphanage(int cpu, struct rcu_state *rsp,
         * because _rcu_barrier() excludes CPU-hotplug operations, so it
         * cannot be running now.  Thus no memory barrier is required.
         */
-       if (rdp->nxtlist != NULL) {
-               rsp->qlen_lazy += rdp->qlen_lazy;
-               rsp->qlen += rdp->qlen;
-               rdp->n_cbs_orphaned += rdp->qlen;
-               rdp->qlen_lazy = 0;
-               WRITE_ONCE(rdp->qlen, 0);
-       }
+       rdp->n_cbs_orphaned += rcu_segcblist_n_cbs(&rdp->cblist);
+       rcu_segcblist_extract_count(&rdp->cblist, &rsp->orphan_done);
 
        /*
         * Next, move those callbacks still needing a grace period to
@@ -2679,31 +2617,18 @@ rcu_send_cbs_to_orphanage(int cpu, struct rcu_state *rsp,
         * Some of the callbacks might have gone partway through a grace
         * period, but that is too bad.  They get to start over because we
         * cannot assume that grace periods are synchronized across CPUs.
-        * We don't bother updating the ->nxttail[] array yet, instead
-        * we just reset the whole thing later on.
         */
-       if (*rdp->nxttail[RCU_DONE_TAIL] != NULL) {
-               *rsp->orphan_nxttail = *rdp->nxttail[RCU_DONE_TAIL];
-               rsp->orphan_nxttail = rdp->nxttail[RCU_NEXT_TAIL];
-               *rdp->nxttail[RCU_DONE_TAIL] = NULL;
-       }
+       rcu_segcblist_extract_pend_cbs(&rdp->cblist, &rsp->orphan_pend);
 
        /*
         * Then move the ready-to-invoke callbacks to the orphanage,
         * where some other CPU will pick them up.  These will not be
         * required to pass though another grace period: They are done.
         */
-       if (rdp->nxtlist != NULL) {
-               *rsp->orphan_donetail = rdp->nxtlist;
-               rsp->orphan_donetail = rdp->nxttail[RCU_DONE_TAIL];
-       }
+       rcu_segcblist_extract_done_cbs(&rdp->cblist, &rsp->orphan_done);
 
-       /*
-        * Finally, initialize the rcu_data structure's list to empty and
-        * disallow further callbacks on this CPU.
-        */
-       init_callback_list(rdp);
-       rdp->nxttail[RCU_NEXT_TAIL] = NULL;
+       /* Finally, disallow further callbacks on this CPU.  */
+       rcu_segcblist_disable(&rdp->cblist);
 }
 
 /*
@@ -2712,7 +2637,6 @@ rcu_send_cbs_to_orphanage(int cpu, struct rcu_state *rsp,
  */
 static void rcu_adopt_orphan_cbs(struct rcu_state *rsp, unsigned long flags)
 {
-       int i;
        struct rcu_data *rdp = raw_cpu_ptr(rsp->rda);
 
        /* No-CBs CPUs are handled specially. */
@@ -2721,13 +2645,10 @@ static void rcu_adopt_orphan_cbs(struct rcu_state *rsp, unsigned long flags)
                return;
 
        /* Do the accounting first. */
-       rdp->qlen_lazy += rsp->qlen_lazy;
-       rdp->qlen += rsp->qlen;
-       rdp->n_cbs_adopted += rsp->qlen;
-       if (rsp->qlen_lazy != rsp->qlen)
+       rdp->n_cbs_adopted += rsp->orphan_done.len;
+       if (rsp->orphan_done.len_lazy != rsp->orphan_done.len)
                rcu_idle_count_callbacks_posted();
-       rsp->qlen_lazy = 0;
-       rsp->qlen = 0;
+       rcu_segcblist_insert_count(&rdp->cblist, &rsp->orphan_done);
 
        /*
         * We do not need a memory barrier here because the only way we
@@ -2735,24 +2656,13 @@ static void rcu_adopt_orphan_cbs(struct rcu_state *rsp, unsigned long flags)
         * we are the task doing the rcu_barrier().
         */
 
-       /* First adopt the ready-to-invoke callbacks. */
-       if (rsp->orphan_donelist != NULL) {
-               *rsp->orphan_donetail = *rdp->nxttail[RCU_DONE_TAIL];
-               *rdp->nxttail[RCU_DONE_TAIL] = rsp->orphan_donelist;
-               for (i = RCU_NEXT_SIZE - 1; i >= RCU_DONE_TAIL; i--)
-                       if (rdp->nxttail[i] == rdp->nxttail[RCU_DONE_TAIL])
-                               rdp->nxttail[i] = rsp->orphan_donetail;
-               rsp->orphan_donelist = NULL;
-               rsp->orphan_donetail = &rsp->orphan_donelist;
-       }
-
-       /* And then adopt the callbacks that still need a grace period. */
-       if (rsp->orphan_nxtlist != NULL) {
-               *rdp->nxttail[RCU_NEXT_TAIL] = rsp->orphan_nxtlist;
-               rdp->nxttail[RCU_NEXT_TAIL] = rsp->orphan_nxttail;
-               rsp->orphan_nxtlist = NULL;
-               rsp->orphan_nxttail = &rsp->orphan_nxtlist;
-       }
+       /* First adopt the ready-to-invoke callbacks, then the done ones. */
+       rcu_segcblist_insert_done_cbs(&rdp->cblist, &rsp->orphan_done);
+       WARN_ON_ONCE(rsp->orphan_done.head);
+       rcu_segcblist_insert_pend_cbs(&rdp->cblist, &rsp->orphan_pend);
+       WARN_ON_ONCE(rsp->orphan_pend.head);
+       WARN_ON_ONCE(rcu_segcblist_empty(&rdp->cblist) !=
+                    !rcu_segcblist_n_cbs(&rdp->cblist));
 }
 
 /*
@@ -2760,14 +2670,14 @@ static void rcu_adopt_orphan_cbs(struct rcu_state *rsp, unsigned long flags)
  */
 static void rcu_cleanup_dying_cpu(struct rcu_state *rsp)
 {
-       RCU_TRACE(unsigned long mask);
-       RCU_TRACE(struct rcu_data *rdp = this_cpu_ptr(rsp->rda));
-       RCU_TRACE(struct rcu_node *rnp = rdp->mynode);
+       RCU_TRACE(unsigned long mask;)
+       RCU_TRACE(struct rcu_data *rdp = this_cpu_ptr(rsp->rda);)
+       RCU_TRACE(struct rcu_node *rnp = rdp->mynode;)
 
        if (!IS_ENABLED(CONFIG_HOTPLUG_CPU))
                return;
 
-       RCU_TRACE(mask = rdp->grpmask);
+       RCU_TRACE(mask = rdp->grpmask;)
        trace_rcu_grace_period(rsp->name,
                               rnp->gpnum + 1 - !!(rnp->qsmask & mask),
                               TPS("cpuofl"));
@@ -2840,9 +2750,11 @@ static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp)
        rcu_adopt_orphan_cbs(rsp, flags);
        raw_spin_unlock_irqrestore(&rsp->orphan_lock, flags);
 
-       WARN_ONCE(rdp->qlen != 0 || rdp->nxtlist != NULL,
-                 "rcu_cleanup_dead_cpu: Callbacks on offline CPU %d: qlen=%lu, nxtlist=%p\n",
-                 cpu, rdp->qlen, rdp->nxtlist);
+       WARN_ONCE(rcu_segcblist_n_cbs(&rdp->cblist) != 0 ||
+                 !rcu_segcblist_empty(&rdp->cblist),
+                 "rcu_cleanup_dead_cpu: Callbacks on offline CPU %d: qlen=%lu, 1stCB=%p\n",
+                 cpu, rcu_segcblist_n_cbs(&rdp->cblist),
+                 rcu_segcblist_first_cb(&rdp->cblist));
 }
 
 /*
@@ -2852,14 +2764,17 @@ static void rcu_cleanup_dead_cpu(int cpu, struct rcu_state *rsp)
 static void rcu_do_batch(struct rcu_state *rsp, struct rcu_data *rdp)
 {
        unsigned long flags;
-       struct rcu_head *next, *list, **tail;
-       long bl, count, count_lazy;
-       int i;
+       struct rcu_head *rhp;
+       struct rcu_cblist rcl = RCU_CBLIST_INITIALIZER(rcl);
+       long bl, count;
 
        /* If no callbacks are ready, just return. */
-       if (!cpu_has_callbacks_ready_to_invoke(rdp)) {
-               trace_rcu_batch_start(rsp->name, rdp->qlen_lazy, rdp->qlen, 0);
-               trace_rcu_batch_end(rsp->name, 0, !!READ_ONCE(rdp->nxtlist),
+       if (!rcu_segcblist_ready_cbs(&rdp->cblist)) {
+               trace_rcu_batch_start(rsp->name,
+                                     rcu_segcblist_n_lazy_cbs(&rdp->cblist),
+                                     rcu_segcblist_n_cbs(&rdp->cblist), 0);
+               trace_rcu_batch_end(rsp->name, 0,
+                                   !rcu_segcblist_empty(&rdp->cblist),
                                    need_resched(), is_idle_task(current),
                                    rcu_is_callbacks_kthread());
                return;
@@ -2867,73 +2782,61 @@ static void rcu_do_batch(struct rcu_state *rsp, struct rcu_data *rdp)
 
        /*
         * Extract the list of ready callbacks, disabling to prevent
-        * races with call_rcu() from interrupt handlers.
+        * races with call_rcu() from interrupt handlers.  Leave the
+        * callback counts, as rcu_barrier() needs to be conservative.
         */
        local_irq_save(flags);
        WARN_ON_ONCE(cpu_is_offline(smp_processor_id()));
        bl = rdp->blimit;
-       trace_rcu_batch_start(rsp->name, rdp->qlen_lazy, rdp->qlen, bl);
-       list = rdp->nxtlist;
-       rdp->nxtlist = *rdp->nxttail[RCU_DONE_TAIL];
-       *rdp->nxttail[RCU_DONE_TAIL] = NULL;
-       tail = rdp->nxttail[RCU_DONE_TAIL];
-       for (i = RCU_NEXT_SIZE - 1; i >= 0; i--)
-               if (rdp->nxttail[i] == rdp->nxttail[RCU_DONE_TAIL])
-                       rdp->nxttail[i] = &rdp->nxtlist;
+       trace_rcu_batch_start(rsp->name, rcu_segcblist_n_lazy_cbs(&rdp->cblist),
+                             rcu_segcblist_n_cbs(&rdp->cblist), bl);
+       rcu_segcblist_extract_done_cbs(&rdp->cblist, &rcl);
        local_irq_restore(flags);
 
        /* Invoke callbacks. */
-       count = count_lazy = 0;
-       while (list) {
-               next = list->next;
-               prefetch(next);
-               debug_rcu_head_unqueue(list);
-               if (__rcu_reclaim(rsp->name, list))
-                       count_lazy++;
-               list = next;
-               /* Stop only if limit reached and CPU has something to do. */
-               if (++count >= bl &&
+       rhp = rcu_cblist_dequeue(&rcl);
+       for (; rhp; rhp = rcu_cblist_dequeue(&rcl)) {
+               debug_rcu_head_unqueue(rhp);
+               if (__rcu_reclaim(rsp->name, rhp))
+                       rcu_cblist_dequeued_lazy(&rcl);
+               /*
+                * Stop only if limit reached and CPU has something to do.
+                * Note: The rcl structure counts down from zero.
+                */
+               if (-rcl.len >= bl &&
                    (need_resched() ||
                     (!is_idle_task(current) && !rcu_is_callbacks_kthread())))
                        break;
        }
 
        local_irq_save(flags);
-       trace_rcu_batch_end(rsp->name, count, !!list, need_resched(),
-                           is_idle_task(current),
-                           rcu_is_callbacks_kthread());
-
-       /* Update count, and requeue any remaining callbacks. */
-       if (list != NULL) {
-               *tail = rdp->nxtlist;
-               rdp->nxtlist = list;
-               for (i = 0; i < RCU_NEXT_SIZE; i++)
-                       if (&rdp->nxtlist == rdp->nxttail[i])
-                               rdp->nxttail[i] = tail;
-                       else
-                               break;
-       }
+       count = -rcl.len;
+       trace_rcu_batch_end(rsp->name, count, !!rcl.head, need_resched(),
+                           is_idle_task(current), rcu_is_callbacks_kthread());
+
+       /* Update counts and requeue any remaining callbacks. */
+       rcu_segcblist_insert_done_cbs(&rdp->cblist, &rcl);
        smp_mb(); /* List handling before counting for rcu_barrier(). */
-       rdp->qlen_lazy -= count_lazy;
-       WRITE_ONCE(rdp->qlen, rdp->qlen - count);
        rdp->n_cbs_invoked += count;
+       rcu_segcblist_insert_count(&rdp->cblist, &rcl);
 
        /* Reinstate batch limit if we have worked down the excess. */
-       if (rdp->blimit == LONG_MAX && rdp->qlen <= qlowmark)
+       count = rcu_segcblist_n_cbs(&rdp->cblist);
+       if (rdp->blimit == LONG_MAX && count <= qlowmark)
                rdp->blimit = blimit;
 
        /* Reset ->qlen_last_fqs_check trigger if enough CBs have drained. */
-       if (rdp->qlen == 0 && rdp->qlen_last_fqs_check != 0) {
+       if (count == 0 && rdp->qlen_last_fqs_check != 0) {
                rdp->qlen_last_fqs_check = 0;
                rdp->n_force_qs_snap = rsp->n_force_qs;
-       } else if (rdp->qlen < rdp->qlen_last_fqs_check - qhimark)
-               rdp->qlen_last_fqs_check = rdp->qlen;
-       WARN_ON_ONCE((rdp->nxtlist == NULL) != (rdp->qlen == 0));
+       } else if (count < rdp->qlen_last_fqs_check - qhimark)
+               rdp->qlen_last_fqs_check = count;
+       WARN_ON_ONCE(rcu_segcblist_empty(&rdp->cblist) != (count == 0));
 
        local_irq_restore(flags);
 
        /* Re-invoke RCU core processing if there are callbacks remaining. */
-       if (cpu_has_callbacks_ready_to_invoke(rdp))
+       if (rcu_segcblist_ready_cbs(&rdp->cblist))
                invoke_rcu_core();
 }
 
@@ -3099,7 +3002,7 @@ __rcu_process_callbacks(struct rcu_state *rsp)
        bool needwake;
        struct rcu_data *rdp = raw_cpu_ptr(rsp->rda);
 
-       WARN_ON_ONCE(rdp->beenonline == 0);
+       WARN_ON_ONCE(!rdp->beenonline);
 
        /* Update RCU state based on any recent quiescent states. */
        rcu_check_quiescent_state(rsp, rdp);
@@ -3117,7 +3020,7 @@ __rcu_process_callbacks(struct rcu_state *rsp)
        }
 
        /* If there are callbacks ready, invoke them. */
-       if (cpu_has_callbacks_ready_to_invoke(rdp))
+       if (rcu_segcblist_ready_cbs(&rdp->cblist))
                invoke_rcu_callbacks(rsp, rdp);
 
        /* Do any needed deferred wakeups of rcuo kthreads. */
@@ -3189,7 +3092,8 @@ static void __call_rcu_core(struct rcu_state *rsp, struct rcu_data *rdp,
         * invoking force_quiescent_state() if the newly enqueued callback
         * is the only one waiting for a grace period to complete.
         */
-       if (unlikely(rdp->qlen > rdp->qlen_last_fqs_check + qhimark)) {
+       if (unlikely(rcu_segcblist_n_cbs(&rdp->cblist) >
+                    rdp->qlen_last_fqs_check + qhimark)) {
 
                /* Are we ignoring a completed grace period? */
                note_gp_changes(rsp, rdp);
@@ -3207,10 +3111,10 @@ static void __call_rcu_core(struct rcu_state *rsp, struct rcu_data *rdp,
                        /* Give the grace period a kick. */
                        rdp->blimit = LONG_MAX;
                        if (rsp->n_force_qs == rdp->n_force_qs_snap &&
-                           *rdp->nxttail[RCU_DONE_TAIL] != head)
+                           rcu_segcblist_first_pend_cb(&rdp->cblist) != head)
                                force_quiescent_state(rsp);
                        rdp->n_force_qs_snap = rsp->n_force_qs;
-                       rdp->qlen_last_fqs_check = rdp->qlen;
+                       rdp->qlen_last_fqs_check = rcu_segcblist_n_cbs(&rdp->cblist);
                }
        }
 }
@@ -3250,7 +3154,7 @@ __call_rcu(struct rcu_head *head, rcu_callback_t func,
        rdp = this_cpu_ptr(rsp->rda);
 
        /* Add the callback to our list. */
-       if (unlikely(rdp->nxttail[RCU_NEXT_TAIL] == NULL) || cpu != -1) {
+       if (unlikely(!rcu_segcblist_is_enabled(&rdp->cblist)) || cpu != -1) {
                int offline;
 
                if (cpu != -1)
@@ -3269,23 +3173,21 @@ __call_rcu(struct rcu_head *head, rcu_callback_t func,
                 */
                BUG_ON(cpu != -1);
                WARN_ON_ONCE(!rcu_is_watching());
-               if (!likely(rdp->nxtlist))
-                       init_default_callback_list(rdp);
+               if (rcu_segcblist_empty(&rdp->cblist))
+                       rcu_segcblist_init(&rdp->cblist);
        }
-       WRITE_ONCE(rdp->qlen, rdp->qlen + 1);
-       if (lazy)
-               rdp->qlen_lazy++;
-       else
+       rcu_segcblist_enqueue(&rdp->cblist, head, lazy);
+       if (!lazy)
                rcu_idle_count_callbacks_posted();
-       smp_mb();  /* Count before adding callback for rcu_barrier(). */
-       *rdp->nxttail[RCU_NEXT_TAIL] = head;
-       rdp->nxttail[RCU_NEXT_TAIL] = &head->next;
 
        if (__is_kfree_rcu_offset((unsigned long)func))
                trace_rcu_kfree_callback(rsp->name, head, (unsigned long)func,
-                                        rdp->qlen_lazy, rdp->qlen);
+                                        rcu_segcblist_n_lazy_cbs(&rdp->cblist),
+                                        rcu_segcblist_n_cbs(&rdp->cblist));
        else
-               trace_rcu_callback(rsp->name, head, rdp->qlen_lazy, rdp->qlen);
+               trace_rcu_callback(rsp->name, head,
+                                  rcu_segcblist_n_lazy_cbs(&rdp->cblist),
+                                  rcu_segcblist_n_cbs(&rdp->cblist));
 
        /* Go handle any RCU core processing required. */
        __call_rcu_core(rsp, rdp, head, flags);
@@ -3531,41 +3433,6 @@ void cond_synchronize_sched(unsigned long oldstate)
 }
 EXPORT_SYMBOL_GPL(cond_synchronize_sched);
 
-/* Adjust sequence number for start of update-side operation. */
-static void rcu_seq_start(unsigned long *sp)
-{
-       WRITE_ONCE(*sp, *sp + 1);
-       smp_mb(); /* Ensure update-side operation after counter increment. */
-       WARN_ON_ONCE(!(*sp & 0x1));
-}
-
-/* Adjust sequence number for end of update-side operation. */
-static void rcu_seq_end(unsigned long *sp)
-{
-       smp_mb(); /* Ensure update-side operation before counter increment. */
-       WRITE_ONCE(*sp, *sp + 1);
-       WARN_ON_ONCE(*sp & 0x1);
-}
-
-/* Take a snapshot of the update side's sequence number. */
-static unsigned long rcu_seq_snap(unsigned long *sp)
-{
-       unsigned long s;
-
-       s = (READ_ONCE(*sp) + 3) & ~0x1;
-       smp_mb(); /* Above access must not bleed into critical section. */
-       return s;
-}
-
-/*
- * Given a snapshot from rcu_seq_snap(), determine whether or not a
- * full update-side operation has occurred.
- */
-static bool rcu_seq_done(unsigned long *sp, unsigned long s)
-{
-       return ULONG_CMP_GE(READ_ONCE(*sp), s);
-}
-
 /*
  * Check to see if there is any immediate RCU-related work to be done
  * by the current CPU, for the specified type of RCU, returning 1 if so.
@@ -3589,7 +3456,7 @@ static int __rcu_pending(struct rcu_state *rsp, struct rcu_data *rdp)
        /* Is the RCU core waiting for a quiescent state from this CPU? */
        if (rcu_scheduler_fully_active &&
            rdp->core_needs_qs && rdp->cpu_no_qs.b.norm &&
-           rdp->rcu_qs_ctr_snap == __this_cpu_read(rcu_qs_ctr)) {
+           rdp->rcu_qs_ctr_snap == __this_cpu_read(rcu_dynticks.rcu_qs_ctr)) {
                rdp->n_rp_core_needs_qs++;
        } else if (rdp->core_needs_qs && !rdp->cpu_no_qs.b.norm) {
                rdp->n_rp_report_qs++;
@@ -3597,7 +3464,7 @@ static int __rcu_pending(struct rcu_state *rsp, struct rcu_data *rdp)
        }
 
        /* Does this CPU have callbacks ready to invoke? */
-       if (cpu_has_callbacks_ready_to_invoke(rdp)) {
+       if (rcu_segcblist_ready_cbs(&rdp->cblist)) {
                rdp->n_rp_cb_ready++;
                return 1;
        }
@@ -3661,10 +3528,10 @@ static bool __maybe_unused rcu_cpu_has_callbacks(bool *all_lazy)
 
        for_each_rcu_flavor(rsp) {
                rdp = this_cpu_ptr(rsp->rda);
-               if (!rdp->nxtlist)
+               if (rcu_segcblist_empty(&rdp->cblist))
                        continue;
                hc = true;
-               if (rdp->qlen != rdp->qlen_lazy || !all_lazy) {
+               if (rcu_segcblist_n_nonlazy_cbs(&rdp->cblist) || !all_lazy) {
                        al = false;
                        break;
                }
@@ -3773,7 +3640,7 @@ static void _rcu_barrier(struct rcu_state *rsp)
                                __call_rcu(&rdp->barrier_head,
                                           rcu_barrier_callback, rsp, cpu, 0);
                        }
-               } else if (READ_ONCE(rdp->qlen)) {
+               } else if (rcu_segcblist_n_cbs(&rdp->cblist)) {
                        _rcu_barrier_trace(rsp, "OnlineQ", cpu,
                                           rsp->barrier_sequence);
                        smp_call_function_single(cpu, rcu_barrier_func, rsp, 1);
@@ -3882,8 +3749,9 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp)
        rdp->qlen_last_fqs_check = 0;
        rdp->n_force_qs_snap = rsp->n_force_qs;
        rdp->blimit = blimit;
-       if (!rdp->nxtlist)
-               init_callback_list(rdp);  /* Re-enable callbacks on this CPU. */
+       if (rcu_segcblist_empty(&rdp->cblist) && /* No early-boot CBs? */
+           !init_nocb_callback_list(rdp))
+               rcu_segcblist_init(&rdp->cblist);  /* Re-enable callbacks. */
        rdp->dynticks->dynticks_nesting = DYNTICK_TASK_EXIT_IDLE;
        rcu_sysidle_init_percpu_data(rdp->dynticks);
        rcu_dynticks_eqs_online();
@@ -3902,12 +3770,16 @@ rcu_init_percpu_data(int cpu, struct rcu_state *rsp)
        rdp->gpnum = rnp->completed; /* Make CPU later note any new GP. */
        rdp->completed = rnp->completed;
        rdp->cpu_no_qs.b.norm = true;
-       rdp->rcu_qs_ctr_snap = per_cpu(rcu_qs_ctr, cpu);
+       rdp->rcu_qs_ctr_snap = per_cpu(rcu_dynticks.rcu_qs_ctr, cpu);
        rdp->core_needs_qs = false;
        trace_rcu_grace_period(rsp->name, rdp->gpnum, TPS("cpuonl"));
        raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
 }
 
+/*
+ * Invoked early in the CPU-online process, when pretty much all
+ * services are available.  The incoming CPU is not present.
+ */
 int rcutree_prepare_cpu(unsigned int cpu)
 {
        struct rcu_state *rsp;
@@ -3921,6 +3793,9 @@ int rcutree_prepare_cpu(unsigned int cpu)
        return 0;
 }
 
+/*
+ * Update RCU priority boot kthread affinity for CPU-hotplug changes.
+ */
 static void rcutree_affinity_setting(unsigned int cpu, int outgoing)
 {
        struct rcu_data *rdp = per_cpu_ptr(rcu_state_p->rda, cpu);
@@ -3928,20 +3803,34 @@ static void rcutree_affinity_setting(unsigned int cpu, int outgoing)
        rcu_boost_kthread_setaffinity(rdp->mynode, outgoing);
 }
 
+/*
+ * Near the end of the CPU-online process.  Pretty much all services
+ * enabled, and the CPU is now very much alive.
+ */
 int rcutree_online_cpu(unsigned int cpu)
 {
        sync_sched_exp_online_cleanup(cpu);
        rcutree_affinity_setting(cpu, -1);
+       if (IS_ENABLED(CONFIG_TREE_SRCU))
+               srcu_online_cpu(cpu);
        return 0;
 }
 
+/*
+ * Near the beginning of the process.  The CPU is still very much alive
+ * with pretty much all services enabled.
+ */
 int rcutree_offline_cpu(unsigned int cpu)
 {
        rcutree_affinity_setting(cpu, cpu);
+       if (IS_ENABLED(CONFIG_TREE_SRCU))
+               srcu_offline_cpu(cpu);
        return 0;
 }
 
-
+/*
+ * Near the end of the offline process.  We do only tracing here.
+ */
 int rcutree_dying_cpu(unsigned int cpu)
 {
        struct rcu_state *rsp;
@@ -3951,6 +3840,9 @@ int rcutree_dying_cpu(unsigned int cpu)
        return 0;
 }
 
+/*
+ * The outgoing CPU is gone and we are running elsewhere.
+ */
 int rcutree_dead_cpu(unsigned int cpu)
 {
        struct rcu_state *rsp;
@@ -3968,6 +3860,10 @@ int rcutree_dead_cpu(unsigned int cpu)
  * incoming CPUs are not allowed to use RCU read-side critical sections
  * until this function is called.  Failing to observe this restriction
  * will result in lockdep splats.
+ *
+ * Note that this function is special in that it is invoked directly
+ * from the incoming CPU rather than from the cpuhp_step mechanism.
+ * This is because this function must be invoked at a precise location.
  */
 void rcu_cpu_starting(unsigned int cpu)
 {
@@ -3990,9 +3886,6 @@ void rcu_cpu_starting(unsigned int cpu)
 
 #ifdef CONFIG_HOTPLUG_CPU
 /*
- * The CPU is exiting the idle loop into the arch_cpu_idle_dead()
- * function.  We now remove it from the rcu_node tree's ->qsmaskinit
- * bit masks.
  * The CPU is exiting the idle loop into the arch_cpu_idle_dead()
  * function.  We now remove it from the rcu_node tree's ->qsmaskinit
  * bit masks.
@@ -4011,6 +3904,14 @@ static void rcu_cleanup_dying_idle_cpu(int cpu, struct rcu_state *rsp)
        raw_spin_unlock_irqrestore_rcu_node(rnp, flags);
 }
 
+/*
+ * The outgoing function has no further need of RCU, so remove it from
+ * the list of CPUs that RCU must track.
+ *
+ * Note that this function is special in that it is invoked directly
+ * from the outgoing CPU rather than from the cpuhp_step mechanism.
+ * This is because this function must be invoked at a precise location.
+ */
 void rcu_report_dead(unsigned int cpu)
 {
        struct rcu_state *rsp;
@@ -4025,6 +3926,10 @@ void rcu_report_dead(unsigned int cpu)
 }
 #endif
 
+/*
+ * On non-huge systems, use expedited RCU grace periods to make suspend
+ * and hibernation run faster.
+ */
 static int rcu_pm_notify(struct notifier_block *self,
                         unsigned long action, void *hcpu)
 {
@@ -4095,7 +4000,7 @@ early_initcall(rcu_spawn_gp_kthread);
  * task is booting the system, and such primitives are no-ops).  After this
  * function is called, any synchronous grace-period primitives are run as
  * expedited, with the requesting task driving the grace period forward.
- * A later core_initcall() rcu_exp_runtime_mode() will switch to full
+ * A later core_initcall() rcu_set_runtime_mode() will switch to full
  * runtime RCU functionality.
  */
 void rcu_scheduler_starting(void)
@@ -4107,31 +4012,6 @@ void rcu_scheduler_starting(void)
        rcu_test_sync_prims();
 }
 
-/*
- * Compute the per-level fanout, either using the exact fanout specified
- * or balancing the tree, depending on the rcu_fanout_exact boot parameter.
- */
-static void __init rcu_init_levelspread(int *levelspread, const int *levelcnt)
-{
-       int i;
-
-       if (rcu_fanout_exact) {
-               levelspread[rcu_num_lvls - 1] = rcu_fanout_leaf;
-               for (i = rcu_num_lvls - 2; i >= 0; i--)
-                       levelspread[i] = RCU_FANOUT;
-       } else {
-               int ccur;
-               int cprv;
-
-               cprv = nr_cpu_ids;
-               for (i = rcu_num_lvls - 1; i >= 0; i--) {
-                       ccur = levelcnt[i];
-                       levelspread[i] = (cprv + ccur - 1) / ccur;
-                       cprv = ccur;
-               }
-       }
-}
-
 /*
  * Helper function for rcu_init() that initializes one rcu_state structure.
  */
@@ -4141,9 +4021,7 @@ static void __init rcu_init_one(struct rcu_state *rsp)
        static const char * const fqs[] = RCU_FQS_NAME_INIT;
        static struct lock_class_key rcu_node_class[RCU_NUM_LVLS];
        static struct lock_class_key rcu_fqs_class[RCU_NUM_LVLS];
-       static u8 fl_mask = 0x1;
 
-       int levelcnt[RCU_NUM_LVLS];             /* # nodes in each level. */
        int levelspread[RCU_NUM_LVLS];          /* kids/node in each level. */
        int cpustride = 1;
        int i;
@@ -4158,20 +4036,16 @@ static void __init rcu_init_one(struct rcu_state *rsp)
 
        /* Initialize the level-tracking arrays. */
 
-       for (i = 0; i < rcu_num_lvls; i++)
-               levelcnt[i] = num_rcu_lvl[i];
        for (i = 1; i < rcu_num_lvls; i++)
-               rsp->level[i] = rsp->level[i - 1] + levelcnt[i - 1];
-       rcu_init_levelspread(levelspread, levelcnt);
-       rsp->flavor_mask = fl_mask;
-       fl_mask <<= 1;
+               rsp->level[i] = rsp->level[i - 1] + num_rcu_lvl[i - 1];
+       rcu_init_levelspread(levelspread, num_rcu_lvl);
 
        /* Initialize the elements themselves, starting from the leaves. */
 
        for (i = rcu_num_lvls - 1; i >= 0; i--) {
                cpustride *= levelspread[i];
                rnp = rsp->level[i];
-               for (j = 0; j < levelcnt[i]; j++, rnp++) {
+               for (j = 0; j < num_rcu_lvl[i]; j++, rnp++) {
                        raw_spin_lock_init(&ACCESS_PRIVATE(rnp, lock));
                        lockdep_set_class_and_name(&ACCESS_PRIVATE(rnp, lock),
                                                   &rcu_node_class[i], buf[i]);
@@ -4344,6 +4218,8 @@ void __init rcu_init(void)
        for_each_online_cpu(cpu) {
                rcutree_prepare_cpu(cpu);
                rcu_cpu_starting(cpu);
+               if (IS_ENABLED(CONFIG_TREE_SRCU))
+                       srcu_online_cpu(cpu);
        }
 }
 
index ec62a05bfdb3c81b9a82593de2aeefffb96bf300..ba38262c3554495c59b0aacba52ba245ba108d53 100644 (file)
 #include <linux/seqlock.h>
 #include <linux/swait.h>
 #include <linux/stop_machine.h>
+#include <linux/rcu_node_tree.h>
 
-/*
- * Define shape of hierarchy based on NR_CPUS, CONFIG_RCU_FANOUT, and
- * CONFIG_RCU_FANOUT_LEAF.
- * In theory, it should be possible to add more levels straightforwardly.
- * In practice, this did work well going from three levels to four.
- * Of course, your mileage may vary.
- */
-
-#ifdef CONFIG_RCU_FANOUT
-#define RCU_FANOUT CONFIG_RCU_FANOUT
-#else /* #ifdef CONFIG_RCU_FANOUT */
-# ifdef CONFIG_64BIT
-# define RCU_FANOUT 64
-# else
-# define RCU_FANOUT 32
-# endif
-#endif /* #else #ifdef CONFIG_RCU_FANOUT */
-
-#ifdef CONFIG_RCU_FANOUT_LEAF
-#define RCU_FANOUT_LEAF CONFIG_RCU_FANOUT_LEAF
-#else /* #ifdef CONFIG_RCU_FANOUT_LEAF */
-# ifdef CONFIG_64BIT
-# define RCU_FANOUT_LEAF 64
-# else
-# define RCU_FANOUT_LEAF 32
-# endif
-#endif /* #else #ifdef CONFIG_RCU_FANOUT_LEAF */
-
-#define RCU_FANOUT_1         (RCU_FANOUT_LEAF)
-#define RCU_FANOUT_2         (RCU_FANOUT_1 * RCU_FANOUT)
-#define RCU_FANOUT_3         (RCU_FANOUT_2 * RCU_FANOUT)
-#define RCU_FANOUT_4         (RCU_FANOUT_3 * RCU_FANOUT)
-
-#if NR_CPUS <= RCU_FANOUT_1
-#  define RCU_NUM_LVLS       1
-#  define NUM_RCU_LVL_0              1
-#  define NUM_RCU_NODES              NUM_RCU_LVL_0
-#  define NUM_RCU_LVL_INIT    { NUM_RCU_LVL_0 }
-#  define RCU_NODE_NAME_INIT  { "rcu_node_0" }
-#  define RCU_FQS_NAME_INIT   { "rcu_node_fqs_0" }
-#elif NR_CPUS <= RCU_FANOUT_2
-#  define RCU_NUM_LVLS       2
-#  define NUM_RCU_LVL_0              1
-#  define NUM_RCU_LVL_1              DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_1)
-#  define NUM_RCU_NODES              (NUM_RCU_LVL_0 + NUM_RCU_LVL_1)
-#  define NUM_RCU_LVL_INIT    { NUM_RCU_LVL_0, NUM_RCU_LVL_1 }
-#  define RCU_NODE_NAME_INIT  { "rcu_node_0", "rcu_node_1" }
-#  define RCU_FQS_NAME_INIT   { "rcu_node_fqs_0", "rcu_node_fqs_1" }
-#elif NR_CPUS <= RCU_FANOUT_3
-#  define RCU_NUM_LVLS       3
-#  define NUM_RCU_LVL_0              1
-#  define NUM_RCU_LVL_1              DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_2)
-#  define NUM_RCU_LVL_2              DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_1)
-#  define NUM_RCU_NODES              (NUM_RCU_LVL_0 + NUM_RCU_LVL_1 + NUM_RCU_LVL_2)
-#  define NUM_RCU_LVL_INIT    { NUM_RCU_LVL_0, NUM_RCU_LVL_1, NUM_RCU_LVL_2 }
-#  define RCU_NODE_NAME_INIT  { "rcu_node_0", "rcu_node_1", "rcu_node_2" }
-#  define RCU_FQS_NAME_INIT   { "rcu_node_fqs_0", "rcu_node_fqs_1", "rcu_node_fqs_2" }
-#elif NR_CPUS <= RCU_FANOUT_4
-#  define RCU_NUM_LVLS       4
-#  define NUM_RCU_LVL_0              1
-#  define NUM_RCU_LVL_1              DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_3)
-#  define NUM_RCU_LVL_2              DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_2)
-#  define NUM_RCU_LVL_3              DIV_ROUND_UP(NR_CPUS, RCU_FANOUT_1)
-#  define NUM_RCU_NODES              (NUM_RCU_LVL_0 + NUM_RCU_LVL_1 + NUM_RCU_LVL_2 + NUM_RCU_LVL_3)
-#  define NUM_RCU_LVL_INIT    { NUM_RCU_LVL_0, NUM_RCU_LVL_1, NUM_RCU_LVL_2, NUM_RCU_LVL_3 }
-#  define RCU_NODE_NAME_INIT  { "rcu_node_0", "rcu_node_1", "rcu_node_2", "rcu_node_3" }
-#  define RCU_FQS_NAME_INIT   { "rcu_node_fqs_0", "rcu_node_fqs_1", "rcu_node_fqs_2", "rcu_node_fqs_3" }
-#else
-# error "CONFIG_RCU_FANOUT insufficient for NR_CPUS"
-#endif /* #if (NR_CPUS) <= RCU_FANOUT_1 */
-
-extern int rcu_num_lvls;
-extern int rcu_num_nodes;
+#include "rcu_segcblist.h"
 
 /*
  * Dynticks per-CPU state.
@@ -113,6 +42,9 @@ struct rcu_dynticks {
                                    /* Process level is worth LLONG_MAX/2. */
        int dynticks_nmi_nesting;   /* Track NMI nesting level. */
        atomic_t dynticks;          /* Even value for idle, else odd. */
+       bool rcu_need_heavy_qs;     /* GP old, need heavy quiescent state. */
+       unsigned long rcu_qs_ctr;   /* Light universal quiescent state ctr. */
+       bool rcu_urgent_qs;         /* GP old need light quiescent state. */
 #ifdef CONFIG_NO_HZ_FULL_SYSIDLE
        long long dynticks_idle_nesting;
                                    /* irq/process nesting level from idle. */
@@ -261,41 +193,6 @@ struct rcu_node {
  */
 #define leaf_node_cpu_bit(rnp, cpu) (1UL << ((cpu) - (rnp)->grplo))
 
-/*
- * Do a full breadth-first scan of the rcu_node structures for the
- * specified rcu_state structure.
- */
-#define rcu_for_each_node_breadth_first(rsp, rnp) \
-       for ((rnp) = &(rsp)->node[0]; \
-            (rnp) < &(rsp)->node[rcu_num_nodes]; (rnp)++)
-
-/*
- * Do a breadth-first scan of the non-leaf rcu_node structures for the
- * specified rcu_state structure.  Note that if there is a singleton
- * rcu_node tree with but one rcu_node structure, this loop is a no-op.
- */
-#define rcu_for_each_nonleaf_node_breadth_first(rsp, rnp) \
-       for ((rnp) = &(rsp)->node[0]; \
-            (rnp) < (rsp)->level[rcu_num_lvls - 1]; (rnp)++)
-
-/*
- * Scan the leaves of the rcu_node hierarchy for the specified rcu_state
- * structure.  Note that if there is a singleton rcu_node tree with but
- * one rcu_node structure, this loop -will- visit the rcu_node structure.
- * It is still a leaf node, even if it is also the root node.
- */
-#define rcu_for_each_leaf_node(rsp, rnp) \
-       for ((rnp) = (rsp)->level[rcu_num_lvls - 1]; \
-            (rnp) < &(rsp)->node[rcu_num_nodes]; (rnp)++)
-
-/*
- * Iterate over all possible CPUs in a leaf RCU node.
- */
-#define for_each_leaf_node_possible_cpu(rnp, cpu) \
-       for ((cpu) = cpumask_next(rnp->grplo - 1, cpu_possible_mask); \
-            cpu <= rnp->grphi; \
-            cpu = cpumask_next((cpu), cpu_possible_mask))
-
 /*
  * Union to allow "aggregate OR" operation on the need for a quiescent
  * state by the normal and expedited grace periods.
@@ -336,34 +233,9 @@ struct rcu_data {
                                        /* period it is aware of. */
 
        /* 2) batch handling */
-       /*
-        * If nxtlist is not NULL, it is partitioned as follows.
-        * Any of the partitions might be empty, in which case the
-        * pointer to that partition will be equal to the pointer for
-        * the following partition.  When the list is empty, all of
-        * the nxttail elements point to the ->nxtlist pointer itself,
-        * which in that case is NULL.
-        *
-        * [nxtlist, *nxttail[RCU_DONE_TAIL]):
-        *      Entries that batch # <= ->completed
-        *      The grace period for these entries has completed, and
-        *      the other grace-period-completed entries may be moved
-        *      here temporarily in rcu_process_callbacks().
-        * [*nxttail[RCU_DONE_TAIL], *nxttail[RCU_WAIT_TAIL]):
-        *      Entries that batch # <= ->completed - 1: waiting for current GP
-        * [*nxttail[RCU_WAIT_TAIL], *nxttail[RCU_NEXT_READY_TAIL]):
-        *      Entries known to have arrived before current GP ended
-        * [*nxttail[RCU_NEXT_READY_TAIL], *nxttail[RCU_NEXT_TAIL]):
-        *      Entries that might have arrived after current GP ended
-        *      Note that the value of *nxttail[RCU_NEXT_TAIL] will
-        *      always be NULL, as this is the end of the list.
-        */
-       struct rcu_head *nxtlist;
-       struct rcu_head **nxttail[RCU_NEXT_SIZE];
-       unsigned long   nxtcompleted[RCU_NEXT_SIZE];
-                                       /* grace periods for sublists. */
-       long            qlen_lazy;      /* # of lazy queued callbacks */
-       long            qlen;           /* # of queued callbacks, incl lazy */
+       struct rcu_segcblist cblist;    /* Segmented callback list, with */
+                                       /* different callbacks waiting for */
+                                       /* different grace periods. */
        long            qlen_last_fqs_check;
                                        /* qlen at last check for QS forcing */
        unsigned long   n_cbs_invoked;  /* count of RCU cbs invoked. */
@@ -482,7 +354,6 @@ struct rcu_state {
        struct rcu_node *level[RCU_NUM_LVLS + 1];
                                                /* Hierarchy levels (+1 to */
                                                /*  shut bogus gcc warning) */
-       u8 flavor_mask;                         /* bit in flavor mask. */
        struct rcu_data __percpu *rda;          /* pointer of percu rcu_data. */
        call_rcu_func_t call;                   /* call_rcu() flavor. */
        int ncpus;                              /* # CPUs seen so far. */
@@ -502,14 +373,11 @@ struct rcu_state {
 
        raw_spinlock_t orphan_lock ____cacheline_internodealigned_in_smp;
                                                /* Protect following fields. */
-       struct rcu_head *orphan_nxtlist;        /* Orphaned callbacks that */
+       struct rcu_cblist orphan_pend;          /* Orphaned callbacks that */
                                                /*  need a grace period. */
-       struct rcu_head **orphan_nxttail;       /* Tail of above. */
-       struct rcu_head *orphan_donelist;       /* Orphaned callbacks that */
+       struct rcu_cblist orphan_done;          /* Orphaned callbacks that */
                                                /*  are ready to invoke. */
-       struct rcu_head **orphan_donetail;      /* Tail of above. */
-       long qlen_lazy;                         /* Number of lazy callbacks. */
-       long qlen;                              /* Total number of callbacks. */
+                                               /* (Contains counts.) */
        /* End of fields guarded by orphan_lock. */
 
        struct mutex barrier_mutex;             /* Guards barrier fields. */
@@ -596,6 +464,7 @@ extern struct rcu_state rcu_preempt_state;
 #endif /* #ifdef CONFIG_PREEMPT_RCU */
 
 int rcu_dynticks_snap(struct rcu_dynticks *rdtp);
+bool rcu_eqs_special_set(int cpu);
 
 #ifdef CONFIG_RCU_BOOST
 DECLARE_PER_CPU(unsigned int, rcu_cpu_kthread_status);
@@ -673,6 +542,14 @@ static bool rcu_nohz_full_cpu(struct rcu_state *rsp);
 static void rcu_dynticks_task_enter(void);
 static void rcu_dynticks_task_exit(void);
 
+#ifdef CONFIG_SRCU
+void srcu_online_cpu(unsigned int cpu);
+void srcu_offline_cpu(unsigned int cpu);
+#else /* #ifdef CONFIG_SRCU */
+void srcu_online_cpu(unsigned int cpu) { }
+void srcu_offline_cpu(unsigned int cpu) { }
+#endif /* #else #ifdef CONFIG_SRCU */
+
 #endif /* #ifndef RCU_TREE_NONCORE */
 
 #ifdef CONFIG_RCU_TRACE
index a7b639ccd46e0ade81946639ef1d50bdc2b68d21..e513b4ab119769488419eba9bff7601f1d556182 100644 (file)
@@ -292,7 +292,7 @@ static bool exp_funnel_lock(struct rcu_state *rsp, unsigned long s)
                        trace_rcu_exp_funnel_lock(rsp->name, rnp->level,
                                                  rnp->grplo, rnp->grphi,
                                                  TPS("wait"));
-                       wait_event(rnp->exp_wq[(s >> 1) & 0x3],
+                       wait_event(rnp->exp_wq[rcu_seq_ctr(s) & 0x3],
                                   sync_exp_work_done(rsp,
                                                      &rdp->exp_workdone2, s));
                        return true;
@@ -331,6 +331,8 @@ static void sync_sched_exp_handler(void *data)
                return;
        }
        __this_cpu_write(rcu_sched_data.cpu_no_qs.b.exp, true);
+       /* Store .exp before .rcu_urgent_qs. */
+       smp_store_release(this_cpu_ptr(&rcu_dynticks.rcu_urgent_qs), true);
        resched_cpu(smp_processor_id());
 }
 
@@ -531,7 +533,8 @@ static void rcu_exp_wait_wake(struct rcu_state *rsp, unsigned long s)
                                rnp->exp_seq_rq = s;
                        spin_unlock(&rnp->exp_lock);
                }
-               wake_up_all(&rnp->exp_wq[(rsp->expedited_sequence >> 1) & 0x3]);
+               smp_mb(); /* All above changes before wakeup. */
+               wake_up_all(&rnp->exp_wq[rcu_seq_ctr(rsp->expedited_sequence) & 0x3]);
        }
        trace_rcu_exp_grace_period(rsp->name, s, TPS("endwake"));
        mutex_unlock(&rsp->exp_wake_mutex);
@@ -609,9 +612,9 @@ static void _synchronize_rcu_expedited(struct rcu_state *rsp,
        /* Wait for expedited grace period to complete. */
        rdp = per_cpu_ptr(rsp->rda, raw_smp_processor_id());
        rnp = rcu_get_root(rsp);
-       wait_event(rnp->exp_wq[(s >> 1) & 0x3],
-                  sync_exp_work_done(rsp,
-                                     &rdp->exp_workdone0, s));
+       wait_event(rnp->exp_wq[rcu_seq_ctr(s) & 0x3],
+                  sync_exp_work_done(rsp, &rdp->exp_workdone0, s));
+       smp_mb(); /* Workqueue actions happen before return. */
 
        /* Let the next expedited grace period start. */
        mutex_unlock(&rsp->exp_mutex);
@@ -735,15 +738,3 @@ void synchronize_rcu_expedited(void)
 EXPORT_SYMBOL_GPL(synchronize_rcu_expedited);
 
 #endif /* #else #ifdef CONFIG_PREEMPT_RCU */
-
-/*
- * Switch to run-time mode once Tree RCU has fully initialized.
- */
-static int __init rcu_exp_runtime_mode(void)
-{
-       rcu_test_sync_prims();
-       rcu_scheduler_active = RCU_SCHEDULER_RUNNING;
-       rcu_test_sync_prims();
-       return 0;
-}
-core_initcall(rcu_exp_runtime_mode);
index 0a62a8f1caacfab8a2a39c729f70e445f8048cbf..c9a48657512ae35a833d6cc1c56ff9687a899b17 100644 (file)
@@ -1350,10 +1350,10 @@ static bool __maybe_unused rcu_try_advance_all_cbs(void)
                 */
                if ((rdp->completed != rnp->completed ||
                     unlikely(READ_ONCE(rdp->gpwrap))) &&
-                   rdp->nxttail[RCU_DONE_TAIL] != rdp->nxttail[RCU_NEXT_TAIL])
+                   rcu_segcblist_pend_cbs(&rdp->cblist))
                        note_gp_changes(rsp, rdp);
 
-               if (cpu_has_callbacks_ready_to_invoke(rdp))
+               if (rcu_segcblist_ready_cbs(&rdp->cblist))
                        cbs_ready = true;
        }
        return cbs_ready;
@@ -1461,7 +1461,7 @@ static void rcu_prepare_for_idle(void)
        rdtp->last_accelerate = jiffies;
        for_each_rcu_flavor(rsp) {
                rdp = this_cpu_ptr(rsp->rda);
-               if (!*rdp->nxttail[RCU_DONE_TAIL])
+               if (rcu_segcblist_pend_cbs(&rdp->cblist))
                        continue;
                rnp = rdp->mynode;
                raw_spin_lock_rcu_node(rnp); /* irqs already disabled. */
@@ -1529,7 +1529,7 @@ static void rcu_oom_notify_cpu(void *unused)
 
        for_each_rcu_flavor(rsp) {
                rdp = raw_cpu_ptr(rsp->rda);
-               if (rdp->qlen_lazy != 0) {
+               if (rcu_segcblist_n_lazy_cbs(&rdp->cblist)) {
                        atomic_inc(&oom_callback_count);
                        rsp->call(&rdp->oom_head, rcu_oom_callback);
                }
@@ -1709,7 +1709,7 @@ __setup("rcu_nocbs=", rcu_nocb_setup);
 
 static int __init parse_rcu_nocb_poll(char *arg)
 {
-       rcu_nocb_poll = 1;
+       rcu_nocb_poll = true;
        return 0;
 }
 early_param("rcu_nocb_poll", parse_rcu_nocb_poll);
@@ -1860,7 +1860,9 @@ static void __call_rcu_nocb_enqueue(struct rcu_data *rdp,
                        trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu,
                                            TPS("WakeEmpty"));
                } else {
-                       rdp->nocb_defer_wakeup = RCU_NOGP_WAKE;
+                       WRITE_ONCE(rdp->nocb_defer_wakeup, RCU_NOGP_WAKE);
+                       /* Store ->nocb_defer_wakeup before ->rcu_urgent_qs. */
+                       smp_store_release(this_cpu_ptr(&rcu_dynticks.rcu_urgent_qs), true);
                        trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu,
                                            TPS("WakeEmptyIsDeferred"));
                }
@@ -1872,7 +1874,9 @@ static void __call_rcu_nocb_enqueue(struct rcu_data *rdp,
                        trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu,
                                            TPS("WakeOvf"));
                } else {
-                       rdp->nocb_defer_wakeup = RCU_NOGP_WAKE_FORCE;
+                       WRITE_ONCE(rdp->nocb_defer_wakeup, RCU_NOGP_WAKE_FORCE);
+                       /* Store ->nocb_defer_wakeup before ->rcu_urgent_qs. */
+                       smp_store_release(this_cpu_ptr(&rcu_dynticks.rcu_urgent_qs), true);
                        trace_rcu_nocb_wake(rdp->rsp->name, rdp->cpu,
                                            TPS("WakeOvfIsDeferred"));
                }
@@ -1930,30 +1934,26 @@ static bool __maybe_unused rcu_nocb_adopt_orphan_cbs(struct rcu_state *rsp,
                                                     struct rcu_data *rdp,
                                                     unsigned long flags)
 {
-       long ql = rsp->qlen;
-       long qll = rsp->qlen_lazy;
+       long ql = rsp->orphan_done.len;
+       long qll = rsp->orphan_done.len_lazy;
 
        /* If this is not a no-CBs CPU, tell the caller to do it the old way. */
        if (!rcu_is_nocb_cpu(smp_processor_id()))
                return false;
-       rsp->qlen = 0;
-       rsp->qlen_lazy = 0;
 
        /* First, enqueue the donelist, if any.  This preserves CB ordering. */
-       if (rsp->orphan_donelist != NULL) {
-               __call_rcu_nocb_enqueue(rdp, rsp->orphan_donelist,
-                                       rsp->orphan_donetail, ql, qll, flags);
-               ql = qll = 0;
-               rsp->orphan_donelist = NULL;
-               rsp->orphan_donetail = &rsp->orphan_donelist;
+       if (rsp->orphan_done.head) {
+               __call_rcu_nocb_enqueue(rdp, rcu_cblist_head(&rsp->orphan_done),
+                                       rcu_cblist_tail(&rsp->orphan_done),
+                                       ql, qll, flags);
        }
-       if (rsp->orphan_nxtlist != NULL) {
-               __call_rcu_nocb_enqueue(rdp, rsp->orphan_nxtlist,
-                                       rsp->orphan_nxttail, ql, qll, flags);
-               ql = qll = 0;
-               rsp->orphan_nxtlist = NULL;
-               rsp->orphan_nxttail = &rsp->orphan_nxtlist;
+       if (rsp->orphan_pend.head) {
+               __call_rcu_nocb_enqueue(rdp, rcu_cblist_head(&rsp->orphan_pend),
+                                       rcu_cblist_tail(&rsp->orphan_pend),
+                                       ql, qll, flags);
        }
+       rcu_cblist_init(&rsp->orphan_done);
+       rcu_cblist_init(&rsp->orphan_pend);
        return true;
 }
 
@@ -2395,16 +2395,16 @@ static bool init_nocb_callback_list(struct rcu_data *rdp)
                return false;
 
        /* If there are early-boot callbacks, move them to nocb lists. */
-       if (rdp->nxtlist) {
-               rdp->nocb_head = rdp->nxtlist;
-               rdp->nocb_tail = rdp->nxttail[RCU_NEXT_TAIL];
-               atomic_long_set(&rdp->nocb_q_count, rdp->qlen);
-               atomic_long_set(&rdp->nocb_q_count_lazy, rdp->qlen_lazy);
-               rdp->nxtlist = NULL;
-               rdp->qlen = 0;
-               rdp->qlen_lazy = 0;
+       if (!rcu_segcblist_empty(&rdp->cblist)) {
+               rdp->nocb_head = rcu_segcblist_head(&rdp->cblist);
+               rdp->nocb_tail = rcu_segcblist_tail(&rdp->cblist);
+               atomic_long_set(&rdp->nocb_q_count,
+                               rcu_segcblist_n_cbs(&rdp->cblist));
+               atomic_long_set(&rdp->nocb_q_count_lazy,
+                               rcu_segcblist_n_lazy_cbs(&rdp->cblist));
+               rcu_segcblist_init(&rdp->cblist);
        }
-       rdp->nxttail[RCU_NEXT_TAIL] = NULL;
+       rcu_segcblist_disable(&rdp->cblist);
        return true;
 }
 
index 8751a748499a3d3a93419fe5273bbf4876aa2149..6cea17a1ea301f23180126504acf9d84d27e16f6 100644 (file)
 #include <linux/mutex.h>
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
+#include <linux/prefetch.h>
 
 #define RCU_TREE_NONCORE
 #include "tree.h"
-
-DECLARE_PER_CPU_SHARED_ALIGNED(unsigned long, rcu_qs_ctr);
+#include "rcu.h"
 
 static int r_open(struct inode *inode, struct file *file,
                                        const struct seq_operations *op)
@@ -121,7 +121,7 @@ static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp)
                   cpu_is_offline(rdp->cpu) ? '!' : ' ',
                   ulong2long(rdp->completed), ulong2long(rdp->gpnum),
                   rdp->cpu_no_qs.b.norm,
-                  rdp->rcu_qs_ctr_snap == per_cpu(rcu_qs_ctr, rdp->cpu),
+                  rdp->rcu_qs_ctr_snap == per_cpu(rdp->dynticks->rcu_qs_ctr, rdp->cpu),
                   rdp->core_needs_qs);
        seq_printf(m, " dt=%d/%llx/%d df=%lu",
                   rcu_dynticks_snap(rdp->dynticks),
@@ -130,17 +130,15 @@ static void print_one_rcu_data(struct seq_file *m, struct rcu_data *rdp)
                   rdp->dynticks_fqs);
        seq_printf(m, " of=%lu", rdp->offline_fqs);
        rcu_nocb_q_lengths(rdp, &ql, &qll);
-       qll += rdp->qlen_lazy;
-       ql += rdp->qlen;
+       qll += rcu_segcblist_n_lazy_cbs(&rdp->cblist);
+       ql += rcu_segcblist_n_cbs(&rdp->cblist);
        seq_printf(m, " ql=%ld/%ld qs=%c%c%c%c",
                   qll, ql,
-                  ".N"[rdp->nxttail[RCU_NEXT_READY_TAIL] !=
-                       rdp->nxttail[RCU_NEXT_TAIL]],
-                  ".R"[rdp->nxttail[RCU_WAIT_TAIL] !=
-                       rdp->nxttail[RCU_NEXT_READY_TAIL]],
-                  ".W"[rdp->nxttail[RCU_DONE_TAIL] !=
-                       rdp->nxttail[RCU_WAIT_TAIL]],
-                  ".D"[&rdp->nxtlist != rdp->nxttail[RCU_DONE_TAIL]]);
+                  ".N"[!rcu_segcblist_segempty(&rdp->cblist, RCU_NEXT_TAIL)],
+                  ".R"[!rcu_segcblist_segempty(&rdp->cblist,
+                                               RCU_NEXT_READY_TAIL)],
+                  ".W"[!rcu_segcblist_segempty(&rdp->cblist, RCU_WAIT_TAIL)],
+                  ".D"[!rcu_segcblist_segempty(&rdp->cblist, RCU_DONE_TAIL)]);
 #ifdef CONFIG_RCU_BOOST
        seq_printf(m, " kt=%d/%c ktl=%x",
                   per_cpu(rcu_cpu_has_work, rdp->cpu),
@@ -278,7 +276,9 @@ static void print_one_rcu_state(struct seq_file *m, struct rcu_state *rsp)
        seq_printf(m, "nfqs=%lu/nfqsng=%lu(%lu) fqlh=%lu oqlen=%ld/%ld\n",
                   rsp->n_force_qs, rsp->n_force_qs_ngp,
                   rsp->n_force_qs - rsp->n_force_qs_ngp,
-                  READ_ONCE(rsp->n_force_qs_lh), rsp->qlen_lazy, rsp->qlen);
+                  READ_ONCE(rsp->n_force_qs_lh),
+                  rsp->orphan_done.len_lazy,
+                  rsp->orphan_done.len);
        for (rnp = &rsp->node[0]; rnp - &rsp->node[0] < rcu_num_nodes; rnp++) {
                if (rnp->level != level) {
                        seq_puts(m, "\n");
index 55c8530316c7ce6077df9814cc4c7997f7282486..273e869ca21d546b5457987bd676f70c08bba5f3 100644 (file)
@@ -124,7 +124,7 @@ EXPORT_SYMBOL(rcu_read_lock_sched_held);
  * non-expedited counterparts?  Intended for use within RCU.  Note
  * that if the user specifies both rcu_expedited and rcu_normal, then
  * rcu_normal wins.  (Except during the time period during boot from
- * when the first task is spawned until the rcu_exp_runtime_mode()
+ * when the first task is spawned until the rcu_set_runtime_mode()
  * core_initcall() is invoked, at which point everything is expedited.)
  */
 bool rcu_gp_is_normal(void)
@@ -190,6 +190,39 @@ void rcu_end_inkernel_boot(void)
 
 #endif /* #ifndef CONFIG_TINY_RCU */
 
+/*
+ * Test each non-SRCU synchronous grace-period wait API.  This is
+ * useful just after a change in mode for these primitives, and
+ * during early boot.
+ */
+void rcu_test_sync_prims(void)
+{
+       if (!IS_ENABLED(CONFIG_PROVE_RCU))
+               return;
+       synchronize_rcu();
+       synchronize_rcu_bh();
+       synchronize_sched();
+       synchronize_rcu_expedited();
+       synchronize_rcu_bh_expedited();
+       synchronize_sched_expedited();
+}
+
+#if !defined(CONFIG_TINY_RCU) || defined(CONFIG_SRCU)
+
+/*
+ * Switch to run-time mode once RCU has fully initialized.
+ */
+static int __init rcu_set_runtime_mode(void)
+{
+       rcu_test_sync_prims();
+       rcu_scheduler_active = RCU_SCHEDULER_RUNNING;
+       rcu_test_sync_prims();
+       return 0;
+}
+core_initcall(rcu_set_runtime_mode);
+
+#endif /* #if !defined(CONFIG_TINY_RCU) || defined(CONFIG_SRCU) */
+
 #ifdef CONFIG_PREEMPT_RCU
 
 /*
@@ -632,6 +665,7 @@ static void check_holdout_task(struct task_struct *t,
                put_task_struct(t);
                return;
        }
+       rcu_request_urgent_qs_task(t);
        if (!needreport)
                return;
        if (*firstreport) {
@@ -817,23 +851,6 @@ static void rcu_spawn_tasks_kthread(void)
 
 #endif /* #ifdef CONFIG_TASKS_RCU */
 
-/*
- * Test each non-SRCU synchronous grace-period wait API.  This is
- * useful just after a change in mode for these primitives, and
- * during early boot.
- */
-void rcu_test_sync_prims(void)
-{
-       if (!IS_ENABLED(CONFIG_PROVE_RCU))
-               return;
-       synchronize_rcu();
-       synchronize_rcu_bh();
-       synchronize_sched();
-       synchronize_rcu_expedited();
-       synchronize_rcu_bh_expedited();
-       synchronize_sched_expedited();
-}
-
 #ifdef CONFIG_PROVE_RCU
 
 /*
index c51147a1204c841fcae7f43aa3ad8d98dda9bcb0..759f4bd52cd6b3724b858d41f57ff305a3747c8b 100644 (file)
@@ -3382,7 +3382,7 @@ static void __sched notrace __schedule(bool preempt)
                hrtick_clear(rq);
 
        local_irq_disable();
-       rcu_note_context_switch();
+       rcu_note_context_switch(preempt);
 
        /*
         * Make sure that signal_pending_state()->signal_pending() below
index a8c54f384553e9a588399cc0db51a7eaef76e733..ca92bcfeb322f3f836031ec8b3ab21867f39adf5 100644 (file)
@@ -1237,7 +1237,7 @@ struct sighand_struct *__lock_task_sighand(struct task_struct *tsk,
                }
                /*
                 * This sighand can be already freed and even reused, but
-                * we rely on SLAB_DESTROY_BY_RCU and sighand_ctor() which
+                * we rely on SLAB_TYPESAFE_BY_RCU and sighand_ctor() which
                 * initializes ->siglock: this slab can't go away, it has
                 * the same object type, ->siglock can't be reinitialized.
                 *
index 21343d1102963485eb9d706012be8d4cc5752edf..4dfba1a76cc360f649cbe6f35b57cf9413f2f5e1 100644 (file)
@@ -2576,7 +2576,7 @@ static int do_proc_dointvec_jiffies_conv(bool *negp, unsigned long *lvalp,
                                         int write, void *data)
 {
        if (write) {
-               if (*lvalp > LONG_MAX / HZ)
+               if (*lvalp > INT_MAX / HZ)
                        return 1;
                *valp = *negp ? -(*lvalp*HZ) : (*lvalp*HZ);
        } else {
index 8a5e44236f78d3ba069e0c81ef3304f4be5ba7fd..4559e914452b4b8a47d1cf2efc0320be253e5025 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/pid_namespace.h>
 #include <net/genetlink.h>
 #include <linux/atomic.h>
+#include <linux/sched/cputime.h>
 
 /*
  * Maximum length of a cpumask that can be specified in
@@ -210,6 +211,8 @@ static int fill_stats_for_tgid(pid_t tgid, struct taskstats *stats)
        struct task_struct *tsk, *first;
        unsigned long flags;
        int rc = -ESRCH;
+       u64 delta, utime, stime;
+       u64 start_time;
 
        /*
         * Add additional stats from live tasks except zombie thread group
@@ -227,6 +230,7 @@ static int fill_stats_for_tgid(pid_t tgid, struct taskstats *stats)
                memset(stats, 0, sizeof(*stats));
 
        tsk = first;
+       start_time = ktime_get_ns();
        do {
                if (tsk->exit_state)
                        continue;
@@ -238,6 +242,16 @@ static int fill_stats_for_tgid(pid_t tgid, struct taskstats *stats)
                 */
                delayacct_add_tsk(stats, tsk);
 
+               /* calculate task elapsed time in nsec */
+               delta = start_time - tsk->start_time;
+               /* Convert to micro seconds */
+               do_div(delta, NSEC_PER_USEC);
+               stats->ac_etime += delta;
+
+               task_cputime(tsk, &utime, &stime);
+               stats->ac_utime += div_u64(utime, NSEC_PER_USEC);
+               stats->ac_stime += div_u64(stime, NSEC_PER_USEC);
+
                stats->nvcsw += tsk->nvcsw;
                stats->nivcsw += tsk->nivcsw;
        } while_each_thread(first, tsk);
index 6574bba44b55a2917d37e683c312bf10842f88cb..49c73c6ed648900d873190f9ebaefe9cb44f4f98 100644 (file)
@@ -230,20 +230,6 @@ SYSCALL_DEFINE1(adjtimex, struct timex __user *, txc_p)
        return copy_to_user(txc_p, &txc, sizeof(struct timex)) ? -EFAULT : ret;
 }
 
-/**
- * current_fs_time - Return FS time
- * @sb: Superblock.
- *
- * Return the current time truncated to the time granularity supported by
- * the fs.
- */
-struct timespec current_fs_time(struct super_block *sb)
-{
-       struct timespec now = current_kernel_time();
-       return timespec_trunc(now, sb->s_time_gran);
-}
-EXPORT_SYMBOL(current_fs_time);
-
 /*
  * Convert jiffies to milliseconds and back.
  *
index 00077a57b7468660f8629b915fcb0fcf17966d26..39dca4e86a94f0867c29aaa29b47d881eefd02e8 100644 (file)
@@ -3631,22 +3631,20 @@ ftrace_match_record(struct dyn_ftrace *rec, struct ftrace_glob *func_g,
                /* blank module name to match all modules */
                if (!mod_g->len) {
                        /* blank module globbing: modname xor exclude_mod */
-                       if ((!exclude_mod) != (!modname))
+                       if (!exclude_mod != !modname)
                                goto func_match;
                        return 0;
                }
 
-               /* not matching the module */
-               if (!modname || !mod_matches) {
-                       if (exclude_mod)
-                               goto func_match;
-                       else
-                               return 0;
-               }
-
-               if (mod_matches && exclude_mod)
+               /*
+                * exclude_mod is set to trace everything but the given
+                * module. If it is set and the module matches, then
+                * return 0. If it is not set, and the module doesn't match
+                * also return 0. Otherwise, check the function to see if
+                * that matches.
+                */
+               if (!mod_matches == !exclude_mod)
                        return 0;
-
 func_match:
                /* blank search means to match all funcs in the mod */
                if (!func_g->len)
index 80eda7d254ed99640efcc90956692cfebf8eaafa..c4536c4490217a2e6b59e423c70c0f1836a34a9d 100644 (file)
@@ -1976,7 +1976,7 @@ static void __trace_find_cmdline(int pid, char comm[])
 
        map = savedcmd->map_pid_to_cmdline[pid];
        if (map != NO_CMDLINE_MAP)
-               strcpy(comm, get_saved_cmdlines(map));
+               strlcpy(comm, get_saved_cmdlines(map), TASK_COMM_LEN);
        else
                strcpy(comm, "<...>");
 }
@@ -3311,13 +3311,14 @@ static void test_cpu_buff_start(struct trace_iterator *iter)
        if (!(iter->iter_flags & TRACE_FILE_ANNOTATE))
                return;
 
-       if (iter->started && cpumask_test_cpu(iter->cpu, iter->started))
+       if (cpumask_available(iter->started) &&
+           cpumask_test_cpu(iter->cpu, iter->started))
                return;
 
        if (per_cpu_ptr(iter->trace_buffer->data, iter->cpu)->skipped_entries)
                return;
 
-       if (iter->started)
+       if (cpumask_available(iter->started))
                cpumask_set_cpu(iter->cpu, iter->started);
 
        /* Don't print started cpu buffer for the first entry of the trace */
index c203ac4df791f28e074d387ce573cec74bc40cf6..adcdbbeae0108bad436d0af31297dc555ad7f545 100644 (file)
@@ -348,14 +348,14 @@ FTRACE_ENTRY(hwlat, hwlat_entry,
                __field(        u64,                    duration        )
                __field(        u64,                    outer_duration  )
                __field(        u64,                    nmi_total_ts    )
-               __field_struct( struct timespec,        timestamp       )
-               __field_desc(   long,   timestamp,      tv_sec          )
+               __field_struct( struct timespec64,      timestamp       )
+               __field_desc(   s64,    timestamp,      tv_sec          )
                __field_desc(   long,   timestamp,      tv_nsec         )
                __field(        unsigned int,           nmi_count       )
                __field(        unsigned int,           seqnum          )
        ),
 
-       F_printk("cnt:%u\tts:%010lu.%010lu\tinner:%llu\touter:%llunmi-ts:%llu\tnmi-count:%u\n",
+       F_printk("cnt:%u\tts:%010llu.%010lu\tinner:%llu\touter:%llunmi-ts:%llu\tnmi-count:%u\n",
                 __entry->seqnum,
                 __entry->tv_sec,
                 __entry->tv_nsec,
index 21ea6ae77d93fd45f50ed71059fbe4954b9ef2c0..d7c8e4ec3d9d6cd92b6d78a2c66c984cbbc6fb6c 100644 (file)
@@ -79,12 +79,12 @@ static u64 last_tracing_thresh = DEFAULT_LAT_THRESHOLD * NSEC_PER_USEC;
 
 /* Individual latency samples are stored here when detected. */
 struct hwlat_sample {
-       u64             seqnum;         /* unique sequence */
-       u64             duration;       /* delta */
-       u64             outer_duration; /* delta (outer loop) */
-       u64             nmi_total_ts;   /* Total time spent in NMIs */
-       struct timespec timestamp;      /* wall time */
-       int             nmi_count;      /* # NMIs during this sample */
+       u64                     seqnum;         /* unique sequence */
+       u64                     duration;       /* delta */
+       u64                     outer_duration; /* delta (outer loop) */
+       u64                     nmi_total_ts;   /* Total time spent in NMIs */
+       struct timespec64       timestamp;      /* wall time */
+       int                     nmi_count;      /* # NMIs during this sample */
 };
 
 /* keep the global state somewhere. */
@@ -250,7 +250,7 @@ static int get_sample(void)
                s.seqnum = hwlat_data.count;
                s.duration = sample;
                s.outer_duration = outer_sample;
-               s.timestamp = CURRENT_TIME;
+               ktime_get_real_ts64(&s.timestamp);
                s.nmi_total_ts = nmi_total_ts;
                s.nmi_count = nmi_count;
                trace_hwlat_sample(&s);
index 02a4aeb22c4785cc808a7906c970dfa420796cbe..08f9bab8089e74c2acd63e0eaa7ef53f922b88c4 100644 (file)
@@ -4,7 +4,6 @@
  * Copyright (C) 2008 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
  *
  */
-
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/ftrace.h>
@@ -1161,11 +1160,11 @@ trace_hwlat_print(struct trace_iterator *iter, int flags,
 
        trace_assign_type(field, entry);
 
-       trace_seq_printf(s, "#%-5u inner/outer(us): %4llu/%-5llu ts:%ld.%09ld",
+       trace_seq_printf(s, "#%-5u inner/outer(us): %4llu/%-5llu ts:%lld.%09ld",
                         field->seqnum,
                         field->duration,
                         field->outer_duration,
-                        field->timestamp.tv_sec,
+                        (long long)field->timestamp.tv_sec,
                         field->timestamp.tv_nsec);
 
        if (field->nmi_count) {
@@ -1195,10 +1194,10 @@ trace_hwlat_raw(struct trace_iterator *iter, int flags,
 
        trace_assign_type(field, iter->ent);
 
-       trace_seq_printf(s, "%llu %lld %ld %09ld %u\n",
+       trace_seq_printf(s, "%llu %lld %lld %09ld %u\n",
                         field->duration,
                         field->outer_duration,
-                        field->timestamp.tv_sec,
+                        (long long)field->timestamp.tv_sec,
                         field->timestamp.tv_nsec,
                         field->seqnum);
 
index e2a617e09ab78c33e7512c5d6e09d477e6a193e8..e4587ebe52c7ec3c7923c661dea9b8f15b77bd8e 100644 (file)
@@ -1719,19 +1719,21 @@ config LKDTM
        Documentation/fault-injection/provoke-crashes.txt
 
 config TEST_LIST_SORT
-       bool "Linked list sorting test"
-       depends on DEBUG_KERNEL
+       tristate "Linked list sorting test"
+       depends on DEBUG_KERNEL || m
        help
          Enable this to turn on 'list_sort()' function test. This test is
-         executed only once during system boot, so affects only boot time.
+         executed only once during system boot (so affects only boot time),
+         or at module load time.
 
          If unsure, say N.
 
 config TEST_SORT
-       bool "Array-based sort test"
-       depends on DEBUG_KERNEL
+       tristate "Array-based sort test"
+       depends on DEBUG_KERNEL || m
        help
-         This option enables the self-test function of 'sort()' at boot.
+         This option enables the self-test function of 'sort()' at boot,
+         or at module load time.
 
          If unsure, say N.
 
index a155c73e3437ad539a809524dd3d162cd8db1b75..0166fbc0fa811f8462bc2f3dafcae9408ae922c4 100644 (file)
@@ -52,6 +52,7 @@ obj-$(CONFIG_TEST_FIRMWARE) += test_firmware.o
 obj-$(CONFIG_TEST_HASH) += test_hash.o test_siphash.o
 obj-$(CONFIG_TEST_KASAN) += test_kasan.o
 obj-$(CONFIG_TEST_KSTRTOX) += test-kstrtox.o
+obj-$(CONFIG_TEST_LIST_SORT) += test_list_sort.o
 obj-$(CONFIG_TEST_LKM) += test_module.o
 obj-$(CONFIG_TEST_RHASHTABLE) += test_rhashtable.o
 obj-$(CONFIG_TEST_SORT) += test_sort.o
index cb1464c411a2b4fa88778343bf33208ccd8dae76..78eca713b1d9ad99caa14deb3b688559aaf0fd63 100644 (file)
@@ -17,7 +17,7 @@ static int devm_ioremap_match(struct device *dev, void *res, void *match_data)
 /**
  * devm_ioremap - Managed ioremap()
  * @dev: Generic device to remap IO address for
- * @offset: BUS offset to map
+ * @offset: Resource address to map
  * @size: Size of map
  *
  * Managed ioremap().  Map is automatically unmapped on driver detach.
@@ -45,7 +45,7 @@ EXPORT_SYMBOL(devm_ioremap);
 /**
  * devm_ioremap_nocache - Managed ioremap_nocache()
  * @dev: Generic device to remap IO address for
- * @offset: BUS offset to map
+ * @offset: Resource address to map
  * @size: Size of map
  *
  * Managed ioremap_nocache().  Map is automatically unmapped on driver
@@ -74,7 +74,7 @@ EXPORT_SYMBOL(devm_ioremap_nocache);
 /**
  * devm_ioremap_wc - Managed ioremap_wc()
  * @dev: Generic device to remap IO address for
- * @offset: BUS offset to map
+ * @offset: Resource address to map
  * @size: Size of map
  *
  * Managed ioremap_wc().  Map is automatically unmapped on driver detach.
index fe4d50c992df618a914e4696d7f698e4e8b76c83..ea4cc3dde4f1bac9f3b8337fdac95408cb3e8b35 100644 (file)
@@ -1498,7 +1498,7 @@ void debug_dma_alloc_coherent(struct device *dev, size_t size,
        entry->type      = dma_debug_coherent;
        entry->dev       = dev;
        entry->pfn       = page_to_pfn(virt_to_page(virt));
-       entry->offset    = (size_t) virt & ~PAGE_MASK;
+       entry->offset    = offset_in_page(virt);
        entry->size      = size;
        entry->dev_addr  = dma_addr;
        entry->direction = DMA_BIDIRECTIONAL;
@@ -1514,7 +1514,7 @@ void debug_dma_free_coherent(struct device *dev, size_t size,
                .type           = dma_debug_coherent,
                .dev            = dev,
                .pfn            = page_to_pfn(virt_to_page(virt)),
-               .offset         = (size_t) virt & ~PAGE_MASK,
+               .offset         = offset_in_page(virt),
                .dev_addr       = addr,
                .size           = size,
                .direction      = DMA_BIDIRECTIONAL,
index 6a823a53e357bc83e84476d93cc2c155f0adfee5..4ff157159a0d4d9d746fad5d228e878bdecd5be2 100644 (file)
@@ -56,7 +56,7 @@ static void fail_dump(struct fault_attr *attr)
 
 static bool fail_task(struct fault_attr *attr, struct task_struct *task)
 {
-       return !in_interrupt() && task->make_it_fail;
+       return in_task() && task->make_it_fail;
 }
 
 #define MAX_STACK_TRACE_DEPTH 32
index 4952311422c12a40d9b4adc1806006880c3c4d04..f835964c9485f147699609bf2c2dc1ffecb8833b 100644 (file)
@@ -790,6 +790,8 @@ void iov_iter_revert(struct iov_iter *i, size_t unroll)
 {
        if (!unroll)
                return;
+       if (WARN_ON(unroll > MAX_RW_COUNT))
+               return;
        i->count += unroll;
        if (unlikely(i->type & ITER_PIPE)) {
                struct pipe_inode_info *pipe = i->pipe;
@@ -1028,10 +1030,7 @@ EXPORT_SYMBOL(iov_iter_get_pages);
 
 static struct page **get_pages_array(size_t n)
 {
-       struct page **p = kmalloc(n * sizeof(struct page *), GFP_KERNEL);
-       if (!p)
-               p = vmalloc(n * sizeof(struct page *));
-       return p;
+       return kvmalloc_array(n, sizeof(struct page *), GFP_KERNEL);
 }
 
 static ssize_t pipe_get_pages_alloc(struct iov_iter *i,
index 3fe401067e20ba81c762fb00ae00730de6b9502f..9e9acc37652f2814542438f65d20ea9b3aab6539 100644 (file)
@@ -1,6 +1,3 @@
-
-#define pr_fmt(fmt) "list_sort_test: " fmt
-
 #include <linux/kernel.h>
 #include <linux/bug.h>
 #include <linux/compiler.h>
@@ -145,149 +142,3 @@ void list_sort(void *priv, struct list_head *head,
        merge_and_restore_back_links(priv, cmp, head, part[max_lev], list);
 }
 EXPORT_SYMBOL(list_sort);
-
-#ifdef CONFIG_TEST_LIST_SORT
-
-#include <linux/slab.h>
-#include <linux/random.h>
-
-/*
- * The pattern of set bits in the list length determines which cases
- * are hit in list_sort().
- */
-#define TEST_LIST_LEN (512+128+2) /* not including head */
-
-#define TEST_POISON1 0xDEADBEEF
-#define TEST_POISON2 0xA324354C
-
-struct debug_el {
-       unsigned int poison1;
-       struct list_head list;
-       unsigned int poison2;
-       int value;
-       unsigned serial;
-};
-
-/* Array, containing pointers to all elements in the test list */
-static struct debug_el **elts __initdata;
-
-static int __init check(struct debug_el *ela, struct debug_el *elb)
-{
-       if (ela->serial >= TEST_LIST_LEN) {
-               pr_err("error: incorrect serial %d\n", ela->serial);
-               return -EINVAL;
-       }
-       if (elb->serial >= TEST_LIST_LEN) {
-               pr_err("error: incorrect serial %d\n", elb->serial);
-               return -EINVAL;
-       }
-       if (elts[ela->serial] != ela || elts[elb->serial] != elb) {
-               pr_err("error: phantom element\n");
-               return -EINVAL;
-       }
-       if (ela->poison1 != TEST_POISON1 || ela->poison2 != TEST_POISON2) {
-               pr_err("error: bad poison: %#x/%#x\n",
-                       ela->poison1, ela->poison2);
-               return -EINVAL;
-       }
-       if (elb->poison1 != TEST_POISON1 || elb->poison2 != TEST_POISON2) {
-               pr_err("error: bad poison: %#x/%#x\n",
-                       elb->poison1, elb->poison2);
-               return -EINVAL;
-       }
-       return 0;
-}
-
-static int __init cmp(void *priv, struct list_head *a, struct list_head *b)
-{
-       struct debug_el *ela, *elb;
-
-       ela = container_of(a, struct debug_el, list);
-       elb = container_of(b, struct debug_el, list);
-
-       check(ela, elb);
-       return ela->value - elb->value;
-}
-
-static int __init list_sort_test(void)
-{
-       int i, count = 1, err = -ENOMEM;
-       struct debug_el *el;
-       struct list_head *cur;
-       LIST_HEAD(head);
-
-       pr_debug("start testing list_sort()\n");
-
-       elts = kcalloc(TEST_LIST_LEN, sizeof(*elts), GFP_KERNEL);
-       if (!elts) {
-               pr_err("error: cannot allocate memory\n");
-               return err;
-       }
-
-       for (i = 0; i < TEST_LIST_LEN; i++) {
-               el = kmalloc(sizeof(*el), GFP_KERNEL);
-               if (!el) {
-                       pr_err("error: cannot allocate memory\n");
-                       goto exit;
-               }
-                /* force some equivalencies */
-               el->value = prandom_u32() % (TEST_LIST_LEN / 3);
-               el->serial = i;
-               el->poison1 = TEST_POISON1;
-               el->poison2 = TEST_POISON2;
-               elts[i] = el;
-               list_add_tail(&el->list, &head);
-       }
-
-       list_sort(NULL, &head, cmp);
-
-       err = -EINVAL;
-       for (cur = head.next; cur->next != &head; cur = cur->next) {
-               struct debug_el *el1;
-               int cmp_result;
-
-               if (cur->next->prev != cur) {
-                       pr_err("error: list is corrupted\n");
-                       goto exit;
-               }
-
-               cmp_result = cmp(NULL, cur, cur->next);
-               if (cmp_result > 0) {
-                       pr_err("error: list is not sorted\n");
-                       goto exit;
-               }
-
-               el = container_of(cur, struct debug_el, list);
-               el1 = container_of(cur->next, struct debug_el, list);
-               if (cmp_result == 0 && el->serial >= el1->serial) {
-                       pr_err("error: order of equivalent elements not "
-                               "preserved\n");
-                       goto exit;
-               }
-
-               if (check(el, el1)) {
-                       pr_err("error: element check failed\n");
-                       goto exit;
-               }
-               count++;
-       }
-       if (head.prev != cur) {
-               pr_err("error: list is corrupted\n");
-               goto exit;
-       }
-
-
-       if (count != TEST_LIST_LEN) {
-               pr_err("error: bad list length %d", count);
-               goto exit;
-       }
-
-       err = 0;
-exit:
-       for (i = 0; i < TEST_LIST_LEN; i++)
-               kfree(elts[i]);
-       kfree(elts);
-       return err;
-}
-late_initcall(list_sort_test);
-#endif /* CONFIG_TEST_LIST_SORT */
index a930e436db5d8ff6b3e4959ae60761607bcd47cc..d9e7274a04cd98d14456b1bba9ad2e241eae8895 100644 (file)
@@ -86,16 +86,9 @@ static int alloc_bucket_locks(struct rhashtable *ht, struct bucket_table *tbl,
                size = min(size, 1U << tbl->nest);
 
        if (sizeof(spinlock_t) != 0) {
-               tbl->locks = NULL;
-#ifdef CONFIG_NUMA
-               if (size * sizeof(spinlock_t) > PAGE_SIZE &&
-                   gfp == GFP_KERNEL)
-                       tbl->locks = vmalloc(size * sizeof(spinlock_t));
-#endif
-               if (gfp != GFP_KERNEL)
-                       gfp |= __GFP_NOWARN | __GFP_NORETRY;
-
-               if (!tbl->locks)
+               if (gfpflags_allow_blocking(gfp))
+                       tbl->locks = kvmalloc(size * sizeof(spinlock_t), gfp);
+               else
                        tbl->locks = kmalloc_array(size, sizeof(spinlock_t),
                                                   gfp);
                if (!tbl->locks)
diff --git a/lib/test_list_sort.c b/lib/test_list_sort.c
new file mode 100644 (file)
index 0000000..28e8173
--- /dev/null
@@ -0,0 +1,150 @@
+#define pr_fmt(fmt) "list_sort_test: " fmt
+
+#include <linux/kernel.h>
+#include <linux/list_sort.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/printk.h>
+#include <linux/slab.h>
+#include <linux/random.h>
+
+/*
+ * The pattern of set bits in the list length determines which cases
+ * are hit in list_sort().
+ */
+#define TEST_LIST_LEN (512+128+2) /* not including head */
+
+#define TEST_POISON1 0xDEADBEEF
+#define TEST_POISON2 0xA324354C
+
+struct debug_el {
+       unsigned int poison1;
+       struct list_head list;
+       unsigned int poison2;
+       int value;
+       unsigned serial;
+};
+
+/* Array, containing pointers to all elements in the test list */
+static struct debug_el **elts __initdata;
+
+static int __init check(struct debug_el *ela, struct debug_el *elb)
+{
+       if (ela->serial >= TEST_LIST_LEN) {
+               pr_err("error: incorrect serial %d\n", ela->serial);
+               return -EINVAL;
+       }
+       if (elb->serial >= TEST_LIST_LEN) {
+               pr_err("error: incorrect serial %d\n", elb->serial);
+               return -EINVAL;
+       }
+       if (elts[ela->serial] != ela || elts[elb->serial] != elb) {
+               pr_err("error: phantom element\n");
+               return -EINVAL;
+       }
+       if (ela->poison1 != TEST_POISON1 || ela->poison2 != TEST_POISON2) {
+               pr_err("error: bad poison: %#x/%#x\n",
+                       ela->poison1, ela->poison2);
+               return -EINVAL;
+       }
+       if (elb->poison1 != TEST_POISON1 || elb->poison2 != TEST_POISON2) {
+               pr_err("error: bad poison: %#x/%#x\n",
+                       elb->poison1, elb->poison2);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static int __init cmp(void *priv, struct list_head *a, struct list_head *b)
+{
+       struct debug_el *ela, *elb;
+
+       ela = container_of(a, struct debug_el, list);
+       elb = container_of(b, struct debug_el, list);
+
+       check(ela, elb);
+       return ela->value - elb->value;
+}
+
+static int __init list_sort_test(void)
+{
+       int i, count = 1, err = -ENOMEM;
+       struct debug_el *el;
+       struct list_head *cur;
+       LIST_HEAD(head);
+
+       pr_debug("start testing list_sort()\n");
+
+       elts = kcalloc(TEST_LIST_LEN, sizeof(*elts), GFP_KERNEL);
+       if (!elts) {
+               pr_err("error: cannot allocate memory\n");
+               return err;
+       }
+
+       for (i = 0; i < TEST_LIST_LEN; i++) {
+               el = kmalloc(sizeof(*el), GFP_KERNEL);
+               if (!el) {
+                       pr_err("error: cannot allocate memory\n");
+                       goto exit;
+               }
+                /* force some equivalencies */
+               el->value = prandom_u32() % (TEST_LIST_LEN / 3);
+               el->serial = i;
+               el->poison1 = TEST_POISON1;
+               el->poison2 = TEST_POISON2;
+               elts[i] = el;
+               list_add_tail(&el->list, &head);
+       }
+
+       list_sort(NULL, &head, cmp);
+
+       err = -EINVAL;
+       for (cur = head.next; cur->next != &head; cur = cur->next) {
+               struct debug_el *el1;
+               int cmp_result;
+
+               if (cur->next->prev != cur) {
+                       pr_err("error: list is corrupted\n");
+                       goto exit;
+               }
+
+               cmp_result = cmp(NULL, cur, cur->next);
+               if (cmp_result > 0) {
+                       pr_err("error: list is not sorted\n");
+                       goto exit;
+               }
+
+               el = container_of(cur, struct debug_el, list);
+               el1 = container_of(cur->next, struct debug_el, list);
+               if (cmp_result == 0 && el->serial >= el1->serial) {
+                       pr_err("error: order of equivalent elements not "
+                               "preserved\n");
+                       goto exit;
+               }
+
+               if (check(el, el1)) {
+                       pr_err("error: element check failed\n");
+                       goto exit;
+               }
+               count++;
+       }
+       if (head.prev != cur) {
+               pr_err("error: list is corrupted\n");
+               goto exit;
+       }
+
+
+       if (count != TEST_LIST_LEN) {
+               pr_err("error: bad list length %d", count);
+               goto exit;
+       }
+
+       err = 0;
+exit:
+       for (i = 0; i < TEST_LIST_LEN; i++)
+               kfree(elts[i]);
+       kfree(elts);
+       return err;
+}
+module_init(list_sort_test);
+MODULE_LICENSE("GPL");
index 4db3911db50ace76356b6530f03480955226b79a..d389c1cc2f6cf795783c0572771b54bb64f9b751 100644 (file)
@@ -1,11 +1,8 @@
 #include <linux/sort.h>
 #include <linux/slab.h>
-#include <linux/init.h>
+#include <linux/module.h>
 
-/*
- * A simple boot-time regression test
- * License: GPL
- */
+/* a simple boot-time regression test */
 
 #define TEST_LEN 1000
 
@@ -41,4 +38,6 @@ exit:
        kfree(a);
        return err;
 }
-subsys_initcall(test_sort_init);
+
+module_init(test_sort_init);
+MODULE_LICENSE("GPL");
index 176641cc549d9ff75dc7cb1a587cc753dd1e7e54..2d41de3f98a1c9a0e0883b3d73b6980b0110cff1 100644 (file)
@@ -1477,6 +1477,9 @@ int kptr_restrict __read_mostly;
  * by an extra set of alphanumeric characters that are extended format
  * specifiers.
  *
+ * Please update scripts/checkpatch.pl when adding/removing conversion
+ * characters.  (Search for "check for vsprintf extension").
+ *
  * Right now we handle:
  *
  * - 'F' For symbolic function descriptor pointers with offset
index 3fe6ce5b53e51999b0ad15f97843b93c313cb60f..02894305292663abc7c4ac9b8e1fbaed18396f6b 100644 (file)
@@ -109,7 +109,7 @@ int zlib_inflate_table(codetype type, unsigned short *lens, unsigned codes,
         *bits = 1;
         return 0;     /* no symbols, but wait for decoding to report error */
     }
-    for (min = 1; min <= MAXBITS; min++)
+    for (min = 1; min < MAXBITS; min++)
         if (count[min] != 0) break;
     if (root < min) root = min;
 
index 09c5282ebdd2812fbb758255194d9063cf5dcf97..613c59e928cb5b07075c197126e01b9cdafff992 100644 (file)
@@ -89,11 +89,6 @@ static void map_pages(struct list_head *list)
        list_splice(&tmp_list, list);
 }
 
-static inline bool migrate_async_suitable(int migratetype)
-{
-       return is_migrate_cma(migratetype) || migratetype == MIGRATE_MOVABLE;
-}
-
 #ifdef CONFIG_COMPACTION
 
 int PageMovable(struct page *page)
@@ -988,6 +983,22 @@ isolate_migratepages_range(struct compact_control *cc, unsigned long start_pfn,
 #endif /* CONFIG_COMPACTION || CONFIG_CMA */
 #ifdef CONFIG_COMPACTION
 
+static bool suitable_migration_source(struct compact_control *cc,
+                                                       struct page *page)
+{
+       int block_mt;
+
+       if ((cc->mode != MIGRATE_ASYNC) || !cc->direct_compaction)
+               return true;
+
+       block_mt = get_pageblock_migratetype(page);
+
+       if (cc->migratetype == MIGRATE_MOVABLE)
+               return is_migrate_movable(block_mt);
+       else
+               return block_mt == cc->migratetype;
+}
+
 /* Returns true if the page is within a block suitable for migration to */
 static bool suitable_migration_target(struct compact_control *cc,
                                                        struct page *page)
@@ -1007,7 +1018,7 @@ static bool suitable_migration_target(struct compact_control *cc,
                return true;
 
        /* If the block is MIGRATE_MOVABLE or MIGRATE_CMA, allow migration */
-       if (migrate_async_suitable(get_pageblock_migratetype(page)))
+       if (is_migrate_movable(get_pageblock_migratetype(page)))
                return true;
 
        /* Otherwise skip the block */
@@ -1242,8 +1253,7 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone,
                 * Async compaction is optimistic to see if the minimum amount
                 * of work satisfies the allocation.
                 */
-               if (cc->mode == MIGRATE_ASYNC &&
-                   !migrate_async_suitable(get_pageblock_migratetype(page)))
+               if (!suitable_migration_source(cc, page))
                        continue;
 
                /* Perform the isolation */
@@ -1276,11 +1286,11 @@ static inline bool is_via_compact_memory(int order)
        return order == -1;
 }
 
-static enum compact_result __compact_finished(struct zone *zone, struct compact_control *cc,
-                           const int migratetype)
+static enum compact_result __compact_finished(struct zone *zone,
+                                               struct compact_control *cc)
 {
        unsigned int order;
-       unsigned long watermark;
+       const int migratetype = cc->migratetype;
 
        if (cc->contended || fatal_signal_pending(current))
                return COMPACT_CONTENDED;
@@ -1308,12 +1318,16 @@ static enum compact_result __compact_finished(struct zone *zone, struct compact_
        if (is_via_compact_memory(cc->order))
                return COMPACT_CONTINUE;
 
-       /* Compaction run is not finished if the watermark is not met */
-       watermark = zone->watermark[cc->alloc_flags & ALLOC_WMARK_MASK];
-
-       if (!zone_watermark_ok(zone, cc->order, watermark, cc->classzone_idx,
-                                                       cc->alloc_flags))
-               return COMPACT_CONTINUE;
+       if (cc->finishing_block) {
+               /*
+                * We have finished the pageblock, but better check again that
+                * we really succeeded.
+                */
+               if (IS_ALIGNED(cc->migrate_pfn, pageblock_nr_pages))
+                       cc->finishing_block = false;
+               else
+                       return COMPACT_CONTINUE;
+       }
 
        /* Direct compactor: Is a suitable page free? */
        for (order = cc->order; order < MAX_ORDER; order++) {
@@ -1335,20 +1349,40 @@ static enum compact_result __compact_finished(struct zone *zone, struct compact_
                 * other migratetype buddy lists.
                 */
                if (find_suitable_fallback(area, order, migratetype,
-                                               true, &can_steal) != -1)
-                       return COMPACT_SUCCESS;
+                                               true, &can_steal) != -1) {
+
+                       /* movable pages are OK in any pageblock */
+                       if (migratetype == MIGRATE_MOVABLE)
+                               return COMPACT_SUCCESS;
+
+                       /*
+                        * We are stealing for a non-movable allocation. Make
+                        * sure we finish compacting the current pageblock
+                        * first so it is as free as possible and we won't
+                        * have to steal another one soon. This only applies
+                        * to sync compaction, as async compaction operates
+                        * on pageblocks of the same migratetype.
+                        */
+                       if (cc->mode == MIGRATE_ASYNC ||
+                                       IS_ALIGNED(cc->migrate_pfn,
+                                                       pageblock_nr_pages)) {
+                               return COMPACT_SUCCESS;
+                       }
+
+                       cc->finishing_block = true;
+                       return COMPACT_CONTINUE;
+               }
        }
 
        return COMPACT_NO_SUITABLE_PAGE;
 }
 
 static enum compact_result compact_finished(struct zone *zone,
-                       struct compact_control *cc,
-                       const int migratetype)
+                       struct compact_control *cc)
 {
        int ret;
 
-       ret = __compact_finished(zone, cc, migratetype);
+       ret = __compact_finished(zone, cc);
        trace_mm_compaction_finished(zone, cc->order, ret);
        if (ret == COMPACT_NO_SUITABLE_PAGE)
                ret = COMPACT_CONTINUE;
@@ -1481,9 +1515,9 @@ static enum compact_result compact_zone(struct zone *zone, struct compact_contro
        enum compact_result ret;
        unsigned long start_pfn = zone->zone_start_pfn;
        unsigned long end_pfn = zone_end_pfn(zone);
-       const int migratetype = gfpflags_to_migratetype(cc->gfp_mask);
        const bool sync = cc->mode != MIGRATE_ASYNC;
 
+       cc->migratetype = gfpflags_to_migratetype(cc->gfp_mask);
        ret = compaction_suitable(zone, cc->order, cc->alloc_flags,
                                                        cc->classzone_idx);
        /* Compaction is likely to fail */
@@ -1533,8 +1567,7 @@ static enum compact_result compact_zone(struct zone *zone, struct compact_contro
 
        migrate_prep_local();
 
-       while ((ret = compact_finished(zone, cc, migratetype)) ==
-                                               COMPACT_CONTINUE) {
+       while ((ret = compact_finished(zone, cc)) == COMPACT_CONTINUE) {
                int err;
 
                switch (isolate_migratepages(zone, cc)) {
index 681da61080bc35fe6a3cee9084f65fd7acd3ecdc..6f1be573a5e60fbb0c4a6cbcf85df9b32b0fc673 100644 (file)
@@ -2050,7 +2050,7 @@ generic_file_read_iter(struct kiocb *iocb, struct iov_iter *iter)
                        iocb->ki_pos += retval;
                        count -= retval;
                }
-               iov_iter_revert(iter, iov_iter_count(iter) - count);
+               iov_iter_revert(iter, count - iov_iter_count(iter));
 
                /*
                 * Btrfs can have a short DIO read if we encounter
@@ -2791,12 +2791,6 @@ ssize_t generic_perform_write(struct file *file,
        ssize_t written = 0;
        unsigned int flags = 0;
 
-       /*
-        * Copies from kernel address space cannot fail (NFSD is a big user).
-        */
-       if (!iter_is_iovec(i))
-               flags |= AOP_FLAG_UNINTERRUPTIBLE;
-
        do {
                struct page *page;
                unsigned long offset;   /* Offset into pagecache page */
index db77dcb38afda3d3720a228e14236fb2e324f929..72ebec18629c2529fc6d2b6faeb46040adcac611 100644 (file)
@@ -200,10 +200,7 @@ struct frame_vector *frame_vector_create(unsigned int nr_frames)
         * Avoid higher order allocations, use vmalloc instead. It should
         * be rare anyway.
         */
-       if (size <= PAGE_SIZE)
-               vec = kmalloc(size, GFP_KERNEL);
-       else
-               vec = vmalloc(size);
+       vec = kvmalloc(size, GFP_KERNEL);
        if (!vec)
                return NULL;
        vec->nr_allocated = nr_frames;
index b787c4cfda0e61debd37f168a3061d4a5dfd4ce5..a84909cf20d36b3d84f00d8529127f78f6b5981d 100644 (file)
@@ -715,7 +715,8 @@ int do_huge_pmd_anonymous_page(struct vm_fault *vmf)
 }
 
 static void insert_pfn_pmd(struct vm_area_struct *vma, unsigned long addr,
-               pmd_t *pmd, pfn_t pfn, pgprot_t prot, bool write)
+               pmd_t *pmd, pfn_t pfn, pgprot_t prot, bool write,
+               pgtable_t pgtable)
 {
        struct mm_struct *mm = vma->vm_mm;
        pmd_t entry;
@@ -729,6 +730,12 @@ static void insert_pfn_pmd(struct vm_area_struct *vma, unsigned long addr,
                entry = pmd_mkyoung(pmd_mkdirty(entry));
                entry = maybe_pmd_mkwrite(entry, vma);
        }
+
+       if (pgtable) {
+               pgtable_trans_huge_deposit(mm, pmd, pgtable);
+               atomic_long_inc(&mm->nr_ptes);
+       }
+
        set_pmd_at(mm, addr, pmd, entry);
        update_mmu_cache_pmd(vma, addr, pmd);
        spin_unlock(ptl);
@@ -738,6 +745,7 @@ int vmf_insert_pfn_pmd(struct vm_area_struct *vma, unsigned long addr,
                        pmd_t *pmd, pfn_t pfn, bool write)
 {
        pgprot_t pgprot = vma->vm_page_prot;
+       pgtable_t pgtable = NULL;
        /*
         * If we had pmd_special, we could avoid all these restrictions,
         * but we need to be consistent with PTEs and architectures that
@@ -752,9 +760,15 @@ int vmf_insert_pfn_pmd(struct vm_area_struct *vma, unsigned long addr,
        if (addr < vma->vm_start || addr >= vma->vm_end)
                return VM_FAULT_SIGBUS;
 
+       if (arch_needs_pgtable_deposit()) {
+               pgtable = pte_alloc_one(vma->vm_mm, addr);
+               if (!pgtable)
+                       return VM_FAULT_OOM;
+       }
+
        track_pfn_insert(vma, &pgprot, pfn);
 
-       insert_pfn_pmd(vma, addr, pmd, pfn, pgprot, write);
+       insert_pfn_pmd(vma, addr, pmd, pfn, pgprot, write, pgtable);
        return VM_FAULT_NOPAGE;
 }
 EXPORT_SYMBOL_GPL(vmf_insert_pfn_pmd);
@@ -1611,12 +1625,13 @@ int zap_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma,
                        tlb->fullmm);
        tlb_remove_pmd_tlb_entry(tlb, pmd, addr);
        if (vma_is_dax(vma)) {
+               if (arch_needs_pgtable_deposit())
+                       zap_deposited_table(tlb->mm, pmd);
                spin_unlock(ptl);
                if (is_huge_zero_pmd(orig_pmd))
                        tlb_remove_page_size(tlb, pmd_page(orig_pmd), HPAGE_PMD_SIZE);
        } else if (is_huge_zero_pmd(orig_pmd)) {
-               pte_free(tlb->mm, pgtable_trans_huge_withdraw(tlb->mm, pmd));
-               atomic_long_dec(&tlb->mm->nr_ptes);
+               zap_deposited_table(tlb->mm, pmd);
                spin_unlock(ptl);
                tlb_remove_page_size(tlb, pmd_page(orig_pmd), HPAGE_PMD_SIZE);
        } else {
@@ -1625,10 +1640,7 @@ int zap_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma,
                VM_BUG_ON_PAGE(page_mapcount(page) < 0, page);
                VM_BUG_ON_PAGE(!PageHead(page), page);
                if (PageAnon(page)) {
-                       pgtable_t pgtable;
-                       pgtable = pgtable_trans_huge_withdraw(tlb->mm, pmd);
-                       pte_free(tlb->mm, pgtable);
-                       atomic_long_dec(&tlb->mm->nr_ptes);
+                       zap_deposited_table(tlb->mm, pmd);
                        add_mm_counter(tlb->mm, MM_ANONPAGES, -HPAGE_PMD_NR);
                } else {
                        if (arch_needs_pgtable_deposit())
index 04d08ef91224bfb8be0a6a2aed456281f7702c44..0e4f558412fb195c0b2bd997fbc0ac1b9c1e4566 100644 (file)
@@ -183,6 +183,7 @@ extern int user_min_free_kbytes;
 struct compact_control {
        struct list_head freepages;     /* List of free pages to migrate to */
        struct list_head migratepages;  /* List of pages being migrated */
+       struct zone *zone;
        unsigned long nr_freepages;     /* Number of isolated free pages */
        unsigned long nr_migratepages;  /* Number of pages to migrate */
        unsigned long total_migrate_scanned;
@@ -190,17 +191,18 @@ struct compact_control {
        unsigned long free_pfn;         /* isolate_freepages search base */
        unsigned long migrate_pfn;      /* isolate_migratepages search base */
        unsigned long last_migrated_pfn;/* Not yet flushed page being freed */
+       const gfp_t gfp_mask;           /* gfp mask of a direct compactor */
+       int order;                      /* order a direct compactor needs */
+       int migratetype;                /* migratetype of direct compactor */
+       const unsigned int alloc_flags; /* alloc flags of a direct compactor */
+       const int classzone_idx;        /* zone index of a direct compactor */
        enum migrate_mode mode;         /* Async or sync migration mode */
        bool ignore_skip_hint;          /* Scan blocks even if marked skip */
        bool ignore_block_suitable;     /* Scan blocks considered unsuitable */
        bool direct_compaction;         /* False from kcompactd or /proc/... */
        bool whole_zone;                /* Whole zone should/has been scanned */
-       int order;                      /* order a direct compactor needs */
-       const gfp_t gfp_mask;           /* gfp mask of a direct compactor */
-       const unsigned int alloc_flags; /* alloc flags of a direct compactor */
-       const int classzone_idx;        /* zone index of a direct compactor */
-       struct zone *zone;
        bool contended;                 /* Signal lock or sched contention */
+       bool finishing_block;           /* Finishing current pageblock */
 };
 
 unsigned long
index 9348d27088c1145872495859c8eee26f6dc7f23f..c81549d5c8330f59bec68165127dff1d3aab85bd 100644 (file)
@@ -413,7 +413,7 @@ void kasan_cache_create(struct kmem_cache *cache, size_t *size,
        *size += sizeof(struct kasan_alloc_meta);
 
        /* Add free meta. */
-       if (cache->flags & SLAB_DESTROY_BY_RCU || cache->ctor ||
+       if (cache->flags & SLAB_TYPESAFE_BY_RCU || cache->ctor ||
            cache->object_size < sizeof(struct kasan_free_meta)) {
                cache->kasan_info.free_meta_offset = *size;
                *size += sizeof(struct kasan_free_meta);
@@ -561,7 +561,7 @@ static void kasan_poison_slab_free(struct kmem_cache *cache, void *object)
        unsigned long rounded_up_size = round_up(size, KASAN_SHADOW_SCALE_SIZE);
 
        /* RCU slabs could be legally used after free within the RCU period */
-       if (unlikely(cache->flags & SLAB_DESTROY_BY_RCU))
+       if (unlikely(cache->flags & SLAB_TYPESAFE_BY_RCU))
                return;
 
        kasan_poison_shadow(object, rounded_up_size, KASAN_KMALLOC_FREE);
@@ -572,7 +572,7 @@ bool kasan_slab_free(struct kmem_cache *cache, void *object)
        s8 shadow_byte;
 
        /* RCU slabs could be legally used after free within the RCU period */
-       if (unlikely(cache->flags & SLAB_DESTROY_BY_RCU))
+       if (unlikely(cache->flags & SLAB_TYPESAFE_BY_RCU))
                return false;
 
        shadow_byte = READ_ONCE(*(s8 *)kasan_mem_to_shadow(object));
@@ -691,7 +691,7 @@ int kasan_module_alloc(void *addr, size_t size)
 
        ret = __vmalloc_node_range(shadow_size, 1, shadow_start,
                        shadow_start + shadow_size,
-                       GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO,
+                       GFP_KERNEL | __GFP_ZERO,
                        PAGE_KERNEL, VM_NO_GUARD, NUMA_NO_NODE,
                        __builtin_return_address(0));
 
index 7cb9c88bb4a33ca11c3266f398ffffb53c5afc13..945fd1ca49b5af0bc3b87dbfe8098f0f602775a2 100644 (file)
@@ -612,7 +612,8 @@ static void __collapse_huge_page_copy(pte_t *pte, struct page *page,
                                      spinlock_t *ptl)
 {
        pte_t *_pte;
-       for (_pte = pte; _pte < pte+HPAGE_PMD_NR; _pte++) {
+       for (_pte = pte; _pte < pte + HPAGE_PMD_NR;
+                               _pte++, page++, address += PAGE_SIZE) {
                pte_t pteval = *_pte;
                struct page *src_page;
 
@@ -651,9 +652,7 @@ static void __collapse_huge_page_copy(pte_t *pte, struct page *page,
                        spin_unlock(ptl);
                        free_page_and_swap_cache(src_page);
                }
-
-               address += PAGE_SIZE;
-               page++;
+               cond_resched();
        }
 }
 
@@ -907,8 +906,10 @@ static bool __collapse_huge_page_swapin(struct mm_struct *mm,
                                return false;
                        }
                        /* check if the pmd is still valid */
-                       if (mm_find_pmd(mm, address) != pmd)
+                       if (mm_find_pmd(mm, address) != pmd) {
+                               trace_mm_collapse_huge_page_swapin(mm, swapped_in, referenced, 0);
                                return false;
+                       }
                }
                if (ret & VM_FAULT_ERROR) {
                        trace_mm_collapse_huge_page_swapin(mm, swapped_in, referenced, 0);
index 5bf191756a4a07b04ffe1dd792f475e1e0af0492..2d5959c5f7c50469ca3d59da9c62c6c2dd932917 100644 (file)
@@ -95,7 +95,7 @@ void kmemcheck_slab_alloc(struct kmem_cache *s, gfp_t gfpflags, void *object,
 void kmemcheck_slab_free(struct kmem_cache *s, void *object, size_t size)
 {
        /* TODO: RCU freeing is unsupported for now; hide false positives. */
-       if (!s->ctor && !(s->flags & SLAB_DESTROY_BY_RCU))
+       if (!s->ctor && !(s->flags & SLAB_TYPESAFE_BY_RCU))
                kmemcheck_mark_freed(object, size);
 }
 
index ff73899af61a2c25582a66f56d473b0da6ce1b9c..94172089f52fce369c57ce8d3e783a9480d522f2 100644 (file)
@@ -5528,7 +5528,7 @@ static void uncharge_list(struct list_head *page_list)
                next = page->lru.next;
 
                VM_BUG_ON_PAGE(PageLRU(page), page);
-               VM_BUG_ON_PAGE(page_count(page), page);
+               VM_BUG_ON_PAGE(!PageHWPoison(page) && page_count(page), page);
 
                if (!page->mem_cgroup)
                        continue;
index 73066b80d14af70d0fdf12e2228823b84c258903..2527dfeddb003d245ac2e2bd964134030426f777 100644 (file)
@@ -539,6 +539,13 @@ static int delete_from_lru_cache(struct page *p)
                 */
                ClearPageActive(p);
                ClearPageUnevictable(p);
+
+               /*
+                * Poisoned page might never drop its ref count to 0 so we have
+                * to uncharge it manually from its memcg.
+                */
+               mem_cgroup_uncharge(p);
+
                /*
                 * drop the page count elevated by isolate_lru_page()
                 */
index a7652acd2ab93c2e290f31fbe80e36d157abb609..54ca545629286223a16ef931830a3757b29da77d 100644 (file)
@@ -21,7 +21,7 @@
 #include <linux/slab.h>
 
 /* global SRCU for all MMs */
-static struct srcu_struct srcu;
+DEFINE_STATIC_SRCU(srcu);
 
 /*
  * This function allows mmu_notifier::release callback to delay a call to
@@ -252,12 +252,6 @@ static int do_mmu_notifier_register(struct mmu_notifier *mn,
 
        BUG_ON(atomic_read(&mm->mm_users) <= 0);
 
-       /*
-        * Verify that mmu_notifier_init() already run and the global srcu is
-        * initialized.
-        */
-       BUG_ON(!srcu.per_cpu_ref);
-
        ret = -ENOMEM;
        mmu_notifier_mm = kmalloc(sizeof(struct mmu_notifier_mm), GFP_KERNEL);
        if (unlikely(!mmu_notifier_mm))
@@ -406,9 +400,3 @@ void mmu_notifier_unregister_no_release(struct mmu_notifier *mn,
        mmdrop(mm);
 }
 EXPORT_SYMBOL_GPL(mmu_notifier_unregister_no_release);
-
-static int __init mmu_notifier_init(void)
-{
-       return init_srcu_struct(&srcu);
-}
-subsys_initcall(mmu_notifier_init);
index 2d131b97a85169eb11716874b552dc4cef5b4115..fc184f597d59d9af942f8dc60229b999173fe22f 100644 (file)
@@ -237,12 +237,16 @@ void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot)
 }
 EXPORT_SYMBOL(__vmalloc);
 
+void *__vmalloc_node_flags(unsigned long size, int node, gfp_t flags)
+{
+       return __vmalloc(size, flags, PAGE_KERNEL);
+}
+
 void *vmalloc_user(unsigned long size)
 {
        void *ret;
 
-       ret = __vmalloc(size, GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO,
-                       PAGE_KERNEL);
+       ret = __vmalloc(size, GFP_KERNEL | __GFP_ZERO, PAGE_KERNEL);
        if (ret) {
                struct vm_area_struct *vma;
 
index 2c25de46c58fd68aa8e9f3657998e40136d329c7..f9e450c6b6e414d61b00d5a61be9cdea3b773e1b 100644 (file)
@@ -1832,9 +1832,9 @@ static inline struct page *__rmqueue_cma_fallback(struct zone *zone,
  * Note that start_page and end_pages are not aligned on a pageblock
  * boundary. If alignment is required, use move_freepages_block()
  */
-int move_freepages(struct zone *zone,
+static int move_freepages(struct zone *zone,
                          struct page *start_page, struct page *end_page,
-                         int migratetype)
+                         int migratetype, int *num_movable)
 {
        struct page *page;
        unsigned int order;
@@ -1851,6 +1851,9 @@ int move_freepages(struct zone *zone,
        VM_BUG_ON(page_zone(start_page) != page_zone(end_page));
 #endif
 
+       if (num_movable)
+               *num_movable = 0;
+
        for (page = start_page; page <= end_page;) {
                if (!pfn_valid_within(page_to_pfn(page))) {
                        page++;
@@ -1861,6 +1864,15 @@ int move_freepages(struct zone *zone,
                VM_BUG_ON_PAGE(page_to_nid(page) != zone_to_nid(zone), page);
 
                if (!PageBuddy(page)) {
+                       /*
+                        * We assume that pages that could be isolated for
+                        * migration are movable. But we don't actually try
+                        * isolating, as that would be expensive.
+                        */
+                       if (num_movable &&
+                                       (PageLRU(page) || __PageMovable(page)))
+                               (*num_movable)++;
+
                        page++;
                        continue;
                }
@@ -1876,7 +1888,7 @@ int move_freepages(struct zone *zone,
 }
 
 int move_freepages_block(struct zone *zone, struct page *page,
-                               int migratetype)
+                               int migratetype, int *num_movable)
 {
        unsigned long start_pfn, end_pfn;
        struct page *start_page, *end_page;
@@ -1893,7 +1905,8 @@ int move_freepages_block(struct zone *zone, struct page *page,
        if (!zone_spans_pfn(zone, end_pfn))
                return 0;
 
-       return move_freepages(zone, start_page, end_page, migratetype);
+       return move_freepages(zone, start_page, end_page, migratetype,
+                                                               num_movable);
 }
 
 static void change_pageblock_range(struct page *pageblock_page,
@@ -1943,28 +1956,79 @@ static bool can_steal_fallback(unsigned int order, int start_mt)
 /*
  * This function implements actual steal behaviour. If order is large enough,
  * we can steal whole pageblock. If not, we first move freepages in this
- * pageblock and check whether half of pages are moved or not. If half of
- * pages are moved, we can change migratetype of pageblock and permanently
- * use it's pages as requested migratetype in the future.
+ * pageblock to our migratetype and determine how many already-allocated pages
+ * are there in the pageblock with a compatible migratetype. If at least half
+ * of pages are free or compatible, we can change migratetype of the pageblock
+ * itself, so pages freed in the future will be put on the correct free list.
  */
 static void steal_suitable_fallback(struct zone *zone, struct page *page,
-                                                         int start_type)
+                                       int start_type, bool whole_block)
 {
        unsigned int current_order = page_order(page);
-       int pages;
+       struct free_area *area;
+       int free_pages, movable_pages, alike_pages;
+       int old_block_type;
+
+       old_block_type = get_pageblock_migratetype(page);
+
+       /*
+        * This can happen due to races and we want to prevent broken
+        * highatomic accounting.
+        */
+       if (is_migrate_highatomic(old_block_type))
+               goto single_page;
 
        /* Take ownership for orders >= pageblock_order */
        if (current_order >= pageblock_order) {
                change_pageblock_range(page, current_order, start_type);
-               return;
+               goto single_page;
+       }
+
+       /* We are not allowed to try stealing from the whole block */
+       if (!whole_block)
+               goto single_page;
+
+       free_pages = move_freepages_block(zone, page, start_type,
+                                               &movable_pages);
+       /*
+        * Determine how many pages are compatible with our allocation.
+        * For movable allocation, it's the number of movable pages which
+        * we just obtained. For other types it's a bit more tricky.
+        */
+       if (start_type == MIGRATE_MOVABLE) {
+               alike_pages = movable_pages;
+       } else {
+               /*
+                * If we are falling back a RECLAIMABLE or UNMOVABLE allocation
+                * to MOVABLE pageblock, consider all non-movable pages as
+                * compatible. If it's UNMOVABLE falling back to RECLAIMABLE or
+                * vice versa, be conservative since we can't distinguish the
+                * exact migratetype of non-movable pages.
+                */
+               if (old_block_type == MIGRATE_MOVABLE)
+                       alike_pages = pageblock_nr_pages
+                                               - (free_pages + movable_pages);
+               else
+                       alike_pages = 0;
        }
 
-       pages = move_freepages_block(zone, page, start_type);
+       /* moving whole block can fail due to zone boundary conditions */
+       if (!free_pages)
+               goto single_page;
 
-       /* Claim the whole block if over half of it is free */
-       if (pages >= (1 << (pageblock_order-1)) ||
+       /*
+        * If a sufficient number of pages in the block are either free or of
+        * comparable migratability as our allocation, claim the whole block.
+        */
+       if (free_pages + alike_pages >= (1 << (pageblock_order-1)) ||
                        page_group_by_mobility_disabled)
                set_pageblock_migratetype(page, start_type);
+
+       return;
+
+single_page:
+       area = &zone->free_area[current_order];
+       list_move(&page->lru, &area->free_list[start_type]);
 }
 
 /*
@@ -2034,7 +2098,7 @@ static void reserve_highatomic_pageblock(struct page *page, struct zone *zone,
            && !is_migrate_cma(mt)) {
                zone->nr_reserved_highatomic += pageblock_nr_pages;
                set_pageblock_migratetype(page, MIGRATE_HIGHATOMIC);
-               move_freepages_block(zone, page, MIGRATE_HIGHATOMIC);
+               move_freepages_block(zone, page, MIGRATE_HIGHATOMIC, NULL);
        }
 
 out_unlock:
@@ -2111,7 +2175,8 @@ static bool unreserve_highatomic_pageblock(const struct alloc_context *ac,
                         * may increase.
                         */
                        set_pageblock_migratetype(page, ac->migratetype);
-                       ret = move_freepages_block(zone, page, ac->migratetype);
+                       ret = move_freepages_block(zone, page, ac->migratetype,
+                                                                       NULL);
                        if (ret) {
                                spin_unlock_irqrestore(&zone->lock, flags);
                                return ret;
@@ -2123,8 +2188,13 @@ static bool unreserve_highatomic_pageblock(const struct alloc_context *ac,
        return false;
 }
 
-/* Remove an element from the buddy allocator from the fallback list */
-static inline struct page *
+/*
+ * Try finding a free buddy page on the fallback list and put it on the free
+ * list of requested migratetype, possibly along with other pages from the same
+ * block, depending on fragmentation avoidance heuristics. Returns true if
+ * fallback was found so that __rmqueue_smallest() can grab it.
+ */
+static inline bool
 __rmqueue_fallback(struct zone *zone, unsigned int order, int start_migratetype)
 {
        struct free_area *area;
@@ -2145,32 +2215,17 @@ __rmqueue_fallback(struct zone *zone, unsigned int order, int start_migratetype)
 
                page = list_first_entry(&area->free_list[fallback_mt],
                                                struct page, lru);
-               if (can_steal && !is_migrate_highatomic_page(page))
-                       steal_suitable_fallback(zone, page, start_migratetype);
-
-               /* Remove the page from the freelists */
-               area->nr_free--;
-               list_del(&page->lru);
-               rmv_page_order(page);
 
-               expand(zone, page, order, current_order, area,
-                                       start_migratetype);
-               /*
-                * The pcppage_migratetype may differ from pageblock's
-                * migratetype depending on the decisions in
-                * find_suitable_fallback(). This is OK as long as it does not
-                * differ for MIGRATE_CMA pageblocks. Those can be used as
-                * fallback only via special __rmqueue_cma_fallback() function
-                */
-               set_pcppage_migratetype(page, start_migratetype);
+               steal_suitable_fallback(zone, page, start_migratetype,
+                                                               can_steal);
 
                trace_mm_page_alloc_extfrag(page, order, current_order,
                        start_migratetype, fallback_mt);
 
-               return page;
+               return true;
        }
 
-       return NULL;
+       return false;
 }
 
 /*
@@ -2182,13 +2237,14 @@ static struct page *__rmqueue(struct zone *zone, unsigned int order,
 {
        struct page *page;
 
+retry:
        page = __rmqueue_smallest(zone, order, migratetype);
        if (unlikely(!page)) {
                if (migratetype == MIGRATE_MOVABLE)
                        page = __rmqueue_cma_fallback(zone, order);
 
-               if (!page)
-                       page = __rmqueue_fallback(zone, order, migratetype);
+               if (!page && __rmqueue_fallback(zone, order, migratetype))
+                       goto retry;
        }
 
        trace_mm_page_alloc_zone_locked(page, order, migratetype);
@@ -3227,14 +3283,15 @@ __alloc_pages_direct_compact(gfp_t gfp_mask, unsigned int order,
                enum compact_priority prio, enum compact_result *compact_result)
 {
        struct page *page;
+       unsigned int noreclaim_flag;
 
        if (!order)
                return NULL;
 
-       current->flags |= PF_MEMALLOC;
+       noreclaim_flag = memalloc_noreclaim_save();
        *compact_result = try_to_compact_pages(gfp_mask, order, alloc_flags, ac,
                                                                        prio);
-       current->flags &= ~PF_MEMALLOC;
+       memalloc_noreclaim_restore(noreclaim_flag);
 
        if (*compact_result <= COMPACT_INACTIVE)
                return NULL;
@@ -3381,12 +3438,13 @@ __perform_reclaim(gfp_t gfp_mask, unsigned int order,
 {
        struct reclaim_state reclaim_state;
        int progress;
+       unsigned int noreclaim_flag;
 
        cond_resched();
 
        /* We now go into synchronous reclaim */
        cpuset_memory_pressure_bump();
-       current->flags |= PF_MEMALLOC;
+       noreclaim_flag = memalloc_noreclaim_save();
        lockdep_set_current_reclaim_state(gfp_mask);
        reclaim_state.reclaimed_slab = 0;
        current->reclaim_state = &reclaim_state;
@@ -3396,7 +3454,7 @@ __perform_reclaim(gfp_t gfp_mask, unsigned int order,
 
        current->reclaim_state = NULL;
        lockdep_clear_current_reclaim_state();
-       current->flags &= ~PF_MEMALLOC;
+       memalloc_noreclaim_restore(noreclaim_flag);
 
        cond_resched();
 
@@ -3609,6 +3667,7 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
                                                struct alloc_context *ac)
 {
        bool can_direct_reclaim = gfp_mask & __GFP_DIRECT_RECLAIM;
+       const bool costly_order = order > PAGE_ALLOC_COSTLY_ORDER;
        struct page *page = NULL;
        unsigned int alloc_flags;
        unsigned long did_some_progress;
@@ -3676,12 +3735,17 @@ retry_cpuset:
 
        /*
         * For costly allocations, try direct compaction first, as it's likely
-        * that we have enough base pages and don't need to reclaim. Don't try
-        * that for allocations that are allowed to ignore watermarks, as the
-        * ALLOC_NO_WATERMARKS attempt didn't yet happen.
+        * that we have enough base pages and don't need to reclaim. For non-
+        * movable high-order allocations, do that as well, as compaction will
+        * try prevent permanent fragmentation by migrating from blocks of the
+        * same migratetype.
+        * Don't try this for allocations that are allowed to ignore
+        * watermarks, as the ALLOC_NO_WATERMARKS attempt didn't yet happen.
         */
-       if (can_direct_reclaim && order > PAGE_ALLOC_COSTLY_ORDER &&
-               !gfp_pfmemalloc_allowed(gfp_mask)) {
+       if (can_direct_reclaim &&
+                       (costly_order ||
+                          (order > 0 && ac->migratetype != MIGRATE_MOVABLE))
+                       && !gfp_pfmemalloc_allowed(gfp_mask)) {
                page = __alloc_pages_direct_compact(gfp_mask, order,
                                                alloc_flags, ac,
                                                INIT_COMPACT_PRIORITY,
@@ -3693,7 +3757,7 @@ retry_cpuset:
                 * Checks for costly allocations with __GFP_NORETRY, which
                 * includes THP page fault allocations
                 */
-               if (gfp_mask & __GFP_NORETRY) {
+               if (costly_order && (gfp_mask & __GFP_NORETRY)) {
                        /*
                         * If compaction is deferred for high-order allocations,
                         * it is because sync compaction recently failed. If
@@ -3774,7 +3838,7 @@ retry:
         * Do not retry costly high order allocations unless they are
         * __GFP_REPEAT
         */
-       if (order > PAGE_ALLOC_COSTLY_ORDER && !(gfp_mask & __GFP_REPEAT))
+       if (costly_order && !(gfp_mask & __GFP_REPEAT))
                goto nopage;
 
        if (should_reclaim_retry(gfp_mask, order, ac, alloc_flags,
index 7927bbb54a4e3200e39fc098b787794f21f6c855..5092e4ef00c832fefb624a1d9d8f618402ad4402 100644 (file)
@@ -66,7 +66,8 @@ out:
 
                set_pageblock_migratetype(page, MIGRATE_ISOLATE);
                zone->nr_isolate_pageblock++;
-               nr_pages = move_freepages_block(zone, page, MIGRATE_ISOLATE);
+               nr_pages = move_freepages_block(zone, page, MIGRATE_ISOLATE,
+                                                                       NULL);
 
                __mod_zone_freepage_state(zone, -nr_pages, migratetype);
        }
@@ -120,7 +121,7 @@ static void unset_migratetype_isolate(struct page *page, unsigned migratetype)
         * pageblock scanning for freepage moving.
         */
        if (!isolated_page) {
-               nr_pages = move_freepages_block(zone, page, migratetype);
+               nr_pages = move_freepages_block(zone, page, migratetype, NULL);
                __mod_zone_freepage_state(zone, nr_pages, migratetype);
        }
        set_pageblock_migratetype(page, migratetype);
index 3ff241f714ebc066ce34a4d68381efcb303f4043..d405f0e0ee9651b40dceac3f45a851469b576e48 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -430,7 +430,7 @@ static void anon_vma_ctor(void *data)
 void __init anon_vma_init(void)
 {
        anon_vma_cachep = kmem_cache_create("anon_vma", sizeof(struct anon_vma),
-                       0, SLAB_DESTROY_BY_RCU|SLAB_PANIC|SLAB_ACCOUNT,
+                       0, SLAB_TYPESAFE_BY_RCU|SLAB_PANIC|SLAB_ACCOUNT,
                        anon_vma_ctor);
        anon_vma_chain_cachep = KMEM_CACHE(anon_vma_chain,
                        SLAB_PANIC|SLAB_ACCOUNT);
@@ -481,7 +481,7 @@ struct anon_vma *page_get_anon_vma(struct page *page)
         * If this page is still mapped, then its anon_vma cannot have been
         * freed.  But if it has been unmapped, we have no security against the
         * anon_vma structure being freed and reused (for another anon_vma:
-        * SLAB_DESTROY_BY_RCU guarantees that - so the atomic_inc_not_zero()
+        * SLAB_TYPESAFE_BY_RCU guarantees that - so the atomic_inc_not_zero()
         * above cannot corrupt).
         */
        if (!page_mapped(page)) {
index 1880d482a0cbeb0174c9a55d45b842ab2d36685f..2a31ee3c5814f192234385303a0d86cc77790580 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -1728,7 +1728,7 @@ static void slab_destroy(struct kmem_cache *cachep, struct page *page)
 
        freelist = page->freelist;
        slab_destroy_debugcheck(cachep, page);
-       if (unlikely(cachep->flags & SLAB_DESTROY_BY_RCU))
+       if (unlikely(cachep->flags & SLAB_TYPESAFE_BY_RCU))
                call_rcu(&page->rcu_head, kmem_rcu_free);
        else
                kmem_freepages(cachep, page);
@@ -1924,7 +1924,7 @@ static bool set_objfreelist_slab_cache(struct kmem_cache *cachep,
 
        cachep->num = 0;
 
-       if (cachep->ctor || flags & SLAB_DESTROY_BY_RCU)
+       if (cachep->ctor || flags & SLAB_TYPESAFE_BY_RCU)
                return false;
 
        left = calculate_slab_order(cachep, size,
@@ -2030,7 +2030,7 @@ __kmem_cache_create (struct kmem_cache *cachep, unsigned long flags)
        if (size < 4096 || fls(size - 1) == fls(size-1 + REDZONE_ALIGN +
                                                2 * sizeof(unsigned long long)))
                flags |= SLAB_RED_ZONE | SLAB_STORE_USER;
-       if (!(flags & SLAB_DESTROY_BY_RCU))
+       if (!(flags & SLAB_TYPESAFE_BY_RCU))
                flags |= SLAB_POISON;
 #endif
 #endif
index 65e7c3fcac72790acece0ac140d864151f95f166..9cfcf099709c19cfc8b5070325a0527c763eddaa 100644 (file)
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -126,7 +126,7 @@ static inline unsigned long kmem_cache_flags(unsigned long object_size,
 
 /* Legal flag mask for kmem_cache_create(), for various configurations */
 #define SLAB_CORE_FLAGS (SLAB_HWCACHE_ALIGN | SLAB_CACHE_DMA | SLAB_PANIC | \
-                        SLAB_DESTROY_BY_RCU | SLAB_DEBUG_OBJECTS )
+                        SLAB_TYPESAFE_BY_RCU | SLAB_DEBUG_OBJECTS )
 
 #if defined(CONFIG_DEBUG_SLAB)
 #define SLAB_DEBUG_FLAGS (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER)
@@ -415,7 +415,7 @@ static inline size_t slab_ksize(const struct kmem_cache *s)
         * back there or track user information then we can
         * only use the space before that information.
         */
-       if (s->flags & (SLAB_DESTROY_BY_RCU | SLAB_STORE_USER))
+       if (s->flags & (SLAB_TYPESAFE_BY_RCU | SLAB_STORE_USER))
                return s->inuse;
        /*
         * Else we can use all the padding etc for the allocation
index 09d0e849b07f47d82f5d9a5cda4862517d297cb2..01a0fe2eb33267f8f04f7e90fd79358cd1f41d07 100644 (file)
@@ -39,7 +39,7 @@ static DECLARE_WORK(slab_caches_to_rcu_destroy_work,
  * Set of flags that will prevent slab merging
  */
 #define SLAB_NEVER_MERGE (SLAB_RED_ZONE | SLAB_POISON | SLAB_STORE_USER | \
-               SLAB_TRACE | SLAB_DESTROY_BY_RCU | SLAB_NOLEAKTRACE | \
+               SLAB_TRACE | SLAB_TYPESAFE_BY_RCU | SLAB_NOLEAKTRACE | \
                SLAB_FAILSLAB | SLAB_KASAN)
 
 #define SLAB_MERGE_SAME (SLAB_RECLAIM_ACCOUNT | SLAB_CACHE_DMA | \
@@ -500,7 +500,7 @@ static void slab_caches_to_rcu_destroy_workfn(struct work_struct *work)
        struct kmem_cache *s, *s2;
 
        /*
-        * On destruction, SLAB_DESTROY_BY_RCU kmem_caches are put on the
+        * On destruction, SLAB_TYPESAFE_BY_RCU kmem_caches are put on the
         * @slab_caches_to_rcu_destroy list.  The slab pages are freed
         * through RCU and and the associated kmem_cache are dereferenced
         * while freeing the pages, so the kmem_caches should be freed only
@@ -537,7 +537,7 @@ static int shutdown_cache(struct kmem_cache *s)
        memcg_unlink_cache(s);
        list_del(&s->list);
 
-       if (s->flags & SLAB_DESTROY_BY_RCU) {
+       if (s->flags & SLAB_TYPESAFE_BY_RCU) {
                list_add_tail(&s->list, &slab_caches_to_rcu_destroy);
                schedule_work(&slab_caches_to_rcu_destroy_work);
        } else {
index eac04d4357ec6b8d653de4c30c96ffdd97974462..1bae78d71096ad26bbe4575f631f3fad7b694388 100644 (file)
--- a/mm/slob.c
+++ b/mm/slob.c
@@ -126,7 +126,7 @@ static inline void clear_slob_page_free(struct page *sp)
 
 /*
  * struct slob_rcu is inserted at the tail of allocated slob blocks, which
- * were created with a SLAB_DESTROY_BY_RCU slab. slob_rcu is used to free
+ * were created with a SLAB_TYPESAFE_BY_RCU slab. slob_rcu is used to free
  * the block using call_rcu.
  */
 struct slob_rcu {
@@ -524,7 +524,7 @@ EXPORT_SYMBOL(ksize);
 
 int __kmem_cache_create(struct kmem_cache *c, unsigned long flags)
 {
-       if (flags & SLAB_DESTROY_BY_RCU) {
+       if (flags & SLAB_TYPESAFE_BY_RCU) {
                /* leave room for rcu footer at the end of object */
                c->size += sizeof(struct slob_rcu);
        }
@@ -598,7 +598,7 @@ static void kmem_rcu_free(struct rcu_head *head)
 void kmem_cache_free(struct kmem_cache *c, void *b)
 {
        kmemleak_free_recursive(b, c->flags);
-       if (unlikely(c->flags & SLAB_DESTROY_BY_RCU)) {
+       if (unlikely(c->flags & SLAB_TYPESAFE_BY_RCU)) {
                struct slob_rcu *slob_rcu;
                slob_rcu = b + (c->size - sizeof(struct slob_rcu));
                slob_rcu->size = c->size;
index 7f4bc7027ed53536efaaf5663f007bd2442de503..57e5156f02be6bcc23e70ec801e9cc1c3bbdd631 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1687,7 +1687,7 @@ static void rcu_free_slab(struct rcu_head *h)
 
 static void free_slab(struct kmem_cache *s, struct page *page)
 {
-       if (unlikely(s->flags & SLAB_DESTROY_BY_RCU)) {
+       if (unlikely(s->flags & SLAB_TYPESAFE_BY_RCU)) {
                struct rcu_head *head;
 
                if (need_reserve_slab_rcu) {
@@ -2963,7 +2963,7 @@ static __always_inline void slab_free(struct kmem_cache *s, struct page *page,
         * slab_free_freelist_hook() could have put the items into quarantine.
         * If so, no need to free them.
         */
-       if (s->flags & SLAB_KASAN && !(s->flags & SLAB_DESTROY_BY_RCU))
+       if (s->flags & SLAB_KASAN && !(s->flags & SLAB_TYPESAFE_BY_RCU))
                return;
        do_slab_free(s, page, head, tail, cnt, addr);
 }
@@ -3433,7 +3433,7 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order)
         * the slab may touch the object after free or before allocation
         * then we should never poison the object itself.
         */
-       if ((flags & SLAB_POISON) && !(flags & SLAB_DESTROY_BY_RCU) &&
+       if ((flags & SLAB_POISON) && !(flags & SLAB_TYPESAFE_BY_RCU) &&
                        !s->ctor)
                s->flags |= __OBJECT_POISON;
        else
@@ -3455,7 +3455,7 @@ static int calculate_sizes(struct kmem_cache *s, int forced_order)
         */
        s->inuse = size;
 
-       if (((flags & (SLAB_DESTROY_BY_RCU | SLAB_POISON)) ||
+       if (((flags & (SLAB_TYPESAFE_BY_RCU | SLAB_POISON)) ||
                s->ctor)) {
                /*
                 * Relocate free pointer after the object if it is not
@@ -3537,7 +3537,7 @@ static int kmem_cache_open(struct kmem_cache *s, unsigned long flags)
        s->flags = kmem_cache_flags(s->size, flags, s->name, s->ctor);
        s->reserved = 0;
 
-       if (need_reserve_slab_rcu && (s->flags & SLAB_DESTROY_BY_RCU))
+       if (need_reserve_slab_rcu && (s->flags & SLAB_TYPESAFE_BY_RCU))
                s->reserved = sizeof(struct rcu_head);
 
        if (!calculate_sizes(s, -1))
@@ -5042,7 +5042,7 @@ SLAB_ATTR_RO(cache_dma);
 
 static ssize_t destroy_by_rcu_show(struct kmem_cache *s, char *buf)
 {
-       return sprintf(buf, "%d\n", !!(s->flags & SLAB_DESTROY_BY_RCU));
+       return sprintf(buf, "%d\n", !!(s->flags & SLAB_TYPESAFE_BY_RCU));
 }
 SLAB_ATTR_RO(destroy_by_rcu);
 
index aa1c415f4abd6785ee7ee5d6f3f56ab74cd7bc60..58f6c78f1dad313dc7aa9b2ec31ddab361335fe1 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/cpumask.h>
 #include <linux/vmalloc.h>
 #include <linux/mutex.h>
+#include <linux/mm.h>
 
 #ifdef CONFIG_SWAP
 
@@ -119,16 +120,18 @@ static int alloc_swap_slot_cache(unsigned int cpu)
 
        /*
         * Do allocation outside swap_slots_cache_mutex
-        * as vzalloc could trigger reclaim and get_swap_page,
+        * as kvzalloc could trigger reclaim and get_swap_page,
         * which can lock swap_slots_cache_mutex.
         */
-       slots = vzalloc(sizeof(swp_entry_t) * SWAP_SLOTS_CACHE_SIZE);
+       slots = kvzalloc(sizeof(swp_entry_t) * SWAP_SLOTS_CACHE_SIZE,
+                        GFP_KERNEL);
        if (!slots)
                return -ENOMEM;
 
-       slots_ret = vzalloc(sizeof(swp_entry_t) * SWAP_SLOTS_CACHE_SIZE);
+       slots_ret = kvzalloc(sizeof(swp_entry_t) * SWAP_SLOTS_CACHE_SIZE,
+                            GFP_KERNEL);
        if (!slots_ret) {
-               vfree(slots);
+               kvfree(slots);
                return -ENOMEM;
        }
 
@@ -152,9 +155,9 @@ static int alloc_swap_slot_cache(unsigned int cpu)
 out:
        mutex_unlock(&swap_slots_cache_mutex);
        if (slots)
-               vfree(slots);
+               kvfree(slots);
        if (slots_ret)
-               vfree(slots_ret);
+               kvfree(slots_ret);
        return 0;
 }
 
@@ -171,7 +174,7 @@ static void drain_slots_cache_cpu(unsigned int cpu, unsigned int type,
                cache->cur = 0;
                cache->nr = 0;
                if (free_slots && cache->slots) {
-                       vfree(cache->slots);
+                       kvfree(cache->slots);
                        cache->slots = NULL;
                }
                mutex_unlock(&cache->alloc_lock);
@@ -186,7 +189,7 @@ static void drain_slots_cache_cpu(unsigned int cpu, unsigned int type,
                }
                spin_unlock_irq(&cache->free_lock);
                if (slots)
-                       vfree(slots);
+                       kvfree(slots);
        }
 }
 
index 7bfb9bd1ca211ef0682085b99e9723cfeab9b5fe..539b8885e3d1d4942dbb905b60b87d40726e3de5 100644 (file)
@@ -523,7 +523,7 @@ int init_swap_address_space(unsigned int type, unsigned long nr_pages)
        unsigned int i, nr;
 
        nr = DIV_ROUND_UP(nr_pages, SWAP_ADDRESS_SPACE_PAGES);
-       spaces = vzalloc(sizeof(struct address_space) * nr);
+       spaces = kvzalloc(sizeof(struct address_space) * nr, GFP_KERNEL);
        if (!spaces)
                return -ENOMEM;
        for (i = 0; i < nr; i++) {
index b86b2aca3fb9b10321ea8f6770c7d10905724b2d..4f6cba1b66322f3500714950ef3a12eeda9e4455 100644 (file)
@@ -2270,8 +2270,8 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
        free_percpu(p->percpu_cluster);
        p->percpu_cluster = NULL;
        vfree(swap_map);
-       vfree(cluster_info);
-       vfree(frontswap_map);
+       kvfree(cluster_info);
+       kvfree(frontswap_map);
        /* Destroy swap account information */
        swap_cgroup_swapoff(p->type);
        exit_swap_address_space(p->type);
@@ -2794,7 +2794,8 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
                p->cluster_next = 1 + (prandom_u32() % p->highest_bit);
                nr_cluster = DIV_ROUND_UP(maxpages, SWAPFILE_CLUSTER);
 
-               cluster_info = vzalloc(nr_cluster * sizeof(*cluster_info));
+               cluster_info = kvzalloc(nr_cluster * sizeof(*cluster_info),
+                                       GFP_KERNEL);
                if (!cluster_info) {
                        error = -ENOMEM;
                        goto bad_swap;
@@ -2827,7 +2828,8 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
        }
        /* frontswap enabled? set up bit-per-page map for frontswap */
        if (IS_ENABLED(CONFIG_FRONTSWAP))
-               frontswap_map = vzalloc(BITS_TO_LONGS(maxpages) * sizeof(long));
+               frontswap_map = kvzalloc(BITS_TO_LONGS(maxpages) * sizeof(long),
+                                        GFP_KERNEL);
 
        if (p->bdev &&(swap_flags & SWAP_FLAG_DISCARD) && swap_discardable(p)) {
                /*
index 83a059e8cd1de2c950dfc4ad790fcf1140df34b6..6479ed2afc53fb9dd8d9719051ea77e7a5b200af 100644 (file)
@@ -67,17 +67,14 @@ static void truncate_exceptional_entry(struct address_space *mapping,
 
 /*
  * Invalidate exceptional entry if easily possible. This handles exceptional
- * entries for invalidate_inode_pages() so for DAX it evicts only unlocked and
- * clean entries.
+ * entries for invalidate_inode_pages().
  */
 static int invalidate_exceptional_entry(struct address_space *mapping,
                                        pgoff_t index, void *entry)
 {
-       /* Handled by shmem itself */
-       if (shmem_mapping(mapping))
+       /* Handled by shmem itself, or for DAX we do nothing. */
+       if (shmem_mapping(mapping) || dax_mapping(mapping))
                return 1;
-       if (dax_mapping(mapping))
-               return dax_invalidate_mapping_entry(mapping, index);
        clear_shadow_entry(mapping, index, entry);
        return 1;
 }
@@ -689,7 +686,17 @@ int invalidate_inode_pages2_range(struct address_space *mapping,
                cond_resched();
                index++;
        }
-
+       /*
+        * For DAX we invalidate page tables after invalidating radix tree.  We
+        * could invalidate page tables while invalidating each entry however
+        * that would be expensive. And doing range unmapping before doesn't
+        * work as we have no cheap way to find whether radix tree entry didn't
+        * get remapped later.
+        */
+       if (dax_mapping(mapping)) {
+               unmap_mapping_range(mapping, (loff_t)start << PAGE_SHIFT,
+                                   (loff_t)(end - start + 1) << PAGE_SHIFT, 0);
+       }
 out:
        cleancache_invalidate_inode(mapping);
        return ret;
index 656dc5e37a8721e892d1b2fd0a9f8c1808b17a2d..464df34899031d46058b7cbadc1c3be24ae8dc89 100644 (file)
--- a/mm/util.c
+++ b/mm/util.c
@@ -329,6 +329,64 @@ unsigned long vm_mmap(struct file *file, unsigned long addr,
 }
 EXPORT_SYMBOL(vm_mmap);
 
+/**
+ * kvmalloc_node - attempt to allocate physically contiguous memory, but upon
+ * failure, fall back to non-contiguous (vmalloc) allocation.
+ * @size: size of the request.
+ * @flags: gfp mask for the allocation - must be compatible (superset) with GFP_KERNEL.
+ * @node: numa node to allocate from
+ *
+ * Uses kmalloc to get the memory but if the allocation fails then falls back
+ * to the vmalloc allocator. Use kvfree for freeing the memory.
+ *
+ * Reclaim modifiers - __GFP_NORETRY and __GFP_NOFAIL are not supported. __GFP_REPEAT
+ * is supported only for large (>32kB) allocations, and it should be used only if
+ * kmalloc is preferable to the vmalloc fallback, due to visible performance drawbacks.
+ *
+ * Any use of gfp flags outside of GFP_KERNEL should be consulted with mm people.
+ */
+void *kvmalloc_node(size_t size, gfp_t flags, int node)
+{
+       gfp_t kmalloc_flags = flags;
+       void *ret;
+
+       /*
+        * vmalloc uses GFP_KERNEL for some internal allocations (e.g page tables)
+        * so the given set of flags has to be compatible.
+        */
+       WARN_ON_ONCE((flags & GFP_KERNEL) != GFP_KERNEL);
+
+       /*
+        * Make sure that larger requests are not too disruptive - no OOM
+        * killer and no allocation failure warnings as we have a fallback
+        */
+       if (size > PAGE_SIZE) {
+               kmalloc_flags |= __GFP_NOWARN;
+
+               /*
+                * We have to override __GFP_REPEAT by __GFP_NORETRY for !costly
+                * requests because there is no other way to tell the allocator
+                * that we want to fail rather than retry endlessly.
+                */
+               if (!(kmalloc_flags & __GFP_REPEAT) ||
+                               (size <= PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER))
+                       kmalloc_flags |= __GFP_NORETRY;
+       }
+
+       ret = kmalloc_node(size, kmalloc_flags, node);
+
+       /*
+        * It doesn't really make sense to fallback to vmalloc for sub page
+        * requests
+        */
+       if (ret || size <= PAGE_SIZE)
+               return ret;
+
+       return __vmalloc_node_flags_caller(size, node, flags,
+                       __builtin_return_address(0));
+}
+EXPORT_SYMBOL(kvmalloc_node);
+
 void kvfree(const void *addr)
 {
        if (is_vmalloc_addr(addr))
index b52aeed3f58eb735709578b7c557dad1fe8403e0..34a1c3e46ed72594b499e7f61e8aacdd4c5fe818 100644 (file)
@@ -521,7 +521,7 @@ overflow:
                }
        }
 
-       if (printk_ratelimit())
+       if (!(gfp_mask & __GFP_NOWARN) && printk_ratelimit())
                pr_warn("vmap allocation for size %lu failed: use vmalloc=<size> to increase size\n",
                        size);
        kfree(va);
@@ -1658,7 +1658,7 @@ static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask,
        struct page **pages;
        unsigned int nr_pages, array_size, i;
        const gfp_t nested_gfp = (gfp_mask & GFP_RECLAIM_MASK) | __GFP_ZERO;
-       const gfp_t alloc_mask = gfp_mask | __GFP_NOWARN;
+       const gfp_t alloc_mask = gfp_mask | __GFP_HIGHMEM | __GFP_NOWARN;
 
        nr_pages = get_vm_area_size(area) >> PAGE_SHIFT;
        array_size = (nr_pages * sizeof(struct page *));
@@ -1786,6 +1786,13 @@ fail:
  *     Allocate enough pages to cover @size from the page level
  *     allocator with @gfp_mask flags.  Map them into contiguous
  *     kernel virtual space, using a pagetable protection of @prot.
+ *
+ *     Reclaim modifiers in @gfp_mask - __GFP_NORETRY, __GFP_REPEAT
+ *     and __GFP_NOFAIL are not supported
+ *
+ *     Any use of gfp flags outside of GFP_KERNEL should be consulted
+ *     with mm people.
+ *
  */
 static void *__vmalloc_node(unsigned long size, unsigned long align,
                            gfp_t gfp_mask, pgprot_t prot,
@@ -1809,6 +1816,13 @@ static inline void *__vmalloc_node_flags(unsigned long size,
                                        node, __builtin_return_address(0));
 }
 
+
+void *__vmalloc_node_flags_caller(unsigned long size, int node, gfp_t flags,
+                                 void *caller)
+{
+       return __vmalloc_node(size, 1, flags, PAGE_KERNEL, node, caller);
+}
+
 /**
  *     vmalloc  -  allocate virtually contiguous memory
  *     @size:          allocation size
@@ -1821,7 +1835,7 @@ static inline void *__vmalloc_node_flags(unsigned long size,
 void *vmalloc(unsigned long size)
 {
        return __vmalloc_node_flags(size, NUMA_NO_NODE,
-                                   GFP_KERNEL | __GFP_HIGHMEM);
+                                   GFP_KERNEL);
 }
 EXPORT_SYMBOL(vmalloc);
 
@@ -1838,7 +1852,7 @@ EXPORT_SYMBOL(vmalloc);
 void *vzalloc(unsigned long size)
 {
        return __vmalloc_node_flags(size, NUMA_NO_NODE,
-                               GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO);
+                               GFP_KERNEL | __GFP_ZERO);
 }
 EXPORT_SYMBOL(vzalloc);
 
@@ -1855,7 +1869,7 @@ void *vmalloc_user(unsigned long size)
        void *ret;
 
        ret = __vmalloc_node(size, SHMLBA,
-                            GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO,
+                            GFP_KERNEL | __GFP_ZERO,
                             PAGE_KERNEL, NUMA_NO_NODE,
                             __builtin_return_address(0));
        if (ret) {
@@ -1879,7 +1893,7 @@ EXPORT_SYMBOL(vmalloc_user);
  */
 void *vmalloc_node(unsigned long size, int node)
 {
-       return __vmalloc_node(size, 1, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL,
+       return __vmalloc_node(size, 1, GFP_KERNEL, PAGE_KERNEL,
                                        node, __builtin_return_address(0));
 }
 EXPORT_SYMBOL(vmalloc_node);
@@ -1899,7 +1913,7 @@ EXPORT_SYMBOL(vmalloc_node);
 void *vzalloc_node(unsigned long size, int node)
 {
        return __vmalloc_node_flags(size, node,
-                        GFP_KERNEL | __GFP_HIGHMEM | __GFP_ZERO);
+                        GFP_KERNEL | __GFP_ZERO);
 }
 EXPORT_SYMBOL(vzalloc_node);
 
@@ -1921,7 +1935,7 @@ EXPORT_SYMBOL(vzalloc_node);
 
 void *vmalloc_exec(unsigned long size)
 {
-       return __vmalloc_node(size, 1, GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL_EXEC,
+       return __vmalloc_node(size, 1, GFP_KERNEL, PAGE_KERNEL_EXEC,
                              NUMA_NO_NODE, __builtin_return_address(0));
 }
 
index 4e7ed65842aff72beb90815262dacd29987cbcf8..8ad39bbc79e67eaff24c42201ae2470ffc21d0a7 100644 (file)
@@ -1449,7 +1449,7 @@ static __always_inline void update_lru_sizes(struct lruvec *lruvec,
  *
  * Appropriate locks must be held before calling this function.
  *
- * @nr_to_scan:        The number of pages to look through on the list.
+ * @nr_to_scan:        The number of eligible pages to look through on the list.
  * @lruvec:    The LRU vector to pull pages from.
  * @dst:       The temp list to put pages on to.
  * @nr_scanned:        The number of pages that were scanned.
@@ -1469,11 +1469,13 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
        unsigned long nr_zone_taken[MAX_NR_ZONES] = { 0 };
        unsigned long nr_skipped[MAX_NR_ZONES] = { 0, };
        unsigned long skipped = 0;
-       unsigned long scan, nr_pages;
+       unsigned long scan, total_scan, nr_pages;
        LIST_HEAD(pages_skipped);
 
-       for (scan = 0; scan < nr_to_scan && nr_taken < nr_to_scan &&
-                                       !list_empty(src); scan++) {
+       scan = 0;
+       for (total_scan = 0;
+            scan < nr_to_scan && nr_taken < nr_to_scan && !list_empty(src);
+            total_scan++) {
                struct page *page;
 
                page = lru_to_page(src);
@@ -1487,6 +1489,13 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
                        continue;
                }
 
+               /*
+                * Do not count skipped pages because that makes the function
+                * return with no isolated pages if the LRU mostly contains
+                * ineligible pages.  This causes the VM to not reclaim any
+                * pages, triggering a premature OOM.
+                */
+               scan++;
                switch (__isolate_lru_page(page, mode)) {
                case 0:
                        nr_pages = hpage_nr_pages(page);
@@ -1524,9 +1533,9 @@ static unsigned long isolate_lru_pages(unsigned long nr_to_scan,
                        skipped += nr_skipped[zid];
                }
        }
-       *nr_scanned = scan;
+       *nr_scanned = total_scan;
        trace_mm_vmscan_lru_isolate(sc->reclaim_idx, sc->order, nr_to_scan,
-                                   scan, skipped, nr_taken, mode, lru);
+                                   total_scan, skipped, nr_taken, mode, lru);
        update_lru_sizes(lruvec, lru, nr_zone_taken);
        return nr_taken;
 }
@@ -3036,6 +3045,7 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *memcg,
        struct zonelist *zonelist;
        unsigned long nr_reclaimed;
        int nid;
+       unsigned int noreclaim_flag;
        struct scan_control sc = {
                .nr_to_reclaim = max(nr_pages, SWAP_CLUSTER_MAX),
                .gfp_mask = (current_gfp_context(gfp_mask) & GFP_RECLAIM_MASK) |
@@ -3062,9 +3072,9 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *memcg,
                                            sc.gfp_mask,
                                            sc.reclaim_idx);
 
-       current->flags |= PF_MEMALLOC;
+       noreclaim_flag = memalloc_noreclaim_save();
        nr_reclaimed = do_try_to_free_pages(zonelist, &sc);
-       current->flags &= ~PF_MEMALLOC;
+       memalloc_noreclaim_restore(noreclaim_flag);
 
        trace_mm_vmscan_memcg_reclaim_end(nr_reclaimed);
 
@@ -3589,8 +3599,9 @@ unsigned long shrink_all_memory(unsigned long nr_to_reclaim)
        struct zonelist *zonelist = node_zonelist(numa_node_id(), sc.gfp_mask);
        struct task_struct *p = current;
        unsigned long nr_reclaimed;
+       unsigned int noreclaim_flag;
 
-       p->flags |= PF_MEMALLOC;
+       noreclaim_flag = memalloc_noreclaim_save();
        lockdep_set_current_reclaim_state(sc.gfp_mask);
        reclaim_state.reclaimed_slab = 0;
        p->reclaim_state = &reclaim_state;
@@ -3599,7 +3610,7 @@ unsigned long shrink_all_memory(unsigned long nr_to_reclaim)
 
        p->reclaim_state = NULL;
        lockdep_clear_current_reclaim_state();
-       p->flags &= ~PF_MEMALLOC;
+       memalloc_noreclaim_restore(noreclaim_flag);
 
        return nr_reclaimed;
 }
@@ -3764,6 +3775,7 @@ static int __node_reclaim(struct pglist_data *pgdat, gfp_t gfp_mask, unsigned in
        struct task_struct *p = current;
        struct reclaim_state reclaim_state;
        int classzone_idx = gfp_zone(gfp_mask);
+       unsigned int noreclaim_flag;
        struct scan_control sc = {
                .nr_to_reclaim = max(nr_pages, SWAP_CLUSTER_MAX),
                .gfp_mask = (gfp_mask = current_gfp_context(gfp_mask)),
@@ -3781,7 +3793,8 @@ static int __node_reclaim(struct pglist_data *pgdat, gfp_t gfp_mask, unsigned in
         * and we also need to be able to write out pages for RECLAIM_WRITE
         * and RECLAIM_UNMAP.
         */
-       p->flags |= PF_MEMALLOC | PF_SWAPWRITE;
+       noreclaim_flag = memalloc_noreclaim_save();
+       p->flags |= PF_SWAPWRITE;
        lockdep_set_current_reclaim_state(gfp_mask);
        reclaim_state.reclaimed_slab = 0;
        p->reclaim_state = &reclaim_state;
@@ -3797,7 +3810,8 @@ static int __node_reclaim(struct pglist_data *pgdat, gfp_t gfp_mask, unsigned in
        }
 
        p->reclaim_state = NULL;
-       current->flags &= ~(PF_MEMALLOC | PF_SWAPWRITE);
+       current->flags &= ~PF_SWAPWRITE;
+       memalloc_noreclaim_restore(noreclaim_flag);
        lockdep_clear_current_reclaim_state();
        return sc.nr_reclaimed >= nr_pages;
 }
index f5fa1bd1eb1656cb4e608bd301c83e92f66ac3b2..76f73670200ac1d34b5f17388df8356fadffaf71 100644 (file)
@@ -1359,8 +1359,6 @@ static bool is_zone_first_populated(pg_data_t *pgdat, struct zone *zone)
                        return zone == compare;
        }
 
-       /* The zone must be somewhere! */
-       WARN_ON_ONCE(1);
        return false;
 }
 
index 9ee5787634e59690d67cb8fa148e03b18d455c99..953b6728bd00c8ca7a4a20f2d2036c6f8f27f8e3 100644 (file)
@@ -626,11 +626,18 @@ static netdev_features_t vlan_dev_fix_features(struct net_device *dev,
 {
        struct net_device *real_dev = vlan_dev_priv(dev)->real_dev;
        netdev_features_t old_features = features;
+       netdev_features_t lower_features;
 
-       features = netdev_intersect_features(features, real_dev->vlan_features);
-       features |= NETIF_F_RXCSUM;
-       features = netdev_intersect_features(features, real_dev->features);
+       lower_features = netdev_intersect_features((real_dev->vlan_features |
+                                                   NETIF_F_RXCSUM),
+                                                  real_dev->features);
 
+       /* Add HW_CSUM setting to preserve user ability to control
+        * checksum offload on the vlan device.
+        */
+       if (lower_features & (NETIF_F_IP_CSUM|NETIF_F_IPV6_CSUM))
+               lower_features |= NETIF_F_HW_CSUM;
+       features = netdev_intersect_features(features, lower_features);
        features |= old_features & (NETIF_F_SOFT_FEATURES | NETIF_F_GSO_SOFTWARE);
        features |= NETIF_F_LLTX;
 
index 71e85643b3f96db09de3330263f556fedba65257..6ad3e043c6174ae97a82525688988e740d87fd29 100644 (file)
@@ -454,8 +454,8 @@ static int xen_9pfs_front_probe(struct xenbus_device *dev,
                        goto error_xenbus;
        }
        priv->tag = xenbus_read(xbt, dev->nodename, "tag", NULL);
-       if (!priv->tag) {
-               ret = -EINVAL;
+       if (IS_ERR(priv->tag)) {
+               ret = PTR_ERR(priv->tag);
                goto error_xenbus;
        }
        ret = xenbus_transaction_end(xbt, 0);
@@ -525,7 +525,7 @@ static struct xenbus_driver xen_9pfs_front_driver = {
        .otherend_changed = xen_9pfs_front_changed,
 };
 
-int p9_trans_xen_init(void)
+static int p9_trans_xen_init(void)
 {
        if (!xen_domain())
                return -ENODEV;
@@ -537,7 +537,7 @@ int p9_trans_xen_init(void)
 }
 module_init(p9_trans_xen_init);
 
-void p9_trans_xen_exit(void)
+static void p9_trans_xen_exit(void)
 {
        v9fs_unregister_trans(&p9_xen_trans);
        return xenbus_unregister_driver(&xen_9pfs_front_driver);
index a572db710d4eb68a03ba0d9d958f41f931aff6b9..574f78824d8a2ae53751bbe1849e53502bc575be 100644 (file)
@@ -133,6 +133,8 @@ static inline size_t br_port_info_size(void)
                + nla_total_size(1)     /* IFLA_BRPORT_MCAST_TO_UCAST */
                + nla_total_size(1)     /* IFLA_BRPORT_LEARNING */
                + nla_total_size(1)     /* IFLA_BRPORT_UNICAST_FLOOD */
+               + nla_total_size(1)     /* IFLA_BRPORT_MCAST_FLOOD */
+               + nla_total_size(1)     /* IFLA_BRPORT_BCAST_FLOOD */
                + nla_total_size(1)     /* IFLA_BRPORT_PROXYARP */
                + nla_total_size(1)     /* IFLA_BRPORT_PROXYARP_WIFI */
                + nla_total_size(1)     /* IFLA_BRPORT_VLAN_TUNNEL */
@@ -633,6 +635,8 @@ static const struct nla_policy br_port_policy[IFLA_BRPORT_MAX + 1] = {
        [IFLA_BRPORT_PROXYARP_WIFI] = { .type = NLA_U8 },
        [IFLA_BRPORT_MULTICAST_ROUTER] = { .type = NLA_U8 },
        [IFLA_BRPORT_MCAST_TO_UCAST] = { .type = NLA_U8 },
+       [IFLA_BRPORT_MCAST_FLOOD] = { .type = NLA_U8 },
+       [IFLA_BRPORT_BCAST_FLOOD] = { .type = NLA_U8 },
 };
 
 /* Change the state of the port and notify spanning tree */
@@ -831,6 +835,13 @@ static int br_validate(struct nlattr *tb[], struct nlattr *data[])
                        return -EPROTONOSUPPORT;
                }
        }
+
+       if (data[IFLA_BR_VLAN_DEFAULT_PVID]) {
+               __u16 defpvid = nla_get_u16(data[IFLA_BR_VLAN_DEFAULT_PVID]);
+
+               if (defpvid >= VLAN_VID_MASK)
+                       return -EINVAL;
+       }
 #endif
 
        return 0;
index 108533859a53292cde61a3cedd052a2579684e87..4fd02831beed20fb3d98475c7da2a0b4f2818513 100644 (file)
@@ -45,6 +45,17 @@ bool libceph_compatible(void *data)
 }
 EXPORT_SYMBOL(libceph_compatible);
 
+static int param_get_supported_features(char *buffer,
+                                       const struct kernel_param *kp)
+{
+       return sprintf(buffer, "0x%llx", CEPH_FEATURES_SUPPORTED_DEFAULT);
+}
+static const struct kernel_param_ops param_ops_supported_features = {
+       .get = param_get_supported_features,
+};
+module_param_cb(supported_features, &param_ops_supported_features, NULL,
+               S_IRUGO);
+
 /*
  * find filename portion of a path (/foo/bar/baz -> baz)
  */
@@ -187,7 +198,7 @@ void *ceph_kvmalloc(size_t size, gfp_t flags)
                        return ptr;
        }
 
-       return __vmalloc(size, flags | __GFP_HIGHMEM, PAGE_KERNEL);
+       return __vmalloc(size, flags, PAGE_KERNEL);
 }
 
 
@@ -596,9 +607,7 @@ EXPORT_SYMBOL(ceph_client_gid);
 /*
  * create a fresh client instance
  */
-struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private,
-                                      u64 supported_features,
-                                      u64 required_features)
+struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private)
 {
        struct ceph_client *client;
        struct ceph_entity_addr *myaddr = NULL;
@@ -615,14 +624,12 @@ struct ceph_client *ceph_create_client(struct ceph_options *opt, void *private,
        init_waitqueue_head(&client->auth_wq);
        client->auth_err = 0;
 
-       if (!ceph_test_opt(client, NOMSGAUTH))
-               required_features |= CEPH_FEATURE_MSG_AUTH;
-
        client->extra_mon_dispatch = NULL;
-       client->supported_features = CEPH_FEATURES_SUPPORTED_DEFAULT |
-               supported_features;
-       client->required_features = CEPH_FEATURES_REQUIRED_DEFAULT |
-               required_features;
+       client->supported_features = CEPH_FEATURES_SUPPORTED_DEFAULT;
+       client->required_features = CEPH_FEATURES_REQUIRED_DEFAULT;
+
+       if (!ceph_test_opt(client, NOMSGAUTH))
+               client->required_features |= CEPH_FEATURE_MSG_AUTH;
 
        /* msgr */
        if (ceph_test_opt(client, MYIP))
index b9233b9903990bd38721213ce287a8045debd8c7..08ada893f01e6acb61b5f91425539a33d7b2c0d4 100644 (file)
@@ -179,6 +179,57 @@ int ceph_cls_break_lock(struct ceph_osd_client *osdc,
 }
 EXPORT_SYMBOL(ceph_cls_break_lock);
 
+int ceph_cls_set_cookie(struct ceph_osd_client *osdc,
+                       struct ceph_object_id *oid,
+                       struct ceph_object_locator *oloc,
+                       char *lock_name, u8 type, char *old_cookie,
+                       char *tag, char *new_cookie)
+{
+       int cookie_op_buf_size;
+       int name_len = strlen(lock_name);
+       int old_cookie_len = strlen(old_cookie);
+       int tag_len = strlen(tag);
+       int new_cookie_len = strlen(new_cookie);
+       void *p, *end;
+       struct page *cookie_op_page;
+       int ret;
+
+       cookie_op_buf_size = name_len + sizeof(__le32) +
+                            old_cookie_len + sizeof(__le32) +
+                            tag_len + sizeof(__le32) +
+                            new_cookie_len + sizeof(__le32) +
+                            sizeof(u8) + CEPH_ENCODING_START_BLK_LEN;
+       if (cookie_op_buf_size > PAGE_SIZE)
+               return -E2BIG;
+
+       cookie_op_page = alloc_page(GFP_NOIO);
+       if (!cookie_op_page)
+               return -ENOMEM;
+
+       p = page_address(cookie_op_page);
+       end = p + cookie_op_buf_size;
+
+       /* encode cls_lock_set_cookie_op struct */
+       ceph_start_encoding(&p, 1, 1,
+                           cookie_op_buf_size - CEPH_ENCODING_START_BLK_LEN);
+       ceph_encode_string(&p, end, lock_name, name_len);
+       ceph_encode_8(&p, type);
+       ceph_encode_string(&p, end, old_cookie, old_cookie_len);
+       ceph_encode_string(&p, end, tag, tag_len);
+       ceph_encode_string(&p, end, new_cookie, new_cookie_len);
+
+       dout("%s lock_name %s type %d old_cookie %s tag %s new_cookie %s\n",
+            __func__, lock_name, type, old_cookie, tag, new_cookie);
+       ret = ceph_osdc_call(osdc, oid, oloc, "lock", "set_cookie",
+                            CEPH_OSD_FLAG_WRITE, cookie_op_page,
+                            cookie_op_buf_size, NULL, NULL);
+
+       dout("%s: status %d\n", __func__, ret);
+       __free_page(cookie_op_page);
+       return ret;
+}
+EXPORT_SYMBOL(ceph_cls_set_cookie);
+
 void ceph_free_lockers(struct ceph_locker *lockers, u32 num_lockers)
 {
        int i;
index c62b2b029a6e6fe66fa3440551d0602fc8c4123e..71ba13927b3d1726bd488403de8274478a956091 100644 (file)
@@ -62,7 +62,8 @@ static int osdmap_show(struct seq_file *s, void *p)
                return 0;
 
        down_read(&osdc->lock);
-       seq_printf(s, "epoch %d flags 0x%x\n", map->epoch, map->flags);
+       seq_printf(s, "epoch %u barrier %u flags 0x%x\n", map->epoch,
+                       osdc->epoch_barrier, map->flags);
 
        for (n = rb_first(&map->pg_pools); n; n = rb_next(n)) {
                struct ceph_pg_pool_info *pi =
@@ -177,9 +178,7 @@ static void dump_request(struct seq_file *s, struct ceph_osd_request *req)
        seq_printf(s, "%llu\t", req->r_tid);
        dump_target(s, &req->r_t);
 
-       seq_printf(s, "\t%d\t%u'%llu", req->r_attempts,
-                  le32_to_cpu(req->r_replay_version.epoch),
-                  le64_to_cpu(req->r_replay_version.version));
+       seq_printf(s, "\t%d", req->r_attempts);
 
        for (i = 0; i < req->r_num_ops; i++) {
                struct ceph_osd_req_op *op = &req->r_ops[i];
index f76bb333261384257490b0f5125207028e8352aa..5766a6c896c4fa7290fffdbee239701ca4e2eeef 100644 (file)
@@ -1386,8 +1386,9 @@ static void prepare_write_keepalive(struct ceph_connection *con)
        dout("prepare_write_keepalive %p\n", con);
        con_out_kvec_reset(con);
        if (con->peer_features & CEPH_FEATURE_MSGR_KEEPALIVE2) {
-               struct timespec now = CURRENT_TIME;
+               struct timespec now;
 
+               ktime_get_real_ts(&now);
                con_out_kvec_add(con, sizeof(tag_keepalive2), &tag_keepalive2);
                ceph_encode_timespec(&con->out_temp_keepalive2, &now);
                con_out_kvec_add(con, sizeof(con->out_temp_keepalive2),
@@ -3176,8 +3177,9 @@ bool ceph_con_keepalive_expired(struct ceph_connection *con,
 {
        if (interval > 0 &&
            (con->peer_features & CEPH_FEATURE_MSGR_KEEPALIVE2)) {
-               struct timespec now = CURRENT_TIME;
+               struct timespec now;
                struct timespec ts;
+               ktime_get_real_ts(&now);
                jiffies_to_timespec(interval, &ts);
                ts = timespec_add(con->last_keepalive_ack, ts);
                return timespec_compare(&now, &ts) >= 0;
index e15ea9e4c4955fbd697e545cedfdb7f7925c347e..924f07c36ddbc2864c7428723766d0a64729c7c4 100644 (file)
@@ -961,6 +961,7 @@ struct ceph_osd_request *ceph_osdc_new_request(struct ceph_osd_client *osdc,
                                       truncate_size, truncate_seq);
        }
 
+       req->r_abort_on_full = true;
        req->r_flags = flags;
        req->r_base_oloc.pool = layout->pool_id;
        req->r_base_oloc.pool_ns = ceph_try_get_string(layout->pool_ns);
@@ -1005,7 +1006,7 @@ static bool osd_registered(struct ceph_osd *osd)
  */
 static void osd_init(struct ceph_osd *osd)
 {
-       atomic_set(&osd->o_ref, 1);
+       refcount_set(&osd->o_ref, 1);
        RB_CLEAR_NODE(&osd->o_node);
        osd->o_requests = RB_ROOT;
        osd->o_linger_requests = RB_ROOT;
@@ -1050,9 +1051,9 @@ static struct ceph_osd *create_osd(struct ceph_osd_client *osdc, int onum)
 
 static struct ceph_osd *get_osd(struct ceph_osd *osd)
 {
-       if (atomic_inc_not_zero(&osd->o_ref)) {
-               dout("get_osd %p %d -> %d\n", osd, atomic_read(&osd->o_ref)-1,
-                    atomic_read(&osd->o_ref));
+       if (refcount_inc_not_zero(&osd->o_ref)) {
+               dout("get_osd %p %d -> %d\n", osd, refcount_read(&osd->o_ref)-1,
+                    refcount_read(&osd->o_ref));
                return osd;
        } else {
                dout("get_osd %p FAIL\n", osd);
@@ -1062,9 +1063,9 @@ static struct ceph_osd *get_osd(struct ceph_osd *osd)
 
 static void put_osd(struct ceph_osd *osd)
 {
-       dout("put_osd %p %d -> %d\n", osd, atomic_read(&osd->o_ref),
-            atomic_read(&osd->o_ref) - 1);
-       if (atomic_dec_and_test(&osd->o_ref)) {
+       dout("put_osd %p %d -> %d\n", osd, refcount_read(&osd->o_ref),
+            refcount_read(&osd->o_ref) - 1);
+       if (refcount_dec_and_test(&osd->o_ref)) {
                osd_cleanup(osd);
                kfree(osd);
        }
@@ -1297,8 +1298,9 @@ static bool target_should_be_paused(struct ceph_osd_client *osdc,
                       __pool_full(pi);
 
        WARN_ON(pi->id != t->base_oloc.pool);
-       return (t->flags & CEPH_OSD_FLAG_READ && pauserd) ||
-              (t->flags & CEPH_OSD_FLAG_WRITE && pausewr);
+       return ((t->flags & CEPH_OSD_FLAG_READ) && pauserd) ||
+              ((t->flags & CEPH_OSD_FLAG_WRITE) && pausewr) ||
+              (osdc->osdmap->epoch < osdc->epoch_barrier);
 }
 
 enum calc_target_result {
@@ -1503,9 +1505,10 @@ static void encode_request(struct ceph_osd_request *req, struct ceph_msg *msg)
        ceph_encode_32(&p, req->r_flags);
        ceph_encode_timespec(p, &req->r_mtime);
        p += sizeof(struct ceph_timespec);
-       /* aka reassert_version */
-       memcpy(p, &req->r_replay_version, sizeof(req->r_replay_version));
-       p += sizeof(req->r_replay_version);
+
+       /* reassert_version */
+       memset(p, 0, sizeof(struct ceph_eversion));
+       p += sizeof(struct ceph_eversion);
 
        /* oloc */
        ceph_start_encoding(&p, 5, 4,
@@ -1626,6 +1629,7 @@ static void maybe_request_map(struct ceph_osd_client *osdc)
                ceph_monc_renew_subs(&osdc->client->monc);
 }
 
+static void complete_request(struct ceph_osd_request *req, int err);
 static void send_map_check(struct ceph_osd_request *req);
 
 static void __submit_request(struct ceph_osd_request *req, bool wrlocked)
@@ -1635,6 +1639,7 @@ static void __submit_request(struct ceph_osd_request *req, bool wrlocked)
        enum calc_target_result ct_res;
        bool need_send = false;
        bool promoted = false;
+       bool need_abort = false;
 
        WARN_ON(req->r_tid);
        dout("%s req %p wrlocked %d\n", __func__, req, wrlocked);
@@ -1650,8 +1655,13 @@ again:
                goto promote;
        }
 
-       if ((req->r_flags & CEPH_OSD_FLAG_WRITE) &&
-           ceph_osdmap_flag(osdc, CEPH_OSDMAP_PAUSEWR)) {
+       if (osdc->osdmap->epoch < osdc->epoch_barrier) {
+               dout("req %p epoch %u barrier %u\n", req, osdc->osdmap->epoch,
+                    osdc->epoch_barrier);
+               req->r_t.paused = true;
+               maybe_request_map(osdc);
+       } else if ((req->r_flags & CEPH_OSD_FLAG_WRITE) &&
+                  ceph_osdmap_flag(osdc, CEPH_OSDMAP_PAUSEWR)) {
                dout("req %p pausewr\n", req);
                req->r_t.paused = true;
                maybe_request_map(osdc);
@@ -1669,6 +1679,8 @@ again:
                pr_warn_ratelimited("FULL or reached pool quota\n");
                req->r_t.paused = true;
                maybe_request_map(osdc);
+               if (req->r_abort_on_full)
+                       need_abort = true;
        } else if (!osd_homeless(osd)) {
                need_send = true;
        } else {
@@ -1685,6 +1697,8 @@ again:
        link_request(osd, req);
        if (need_send)
                send_request(req);
+       else if (need_abort)
+               complete_request(req, -ENOSPC);
        mutex_unlock(&osd->lock);
 
        if (ct_res == CALC_TARGET_POOL_DNE)
@@ -1799,6 +1813,97 @@ static void abort_request(struct ceph_osd_request *req, int err)
        complete_request(req, err);
 }
 
+static void update_epoch_barrier(struct ceph_osd_client *osdc, u32 eb)
+{
+       if (likely(eb > osdc->epoch_barrier)) {
+               dout("updating epoch_barrier from %u to %u\n",
+                               osdc->epoch_barrier, eb);
+               osdc->epoch_barrier = eb;
+               /* Request map if we're not to the barrier yet */
+               if (eb > osdc->osdmap->epoch)
+                       maybe_request_map(osdc);
+       }
+}
+
+void ceph_osdc_update_epoch_barrier(struct ceph_osd_client *osdc, u32 eb)
+{
+       down_read(&osdc->lock);
+       if (unlikely(eb > osdc->epoch_barrier)) {
+               up_read(&osdc->lock);
+               down_write(&osdc->lock);
+               update_epoch_barrier(osdc, eb);
+               up_write(&osdc->lock);
+       } else {
+               up_read(&osdc->lock);
+       }
+}
+EXPORT_SYMBOL(ceph_osdc_update_epoch_barrier);
+
+/*
+ * Drop all pending requests that are stalled waiting on a full condition to
+ * clear, and complete them with ENOSPC as the return code. Set the
+ * osdc->epoch_barrier to the latest map epoch that we've seen if any were
+ * cancelled.
+ */
+static void ceph_osdc_abort_on_full(struct ceph_osd_client *osdc)
+{
+       struct rb_node *n;
+       bool victims = false;
+
+       dout("enter abort_on_full\n");
+
+       if (!ceph_osdmap_flag(osdc, CEPH_OSDMAP_FULL) && !have_pool_full(osdc))
+               goto out;
+
+       /* Scan list and see if there is anything to abort */
+       for (n = rb_first(&osdc->osds); n; n = rb_next(n)) {
+               struct ceph_osd *osd = rb_entry(n, struct ceph_osd, o_node);
+               struct rb_node *m;
+
+               m = rb_first(&osd->o_requests);
+               while (m) {
+                       struct ceph_osd_request *req = rb_entry(m,
+                                       struct ceph_osd_request, r_node);
+                       m = rb_next(m);
+
+                       if (req->r_abort_on_full) {
+                               victims = true;
+                               break;
+                       }
+               }
+               if (victims)
+                       break;
+       }
+
+       if (!victims)
+               goto out;
+
+       /*
+        * Update the barrier to current epoch if it's behind that point,
+        * since we know we have some calls to be aborted in the tree.
+        */
+       update_epoch_barrier(osdc, osdc->osdmap->epoch);
+
+       for (n = rb_first(&osdc->osds); n; n = rb_next(n)) {
+               struct ceph_osd *osd = rb_entry(n, struct ceph_osd, o_node);
+               struct rb_node *m;
+
+               m = rb_first(&osd->o_requests);
+               while (m) {
+                       struct ceph_osd_request *req = rb_entry(m,
+                                       struct ceph_osd_request, r_node);
+                       m = rb_next(m);
+
+                       if (req->r_abort_on_full &&
+                           (ceph_osdmap_flag(osdc, CEPH_OSDMAP_FULL) ||
+                            pool_full(osdc, req->r_t.target_oloc.pool)))
+                               abort_request(req, -ENOSPC);
+               }
+       }
+out:
+       dout("return abort_on_full barrier=%u\n", osdc->epoch_barrier);
+}
+
 static void check_pool_dne(struct ceph_osd_request *req)
 {
        struct ceph_osd_client *osdc = req->r_osdc;
@@ -3252,11 +3357,13 @@ done:
        pausewr = ceph_osdmap_flag(osdc, CEPH_OSDMAP_PAUSEWR) ||
                  ceph_osdmap_flag(osdc, CEPH_OSDMAP_FULL) ||
                  have_pool_full(osdc);
-       if (was_pauserd || was_pausewr || pauserd || pausewr)
+       if (was_pauserd || was_pausewr || pauserd || pausewr ||
+           osdc->osdmap->epoch < osdc->epoch_barrier)
                maybe_request_map(osdc);
 
        kick_requests(osdc, &need_resend, &need_resend_linger);
 
+       ceph_osdc_abort_on_full(osdc);
        ceph_monc_got_map(&osdc->client->monc, CEPH_SUB_OSDMAP,
                          osdc->osdmap->epoch);
        up_write(&osdc->lock);
@@ -3574,7 +3681,7 @@ ceph_osdc_watch(struct ceph_osd_client *osdc,
        ceph_oid_copy(&lreq->t.base_oid, oid);
        ceph_oloc_copy(&lreq->t.base_oloc, oloc);
        lreq->t.flags = CEPH_OSD_FLAG_WRITE;
-       lreq->mtime = CURRENT_TIME;
+       ktime_get_real_ts(&lreq->mtime);
 
        lreq->reg_req = alloc_linger_request(lreq);
        if (!lreq->reg_req) {
@@ -3632,7 +3739,7 @@ int ceph_osdc_unwatch(struct ceph_osd_client *osdc,
        ceph_oid_copy(&req->r_base_oid, &lreq->t.base_oid);
        ceph_oloc_copy(&req->r_base_oloc, &lreq->t.base_oloc);
        req->r_flags = CEPH_OSD_FLAG_WRITE;
-       req->r_mtime = CURRENT_TIME;
+       ktime_get_real_ts(&req->r_mtime);
        osd_req_op_watch_init(req, 0, lreq->linger_id,
                              CEPH_OSD_WATCH_OP_UNWATCH);
 
@@ -4126,7 +4233,7 @@ void ceph_osdc_stop(struct ceph_osd_client *osdc)
                close_osd(osd);
        }
        up_write(&osdc->lock);
-       WARN_ON(atomic_read(&osdc->homeless_osd.o_ref) != 1);
+       WARN_ON(refcount_read(&osdc->homeless_osd.o_ref) != 1);
        osd_cleanup(&osdc->homeless_osd);
 
        WARN_ON(!list_empty(&osdc->osd_lru));
index 6864007e64fc3236f6d118f8a4a1869255bbba92..ce09f73be759c562cb9ffe093eb1c44350c8adde 100644 (file)
@@ -16,7 +16,7 @@ static void ceph_pagelist_unmap_tail(struct ceph_pagelist *pl)
 
 void ceph_pagelist_release(struct ceph_pagelist *pl)
 {
-       if (!atomic_dec_and_test(&pl->refcnt))
+       if (!refcount_dec_and_test(&pl->refcnt))
                return;
        ceph_pagelist_unmap_tail(pl);
        while (!list_empty(&pl->head)) {
index 705414e78ae0b05d2d1b8d5d8f8e8fbb6007bfb4..e14a5d038656f004da16aa044fdecca9d094a71b 100644 (file)
@@ -49,7 +49,7 @@ struct ceph_snap_context *ceph_create_snap_context(u32 snap_count,
        if (!snapc)
                return NULL;
 
-       atomic_set(&snapc->nref, 1);
+       refcount_set(&snapc->nref, 1);
        snapc->num_snaps = snap_count;
 
        return snapc;
@@ -59,7 +59,7 @@ EXPORT_SYMBOL(ceph_create_snap_context);
 struct ceph_snap_context *ceph_get_snap_context(struct ceph_snap_context *sc)
 {
        if (sc)
-               atomic_inc(&sc->nref);
+               refcount_inc(&sc->nref);
        return sc;
 }
 EXPORT_SYMBOL(ceph_get_snap_context);
@@ -68,7 +68,7 @@ void ceph_put_snap_context(struct ceph_snap_context *sc)
 {
        if (!sc)
                return;
-       if (atomic_dec_and_test(&sc->nref)) {
+       if (refcount_dec_and_test(&sc->nref)) {
                /*printk(" deleting snap_context %p\n", sc);*/
                kfree(sc);
        }
index d07aa5ffb511e408b166624d424130c5105560ca..fca407b4a6ea178d9224949bc57f89a26c97c5c1 100644 (file)
@@ -81,6 +81,7 @@
 #include <linux/hash.h>
 #include <linux/slab.h>
 #include <linux/sched.h>
+#include <linux/sched/mm.h>
 #include <linux/mutex.h>
 #include <linux/string.h>
 #include <linux/mm.h>
@@ -4235,7 +4236,7 @@ static int __netif_receive_skb(struct sk_buff *skb)
        int ret;
 
        if (sk_memalloc_socks() && skb_pfmemalloc(skb)) {
-               unsigned long pflags = current->flags;
+               unsigned int noreclaim_flag;
 
                /*
                 * PFMEMALLOC skbs are special, they should
@@ -4246,9 +4247,9 @@ static int __netif_receive_skb(struct sk_buff *skb)
                 * Use PF_MEMALLOC as this saves us from propagating the allocation
                 * context down to all allocation sites.
                 */
-               current->flags |= PF_MEMALLOC;
+               noreclaim_flag = memalloc_noreclaim_save();
                ret = __netif_receive_skb_core(skb, true);
-               current_restore_flags(pflags, PF_MEMALLOC);
+               memalloc_noreclaim_restore(noreclaim_flag);
        } else
                ret = __netif_receive_skb_core(skb, false);
 
@@ -6851,6 +6852,32 @@ int dev_change_proto_down(struct net_device *dev, bool proto_down)
 }
 EXPORT_SYMBOL(dev_change_proto_down);
 
+bool __dev_xdp_attached(struct net_device *dev, xdp_op_t xdp_op)
+{
+       struct netdev_xdp xdp;
+
+       memset(&xdp, 0, sizeof(xdp));
+       xdp.command = XDP_QUERY_PROG;
+
+       /* Query must always succeed. */
+       WARN_ON(xdp_op(dev, &xdp) < 0);
+       return xdp.prog_attached;
+}
+
+static int dev_xdp_install(struct net_device *dev, xdp_op_t xdp_op,
+                          struct netlink_ext_ack *extack,
+                          struct bpf_prog *prog)
+{
+       struct netdev_xdp xdp;
+
+       memset(&xdp, 0, sizeof(xdp));
+       xdp.command = XDP_SETUP_PROG;
+       xdp.extack = extack;
+       xdp.prog = prog;
+
+       return xdp_op(dev, &xdp);
+}
+
 /**
  *     dev_change_xdp_fd - set or clear a bpf program for a device rx path
  *     @dev: device
@@ -6863,41 +6890,34 @@ EXPORT_SYMBOL(dev_change_proto_down);
 int dev_change_xdp_fd(struct net_device *dev, struct netlink_ext_ack *extack,
                      int fd, u32 flags)
 {
-       int (*xdp_op)(struct net_device *dev, struct netdev_xdp *xdp);
        const struct net_device_ops *ops = dev->netdev_ops;
        struct bpf_prog *prog = NULL;
-       struct netdev_xdp xdp;
+       xdp_op_t xdp_op, xdp_chk;
        int err;
 
        ASSERT_RTNL();
 
-       xdp_op = ops->ndo_xdp;
+       xdp_op = xdp_chk = ops->ndo_xdp;
+       if (!xdp_op && (flags & XDP_FLAGS_DRV_MODE))
+               return -EOPNOTSUPP;
        if (!xdp_op || (flags & XDP_FLAGS_SKB_MODE))
                xdp_op = generic_xdp_install;
+       if (xdp_op == xdp_chk)
+               xdp_chk = generic_xdp_install;
 
        if (fd >= 0) {
-               if (flags & XDP_FLAGS_UPDATE_IF_NOEXIST) {
-                       memset(&xdp, 0, sizeof(xdp));
-                       xdp.command = XDP_QUERY_PROG;
-
-                       err = xdp_op(dev, &xdp);
-                       if (err < 0)
-                               return err;
-                       if (xdp.prog_attached)
-                               return -EBUSY;
-               }
+               if (xdp_chk && __dev_xdp_attached(dev, xdp_chk))
+                       return -EEXIST;
+               if ((flags & XDP_FLAGS_UPDATE_IF_NOEXIST) &&
+                   __dev_xdp_attached(dev, xdp_op))
+                       return -EBUSY;
 
                prog = bpf_prog_get_type(fd, BPF_PROG_TYPE_XDP);
                if (IS_ERR(prog))
                        return PTR_ERR(prog);
        }
 
-       memset(&xdp, 0, sizeof(xdp));
-       xdp.command = XDP_SETUP_PROG;
-       xdp.extack = extack;
-       xdp.prog = prog;
-
-       err = xdp_op(dev, &xdp);
+       err = dev_xdp_install(dev, xdp_op, extack, prog);
        if (err < 0 && prog)
                bpf_prog_put(prog);
 
@@ -7264,12 +7284,10 @@ static int netif_alloc_rx_queues(struct net_device *dev)
 
        BUG_ON(count < 1);
 
-       rx = kzalloc(sz, GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
-       if (!rx) {
-               rx = vzalloc(sz);
-               if (!rx)
-                       return -ENOMEM;
-       }
+       rx = kvzalloc(sz, GFP_KERNEL | __GFP_REPEAT);
+       if (!rx)
+               return -ENOMEM;
+
        dev->_rx = rx;
 
        for (i = 0; i < count; i++)
@@ -7306,12 +7324,10 @@ static int netif_alloc_netdev_queues(struct net_device *dev)
        if (count < 1 || count > 0xffff)
                return -EINVAL;
 
-       tx = kzalloc(sz, GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
-       if (!tx) {
-               tx = vzalloc(sz);
-               if (!tx)
-                       return -ENOMEM;
-       }
+       tx = kvzalloc(sz, GFP_KERNEL | __GFP_REPEAT);
+       if (!tx)
+               return -ENOMEM;
+
        dev->_tx = tx;
 
        netdev_for_each_tx_queue(dev, netdev_init_one_queue, NULL);
@@ -7845,9 +7861,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
        /* ensure 32-byte alignment of whole construct */
        alloc_size += NETDEV_ALIGN - 1;
 
-       p = kzalloc(alloc_size, GFP_KERNEL | __GFP_NOWARN | __GFP_REPEAT);
-       if (!p)
-               p = vzalloc(alloc_size);
+       p = kvzalloc(alloc_size, GFP_KERNEL | __GFP_REPEAT);
        if (!p)
                return NULL;
 
index 58b0bcc125b5559f299dc2f195deccb5c43d0844..d274f81fcc2c08f1e85df4ed00b9a034f3ae0739 100644 (file)
@@ -1132,10 +1132,6 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
                lladdr = neigh->ha;
        }
 
-       if (new & NUD_CONNECTED)
-               neigh->confirmed = jiffies;
-       neigh->updated = jiffies;
-
        /* If entry was valid and address is not changed,
           do not change entry state, if new one is STALE.
         */
@@ -1157,6 +1153,16 @@ int neigh_update(struct neighbour *neigh, const u8 *lladdr, u8 new,
                }
        }
 
+       /* Update timestamps only once we know we will make a change to the
+        * neighbour entry. Otherwise we risk to move the locktime window with
+        * noop updates and ignore relevant ARP updates.
+        */
+       if (new != old || lladdr != neigh->ha) {
+               if (new & NUD_CONNECTED)
+                       neigh->confirmed = jiffies;
+               neigh->updated = jiffies;
+       }
+
        if (new != old) {
                neigh_del_timer(neigh);
                if (new & NUD_PROBE)
index bcb0f610ee422a12ad6b8ae41763296ba0fa3c6a..49a279a7cc15b0d2409236f53a0629ccc927e07c 100644 (file)
@@ -899,8 +899,7 @@ static size_t rtnl_port_size(const struct net_device *dev,
 static size_t rtnl_xdp_size(void)
 {
        size_t xdp_size = nla_total_size(0) +   /* nest IFLA_XDP */
-                         nla_total_size(1) +   /* XDP_ATTACHED */
-                         nla_total_size(4);    /* XDP_FLAGS */
+                         nla_total_size(1);    /* XDP_ATTACHED */
 
        return xdp_size;
 }
@@ -1247,37 +1246,34 @@ static int rtnl_fill_link_ifmap(struct sk_buff *skb, struct net_device *dev)
        return 0;
 }
 
+static u8 rtnl_xdp_attached_mode(struct net_device *dev)
+{
+       const struct net_device_ops *ops = dev->netdev_ops;
+
+       ASSERT_RTNL();
+
+       if (rcu_access_pointer(dev->xdp_prog))
+               return XDP_ATTACHED_SKB;
+       if (ops->ndo_xdp && __dev_xdp_attached(dev, ops->ndo_xdp))
+               return XDP_ATTACHED_DRV;
+
+       return XDP_ATTACHED_NONE;
+}
+
 static int rtnl_xdp_fill(struct sk_buff *skb, struct net_device *dev)
 {
        struct nlattr *xdp;
-       u32 xdp_flags = 0;
-       u8 val = 0;
        int err;
 
        xdp = nla_nest_start(skb, IFLA_XDP);
        if (!xdp)
                return -EMSGSIZE;
-       if (rcu_access_pointer(dev->xdp_prog)) {
-               xdp_flags = XDP_FLAGS_SKB_MODE;
-               val = 1;
-       } else if (dev->netdev_ops->ndo_xdp) {
-               struct netdev_xdp xdp_op = {};
-
-               xdp_op.command = XDP_QUERY_PROG;
-               err = dev->netdev_ops->ndo_xdp(dev, &xdp_op);
-               if (err)
-                       goto err_cancel;
-               val = xdp_op.prog_attached;
-       }
-       err = nla_put_u8(skb, IFLA_XDP_ATTACHED, val);
+
+       err = nla_put_u8(skb, IFLA_XDP_ATTACHED,
+                        rtnl_xdp_attached_mode(dev));
        if (err)
                goto err_cancel;
 
-       if (xdp_flags) {
-               err = nla_put_u32(skb, IFLA_XDP_FLAGS, xdp_flags);
-               if (err)
-                       goto err_cancel;
-       }
        nla_nest_end(skb, xdp);
        return 0;
 
@@ -1631,13 +1627,13 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
                                               cb->nlh->nlmsg_seq, 0,
                                               flags,
                                               ext_filter_mask);
-                       /* If we ran out of room on the first message,
-                        * we're in trouble
-                        */
-                       WARN_ON((err == -EMSGSIZE) && (skb->len == 0));
 
-                       if (err < 0)
-                               goto out;
+                       if (err < 0) {
+                               if (likely(skb->len))
+                                       goto out;
+
+                               goto out_err;
+                       }
 
                        nl_dump_check_consistent(cb, nlmsg_hdr(skb));
 cont:
@@ -1645,10 +1641,12 @@ cont:
                }
        }
 out:
+       err = skb->len;
+out_err:
        cb->args[1] = idx;
        cb->args[0] = h;
 
-       return skb->len;
+       return err;
 }
 
 int rtnl_nla_parse_ifla(struct nlattr **tb, const struct nlattr *head, int len,
@@ -2199,6 +2197,11 @@ static int do_setlink(const struct sk_buff *skb,
                                err = -EINVAL;
                                goto errout;
                        }
+                       if ((xdp_flags & XDP_FLAGS_SKB_MODE) &&
+                           (xdp_flags & XDP_FLAGS_DRV_MODE)) {
+                               err = -EINVAL;
+                               goto errout;
+                       }
                }
 
                if (xdp[IFLA_XDP_FD]) {
@@ -3452,8 +3455,12 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb)
                                err = br_dev->netdev_ops->ndo_bridge_getlink(
                                                skb, portid, seq, dev,
                                                filter_mask, NLM_F_MULTI);
-                               if (err < 0 && err != -EOPNOTSUPP)
-                                       break;
+                               if (err < 0 && err != -EOPNOTSUPP) {
+                                       if (likely(skb->len))
+                                               break;
+
+                                       goto out_err;
+                               }
                        }
                        idx++;
                }
@@ -3464,16 +3471,22 @@ static int rtnl_bridge_getlink(struct sk_buff *skb, struct netlink_callback *cb)
                                                              seq, dev,
                                                              filter_mask,
                                                              NLM_F_MULTI);
-                               if (err < 0 && err != -EOPNOTSUPP)
-                                       break;
+                               if (err < 0 && err != -EOPNOTSUPP) {
+                                       if (likely(skb->len))
+                                               break;
+
+                                       goto out_err;
+                               }
                        }
                        idx++;
                }
        }
+       err = skb->len;
+out_err:
        rcu_read_unlock();
        cb->args[0] = idx;
 
-       return skb->len;
+       return err;
 }
 
 static inline size_t bridge_nlmsg_size(void)
index 6bd2f8fb0476baabf507557fc0d06b6787511c70..ae35cce3a40d70387bee815798933aa43a0e6d84 100644 (file)
@@ -24,9 +24,13 @@ static siphash_key_t ts_secret __read_mostly;
 
 static __always_inline void net_secret_init(void)
 {
-       net_get_random_once(&ts_secret, sizeof(ts_secret));
        net_get_random_once(&net_secret, sizeof(net_secret));
 }
+
+static __always_inline void ts_secret_init(void)
+{
+       net_get_random_once(&ts_secret, sizeof(ts_secret));
+}
 #endif
 
 #ifdef CONFIG_INET
@@ -47,7 +51,7 @@ static u32 seq_scale(u32 seq)
 #endif
 
 #if IS_ENABLED(CONFIG_IPV6)
-static u32 secure_tcpv6_ts_off(const __be32 *saddr, const __be32 *daddr)
+u32 secure_tcpv6_ts_off(const __be32 *saddr, const __be32 *daddr)
 {
        const struct {
                struct in6_addr saddr;
@@ -60,12 +64,14 @@ static u32 secure_tcpv6_ts_off(const __be32 *saddr, const __be32 *daddr)
        if (sysctl_tcp_timestamps != 1)
                return 0;
 
+       ts_secret_init();
        return siphash(&combined, offsetofend(typeof(combined), daddr),
                       &ts_secret);
 }
+EXPORT_SYMBOL(secure_tcpv6_ts_off);
 
-u32 secure_tcpv6_seq_and_tsoff(const __be32 *saddr, const __be32 *daddr,
-                              __be16 sport, __be16 dport, u32 *tsoff)
+u32 secure_tcpv6_seq(const __be32 *saddr, const __be32 *daddr,
+                    __be16 sport, __be16 dport)
 {
        const struct {
                struct in6_addr saddr;
@@ -78,14 +84,14 @@ u32 secure_tcpv6_seq_and_tsoff(const __be32 *saddr, const __be32 *daddr,
                .sport = sport,
                .dport = dport
        };
-       u64 hash;
+       u32 hash;
+
        net_secret_init();
        hash = siphash(&combined, offsetofend(typeof(combined), dport),
                       &net_secret);
-       *tsoff = secure_tcpv6_ts_off(saddr, daddr);
        return seq_scale(hash);
 }
-EXPORT_SYMBOL(secure_tcpv6_seq_and_tsoff);
+EXPORT_SYMBOL(secure_tcpv6_seq);
 
 u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
                               __be16 dport)
@@ -107,11 +113,12 @@ EXPORT_SYMBOL(secure_ipv6_port_ephemeral);
 #endif
 
 #ifdef CONFIG_INET
-static u32 secure_tcp_ts_off(__be32 saddr, __be32 daddr)
+u32 secure_tcp_ts_off(__be32 saddr, __be32 daddr)
 {
        if (sysctl_tcp_timestamps != 1)
                return 0;
 
+       ts_secret_init();
        return siphash_2u32((__force u32)saddr, (__force u32)daddr,
                            &ts_secret);
 }
@@ -121,15 +128,15 @@ static u32 secure_tcp_ts_off(__be32 saddr, __be32 daddr)
  * it would be easy enough to have the former function use siphash_4u32, passing
  * the arguments as separate u32.
  */
-u32 secure_tcp_seq_and_tsoff(__be32 saddr, __be32 daddr,
-                            __be16 sport, __be16 dport, u32 *tsoff)
+u32 secure_tcp_seq(__be32 saddr, __be32 daddr,
+                  __be16 sport, __be16 dport)
 {
-       u64 hash;
+       u32 hash;
+
        net_secret_init();
        hash = siphash_3u32((__force u32)saddr, (__force u32)daddr,
                            (__force u32)sport << 16 | (__force u32)dport,
                            &net_secret);
-       *tsoff = secure_tcp_ts_off(saddr, daddr);
        return seq_scale(hash);
 }
 
index b5baeb9cb0fb1bff2fb7c49c0a850bc493f7e58d..727f924b7f91f495d9e7a4e7297c9c937d3258ed 100644 (file)
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/sched.h>
+#include <linux/sched/mm.h>
 #include <linux/timer.h>
 #include <linux/string.h>
 #include <linux/sockios.h>
 
 #include <trace/events/sock.h>
 
-#ifdef CONFIG_INET
 #include <net/tcp.h>
-#endif
-
 #include <net/busy_poll.h>
 
 static DEFINE_MUTEX(proto_list_mutex);
@@ -372,14 +370,14 @@ EXPORT_SYMBOL_GPL(sk_clear_memalloc);
 int __sk_backlog_rcv(struct sock *sk, struct sk_buff *skb)
 {
        int ret;
-       unsigned long pflags = current->flags;
+       unsigned int noreclaim_flag;
 
        /* these should have been dropped before queueing */
        BUG_ON(!sock_flag(sk, SOCK_MEMALLOC));
 
-       current->flags |= PF_MEMALLOC;
+       noreclaim_flag = memalloc_noreclaim_save();
        ret = sk->sk_backlog_rcv(sk, skb);
-       current_restore_flags(pflags, PF_MEMALLOC);
+       memalloc_noreclaim_restore(noreclaim_flag);
 
        return ret;
 }
@@ -1802,28 +1800,24 @@ EXPORT_SYMBOL(skb_set_owner_w);
  * delay queue. We want to allow the owner socket to send more
  * packets, as if they were already TX completed by a typical driver.
  * But we also want to keep skb->sk set because some packet schedulers
- * rely on it (sch_fq for example). So we set skb->truesize to a small
- * amount (1) and decrease sk_wmem_alloc accordingly.
+ * rely on it (sch_fq for example).
  */
 void skb_orphan_partial(struct sk_buff *skb)
 {
-       /* If this skb is a TCP pure ACK or already went here,
-        * we have nothing to do. 2 is already a very small truesize.
-        */
-       if (skb->truesize <= 2)
+       if (skb_is_tcp_pure_ack(skb))
                return;
 
-       /* TCP stack sets skb->ooo_okay based on sk_wmem_alloc,
-        * so we do not completely orphan skb, but transfert all
-        * accounted bytes but one, to avoid unexpected reorders.
-        */
        if (skb->destructor == sock_wfree
 #ifdef CONFIG_INET
            || skb->destructor == tcp_wfree
 #endif
                ) {
-               atomic_sub(skb->truesize - 1, &skb->sk->sk_wmem_alloc);
-               skb->truesize = 1;
+               struct sock *sk = skb->sk;
+
+               if (atomic_inc_not_zero(&sk->sk_refcnt)) {
+                       atomic_sub(skb->truesize, &sk->sk_wmem_alloc);
+                       skb->destructor = sock_efree;
+               }
        } else {
                skb_orphan(skb);
        }
index b99168b0fabf2a8c65defdd0b93d362630774e1a..f75482bdee9a0e5cc9ef89806b7d2d67ddb38ba1 100644 (file)
@@ -951,7 +951,7 @@ static struct proto dccp_v4_prot = {
        .orphan_count           = &dccp_orphan_count,
        .max_header             = MAX_DCCP_HEADER,
        .obj_size               = sizeof(struct dccp_sock),
-       .slab_flags             = SLAB_DESTROY_BY_RCU,
+       .slab_flags             = SLAB_TYPESAFE_BY_RCU,
        .rsk_prot               = &dccp_request_sock_ops,
        .twsk_prot              = &dccp_timewait_sock_ops,
        .h.hashinfo             = &dccp_hashinfo,
index d9b6a4e403e701fd9b9ecf92bac496e45570054e..992621172220d136a1114a58f1c0e75219c57ea4 100644 (file)
@@ -426,6 +426,9 @@ static struct sock *dccp_v6_request_recv_sock(const struct sock *sk,
                newsk->sk_backlog_rcv = dccp_v4_do_rcv;
                newnp->pktoptions  = NULL;
                newnp->opt         = NULL;
+               newnp->ipv6_mc_list = NULL;
+               newnp->ipv6_ac_list = NULL;
+               newnp->ipv6_fl_list = NULL;
                newnp->mcast_oif   = inet6_iif(skb);
                newnp->mcast_hops  = ipv6_hdr(skb)->hop_limit;
 
@@ -490,6 +493,9 @@ static struct sock *dccp_v6_request_recv_sock(const struct sock *sk,
        /* Clone RX bits */
        newnp->rxopt.all = np->rxopt.all;
 
+       newnp->ipv6_mc_list = NULL;
+       newnp->ipv6_ac_list = NULL;
+       newnp->ipv6_fl_list = NULL;
        newnp->pktoptions = NULL;
        newnp->opt        = NULL;
        newnp->mcast_oif  = inet6_iif(skb);
@@ -1014,7 +1020,7 @@ static struct proto dccp_v6_prot = {
        .orphan_count      = &dccp_orphan_count,
        .max_header        = MAX_DCCP_HEADER,
        .obj_size          = sizeof(struct dccp6_sock),
-       .slab_flags        = SLAB_DESTROY_BY_RCU,
+       .slab_flags        = SLAB_TYPESAFE_BY_RCU,
        .rsk_prot          = &dccp6_request_sock_ops,
        .twsk_prot         = &dccp6_timewait_sock_ops,
        .h.hashinfo        = &dccp_hashinfo,
index 9afa2a5030b2570c89de8decc3b20aad3a224e5c..405483a07efc7ac2efcfe86e285a7673547c9691 100644 (file)
@@ -2361,7 +2361,8 @@ MODULE_AUTHOR("Linux DECnet Project Team");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_NETPROTO(PF_DECnet);
 
-static char banner[] __initdata = KERN_INFO "NET4: DECnet for Linux: V.2.5.68s (C) 1995-2003 Linux DECnet Project Team\n";
+static const char banner[] __initconst = KERN_INFO
+"NET4: DECnet for Linux: V.2.5.68s (C) 1995-2003 Linux DECnet Project Team\n";
 
 static int __init decnet_init(void)
 {
index 482730cd8a562e048b08f275551361ca813a8792..eeb5fc561f800f042023f95e88f0fe5fd64d3f52 100644 (file)
@@ -110,7 +110,7 @@ struct neigh_table dn_neigh_table = {
 static int dn_neigh_construct(struct neighbour *neigh)
 {
        struct net_device *dev = neigh->dev;
-       struct dn_neigh *dn = (struct dn_neigh *)neigh;
+       struct dn_neigh *dn = container_of(neigh, struct dn_neigh, n);
        struct dn_dev *dn_db;
        struct neigh_parms *parms;
 
@@ -339,7 +339,7 @@ int dn_to_neigh_output(struct net *net, struct sock *sk, struct sk_buff *skb)
        struct dst_entry *dst = skb_dst(skb);
        struct dn_route *rt = (struct dn_route *) dst;
        struct neighbour *neigh = rt->n;
-       struct dn_neigh *dn = (struct dn_neigh *)neigh;
+       struct dn_neigh *dn = container_of(neigh, struct dn_neigh, n);
        struct dn_dev *dn_db;
        bool use_long;
 
@@ -391,7 +391,7 @@ int dn_neigh_router_hello(struct net *net, struct sock *sk, struct sk_buff *skb)
 
        neigh = __neigh_lookup(&dn_neigh_table, &src, skb->dev, 1);
 
-       dn = (struct dn_neigh *)neigh;
+       dn = container_of(neigh, struct dn_neigh, n);
 
        if (neigh) {
                write_lock(&neigh->lock);
@@ -451,7 +451,7 @@ int dn_neigh_endnode_hello(struct net *net, struct sock *sk, struct sk_buff *skb
 
        neigh = __neigh_lookup(&dn_neigh_table, &src, skb->dev, 1);
 
-       dn = (struct dn_neigh *)neigh;
+       dn = container_of(neigh, struct dn_neigh, n);
 
        if (neigh) {
                write_lock(&neigh->lock);
@@ -510,7 +510,7 @@ static void neigh_elist_cb(struct neighbour *neigh, void *_info)
        if (neigh->dev != s->dev)
                return;
 
-       dn = (struct dn_neigh *) neigh;
+       dn = container_of(neigh, struct dn_neigh, n);
        if (!(dn->flags & (DN_NDFLAG_R1|DN_NDFLAG_R2)))
                return;
 
@@ -549,7 +549,7 @@ int dn_neigh_elist(struct net_device *dev, unsigned char *ptr, int n)
 static inline void dn_neigh_format_entry(struct seq_file *seq,
                                         struct neighbour *n)
 {
-       struct dn_neigh *dn = (struct dn_neigh *) n;
+       struct dn_neigh *dn = container_of(n, struct dn_neigh, n);
        char buf[DN_ASCBUF_LEN];
 
        read_lock(&n->lock);
index 0937b34c27cacb2dec73a67a76ff11fe26722500..d54345a06f720fb1cd7632a364aa7e7e19ff6216 100644 (file)
@@ -653,6 +653,7 @@ static int arp_process(struct net *net, struct sock *sk, struct sk_buff *skb)
        unsigned char *arp_ptr;
        struct rtable *rt;
        unsigned char *sha;
+       unsigned char *tha = NULL;
        __be32 sip, tip;
        u16 dev_type = dev->type;
        int addr_type;
@@ -724,6 +725,7 @@ static int arp_process(struct net *net, struct sock *sk, struct sk_buff *skb)
                break;
 #endif
        default:
+               tha = arp_ptr;
                arp_ptr += dev->addr_len;
        }
        memcpy(&tip, arp_ptr, 4);
@@ -842,8 +844,18 @@ static int arp_process(struct net *net, struct sock *sk, struct sk_buff *skb)
                   It is possible, that this option should be enabled for some
                   devices (strip is candidate)
                 */
-               is_garp = arp->ar_op == htons(ARPOP_REQUEST) && tip == sip &&
-                         addr_type == RTN_UNICAST;
+               is_garp = tip == sip && addr_type == RTN_UNICAST;
+
+               /* Unsolicited ARP _replies_ also require target hwaddr to be
+                * the same as source.
+                */
+               if (is_garp && arp->ar_op == htons(ARPOP_REPLY))
+                       is_garp =
+                               /* IPv4 over IEEE 1394 doesn't provide target
+                                * hardware address field in its ARP payload.
+                                */
+                               tha &&
+                               !memcmp(tha, sha, dev->addr_len);
 
                if (!n &&
                    ((arp->ar_op == htons(ARPOP_REPLY)  &&
index 39bd1edee67649af86eb582c0ea478713360a506..83e3ed258467dbfd620bd27d48a0b33f5ef7a067 100644 (file)
@@ -763,7 +763,7 @@ static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
        unsigned int e = 0, s_e;
        struct fib_table *tb;
        struct hlist_head *head;
-       int dumped = 0;
+       int dumped = 0, err;
 
        if (nlmsg_len(cb->nlh) >= sizeof(struct rtmsg) &&
            ((struct rtmsg *) nlmsg_data(cb->nlh))->rtm_flags & RTM_F_CLONED)
@@ -783,20 +783,27 @@ static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)
                        if (dumped)
                                memset(&cb->args[2], 0, sizeof(cb->args) -
                                                 2 * sizeof(cb->args[0]));
-                       if (fib_table_dump(tb, skb, cb) < 0)
-                               goto out;
+                       err = fib_table_dump(tb, skb, cb);
+                       if (err < 0) {
+                               if (likely(skb->len))
+                                       goto out;
+
+                               goto out_err;
+                       }
                        dumped = 1;
 next:
                        e++;
                }
        }
 out:
+       err = skb->len;
+out_err:
        rcu_read_unlock();
 
        cb->args[1] = e;
        cb->args[0] = h;
 
-       return skb->len;
+       return err;
 }
 
 /* Prepare and feed intra-kernel routing request.
index 1201409ba1dcb18ee028003b065410b87bf4a602..51182ff2b4415238210e83208bf7f45b5fb55326 100644 (file)
@@ -1983,6 +1983,8 @@ static int fn_trie_dump_leaf(struct key_vector *l, struct fib_table *tb,
 
        /* rcu_read_lock is hold by caller */
        hlist_for_each_entry_rcu(fa, &l->leaf, fa_list) {
+               int err;
+
                if (i < s_i) {
                        i++;
                        continue;
@@ -1993,17 +1995,14 @@ static int fn_trie_dump_leaf(struct key_vector *l, struct fib_table *tb,
                        continue;
                }
 
-               if (fib_dump_info(skb, NETLINK_CB(cb->skb).portid,
-                                 cb->nlh->nlmsg_seq,
-                                 RTM_NEWROUTE,
-                                 tb->tb_id,
-                                 fa->fa_type,
-                                 xkey,
-                                 KEYLENGTH - fa->fa_slen,
-                                 fa->fa_tos,
-                                 fa->fa_info, NLM_F_MULTI) < 0) {
+               err = fib_dump_info(skb, NETLINK_CB(cb->skb).portid,
+                                   cb->nlh->nlmsg_seq, RTM_NEWROUTE,
+                                   tb->tb_id, fa->fa_type,
+                                   xkey, KEYLENGTH - fa->fa_slen,
+                                   fa->fa_tos, fa->fa_info, NLM_F_MULTI);
+               if (err < 0) {
                        cb->args[4] = i;
-                       return -1;
+                       return err;
                }
                i++;
        }
@@ -2025,10 +2024,13 @@ int fib_table_dump(struct fib_table *tb, struct sk_buff *skb,
        t_key key = cb->args[3];
 
        while ((l = leaf_walk_rcu(&tp, key)) != NULL) {
-               if (fn_trie_dump_leaf(l, tb, skb, cb) < 0) {
+               int err;
+
+               err = fn_trie_dump_leaf(l, tb, skb, cb);
+               if (err < 0) {
                        cb->args[3] = key;
                        cb->args[2] = count;
-                       return -1;
+                       return err;
                }
 
                ++count;
index 5e313c1ac94fc88eca5fe3a0e9e46e551e955ff0..1054d330bf9df3189a21dbb08e27c0e6ad136775 100644 (file)
@@ -794,6 +794,8 @@ struct sock *inet_csk_clone_lock(const struct sock *sk,
                /* listeners have SOCK_RCU_FREE, not the children */
                sock_reset_flag(newsk, SOCK_RCU_FREE);
 
+               inet_sk(newsk)->mc_list = NULL;
+
                newsk->sk_mark = inet_rsk(req)->ir_mark;
                atomic64_set(&newsk->sk_cookie,
                             atomic64_read(&inet_rsk(req)->ir_cookie));
index 8bea74298173f5198e7b3083b5afb5e1398df977..e9a59d2d91d4061f299065173d9212eefe72ef89 100644 (file)
@@ -678,11 +678,7 @@ int inet_ehash_locks_alloc(struct inet_hashinfo *hashinfo)
                /* no more locks than number of hash buckets */
                nblocks = min(nblocks, hashinfo->ehash_mask + 1);
 
-               hashinfo->ehash_locks = kmalloc_array(nblocks, locksz,
-                                                     GFP_KERNEL | __GFP_NOWARN);
-               if (!hashinfo->ehash_locks)
-                       hashinfo->ehash_locks = vmalloc(nblocks * locksz);
-
+               hashinfo->ehash_locks = kvmalloc_array(nblocks, locksz, GFP_KERNEL);
                if (!hashinfo->ehash_locks)
                        return -ENOMEM;
 
index 40977413fd4843f304a6782286e46403bbab9d57..4ec9affb2252408b0c218ad63b17a891ff2ab8ed 100644 (file)
@@ -546,12 +546,13 @@ static int vti_fill_info(struct sk_buff *skb, const struct net_device *dev)
        struct ip_tunnel *t = netdev_priv(dev);
        struct ip_tunnel_parm *p = &t->parms;
 
-       nla_put_u32(skb, IFLA_VTI_LINK, p->link);
-       nla_put_be32(skb, IFLA_VTI_IKEY, p->i_key);
-       nla_put_be32(skb, IFLA_VTI_OKEY, p->o_key);
-       nla_put_in_addr(skb, IFLA_VTI_LOCAL, p->iph.saddr);
-       nla_put_in_addr(skb, IFLA_VTI_REMOTE, p->iph.daddr);
-       nla_put_u32(skb, IFLA_VTI_FWMARK, t->fwmark);
+       if (nla_put_u32(skb, IFLA_VTI_LINK, p->link) ||
+           nla_put_be32(skb, IFLA_VTI_IKEY, p->i_key) ||
+           nla_put_be32(skb, IFLA_VTI_OKEY, p->o_key) ||
+           nla_put_in_addr(skb, IFLA_VTI_LOCAL, p->iph.saddr) ||
+           nla_put_in_addr(skb, IFLA_VTI_REMOTE, p->iph.daddr) ||
+           nla_put_u32(skb, IFLA_VTI_FWMARK, t->fwmark))
+               return -EMSGSIZE;
 
        return 0;
 }
index 3a02d52ed50ec54ce3f9f3eb07dc9f4133535a80..551de4d023a8edbf74835b43cb32d9173eedae36 100644 (file)
@@ -1980,6 +1980,20 @@ int ip_mr_input(struct sk_buff *skb)
        struct net *net = dev_net(skb->dev);
        int local = skb_rtable(skb)->rt_flags & RTCF_LOCAL;
        struct mr_table *mrt;
+       struct net_device *dev;
+
+       /* skb->dev passed in is the loX master dev for vrfs.
+        * As there are no vifs associated with loopback devices,
+        * get the proper interface that does have a vif associated with it.
+        */
+       dev = skb->dev;
+       if (netif_is_l3_master(skb->dev)) {
+               dev = dev_get_by_index_rcu(net, IPCB(skb)->iif);
+               if (!dev) {
+                       kfree_skb(skb);
+                       return -ENODEV;
+               }
+       }
 
        /* Packet is looped back after forward, it should not be
         * forwarded second time, but still can be delivered locally.
@@ -2017,7 +2031,7 @@ int ip_mr_input(struct sk_buff *skb)
        /* already under rcu_read_lock() */
        cache = ipmr_cache_find(mrt, ip_hdr(skb)->saddr, ip_hdr(skb)->daddr);
        if (!cache) {
-               int vif = ipmr_find_vif(mrt, skb->dev);
+               int vif = ipmr_find_vif(mrt, dev);
 
                if (vif >= 0)
                        cache = ipmr_cache_find_any(mrt, ip_hdr(skb)->daddr,
@@ -2037,7 +2051,7 @@ int ip_mr_input(struct sk_buff *skb)
                }
 
                read_lock(&mrt_lock);
-               vif = ipmr_find_vif(mrt, skb->dev);
+               vif = ipmr_find_vif(mrt, dev);
                if (vif >= 0) {
                        int err2 = ipmr_cache_unresolved(mrt, vif, skb);
                        read_unlock(&mrt_lock);
index 496b97e17aaf7ed2cf41cef303cb0696927f66ac..0257d965f11119acf8c55888d6e672d171ef5f08 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/siphash.h>
 #include <linux/kernel.h>
 #include <linux/export.h>
+#include <net/secure_seq.h>
 #include <net/tcp.h>
 #include <net/route.h>
 
@@ -203,7 +204,7 @@ EXPORT_SYMBOL_GPL(__cookie_v4_check);
 
 struct sock *tcp_get_cookie_sock(struct sock *sk, struct sk_buff *skb,
                                 struct request_sock *req,
-                                struct dst_entry *dst)
+                                struct dst_entry *dst, u32 tsoff)
 {
        struct inet_connection_sock *icsk = inet_csk(sk);
        struct sock *child;
@@ -213,6 +214,7 @@ struct sock *tcp_get_cookie_sock(struct sock *sk, struct sk_buff *skb,
                                                 NULL, &own_req);
        if (child) {
                atomic_set(&req->rsk_refcnt, 1);
+               tcp_sk(child)->tsoffset = tsoff;
                sock_rps_save_rxhash(child, skb);
                inet_csk_reqsk_queue_add(sk, req, child);
        } else {
@@ -292,6 +294,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
        struct rtable *rt;
        __u8 rcv_wscale;
        struct flowi4 fl4;
+       u32 tsoff = 0;
 
        if (!sock_net(sk)->ipv4.sysctl_tcp_syncookies || !th->ack || th->rst)
                goto out;
@@ -311,6 +314,11 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
        memset(&tcp_opt, 0, sizeof(tcp_opt));
        tcp_parse_options(skb, &tcp_opt, 0, NULL);
 
+       if (tcp_opt.saw_tstamp && tcp_opt.rcv_tsecr) {
+               tsoff = secure_tcp_ts_off(ip_hdr(skb)->daddr, ip_hdr(skb)->saddr);
+               tcp_opt.rcv_tsecr -= tsoff;
+       }
+
        if (!cookie_timestamp_decode(&tcp_opt))
                goto out;
 
@@ -381,7 +389,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb)
        ireq->rcv_wscale  = rcv_wscale;
        ireq->ecn_ok = cookie_ecn_ok(&tcp_opt, sock_net(sk), &rt->dst);
 
-       ret = tcp_get_cookie_sock(sk, skb, req, &rt->dst);
+       ret = tcp_get_cookie_sock(sk, skb, req, &rt->dst, tsoff);
        /* ip_queue_xmit() depends on our flow being setup
         * Normal sockets get it right from inet_csk_route_child_sock()
         */
index 9739962bfb3fd2d39cb13f643def223f4f17fcb6..174d4376baa5374c11caecc0e0452fa938d63561 100644 (file)
@@ -85,7 +85,6 @@ int sysctl_tcp_dsack __read_mostly = 1;
 int sysctl_tcp_app_win __read_mostly = 31;
 int sysctl_tcp_adv_win_scale __read_mostly = 1;
 EXPORT_SYMBOL(sysctl_tcp_adv_win_scale);
-EXPORT_SYMBOL(sysctl_tcp_timestamps);
 
 /* rfc5961 challenge ack rate limiting */
 int sysctl_tcp_challenge_ack_limit = 1000;
@@ -1180,13 +1179,14 @@ static int tcp_match_skb_to_sack(struct sock *sk, struct sk_buff *skb,
                 */
                if (pkt_len > mss) {
                        unsigned int new_len = (pkt_len / mss) * mss;
-                       if (!in_sack && new_len < pkt_len) {
+                       if (!in_sack && new_len < pkt_len)
                                new_len += mss;
-                               if (new_len >= skb->len)
-                                       return 0;
-                       }
                        pkt_len = new_len;
                }
+
+               if (pkt_len >= skb->len && !in_sack)
+                       return 0;
+
                err = tcp_fragment(sk, skb, pkt_len, mss, GFP_ATOMIC);
                if (err < 0)
                        return err;
@@ -3190,7 +3190,7 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets,
                        int delta;
 
                        /* Non-retransmitted hole got filled? That's reordering */
-                       if (reord < prior_fackets)
+                       if (reord < prior_fackets && reord <= tp->fackets_out)
                                tcp_update_reordering(sk, tp->fackets_out - reord, 0);
 
                        delta = tcp_is_fack(tp) ? pkts_acked :
@@ -6347,8 +6347,8 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
        if (security_inet_conn_request(sk, skb, req))
                goto drop_and_free;
 
-       if (isn && tmp_opt.tstamp_ok)
-               af_ops->init_seq_tsoff(skb, &tcp_rsk(req)->ts_off);
+       if (tmp_opt.tstamp_ok)
+               tcp_rsk(req)->ts_off = af_ops->init_ts_off(skb);
 
        if (!want_cookie && !isn) {
                /* Kill the following clause, if you dislike this way. */
@@ -6368,7 +6368,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
                        goto drop_and_release;
                }
 
-               isn = af_ops->init_seq_tsoff(skb, &tcp_rsk(req)->ts_off);
+               isn = af_ops->init_seq(skb);
        }
        if (!dst) {
                dst = af_ops->route_req(sk, &fl, req);
@@ -6380,7 +6380,6 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
 
        if (want_cookie) {
                isn = cookie_init_sequence(af_ops, sk, skb, &req->mss);
-               tcp_rsk(req)->ts_off = 0;
                req->cookie_ts = tmp_opt.tstamp_ok;
                if (!tmp_opt.tstamp_ok)
                        inet_rsk(req)->ecn_ok = 0;
index cbbafe546c0f5c5f43531eaf24f5b460264785c6..5ab2aac5ca191075383fc75214da816873bb222c 100644 (file)
@@ -94,12 +94,18 @@ static int tcp_v4_md5_hash_hdr(char *md5_hash, const struct tcp_md5sig_key *key,
 struct inet_hashinfo tcp_hashinfo;
 EXPORT_SYMBOL(tcp_hashinfo);
 
-static u32 tcp_v4_init_seq_and_tsoff(const struct sk_buff *skb, u32 *tsoff)
+static u32 tcp_v4_init_seq(const struct sk_buff *skb)
 {
-       return secure_tcp_seq_and_tsoff(ip_hdr(skb)->daddr,
-                                       ip_hdr(skb)->saddr,
-                                       tcp_hdr(skb)->dest,
-                                       tcp_hdr(skb)->source, tsoff);
+       return secure_tcp_seq(ip_hdr(skb)->daddr,
+                             ip_hdr(skb)->saddr,
+                             tcp_hdr(skb)->dest,
+                             tcp_hdr(skb)->source);
+}
+
+static u32 tcp_v4_init_ts_off(const struct sk_buff *skb)
+{
+       return secure_tcp_ts_off(ip_hdr(skb)->daddr,
+                                ip_hdr(skb)->saddr);
 }
 
 int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
@@ -145,7 +151,6 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        struct flowi4 *fl4;
        struct rtable *rt;
        int err;
-       u32 seq;
        struct ip_options_rcu *inet_opt;
        struct inet_timewait_death_row *tcp_death_row = &sock_net(sk)->ipv4.tcp_death_row;
 
@@ -232,13 +237,13 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        rt = NULL;
 
        if (likely(!tp->repair)) {
-               seq = secure_tcp_seq_and_tsoff(inet->inet_saddr,
-                                              inet->inet_daddr,
-                                              inet->inet_sport,
-                                              usin->sin_port,
-                                              &tp->tsoffset);
                if (!tp->write_seq)
-                       tp->write_seq = seq;
+                       tp->write_seq = secure_tcp_seq(inet->inet_saddr,
+                                                      inet->inet_daddr,
+                                                      inet->inet_sport,
+                                                      usin->sin_port);
+               tp->tsoffset = secure_tcp_ts_off(inet->inet_saddr,
+                                                inet->inet_daddr);
        }
 
        inet->inet_id = tp->write_seq ^ jiffies;
@@ -1239,7 +1244,8 @@ static const struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = {
        .cookie_init_seq =      cookie_v4_init_sequence,
 #endif
        .route_req      =       tcp_v4_route_req,
-       .init_seq_tsoff =       tcp_v4_init_seq_and_tsoff,
+       .init_seq       =       tcp_v4_init_seq,
+       .init_ts_off    =       tcp_v4_init_ts_off,
        .send_synack    =       tcp_v4_send_synack,
 };
 
@@ -2389,7 +2395,7 @@ struct proto tcp_prot = {
        .sysctl_rmem            = sysctl_tcp_rmem,
        .max_header             = MAX_TCP_HEADER,
        .obj_size               = sizeof(struct tcp_sock),
-       .slab_flags             = SLAB_DESTROY_BY_RCU,
+       .slab_flags             = SLAB_TYPESAFE_BY_RCU,
        .twsk_prot              = &tcp_timewait_sock_ops,
        .rsk_prot               = &tcp_request_sock_ops,
        .h.hashinfo             = &tcp_hashinfo,
index 9d0d4f39e42be15d8ad7389bc7562449b92ea5fa..653bbd67e3a39b68d27d26d17571c00ce2854bfd 100644 (file)
@@ -1011,10 +1011,7 @@ static int __net_init tcp_net_metrics_init(struct net *net)
        tcp_metrics_hash_log = order_base_2(slots);
        size = sizeof(struct tcpm_hash_bucket) << tcp_metrics_hash_log;
 
-       tcp_metrics_hash = kzalloc(size, GFP_KERNEL | __GFP_NOWARN);
-       if (!tcp_metrics_hash)
-               tcp_metrics_hash = vzalloc(size);
-
+       tcp_metrics_hash = kvzalloc(size, GFP_KERNEL);
        if (!tcp_metrics_hash)
                return -ENOMEM;
 
index 60111a0fc2017e817fc37087b3862b82e002da0f..4858e190f6ac130c9441f58cb8944cc82bf67270 100644 (file)
@@ -1514,6 +1514,7 @@ static void tcp_cwnd_application_limited(struct sock *sk)
 
 static void tcp_cwnd_validate(struct sock *sk, bool is_cwnd_limited)
 {
+       const struct tcp_congestion_ops *ca_ops = inet_csk(sk)->icsk_ca_ops;
        struct tcp_sock *tp = tcp_sk(sk);
 
        /* Track the maximum number of outstanding packets in each
@@ -1536,7 +1537,8 @@ static void tcp_cwnd_validate(struct sock *sk, bool is_cwnd_limited)
                        tp->snd_cwnd_used = tp->packets_out;
 
                if (sysctl_tcp_slow_start_after_idle &&
-                   (s32)(tcp_time_stamp - tp->snd_cwnd_stamp) >= inet_csk(sk)->icsk_rto)
+                   (s32)(tcp_time_stamp - tp->snd_cwnd_stamp) >= inet_csk(sk)->icsk_rto &&
+                   !ca_ops->cong_control)
                        tcp_cwnd_application_limited(sk);
 
                /* The following conditions together indicate the starvation
index ea6e4cff9fafe99af23fd8ea666cd979d5af9104..1d6219bf2d6b48abaa73ad7f178049d95124cc90 100644 (file)
@@ -1612,7 +1612,7 @@ static void udp_v4_rehash(struct sock *sk)
        udp_lib_rehash(sk, new_hash);
 }
 
-int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
+static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
 {
        int rc;
 
@@ -1657,7 +1657,7 @@ EXPORT_SYMBOL(udp_encap_enable);
  * Note that in the success and error cases, the skb is assumed to
  * have either been requeued or freed.
  */
-int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
+static int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
 {
        struct udp_sock *up = udp_sk(sk);
        int is_udplite = IS_UDPLITE(sk);
index feb50a16398dfa856fd928fe823b4f6556d2caa1..a8cf8c6fb60ccf532fda1b109f902ead378acf22 100644 (file)
@@ -25,7 +25,6 @@ int udp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock,
                int flags, int *addr_len);
 int udp_sendpage(struct sock *sk, struct page *page, int offset, size_t size,
                 int flags);
-int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
 void udp_destroy_sock(struct sock *sk);
 
 #ifdef CONFIG_PROC_FS
index 77a4bd526d6e421cb8d384e2d9febd55700aec8e..6a4fb1e629fb7609048156974ae2eb322cebddae 100644 (file)
@@ -1022,7 +1022,10 @@ ipv6_add_addr(struct inet6_dev *idev, const struct in6_addr *addr,
        INIT_HLIST_NODE(&ifa->addr_lst);
        ifa->scope = scope;
        ifa->prefix_len = pfxlen;
-       ifa->flags = flags | IFA_F_TENTATIVE;
+       ifa->flags = flags;
+       /* No need to add the TENTATIVE flag for addresses with NODAD */
+       if (!(flags & IFA_F_NODAD))
+               ifa->flags |= IFA_F_TENTATIVE;
        ifa->valid_lft = valid_lft;
        ifa->prefered_lft = prefered_lft;
        ifa->cstamp = ifa->tstamp = jiffies;
@@ -3548,6 +3551,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
  */
 static struct notifier_block ipv6_dev_notf = {
        .notifier_call = addrconf_notify,
+       .priority = ADDRCONF_NOTIFY_PRIORITY,
 };
 
 static void addrconf_type_change(struct net_device *dev, unsigned long event)
index af8f52ee7180868294930629f4f312c012a7a35c..2fd5ca151dcfca6034b0b0b27a3fe9abc7899e75 100644 (file)
@@ -41,13 +41,7 @@ static int alloc_ila_locks(struct ila_net *ilan)
        size = roundup_pow_of_two(nr_pcpus * LOCKS_PER_CPU);
 
        if (sizeof(spinlock_t) != 0) {
-#ifdef CONFIG_NUMA
-               if (size * sizeof(spinlock_t) > PAGE_SIZE)
-                       ilan->locks = vmalloc(size * sizeof(spinlock_t));
-               else
-#endif
-               ilan->locks = kmalloc_array(size, sizeof(spinlock_t),
-                                           GFP_KERNEL);
+               ilan->locks = kvmalloc(size * sizeof(spinlock_t), GFP_KERNEL);
                if (!ilan->locks)
                        return -ENOMEM;
                for (i = 0; i < size; i++)
index 93e58a5e18374bee41f5a17f0c5911e381acb142..280268f1dd7b0972d7fadbcc9e28b043ceae423d 100644 (file)
@@ -63,7 +63,6 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
        const struct net_offload *ops;
        int proto;
        struct frag_hdr *fptr;
-       unsigned int unfrag_ip6hlen;
        unsigned int payload_len;
        u8 *prevhdr;
        int offset = 0;
@@ -116,8 +115,10 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
                skb->network_header = (u8 *)ipv6h - skb->head;
 
                if (udpfrag) {
-                       unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
-                       fptr = (struct frag_hdr *)((u8 *)ipv6h + unfrag_ip6hlen);
+                       int err = ip6_find_1stfragopt(skb, &prevhdr);
+                       if (err < 0)
+                               return ERR_PTR(err);
+                       fptr = (struct frag_hdr *)((u8 *)ipv6h + err);
                        fptr->frag_off = htons(offset);
                        if (skb->next)
                                fptr->frag_off |= htons(IP6_MF);
index 58f6288e9ba53e6964b74d71dde7615ead695c06..d4a31becbd25dda895d7391e1e65c2de237bf2a3 100644 (file)
@@ -597,7 +597,10 @@ int ip6_fragment(struct net *net, struct sock *sk, struct sk_buff *skb,
        int ptr, offset = 0, err = 0;
        u8 *prevhdr, nexthdr = 0;
 
-       hlen = ip6_find_1stfragopt(skb, &prevhdr);
+       err = ip6_find_1stfragopt(skb, &prevhdr);
+       if (err < 0)
+               goto fail;
+       hlen = err;
        nexthdr = *prevhdr;
 
        mtu = ip6_skb_dst_mtu(skb);
index cd4252346a32d90e8e133bd985811b6241e4bcd7..e9065b8d3af852c6e9a7359667f68a5ad00bfe75 100644 (file)
@@ -79,14 +79,13 @@ EXPORT_SYMBOL(ipv6_select_ident);
 int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
 {
        u16 offset = sizeof(struct ipv6hdr);
-       struct ipv6_opt_hdr *exthdr =
-                               (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1);
        unsigned int packet_len = skb_tail_pointer(skb) -
                skb_network_header(skb);
        int found_rhdr = 0;
        *nexthdr = &ipv6_hdr(skb)->nexthdr;
 
-       while (offset + 1 <= packet_len) {
+       while (offset <= packet_len) {
+               struct ipv6_opt_hdr *exthdr;
 
                switch (**nexthdr) {
 
@@ -107,13 +106,16 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
                        return offset;
                }
 
-               offset += ipv6_optlen(exthdr);
-               *nexthdr = &exthdr->nexthdr;
+               if (offset + sizeof(struct ipv6_opt_hdr) > packet_len)
+                       return -EINVAL;
+
                exthdr = (struct ipv6_opt_hdr *)(skb_network_header(skb) +
                                                 offset);
+               offset += ipv6_optlen(exthdr);
+               *nexthdr = &exthdr->nexthdr;
        }
 
-       return offset;
+       return -EINVAL;
 }
 EXPORT_SYMBOL(ip6_find_1stfragopt);
 
index 2f1136627dcbd7135b887a0b4b077fb8e854811d..dc61b0b5e64edf7bd69ab905573e38415abf2346 100644 (file)
@@ -3709,7 +3709,10 @@ static int ip6_route_dev_notify(struct notifier_block *this,
        struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct net *net = dev_net(dev);
 
-       if (event == NETDEV_REGISTER && (dev->flags & IFF_LOOPBACK)) {
+       if (!(dev->flags & IFF_LOOPBACK))
+               return NOTIFY_OK;
+
+       if (event == NETDEV_REGISTER) {
                net->ipv6.ip6_null_entry->dst.dev = dev;
                net->ipv6.ip6_null_entry->rt6i_idev = in6_dev_get(dev);
 #ifdef CONFIG_IPV6_MULTIPLE_TABLES
@@ -3717,6 +3720,12 @@ static int ip6_route_dev_notify(struct notifier_block *this,
                net->ipv6.ip6_prohibit_entry->rt6i_idev = in6_dev_get(dev);
                net->ipv6.ip6_blk_hole_entry->dst.dev = dev;
                net->ipv6.ip6_blk_hole_entry->rt6i_idev = in6_dev_get(dev);
+#endif
+        } else if (event == NETDEV_UNREGISTER) {
+               in6_dev_put(net->ipv6.ip6_null_entry->rt6i_idev);
+#ifdef CONFIG_IPV6_MULTIPLE_TABLES
+               in6_dev_put(net->ipv6.ip6_prohibit_entry->rt6i_idev);
+               in6_dev_put(net->ipv6.ip6_blk_hole_entry->rt6i_idev);
 #endif
        }
 
@@ -4024,7 +4033,7 @@ static struct pernet_operations ip6_route_net_late_ops = {
 
 static struct notifier_block ip6_route_dev_notifier = {
        .notifier_call = ip6_route_dev_notify,
-       .priority = 0,
+       .priority = ADDRCONF_NOTIFY_PRIORITY - 10,
 };
 
 void __init ip6_route_init_special_entries(void)
index 895ff650db43017ef39344679771d94ad6eaaf00..5abc3692b9011b140816dc4ce6223e79e5defddb 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/random.h>
 #include <linux/siphash.h>
 #include <linux/kernel.h>
+#include <net/secure_seq.h>
 #include <net/ipv6.h>
 #include <net/tcp.h>
 
@@ -143,6 +144,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
        int mss;
        struct dst_entry *dst;
        __u8 rcv_wscale;
+       u32 tsoff = 0;
 
        if (!sock_net(sk)->ipv4.sysctl_tcp_syncookies || !th->ack || th->rst)
                goto out;
@@ -162,6 +164,12 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
        memset(&tcp_opt, 0, sizeof(tcp_opt));
        tcp_parse_options(skb, &tcp_opt, 0, NULL);
 
+       if (tcp_opt.saw_tstamp && tcp_opt.rcv_tsecr) {
+               tsoff = secure_tcpv6_ts_off(ipv6_hdr(skb)->daddr.s6_addr32,
+                                           ipv6_hdr(skb)->saddr.s6_addr32);
+               tcp_opt.rcv_tsecr -= tsoff;
+       }
+
        if (!cookie_timestamp_decode(&tcp_opt))
                goto out;
 
@@ -242,7 +250,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
        ireq->rcv_wscale = rcv_wscale;
        ireq->ecn_ok = cookie_ecn_ok(&tcp_opt, sock_net(sk), dst);
 
-       ret = tcp_get_cookie_sock(sk, skb, req, dst);
+       ret = tcp_get_cookie_sock(sk, skb, req, dst, tsoff);
 out:
        return ret;
 out_free:
index 8e42e8f54b705ed8780890c7434feeff1055599a..4f4310a36a0481e2bd068e39285011ff28377ea5 100644 (file)
@@ -101,12 +101,18 @@ static void inet6_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb)
        }
 }
 
-static u32 tcp_v6_init_seq_and_tsoff(const struct sk_buff *skb, u32 *tsoff)
+static u32 tcp_v6_init_seq(const struct sk_buff *skb)
 {
-       return secure_tcpv6_seq_and_tsoff(ipv6_hdr(skb)->daddr.s6_addr32,
-                                         ipv6_hdr(skb)->saddr.s6_addr32,
-                                         tcp_hdr(skb)->dest,
-                                         tcp_hdr(skb)->source, tsoff);
+       return secure_tcpv6_seq(ipv6_hdr(skb)->daddr.s6_addr32,
+                               ipv6_hdr(skb)->saddr.s6_addr32,
+                               tcp_hdr(skb)->dest,
+                               tcp_hdr(skb)->source);
+}
+
+static u32 tcp_v6_init_ts_off(const struct sk_buff *skb)
+{
+       return secure_tcpv6_ts_off(ipv6_hdr(skb)->daddr.s6_addr32,
+                                  ipv6_hdr(skb)->saddr.s6_addr32);
 }
 
 static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
@@ -122,7 +128,6 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
        struct flowi6 fl6;
        struct dst_entry *dst;
        int addr_type;
-       u32 seq;
        int err;
        struct inet_timewait_death_row *tcp_death_row = &sock_net(sk)->ipv4.tcp_death_row;
 
@@ -282,13 +287,13 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
        sk_set_txhash(sk);
 
        if (likely(!tp->repair)) {
-               seq = secure_tcpv6_seq_and_tsoff(np->saddr.s6_addr32,
-                                                sk->sk_v6_daddr.s6_addr32,
-                                                inet->inet_sport,
-                                                inet->inet_dport,
-                                                &tp->tsoffset);
                if (!tp->write_seq)
-                       tp->write_seq = seq;
+                       tp->write_seq = secure_tcpv6_seq(np->saddr.s6_addr32,
+                                                        sk->sk_v6_daddr.s6_addr32,
+                                                        inet->inet_sport,
+                                                        inet->inet_dport);
+               tp->tsoffset = secure_tcpv6_ts_off(np->saddr.s6_addr32,
+                                                  sk->sk_v6_daddr.s6_addr32);
        }
 
        if (tcp_fastopen_defer_connect(sk, &err))
@@ -749,7 +754,8 @@ static const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = {
        .cookie_init_seq =      cookie_v6_init_sequence,
 #endif
        .route_req      =       tcp_v6_route_req,
-       .init_seq_tsoff =       tcp_v6_init_seq_and_tsoff,
+       .init_seq       =       tcp_v6_init_seq,
+       .init_ts_off    =       tcp_v6_init_ts_off,
        .send_synack    =       tcp_v6_send_synack,
 };
 
@@ -1056,6 +1062,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
                newtp->af_specific = &tcp_sock_ipv6_mapped_specific;
 #endif
 
+               newnp->ipv6_mc_list = NULL;
                newnp->ipv6_ac_list = NULL;
                newnp->ipv6_fl_list = NULL;
                newnp->pktoptions  = NULL;
@@ -1125,6 +1132,7 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
           First: no IPv4 options.
         */
        newinet->inet_opt = NULL;
+       newnp->ipv6_mc_list = NULL;
        newnp->ipv6_ac_list = NULL;
        newnp->ipv6_fl_list = NULL;
 
@@ -1911,7 +1919,7 @@ struct proto tcpv6_prot = {
        .sysctl_rmem            = sysctl_tcp_rmem,
        .max_header             = MAX_TCP_HEADER,
        .obj_size               = sizeof(struct tcp6_sock),
-       .slab_flags             = SLAB_DESTROY_BY_RCU,
+       .slab_flags             = SLAB_TYPESAFE_BY_RCU,
        .twsk_prot              = &tcp6_timewait_sock_ops,
        .rsk_prot               = &tcp6_request_sock_ops,
        .h.hashinfo             = &tcp_hashinfo,
index 04862abfe4ec27d978adadd27735a9d19e3c4365..06ec39b796092ad5e8954c0cfd10e75205ffce54 100644 (file)
@@ -526,7 +526,7 @@ out:
        return;
 }
 
-int __udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
+static int __udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
 {
        int rc;
 
@@ -569,7 +569,7 @@ void udpv6_encap_enable(void)
 }
 EXPORT_SYMBOL(udpv6_encap_enable);
 
-int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
+static int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
 {
        struct udp_sock *up = udp_sk(sk);
        int is_udplite = IS_UDPLITE(sk);
index e78bdc76dcc33ceda888fb323a530f774057edbb..f180b3d85e3147facb487720bb3d98722ae76a45 100644 (file)
@@ -26,7 +26,6 @@ int compat_udpv6_getsockopt(struct sock *sk, int level, int optname,
 int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len);
 int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int noblock,
                  int flags, int *addr_len);
-int __udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
 void udpv6_destroy_sock(struct sock *sk);
 
 #ifdef CONFIG_PROC_FS
index ac858c480f2f272f37275cddfd9ffe889a91af97..a2267f80febbb6f31459097f27bd89d51d0f2b11 100644 (file)
@@ -29,6 +29,7 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
        u8 frag_hdr_sz = sizeof(struct frag_hdr);
        __wsum csum;
        int tnl_hlen;
+       int err;
 
        mss = skb_shinfo(skb)->gso_size;
        if (unlikely(skb->len <= mss))
@@ -90,7 +91,10 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb,
                /* Find the unfragmentable header and shift it left by frag_hdr_sz
                 * bytes to insert fragment header.
                 */
-               unfrag_ip6hlen = ip6_find_1stfragopt(skb, &prevhdr);
+               err = ip6_find_1stfragopt(skb, &prevhdr);
+               if (err < 0)
+                       return ERR_PTR(err);
+               unfrag_ip6hlen = err;
                nexthdr = *prevhdr;
                *prevhdr = NEXTHDR_FRAGMENT;
                unfrag_len = (skb_network_header(skb) - skb_mac_header(skb)) +
index cb4fff785cbf5aaad520442dc243ae62dc5750ea..8364fe5b59e4ca01ef8d05b1038dbe96fedf657b 100644 (file)
@@ -142,7 +142,7 @@ static struct proto llc_proto = {
        .name     = "LLC",
        .owner    = THIS_MODULE,
        .obj_size = sizeof(struct llc_sock),
-       .slab_flags = SLAB_DESTROY_BY_RCU,
+       .slab_flags = SLAB_TYPESAFE_BY_RCU,
 };
 
 /**
index 8bc5a1bd2d453542df31506f543feb64b64cdd96..9b02c13d258b005bb10029b3baf8ec4db71f18b4 100644 (file)
@@ -506,7 +506,7 @@ static struct sock *__llc_lookup_established(struct llc_sap *sap,
 again:
        sk_nulls_for_each_rcu(rc, node, laddr_hb) {
                if (llc_estab_match(sap, daddr, laddr, rc)) {
-                       /* Extra checks required by SLAB_DESTROY_BY_RCU */
+                       /* Extra checks required by SLAB_TYPESAFE_BY_RCU */
                        if (unlikely(!atomic_inc_not_zero(&rc->sk_refcnt)))
                                goto again;
                        if (unlikely(llc_sk(rc)->sap != sap ||
@@ -565,7 +565,7 @@ static struct sock *__llc_lookup_listener(struct llc_sap *sap,
 again:
        sk_nulls_for_each_rcu(rc, node, laddr_hb) {
                if (llc_listener_match(sap, laddr, rc)) {
-                       /* Extra checks required by SLAB_DESTROY_BY_RCU */
+                       /* Extra checks required by SLAB_TYPESAFE_BY_RCU */
                        if (unlikely(!atomic_inc_not_zero(&rc->sk_refcnt)))
                                goto again;
                        if (unlikely(llc_sk(rc)->sap != sap ||
index 5404d0d195cc581613e356b75bd70321e617673e..63b6ab0563705f4b15c6bc8e3d9c7ad85a2af381 100644 (file)
@@ -328,7 +328,7 @@ static struct sock *llc_lookup_dgram(struct llc_sap *sap,
 again:
        sk_nulls_for_each_rcu(rc, node, laddr_hb) {
                if (llc_dgram_match(sap, laddr, rc)) {
-                       /* Extra checks required by SLAB_DESTROY_BY_RCU */
+                       /* Extra checks required by SLAB_TYPESAFE_BY_RCU */
                        if (unlikely(!atomic_inc_not_zero(&rc->sk_refcnt)))
                                goto again;
                        if (unlikely(llc_sk(rc)->sap != sap ||
index 6db09fa18269f3a12032345afa5af0fa336a8c50..364d4e13764942db0b41eee7a9561b3c00e946ae 100644 (file)
@@ -66,6 +66,8 @@ ieee80211_ibss_build_presp(struct ieee80211_sub_if_data *sdata,
                    2 + (IEEE80211_MAX_SUPP_RATES - 8) +
                    2 + sizeof(struct ieee80211_ht_cap) +
                    2 + sizeof(struct ieee80211_ht_operation) +
+                   2 + sizeof(struct ieee80211_vht_cap) +
+                   2 + sizeof(struct ieee80211_vht_operation) +
                    ifibss->ie_len;
        presp = kzalloc(sizeof(*presp) + frame_len, GFP_KERNEL);
        if (!presp)
index 89dff563b1ecf5eb938985143396cc1287bc9914..0ea9712bd99ea698f40b068d5ee31a69133224a3 100644 (file)
@@ -4382,6 +4382,10 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
        if (WARN_ON(!ifmgd->auth_data && !ifmgd->assoc_data))
                return -EINVAL;
 
+       /* If a reconfig is happening, bail out */
+       if (local->in_reconfig)
+               return -EBUSY;
+
        if (assoc) {
                rcu_read_lock();
                have_sta = sta_info_get(sdata, cbss->bssid);
index 088e2b459d0f01a6d33b7a5166c3dc0a394523e9..257ec66009da2dd7010d063c0ad29dbb9a32564e 100644 (file)
@@ -2005,10 +2005,7 @@ static int resize_platform_label_table(struct net *net, size_t limit)
        unsigned index;
 
        if (size) {
-               labels = kzalloc(size, GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY);
-               if (!labels)
-                       labels = vzalloc(size);
-
+               labels = kvzalloc(size, GFP_KERNEL);
                if (!labels)
                        goto nolabels;
        }
index 3c8f1ed2f5558fe0fcf0d230d5d8553ba84c68fe..e847dbaa0c6b3aefc3d417421a2b529a10735e38 100644 (file)
@@ -911,7 +911,7 @@ static unsigned int early_drop_list(struct net *net,
                        continue;
 
                /* kill only if still in same netns -- might have moved due to
-                * SLAB_DESTROY_BY_RCU rules.
+                * SLAB_TYPESAFE_BY_RCU rules.
                 *
                 * We steal the timer reference.  If that fails timer has
                 * already fired or someone else deleted it. Just drop ref
@@ -1114,7 +1114,7 @@ __nf_conntrack_alloc(struct net *net,
 
        /*
         * Do not use kmem_cache_zalloc(), as this cache uses
-        * SLAB_DESTROY_BY_RCU.
+        * SLAB_TYPESAFE_BY_RCU.
         */
        ct = kmem_cache_alloc(nf_conntrack_cachep, gfp);
        if (ct == NULL)
@@ -1159,7 +1159,7 @@ void nf_conntrack_free(struct nf_conn *ct)
        struct net *net = nf_ct_net(ct);
 
        /* A freed object has refcnt == 0, that's
-        * the golden rule for SLAB_DESTROY_BY_RCU
+        * the golden rule for SLAB_TYPESAFE_BY_RCU
         */
        NF_CT_ASSERT(atomic_read(&ct->ct_general.use) == 0);
 
@@ -1929,7 +1929,7 @@ int nf_conntrack_init_start(void)
        nf_conntrack_cachep = kmem_cache_create("nf_conntrack",
                                                sizeof(struct nf_conn),
                                                NFCT_INFOMASK + 1,
-                                               SLAB_DESTROY_BY_RCU | SLAB_HWCACHE_ALIGN, NULL);
+                                               SLAB_TYPESAFE_BY_RCU | SLAB_HWCACHE_ALIGN, NULL);
        if (!nf_conntrack_cachep)
                goto err_cachep;
 
index f134d384852ff2e9795cb8108b1387cfb3966f73..8876b7da6884c210393d1988032cbb5bd7018507 100644 (file)
@@ -763,17 +763,8 @@ EXPORT_SYMBOL(xt_check_entry_offsets);
  */
 unsigned int *xt_alloc_entry_offsets(unsigned int size)
 {
-       unsigned int *off;
+       return kvmalloc_array(size, sizeof(unsigned int), GFP_KERNEL | __GFP_ZERO);
 
-       off = kcalloc(size, sizeof(unsigned int), GFP_KERNEL | __GFP_NOWARN);
-
-       if (off)
-               return off;
-
-       if (size < (SIZE_MAX / sizeof(unsigned int)))
-               off = vmalloc(size * sizeof(unsigned int));
-
-       return off;
 }
 EXPORT_SYMBOL(xt_alloc_entry_offsets);
 
@@ -1007,8 +998,7 @@ struct xt_table_info *xt_alloc_table_info(unsigned int size)
        if (sz <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER))
                info = kmalloc(sz, GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY);
        if (!info) {
-               info = __vmalloc(sz, GFP_KERNEL | __GFP_NOWARN |
-                                    __GFP_NORETRY | __GFP_HIGHMEM,
+               info = __vmalloc(sz, GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY,
                                 PAGE_KERNEL);
                if (!info)
                        return NULL;
@@ -1116,7 +1106,7 @@ static int xt_jumpstack_alloc(struct xt_table_info *i)
 
        size = sizeof(void **) * nr_cpu_ids;
        if (size > PAGE_SIZE)
-               i->jumpstack = vzalloc(size);
+               i->jumpstack = kvzalloc(size, GFP_KERNEL);
        else
                i->jumpstack = kzalloc(size, GFP_KERNEL);
        if (i->jumpstack == NULL)
@@ -1138,12 +1128,8 @@ static int xt_jumpstack_alloc(struct xt_table_info *i)
         */
        size = sizeof(void *) * i->stacksize * 2u;
        for_each_possible_cpu(cpu) {
-               if (size > PAGE_SIZE)
-                       i->jumpstack[cpu] = vmalloc_node(size,
-                               cpu_to_node(cpu));
-               else
-                       i->jumpstack[cpu] = kmalloc_node(size,
-                               GFP_KERNEL, cpu_to_node(cpu));
+               i->jumpstack[cpu] = kvmalloc_node(size, GFP_KERNEL,
+                       cpu_to_node(cpu));
                if (i->jumpstack[cpu] == NULL)
                        /*
                         * Freeing will be done later on by the callers. The
index 37d581a31cffcee58cb73209dd53d0a18e3fc68f..3f6c4fa78bdb717c067b57b53a0900529dcc4000 100644 (file)
@@ -388,10 +388,7 @@ static int recent_mt_check(const struct xt_mtchk_param *par,
        }
 
        sz = sizeof(*t) + sizeof(t->iphash[0]) * ip_list_hash_size;
-       if (sz <= PAGE_SIZE)
-               t = kzalloc(sz, GFP_KERNEL);
-       else
-               t = vzalloc(sz);
+       t = kvzalloc(sz, GFP_KERNEL);
        if (t == NULL) {
                ret = -ENOMEM;
                goto out;
index f4001763134da35ed5f0f04bc2836015bb15a4af..e3eeed19cc7a130e80e24a3d67776a5b5a3c2698 100644 (file)
@@ -2658,13 +2658,6 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
                dev = dev_get_by_index(sock_net(&po->sk), saddr->sll_ifindex);
        }
 
-       sockc.tsflags = po->sk.sk_tsflags;
-       if (msg->msg_controllen) {
-               err = sock_cmsg_send(&po->sk, msg, &sockc);
-               if (unlikely(err))
-                       goto out;
-       }
-
        err = -ENXIO;
        if (unlikely(dev == NULL))
                goto out;
@@ -2672,6 +2665,13 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
        if (unlikely(!(dev->flags & IFF_UP)))
                goto out_put;
 
+       sockc.tsflags = po->sk.sk_tsflags;
+       if (msg->msg_controllen) {
+               err = sock_cmsg_send(&po->sk, msg, &sockc);
+               if (unlikely(err))
+                       goto out_put;
+       }
+
        if (po->sk.sk_socket->type == SOCK_RAW)
                reserve = dev->hard_header_len;
        size_max = po->tx_ring.frame_size
index bbe57d57b67fd498692bd41db49147511f1bb091..e88342fde1bc409aed6a3c86e7a628030eaac66f 100644 (file)
@@ -1831,6 +1831,12 @@ static int tc_dump_tclass_root(struct Qdisc *root, struct sk_buff *skb,
        if (!qdisc_dev(root))
                return 0;
 
+       if (tcm->tcm_parent) {
+               q = qdisc_match_from_root(root, TC_H_MAJ(tcm->tcm_parent));
+               if (q && tc_dump_tclass_qdisc(q, skb, tcm, cb, t_p, s_t) < 0)
+                       return -1;
+               return 0;
+       }
        hash_for_each(qdisc_dev(root)->qdisc_hash, b, q, hash) {
                if (tc_dump_tclass_qdisc(q, skb, tcm, cb, t_p, s_t) < 0)
                        return -1;
index d00f4c7c2f3af980b82281485e6fb31006765e92..b30a2c70bd489b36a2295a11707b6a36d4eb9ac0 100644 (file)
@@ -376,10 +376,7 @@ static int choke_change(struct Qdisc *sch, struct nlattr *opt)
        if (mask != q->tab_mask) {
                struct sk_buff **ntab;
 
-               ntab = kcalloc(mask + 1, sizeof(struct sk_buff *),
-                              GFP_KERNEL | __GFP_NOWARN);
-               if (!ntab)
-                       ntab = vzalloc((mask + 1) * sizeof(struct sk_buff *));
+               ntab = kvmalloc_array((mask + 1), sizeof(struct sk_buff *), GFP_KERNEL | __GFP_ZERO);
                if (!ntab)
                        return -ENOMEM;
 
index da4f67bda0ee148910cc79a7d64cdf85ce318beb..b488721a0059adb24aea47240afa0164a6e467a9 100644 (file)
@@ -624,16 +624,6 @@ static void fq_rehash(struct fq_sched_data *q,
        q->stat_gc_flows += fcnt;
 }
 
-static void *fq_alloc_node(size_t sz, int node)
-{
-       void *ptr;
-
-       ptr = kmalloc_node(sz, GFP_KERNEL | __GFP_REPEAT | __GFP_NOWARN, node);
-       if (!ptr)
-               ptr = vmalloc_node(sz, node);
-       return ptr;
-}
-
 static void fq_free(void *addr)
 {
        kvfree(addr);
@@ -650,7 +640,7 @@ static int fq_resize(struct Qdisc *sch, u32 log)
                return 0;
 
        /* If XPS was setup, we can allocate memory on right NUMA node */
-       array = fq_alloc_node(sizeof(struct rb_root) << log,
+       array = kvmalloc_node(sizeof(struct rb_root) << log, GFP_KERNEL | __GFP_REPEAT,
                              netdev_queue_numa_node_read(sch->dev_queue));
        if (!array)
                return -ENOMEM;
index 18bbb5476c836128dae1779c7b493cbb5c485e14..9201abce928cda39f099fc94d9fc96de1468a947 100644 (file)
@@ -446,27 +446,13 @@ static int fq_codel_change(struct Qdisc *sch, struct nlattr *opt)
        return 0;
 }
 
-static void *fq_codel_zalloc(size_t sz)
-{
-       void *ptr = kzalloc(sz, GFP_KERNEL | __GFP_NOWARN);
-
-       if (!ptr)
-               ptr = vzalloc(sz);
-       return ptr;
-}
-
-static void fq_codel_free(void *addr)
-{
-       kvfree(addr);
-}
-
 static void fq_codel_destroy(struct Qdisc *sch)
 {
        struct fq_codel_sched_data *q = qdisc_priv(sch);
 
        tcf_destroy_chain(&q->filter_list);
-       fq_codel_free(q->backlogs);
-       fq_codel_free(q->flows);
+       kvfree(q->backlogs);
+       kvfree(q->flows);
 }
 
 static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt)
@@ -493,13 +479,13 @@ static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt)
        }
 
        if (!q->flows) {
-               q->flows = fq_codel_zalloc(q->flows_cnt *
-                                          sizeof(struct fq_codel_flow));
+               q->flows = kvzalloc(q->flows_cnt *
+                                          sizeof(struct fq_codel_flow), GFP_KERNEL);
                if (!q->flows)
                        return -ENOMEM;
-               q->backlogs = fq_codel_zalloc(q->flows_cnt * sizeof(u32));
+               q->backlogs = kvzalloc(q->flows_cnt * sizeof(u32), GFP_KERNEL);
                if (!q->backlogs) {
-                       fq_codel_free(q->flows);
+                       kvfree(q->flows);
                        return -ENOMEM;
                }
                for (i = 0; i < q->flows_cnt; i++) {
index c19d346e6c5a438c051abf8ce4eb785d075d36c2..51d3ba682af9ba0f69a3f3c3036519bf527cdee0 100644 (file)
@@ -467,29 +467,14 @@ static void hhf_reset(struct Qdisc *sch)
                rtnl_kfree_skbs(skb, skb);
 }
 
-static void *hhf_zalloc(size_t sz)
-{
-       void *ptr = kzalloc(sz, GFP_KERNEL | __GFP_NOWARN);
-
-       if (!ptr)
-               ptr = vzalloc(sz);
-
-       return ptr;
-}
-
-static void hhf_free(void *addr)
-{
-       kvfree(addr);
-}
-
 static void hhf_destroy(struct Qdisc *sch)
 {
        int i;
        struct hhf_sched_data *q = qdisc_priv(sch);
 
        for (i = 0; i < HHF_ARRAYS_CNT; i++) {
-               hhf_free(q->hhf_arrays[i]);
-               hhf_free(q->hhf_valid_bits[i]);
+               kvfree(q->hhf_arrays[i]);
+               kvfree(q->hhf_valid_bits[i]);
        }
 
        for (i = 0; i < HH_FLOWS_CNT; i++) {
@@ -503,7 +488,7 @@ static void hhf_destroy(struct Qdisc *sch)
                        kfree(flow);
                }
        }
-       hhf_free(q->hh_flows);
+       kvfree(q->hh_flows);
 }
 
 static const struct nla_policy hhf_policy[TCA_HHF_MAX + 1] = {
@@ -609,8 +594,8 @@ static int hhf_init(struct Qdisc *sch, struct nlattr *opt)
 
        if (!q->hh_flows) {
                /* Initialize heavy-hitter flow table. */
-               q->hh_flows = hhf_zalloc(HH_FLOWS_CNT *
-                                        sizeof(struct list_head));
+               q->hh_flows = kvzalloc(HH_FLOWS_CNT *
+                                        sizeof(struct list_head), GFP_KERNEL);
                if (!q->hh_flows)
                        return -ENOMEM;
                for (i = 0; i < HH_FLOWS_CNT; i++)
@@ -624,8 +609,8 @@ static int hhf_init(struct Qdisc *sch, struct nlattr *opt)
 
                /* Initialize heavy-hitter filter arrays. */
                for (i = 0; i < HHF_ARRAYS_CNT; i++) {
-                       q->hhf_arrays[i] = hhf_zalloc(HHF_ARRAYS_LEN *
-                                                     sizeof(u32));
+                       q->hhf_arrays[i] = kvzalloc(HHF_ARRAYS_LEN *
+                                                     sizeof(u32), GFP_KERNEL);
                        if (!q->hhf_arrays[i]) {
                                /* Note: hhf_destroy() will be called
                                 * by our caller.
@@ -637,8 +622,8 @@ static int hhf_init(struct Qdisc *sch, struct nlattr *opt)
 
                /* Initialize valid bits of heavy-hitter filter arrays. */
                for (i = 0; i < HHF_ARRAYS_CNT; i++) {
-                       q->hhf_valid_bits[i] = hhf_zalloc(HHF_ARRAYS_LEN /
-                                                         BITS_PER_BYTE);
+                       q->hhf_valid_bits[i] = kvzalloc(HHF_ARRAYS_LEN /
+                                                         BITS_PER_BYTE, GFP_KERNEL);
                        if (!q->hhf_valid_bits[i]) {
                                /* Note: hhf_destroy() will be called
                                 * by our caller.
index f0ce4780f395c50683fbbd070c8fa3cb7eede7ec..1b3dd6190e9386c6f8104153eb9fdc0255e03ac5 100644 (file)
@@ -702,15 +702,11 @@ static int get_dist_table(struct Qdisc *sch, const struct nlattr *attr)
        spinlock_t *root_lock;
        struct disttable *d;
        int i;
-       size_t s;
 
        if (n > NETEM_DIST_MAX)
                return -EINVAL;
 
-       s = sizeof(struct disttable) + n * sizeof(s16);
-       d = kmalloc(s, GFP_KERNEL | __GFP_NOWARN);
-       if (!d)
-               d = vmalloc(s);
+       d = kvmalloc(sizeof(struct disttable) + n * sizeof(s16), GFP_KERNEL);
        if (!d)
                return -ENOMEM;
 
index b00e02c139de8d7c0b66ec6ee0d8b6c677529609..332d94be6e1cb09386307b6c16b6954244a805c9 100644 (file)
@@ -685,11 +685,7 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt)
 
 static void *sfq_alloc(size_t sz)
 {
-       void *ptr = kmalloc(sz, GFP_KERNEL | __GFP_NOWARN);
-
-       if (!ptr)
-               ptr = vmalloc(sz);
-       return ptr;
+       return  kvmalloc(sz, GFP_KERNEL);
 }
 
 static void sfq_free(void *addr)
index 961ee59f696a0b0a8b6c2bade0031a073dff53ad..f5b45b8b8b16e6965d24cd79b150828a608c2121 100644 (file)
@@ -240,12 +240,10 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
        struct sctp_bind_addr *bp;
        struct ipv6_pinfo *np = inet6_sk(sk);
        struct sctp_sockaddr_entry *laddr;
-       union sctp_addr *baddr = NULL;
        union sctp_addr *daddr = &t->ipaddr;
        union sctp_addr dst_saddr;
        struct in6_addr *final_p, final;
        __u8 matchlen = 0;
-       __u8 bmatchlen;
        sctp_scope_t scope;
 
        memset(fl6, 0, sizeof(struct flowi6));
@@ -312,23 +310,37 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
         */
        rcu_read_lock();
        list_for_each_entry_rcu(laddr, &bp->address_list, list) {
-               if (!laddr->valid)
+               struct dst_entry *bdst;
+               __u8 bmatchlen;
+
+               if (!laddr->valid ||
+                   laddr->state != SCTP_ADDR_SRC ||
+                   laddr->a.sa.sa_family != AF_INET6 ||
+                   scope > sctp_scope(&laddr->a))
                        continue;
-               if ((laddr->state == SCTP_ADDR_SRC) &&
-                   (laddr->a.sa.sa_family == AF_INET6) &&
-                   (scope <= sctp_scope(&laddr->a))) {
-                       bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a);
-                       if (!baddr || (matchlen < bmatchlen)) {
-                               baddr = &laddr->a;
-                               matchlen = bmatchlen;
-                       }
-               }
-       }
-       if (baddr) {
-               fl6->saddr = baddr->v6.sin6_addr;
-               fl6->fl6_sport = baddr->v6.sin6_port;
+
+               fl6->saddr = laddr->a.v6.sin6_addr;
+               fl6->fl6_sport = laddr->a.v6.sin6_port;
                final_p = fl6_update_dst(fl6, rcu_dereference(np->opt), &final);
-               dst = ip6_dst_lookup_flow(sk, fl6, final_p);
+               bdst = ip6_dst_lookup_flow(sk, fl6, final_p);
+
+               if (!IS_ERR(bdst) &&
+                   ipv6_chk_addr(dev_net(bdst->dev),
+                                 &laddr->a.v6.sin6_addr, bdst->dev, 1)) {
+                       if (!IS_ERR_OR_NULL(dst))
+                               dst_release(dst);
+                       dst = bdst;
+                       break;
+               }
+
+               bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a);
+               if (matchlen > bmatchlen)
+                       continue;
+
+               if (!IS_ERR_OR_NULL(dst))
+                       dst_release(dst);
+               dst = bdst;
+               matchlen = bmatchlen;
        }
        rcu_read_unlock();
 
@@ -665,6 +677,9 @@ static struct sock *sctp_v6_create_accept_sk(struct sock *sk,
        newnp = inet6_sk(newsk);
 
        memcpy(newnp, np, sizeof(struct ipv6_pinfo));
+       newnp->ipv6_mc_list = NULL;
+       newnp->ipv6_ac_list = NULL;
+       newnp->ipv6_fl_list = NULL;
 
        rcu_read_lock();
        opt = rcu_dereference(np->opt);
index c717ef0896aa2accaee05e3cf4c10d066c61eeb3..33954852f3f89b3bd05595a159e5c2ed56d074ad 100644 (file)
@@ -8,6 +8,10 @@ config SMC
          The Linux implementation of the SMC-R solution is designed as
          a separate socket family SMC.
 
+         Warning: SMC will expose all memory for remote reads and writes
+         once a connection is established.  Don't enable this option except
+         for tightly controlled lab environment.
+
          Select this option if you want to run SMC socket applications
 
 config SMC_DIAG
index 5b6ee21368a68b4c02a5b8987a09a6d6ee613a0e..6793d7348cc811f41395c5ca3a9d1f1390813646 100644 (file)
@@ -101,7 +101,7 @@ struct proto smc_proto = {
        .unhash         = smc_unhash_sk,
        .obj_size       = sizeof(struct smc_sock),
        .h.smc_hash     = &smc_v4_hashinfo,
-       .slab_flags     = SLAB_DESTROY_BY_RCU,
+       .slab_flags     = SLAB_TYPESAFE_BY_RCU,
 };
 EXPORT_SYMBOL_GPL(smc_proto);
 
index e41f594a1e1d0c3d47706e4c80f9de587f953c9b..03ec058d18df642ef7e219000a62e51bc6c0e6fe 100644 (file)
@@ -204,7 +204,7 @@ int smc_clc_send_confirm(struct smc_sock *smc)
        memcpy(&cclc.lcl.mac, &link->smcibdev->mac[link->ibport - 1], ETH_ALEN);
        hton24(cclc.qpn, link->roce_qp->qp_num);
        cclc.rmb_rkey =
-               htonl(conn->rmb_desc->mr_rx[SMC_SINGLE_LINK]->rkey);
+               htonl(conn->rmb_desc->rkey[SMC_SINGLE_LINK]);
        cclc.conn_idx = 1; /* for now: 1 RMB = 1 RMBE */
        cclc.rmbe_alert_token = htonl(conn->alert_token_local);
        cclc.qp_mtu = min(link->path_mtu, link->peer_mtu);
@@ -256,7 +256,7 @@ int smc_clc_send_accept(struct smc_sock *new_smc, int srv_first_contact)
        memcpy(&aclc.lcl.mac, link->smcibdev->mac[link->ibport - 1], ETH_ALEN);
        hton24(aclc.qpn, link->roce_qp->qp_num);
        aclc.rmb_rkey =
-               htonl(conn->rmb_desc->mr_rx[SMC_SINGLE_LINK]->rkey);
+               htonl(conn->rmb_desc->rkey[SMC_SINGLE_LINK]);
        aclc.conn_idx = 1;                      /* as long as 1 RMB = 1 RMBE */
        aclc.rmbe_alert_token = htonl(conn->alert_token_local);
        aclc.qp_mtu = link->path_mtu;
index 65020e93ff210bb7f5db079399984c55e54c80f1..3ac09a629ea1a4c38c6bc21d996a69611c1633b7 100644 (file)
@@ -613,19 +613,8 @@ int smc_rmb_create(struct smc_sock *smc)
                        rmb_desc = NULL;
                        continue; /* if mapping failed, try smaller one */
                }
-               rc = smc_ib_get_memory_region(lgr->lnk[SMC_SINGLE_LINK].roce_pd,
-                                             IB_ACCESS_REMOTE_WRITE |
-                                             IB_ACCESS_LOCAL_WRITE,
-                                            &rmb_desc->mr_rx[SMC_SINGLE_LINK]);
-               if (rc) {
-                       smc_ib_buf_unmap(lgr->lnk[SMC_SINGLE_LINK].smcibdev,
-                                        tmp_bufsize, rmb_desc,
-                                        DMA_FROM_DEVICE);
-                       kfree(rmb_desc->cpu_addr);
-                       kfree(rmb_desc);
-                       rmb_desc = NULL;
-                       continue;
-               }
+               rmb_desc->rkey[SMC_SINGLE_LINK] =
+                       lgr->lnk[SMC_SINGLE_LINK].roce_pd->unsafe_global_rkey;
                rmb_desc->used = 1;
                write_lock_bh(&lgr->rmbs_lock);
                list_add(&rmb_desc->list,
@@ -668,6 +657,7 @@ int smc_rmb_rtoken_handling(struct smc_connection *conn,
 
        for (i = 0; i < SMC_RMBS_PER_LGR_MAX; i++) {
                if ((lgr->rtokens[i][SMC_SINGLE_LINK].rkey == rkey) &&
+                   (lgr->rtokens[i][SMC_SINGLE_LINK].dma_addr == dma_addr) &&
                    test_bit(i, lgr->rtokens_used_mask)) {
                        conn->rtoken_idx = i;
                        return 0;
index 27eb38056a27fb07e3ce72afbacaffaf4ae55f73..b013cb43a327ea81cd8bc9e4a5ffff733f87f6a7 100644 (file)
@@ -93,7 +93,7 @@ struct smc_buf_desc {
        u64                     dma_addr[SMC_LINKS_PER_LGR_MAX];
                                                /* mapped address of buffer */
        void                    *cpu_addr;      /* virtual address of buffer */
-       struct ib_mr            *mr_rx[SMC_LINKS_PER_LGR_MAX];
+       u32                     rkey[SMC_LINKS_PER_LGR_MAX];
                                                /* for rmb only:
                                                 * rkey provided to peer
                                                 */
index cb69ab977cd73963fef1fe27b1407e58a6e7cadd..b31715505a358cd4e73d1af6c58a49ef7ef8ecbe 100644 (file)
@@ -37,24 +37,6 @@ u8 local_systemid[SMC_SYSTEMID_LEN] = SMC_LOCAL_SYSTEMID_RESET;      /* unique system
                                                                 * identifier
                                                                 */
 
-int smc_ib_get_memory_region(struct ib_pd *pd, int access_flags,
-                            struct ib_mr **mr)
-{
-       int rc;
-
-       if (*mr)
-               return 0; /* already done */
-
-       /* obtain unique key -
-        * next invocation of get_dma_mr returns a different key!
-        */
-       *mr = pd->device->get_dma_mr(pd, access_flags);
-       rc = PTR_ERR_OR_ZERO(*mr);
-       if (IS_ERR(*mr))
-               *mr = NULL;
-       return rc;
-}
-
 static int smc_ib_modify_qp_init(struct smc_link *lnk)
 {
        struct ib_qp_attr qp_attr;
@@ -210,7 +192,8 @@ int smc_ib_create_protection_domain(struct smc_link *lnk)
 {
        int rc;
 
-       lnk->roce_pd = ib_alloc_pd(lnk->smcibdev->ibdev, 0);
+       lnk->roce_pd = ib_alloc_pd(lnk->smcibdev->ibdev,
+                                  IB_PD_UNSAFE_GLOBAL_RKEY);
        rc = PTR_ERR_OR_ZERO(lnk->roce_pd);
        if (IS_ERR(lnk->roce_pd))
                lnk->roce_pd = NULL;
index 7e1f0e24d17790f526aa50d07ff5e5d6596b6f3c..b567152a526d48c86110a9574833e8610684af4b 100644 (file)
@@ -61,8 +61,6 @@ void smc_ib_dealloc_protection_domain(struct smc_link *lnk);
 int smc_ib_create_protection_domain(struct smc_link *lnk);
 void smc_ib_destroy_queue_pair(struct smc_link *lnk);
 int smc_ib_create_queue_pair(struct smc_link *lnk);
-int smc_ib_get_memory_region(struct ib_pd *pd, int access_flags,
-                            struct ib_mr **mr);
 int smc_ib_ready_link(struct smc_link *lnk);
 int smc_ib_modify_qp_rts(struct smc_link *lnk);
 int smc_ib_modify_qp_reset(struct smc_link *lnk);
index 04ce2c0b660e0d381a22038bb463d46312befaf5..ac09ca8032965bfd4280fb3f6d3410c08cbda243 100644 (file)
@@ -52,6 +52,7 @@ config SUNRPC_XPRT_RDMA
        tristate "RPC-over-RDMA transport"
        depends on SUNRPC && INFINIBAND && INFINIBAND_ADDR_TRANS
        default SUNRPC && INFINIBAND
+       select SG_POOL
        help
          This option allows the NFS client and server to use RDMA
          transports (InfiniBand, iWARP, or RoCE).
index 52da3ce54bb53c8434f0acc276c0003e385486e7..b5cb921775a0b20358f590b69b4cdfd0609a1acb 100644 (file)
@@ -1042,8 +1042,6 @@ struct rpc_task *rpc_run_task(const struct rpc_task_setup *task_setup_data)
        struct rpc_task *task;
 
        task = rpc_new_task(task_setup_data);
-       if (IS_ERR(task))
-               goto out;
 
        rpc_task_set_client(task, task_setup_data->rpc_client);
        rpc_task_set_rpc_message(task, task_setup_data->rpc_message);
@@ -1053,7 +1051,6 @@ struct rpc_task *rpc_run_task(const struct rpc_task_setup *task_setup_data)
 
        atomic_inc(&task->tk_count);
        rpc_execute(task);
-out:
        return task;
 }
 EXPORT_SYMBOL_GPL(rpc_run_task);
@@ -1140,10 +1137,6 @@ struct rpc_task *rpc_run_bc_task(struct rpc_rqst *req)
         * Create an rpc_task to send the data
         */
        task = rpc_new_task(&task_setup_data);
-       if (IS_ERR(task)) {
-               xprt_free_bc_request(req);
-               goto out;
-       }
        task->tk_rqstp = req;
 
        /*
@@ -1158,7 +1151,6 @@ struct rpc_task *rpc_run_bc_task(struct rpc_rqst *req)
        WARN_ON_ONCE(atomic_read(&task->tk_count) != 2);
        rpc_execute(task);
 
-out:
        dprintk("RPC: rpc_run_bc_task: task= %p\n", task);
        return task;
 }
index 5db68b371db2cac54e37cc0a883259dbc61125cb..0cc83839c13c3621a70a4b9e8ded773217a2edf3 100644 (file)
@@ -965,11 +965,6 @@ struct rpc_task *rpc_new_task(const struct rpc_task_setup *setup_data)
 
        if (task == NULL) {
                task = rpc_alloc_task();
-               if (task == NULL) {
-                       rpc_release_calldata(setup_data->callback_ops,
-                                       setup_data->callback_data);
-                       return ERR_PTR(-ENOMEM);
-               }
                flags = RPC_TASK_DYNAMIC;
        }
 
index a08aeb56b8e457d56285558048e4a41ab00b03c9..bc0f5a0ecbdce2a5203bf707ebfba8c99821d0f7 100644 (file)
@@ -702,59 +702,32 @@ found_pool:
        return task;
 }
 
-/*
- * Create or destroy enough new threads to make the number
- * of threads the given number.  If `pool' is non-NULL, applies
- * only to threads in that pool, otherwise round-robins between
- * all pools.  Caller must ensure that mutual exclusion between this and
- * server startup or shutdown.
- *
- * Destroying threads relies on the service threads filling in
- * rqstp->rq_task, which only the nfs ones do.  Assumes the serv
- * has been created using svc_create_pooled().
- *
- * Based on code that used to be in nfsd_svc() but tweaked
- * to be pool-aware.
- */
-int
-svc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
+/* create new threads */
+static int
+svc_start_kthreads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
 {
        struct svc_rqst *rqstp;
        struct task_struct *task;
        struct svc_pool *chosen_pool;
-       int error = 0;
        unsigned int state = serv->sv_nrthreads-1;
        int node;
 
-       if (pool == NULL) {
-               /* The -1 assumes caller has done a svc_get() */
-               nrservs -= (serv->sv_nrthreads-1);
-       } else {
-               spin_lock_bh(&pool->sp_lock);
-               nrservs -= pool->sp_nrthreads;
-               spin_unlock_bh(&pool->sp_lock);
-       }
-
-       /* create new threads */
-       while (nrservs > 0) {
+       do {
                nrservs--;
                chosen_pool = choose_pool(serv, pool, &state);
 
                node = svc_pool_map_get_node(chosen_pool->sp_id);
                rqstp = svc_prepare_thread(serv, chosen_pool, node);
-               if (IS_ERR(rqstp)) {
-                       error = PTR_ERR(rqstp);
-                       break;
-               }
+               if (IS_ERR(rqstp))
+                       return PTR_ERR(rqstp);
 
                __module_get(serv->sv_ops->svo_module);
                task = kthread_create_on_node(serv->sv_ops->svo_function, rqstp,
                                              node, "%s", serv->sv_name);
                if (IS_ERR(task)) {
-                       error = PTR_ERR(task);
                        module_put(serv->sv_ops->svo_module);
                        svc_exit_thread(rqstp);
-                       break;
+                       return PTR_ERR(task);
                }
 
                rqstp->rq_task = task;
@@ -763,18 +736,103 @@ svc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
 
                svc_sock_update_bufs(serv);
                wake_up_process(task);
-       }
+       } while (nrservs > 0);
+
+       return 0;
+}
+
+
+/* destroy old threads */
+static int
+svc_signal_kthreads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
+{
+       struct task_struct *task;
+       unsigned int state = serv->sv_nrthreads-1;
+
        /* destroy old threads */
-       while (nrservs < 0 &&
-              (task = choose_victim(serv, pool, &state)) != NULL) {
+       do {
+               task = choose_victim(serv, pool, &state);
+               if (task == NULL)
+                       break;
                send_sig(SIGINT, task, 1);
                nrservs++;
+       } while (nrservs < 0);
+
+       return 0;
+}
+
+/*
+ * Create or destroy enough new threads to make the number
+ * of threads the given number.  If `pool' is non-NULL, applies
+ * only to threads in that pool, otherwise round-robins between
+ * all pools.  Caller must ensure that mutual exclusion between this and
+ * server startup or shutdown.
+ *
+ * Destroying threads relies on the service threads filling in
+ * rqstp->rq_task, which only the nfs ones do.  Assumes the serv
+ * has been created using svc_create_pooled().
+ *
+ * Based on code that used to be in nfsd_svc() but tweaked
+ * to be pool-aware.
+ */
+int
+svc_set_num_threads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
+{
+       if (pool == NULL) {
+               /* The -1 assumes caller has done a svc_get() */
+               nrservs -= (serv->sv_nrthreads-1);
+       } else {
+               spin_lock_bh(&pool->sp_lock);
+               nrservs -= pool->sp_nrthreads;
+               spin_unlock_bh(&pool->sp_lock);
        }
 
-       return error;
+       if (nrservs > 0)
+               return svc_start_kthreads(serv, pool, nrservs);
+       if (nrservs < 0)
+               return svc_signal_kthreads(serv, pool, nrservs);
+       return 0;
 }
 EXPORT_SYMBOL_GPL(svc_set_num_threads);
 
+/* destroy old threads */
+static int
+svc_stop_kthreads(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
+{
+       struct task_struct *task;
+       unsigned int state = serv->sv_nrthreads-1;
+
+       /* destroy old threads */
+       do {
+               task = choose_victim(serv, pool, &state);
+               if (task == NULL)
+                       break;
+               kthread_stop(task);
+               nrservs++;
+       } while (nrservs < 0);
+       return 0;
+}
+
+int
+svc_set_num_threads_sync(struct svc_serv *serv, struct svc_pool *pool, int nrservs)
+{
+       if (pool == NULL) {
+               /* The -1 assumes caller has done a svc_get() */
+               nrservs -= (serv->sv_nrthreads-1);
+       } else {
+               spin_lock_bh(&pool->sp_lock);
+               nrservs -= pool->sp_nrthreads;
+               spin_unlock_bh(&pool->sp_lock);
+       }
+
+       if (nrservs > 0)
+               return svc_start_kthreads(serv, pool, nrservs);
+       if (nrservs < 0)
+               return svc_stop_kthreads(serv, pool, nrservs);
+       return 0;
+}
+EXPORT_SYMBOL_GPL(svc_set_num_threads_sync);
+
 /*
  * Called from a server thread as it's exiting. Caller must hold the "service
  * mutex" for the service.
index 1f7082144e0168070a9e8ed703ca044f9700b8dc..e34f4ee7f2b6cecdf404daab0d3aab363d94ba01 100644 (file)
@@ -807,7 +807,7 @@ void xdr_init_decode(struct xdr_stream *xdr, struct xdr_buf *buf, __be32 *p)
 EXPORT_SYMBOL_GPL(xdr_init_decode);
 
 /**
- * xdr_init_decode - Initialize an xdr_stream for decoding data.
+ * xdr_init_decode_pages - Initialize an xdr_stream for decoding into pages
  * @xdr: pointer to xdr_stream struct
  * @buf: pointer to XDR buffer from which to decode data
  * @pages: list of pages to decode into
index b530a2852ba87ac042baec67bf64a3e57e1232b5..3e63c5e97ebe67875f98836eae254f7d3c3460ba 100644 (file)
@@ -651,6 +651,7 @@ void xprt_force_disconnect(struct rpc_xprt *xprt)
        xprt_wake_pending_tasks(xprt, -EAGAIN);
        spin_unlock_bh(&xprt->transport_lock);
 }
+EXPORT_SYMBOL_GPL(xprt_force_disconnect);
 
 /**
  * xprt_conditional_disconnect - force a transport to disconnect
index ef19fa42c50ff2e15ecdee7d87f1207ffc3c445c..c1ae8142ab734739c8631e537f0c1157e8e06a60 100644 (file)
@@ -4,5 +4,5 @@ rpcrdma-y := transport.o rpc_rdma.o verbs.o \
        fmr_ops.o frwr_ops.o \
        svc_rdma.o svc_rdma_backchannel.o svc_rdma_transport.o \
        svc_rdma_marshal.o svc_rdma_sendto.o svc_rdma_recvfrom.o \
-       module.o
+       svc_rdma_rw.o module.o
 rpcrdma-$(CONFIG_SUNRPC_BACKCHANNEL) += backchannel.o
index a044be2d6ad726eccfbd991038086aefc746df47..694e9b13ecf07722848d86345589ad4793474fb5 100644 (file)
@@ -494,7 +494,7 @@ rpcrdma_prepare_hdr_sge(struct rpcrdma_ia *ia, struct rpcrdma_req *req,
        }
        sge->length = len;
 
-       ib_dma_sync_single_for_device(ia->ri_device, sge->addr,
+       ib_dma_sync_single_for_device(rdmab_device(rb), sge->addr,
                                      sge->length, DMA_TO_DEVICE);
        req->rl_send_wr.num_sge++;
        return true;
@@ -523,7 +523,7 @@ rpcrdma_prepare_msg_sges(struct rpcrdma_ia *ia, struct rpcrdma_req *req,
        sge[sge_no].addr = rdmab_addr(rb);
        sge[sge_no].length = xdr->head[0].iov_len;
        sge[sge_no].lkey = rdmab_lkey(rb);
-       ib_dma_sync_single_for_device(device, sge[sge_no].addr,
+       ib_dma_sync_single_for_device(rdmab_device(rb), sge[sge_no].addr,
                                      sge[sge_no].length, DMA_TO_DEVICE);
 
        /* If there is a Read chunk, the page list is being handled
@@ -781,9 +781,11 @@ rpcrdma_marshal_req(struct rpc_rqst *rqst)
        return 0;
 
 out_err:
-       pr_err("rpcrdma: rpcrdma_marshal_req failed, status %ld\n",
-              PTR_ERR(iptr));
-       r_xprt->rx_stats.failed_marshal_count++;
+       if (PTR_ERR(iptr) != -ENOBUFS) {
+               pr_err("rpcrdma: rpcrdma_marshal_req failed, status %ld\n",
+                      PTR_ERR(iptr));
+               r_xprt->rx_stats.failed_marshal_count++;
+       }
        return PTR_ERR(iptr);
 }
 
index c846ca9f1ebaa661f1e4a93893752950d35a4b6a..a4a8f6989ee747a1a5046e1e5cff92a0ca167775 100644 (file)
@@ -58,9 +58,9 @@ unsigned int svcrdma_max_requests = RPCRDMA_MAX_REQUESTS;
 unsigned int svcrdma_max_bc_requests = RPCRDMA_MAX_BC_REQUESTS;
 static unsigned int min_max_requests = 4;
 static unsigned int max_max_requests = 16384;
-unsigned int svcrdma_max_req_size = RPCRDMA_MAX_REQ_SIZE;
-static unsigned int min_max_inline = 4096;
-static unsigned int max_max_inline = 65536;
+unsigned int svcrdma_max_req_size = RPCRDMA_DEF_INLINE_THRESH;
+static unsigned int min_max_inline = RPCRDMA_DEF_INLINE_THRESH;
+static unsigned int max_max_inline = RPCRDMA_MAX_INLINE_THRESH;
 
 atomic_t rdma_stat_recv;
 atomic_t rdma_stat_read;
@@ -247,8 +247,6 @@ int svc_rdma_init(void)
        dprintk("SVCRDMA Module Init, register RPC RDMA transport\n");
        dprintk("\tsvcrdma_ord      : %d\n", svcrdma_ord);
        dprintk("\tmax_requests     : %u\n", svcrdma_max_requests);
-       dprintk("\tsq_depth         : %u\n",
-               svcrdma_max_requests * RPCRDMA_SQ_DEPTH_MULT);
        dprintk("\tmax_bc_requests  : %u\n", svcrdma_max_bc_requests);
        dprintk("\tmax_inline       : %d\n", svcrdma_max_req_size);
 
index ff1df40f0d261bc956f1af3410d8780f4c582b83..c676ed0efb5af2cceb6ed59e238a0f7a0109f916 100644 (file)
 
 #undef SVCRDMA_BACKCHANNEL_DEBUG
 
-int svc_rdma_handle_bc_reply(struct rpc_xprt *xprt, struct rpcrdma_msg *rmsgp,
+/**
+ * svc_rdma_handle_bc_reply - Process incoming backchannel reply
+ * @xprt: controlling backchannel transport
+ * @rdma_resp: pointer to incoming transport header
+ * @rcvbuf: XDR buffer into which to decode the reply
+ *
+ * Returns:
+ *     %0 if @rcvbuf is filled in, xprt_complete_rqst called,
+ *     %-EAGAIN if server should call ->recvfrom again.
+ */
+int svc_rdma_handle_bc_reply(struct rpc_xprt *xprt, __be32 *rdma_resp,
                             struct xdr_buf *rcvbuf)
 {
        struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt);
@@ -27,13 +37,13 @@ int svc_rdma_handle_bc_reply(struct rpc_xprt *xprt, struct rpcrdma_msg *rmsgp,
 
        p = (__be32 *)src->iov_base;
        len = src->iov_len;
-       xid = rmsgp->rm_xid;
+       xid = *rdma_resp;
 
 #ifdef SVCRDMA_BACKCHANNEL_DEBUG
        pr_info("%s: xid=%08x, length=%zu\n",
                __func__, be32_to_cpu(xid), len);
        pr_info("%s: RPC/RDMA: %*ph\n",
-               __func__, (int)RPCRDMA_HDRLEN_MIN, rmsgp);
+               __func__, (int)RPCRDMA_HDRLEN_MIN, rdma_resp);
        pr_info("%s:      RPC: %*ph\n",
                __func__, (int)len, p);
 #endif
@@ -53,7 +63,7 @@ int svc_rdma_handle_bc_reply(struct rpc_xprt *xprt, struct rpcrdma_msg *rmsgp,
                goto out_unlock;
        memcpy(dst->iov_base, p, len);
 
-       credits = be32_to_cpu(rmsgp->rm_credit);
+       credits = be32_to_cpup(rdma_resp + 2);
        if (credits == 0)
                credits = 1;    /* don't deadlock */
        else if (credits > r_xprt->rx_buf.rb_bc_max_requests)
@@ -90,9 +100,9 @@ out_notfound:
  * Caller holds the connection's mutex and has already marshaled
  * the RPC/RDMA request.
  *
- * This is similar to svc_rdma_reply, but takes an rpc_rqst
- * instead, does not support chunks, and avoids blocking memory
- * allocation.
+ * This is similar to svc_rdma_send_reply_msg, but takes a struct
+ * rpc_rqst instead, does not support chunks, and avoids blocking
+ * memory allocation.
  *
  * XXX: There is still an opportunity to block in svc_rdma_send()
  * if there are no SQ entries to post the Send. This may occur if
@@ -101,59 +111,36 @@ out_notfound:
 static int svc_rdma_bc_sendto(struct svcxprt_rdma *rdma,
                              struct rpc_rqst *rqst)
 {
-       struct xdr_buf *sndbuf = &rqst->rq_snd_buf;
        struct svc_rdma_op_ctxt *ctxt;
-       struct svc_rdma_req_map *vec;
-       struct ib_send_wr send_wr;
        int ret;
 
-       vec = svc_rdma_get_req_map(rdma);
-       ret = svc_rdma_map_xdr(rdma, sndbuf, vec, false);
-       if (ret)
+       ctxt = svc_rdma_get_context(rdma);
+
+       /* rpcrdma_bc_send_request builds the transport header and
+        * the backchannel RPC message in the same buffer. Thus only
+        * one SGE is needed to send both.
+        */
+       ret = svc_rdma_map_reply_hdr(rdma, ctxt, rqst->rq_buffer,
+                                    rqst->rq_snd_buf.len);
+       if (ret < 0)
                goto out_err;
 
        ret = svc_rdma_repost_recv(rdma, GFP_NOIO);
        if (ret)
                goto out_err;
 
-       ctxt = svc_rdma_get_context(rdma);
-       ctxt->pages[0] = virt_to_page(rqst->rq_buffer);
-       ctxt->count = 1;
-
-       ctxt->direction = DMA_TO_DEVICE;
-       ctxt->sge[0].lkey = rdma->sc_pd->local_dma_lkey;
-       ctxt->sge[0].length = sndbuf->len;
-       ctxt->sge[0].addr =
-           ib_dma_map_page(rdma->sc_cm_id->device, ctxt->pages[0], 0,
-                           sndbuf->len, DMA_TO_DEVICE);
-       if (ib_dma_mapping_error(rdma->sc_cm_id->device, ctxt->sge[0].addr)) {
-               ret = -EIO;
-               goto out_unmap;
-       }
-       svc_rdma_count_mappings(rdma, ctxt);
-
-       memset(&send_wr, 0, sizeof(send_wr));
-       ctxt->cqe.done = svc_rdma_wc_send;
-       send_wr.wr_cqe = &ctxt->cqe;
-       send_wr.sg_list = ctxt->sge;
-       send_wr.num_sge = 1;
-       send_wr.opcode = IB_WR_SEND;
-       send_wr.send_flags = IB_SEND_SIGNALED;
-
-       ret = svc_rdma_send(rdma, &send_wr);
-       if (ret) {
-               ret = -EIO;
+       ret = svc_rdma_post_send_wr(rdma, ctxt, 1, 0);
+       if (ret)
                goto out_unmap;
-       }
 
 out_err:
-       svc_rdma_put_req_map(rdma, vec);
        dprintk("svcrdma: %s returns %d\n", __func__, ret);
        return ret;
 
 out_unmap:
        svc_rdma_unmap_dma(ctxt);
        svc_rdma_put_context(ctxt, 1);
+       ret = -EIO;
        goto out_err;
 }
 
index 1c4aabf0f65772c13265421262feb030ab4a58ca..bdcf7d85a3dc098e63ca3ff77309496262b39b76 100644 (file)
@@ -166,92 +166,3 @@ out_inval:
        dprintk("svcrdma: failed to parse transport header\n");
        return -EINVAL;
 }
-
-int svc_rdma_xdr_encode_error(struct svcxprt_rdma *xprt,
-                             struct rpcrdma_msg *rmsgp,
-                             enum rpcrdma_errcode err, __be32 *va)
-{
-       __be32 *startp = va;
-
-       *va++ = rmsgp->rm_xid;
-       *va++ = rmsgp->rm_vers;
-       *va++ = xprt->sc_fc_credits;
-       *va++ = rdma_error;
-       *va++ = cpu_to_be32(err);
-       if (err == ERR_VERS) {
-               *va++ = rpcrdma_version;
-               *va++ = rpcrdma_version;
-       }
-
-       return (int)((unsigned long)va - (unsigned long)startp);
-}
-
-/**
- * svc_rdma_xdr_get_reply_hdr_length - Get length of Reply transport header
- * @rdma_resp: buffer containing Reply transport header
- *
- * Returns length of transport header, in bytes.
- */
-unsigned int svc_rdma_xdr_get_reply_hdr_len(__be32 *rdma_resp)
-{
-       unsigned int nsegs;
-       __be32 *p;
-
-       p = rdma_resp;
-
-       /* RPC-over-RDMA V1 replies never have a Read list. */
-       p += rpcrdma_fixed_maxsz + 1;
-
-       /* Skip Write list. */
-       while (*p++ != xdr_zero) {
-               nsegs = be32_to_cpup(p++);
-               p += nsegs * rpcrdma_segment_maxsz;
-       }
-
-       /* Skip Reply chunk. */
-       if (*p++ != xdr_zero) {
-               nsegs = be32_to_cpup(p++);
-               p += nsegs * rpcrdma_segment_maxsz;
-       }
-
-       return (unsigned long)p - (unsigned long)rdma_resp;
-}
-
-void svc_rdma_xdr_encode_write_list(struct rpcrdma_msg *rmsgp, int chunks)
-{
-       struct rpcrdma_write_array *ary;
-
-       /* no read-list */
-       rmsgp->rm_body.rm_chunks[0] = xdr_zero;
-
-       /* write-array discrim */
-       ary = (struct rpcrdma_write_array *)
-               &rmsgp->rm_body.rm_chunks[1];
-       ary->wc_discrim = xdr_one;
-       ary->wc_nchunks = cpu_to_be32(chunks);
-
-       /* write-list terminator */
-       ary->wc_array[chunks].wc_target.rs_handle = xdr_zero;
-
-       /* reply-array discriminator */
-       ary->wc_array[chunks].wc_target.rs_length = xdr_zero;
-}
-
-void svc_rdma_xdr_encode_reply_array(struct rpcrdma_write_array *ary,
-                                int chunks)
-{
-       ary->wc_discrim = xdr_one;
-       ary->wc_nchunks = cpu_to_be32(chunks);
-}
-
-void svc_rdma_xdr_encode_array_chunk(struct rpcrdma_write_array *ary,
-                                    int chunk_no,
-                                    __be32 rs_handle,
-                                    __be64 rs_offset,
-                                    u32 write_len)
-{
-       struct rpcrdma_segment *seg = &ary->wc_array[chunk_no].wc_target;
-       seg->rs_handle = rs_handle;
-       seg->rs_offset = rs_offset;
-       seg->rs_length = cpu_to_be32(write_len);
-}
index f7b2daf72a86582807798379ac3be336b061a958..27a99bf5b1a6f669be74f86347c7a16e3ce213fe 100644 (file)
@@ -558,33 +558,85 @@ static void rdma_read_complete(struct svc_rqst *rqstp,
        rqstp->rq_arg.buflen = head->arg.buflen;
 }
 
+static void svc_rdma_send_error(struct svcxprt_rdma *xprt,
+                               __be32 *rdma_argp, int status)
+{
+       struct svc_rdma_op_ctxt *ctxt;
+       __be32 *p, *err_msgp;
+       unsigned int length;
+       struct page *page;
+       int ret;
+
+       ret = svc_rdma_repost_recv(xprt, GFP_KERNEL);
+       if (ret)
+               return;
+
+       page = alloc_page(GFP_KERNEL);
+       if (!page)
+               return;
+       err_msgp = page_address(page);
+
+       p = err_msgp;
+       *p++ = *rdma_argp;
+       *p++ = *(rdma_argp + 1);
+       *p++ = xprt->sc_fc_credits;
+       *p++ = rdma_error;
+       if (status == -EPROTONOSUPPORT) {
+               *p++ = err_vers;
+               *p++ = rpcrdma_version;
+               *p++ = rpcrdma_version;
+       } else {
+               *p++ = err_chunk;
+       }
+       length = (unsigned long)p - (unsigned long)err_msgp;
+
+       /* Map transport header; no RPC message payload */
+       ctxt = svc_rdma_get_context(xprt);
+       ret = svc_rdma_map_reply_hdr(xprt, ctxt, err_msgp, length);
+       if (ret) {
+               dprintk("svcrdma: Error %d mapping send for protocol error\n",
+                       ret);
+               return;
+       }
+
+       ret = svc_rdma_post_send_wr(xprt, ctxt, 1, 0);
+       if (ret) {
+               dprintk("svcrdma: Error %d posting send for protocol error\n",
+                       ret);
+               svc_rdma_unmap_dma(ctxt);
+               svc_rdma_put_context(ctxt, 1);
+       }
+}
+
 /* By convention, backchannel calls arrive via rdma_msg type
  * messages, and never populate the chunk lists. This makes
  * the RPC/RDMA header small and fixed in size, so it is
  * straightforward to check the RPC header's direction field.
  */
-static bool
-svc_rdma_is_backchannel_reply(struct svc_xprt *xprt, struct rpcrdma_msg *rmsgp)
+static bool svc_rdma_is_backchannel_reply(struct svc_xprt *xprt,
+                                         __be32 *rdma_resp)
 {
-       __be32 *p = (__be32 *)rmsgp;
+       __be32 *p;
 
        if (!xprt->xpt_bc_xprt)
                return false;
 
-       if (rmsgp->rm_type != rdma_msg)
+       p = rdma_resp + 3;
+       if (*p++ != rdma_msg)
                return false;
-       if (rmsgp->rm_body.rm_chunks[0] != xdr_zero)
+
+       if (*p++ != xdr_zero)
                return false;
-       if (rmsgp->rm_body.rm_chunks[1] != xdr_zero)
+       if (*p++ != xdr_zero)
                return false;
-       if (rmsgp->rm_body.rm_chunks[2] != xdr_zero)
+       if (*p++ != xdr_zero)
                return false;
 
-       /* sanity */
-       if (p[7] != rmsgp->rm_xid)
+       /* XID sanity */
+       if (*p++ != *rdma_resp)
                return false;
        /* call direction */
-       if (p[8] == cpu_to_be32(RPC_CALL))
+       if (*p == cpu_to_be32(RPC_CALL))
                return false;
 
        return true;
@@ -650,8 +702,9 @@ int svc_rdma_recvfrom(struct svc_rqst *rqstp)
                goto out_drop;
        rqstp->rq_xprt_hlen = ret;
 
-       if (svc_rdma_is_backchannel_reply(xprt, rmsgp)) {
-               ret = svc_rdma_handle_bc_reply(xprt->xpt_bc_xprt, rmsgp,
+       if (svc_rdma_is_backchannel_reply(xprt, &rmsgp->rm_xid)) {
+               ret = svc_rdma_handle_bc_reply(xprt->xpt_bc_xprt,
+                                              &rmsgp->rm_xid,
                                               &rqstp->rq_arg);
                svc_rdma_put_context(ctxt, 0);
                if (ret)
@@ -686,7 +739,7 @@ complete:
        return ret;
 
 out_err:
-       svc_rdma_send_error(rdma_xprt, rmsgp, ret);
+       svc_rdma_send_error(rdma_xprt, &rmsgp->rm_xid, ret);
        svc_rdma_put_context(ctxt, 0);
        return 0;
 
diff --git a/net/sunrpc/xprtrdma/svc_rdma_rw.c b/net/sunrpc/xprtrdma/svc_rdma_rw.c
new file mode 100644 (file)
index 0000000..0cf6202
--- /dev/null
@@ -0,0 +1,512 @@
+/*
+ * Copyright (c) 2016 Oracle.  All rights reserved.
+ *
+ * Use the core R/W API to move RPC-over-RDMA Read and Write chunks.
+ */
+
+#include <linux/sunrpc/rpc_rdma.h>
+#include <linux/sunrpc/svc_rdma.h>
+#include <linux/sunrpc/debug.h>
+
+#include <rdma/rw.h>
+
+#define RPCDBG_FACILITY        RPCDBG_SVCXPRT
+
+/* Each R/W context contains state for one chain of RDMA Read or
+ * Write Work Requests.
+ *
+ * Each WR chain handles a single contiguous server-side buffer,
+ * because scatterlist entries after the first have to start on
+ * page alignment. xdr_buf iovecs cannot guarantee alignment.
+ *
+ * Each WR chain handles only one R_key. Each RPC-over-RDMA segment
+ * from a client may contain a unique R_key, so each WR chain moves
+ * up to one segment at a time.
+ *
+ * The scatterlist makes this data structure over 4KB in size. To
+ * make it less likely to fail, and to handle the allocation for
+ * smaller I/O requests without disabling bottom-halves, these
+ * contexts are created on demand, but cached and reused until the
+ * controlling svcxprt_rdma is destroyed.
+ */
+struct svc_rdma_rw_ctxt {
+       struct list_head        rw_list;
+       struct rdma_rw_ctx      rw_ctx;
+       int                     rw_nents;
+       struct sg_table         rw_sg_table;
+       struct scatterlist      rw_first_sgl[0];
+};
+
+static inline struct svc_rdma_rw_ctxt *
+svc_rdma_next_ctxt(struct list_head *list)
+{
+       return list_first_entry_or_null(list, struct svc_rdma_rw_ctxt,
+                                       rw_list);
+}
+
+static struct svc_rdma_rw_ctxt *
+svc_rdma_get_rw_ctxt(struct svcxprt_rdma *rdma, unsigned int sges)
+{
+       struct svc_rdma_rw_ctxt *ctxt;
+
+       spin_lock(&rdma->sc_rw_ctxt_lock);
+
+       ctxt = svc_rdma_next_ctxt(&rdma->sc_rw_ctxts);
+       if (ctxt) {
+               list_del(&ctxt->rw_list);
+               spin_unlock(&rdma->sc_rw_ctxt_lock);
+       } else {
+               spin_unlock(&rdma->sc_rw_ctxt_lock);
+               ctxt = kmalloc(sizeof(*ctxt) +
+                              SG_CHUNK_SIZE * sizeof(struct scatterlist),
+                              GFP_KERNEL);
+               if (!ctxt)
+                       goto out;
+               INIT_LIST_HEAD(&ctxt->rw_list);
+       }
+
+       ctxt->rw_sg_table.sgl = ctxt->rw_first_sgl;
+       if (sg_alloc_table_chained(&ctxt->rw_sg_table, sges,
+                                  ctxt->rw_sg_table.sgl)) {
+               kfree(ctxt);
+               ctxt = NULL;
+       }
+out:
+       return ctxt;
+}
+
+static void svc_rdma_put_rw_ctxt(struct svcxprt_rdma *rdma,
+                                struct svc_rdma_rw_ctxt *ctxt)
+{
+       sg_free_table_chained(&ctxt->rw_sg_table, true);
+
+       spin_lock(&rdma->sc_rw_ctxt_lock);
+       list_add(&ctxt->rw_list, &rdma->sc_rw_ctxts);
+       spin_unlock(&rdma->sc_rw_ctxt_lock);
+}
+
+/**
+ * svc_rdma_destroy_rw_ctxts - Free accumulated R/W contexts
+ * @rdma: transport about to be destroyed
+ *
+ */
+void svc_rdma_destroy_rw_ctxts(struct svcxprt_rdma *rdma)
+{
+       struct svc_rdma_rw_ctxt *ctxt;
+
+       while ((ctxt = svc_rdma_next_ctxt(&rdma->sc_rw_ctxts)) != NULL) {
+               list_del(&ctxt->rw_list);
+               kfree(ctxt);
+       }
+}
+
+/* A chunk context tracks all I/O for moving one Read or Write
+ * chunk. This is a a set of rdma_rw's that handle data movement
+ * for all segments of one chunk.
+ *
+ * These are small, acquired with a single allocator call, and
+ * no more than one is needed per chunk. They are allocated on
+ * demand, and not cached.
+ */
+struct svc_rdma_chunk_ctxt {
+       struct ib_cqe           cc_cqe;
+       struct svcxprt_rdma     *cc_rdma;
+       struct list_head        cc_rwctxts;
+       int                     cc_sqecount;
+       enum dma_data_direction cc_dir;
+};
+
+static void svc_rdma_cc_init(struct svcxprt_rdma *rdma,
+                            struct svc_rdma_chunk_ctxt *cc,
+                            enum dma_data_direction dir)
+{
+       cc->cc_rdma = rdma;
+       svc_xprt_get(&rdma->sc_xprt);
+
+       INIT_LIST_HEAD(&cc->cc_rwctxts);
+       cc->cc_sqecount = 0;
+       cc->cc_dir = dir;
+}
+
+static void svc_rdma_cc_release(struct svc_rdma_chunk_ctxt *cc)
+{
+       struct svcxprt_rdma *rdma = cc->cc_rdma;
+       struct svc_rdma_rw_ctxt *ctxt;
+
+       while ((ctxt = svc_rdma_next_ctxt(&cc->cc_rwctxts)) != NULL) {
+               list_del(&ctxt->rw_list);
+
+               rdma_rw_ctx_destroy(&ctxt->rw_ctx, rdma->sc_qp,
+                                   rdma->sc_port_num, ctxt->rw_sg_table.sgl,
+                                   ctxt->rw_nents, cc->cc_dir);
+               svc_rdma_put_rw_ctxt(rdma, ctxt);
+       }
+       svc_xprt_put(&rdma->sc_xprt);
+}
+
+/* State for sending a Write or Reply chunk.
+ *  - Tracks progress of writing one chunk over all its segments
+ *  - Stores arguments for the SGL constructor functions
+ */
+struct svc_rdma_write_info {
+       /* write state of this chunk */
+       unsigned int            wi_seg_off;
+       unsigned int            wi_seg_no;
+       unsigned int            wi_nsegs;
+       __be32                  *wi_segs;
+
+       /* SGL constructor arguments */
+       struct xdr_buf          *wi_xdr;
+       unsigned char           *wi_base;
+       unsigned int            wi_next_off;
+
+       struct svc_rdma_chunk_ctxt      wi_cc;
+};
+
+static struct svc_rdma_write_info *
+svc_rdma_write_info_alloc(struct svcxprt_rdma *rdma, __be32 *chunk)
+{
+       struct svc_rdma_write_info *info;
+
+       info = kmalloc(sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return info;
+
+       info->wi_seg_off = 0;
+       info->wi_seg_no = 0;
+       info->wi_nsegs = be32_to_cpup(++chunk);
+       info->wi_segs = ++chunk;
+       svc_rdma_cc_init(rdma, &info->wi_cc, DMA_TO_DEVICE);
+       return info;
+}
+
+static void svc_rdma_write_info_free(struct svc_rdma_write_info *info)
+{
+       svc_rdma_cc_release(&info->wi_cc);
+       kfree(info);
+}
+
+/**
+ * svc_rdma_write_done - Write chunk completion
+ * @cq: controlling Completion Queue
+ * @wc: Work Completion
+ *
+ * Pages under I/O are freed by a subsequent Send completion.
+ */
+static void svc_rdma_write_done(struct ib_cq *cq, struct ib_wc *wc)
+{
+       struct ib_cqe *cqe = wc->wr_cqe;
+       struct svc_rdma_chunk_ctxt *cc =
+                       container_of(cqe, struct svc_rdma_chunk_ctxt, cc_cqe);
+       struct svcxprt_rdma *rdma = cc->cc_rdma;
+       struct svc_rdma_write_info *info =
+                       container_of(cc, struct svc_rdma_write_info, wi_cc);
+
+       atomic_add(cc->cc_sqecount, &rdma->sc_sq_avail);
+       wake_up(&rdma->sc_send_wait);
+
+       if (unlikely(wc->status != IB_WC_SUCCESS)) {
+               set_bit(XPT_CLOSE, &rdma->sc_xprt.xpt_flags);
+               if (wc->status != IB_WC_WR_FLUSH_ERR)
+                       pr_err("svcrdma: write ctx: %s (%u/0x%x)\n",
+                              ib_wc_status_msg(wc->status),
+                              wc->status, wc->vendor_err);
+       }
+
+       svc_rdma_write_info_free(info);
+}
+
+/* This function sleeps when the transport's Send Queue is congested.
+ *
+ * Assumptions:
+ * - If ib_post_send() succeeds, only one completion is expected,
+ *   even if one or more WRs are flushed. This is true when posting
+ *   an rdma_rw_ctx or when posting a single signaled WR.
+ */
+static int svc_rdma_post_chunk_ctxt(struct svc_rdma_chunk_ctxt *cc)
+{
+       struct svcxprt_rdma *rdma = cc->cc_rdma;
+       struct svc_xprt *xprt = &rdma->sc_xprt;
+       struct ib_send_wr *first_wr, *bad_wr;
+       struct list_head *tmp;
+       struct ib_cqe *cqe;
+       int ret;
+
+       first_wr = NULL;
+       cqe = &cc->cc_cqe;
+       list_for_each(tmp, &cc->cc_rwctxts) {
+               struct svc_rdma_rw_ctxt *ctxt;
+
+               ctxt = list_entry(tmp, struct svc_rdma_rw_ctxt, rw_list);
+               first_wr = rdma_rw_ctx_wrs(&ctxt->rw_ctx, rdma->sc_qp,
+                                          rdma->sc_port_num, cqe, first_wr);
+               cqe = NULL;
+       }
+
+       do {
+               if (atomic_sub_return(cc->cc_sqecount,
+                                     &rdma->sc_sq_avail) > 0) {
+                       ret = ib_post_send(rdma->sc_qp, first_wr, &bad_wr);
+                       if (ret)
+                               break;
+                       return 0;
+               }
+
+               atomic_inc(&rdma_stat_sq_starve);
+               atomic_add(cc->cc_sqecount, &rdma->sc_sq_avail);
+               wait_event(rdma->sc_send_wait,
+                          atomic_read(&rdma->sc_sq_avail) > cc->cc_sqecount);
+       } while (1);
+
+       pr_err("svcrdma: ib_post_send failed (%d)\n", ret);
+       set_bit(XPT_CLOSE, &xprt->xpt_flags);
+
+       /* If even one was posted, there will be a completion. */
+       if (bad_wr != first_wr)
+               return 0;
+
+       atomic_add(cc->cc_sqecount, &rdma->sc_sq_avail);
+       wake_up(&rdma->sc_send_wait);
+       return -ENOTCONN;
+}
+
+/* Build and DMA-map an SGL that covers one kvec in an xdr_buf
+ */
+static void svc_rdma_vec_to_sg(struct svc_rdma_write_info *info,
+                              unsigned int len,
+                              struct svc_rdma_rw_ctxt *ctxt)
+{
+       struct scatterlist *sg = ctxt->rw_sg_table.sgl;
+
+       sg_set_buf(&sg[0], info->wi_base, len);
+       info->wi_base += len;
+
+       ctxt->rw_nents = 1;
+}
+
+/* Build and DMA-map an SGL that covers part of an xdr_buf's pagelist.
+ */
+static void svc_rdma_pagelist_to_sg(struct svc_rdma_write_info *info,
+                                   unsigned int remaining,
+                                   struct svc_rdma_rw_ctxt *ctxt)
+{
+       unsigned int sge_no, sge_bytes, page_off, page_no;
+       struct xdr_buf *xdr = info->wi_xdr;
+       struct scatterlist *sg;
+       struct page **page;
+
+       page_off = (info->wi_next_off + xdr->page_base) & ~PAGE_MASK;
+       page_no = (info->wi_next_off + xdr->page_base) >> PAGE_SHIFT;
+       page = xdr->pages + page_no;
+       info->wi_next_off += remaining;
+       sg = ctxt->rw_sg_table.sgl;
+       sge_no = 0;
+       do {
+               sge_bytes = min_t(unsigned int, remaining,
+                                 PAGE_SIZE - page_off);
+               sg_set_page(sg, *page, sge_bytes, page_off);
+
+               remaining -= sge_bytes;
+               sg = sg_next(sg);
+               page_off = 0;
+               sge_no++;
+               page++;
+       } while (remaining);
+
+       ctxt->rw_nents = sge_no;
+}
+
+/* Construct RDMA Write WRs to send a portion of an xdr_buf containing
+ * an RPC Reply.
+ */
+static int
+svc_rdma_build_writes(struct svc_rdma_write_info *info,
+                     void (*constructor)(struct svc_rdma_write_info *info,
+                                         unsigned int len,
+                                         struct svc_rdma_rw_ctxt *ctxt),
+                     unsigned int remaining)
+{
+       struct svc_rdma_chunk_ctxt *cc = &info->wi_cc;
+       struct svcxprt_rdma *rdma = cc->cc_rdma;
+       struct svc_rdma_rw_ctxt *ctxt;
+       __be32 *seg;
+       int ret;
+
+       cc->cc_cqe.done = svc_rdma_write_done;
+       seg = info->wi_segs + info->wi_seg_no * rpcrdma_segment_maxsz;
+       do {
+               unsigned int write_len;
+               u32 seg_length, seg_handle;
+               u64 seg_offset;
+
+               if (info->wi_seg_no >= info->wi_nsegs)
+                       goto out_overflow;
+
+               seg_handle = be32_to_cpup(seg);
+               seg_length = be32_to_cpup(seg + 1);
+               xdr_decode_hyper(seg + 2, &seg_offset);
+               seg_offset += info->wi_seg_off;
+
+               write_len = min(remaining, seg_length - info->wi_seg_off);
+               ctxt = svc_rdma_get_rw_ctxt(rdma,
+                                           (write_len >> PAGE_SHIFT) + 2);
+               if (!ctxt)
+                       goto out_noctx;
+
+               constructor(info, write_len, ctxt);
+               ret = rdma_rw_ctx_init(&ctxt->rw_ctx, rdma->sc_qp,
+                                      rdma->sc_port_num, ctxt->rw_sg_table.sgl,
+                                      ctxt->rw_nents, 0, seg_offset,
+                                      seg_handle, DMA_TO_DEVICE);
+               if (ret < 0)
+                       goto out_initerr;
+
+               list_add(&ctxt->rw_list, &cc->cc_rwctxts);
+               cc->cc_sqecount += ret;
+               if (write_len == seg_length - info->wi_seg_off) {
+                       seg += 4;
+                       info->wi_seg_no++;
+                       info->wi_seg_off = 0;
+               } else {
+                       info->wi_seg_off += write_len;
+               }
+               remaining -= write_len;
+       } while (remaining);
+
+       return 0;
+
+out_overflow:
+       dprintk("svcrdma: inadequate space in Write chunk (%u)\n",
+               info->wi_nsegs);
+       return -E2BIG;
+
+out_noctx:
+       dprintk("svcrdma: no R/W ctxs available\n");
+       return -ENOMEM;
+
+out_initerr:
+       svc_rdma_put_rw_ctxt(rdma, ctxt);
+       pr_err("svcrdma: failed to map pagelist (%d)\n", ret);
+       return -EIO;
+}
+
+/* Send one of an xdr_buf's kvecs by itself. To send a Reply
+ * chunk, the whole RPC Reply is written back to the client.
+ * This function writes either the head or tail of the xdr_buf
+ * containing the Reply.
+ */
+static int svc_rdma_send_xdr_kvec(struct svc_rdma_write_info *info,
+                                 struct kvec *vec)
+{
+       info->wi_base = vec->iov_base;
+       return svc_rdma_build_writes(info, svc_rdma_vec_to_sg,
+                                    vec->iov_len);
+}
+
+/* Send an xdr_buf's page list by itself. A Write chunk is
+ * just the page list. a Reply chunk is the head, page list,
+ * and tail. This function is shared between the two types
+ * of chunk.
+ */
+static int svc_rdma_send_xdr_pagelist(struct svc_rdma_write_info *info,
+                                     struct xdr_buf *xdr)
+{
+       info->wi_xdr = xdr;
+       info->wi_next_off = 0;
+       return svc_rdma_build_writes(info, svc_rdma_pagelist_to_sg,
+                                    xdr->page_len);
+}
+
+/**
+ * svc_rdma_send_write_chunk - Write all segments in a Write chunk
+ * @rdma: controlling RDMA transport
+ * @wr_ch: Write chunk provided by client
+ * @xdr: xdr_buf containing the data payload
+ *
+ * Returns a non-negative number of bytes the chunk consumed, or
+ *     %-E2BIG if the payload was larger than the Write chunk,
+ *     %-ENOMEM if rdma_rw context pool was exhausted,
+ *     %-ENOTCONN if posting failed (connection is lost),
+ *     %-EIO if rdma_rw initialization failed (DMA mapping, etc).
+ */
+int svc_rdma_send_write_chunk(struct svcxprt_rdma *rdma, __be32 *wr_ch,
+                             struct xdr_buf *xdr)
+{
+       struct svc_rdma_write_info *info;
+       int ret;
+
+       if (!xdr->page_len)
+               return 0;
+
+       info = svc_rdma_write_info_alloc(rdma, wr_ch);
+       if (!info)
+               return -ENOMEM;
+
+       ret = svc_rdma_send_xdr_pagelist(info, xdr);
+       if (ret < 0)
+               goto out_err;
+
+       ret = svc_rdma_post_chunk_ctxt(&info->wi_cc);
+       if (ret < 0)
+               goto out_err;
+       return xdr->page_len;
+
+out_err:
+       svc_rdma_write_info_free(info);
+       return ret;
+}
+
+/**
+ * svc_rdma_send_reply_chunk - Write all segments in the Reply chunk
+ * @rdma: controlling RDMA transport
+ * @rp_ch: Reply chunk provided by client
+ * @writelist: true if client provided a Write list
+ * @xdr: xdr_buf containing an RPC Reply
+ *
+ * Returns a non-negative number of bytes the chunk consumed, or
+ *     %-E2BIG if the payload was larger than the Reply chunk,
+ *     %-ENOMEM if rdma_rw context pool was exhausted,
+ *     %-ENOTCONN if posting failed (connection is lost),
+ *     %-EIO if rdma_rw initialization failed (DMA mapping, etc).
+ */
+int svc_rdma_send_reply_chunk(struct svcxprt_rdma *rdma, __be32 *rp_ch,
+                             bool writelist, struct xdr_buf *xdr)
+{
+       struct svc_rdma_write_info *info;
+       int consumed, ret;
+
+       info = svc_rdma_write_info_alloc(rdma, rp_ch);
+       if (!info)
+               return -ENOMEM;
+
+       ret = svc_rdma_send_xdr_kvec(info, &xdr->head[0]);
+       if (ret < 0)
+               goto out_err;
+       consumed = xdr->head[0].iov_len;
+
+       /* Send the page list in the Reply chunk only if the
+        * client did not provide Write chunks.
+        */
+       if (!writelist && xdr->page_len) {
+               ret = svc_rdma_send_xdr_pagelist(info, xdr);
+               if (ret < 0)
+                       goto out_err;
+               consumed += xdr->page_len;
+       }
+
+       if (xdr->tail[0].iov_len) {
+               ret = svc_rdma_send_xdr_kvec(info, &xdr->tail[0]);
+               if (ret < 0)
+                       goto out_err;
+               consumed += xdr->tail[0].iov_len;
+       }
+
+       ret = svc_rdma_post_chunk_ctxt(&info->wi_cc);
+       if (ret < 0)
+               goto out_err;
+       return consumed;
+
+out_err:
+       svc_rdma_write_info_free(info);
+       return ret;
+}
index 515221b16d0956ea027e91985c89606c403d5109..1736337f3a557a68399f5d1b103822cc08d19562 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2016 Oracle. All rights reserved.
  * Copyright (c) 2014 Open Grid Computing, Inc. All rights reserved.
  * Copyright (c) 2005-2006 Network Appliance, Inc. All rights reserved.
  *
  * Author: Tom Tucker <tom@opengridcomputing.com>
  */
 
+/* Operation
+ *
+ * The main entry point is svc_rdma_sendto. This is called by the
+ * RPC server when an RPC Reply is ready to be transmitted to a client.
+ *
+ * The passed-in svc_rqst contains a struct xdr_buf which holds an
+ * XDR-encoded RPC Reply message. sendto must construct the RPC-over-RDMA
+ * transport header, post all Write WRs needed for this Reply, then post
+ * a Send WR conveying the transport header and the RPC message itself to
+ * the client.
+ *
+ * svc_rdma_sendto must fully transmit the Reply before returning, as
+ * the svc_rqst will be recycled as soon as sendto returns. Remaining
+ * resources referred to by the svc_rqst are also recycled at that time.
+ * Therefore any resources that must remain longer must be detached
+ * from the svc_rqst and released later.
+ *
+ * Page Management
+ *
+ * The I/O that performs Reply transmission is asynchronous, and may
+ * complete well after sendto returns. Thus pages under I/O must be
+ * removed from the svc_rqst before sendto returns.
+ *
+ * The logic here depends on Send Queue and completion ordering. Since
+ * the Send WR is always posted last, it will always complete last. Thus
+ * when it completes, it is guaranteed that all previous Write WRs have
+ * also completed.
+ *
+ * Write WRs are constructed and posted. Each Write segment gets its own
+ * svc_rdma_rw_ctxt, allowing the Write completion handler to find and
+ * DMA-unmap the pages under I/O for that Write segment. The Write
+ * completion handler does not release any pages.
+ *
+ * When the Send WR is constructed, it also gets its own svc_rdma_op_ctxt.
+ * The ownership of all of the Reply's pages are transferred into that
+ * ctxt, the Send WR is posted, and sendto returns.
+ *
+ * The svc_rdma_op_ctxt is presented when the Send WR completes. The
+ * Send completion handler finally releases the Reply's pages.
+ *
+ * This mechanism also assumes that completions on the transport's Send
+ * Completion Queue do not run in parallel. Otherwise a Write completion
+ * and Send completion running at the same time could release pages that
+ * are still DMA-mapped.
+ *
+ * Error Handling
+ *
+ * - If the Send WR is posted successfully, it will either complete
+ *   successfully, or get flushed. Either way, the Send completion
+ *   handler releases the Reply's pages.
+ * - If the Send WR cannot be not posted, the forward path releases
+ *   the Reply's pages.
+ *
+ * This handles the case, without the use of page reference counting,
+ * where two different Write segments send portions of the same page.
+ */
+
 #include <linux/sunrpc/debug.h>
 #include <linux/sunrpc/rpc_rdma.h>
 #include <linux/spinlock.h>
@@ -55,113 +113,141 @@ static u32 xdr_padsize(u32 len)
        return (len & 3) ? (4 - (len & 3)) : 0;
 }
 
-int svc_rdma_map_xdr(struct svcxprt_rdma *xprt,
-                    struct xdr_buf *xdr,
-                    struct svc_rdma_req_map *vec,
-                    bool write_chunk_present)
+/* Returns length of transport header, in bytes.
+ */
+static unsigned int svc_rdma_reply_hdr_len(__be32 *rdma_resp)
 {
-       int sge_no;
-       u32 sge_bytes;
-       u32 page_bytes;
-       u32 page_off;
-       int page_no;
-
-       if (xdr->len !=
-           (xdr->head[0].iov_len + xdr->page_len + xdr->tail[0].iov_len)) {
-               pr_err("svcrdma: %s: XDR buffer length error\n", __func__);
-               return -EIO;
-       }
+       unsigned int nsegs;
+       __be32 *p;
 
-       /* Skip the first sge, this is for the RPCRDMA header */
-       sge_no = 1;
+       p = rdma_resp;
+
+       /* RPC-over-RDMA V1 replies never have a Read list. */
+       p += rpcrdma_fixed_maxsz + 1;
 
-       /* Head SGE */
-       vec->sge[sge_no].iov_base = xdr->head[0].iov_base;
-       vec->sge[sge_no].iov_len = xdr->head[0].iov_len;
-       sge_no++;
-
-       /* pages SGE */
-       page_no = 0;
-       page_bytes = xdr->page_len;
-       page_off = xdr->page_base;
-       while (page_bytes) {
-               vec->sge[sge_no].iov_base =
-                       page_address(xdr->pages[page_no]) + page_off;
-               sge_bytes = min_t(u32, page_bytes, (PAGE_SIZE - page_off));
-               page_bytes -= sge_bytes;
-               vec->sge[sge_no].iov_len = sge_bytes;
-
-               sge_no++;
-               page_no++;
-               page_off = 0; /* reset for next time through loop */
+       /* Skip Write list. */
+       while (*p++ != xdr_zero) {
+               nsegs = be32_to_cpup(p++);
+               p += nsegs * rpcrdma_segment_maxsz;
        }
 
-       /* Tail SGE */
-       if (xdr->tail[0].iov_len) {
-               unsigned char *base = xdr->tail[0].iov_base;
-               size_t len = xdr->tail[0].iov_len;
-               u32 xdr_pad = xdr_padsize(xdr->page_len);
+       /* Skip Reply chunk. */
+       if (*p++ != xdr_zero) {
+               nsegs = be32_to_cpup(p++);
+               p += nsegs * rpcrdma_segment_maxsz;
+       }
 
-               if (write_chunk_present && xdr_pad) {
-                       base += xdr_pad;
-                       len -= xdr_pad;
-               }
+       return (unsigned long)p - (unsigned long)rdma_resp;
+}
 
-               if (len) {
-                       vec->sge[sge_no].iov_base = base;
-                       vec->sge[sge_no].iov_len = len;
-                       sge_no++;
+/* One Write chunk is copied from Call transport header to Reply
+ * transport header. Each segment's length field is updated to
+ * reflect number of bytes consumed in the segment.
+ *
+ * Returns number of segments in this chunk.
+ */
+static unsigned int xdr_encode_write_chunk(__be32 *dst, __be32 *src,
+                                          unsigned int remaining)
+{
+       unsigned int i, nsegs;
+       u32 seg_len;
+
+       /* Write list discriminator */
+       *dst++ = *src++;
+
+       /* number of segments in this chunk */
+       nsegs = be32_to_cpup(src);
+       *dst++ = *src++;
+
+       for (i = nsegs; i; i--) {
+               /* segment's RDMA handle */
+               *dst++ = *src++;
+
+               /* bytes returned in this segment */
+               seg_len = be32_to_cpu(*src);
+               if (remaining >= seg_len) {
+                       /* entire segment was consumed */
+                       *dst = *src;
+                       remaining -= seg_len;
+               } else {
+                       /* segment only partly filled */
+                       *dst = cpu_to_be32(remaining);
+                       remaining = 0;
                }
-       }
+               dst++; src++;
 
-       dprintk("svcrdma: %s: sge_no %d page_no %d "
-               "page_base %u page_len %u head_len %zu tail_len %zu\n",
-               __func__, sge_no, page_no, xdr->page_base, xdr->page_len,
-               xdr->head[0].iov_len, xdr->tail[0].iov_len);
+               /* segment's RDMA offset */
+               *dst++ = *src++;
+               *dst++ = *src++;
+       }
 
-       vec->count = sge_no;
-       return 0;
+       return nsegs;
 }
 
-static dma_addr_t dma_map_xdr(struct svcxprt_rdma *xprt,
-                             struct xdr_buf *xdr,
-                             u32 xdr_off, size_t len, int dir)
+/* The client provided a Write list in the Call message. Fill in
+ * the segments in the first Write chunk in the Reply's transport
+ * header with the number of bytes consumed in each segment.
+ * Remaining chunks are returned unused.
+ *
+ * Assumptions:
+ *  - Client has provided only one Write chunk
+ */
+static void svc_rdma_xdr_encode_write_list(__be32 *rdma_resp, __be32 *wr_ch,
+                                          unsigned int consumed)
 {
-       struct page *page;
-       dma_addr_t dma_addr;
-       if (xdr_off < xdr->head[0].iov_len) {
-               /* This offset is in the head */
-               xdr_off += (unsigned long)xdr->head[0].iov_base & ~PAGE_MASK;
-               page = virt_to_page(xdr->head[0].iov_base);
-       } else {
-               xdr_off -= xdr->head[0].iov_len;
-               if (xdr_off < xdr->page_len) {
-                       /* This offset is in the page list */
-                       xdr_off += xdr->page_base;
-                       page = xdr->pages[xdr_off >> PAGE_SHIFT];
-                       xdr_off &= ~PAGE_MASK;
-               } else {
-                       /* This offset is in the tail */
-                       xdr_off -= xdr->page_len;
-                       xdr_off += (unsigned long)
-                               xdr->tail[0].iov_base & ~PAGE_MASK;
-                       page = virt_to_page(xdr->tail[0].iov_base);
-               }
+       unsigned int nsegs;
+       __be32 *p, *q;
+
+       /* RPC-over-RDMA V1 replies never have a Read list. */
+       p = rdma_resp + rpcrdma_fixed_maxsz + 1;
+
+       q = wr_ch;
+       while (*q != xdr_zero) {
+               nsegs = xdr_encode_write_chunk(p, q, consumed);
+               q += 2 + nsegs * rpcrdma_segment_maxsz;
+               p += 2 + nsegs * rpcrdma_segment_maxsz;
+               consumed = 0;
        }
-       dma_addr = ib_dma_map_page(xprt->sc_cm_id->device, page, xdr_off,
-                                  min_t(size_t, PAGE_SIZE, len), dir);
-       return dma_addr;
+
+       /* Terminate Write list */
+       *p++ = xdr_zero;
+
+       /* Reply chunk discriminator; may be replaced later */
+       *p = xdr_zero;
+}
+
+/* The client provided a Reply chunk in the Call message. Fill in
+ * the segments in the Reply chunk in the Reply message with the
+ * number of bytes consumed in each segment.
+ *
+ * Assumptions:
+ * - Reply can always fit in the provided Reply chunk
+ */
+static void svc_rdma_xdr_encode_reply_chunk(__be32 *rdma_resp, __be32 *rp_ch,
+                                           unsigned int consumed)
+{
+       __be32 *p;
+
+       /* Find the Reply chunk in the Reply's xprt header.
+        * RPC-over-RDMA V1 replies never have a Read list.
+        */
+       p = rdma_resp + rpcrdma_fixed_maxsz + 1;
+
+       /* Skip past Write list */
+       while (*p++ != xdr_zero)
+               p += 1 + be32_to_cpup(p) * rpcrdma_segment_maxsz;
+
+       xdr_encode_write_chunk(p, rp_ch, consumed);
 }
 
 /* Parse the RPC Call's transport header.
  */
-static void svc_rdma_get_write_arrays(struct rpcrdma_msg *rmsgp,
-                                     struct rpcrdma_write_array **write,
-                                     struct rpcrdma_write_array **reply)
+static void svc_rdma_get_write_arrays(__be32 *rdma_argp,
+                                     __be32 **write, __be32 **reply)
 {
        __be32 *p;
 
-       p = (__be32 *)&rmsgp->rm_body.rm_chunks[0];
+       p = rdma_argp + rpcrdma_fixed_maxsz;
 
        /* Read list */
        while (*p++ != xdr_zero)
@@ -169,7 +255,7 @@ static void svc_rdma_get_write_arrays(struct rpcrdma_msg *rmsgp,
 
        /* Write list */
        if (*p != xdr_zero) {
-               *write = (struct rpcrdma_write_array *)p;
+               *write = p;
                while (*p++ != xdr_zero)
                        p += 1 + be32_to_cpu(*p) * 4;
        } else {
@@ -179,7 +265,7 @@ static void svc_rdma_get_write_arrays(struct rpcrdma_msg *rmsgp,
 
        /* Reply chunk */
        if (*p != xdr_zero)
-               *reply = (struct rpcrdma_write_array *)p;
+               *reply = p;
        else
                *reply = NULL;
 }
@@ -189,360 +275,321 @@ static void svc_rdma_get_write_arrays(struct rpcrdma_msg *rmsgp,
  * Invalidate, and responder chooses one rkey to invalidate.
  *
  * Find a candidate rkey to invalidate when sending a reply.  Picks the
- * first rkey it finds in the chunks lists.
+ * first R_key it finds in the chunk lists.
  *
  * Returns zero if RPC's chunk lists are empty.
  */
-static u32 svc_rdma_get_inv_rkey(struct rpcrdma_msg *rdma_argp,
-                                struct rpcrdma_write_array *wr_ary,
-                                struct rpcrdma_write_array *rp_ary)
+static u32 svc_rdma_get_inv_rkey(__be32 *rdma_argp,
+                                __be32 *wr_lst, __be32 *rp_ch)
 {
-       struct rpcrdma_read_chunk *rd_ary;
-       struct rpcrdma_segment *arg_ch;
+       __be32 *p;
 
-       rd_ary = (struct rpcrdma_read_chunk *)&rdma_argp->rm_body.rm_chunks[0];
-       if (rd_ary->rc_discrim != xdr_zero)
-               return be32_to_cpu(rd_ary->rc_target.rs_handle);
+       p = rdma_argp + rpcrdma_fixed_maxsz;
+       if (*p != xdr_zero)
+               p += 2;
+       else if (wr_lst && be32_to_cpup(wr_lst + 1))
+               p = wr_lst + 2;
+       else if (rp_ch && be32_to_cpup(rp_ch + 1))
+               p = rp_ch + 2;
+       else
+               return 0;
+       return be32_to_cpup(p);
+}
 
-       if (wr_ary && be32_to_cpu(wr_ary->wc_nchunks)) {
-               arg_ch = &wr_ary->wc_array[0].wc_target;
-               return be32_to_cpu(arg_ch->rs_handle);
-       }
+/* ib_dma_map_page() is used here because svc_rdma_dma_unmap()
+ * is used during completion to DMA-unmap this memory, and
+ * it uses ib_dma_unmap_page() exclusively.
+ */
+static int svc_rdma_dma_map_buf(struct svcxprt_rdma *rdma,
+                               struct svc_rdma_op_ctxt *ctxt,
+                               unsigned int sge_no,
+                               unsigned char *base,
+                               unsigned int len)
+{
+       unsigned long offset = (unsigned long)base & ~PAGE_MASK;
+       struct ib_device *dev = rdma->sc_cm_id->device;
+       dma_addr_t dma_addr;
 
-       if (rp_ary && be32_to_cpu(rp_ary->wc_nchunks)) {
-               arg_ch = &rp_ary->wc_array[0].wc_target;
-               return be32_to_cpu(arg_ch->rs_handle);
-       }
+       dma_addr = ib_dma_map_page(dev, virt_to_page(base),
+                                  offset, len, DMA_TO_DEVICE);
+       if (ib_dma_mapping_error(dev, dma_addr))
+               return -EIO;
 
+       ctxt->sge[sge_no].addr = dma_addr;
+       ctxt->sge[sge_no].length = len;
+       ctxt->sge[sge_no].lkey = rdma->sc_pd->local_dma_lkey;
+       svc_rdma_count_mappings(rdma, ctxt);
        return 0;
 }
 
-/* Assumptions:
- * - The specified write_len can be represented in sc_max_sge * PAGE_SIZE
- */
-static int send_write(struct svcxprt_rdma *xprt, struct svc_rqst *rqstp,
-                     u32 rmr, u64 to,
-                     u32 xdr_off, int write_len,
-                     struct svc_rdma_req_map *vec)
+static int svc_rdma_dma_map_page(struct svcxprt_rdma *rdma,
+                                struct svc_rdma_op_ctxt *ctxt,
+                                unsigned int sge_no,
+                                struct page *page,
+                                unsigned int offset,
+                                unsigned int len)
 {
-       struct ib_rdma_wr write_wr;
-       struct ib_sge *sge;
-       int xdr_sge_no;
-       int sge_no;
-       int sge_bytes;
-       int sge_off;
-       int bc;
-       struct svc_rdma_op_ctxt *ctxt;
+       struct ib_device *dev = rdma->sc_cm_id->device;
+       dma_addr_t dma_addr;
 
-       if (vec->count > RPCSVC_MAXPAGES) {
-               pr_err("svcrdma: Too many pages (%lu)\n", vec->count);
+       dma_addr = ib_dma_map_page(dev, page, offset, len, DMA_TO_DEVICE);
+       if (ib_dma_mapping_error(dev, dma_addr))
                return -EIO;
-       }
 
-       dprintk("svcrdma: RDMA_WRITE rmr=%x, to=%llx, xdr_off=%d, "
-               "write_len=%d, vec->sge=%p, vec->count=%lu\n",
-               rmr, (unsigned long long)to, xdr_off,
-               write_len, vec->sge, vec->count);
+       ctxt->sge[sge_no].addr = dma_addr;
+       ctxt->sge[sge_no].length = len;
+       ctxt->sge[sge_no].lkey = rdma->sc_pd->local_dma_lkey;
+       svc_rdma_count_mappings(rdma, ctxt);
+       return 0;
+}
 
-       ctxt = svc_rdma_get_context(xprt);
+/**
+ * svc_rdma_map_reply_hdr - DMA map the transport header buffer
+ * @rdma: controlling transport
+ * @ctxt: op_ctxt for the Send WR
+ * @rdma_resp: buffer containing transport header
+ * @len: length of transport header
+ *
+ * Returns:
+ *     %0 if the header is DMA mapped,
+ *     %-EIO if DMA mapping failed.
+ */
+int svc_rdma_map_reply_hdr(struct svcxprt_rdma *rdma,
+                          struct svc_rdma_op_ctxt *ctxt,
+                          __be32 *rdma_resp,
+                          unsigned int len)
+{
        ctxt->direction = DMA_TO_DEVICE;
-       sge = ctxt->sge;
-
-       /* Find the SGE associated with xdr_off */
-       for (bc = xdr_off, xdr_sge_no = 1; bc && xdr_sge_no < vec->count;
-            xdr_sge_no++) {
-               if (vec->sge[xdr_sge_no].iov_len > bc)
-                       break;
-               bc -= vec->sge[xdr_sge_no].iov_len;
-       }
-
-       sge_off = bc;
-       bc = write_len;
-       sge_no = 0;
-
-       /* Copy the remaining SGE */
-       while (bc != 0) {
-               sge_bytes = min_t(size_t,
-                         bc, vec->sge[xdr_sge_no].iov_len-sge_off);
-               sge[sge_no].length = sge_bytes;
-               sge[sge_no].addr =
-                       dma_map_xdr(xprt, &rqstp->rq_res, xdr_off,
-                                   sge_bytes, DMA_TO_DEVICE);
-               xdr_off += sge_bytes;
-               if (ib_dma_mapping_error(xprt->sc_cm_id->device,
-                                        sge[sge_no].addr))
-                       goto err;
-               svc_rdma_count_mappings(xprt, ctxt);
-               sge[sge_no].lkey = xprt->sc_pd->local_dma_lkey;
-               ctxt->count++;
-               sge_off = 0;
-               sge_no++;
-               xdr_sge_no++;
-               if (xdr_sge_no > vec->count) {
-                       pr_err("svcrdma: Too many sges (%d)\n", xdr_sge_no);
-                       goto err;
-               }
-               bc -= sge_bytes;
-               if (sge_no == xprt->sc_max_sge)
-                       break;
-       }
-
-       /* Prepare WRITE WR */
-       memset(&write_wr, 0, sizeof write_wr);
-       ctxt->cqe.done = svc_rdma_wc_write;
-       write_wr.wr.wr_cqe = &ctxt->cqe;
-       write_wr.wr.sg_list = &sge[0];
-       write_wr.wr.num_sge = sge_no;
-       write_wr.wr.opcode = IB_WR_RDMA_WRITE;
-       write_wr.wr.send_flags = IB_SEND_SIGNALED;
-       write_wr.rkey = rmr;
-       write_wr.remote_addr = to;
-
-       /* Post It */
-       atomic_inc(&rdma_stat_write);
-       if (svc_rdma_send(xprt, &write_wr.wr))
-               goto err;
-       return write_len - bc;
- err:
-       svc_rdma_unmap_dma(ctxt);
-       svc_rdma_put_context(ctxt, 0);
-       return -EIO;
+       ctxt->pages[0] = virt_to_page(rdma_resp);
+       ctxt->count = 1;
+       return svc_rdma_dma_map_page(rdma, ctxt, 0, ctxt->pages[0], 0, len);
 }
 
-noinline
-static int send_write_chunks(struct svcxprt_rdma *xprt,
-                            struct rpcrdma_write_array *wr_ary,
-                            struct rpcrdma_msg *rdma_resp,
-                            struct svc_rqst *rqstp,
-                            struct svc_rdma_req_map *vec)
+/* Load the xdr_buf into the ctxt's sge array, and DMA map each
+ * element as it is added.
+ *
+ * Returns the number of sge elements loaded on success, or
+ * a negative errno on failure.
+ */
+static int svc_rdma_map_reply_msg(struct svcxprt_rdma *rdma,
+                                 struct svc_rdma_op_ctxt *ctxt,
+                                 struct xdr_buf *xdr, __be32 *wr_lst)
 {
-       u32 xfer_len = rqstp->rq_res.page_len;
-       int write_len;
-       u32 xdr_off;
-       int chunk_off;
-       int chunk_no;
-       int nchunks;
-       struct rpcrdma_write_array *res_ary;
+       unsigned int len, sge_no, remaining, page_off;
+       struct page **ppages;
+       unsigned char *base;
+       u32 xdr_pad;
        int ret;
 
-       res_ary = (struct rpcrdma_write_array *)
-               &rdma_resp->rm_body.rm_chunks[1];
-
-       /* Write chunks start at the pagelist */
-       nchunks = be32_to_cpu(wr_ary->wc_nchunks);
-       for (xdr_off = rqstp->rq_res.head[0].iov_len, chunk_no = 0;
-            xfer_len && chunk_no < nchunks;
-            chunk_no++) {
-               struct rpcrdma_segment *arg_ch;
-               u64 rs_offset;
-
-               arg_ch = &wr_ary->wc_array[chunk_no].wc_target;
-               write_len = min(xfer_len, be32_to_cpu(arg_ch->rs_length));
-
-               /* Prepare the response chunk given the length actually
-                * written */
-               xdr_decode_hyper((__be32 *)&arg_ch->rs_offset, &rs_offset);
-               svc_rdma_xdr_encode_array_chunk(res_ary, chunk_no,
-                                               arg_ch->rs_handle,
-                                               arg_ch->rs_offset,
-                                               write_len);
-               chunk_off = 0;
-               while (write_len) {
-                       ret = send_write(xprt, rqstp,
-                                        be32_to_cpu(arg_ch->rs_handle),
-                                        rs_offset + chunk_off,
-                                        xdr_off,
-                                        write_len,
-                                        vec);
-                       if (ret <= 0)
-                               goto out_err;
-                       chunk_off += ret;
-                       xdr_off += ret;
-                       xfer_len -= ret;
-                       write_len -= ret;
+       sge_no = 1;
+
+       ret = svc_rdma_dma_map_buf(rdma, ctxt, sge_no++,
+                                  xdr->head[0].iov_base,
+                                  xdr->head[0].iov_len);
+       if (ret < 0)
+               return ret;
+
+       /* If a Write chunk is present, the xdr_buf's page list
+        * is not included inline. However the Upper Layer may
+        * have added XDR padding in the tail buffer, and that
+        * should not be included inline.
+        */
+       if (wr_lst) {
+               base = xdr->tail[0].iov_base;
+               len = xdr->tail[0].iov_len;
+               xdr_pad = xdr_padsize(xdr->page_len);
+
+               if (len && xdr_pad) {
+                       base += xdr_pad;
+                       len -= xdr_pad;
                }
+
+               goto tail;
+       }
+
+       ppages = xdr->pages + (xdr->page_base >> PAGE_SHIFT);
+       page_off = xdr->page_base & ~PAGE_MASK;
+       remaining = xdr->page_len;
+       while (remaining) {
+               len = min_t(u32, PAGE_SIZE - page_off, remaining);
+
+               ret = svc_rdma_dma_map_page(rdma, ctxt, sge_no++,
+                                           *ppages++, page_off, len);
+               if (ret < 0)
+                       return ret;
+
+               remaining -= len;
+               page_off = 0;
        }
-       /* Update the req with the number of chunks actually used */
-       svc_rdma_xdr_encode_write_list(rdma_resp, chunk_no);
 
-       return rqstp->rq_res.page_len;
+       base = xdr->tail[0].iov_base;
+       len = xdr->tail[0].iov_len;
+tail:
+       if (len) {
+               ret = svc_rdma_dma_map_buf(rdma, ctxt, sge_no++, base, len);
+               if (ret < 0)
+                       return ret;
+       }
 
-out_err:
-       pr_err("svcrdma: failed to send write chunks, rc=%d\n", ret);
-       return -EIO;
+       return sge_no - 1;
 }
 
-noinline
-static int send_reply_chunks(struct svcxprt_rdma *xprt,
-                            struct rpcrdma_write_array *rp_ary,
-                            struct rpcrdma_msg *rdma_resp,
-                            struct svc_rqst *rqstp,
-                            struct svc_rdma_req_map *vec)
+/* The svc_rqst and all resources it owns are released as soon as
+ * svc_rdma_sendto returns. Transfer pages under I/O to the ctxt
+ * so they are released by the Send completion handler.
+ */
+static void svc_rdma_save_io_pages(struct svc_rqst *rqstp,
+                                  struct svc_rdma_op_ctxt *ctxt)
 {
-       u32 xfer_len = rqstp->rq_res.len;
-       int write_len;
-       u32 xdr_off;
-       int chunk_no;
-       int chunk_off;
-       int nchunks;
-       struct rpcrdma_segment *ch;
-       struct rpcrdma_write_array *res_ary;
-       int ret;
+       int i, pages = rqstp->rq_next_page - rqstp->rq_respages;
 
-       /* XXX: need to fix when reply lists occur with read-list and or
-        * write-list */
-       res_ary = (struct rpcrdma_write_array *)
-               &rdma_resp->rm_body.rm_chunks[2];
-
-       /* xdr offset starts at RPC message */
-       nchunks = be32_to_cpu(rp_ary->wc_nchunks);
-       for (xdr_off = 0, chunk_no = 0;
-            xfer_len && chunk_no < nchunks;
-            chunk_no++) {
-               u64 rs_offset;
-               ch = &rp_ary->wc_array[chunk_no].wc_target;
-               write_len = min(xfer_len, be32_to_cpu(ch->rs_length));
-
-               /* Prepare the reply chunk given the length actually
-                * written */
-               xdr_decode_hyper((__be32 *)&ch->rs_offset, &rs_offset);
-               svc_rdma_xdr_encode_array_chunk(res_ary, chunk_no,
-                                               ch->rs_handle, ch->rs_offset,
-                                               write_len);
-               chunk_off = 0;
-               while (write_len) {
-                       ret = send_write(xprt, rqstp,
-                                        be32_to_cpu(ch->rs_handle),
-                                        rs_offset + chunk_off,
-                                        xdr_off,
-                                        write_len,
-                                        vec);
-                       if (ret <= 0)
-                               goto out_err;
-                       chunk_off += ret;
-                       xdr_off += ret;
-                       xfer_len -= ret;
-                       write_len -= ret;
-               }
+       ctxt->count += pages;
+       for (i = 0; i < pages; i++) {
+               ctxt->pages[i + 1] = rqstp->rq_respages[i];
+               rqstp->rq_respages[i] = NULL;
        }
-       /* Update the req with the number of chunks actually used */
-       svc_rdma_xdr_encode_reply_array(res_ary, chunk_no);
+       rqstp->rq_next_page = rqstp->rq_respages + 1;
+}
 
-       return rqstp->rq_res.len;
+/**
+ * svc_rdma_post_send_wr - Set up and post one Send Work Request
+ * @rdma: controlling transport
+ * @ctxt: op_ctxt for transmitting the Send WR
+ * @num_sge: number of SGEs to send
+ * @inv_rkey: R_key argument to Send With Invalidate, or zero
+ *
+ * Returns:
+ *     %0 if the Send* was posted successfully,
+ *     %-ENOTCONN if the connection was lost or dropped,
+ *     %-EINVAL if there was a problem with the Send we built,
+ *     %-ENOMEM if ib_post_send failed.
+ */
+int svc_rdma_post_send_wr(struct svcxprt_rdma *rdma,
+                         struct svc_rdma_op_ctxt *ctxt, int num_sge,
+                         u32 inv_rkey)
+{
+       struct ib_send_wr *send_wr = &ctxt->send_wr;
 
-out_err:
-       pr_err("svcrdma: failed to send reply chunks, rc=%d\n", ret);
-       return -EIO;
+       dprintk("svcrdma: posting Send WR with %u sge(s)\n", num_sge);
+
+       send_wr->next = NULL;
+       ctxt->cqe.done = svc_rdma_wc_send;
+       send_wr->wr_cqe = &ctxt->cqe;
+       send_wr->sg_list = ctxt->sge;
+       send_wr->num_sge = num_sge;
+       send_wr->send_flags = IB_SEND_SIGNALED;
+       if (inv_rkey) {
+               send_wr->opcode = IB_WR_SEND_WITH_INV;
+               send_wr->ex.invalidate_rkey = inv_rkey;
+       } else {
+               send_wr->opcode = IB_WR_SEND;
+       }
+
+       return svc_rdma_send(rdma, send_wr);
 }
 
-/* This function prepares the portion of the RPCRDMA message to be
- * sent in the RDMA_SEND. This function is called after data sent via
- * RDMA has already been transmitted. There are three cases:
- * - The RPCRDMA header, RPC header, and payload are all sent in a
- *   single RDMA_SEND. This is the "inline" case.
- * - The RPCRDMA header and some portion of the RPC header and data
- *   are sent via this RDMA_SEND and another portion of the data is
- *   sent via RDMA.
- * - The RPCRDMA header [NOMSG] is sent in this RDMA_SEND and the RPC
- *   header and data are all transmitted via RDMA.
- * In all three cases, this function prepares the RPCRDMA header in
- * sge[0], the 'type' parameter indicates the type to place in the
- * RPCRDMA header, and the 'byte_count' field indicates how much of
- * the XDR to include in this RDMA_SEND. NB: The offset of the payload
- * to send is zero in the XDR.
+/* Prepare the portion of the RPC Reply that will be transmitted
+ * via RDMA Send. The RPC-over-RDMA transport header is prepared
+ * in sge[0], and the RPC xdr_buf is prepared in following sges.
+ *
+ * Depending on whether a Write list or Reply chunk is present,
+ * the server may send all, a portion of, or none of the xdr_buf.
+ * In the latter case, only the transport header (sge[0]) is
+ * transmitted.
+ *
+ * RDMA Send is the last step of transmitting an RPC reply. Pages
+ * involved in the earlier RDMA Writes are here transferred out
+ * of the rqstp and into the ctxt's page array. These pages are
+ * DMA unmapped by each Write completion, but the subsequent Send
+ * completion finally releases these pages.
+ *
+ * Assumptions:
+ * - The Reply's transport header will never be larger than a page.
  */
-static int send_reply(struct svcxprt_rdma *rdma,
-                     struct svc_rqst *rqstp,
-                     struct page *page,
-                     struct rpcrdma_msg *rdma_resp,
-                     struct svc_rdma_req_map *vec,
-                     int byte_count,
-                     u32 inv_rkey)
+static int svc_rdma_send_reply_msg(struct svcxprt_rdma *rdma,
+                                  __be32 *rdma_argp, __be32 *rdma_resp,
+                                  struct svc_rqst *rqstp,
+                                  __be32 *wr_lst, __be32 *rp_ch)
 {
        struct svc_rdma_op_ctxt *ctxt;
-       struct ib_send_wr send_wr;
-       u32 xdr_off;
-       int sge_no;
-       int sge_bytes;
-       int page_no;
-       int pages;
-       int ret = -EIO;
-
-       /* Prepare the context */
+       u32 inv_rkey;
+       int ret;
+
+       dprintk("svcrdma: sending %s reply: head=%zu, pagelen=%u, tail=%zu\n",
+               (rp_ch ? "RDMA_NOMSG" : "RDMA_MSG"),
+               rqstp->rq_res.head[0].iov_len,
+               rqstp->rq_res.page_len,
+               rqstp->rq_res.tail[0].iov_len);
+
        ctxt = svc_rdma_get_context(rdma);
-       ctxt->direction = DMA_TO_DEVICE;
-       ctxt->pages[0] = page;
-       ctxt->count = 1;
 
-       /* Prepare the SGE for the RPCRDMA Header */
-       ctxt->sge[0].lkey = rdma->sc_pd->local_dma_lkey;
-       ctxt->sge[0].length =
-           svc_rdma_xdr_get_reply_hdr_len((__be32 *)rdma_resp);
-       ctxt->sge[0].addr =
-           ib_dma_map_page(rdma->sc_cm_id->device, page, 0,
-                           ctxt->sge[0].length, DMA_TO_DEVICE);
-       if (ib_dma_mapping_error(rdma->sc_cm_id->device, ctxt->sge[0].addr))
+       ret = svc_rdma_map_reply_hdr(rdma, ctxt, rdma_resp,
+                                    svc_rdma_reply_hdr_len(rdma_resp));
+       if (ret < 0)
                goto err;
-       svc_rdma_count_mappings(rdma, ctxt);
-
-       ctxt->direction = DMA_TO_DEVICE;
 
-       /* Map the payload indicated by 'byte_count' */
-       xdr_off = 0;
-       for (sge_no = 1; byte_count && sge_no < vec->count; sge_no++) {
-               sge_bytes = min_t(size_t, vec->sge[sge_no].iov_len, byte_count);
-               byte_count -= sge_bytes;
-               ctxt->sge[sge_no].addr =
-                       dma_map_xdr(rdma, &rqstp->rq_res, xdr_off,
-                                   sge_bytes, DMA_TO_DEVICE);
-               xdr_off += sge_bytes;
-               if (ib_dma_mapping_error(rdma->sc_cm_id->device,
-                                        ctxt->sge[sge_no].addr))
+       if (!rp_ch) {
+               ret = svc_rdma_map_reply_msg(rdma, ctxt,
+                                            &rqstp->rq_res, wr_lst);
+               if (ret < 0)
                        goto err;
-               svc_rdma_count_mappings(rdma, ctxt);
-               ctxt->sge[sge_no].lkey = rdma->sc_pd->local_dma_lkey;
-               ctxt->sge[sge_no].length = sge_bytes;
        }
-       if (byte_count != 0) {
-               pr_err("svcrdma: Could not map %d bytes\n", byte_count);
+
+       svc_rdma_save_io_pages(rqstp, ctxt);
+
+       inv_rkey = 0;
+       if (rdma->sc_snd_w_inv)
+               inv_rkey = svc_rdma_get_inv_rkey(rdma_argp, wr_lst, rp_ch);
+       ret = svc_rdma_post_send_wr(rdma, ctxt, 1 + ret, inv_rkey);
+       if (ret)
                goto err;
-       }
 
-       /* Save all respages in the ctxt and remove them from the
-        * respages array. They are our pages until the I/O
-        * completes.
+       return 0;
+
+err:
+       pr_err("svcrdma: failed to post Send WR (%d)\n", ret);
+       svc_rdma_unmap_dma(ctxt);
+       svc_rdma_put_context(ctxt, 1);
+       return ret;
+}
+
+/* Given the client-provided Write and Reply chunks, the server was not
+ * able to form a complete reply. Return an RDMA_ERROR message so the
+ * client can retire this RPC transaction. As above, the Send completion
+ * routine releases payload pages that were part of a previous RDMA Write.
+ *
+ * Remote Invalidation is skipped for simplicity.
+ */
+static int svc_rdma_send_error_msg(struct svcxprt_rdma *rdma,
+                                  __be32 *rdma_resp, struct svc_rqst *rqstp)
+{
+       struct svc_rdma_op_ctxt *ctxt;
+       __be32 *p;
+       int ret;
+
+       ctxt = svc_rdma_get_context(rdma);
+
+       /* Replace the original transport header with an
+        * RDMA_ERROR response. XID etc are preserved.
         */
-       pages = rqstp->rq_next_page - rqstp->rq_respages;
-       for (page_no = 0; page_no < pages; page_no++) {
-               ctxt->pages[page_no+1] = rqstp->rq_respages[page_no];
-               ctxt->count++;
-               rqstp->rq_respages[page_no] = NULL;
-       }
-       rqstp->rq_next_page = rqstp->rq_respages + 1;
+       p = rdma_resp + 3;
+       *p++ = rdma_error;
+       *p   = err_chunk;
 
-       if (sge_no > rdma->sc_max_sge) {
-               pr_err("svcrdma: Too many sges (%d)\n", sge_no);
+       ret = svc_rdma_map_reply_hdr(rdma, ctxt, rdma_resp, 20);
+       if (ret < 0)
                goto err;
-       }
-       memset(&send_wr, 0, sizeof send_wr);
-       ctxt->cqe.done = svc_rdma_wc_send;
-       send_wr.wr_cqe = &ctxt->cqe;
-       send_wr.sg_list = ctxt->sge;
-       send_wr.num_sge = sge_no;
-       if (inv_rkey) {
-               send_wr.opcode = IB_WR_SEND_WITH_INV;
-               send_wr.ex.invalidate_rkey = inv_rkey;
-       } else
-               send_wr.opcode = IB_WR_SEND;
-       send_wr.send_flags =  IB_SEND_SIGNALED;
 
-       ret = svc_rdma_send(rdma, &send_wr);
+       svc_rdma_save_io_pages(rqstp, ctxt);
+
+       ret = svc_rdma_post_send_wr(rdma, ctxt, 1 + ret, 0);
        if (ret)
                goto err;
 
        return 0;
 
- err:
+err:
+       pr_err("svcrdma: failed to post Send WR (%d)\n", ret);
        svc_rdma_unmap_dma(ctxt);
        svc_rdma_put_context(ctxt, 1);
        return ret;
@@ -552,39 +599,36 @@ void svc_rdma_prep_reply_hdr(struct svc_rqst *rqstp)
 {
 }
 
+/**
+ * svc_rdma_sendto - Transmit an RPC reply
+ * @rqstp: processed RPC request, reply XDR already in ::rq_res
+ *
+ * Any resources still associated with @rqstp are released upon return.
+ * If no reply message was possible, the connection is closed.
+ *
+ * Returns:
+ *     %0 if an RPC reply has been successfully posted,
+ *     %-ENOMEM if a resource shortage occurred (connection is lost),
+ *     %-ENOTCONN if posting failed (connection is lost).
+ */
 int svc_rdma_sendto(struct svc_rqst *rqstp)
 {
        struct svc_xprt *xprt = rqstp->rq_xprt;
        struct svcxprt_rdma *rdma =
                container_of(xprt, struct svcxprt_rdma, sc_xprt);
-       struct rpcrdma_msg *rdma_argp;
-       struct rpcrdma_msg *rdma_resp;
-       struct rpcrdma_write_array *wr_ary, *rp_ary;
-       int ret;
-       int inline_bytes;
+       __be32 *p, *rdma_argp, *rdma_resp, *wr_lst, *rp_ch;
+       struct xdr_buf *xdr = &rqstp->rq_res;
        struct page *res_page;
-       struct svc_rdma_req_map *vec;
-       u32 inv_rkey;
-       __be32 *p;
-
-       dprintk("svcrdma: sending response for rqstp=%p\n", rqstp);
+       int ret;
 
-       /* Get the RDMA request header. The receive logic always
-        * places this at the start of page 0.
+       /* Find the call's chunk lists to decide how to send the reply.
+        * Receive places the Call's xprt header at the start of page 0.
         */
        rdma_argp = page_address(rqstp->rq_pages[0]);
-       svc_rdma_get_write_arrays(rdma_argp, &wr_ary, &rp_ary);
-
-       inv_rkey = 0;
-       if (rdma->sc_snd_w_inv)
-               inv_rkey = svc_rdma_get_inv_rkey(rdma_argp, wr_ary, rp_ary);
+       svc_rdma_get_write_arrays(rdma_argp, &wr_lst, &rp_ch);
 
-       /* Build an req vec for the XDR */
-       vec = svc_rdma_get_req_map(rdma);
-       ret = svc_rdma_map_xdr(rdma, &rqstp->rq_res, vec, wr_ary != NULL);
-       if (ret)
-               goto err0;
-       inline_bytes = rqstp->rq_res.len;
+       dprintk("svcrdma: preparing response for XID 0x%08x\n",
+               be32_to_cpup(rdma_argp));
 
        /* Create the RDMA response header. xprt->xpt_mutex,
         * acquired in svc_send(), serializes RPC replies. The
@@ -598,115 +642,57 @@ int svc_rdma_sendto(struct svc_rqst *rqstp)
                goto err0;
        rdma_resp = page_address(res_page);
 
-       p = &rdma_resp->rm_xid;
-       *p++ = rdma_argp->rm_xid;
-       *p++ = rdma_argp->rm_vers;
+       p = rdma_resp;
+       *p++ = *rdma_argp;
+       *p++ = *(rdma_argp + 1);
        *p++ = rdma->sc_fc_credits;
-       *p++ = rp_ary ? rdma_nomsg : rdma_msg;
+       *p++ = rp_ch ? rdma_nomsg : rdma_msg;
 
        /* Start with empty chunks */
        *p++ = xdr_zero;
        *p++ = xdr_zero;
        *p   = xdr_zero;
 
-       /* Send any write-chunk data and build resp write-list */
-       if (wr_ary) {
-               ret = send_write_chunks(rdma, wr_ary, rdma_resp, rqstp, vec);
+       if (wr_lst) {
+               /* XXX: Presume the client sent only one Write chunk */
+               ret = svc_rdma_send_write_chunk(rdma, wr_lst, xdr);
                if (ret < 0)
-                       goto err1;
-               inline_bytes -= ret + xdr_padsize(ret);
+                       goto err2;
+               svc_rdma_xdr_encode_write_list(rdma_resp, wr_lst, ret);
        }
-
-       /* Send any reply-list data and update resp reply-list */
-       if (rp_ary) {
-               ret = send_reply_chunks(rdma, rp_ary, rdma_resp, rqstp, vec);
+       if (rp_ch) {
+               ret = svc_rdma_send_reply_chunk(rdma, rp_ch, wr_lst, xdr);
                if (ret < 0)
-                       goto err1;
-               inline_bytes -= ret;
+                       goto err2;
+               svc_rdma_xdr_encode_reply_chunk(rdma_resp, rp_ch, ret);
        }
 
-       /* Post a fresh Receive buffer _before_ sending the reply */
        ret = svc_rdma_post_recv(rdma, GFP_KERNEL);
        if (ret)
                goto err1;
-
-       ret = send_reply(rdma, rqstp, res_page, rdma_resp, vec,
-                        inline_bytes, inv_rkey);
+       ret = svc_rdma_send_reply_msg(rdma, rdma_argp, rdma_resp, rqstp,
+                                     wr_lst, rp_ch);
        if (ret < 0)
                goto err0;
+       return 0;
 
-       svc_rdma_put_req_map(rdma, vec);
-       dprintk("svcrdma: send_reply returns %d\n", ret);
-       return ret;
+ err2:
+       if (ret != -E2BIG)
+               goto err1;
+
+       ret = svc_rdma_post_recv(rdma, GFP_KERNEL);
+       if (ret)
+               goto err1;
+       ret = svc_rdma_send_error_msg(rdma, rdma_resp, rqstp);
+       if (ret < 0)
+               goto err0;
+       return 0;
 
  err1:
        put_page(res_page);
  err0:
-       svc_rdma_put_req_map(rdma, vec);
        pr_err("svcrdma: Could not send reply, err=%d. Closing transport.\n",
               ret);
-       set_bit(XPT_CLOSE, &rdma->sc_xprt.xpt_flags);
+       set_bit(XPT_CLOSE, &xprt->xpt_flags);
        return -ENOTCONN;
 }
-
-void svc_rdma_send_error(struct svcxprt_rdma *xprt, struct rpcrdma_msg *rmsgp,
-                        int status)
-{
-       struct ib_send_wr err_wr;
-       struct page *p;
-       struct svc_rdma_op_ctxt *ctxt;
-       enum rpcrdma_errcode err;
-       __be32 *va;
-       int length;
-       int ret;
-
-       ret = svc_rdma_repost_recv(xprt, GFP_KERNEL);
-       if (ret)
-               return;
-
-       p = alloc_page(GFP_KERNEL);
-       if (!p)
-               return;
-       va = page_address(p);
-
-       /* XDR encode an error reply */
-       err = ERR_CHUNK;
-       if (status == -EPROTONOSUPPORT)
-               err = ERR_VERS;
-       length = svc_rdma_xdr_encode_error(xprt, rmsgp, err, va);
-
-       ctxt = svc_rdma_get_context(xprt);
-       ctxt->direction = DMA_TO_DEVICE;
-       ctxt->count = 1;
-       ctxt->pages[0] = p;
-
-       /* Prepare SGE for local address */
-       ctxt->sge[0].lkey = xprt->sc_pd->local_dma_lkey;
-       ctxt->sge[0].length = length;
-       ctxt->sge[0].addr = ib_dma_map_page(xprt->sc_cm_id->device,
-                                           p, 0, length, DMA_TO_DEVICE);
-       if (ib_dma_mapping_error(xprt->sc_cm_id->device, ctxt->sge[0].addr)) {
-               dprintk("svcrdma: Error mapping buffer for protocol error\n");
-               svc_rdma_put_context(ctxt, 1);
-               return;
-       }
-       svc_rdma_count_mappings(xprt, ctxt);
-
-       /* Prepare SEND WR */
-       memset(&err_wr, 0, sizeof(err_wr));
-       ctxt->cqe.done = svc_rdma_wc_send;
-       err_wr.wr_cqe = &ctxt->cqe;
-       err_wr.sg_list = ctxt->sge;
-       err_wr.num_sge = 1;
-       err_wr.opcode = IB_WR_SEND;
-       err_wr.send_flags = IB_SEND_SIGNALED;
-
-       /* Post It */
-       ret = svc_rdma_send(xprt, &err_wr);
-       if (ret) {
-               dprintk("svcrdma: Error %d posting send for protocol error\n",
-                       ret);
-               svc_rdma_unmap_dma(ctxt);
-               svc_rdma_put_context(ctxt, 1);
-       }
-}
index fc8f14c7bfec60dc5828340861a747e49f06193e..a9d9cb1ba4c6068b1a80c225cb147d1993a75d76 100644 (file)
@@ -272,85 +272,6 @@ static void svc_rdma_destroy_ctxts(struct svcxprt_rdma *xprt)
        }
 }
 
-static struct svc_rdma_req_map *alloc_req_map(gfp_t flags)
-{
-       struct svc_rdma_req_map *map;
-
-       map = kmalloc(sizeof(*map), flags);
-       if (map)
-               INIT_LIST_HEAD(&map->free);
-       return map;
-}
-
-static bool svc_rdma_prealloc_maps(struct svcxprt_rdma *xprt)
-{
-       unsigned int i;
-
-       /* One for each receive buffer on this connection. */
-       i = xprt->sc_max_requests;
-
-       while (i--) {
-               struct svc_rdma_req_map *map;
-
-               map = alloc_req_map(GFP_KERNEL);
-               if (!map) {
-                       dprintk("svcrdma: No memory for request map\n");
-                       return false;
-               }
-               list_add(&map->free, &xprt->sc_maps);
-       }
-       return true;
-}
-
-struct svc_rdma_req_map *svc_rdma_get_req_map(struct svcxprt_rdma *xprt)
-{
-       struct svc_rdma_req_map *map = NULL;
-
-       spin_lock(&xprt->sc_map_lock);
-       if (list_empty(&xprt->sc_maps))
-               goto out_empty;
-
-       map = list_first_entry(&xprt->sc_maps,
-                              struct svc_rdma_req_map, free);
-       list_del_init(&map->free);
-       spin_unlock(&xprt->sc_map_lock);
-
-out:
-       map->count = 0;
-       return map;
-
-out_empty:
-       spin_unlock(&xprt->sc_map_lock);
-
-       /* Pre-allocation amount was incorrect */
-       map = alloc_req_map(GFP_NOIO);
-       if (map)
-               goto out;
-
-       WARN_ONCE(1, "svcrdma: empty request map list?\n");
-       return NULL;
-}
-
-void svc_rdma_put_req_map(struct svcxprt_rdma *xprt,
-                         struct svc_rdma_req_map *map)
-{
-       spin_lock(&xprt->sc_map_lock);
-       list_add(&map->free, &xprt->sc_maps);
-       spin_unlock(&xprt->sc_map_lock);
-}
-
-static void svc_rdma_destroy_maps(struct svcxprt_rdma *xprt)
-{
-       while (!list_empty(&xprt->sc_maps)) {
-               struct svc_rdma_req_map *map;
-
-               map = list_first_entry(&xprt->sc_maps,
-                                      struct svc_rdma_req_map, free);
-               list_del(&map->free);
-               kfree(map);
-       }
-}
-
 /* QP event handler */
 static void qp_event_handler(struct ib_event *event, void *context)
 {
@@ -473,24 +394,6 @@ void svc_rdma_wc_send(struct ib_cq *cq, struct ib_wc *wc)
        svc_rdma_put_context(ctxt, 1);
 }
 
-/**
- * svc_rdma_wc_write - Invoked by RDMA provider for each polled Write WC
- * @cq:        completion queue
- * @wc:        completed WR
- *
- */
-void svc_rdma_wc_write(struct ib_cq *cq, struct ib_wc *wc)
-{
-       struct ib_cqe *cqe = wc->wr_cqe;
-       struct svc_rdma_op_ctxt *ctxt;
-
-       svc_rdma_send_wc_common_put(cq, wc, "write");
-
-       ctxt = container_of(cqe, struct svc_rdma_op_ctxt, cqe);
-       svc_rdma_unmap_dma(ctxt);
-       svc_rdma_put_context(ctxt, 0);
-}
-
 /**
  * svc_rdma_wc_reg - Invoked by RDMA provider for each polled FASTREG WC
  * @cq:        completion queue
@@ -561,14 +464,14 @@ static struct svcxprt_rdma *rdma_create_xprt(struct svc_serv *serv,
        INIT_LIST_HEAD(&cma_xprt->sc_read_complete_q);
        INIT_LIST_HEAD(&cma_xprt->sc_frmr_q);
        INIT_LIST_HEAD(&cma_xprt->sc_ctxts);
-       INIT_LIST_HEAD(&cma_xprt->sc_maps);
+       INIT_LIST_HEAD(&cma_xprt->sc_rw_ctxts);
        init_waitqueue_head(&cma_xprt->sc_send_wait);
 
        spin_lock_init(&cma_xprt->sc_lock);
        spin_lock_init(&cma_xprt->sc_rq_dto_lock);
        spin_lock_init(&cma_xprt->sc_frmr_q_lock);
        spin_lock_init(&cma_xprt->sc_ctxt_lock);
-       spin_lock_init(&cma_xprt->sc_map_lock);
+       spin_lock_init(&cma_xprt->sc_rw_ctxt_lock);
 
        /*
         * Note that this implies that the underlying transport support
@@ -999,6 +902,7 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt)
                newxprt, newxprt->sc_cm_id);
 
        dev = newxprt->sc_cm_id->device;
+       newxprt->sc_port_num = newxprt->sc_cm_id->port_num;
 
        /* Qualify the transport resource defaults with the
         * capabilities of this particular device */
@@ -1014,13 +918,11 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt)
                                            svcrdma_max_bc_requests);
        newxprt->sc_rq_depth = newxprt->sc_max_requests +
                               newxprt->sc_max_bc_requests;
-       newxprt->sc_sq_depth = RPCRDMA_SQ_DEPTH_MULT * newxprt->sc_rq_depth;
+       newxprt->sc_sq_depth = newxprt->sc_rq_depth;
        atomic_set(&newxprt->sc_sq_avail, newxprt->sc_sq_depth);
 
        if (!svc_rdma_prealloc_ctxts(newxprt))
                goto errout;
-       if (!svc_rdma_prealloc_maps(newxprt))
-               goto errout;
 
        /*
         * Limit ORD based on client limit, local device limit, and
@@ -1050,6 +952,8 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt)
        memset(&qp_attr, 0, sizeof qp_attr);
        qp_attr.event_handler = qp_event_handler;
        qp_attr.qp_context = &newxprt->sc_xprt;
+       qp_attr.port_num = newxprt->sc_cm_id->port_num;
+       qp_attr.cap.max_rdma_ctxs = newxprt->sc_max_requests;
        qp_attr.cap.max_send_wr = newxprt->sc_sq_depth;
        qp_attr.cap.max_recv_wr = newxprt->sc_rq_depth;
        qp_attr.cap.max_send_sge = newxprt->sc_max_sge;
@@ -1248,8 +1152,8 @@ static void __svc_rdma_free(struct work_struct *work)
        }
 
        rdma_dealloc_frmr_q(rdma);
+       svc_rdma_destroy_rw_ctxts(rdma);
        svc_rdma_destroy_ctxts(rdma);
-       svc_rdma_destroy_maps(rdma);
 
        /* Destroy the QP if present (not a listener) */
        if (rdma->sc_qp && !IS_ERR(rdma->sc_qp))
index c717f54107768902db7c571ce65f4019624c7bcc..62ecbccd9748e54874059209070ebe4a6b9591e7 100644 (file)
@@ -66,8 +66,8 @@ static unsigned int xprt_rdma_slot_table_entries = RPCRDMA_DEF_SLOT_TABLE;
 unsigned int xprt_rdma_max_inline_read = RPCRDMA_DEF_INLINE;
 static unsigned int xprt_rdma_max_inline_write = RPCRDMA_DEF_INLINE;
 static unsigned int xprt_rdma_inline_write_padding;
-static unsigned int xprt_rdma_memreg_strategy = RPCRDMA_FRMR;
-               int xprt_rdma_pad_optimize = 0;
+unsigned int xprt_rdma_memreg_strategy         = RPCRDMA_FRMR;
+int xprt_rdma_pad_optimize;
 
 #if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
 
@@ -396,7 +396,7 @@ xprt_setup_rdma(struct xprt_create *args)
 
        new_xprt = rpcx_to_rdmax(xprt);
 
-       rc = rpcrdma_ia_open(new_xprt, sap, xprt_rdma_memreg_strategy);
+       rc = rpcrdma_ia_open(new_xprt, sap);
        if (rc)
                goto out1;
 
@@ -457,19 +457,33 @@ out1:
        return ERR_PTR(rc);
 }
 
-/*
- * Close a connection, during shutdown or timeout/reconnect
+/**
+ * xprt_rdma_close - Close down RDMA connection
+ * @xprt: generic transport to be closed
+ *
+ * Called during transport shutdown reconnect, or device
+ * removal. Caller holds the transport's write lock.
  */
 static void
 xprt_rdma_close(struct rpc_xprt *xprt)
 {
        struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt);
+       struct rpcrdma_ep *ep = &r_xprt->rx_ep;
+       struct rpcrdma_ia *ia = &r_xprt->rx_ia;
+
+       dprintk("RPC:       %s: closing xprt %p\n", __func__, xprt);
 
-       dprintk("RPC:       %s: closing\n", __func__);
-       if (r_xprt->rx_ep.rep_connected > 0)
+       if (test_and_clear_bit(RPCRDMA_IAF_REMOVING, &ia->ri_flags)) {
+               xprt_clear_connected(xprt);
+               rpcrdma_ia_remove(ia);
+               return;
+       }
+       if (ep->rep_connected == -ENODEV)
+               return;
+       if (ep->rep_connected > 0)
                xprt->reestablish_timeout = 0;
        xprt_disconnect_done(xprt);
-       rpcrdma_ep_disconnect(&r_xprt->rx_ep, &r_xprt->rx_ia);
+       rpcrdma_ep_disconnect(ep, ia);
 }
 
 static void
@@ -484,6 +498,27 @@ xprt_rdma_set_port(struct rpc_xprt *xprt, u16 port)
        dprintk("RPC:       %s: %u\n", __func__, port);
 }
 
+/**
+ * xprt_rdma_timer - invoked when an RPC times out
+ * @xprt: controlling RPC transport
+ * @task: RPC task that timed out
+ *
+ * Invoked when the transport is still connected, but an RPC
+ * retransmit timeout occurs.
+ *
+ * Since RDMA connections don't have a keep-alive, forcibly
+ * disconnect and retry to connect. This drives full
+ * detection of the network path, and retransmissions of
+ * all pending RPCs.
+ */
+static void
+xprt_rdma_timer(struct rpc_xprt *xprt, struct rpc_task *task)
+{
+       dprintk("RPC: %5u %s: xprt = %p\n", task->tk_pid, __func__, xprt);
+
+       xprt_force_disconnect(xprt);
+}
+
 static void
 xprt_rdma_connect(struct rpc_xprt *xprt, struct rpc_task *task)
 {
@@ -659,6 +694,8 @@ xprt_rdma_free(struct rpc_task *task)
  * xprt_rdma_send_request - marshal and send an RPC request
  * @task: RPC task with an RPC message in rq_snd_buf
  *
+ * Caller holds the transport's write lock.
+ *
  * Return values:
  *        0:   The request has been sent
  * ENOTCONN:   Caller needs to invoke connect logic then call again
@@ -685,6 +722,9 @@ xprt_rdma_send_request(struct rpc_task *task)
        struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt);
        int rc = 0;
 
+       if (!xprt_connected(xprt))
+               goto drop_connection;
+
        /* On retransmit, remove any previously registered chunks */
        if (unlikely(!list_empty(&req->rl_registered)))
                r_xprt->rx_ia.ri_ops->ro_unmap_safe(r_xprt, req, false);
@@ -776,6 +816,7 @@ static struct rpc_xprt_ops xprt_rdma_procs = {
        .alloc_slot             = xprt_alloc_slot,
        .release_request        = xprt_release_rqst_cong,       /* ditto */
        .set_retrans_timeout    = xprt_set_retrans_timeout_def, /* ditto */
+       .timer                  = xprt_rdma_timer,
        .rpcbind                = rpcb_getport_async,   /* sunrpc/rpcb_clnt.c */
        .set_port               = xprt_rdma_set_port,
        .connect                = xprt_rdma_connect,
index 3b332b395045b5b0ad07bc13a30db1420d7f7082..3dbce9ac4327a89ea6d84f348041609c5d653b4a 100644 (file)
@@ -53,7 +53,7 @@
 #include <linux/sunrpc/addr.h>
 #include <linux/sunrpc/svc_rdma.h>
 #include <asm/bitops.h>
-#include <linux/module.h> /* try_module_get()/module_put() */
+
 #include <rdma/ib_cm.h>
 
 #include "xprt_rdma.h"
 /*
  * internal functions
  */
+static void rpcrdma_create_mrs(struct rpcrdma_xprt *r_xprt);
+static void rpcrdma_destroy_mrs(struct rpcrdma_buffer *buf);
+static void rpcrdma_dma_unmap_regbuf(struct rpcrdma_regbuf *rb);
 
-static struct workqueue_struct *rpcrdma_receive_wq;
+static struct workqueue_struct *rpcrdma_receive_wq __read_mostly;
 
 int
 rpcrdma_alloc_wq(void)
@@ -180,7 +183,7 @@ rpcrdma_wc_receive(struct ib_cq *cq, struct ib_wc *wc)
        rep->rr_wc_flags = wc->wc_flags;
        rep->rr_inv_rkey = wc->ex.invalidate_rkey;
 
-       ib_dma_sync_single_for_cpu(rep->rr_device,
+       ib_dma_sync_single_for_cpu(rdmab_device(rep->rr_rdmabuf),
                                   rdmab_addr(rep->rr_rdmabuf),
                                   rep->rr_len, DMA_FROM_DEVICE);
 
@@ -262,6 +265,21 @@ rpcrdma_conn_upcall(struct rdma_cm_id *id, struct rdma_cm_event *event)
                        __func__, ep);
                complete(&ia->ri_done);
                break;
+       case RDMA_CM_EVENT_DEVICE_REMOVAL:
+#if IS_ENABLED(CONFIG_SUNRPC_DEBUG)
+               pr_info("rpcrdma: removing device for %pIS:%u\n",
+                       sap, rpc_get_port(sap));
+#endif
+               set_bit(RPCRDMA_IAF_REMOVING, &ia->ri_flags);
+               ep->rep_connected = -ENODEV;
+               xprt_force_disconnect(&xprt->rx_xprt);
+               wait_for_completion(&ia->ri_remove_done);
+
+               ia->ri_id = NULL;
+               ia->ri_pd = NULL;
+               ia->ri_device = NULL;
+               /* Return 1 to ensure the core destroys the id. */
+               return 1;
        case RDMA_CM_EVENT_ESTABLISHED:
                connstate = 1;
                ib_query_qp(ia->ri_id->qp, attr,
@@ -291,9 +309,6 @@ rpcrdma_conn_upcall(struct rdma_cm_id *id, struct rdma_cm_event *event)
                goto connected;
        case RDMA_CM_EVENT_DISCONNECTED:
                connstate = -ECONNABORTED;
-               goto connected;
-       case RDMA_CM_EVENT_DEVICE_REMOVAL:
-               connstate = -ENODEV;
 connected:
                dprintk("RPC:       %s: %sconnected\n",
                                        __func__, connstate > 0 ? "" : "dis");
@@ -329,14 +344,6 @@ connected:
        return 0;
 }
 
-static void rpcrdma_destroy_id(struct rdma_cm_id *id)
-{
-       if (id) {
-               module_put(id->device->owner);
-               rdma_destroy_id(id);
-       }
-}
-
 static struct rdma_cm_id *
 rpcrdma_create_id(struct rpcrdma_xprt *xprt,
                        struct rpcrdma_ia *ia, struct sockaddr *addr)
@@ -346,6 +353,7 @@ rpcrdma_create_id(struct rpcrdma_xprt *xprt,
        int rc;
 
        init_completion(&ia->ri_done);
+       init_completion(&ia->ri_remove_done);
 
        id = rdma_create_id(&init_net, rpcrdma_conn_upcall, xprt, RDMA_PS_TCP,
                            IB_QPT_RC);
@@ -370,16 +378,6 @@ rpcrdma_create_id(struct rpcrdma_xprt *xprt,
                goto out;
        }
 
-       /* FIXME:
-        * Until xprtrdma supports DEVICE_REMOVAL, the provider must
-        * be pinned while there are active NFS/RDMA mounts to prevent
-        * hangs and crashes at umount time.
-        */
-       if (!ia->ri_async_rc && !try_module_get(id->device->owner)) {
-               dprintk("RPC:       %s: Failed to get device module\n",
-                       __func__);
-               ia->ri_async_rc = -ENODEV;
-       }
        rc = ia->ri_async_rc;
        if (rc)
                goto out;
@@ -389,21 +387,20 @@ rpcrdma_create_id(struct rpcrdma_xprt *xprt,
        if (rc) {
                dprintk("RPC:       %s: rdma_resolve_route() failed %i\n",
                        __func__, rc);
-               goto put;
+               goto out;
        }
        rc = wait_for_completion_interruptible_timeout(&ia->ri_done, wtimeout);
        if (rc < 0) {
                dprintk("RPC:       %s: wait() exited: %i\n",
                        __func__, rc);
-               goto put;
+               goto out;
        }
        rc = ia->ri_async_rc;
        if (rc)
-               goto put;
+               goto out;
 
        return id;
-put:
-       module_put(id->device->owner);
+
 out:
        rdma_destroy_id(id);
        return ERR_PTR(rc);
@@ -413,13 +410,16 @@ out:
  * Exported functions.
  */
 
-/*
- * Open and initialize an Interface Adapter.
- *  o initializes fields of struct rpcrdma_ia, including
- *    interface and provider attributes and protection zone.
+/**
+ * rpcrdma_ia_open - Open and initialize an Interface Adapter.
+ * @xprt: controlling transport
+ * @addr: IP address of remote peer
+ *
+ * Returns 0 on success, negative errno if an appropriate
+ * Interface Adapter could not be found and opened.
  */
 int
-rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg)
+rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr)
 {
        struct rpcrdma_ia *ia = &xprt->rx_ia;
        int rc;
@@ -427,7 +427,7 @@ rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg)
        ia->ri_id = rpcrdma_create_id(xprt, ia, addr);
        if (IS_ERR(ia->ri_id)) {
                rc = PTR_ERR(ia->ri_id);
-               goto out1;
+               goto out_err;
        }
        ia->ri_device = ia->ri_id->device;
 
@@ -435,10 +435,10 @@ rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg)
        if (IS_ERR(ia->ri_pd)) {
                rc = PTR_ERR(ia->ri_pd);
                pr_err("rpcrdma: ib_alloc_pd() returned %d\n", rc);
-               goto out2;
+               goto out_err;
        }
 
-       switch (memreg) {
+       switch (xprt_rdma_memreg_strategy) {
        case RPCRDMA_FRMR:
                if (frwr_is_supported(ia)) {
                        ia->ri_ops = &rpcrdma_frwr_memreg_ops;
@@ -452,28 +452,73 @@ rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg)
                }
                /*FALLTHROUGH*/
        default:
-               pr_err("rpcrdma: Unsupported memory registration mode: %d\n",
-                      memreg);
+               pr_err("rpcrdma: Device %s does not support memreg mode %d\n",
+                      ia->ri_device->name, xprt_rdma_memreg_strategy);
                rc = -EINVAL;
-               goto out3;
+               goto out_err;
        }
 
        return 0;
 
-out3:
-       ib_dealloc_pd(ia->ri_pd);
-       ia->ri_pd = NULL;
-out2:
-       rpcrdma_destroy_id(ia->ri_id);
-       ia->ri_id = NULL;
-out1:
+out_err:
+       rpcrdma_ia_close(ia);
        return rc;
 }
 
-/*
- * Clean up/close an IA.
- *   o if event handles and PD have been initialized, free them.
- *   o close the IA
+/**
+ * rpcrdma_ia_remove - Handle device driver unload
+ * @ia: interface adapter being removed
+ *
+ * Divest transport H/W resources associated with this adapter,
+ * but allow it to be restored later.
+ */
+void
+rpcrdma_ia_remove(struct rpcrdma_ia *ia)
+{
+       struct rpcrdma_xprt *r_xprt = container_of(ia, struct rpcrdma_xprt,
+                                                  rx_ia);
+       struct rpcrdma_ep *ep = &r_xprt->rx_ep;
+       struct rpcrdma_buffer *buf = &r_xprt->rx_buf;
+       struct rpcrdma_req *req;
+       struct rpcrdma_rep *rep;
+
+       cancel_delayed_work_sync(&buf->rb_refresh_worker);
+
+       /* This is similar to rpcrdma_ep_destroy, but:
+        * - Don't cancel the connect worker.
+        * - Don't call rpcrdma_ep_disconnect, which waits
+        *   for another conn upcall, which will deadlock.
+        * - rdma_disconnect is unneeded, the underlying
+        *   connection is already gone.
+        */
+       if (ia->ri_id->qp) {
+               ib_drain_qp(ia->ri_id->qp);
+               rdma_destroy_qp(ia->ri_id);
+               ia->ri_id->qp = NULL;
+       }
+       ib_free_cq(ep->rep_attr.recv_cq);
+       ib_free_cq(ep->rep_attr.send_cq);
+
+       /* The ULP is responsible for ensuring all DMA
+        * mappings and MRs are gone.
+        */
+       list_for_each_entry(rep, &buf->rb_recv_bufs, rr_list)
+               rpcrdma_dma_unmap_regbuf(rep->rr_rdmabuf);
+       list_for_each_entry(req, &buf->rb_allreqs, rl_all) {
+               rpcrdma_dma_unmap_regbuf(req->rl_rdmabuf);
+               rpcrdma_dma_unmap_regbuf(req->rl_sendbuf);
+               rpcrdma_dma_unmap_regbuf(req->rl_recvbuf);
+       }
+       rpcrdma_destroy_mrs(buf);
+
+       /* Allow waiters to continue */
+       complete(&ia->ri_remove_done);
+}
+
+/**
+ * rpcrdma_ia_close - Clean up/close an IA.
+ * @ia: interface adapter to close
+ *
  */
 void
 rpcrdma_ia_close(struct rpcrdma_ia *ia)
@@ -482,13 +527,15 @@ rpcrdma_ia_close(struct rpcrdma_ia *ia)
        if (ia->ri_id != NULL && !IS_ERR(ia->ri_id)) {
                if (ia->ri_id->qp)
                        rdma_destroy_qp(ia->ri_id);
-               rpcrdma_destroy_id(ia->ri_id);
-               ia->ri_id = NULL;
+               rdma_destroy_id(ia->ri_id);
        }
+       ia->ri_id = NULL;
+       ia->ri_device = NULL;
 
        /* If the pd is still busy, xprtrdma missed freeing a resource */
        if (ia->ri_pd && !IS_ERR(ia->ri_pd))
                ib_dealloc_pd(ia->ri_pd);
+       ia->ri_pd = NULL;
 }
 
 /*
@@ -646,6 +693,99 @@ rpcrdma_ep_destroy(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia)
        ib_free_cq(ep->rep_attr.send_cq);
 }
 
+/* Re-establish a connection after a device removal event.
+ * Unlike a normal reconnection, a fresh PD and a new set
+ * of MRs and buffers is needed.
+ */
+static int
+rpcrdma_ep_recreate_xprt(struct rpcrdma_xprt *r_xprt,
+                        struct rpcrdma_ep *ep, struct rpcrdma_ia *ia)
+{
+       struct sockaddr *sap = (struct sockaddr *)&r_xprt->rx_data.addr;
+       int rc, err;
+
+       pr_info("%s: r_xprt = %p\n", __func__, r_xprt);
+
+       rc = -EHOSTUNREACH;
+       if (rpcrdma_ia_open(r_xprt, sap))
+               goto out1;
+
+       rc = -ENOMEM;
+       err = rpcrdma_ep_create(ep, ia, &r_xprt->rx_data);
+       if (err) {
+               pr_err("rpcrdma: rpcrdma_ep_create returned %d\n", err);
+               goto out2;
+       }
+
+       rc = -ENETUNREACH;
+       err = rdma_create_qp(ia->ri_id, ia->ri_pd, &ep->rep_attr);
+       if (err) {
+               pr_err("rpcrdma: rdma_create_qp returned %d\n", err);
+               goto out3;
+       }
+
+       rpcrdma_create_mrs(r_xprt);
+       return 0;
+
+out3:
+       rpcrdma_ep_destroy(ep, ia);
+out2:
+       rpcrdma_ia_close(ia);
+out1:
+       return rc;
+}
+
+static int
+rpcrdma_ep_reconnect(struct rpcrdma_xprt *r_xprt, struct rpcrdma_ep *ep,
+                    struct rpcrdma_ia *ia)
+{
+       struct sockaddr *sap = (struct sockaddr *)&r_xprt->rx_data.addr;
+       struct rdma_cm_id *id, *old;
+       int err, rc;
+
+       dprintk("RPC:       %s: reconnecting...\n", __func__);
+
+       rpcrdma_ep_disconnect(ep, ia);
+
+       rc = -EHOSTUNREACH;
+       id = rpcrdma_create_id(r_xprt, ia, sap);
+       if (IS_ERR(id))
+               goto out;
+
+       /* As long as the new ID points to the same device as the
+        * old ID, we can reuse the transport's existing PD and all
+        * previously allocated MRs. Also, the same device means
+        * the transport's previous DMA mappings are still valid.
+        *
+        * This is a sanity check only. There should be no way these
+        * point to two different devices here.
+        */
+       old = id;
+       rc = -ENETUNREACH;
+       if (ia->ri_device != id->device) {
+               pr_err("rpcrdma: can't reconnect on different device!\n");
+               goto out_destroy;
+       }
+
+       err = rdma_create_qp(id, ia->ri_pd, &ep->rep_attr);
+       if (err) {
+               dprintk("RPC:       %s: rdma_create_qp returned %d\n",
+                       __func__, err);
+               goto out_destroy;
+       }
+
+       /* Atomically replace the transport's ID and QP. */
+       rc = 0;
+       old = ia->ri_id;
+       ia->ri_id = id;
+       rdma_destroy_qp(old);
+
+out_destroy:
+       rdma_destroy_id(old);
+out:
+       return rc;
+}
+
 /*
  * Connect unconnected endpoint.
  */
@@ -654,61 +794,30 @@ rpcrdma_ep_connect(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia)
 {
        struct rpcrdma_xprt *r_xprt = container_of(ia, struct rpcrdma_xprt,
                                                   rx_ia);
-       struct rdma_cm_id *id, *old;
-       struct sockaddr *sap;
        unsigned int extras;
-       int rc = 0;
+       int rc;
 
-       if (ep->rep_connected != 0) {
 retry:
-               dprintk("RPC:       %s: reconnecting...\n", __func__);
-
-               rpcrdma_ep_disconnect(ep, ia);
-
-               sap = (struct sockaddr *)&r_xprt->rx_data.addr;
-               id = rpcrdma_create_id(r_xprt, ia, sap);
-               if (IS_ERR(id)) {
-                       rc = -EHOSTUNREACH;
-                       goto out;
-               }
-               /* TEMP TEMP TEMP - fail if new device:
-                * Deregister/remarshal *all* requests!
-                * Close and recreate adapter, pd, etc!
-                * Re-determine all attributes still sane!
-                * More stuff I haven't thought of!
-                * Rrrgh!
-                */
-               if (ia->ri_device != id->device) {
-                       printk("RPC:       %s: can't reconnect on "
-                               "different device!\n", __func__);
-                       rpcrdma_destroy_id(id);
-                       rc = -ENETUNREACH;
-                       goto out;
-               }
-               /* END TEMP */
-               rc = rdma_create_qp(id, ia->ri_pd, &ep->rep_attr);
-               if (rc) {
-                       dprintk("RPC:       %s: rdma_create_qp failed %i\n",
-                               __func__, rc);
-                       rpcrdma_destroy_id(id);
-                       rc = -ENETUNREACH;
-                       goto out;
-               }
-
-               old = ia->ri_id;
-               ia->ri_id = id;
-
-               rdma_destroy_qp(old);
-               rpcrdma_destroy_id(old);
-       } else {
+       switch (ep->rep_connected) {
+       case 0:
                dprintk("RPC:       %s: connecting...\n", __func__);
                rc = rdma_create_qp(ia->ri_id, ia->ri_pd, &ep->rep_attr);
                if (rc) {
                        dprintk("RPC:       %s: rdma_create_qp failed %i\n",
                                __func__, rc);
-                       /* do not update ep->rep_connected */
-                       return -ENETUNREACH;
+                       rc = -ENETUNREACH;
+                       goto out_noupdate;
                }
+               break;
+       case -ENODEV:
+               rc = rpcrdma_ep_recreate_xprt(r_xprt, ep, ia);
+               if (rc)
+                       goto out_noupdate;
+               break;
+       default:
+               rc = rpcrdma_ep_reconnect(r_xprt, ep, ia);
+               if (rc)
+                       goto out;
        }
 
        ep->rep_connected = 0;
@@ -736,6 +845,8 @@ retry:
 out:
        if (rc)
                ep->rep_connected = rc;
+
+out_noupdate:
        return rc;
 }
 
@@ -878,7 +989,6 @@ struct rpcrdma_rep *
 rpcrdma_create_rep(struct rpcrdma_xprt *r_xprt)
 {
        struct rpcrdma_create_data_internal *cdata = &r_xprt->rx_data;
-       struct rpcrdma_ia *ia = &r_xprt->rx_ia;
        struct rpcrdma_rep *rep;
        int rc;
 
@@ -894,7 +1004,6 @@ rpcrdma_create_rep(struct rpcrdma_xprt *r_xprt)
                goto out_free;
        }
 
-       rep->rr_device = ia->ri_device;
        rep->rr_cqe.done = rpcrdma_wc_receive;
        rep->rr_rxprt = r_xprt;
        INIT_WORK(&rep->rr_work, rpcrdma_reply_handler);
@@ -1037,6 +1146,7 @@ void
 rpcrdma_buffer_destroy(struct rpcrdma_buffer *buf)
 {
        cancel_delayed_work_sync(&buf->rb_recovery_worker);
+       cancel_delayed_work_sync(&buf->rb_refresh_worker);
 
        while (!list_empty(&buf->rb_recv_bufs)) {
                struct rpcrdma_rep *rep;
@@ -1081,7 +1191,8 @@ rpcrdma_get_mw(struct rpcrdma_xprt *r_xprt)
 
 out_nomws:
        dprintk("RPC:       %s: no MWs available\n", __func__);
-       schedule_delayed_work(&buf->rb_refresh_worker, 0);
+       if (r_xprt->rx_ep.rep_connected != -ENODEV)
+               schedule_delayed_work(&buf->rb_refresh_worker, 0);
 
        /* Allow the reply handler and refresh worker to run */
        cond_resched();
@@ -1231,17 +1342,19 @@ rpcrdma_alloc_regbuf(size_t size, enum dma_data_direction direction,
 bool
 __rpcrdma_dma_map_regbuf(struct rpcrdma_ia *ia, struct rpcrdma_regbuf *rb)
 {
+       struct ib_device *device = ia->ri_device;
+
        if (rb->rg_direction == DMA_NONE)
                return false;
 
-       rb->rg_iov.addr = ib_dma_map_single(ia->ri_device,
+       rb->rg_iov.addr = ib_dma_map_single(device,
                                            (void *)rb->rg_base,
                                            rdmab_length(rb),
                                            rb->rg_direction);
-       if (ib_dma_mapping_error(ia->ri_device, rdmab_addr(rb)))
+       if (ib_dma_mapping_error(device, rdmab_addr(rb)))
                return false;
 
-       rb->rg_device = ia->ri_device;
+       rb->rg_device = device;
        rb->rg_iov.lkey = ia->ri_pd->local_dma_lkey;
        return true;
 }
index 171a35116de911878ce88402c3bac2979740af63..1d66acf1a723e51efb0b2e91065122cd66856af7 100644 (file)
@@ -69,6 +69,7 @@ struct rpcrdma_ia {
        struct rdma_cm_id       *ri_id;
        struct ib_pd            *ri_pd;
        struct completion       ri_done;
+       struct completion       ri_remove_done;
        int                     ri_async_rc;
        unsigned int            ri_max_segs;
        unsigned int            ri_max_frmr_depth;
@@ -78,10 +79,15 @@ struct rpcrdma_ia {
        bool                    ri_reminv_expected;
        bool                    ri_implicit_roundup;
        enum ib_mr_type         ri_mrtype;
+       unsigned long           ri_flags;
        struct ib_qp_attr       ri_qp_attr;
        struct ib_qp_init_attr  ri_qp_init_attr;
 };
 
+enum {
+       RPCRDMA_IAF_REMOVING = 0,
+};
+
 /*
  * RDMA Endpoint -- one per transport instance
  */
@@ -164,6 +170,12 @@ rdmab_to_msg(struct rpcrdma_regbuf *rb)
        return (struct rpcrdma_msg *)rb->rg_base;
 }
 
+static inline struct ib_device *
+rdmab_device(struct rpcrdma_regbuf *rb)
+{
+       return rb->rg_device;
+}
+
 #define RPCRDMA_DEF_GFP                (GFP_NOIO | __GFP_NOWARN)
 
 /* To ensure a transport can always make forward progress,
@@ -209,7 +221,6 @@ struct rpcrdma_rep {
        unsigned int            rr_len;
        int                     rr_wc_flags;
        u32                     rr_inv_rkey;
-       struct ib_device        *rr_device;
        struct rpcrdma_xprt     *rr_rxprt;
        struct work_struct      rr_work;
        struct list_head        rr_list;
@@ -380,7 +391,6 @@ struct rpcrdma_buffer {
        spinlock_t              rb_mwlock;      /* protect rb_mws list */
        struct list_head        rb_mws;
        struct list_head        rb_all;
-       char                    *rb_pool;
 
        spinlock_t              rb_lock;        /* protect buf lists */
        int                     rb_send_count, rb_recv_count;
@@ -497,10 +507,16 @@ struct rpcrdma_xprt {
  * Default is 0, see sysctl entry and rpc_rdma.c rpcrdma_convert_iovs() */
 extern int xprt_rdma_pad_optimize;
 
+/* This setting controls the hunt for a supported memory
+ * registration strategy.
+ */
+extern unsigned int xprt_rdma_memreg_strategy;
+
 /*
  * Interface Adapter calls - xprtrdma/verbs.c
  */
-int rpcrdma_ia_open(struct rpcrdma_xprt *, struct sockaddr *, int);
+int rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr);
+void rpcrdma_ia_remove(struct rpcrdma_ia *ia);
 void rpcrdma_ia_close(struct rpcrdma_ia *);
 bool frwr_is_supported(struct rpcrdma_ia *);
 bool fmr_is_supported(struct rpcrdma_ia *);
index 0d4f2f455a7c91a1d7ea2b0fd9c8d121e6da98af..1b92b72e812f942fc9826d8542f29bf1bd7c26c5 100644 (file)
@@ -362,25 +362,25 @@ static int tipc_sk_sock_err(struct socket *sock, long *timeout)
        return 0;
 }
 
-#define tipc_wait_for_cond(sock_, timeout_, condition_)                        \
-({                                                                     \
-       int rc_ = 0;                                                    \
-       int done_ = 0;                                                  \
-                                                                       \
-       while (!(condition_) && !done_) {                               \
-               struct sock *sk_ = sock->sk;                            \
-               DEFINE_WAIT_FUNC(wait_, woken_wake_function);           \
-                                                                       \
-               rc_ = tipc_sk_sock_err(sock_, timeout_);                \
-               if (rc_)                                                \
-                       break;                                          \
-               prepare_to_wait(sk_sleep(sk_), &wait_,                  \
-                               TASK_INTERRUPTIBLE);                    \
-               done_ = sk_wait_event(sk_, timeout_,                    \
-                                     (condition_), &wait_);            \
-               remove_wait_queue(sk_sleep(sk_), &wait_);               \
-       }                                                               \
-       rc_;                                                            \
+#define tipc_wait_for_cond(sock_, timeo_, condition_)                         \
+({                                                                             \
+       struct sock *sk_;                                                      \
+       int rc_;                                                               \
+                                                                              \
+       while ((rc_ = !(condition_))) {                                        \
+               DEFINE_WAIT_FUNC(wait_, woken_wake_function);                  \
+               sk_ = (sock_)->sk;                                             \
+               rc_ = tipc_sk_sock_err((sock_), timeo_);                       \
+               if (rc_)                                                       \
+                       break;                                                 \
+               prepare_to_wait(sk_sleep(sk_), &wait_, TASK_INTERRUPTIBLE);    \
+               release_sock(sk_);                                             \
+               *(timeo_) = wait_woken(&wait_, TASK_INTERRUPTIBLE, *(timeo_)); \
+               sched_annotate_sleep();                                        \
+               lock_sock(sk_);                                                \
+               remove_wait_queue(sk_sleep(sk_), &wait_);                      \
+       }                                                                      \
+       rc_;                                                                   \
 })
 
 /**
index 9dffe0282ad4f08efe8df7ab48695183b5117739..403d86e80162e7796fd75249b1ae876d1eee1e6a 100644 (file)
@@ -576,9 +576,9 @@ static int virtio_vsock_probe(struct virtio_device *vdev)
 
        vsock->vdev = vdev;
 
-       ret = vsock->vdev->config->find_vqs(vsock->vdev, VSOCK_VQ_MAX,
-                                           vsock->vqs, callbacks, names,
-                                           NULL);
+       ret = virtio_find_vqs(vsock->vdev, VSOCK_VQ_MAX,
+                             vsock->vqs, callbacks, names,
+                             NULL);
        if (ret < 0)
                goto out;
 
index 570fc95dc507d8ee08a329e6b313b517fd78ce83..c3bc9da30cff997970dc2cf8aebd05c4795c3cf9 100644 (file)
@@ -2764,8 +2764,8 @@ static int nl80211_parse_mon_options(struct cfg80211_registered_device *rdev,
                        nla_data(info->attrs[NL80211_ATTR_MU_MIMO_GROUP_DATA]);
 
                /* bits 0 and 63 are reserved and must be zero */
-               if ((mumimo_groups[0] & BIT(7)) ||
-                   (mumimo_groups[VHT_MUMIMO_GROUPS_DATA_LEN - 1] & BIT(0)))
+               if ((mumimo_groups[0] & BIT(0)) ||
+                   (mumimo_groups[VHT_MUMIMO_GROUPS_DATA_LEN - 1] & BIT(7)))
                        return -EINVAL;
 
                params->vht_mumimo_groups = mumimo_groups;
index 8b911c29860e79f21b0ac8e1d3a80ed373fd537e..5a1a98df3499841172f47b71418f95d9558158d0 100644 (file)
@@ -1791,32 +1791,40 @@ void x25_kill_by_neigh(struct x25_neigh *nb)
 
 static int __init x25_init(void)
 {
-       int rc = proto_register(&x25_proto, 0);
+       int rc;
 
-       if (rc != 0)
+       rc = proto_register(&x25_proto, 0);
+       if (rc)
                goto out;
 
        rc = sock_register(&x25_family_ops);
-       if (rc != 0)
+       if (rc)
                goto out_proto;
 
        dev_add_pack(&x25_packet_type);
 
        rc = register_netdevice_notifier(&x25_dev_notifier);
-       if (rc != 0)
+       if (rc)
                goto out_sock;
 
-       pr_info("Linux Version 0.2\n");
+       rc = x25_register_sysctl();
+       if (rc)
+               goto out_dev;
 
-       x25_register_sysctl();
        rc = x25_proc_init();
-       if (rc != 0)
-               goto out_dev;
+       if (rc)
+               goto out_sysctl;
+
+       pr_info("Linux Version 0.2\n");
+
 out:
        return rc;
+out_sysctl:
+       x25_unregister_sysctl();
 out_dev:
        unregister_netdevice_notifier(&x25_dev_notifier);
 out_sock:
+       dev_remove_pack(&x25_packet_type);
        sock_unregister(AF_X25);
 out_proto:
        proto_unregister(&x25_proto);
index a06dfe143c675039b57cdc5a83164228730d3e5e..ba078c85f0a1533ffbbadef1ab5789399dd1528a 100644 (file)
@@ -73,9 +73,12 @@ static struct ctl_table x25_table[] = {
        { },
 };
 
-void __init x25_register_sysctl(void)
+int __init x25_register_sysctl(void)
 {
        x25_table_header = register_net_sysctl(&init_net, "net/x25", x25_table);
+       if (!x25_table_header)
+               return -ENOMEM;
+       return 0;
 }
 
 void x25_unregister_sysctl(void)
index b08ab4e889293c30f64b717065e6860603063f7c..9d751e209f313ca8f20a07e6d578cfb98c23defd 100644 (file)
@@ -306,7 +306,9 @@ int main(int argc, char *argv[])
        prog_attach_iptables(argv[2]);
        if (cfg_test_traffic) {
                if (signal(SIGINT, finish) == SIG_ERR)
-                       error(1, errno, "register handler failed");
+                       error(1, errno, "register SIGINT handler failed");
+               if (signal(SIGTERM, finish) == SIG_ERR)
+                       error(1, errno, "register SIGTERM handler failed");
                while (!test_finish) {
                        print_table();
                        printf("\n");
index 9cce2a66bd664c40668b3c8ca0dd12bd148bb21b..512f87a5fd20e08d0b97893b17e20e971425830e 100644 (file)
@@ -100,6 +100,7 @@ int main(int argc, char **argv)
        setrlimit(RLIMIT_MEMLOCK, &r);
 
        signal(SIGINT, int_exit);
+       signal(SIGTERM, int_exit);
 
        if (load_kallsyms()) {
                printf("failed to process /proc/kallsyms\n");
index be59d7dcbdde3664c573a78d6d27adee03234a16..4ed690b907ff844961499d492350746065e423fb 100644 (file)
@@ -180,6 +180,7 @@ int main(int argc, char **argv)
                return 1;
        }
        signal(SIGINT, int_exit);
+       signal(SIGTERM, int_exit);
 
        /* do sampling */
        printf("Sampling at %d Hertz for %d seconds. Ctrl-C also ends.\n",
index 0c5561d193a487f2257ccece359530b97b06a170..fa4336423da569f31fc432b9adc61f0835bb3f69 100644 (file)
@@ -192,6 +192,7 @@ int main(int argc, char **argv)
        setrlimit(RLIMIT_MEMLOCK, &r);
 
        signal(SIGINT, int_exit);
+       signal(SIGTERM, int_exit);
 
        if (load_kallsyms()) {
                printf("failed to process /proc/kallsyms\n");
index 7fee0f1ba9a313baf2d233b3bf705994c183755e..7321a3f253c991f88e96f2a53e6ffa3e7c5f1719 100644 (file)
@@ -127,6 +127,7 @@ int main(int ac, char **argv)
        }
 
        signal(SIGINT, int_exit);
+       signal(SIGTERM, int_exit);
 
        /* start 'ping' in the background to have some kfree_skb events */
        f = popen("ping -c5 localhost", "r");
index 378850c70eb81afdbc5283611573f89ea4d8923e..2431c0321b712ce54d15414836b148d483a8a632 100644 (file)
@@ -62,13 +62,14 @@ static void usage(const char *prog)
        fprintf(stderr,
                "usage: %s [OPTS] IFINDEX\n\n"
                "OPTS:\n"
-               "    -S    use skb-mode\n",
+               "    -S    use skb-mode\n"
+               "    -N    enforce native mode\n",
                prog);
 }
 
 int main(int argc, char **argv)
 {
-       const char *optstr = "S";
+       const char *optstr = "SN";
        char filename[256];
        int opt;
 
@@ -77,6 +78,9 @@ int main(int argc, char **argv)
                case 'S':
                        xdp_flags |= XDP_FLAGS_SKB_MODE;
                        break;
+               case 'N':
+                       xdp_flags |= XDP_FLAGS_DRV_MODE;
+                       break;
                default:
                        usage(basename(argv[0]));
                        return 1;
@@ -102,6 +106,7 @@ int main(int argc, char **argv)
        }
 
        signal(SIGINT, int_exit);
+       signal(SIGTERM, int_exit);
 
        if (set_link_xdp_fd(ifindex, prog_fd[0], xdp_flags) < 0) {
                printf("link set xdp fd failed\n");
index 92b8bde9337c8cec6128e73d23d307b628ba5a38..715cd12eaca5c0729d11e0918e564db9e2fa980f 100644 (file)
@@ -79,6 +79,8 @@ static void usage(const char *cmd)
        printf("    -m <dest-MAC> Used in sending the IP Tunneled pkt\n");
        printf("    -T <stop-after-X-seconds> Default: 0 (forever)\n");
        printf("    -P <IP-Protocol> Default is TCP\n");
+       printf("    -S use skb-mode\n");
+       printf("    -N enforce native mode\n");
        printf("    -h Display this help\n");
 }
 
@@ -138,7 +140,7 @@ int main(int argc, char **argv)
 {
        unsigned char opt_flags[256] = {};
        unsigned int kill_after_s = 0;
-       const char *optstr = "i:a:p:s:d:m:T:P:Sh";
+       const char *optstr = "i:a:p:s:d:m:T:P:SNh";
        int min_port = 0, max_port = 0;
        struct iptnl_info tnl = {};
        struct rlimit r = {RLIM_INFINITY, RLIM_INFINITY};
@@ -206,6 +208,9 @@ int main(int argc, char **argv)
                case 'S':
                        xdp_flags |= XDP_FLAGS_SKB_MODE;
                        break;
+               case 'N':
+                       xdp_flags |= XDP_FLAGS_DRV_MODE;
+                       break;
                default:
                        usage(argv[0]);
                        return 1;
@@ -239,6 +244,7 @@ int main(int argc, char **argv)
        }
 
        signal(SIGINT, int_exit);
+       signal(SIGTERM, int_exit);
 
        while (min_port <= max_port) {
                vip.dport = htons(min_port++);
index afe3fd3af1e40616857b3e6c425be632c1fa2667..61f87a99bf0a1c512e572d3cbdcf4b4b5d7ae785 100644 (file)
@@ -116,12 +116,12 @@ CC_OPTION_CFLAGS = $(filter-out $(GCC_PLUGINS_CFLAGS),$(KBUILD_CFLAGS))
 # Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586)
 
 cc-option = $(call try-run,\
-       $(CC) $(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",$(1),$(2))
+       $(CC) -Werror $(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",$(1),$(2))
 
 # cc-option-yn
 # Usage: flag := $(call cc-option-yn,-march=winchip-c6)
 cc-option-yn = $(call try-run,\
-       $(CC) $(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",y,n)
+       $(CC) -Werror $(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS) $(1) -c -x c /dev/null -o "$$TMP",y,n)
 
 # cc-option-align
 # Prefix align with either -falign or -malign
@@ -131,7 +131,7 @@ cc-option-align = $(subst -functions=0,,\
 # cc-disable-warning
 # Usage: cflags-y += $(call cc-disable-warning,unused-but-set-variable)
 cc-disable-warning = $(call try-run,\
-       $(CC) $(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS) -W$(strip $(1)) -c -x c /dev/null -o "$$TMP",-Wno-$(strip $(1)))
+       $(CC) -Werror $(KBUILD_CPPFLAGS) $(CC_OPTION_CFLAGS) -W$(strip $(1)) -c -x c /dev/null -o "$$TMP",-Wno-$(strip $(1)))
 
 # cc-name
 # Expands to either gcc or clang
index d883116ebaa452d9c2f6c657de53121ebd9d50bd..733e044fff8b37bae101788ac82be43fafa1a942 100644 (file)
@@ -177,6 +177,14 @@ cmd_cc_symtypes_c =                                                         \
 $(obj)/%.symtypes : $(src)/%.c FORCE
        $(call cmd,cc_symtypes_c)
 
+# LLVM assembly
+# Generate .ll files from .c
+quiet_cmd_cc_ll_c = CC $(quiet_modtag)  $@
+      cmd_cc_ll_c = $(CC) $(c_flags) -emit-llvm -S -o $@ $<
+
+$(obj)/%.ll: $(src)/%.c FORCE
+       $(call if_changed_dep,cc_ll_c)
+
 # C (.c) files
 # The C file is compiled and updated dependency information is generated.
 # (See cmd_cc_o_c + relevant part of rule_cc_o_c)
@@ -272,14 +280,14 @@ define rule_cc_o_c
        $(call echo-cmd,checksrc) $(cmd_checksrc)                         \
        $(call cmd_and_fixdep,cc_o_c)                                     \
        $(cmd_modversions_c)                                              \
-       $(cmd_objtool)                                                    \
+       $(call echo-cmd,objtool) $(cmd_objtool)                           \
        $(call echo-cmd,record_mcount) $(cmd_record_mcount)
 endef
 
 define rule_as_o_S
        $(call cmd_and_fixdep,as_o_S)                                     \
        $(cmd_modversions_S)                                              \
-       $(cmd_objtool)
+       $(call echo-cmd,objtool) $(cmd_objtool)
 endef
 
 # List module undefined symbols (or empty line if not enabled)
index a1be75d0a5fd3fbf4742e555046896ea6fa6fe65..34614a48b717eafa2c15f418e6e6769905e32ec1 100644 (file)
@@ -20,12 +20,6 @@ include include/config/auto.conf
 include scripts/Kbuild.include
 include $(src)/Makefile
 
-PHONY += __dtbs_install_prep
-__dtbs_install_prep:
-ifeq ("$(dtbinst-root)", "$(obj)")
-       $(Q)mkdir -p $(INSTALL_DTBS_PATH)
-endif
-
 dtbinst-files  := $(dtb-y)
 dtbinst-dirs   := $(dts-dirs)
 
@@ -35,8 +29,6 @@ quiet_cmd_dtb_install =       INSTALL $<
 
 install-dir = $(patsubst $(dtbinst-root)%,$(INSTALL_DTBS_PATH)%,$(obj))
 
-$(dtbinst-files) $(dtbinst-dirs): | __dtbs_install_prep
-
 $(dtbinst-files): %.dtb: $(obj)/%.dtb
        $(call cmd,dtb_install,$(install-dir))
 
index 7c321a603b079d355bd127aebb04adc0294b4ba5..fb3522fd87029f8e841469d2bb300ef6eb7fe1cb 100644 (file)
@@ -64,7 +64,6 @@ ifeq ($(cc-name),clang)
 KBUILD_CFLAGS += $(call cc-disable-warning, initializer-overrides)
 KBUILD_CFLAGS += $(call cc-disable-warning, unused-value)
 KBUILD_CFLAGS += $(call cc-disable-warning, format)
-KBUILD_CFLAGS += $(call cc-disable-warning, unknown-warning-option)
 KBUILD_CFLAGS += $(call cc-disable-warning, sign-compare)
 KBUILD_CFLAGS += $(call cc-disable-warning, format-zero-length)
 KBUILD_CFLAGS += $(call cc-disable-warning, uninitialized)
index 1106d6ca3a384baa81b077b599d83b8e9941108e..ce753a408c56823dbd1c4b5d4fb5cfe88e7054c4 100644 (file)
@@ -1,33 +1,56 @@
 # ==========================================================================
 # Installing headers
 #
-# header-y  - list files to be installed. They are preprocessed
-#             to remove __KERNEL__ section of the file
-# genhdr-y  - Same as header-y but in a generated/ directory
+# All headers under include/uapi, include/generated/uapi,
+# arch/<arch>/include/uapi and arch/<arch>/include/generated/uapi are
+# exported.
+# They are preprocessed to remove __KERNEL__ section of the file.
 #
 # ==========================================================================
 
+PHONY := __headers
+__headers:
+
+include scripts/Kbuild.include
+
+srcdir        := $(srctree)/$(obj)
+subdirs       := $(patsubst $(srcdir)/%/.,%,$(wildcard $(srcdir)/*/.))
+# caller may set destination dir (when installing to asm/)
+_dst          := $(if $(dst),$(dst),$(obj))
+
+# Recursion
+__headers: $(subdirs)
+
+.PHONY: $(subdirs)
+$(subdirs):
+       $(Q)$(MAKE) $(hdr-inst)=$(obj)/$@ dst=$(_dst)/$@
+
+# Skip header install/check for include/uapi and arch/$(hdr-arch)/include/uapi.
+# We have only sub-directories there.
+skip-inst := $(if $(filter %/uapi,$(obj)),1)
+
+ifeq ($(skip-inst),)
+
 # generated header directory
 gen := $(if $(gen),$(gen),$(subst include/,include/generated/,$(obj)))
 
+# Kbuild file is optional
 kbuild-file := $(srctree)/$(obj)/Kbuild
-include $(kbuild-file)
-
-# called may set destination dir (when installing to asm/)
-_dst := $(if $(destination-y),$(destination-y),$(if $(dst),$(dst),$(obj)))
+-include $(kbuild-file)
 
 old-kbuild-file := $(srctree)/$(subst uapi/,,$(obj))/Kbuild
 ifneq ($(wildcard $(old-kbuild-file)),)
 include $(old-kbuild-file)
 endif
 
-include scripts/Kbuild.include
-
 installdir    := $(INSTALL_HDR_PATH)/$(subst uapi/,,$(_dst))
 
-header-y      := $(sort $(header-y))
-subdirs       := $(patsubst %/,%,$(filter %/, $(header-y)))
-header-y      := $(filter-out %/, $(header-y))
+gendir        := $(objtree)/$(gen)
+header-files  := $(notdir $(wildcard $(srcdir)/*.h))
+header-files  += $(notdir $(wildcard $(srcdir)/*.agh))
+header-files  := $(filter-out $(no-export-headers), $(header-files))
+genhdr-files  := $(notdir $(wildcard $(gendir)/*.h))
+genhdr-files  := $(filter-out $(header-files), $(genhdr-files))
 
 # files used to track state of install/check
 install-file  := $(installdir)/.install
@@ -35,36 +58,20 @@ check-file    := $(installdir)/.check
 
 # generic-y list all files an architecture uses from asm-generic
 # Use this to build a list of headers which require a wrapper
-wrapper-files := $(filter $(header-y), $(generic-y))
-
-srcdir        := $(srctree)/$(obj)
-gendir        := $(objtree)/$(gen)
-
-oldsrcdir     := $(srctree)/$(subst /uapi,,$(obj))
+generic-files := $(notdir $(wildcard $(srctree)/include/uapi/asm-generic/*.h))
+wrapper-files := $(filter $(generic-files), $(generic-y))
+wrapper-files := $(filter-out $(header-files), $(wrapper-files))
 
 # all headers files for this dir
-header-y      := $(filter-out $(generic-y), $(header-y))
-all-files     := $(header-y) $(genhdr-y) $(wrapper-files)
+all-files     := $(header-files) $(genhdr-files) $(wrapper-files)
 output-files  := $(addprefix $(installdir)/, $(all-files))
 
-input-files1  := $(foreach hdr, $(header-y), \
-                  $(if $(wildcard $(srcdir)/$(hdr)), \
-                       $(wildcard $(srcdir)/$(hdr))) \
-                  )
-input-files1-name := $(notdir $(input-files1))
-input-files2  := $(foreach hdr, $(header-y), \
-                  $(if  $(wildcard $(srcdir)/$(hdr)),, \
-                       $(if $(wildcard $(oldsrcdir)/$(hdr)), \
-                               $(wildcard $(oldsrcdir)/$(hdr)), \
-                               $(error Missing UAPI file $(srcdir)/$(hdr))) \
-                  ))
-input-files2-name := $(notdir $(input-files2))
-input-files3  := $(foreach hdr, $(genhdr-y), \
-                  $(if $(wildcard $(gendir)/$(hdr)), \
-                       $(wildcard $(gendir)/$(hdr)), \
-                       $(error Missing generated UAPI file $(gendir)/$(hdr)) \
-                  ))
-input-files3-name := $(notdir $(input-files3))
+ifneq ($(mandatory-y),)
+missing       := $(filter-out $(all-files),$(mandatory-y))
+ifneq ($(missing),)
+$(error Some mandatory headers ($(missing)) are missing in $(obj))
+endif
+endif
 
 # Work out what needs to be removed
 oldheaders    := $(patsubst $(installdir)/%,%,$(wildcard $(installdir)/*.h))
@@ -78,9 +85,8 @@ printdir = $(patsubst $(INSTALL_HDR_PATH)/%/,%,$(dir $@))
 quiet_cmd_install = INSTALL $(printdir) ($(words $(all-files))\
                             file$(if $(word 2, $(all-files)),s))
       cmd_install = \
-        $(CONFIG_SHELL) $< $(installdir) $(srcdir) $(input-files1-name); \
-        $(CONFIG_SHELL) $< $(installdir) $(oldsrcdir) $(input-files2-name); \
-        $(CONFIG_SHELL) $< $(installdir) $(gendir) $(input-files3-name); \
+        $(CONFIG_SHELL) $< $(installdir) $(srcdir) $(header-files); \
+        $(CONFIG_SHELL) $< $(installdir) $(gendir) $(genhdr-files); \
         for F in $(wrapper-files); do                                   \
                 echo "\#include <asm-generic/$$F>" > $(installdir)/$$F;    \
         done;                                                           \
@@ -98,21 +104,21 @@ quiet_cmd_check = CHECK   $(printdir) ($(words $(all-files)) files)
                   $(PERL) $< $(INSTALL_HDR_PATH)/include $(SRCARCH); \
                  touch $@
 
-PHONY += __headersinst __headerscheck
-
 ifndef HDRCHECK
 # Rules for installing headers
-__headersinst: $(subdirs) $(install-file)
+__headers: $(install-file)
        @:
 
 targets += $(install-file)
-$(install-file): scripts/headers_install.sh $(input-files1) $(input-files2) $(input-files3) FORCE
+$(install-file): scripts/headers_install.sh \
+                $(addprefix $(srcdir)/,$(header-files)) \
+                $(addprefix $(gendir)/,$(genhdr-files)) FORCE
        $(if $(unwanted),$(call cmd,remove),)
        $(if $(wildcard $(dir $@)),,$(shell mkdir -p $(dir $@)))
        $(call if_changed,install)
 
 else
-__headerscheck: $(subdirs) $(check-file)
+__headers: $(check-file)
        @:
 
 targets += $(check-file)
@@ -121,11 +127,6 @@ $(check-file): scripts/headers_check.pl $(output-files) FORCE
 
 endif
 
-# Recursion
-.PHONY: $(subdirs)
-$(subdirs):
-       $(Q)$(MAKE) $(hdr-inst)=$(obj)/$@ dst=$(_dst)/$@
-
 targets := $(wildcard $(sort $(targets)))
 cmd_files := $(wildcard \
              $(foreach f,$(targets),$(dir $(f)).$(notdir $(f)).cmd))
@@ -134,6 +135,8 @@ ifneq ($(cmd_files),)
        include $(cmd_files)
 endif
 
+endif # skip-inst
+
 .PHONY: $(PHONY)
 PHONY += FORCE
 FORCE: ;
index c9f975ab98407fdae720340d00e675c2ad8887ca..58c05e5d9870b6c18a72da7dc44ff3112994946d 100644 (file)
@@ -175,7 +175,7 @@ ld_flags       = $(LDFLAGS) $(ldflags-y)
 
 dtc_cpp_flags  = -Wp,-MD,$(depfile).pre.tmp -nostdinc                    \
                 -I$(srctree)/arch/$(SRCARCH)/boot/dts                   \
-                -I$(srctree)/arch/$(SRCARCH)/boot/dts/include           \
+                -I$(srctree)/scripts/dtc/include-prefixes               \
                 -I$(srctree)/drivers/of/testcase-data                   \
                 -undef -D__DTS__
 
@@ -420,3 +420,34 @@ quiet_cmd_xzmisc = XZMISC  $@
 cmd_xzmisc = (cat $(filter-out FORCE,$^) | \
        xz --check=crc32 --lzma2=dict=1MiB) > $@ || \
        (rm -f $@ ; false)
+
+# ASM offsets
+# ---------------------------------------------------------------------------
+
+# Default sed regexp - multiline due to syntax constraints
+#
+# Use [:space:] because LLVM's integrated assembler inserts <tab> around
+# the .ascii directive whereas GCC keeps the <space> as-is.
+define sed-offsets
+       's:^[[:space:]]*\.ascii[[:space:]]*"\(.*\)".*:\1:; \
+       /^->/{s:->#\(.*\):/* \1 */:; \
+       s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \
+       s:->::; p;}'
+endef
+
+# Use filechk to avoid rebuilds when a header changes, but the resulting file
+# does not
+define filechk_offsets
+       (set -e; \
+        echo "#ifndef $2"; \
+        echo "#define $2"; \
+        echo "/*"; \
+        echo " * DO NOT MODIFY."; \
+        echo " *"; \
+        echo " * This file was generated by Kbuild"; \
+        echo " */"; \
+        echo ""; \
+        sed -ne $(sed-offsets); \
+        echo ""; \
+        echo "#endif" )
+endef
index baa3c7be04ad8897761f92abd2b5d428d24f8471..4b9569fa931b90200a2c809598fe3765b157fbb7 100755 (executable)
@@ -55,6 +55,7 @@ my $spelling_file = "$D/spelling.txt";
 my $codespell = 0;
 my $codespellfile = "/usr/share/codespell/dictionary.txt";
 my $conststructsfile = "$D/const_structs.checkpatch";
+my $typedefsfile = "";
 my $color = 1;
 my $allow_c99_comments = 1;
 
@@ -113,6 +114,7 @@ Options:
   --codespell                Use the codespell dictionary for spelling/typos
                              (default:/usr/share/codespell/dictionary.txt)
   --codespellfile            Use this codespell dictionary
+  --typedefsfile             Read additional types from this file
   --color                    Use colors when output is STDOUT (default: on)
   -h, --help, --version      display this help and exit
 
@@ -208,6 +210,7 @@ GetOptions(
        'test-only=s'   => \$tst_only,
        'codespell!'    => \$codespell,
        'codespellfile=s'       => \$codespellfile,
+       'typedefsfile=s'        => \$typedefsfile,
        'color!'        => \$color,
        'h|help'        => \$help,
        'version'       => \$help
@@ -629,29 +632,44 @@ if ($codespell) {
 
 $misspellings = join("|", sort keys %spelling_fix) if keys %spelling_fix;
 
-my $const_structs = "";
-if (open(my $conststructs, '<', $conststructsfile)) {
-       while (<$conststructs>) {
-               my $line = $_;
+sub read_words {
+       my ($wordsRef, $file) = @_;
 
-               $line =~ s/\s*\n?$//g;
-               $line =~ s/^\s*//g;
+       if (open(my $words, '<', $file)) {
+               while (<$words>) {
+                       my $line = $_;
 
-               next if ($line =~ m/^\s*#/);
-               next if ($line =~ m/^\s*$/);
-               if ($line =~ /\s/) {
-                       print("$conststructsfile: '$line' invalid - ignored\n");
-                       next;
-               }
+                       $line =~ s/\s*\n?$//g;
+                       $line =~ s/^\s*//g;
 
-               $const_structs .= '|' if ($const_structs ne "");
-               $const_structs .= $line;
+                       next if ($line =~ m/^\s*#/);
+                       next if ($line =~ m/^\s*$/);
+                       if ($line =~ /\s/) {
+                               print("$file: '$line' invalid - ignored\n");
+                               next;
+                       }
+
+                       $$wordsRef .= '|' if ($$wordsRef ne "");
+                       $$wordsRef .= $line;
+               }
+               close($file);
+               return 1;
        }
-       close($conststructsfile);
-} else {
-       warn "No structs that should be const will be found - file '$conststructsfile': $!\n";
+
+       return 0;
 }
 
+my $const_structs = "";
+read_words(\$const_structs, $conststructsfile)
+    or warn "No structs that should be const will be found - file '$conststructsfile': $!\n";
+
+my $typeOtherTypedefs = "";
+if (length($typedefsfile)) {
+       read_words(\$typeOtherTypedefs, $typedefsfile)
+           or warn "No additional types will be considered - file '$typedefsfile': $!\n";
+}
+$typeTypedefs .= '|' . $typeOtherTypedefs if ($typeOtherTypedefs ne "");
+
 sub build_types {
        my $mods = "(?x:  \n" . join("|\n  ", (@modifierList, @modifierListFile)) . "\n)";
        my $all = "(?x:  \n" . join("|\n  ", (@typeList, @typeListFile)) . "\n)";
@@ -2195,8 +2213,7 @@ sub process {
                        }
                        #next;
                }
-               if ($rawline=~/^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@(.*)/) {
-                       my $context = $4;
+               if ($rawline =~ /^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) {
                        $realline=$1-1;
                        if (defined $2) {
                                $realcnt=$3+1;
@@ -2205,12 +2222,6 @@ sub process {
                        }
                        $in_comment = 0;
 
-                       if ($context =~ /\b(\w+)\s*\(/) {
-                               $context_function = $1;
-                       } else {
-                               undef $context_function;
-                       }
-
                        # Guestimate if this is a continuing comment.  Run
                        # the context looking for a comment "edge".  If this
                        # edge is a close comment then we must be in a comment
@@ -2281,7 +2292,8 @@ sub process {
 
 #extract the line range in the file after the patch is applied
                if (!$in_commit_log &&
-                   $line =~ /^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@/) {
+                   $line =~ /^\@\@ -\d+(?:,\d+)? \+(\d+)(,(\d+))? \@\@(.*)/) {
+                       my $context = $4;
                        $is_patch = 1;
                        $first_line = $linenr + 1;
                        $realline=$1-1;
@@ -2297,6 +2309,11 @@ sub process {
                        %suppress_whiletrailers = ();
                        %suppress_export = ();
                        $suppress_statement = 0;
+                       if ($context =~ /\b(\w+)\s*\(/) {
+                               $context_function = $1;
+                       } else {
+                               undef $context_function;
+                       }
                        next;
 
 # track the line number as we move through the hunk, note that
@@ -2539,6 +2556,7 @@ sub process {
 # Check for git id commit length and improperly formed commit descriptions
                if ($in_commit_log && !$commit_log_possible_stack_dump &&
                    $line !~ /^\s*(?:Link|Patchwork|http|https|BugLink):/i &&
+                   $line !~ /^This reverts commit [0-9a-f]{7,40}/ &&
                    ($line =~ /\bcommit\s+[0-9a-f]{5,}\b/i ||
                     ($line =~ /(?:\s|^)[0-9a-f]{12,40}(?:[\s"'\(\[]|$)/i &&
                      $line !~ /[\<\[][0-9a-f]{12,40}[\>\]]/i &&
@@ -2628,8 +2646,8 @@ sub process {
 # Check if it's the start of a commit log
 # (not a header line and we haven't seen the patch filename)
                if ($in_header_lines && $realfile =~ /^$/ &&
-                   !($rawline =~ /^\s+\S/ ||
-                     $rawline =~ /^(commit\b|from\b|[\w-]+:).*$/i)) {
+                   !($rawline =~ /^\s+(?:\S|$)/ ||
+                     $rawline =~ /^(?:commit\b|from\b|[\w-]+:)/i)) {
                        $in_header_lines = 0;
                        $in_commit_log = 1;
                        $has_commit_log = 1;
@@ -2757,13 +2775,6 @@ sub process {
                        #print "is_start<$is_start> is_end<$is_end> length<$length>\n";
                }
 
-# discourage the addition of CONFIG_EXPERIMENTAL in Kconfig.
-               if ($realfile =~ /Kconfig/ &&
-                   $line =~ /.\s*depends on\s+.*\bEXPERIMENTAL\b/) {
-                       WARN("CONFIG_EXPERIMENTAL",
-                            "Use of CONFIG_EXPERIMENTAL is deprecated. For alternatives, see https://lkml.org/lkml/2012/10/23/580\n");
-               }
-
 # discourage the use of boolean for type definition attributes of Kconfig options
                if ($realfile =~ /Kconfig/ &&
                    $line =~ /^\+\s*\bboolean\b/) {
@@ -3133,6 +3144,17 @@ sub process {
 # check we are in a valid C source file if not then ignore this hunk
                next if ($realfile !~ /\.(h|c)$/);
 
+# check if this appears to be the start function declaration, save the name
+               if ($sline =~ /^\+\{\s*$/ &&
+                   $prevline =~ /^\+(?:(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*)?($Ident)\(/) {
+                       $context_function = $1;
+               }
+
+# check if this appears to be the end of function declaration
+               if ($sline =~ /^\+\}\s*$/) {
+                       undef $context_function;
+               }
+
 # check indentation of any line with a bare else
 # (but not if it is a multiple line "if (foo) return bar; else return baz;")
 # if the previous line is a break or return and is indented 1 tab more...
@@ -3157,12 +3179,6 @@ sub process {
                        }
                }
 
-# discourage the addition of CONFIG_EXPERIMENTAL in #if(def).
-               if ($line =~ /^\+\s*\#\s*if.*\bCONFIG_EXPERIMENTAL\b/) {
-                       WARN("CONFIG_EXPERIMENTAL",
-                            "Use of CONFIG_EXPERIMENTAL is deprecated. For alternatives, see https://lkml.org/lkml/2012/10/23/580\n");
-               }
-
 # check for RCS/CVS revision markers
                if ($rawline =~ /^\+.*\$(Revision|Log|Id)(?:\$|)/) {
                        WARN("CVS_KEYWORD",
@@ -3338,7 +3354,7 @@ sub process {
                }
 
 # Check relative indent for conditionals and blocks.
-               if ($line =~ /\b(?:(?:if|while|for|(?:[a-z_]+|)for_each[a-z_]+)\s*\(|do\b)/ && $line !~ /^.\s*#/ && $line !~ /\}\s*while\s*/) {
+               if ($line =~ /\b(?:(?:if|while|for|(?:[a-z_]+|)for_each[a-z_]+)\s*\(|(?:do|else)\b)/ && $line !~ /^.\s*#/ && $line !~ /\}\s*while\s*/) {
                        ($stat, $cond, $line_nr_next, $remain_next, $off_next) =
                                ctx_statement_block($linenr, $realcnt, 0)
                                        if (!defined $stat);
@@ -3430,6 +3446,8 @@ sub process {
                        if ($check && $s ne '' &&
                            (($sindent % 8) != 0 ||
                             ($sindent < $indent) ||
+                            ($sindent == $indent &&
+                             ($s !~ /^\s*(?:\}|\{|else\b)/)) ||
                             ($sindent > $indent + 8))) {
                                WARN("SUSPECT_CODE_INDENT",
                                     "suspect code indent for conditional statements ($indent, $sindent)\n" . $herecurr . "$stat_real\n");
@@ -4851,8 +4869,10 @@ sub process {
                            $dstat !~ /^\(\{/ &&                                                # ({...
                            $ctx !~ /^.\s*#\s*define\s+TRACE_(?:SYSTEM|INCLUDE_FILE|INCLUDE_PATH)\b/)
                        {
-
-                               if ($dstat =~ /;/) {
+                               if ($dstat =~ /^\s*if\b/) {
+                                       ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE",
+                                             "Macros starting with if should be enclosed by a do - while loop to avoid possible if/else logic defects\n" . "$herectx");
+                               } elsif ($dstat =~ /;/) {
                                        ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE",
                                              "Macros with multiple statements should be enclosed in a do - while loop\n" . "$herectx");
                                } else {
@@ -5174,14 +5194,16 @@ sub process {
                             "break quoted strings at a space character\n" . $hereprev);
                }
 
-#check for an embedded function name in a string when the function is known
-# as part of a diff.  This does not work for -f --file checking as it
-#depends on patch context providing the function name
+# check for an embedded function name in a string when the function is known
+# This does not work very well for -f --file checking as it depends on patch
+# context providing the function name or a single line form for in-file
+# function declarations
                if ($line =~ /^\+.*$String/ &&
                    defined($context_function) &&
-                   get_quoted_string($line, $rawline) =~ /\b$context_function\b/) {
+                   get_quoted_string($line, $rawline) =~ /\b$context_function\b/ &&
+                   length(get_quoted_string($line, $rawline)) != (length($context_function) + 2)) {
                        WARN("EMBEDDED_FUNCTION_NAME",
-                            "Prefer using \"%s\", __func__ to embedded function names\n" . $herecurr);
+                            "Prefer using '\"%s...\", __func__' to using '$context_function', this function's name, in a string\n" . $herecurr);
                }
 
 # check for spaces before a quoted newline
@@ -5676,6 +5698,32 @@ sub process {
                        }
                }
 
+               # check for vsprintf extension %p<foo> misuses
+               if ($^V && $^V ge 5.10.0 &&
+                   defined $stat &&
+                   $stat =~ /^\+(?![^\{]*\{\s*).*\b(\w+)\s*\(.*$String\s*,/s &&
+                   $1 !~ /^_*volatile_*$/) {
+                       my $bad_extension = "";
+                       my $lc = $stat =~ tr@\n@@;
+                       $lc = $lc + $linenr;
+                       for (my $count = $linenr; $count <= $lc; $count++) {
+                               my $fmt = get_quoted_string($lines[$count - 1], raw_line($count, 0));
+                               $fmt =~ s/%%//g;
+                               if ($fmt =~ /(\%[\*\d\.]*p(?![\WFfSsBKRraEhMmIiUDdgVCbGN]).)/) {
+                                       $bad_extension = $1;
+                                       last;
+                               }
+                       }
+                       if ($bad_extension ne "") {
+                               my $stat_real = raw_line($linenr, 0);
+                               for (my $count = $linenr + 1; $count <= $lc; $count++) {
+                                       $stat_real = $stat_real . "\n" . raw_line($count, 0);
+                               }
+                               WARN("VSPRINTF_POINTER_EXTENSION",
+                                    "Invalid vsprintf pointer extension '$bad_extension'\n" . "$here\n$stat_real\n");
+                       }
+               }
+
 # Check for misused memsets
                if ($^V && $^V ge 5.10.0 &&
                    defined $stat &&
@@ -5893,7 +5941,8 @@ sub process {
 
 # check for k[mz]alloc with multiplies that could be kmalloc_array/kcalloc
                if ($^V && $^V ge 5.10.0 &&
-                   $line =~ /\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/) {
+                   defined $stat &&
+                   $stat =~ /^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/) {
                        my $oldfunc = $3;
                        my $a1 = $4;
                        my $a2 = $10;
@@ -5907,11 +5956,17 @@ sub process {
                        }
                        if ($r1 !~ /^sizeof\b/ && $r2 =~ /^sizeof\s*\S/ &&
                            !($r1 =~ /^$Constant$/ || $r1 =~ /^[A-Z_][A-Z0-9_]*$/)) {
+                               my $ctx = '';
+                               my $herectx = $here . "\n";
+                               my $cnt = statement_rawlines($stat);
+                               for (my $n = 0; $n < $cnt; $n++) {
+                                       $herectx .= raw_line($linenr, $n) . "\n";
+                               }
                                if (WARN("ALLOC_WITH_MULTIPLY",
-                                        "Prefer $newfunc over $oldfunc with multiply\n" . $herecurr) &&
+                                        "Prefer $newfunc over $oldfunc with multiply\n" . $herectx) &&
+                                   $cnt == 1 &&
                                    $fix) {
                                        $fixed[$fixlinenr] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1 . ' = ' . "$newfunc(" . trim($r1) . ', ' . trim($r2)/e;
-
                                }
                        }
                }
@@ -6066,11 +6121,11 @@ sub process {
                }
 
 # check for various structs that are normally const (ops, kgdb, device_tree)
+# and avoid what seem like struct definitions 'struct foo {'
                if ($line !~ /\bconst\b/ &&
-                   $line =~ /\bstruct\s+($const_structs)\b/) {
+                   $line =~ /\bstruct\s+($const_structs)\b(?!\s*\{)/) {
                        WARN("CONST_STRUCT",
-                            "struct $1 should normally be const\n" .
-                               $herecurr);
+                            "struct $1 should normally be const\n" . $herecurr);
                }
 
 # use of NR_CPUS is usually wrong
index 5adfc8f52b4fd23e0533cb2084cc893753dd9abf..4b72b530c84f1f4b4e98d8342d9d62fefe8d34d6 100644 (file)
@@ -873,7 +873,7 @@ static void check_simple_bus_reg(struct check *c, struct dt_info *dti, struct no
        while (size--)
                reg = (reg << 32) | fdt32_to_cpu(*(cells++));
 
-       snprintf(unit_addr, sizeof(unit_addr), "%lx", reg);
+       snprintf(unit_addr, sizeof(unit_addr), "%zx", reg);
        if (!streq(unitname, unit_addr))
                FAIL(c, dti, "Node %s simple-bus unit address format error, expected \"%s\"",
                     node->fullpath, unit_addr);
diff --git a/scripts/dtc/include-prefixes/arc b/scripts/dtc/include-prefixes/arc
new file mode 120000 (symlink)
index 0000000..5d21b5a
--- /dev/null
@@ -0,0 +1 @@
+../../../arch/arc/boot/dts
\ No newline at end of file
diff --git a/scripts/dtc/include-prefixes/arm b/scripts/dtc/include-prefixes/arm
new file mode 120000 (symlink)
index 0000000..eb14d45
--- /dev/null
@@ -0,0 +1 @@
+../../../arch/arm/boot/dts
\ No newline at end of file
diff --git a/scripts/dtc/include-prefixes/arm64 b/scripts/dtc/include-prefixes/arm64
new file mode 120000 (symlink)
index 0000000..275c42c
--- /dev/null
@@ -0,0 +1 @@
+../../../arch/arm64/boot/dts
\ No newline at end of file
diff --git a/scripts/dtc/include-prefixes/c6x b/scripts/dtc/include-prefixes/c6x
new file mode 120000 (symlink)
index 0000000..49ded4c
--- /dev/null
@@ -0,0 +1 @@
+../../../arch/c6x/boot/dts
\ No newline at end of file
diff --git a/scripts/dtc/include-prefixes/cris b/scripts/dtc/include-prefixes/cris
new file mode 120000 (symlink)
index 0000000..736d998
--- /dev/null
@@ -0,0 +1 @@
+../../../arch/cris/boot/dts
\ No newline at end of file
diff --git a/scripts/dtc/include-prefixes/dt-bindings b/scripts/dtc/include-prefixes/dt-bindings
new file mode 120000 (symlink)
index 0000000..04fdbb3
--- /dev/null
@@ -0,0 +1 @@
+../../../include/dt-bindings
\ No newline at end of file
diff --git a/scripts/dtc/include-prefixes/h8300 b/scripts/dtc/include-prefixes/h8300
new file mode 120000 (symlink)
index 0000000..3bdaa33
--- /dev/null
@@ -0,0 +1 @@
+../../../arch/h8300/boot/dts
\ No newline at end of file
diff --git a/scripts/dtc/include-prefixes/metag b/scripts/dtc/include-prefixes/metag
new file mode 120000 (symlink)
index 0000000..87a3c84
--- /dev/null
@@ -0,0 +1 @@
+../../../arch/metag/boot/dts
\ No newline at end of file
diff --git a/scripts/dtc/include-prefixes/microblaze b/scripts/dtc/include-prefixes/microblaze
new file mode 120000 (symlink)
index 0000000..d983033
--- /dev/null
@@ -0,0 +1 @@
+../../../arch/microblaze/boot/dts
\ No newline at end of file
diff --git a/scripts/dtc/include-prefixes/mips b/scripts/dtc/include-prefixes/mips
new file mode 120000 (symlink)
index 0000000..ae8d494
--- /dev/null
@@ -0,0 +1 @@
+../../../arch/mips/boot/dts
\ No newline at end of file
diff --git a/scripts/dtc/include-prefixes/nios2 b/scripts/dtc/include-prefixes/nios2
new file mode 120000 (symlink)
index 0000000..5177233
--- /dev/null
@@ -0,0 +1 @@
+../../../arch/nios2/boot/dts
\ No newline at end of file
diff --git a/scripts/dtc/include-prefixes/openrisc b/scripts/dtc/include-prefixes/openrisc
new file mode 120000 (symlink)
index 0000000..71c3bc7
--- /dev/null
@@ -0,0 +1 @@
+../../../arch/openrisc/boot/dts
\ No newline at end of file
diff --git a/scripts/dtc/include-prefixes/powerpc b/scripts/dtc/include-prefixes/powerpc
new file mode 120000 (symlink)
index 0000000..7cd6ec1
--- /dev/null
@@ -0,0 +1 @@
+../../../arch/powerpc/boot/dts
\ No newline at end of file
diff --git a/scripts/dtc/include-prefixes/sh b/scripts/dtc/include-prefixes/sh
new file mode 120000 (symlink)
index 0000000..67d3780
--- /dev/null
@@ -0,0 +1 @@
+../../../arch/sh/boot/dts
\ No newline at end of file
diff --git a/scripts/dtc/include-prefixes/xtensa b/scripts/dtc/include-prefixes/xtensa
new file mode 120000 (symlink)
index 0000000..d1eaf6e
--- /dev/null
@@ -0,0 +1 @@
+../../../arch/xtensa/boot/dts
\ No newline at end of file
index 69148d30ca3f8737142409ed16608220ccc46e44..d02258bafe7b9881fccd224bfd37a2833506c0ea 100644 (file)
@@ -440,16 +440,16 @@ union yyalloc
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  4
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   524
+#define YYLAST   522
 
 /* YYNTOKENS -- Number of terminals.  */
 #define YYNTOKENS  55
 /* YYNNTS -- Number of nonterminals.  */
 #define YYNNTS  49
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  134
+#define YYNRULES  133
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  189
+#define YYNSTATES  187
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
@@ -506,13 +506,13 @@ static const yytype_uint16 yyprhs[] =
       97,   101,   105,   109,   112,   115,   118,   120,   122,   124,
      126,   128,   130,   132,   134,   136,   138,   140,   142,   145,
      146,   148,   150,   153,   155,   157,   159,   161,   164,   166,
-     168,   170,   175,   180,   183,   187,   191,   194,   196,   198,
-     200,   205,   210,   213,   217,   221,   224,   226,   230,   231,
-     233,   235,   239,   242,   245,   247,   248,   250,   252,   257,
-     262,   265,   269,   273,   277,   278,   280,   283,   287,   291,
-     292,   294,   296,   299,   303,   306,   307,   309,   311,   315,
-     318,   321,   323,   326,   327,   330,   334,   339,   341,   345,
-     347,   351,   354,   355,   357
+     168,   170,   175,   180,   183,   187,   190,   192,   194,   196,
+     201,   206,   209,   213,   217,   220,   222,   226,   227,   229,
+     231,   235,   238,   241,   243,   244,   246,   248,   253,   258,
+     261,   265,   269,   273,   274,   276,   279,   283,   287,   288,
+     290,   292,   295,   299,   302,   303,   305,   307,   311,   314,
+     317,   319,   322,   323,   326,   330,   335,   337,   341,   343,
+     347,   350,   351,   353
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
@@ -536,25 +536,24 @@ static const yytype_int8 yyrhs[] =
       74,    75,    -1,     8,    -1,    27,    -1,    32,    -1,    18,
       -1,    72,    76,    -1,    77,    -1,    39,    -1,    43,    -1,
       77,    49,    80,    50,    -1,    77,    49,     1,    50,    -1,
-      77,    35,    -1,    49,    76,    50,    -1,    49,     1,    50,
-      -1,    72,    78,    -1,    79,    -1,    39,    -1,    43,    -1,
-      79,    49,    80,    50,    -1,    79,    49,     1,    50,    -1,
-      79,    35,    -1,    49,    78,    50,    -1,    49,     1,    50,
-      -1,    81,    38,    -1,    81,    -1,    82,    48,    38,    -1,
-      -1,    82,    -1,    83,    -1,    82,    48,    83,    -1,    67,
-      84,    -1,    72,    84,    -1,    85,    -1,    -1,    39,    -1,
-      43,    -1,    85,    49,    80,    50,    -1,    85,    49,     1,
-      50,    -1,    85,    35,    -1,    49,    84,    50,    -1,    49,
-       1,    50,    -1,    66,    76,    34,    -1,    -1,    88,    -1,
-      52,    36,    -1,    53,    90,    47,    -1,    53,     1,    47,
-      -1,    -1,    91,    -1,    92,    -1,    91,    92,    -1,    66,
-      93,    46,    -1,     1,    46,    -1,    -1,    94,    -1,    95,
-      -1,    94,    48,    95,    -1,    78,    97,    -1,    39,    96,
-      -1,    96,    -1,    54,    36,    -1,    -1,    97,    32,    -1,
-      53,    99,    47,    -1,    53,    99,    48,    47,    -1,   100,
-      -1,    99,    48,   100,    -1,    39,    -1,    39,    52,    36,
-      -1,    31,    46,    -1,    -1,    31,    -1,    30,    49,    39,
-      50,    46,    -1
+      77,    35,    -1,    49,    76,    50,    -1,    72,    78,    -1,
+      79,    -1,    39,    -1,    43,    -1,    79,    49,    80,    50,
+      -1,    79,    49,     1,    50,    -1,    79,    35,    -1,    49,
+      78,    50,    -1,    49,     1,    50,    -1,    81,    38,    -1,
+      81,    -1,    82,    48,    38,    -1,    -1,    82,    -1,    83,
+      -1,    82,    48,    83,    -1,    67,    84,    -1,    72,    84,
+      -1,    85,    -1,    -1,    39,    -1,    43,    -1,    85,    49,
+      80,    50,    -1,    85,    49,     1,    50,    -1,    85,    35,
+      -1,    49,    84,    50,    -1,    49,     1,    50,    -1,    66,
+      76,    34,    -1,    -1,    88,    -1,    52,    36,    -1,    53,
+      90,    47,    -1,    53,     1,    47,    -1,    -1,    91,    -1,
+      92,    -1,    91,    92,    -1,    66,    93,    46,    -1,     1,
+      46,    -1,    -1,    94,    -1,    95,    -1,    94,    48,    95,
+      -1,    78,    97,    -1,    39,    96,    -1,    96,    -1,    54,
+      36,    -1,    -1,    97,    32,    -1,    53,    99,    47,    -1,
+      53,    99,    48,    47,    -1,   100,    -1,    99,    48,   100,
+      -1,    39,    -1,    39,    52,    36,    -1,    31,    46,    -1,
+      -1,    31,    -1,    30,    49,    39,    50,    46,    -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
@@ -567,13 +566,13 @@ static const yytype_uint16 yyrline[] =
      238,   240,   242,   247,   250,   251,   255,   256,   257,   258,
      259,   260,   261,   262,   263,   264,   265,   266,   270,   275,
      276,   280,   281,   285,   285,   285,   286,   294,   295,   299,
-     308,   317,   319,   321,   323,   325,   332,   333,   337,   338,
-     339,   341,   343,   345,   347,   352,   353,   354,   358,   359,
-     363,   364,   369,   374,   376,   380,   381,   389,   393,   395,
-     397,   399,   401,   406,   415,   416,   421,   426,   427,   431,
-     432,   436,   437,   441,   443,   448,   449,   453,   454,   458,
-     459,   460,   464,   468,   469,   473,   474,   478,   479,   482,
-     487,   495,   499,   500,   504
+     308,   317,   319,   321,   323,   330,   331,   335,   336,   337,
+     339,   341,   343,   345,   350,   351,   352,   356,   357,   361,
+     362,   367,   372,   374,   378,   379,   387,   391,   393,   395,
+     397,   399,   404,   413,   414,   419,   424,   425,   429,   430,
+     434,   435,   439,   441,   446,   447,   451,   452,   456,   457,
+     458,   462,   466,   467,   471,   472,   476,   477,   480,   485,
+     493,   497,   498,   502
 };
 #endif
 
@@ -636,13 +635,13 @@ static const yytype_uint8 yyr1[] =
       70,    70,    70,    70,    70,    70,    71,    71,    71,    71,
       71,    71,    71,    71,    71,    71,    71,    71,    72,    73,
       73,    74,    74,    75,    75,    75,    75,    76,    76,    77,
-      77,    77,    77,    77,    77,    77,    78,    78,    79,    79,
-      79,    79,    79,    79,    79,    80,    80,    80,    81,    81,
-      82,    82,    83,    84,    84,    85,    85,    85,    85,    85,
-      85,    85,    85,    86,    87,    87,    88,    89,    89,    90,
-      90,    91,    91,    92,    92,    93,    93,    94,    94,    95,
-      95,    95,    96,    97,    97,    98,    98,    99,    99,   100,
-     100,   101,   102,   102,   103
+      77,    77,    77,    77,    77,    78,    78,    79,    79,    79,
+      79,    79,    79,    79,    80,    80,    80,    81,    81,    82,
+      82,    83,    84,    84,    85,    85,    85,    85,    85,    85,
+      85,    85,    86,    87,    87,    88,    89,    89,    90,    90,
+      91,    91,    92,    92,    93,    93,    94,    94,    95,    95,
+      95,    96,    97,    97,    98,    98,    99,    99,   100,   100,
+     101,   102,   102,   103
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
@@ -655,13 +654,13 @@ static const yytype_uint8 yyr2[] =
        3,     3,     3,     2,     2,     2,     1,     1,     1,     1,
        1,     1,     1,     1,     1,     1,     1,     1,     2,     0,
        1,     1,     2,     1,     1,     1,     1,     2,     1,     1,
-       1,     4,     4,     2,     3,     3,     2,     1,     1,     1,
-       4,     4,     2,     3,     3,     2,     1,     3,     0,     1,
-       1,     3,     2,     2,     1,     0,     1,     1,     4,     4,
-       2,     3,     3,     3,     0,     1,     2,     3,     3,     0,
-       1,     1,     2,     3,     2,     0,     1,     1,     3,     2,
-       2,     1,     2,     0,     2,     3,     4,     1,     3,     1,
-       3,     2,     0,     1,     5
+       1,     4,     4,     2,     3,     2,     1,     1,     1,     4,
+       4,     2,     3,     3,     2,     1,     3,     0,     1,     1,
+       3,     2,     2,     1,     0,     1,     1,     4,     4,     2,
+       3,     3,     3,     0,     1,     2,     3,     3,     0,     1,
+       1,     2,     3,     2,     0,     1,     1,     3,     2,     2,
+       1,     2,     0,     2,     3,     4,     1,     3,     1,     3,
+       2,     0,     1,     5
 };
 
 /* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
@@ -675,189 +674,189 @@ static const yytype_uint8 yydefact[] =
        0,    56,     0,     0,    65,    36,    57,     5,    10,    17,
       23,    24,    26,    27,    33,    34,    11,    12,    13,    14,
       15,    39,     0,    43,     6,    37,     0,    44,    22,    38,
-      45,     0,     0,   131,    69,    70,     0,    59,     0,    18,
-      19,     0,   132,    68,    25,    42,   129,     0,   127,    22,
-      40,     0,   115,     0,     0,   111,     9,    17,    41,    95,
-       0,     0,     0,     0,    58,    60,    61,    16,     0,    67,
-     133,   103,   123,    73,     0,     0,   125,     0,     7,   114,
-     108,    78,    79,     0,     0,     0,   123,    77,     0,   116,
-     117,   121,   107,     0,   112,   132,    96,    57,     0,    95,
-      92,    94,    35,     0,    75,    74,    62,    20,   104,     0,
-       0,    86,    89,    90,   130,   126,   128,   120,     0,    78,
-       0,   122,    76,   119,    82,     0,   113,     0,     0,    97,
-       0,    93,   100,     0,   134,   124,     0,    21,   105,    72,
-      71,    85,     0,    84,    83,     0,     0,   118,   102,   101,
-       0,     0,   106,    87,    91,    81,    80,    99,    98
+      45,     0,     0,   130,    69,    70,     0,    59,     0,    18,
+      19,     0,   131,    68,    25,    42,   128,     0,   126,    22,
+      40,     0,   114,     0,     0,   110,     9,    17,    41,    94,
+       0,     0,     0,    58,    60,    61,    16,     0,    67,   132,
+     102,   122,    73,     0,     0,   124,     0,     7,   113,   107,
+      77,    78,     0,     0,     0,   122,    76,     0,   115,   116,
+     120,   106,     0,   111,   131,    95,    57,     0,    94,    91,
+      93,    35,     0,    74,    62,    20,   103,     0,     0,    85,
+      88,    89,   129,   125,   127,   119,     0,    77,     0,   121,
+      75,   118,    81,     0,   112,     0,     0,    96,     0,    92,
+      99,     0,   133,   123,     0,    21,   104,    72,    71,    84,
+       0,    83,    82,     0,     0,   117,   101,   100,     0,     0,
+     105,    86,    90,    80,    79,    98,    97
 };
 
 /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int16 yydefgoto[] =
 {
       -1,     1,     2,     3,    37,    79,    58,    38,    68,    69,
-      70,    82,    40,    41,    42,    43,    44,    71,    94,    95,
-      45,   125,    73,   116,   117,   140,   141,   142,   143,   130,
-     131,    46,   167,   168,    57,    83,    84,    85,   118,   119,
-     120,   121,   138,    53,    77,    78,    47,   102,    48
+      70,    82,    40,    41,    42,    43,    44,    71,    93,    94,
+      45,   124,    73,   115,   116,   138,   139,   140,   141,   129,
+     130,    46,   165,   166,    57,    83,    84,    85,   117,   118,
+     119,   120,   136,    53,    77,    78,    47,   101,    48
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
-#define YYPACT_NINF -111
+#define YYPACT_NINF -94
 static const yytype_int16 yypact[] =
 {
-    -111,    13,  -111,   210,  -111,  -111,    28,  -111,  -111,  -111,
-    -111,  -111,   -27,  -111,    44,  -111,  -111,  -111,  -111,  -111,
-    -111,  -111,  -111,  -111,   -24,  -111,   -20,  -111,  -111,  -111,
-      31,  -111,    32,    42,  -111,  -111,  -111,  -111,  -111,    34,
-     481,  -111,  -111,  -111,  -111,  -111,  -111,  -111,  -111,  -111,
-    -111,    51,    56,  -111,  -111,    52,   108,  -111,   481,    52,
-    -111,   481,    58,  -111,  -111,  -111,    19,     0,    54,    55,
-    -111,    34,    30,   -18,  -111,  -111,    68,   -25,  -111,   481,
-    -111,    45,    33,    59,   159,  -111,  -111,    34,  -111,   395,
-      57,    60,    81,    88,  -111,     0,  -111,  -111,    34,  -111,
-    -111,  -111,  -111,  -111,   257,    72,  -111,   -23,  -111,  -111,
-    -111,    85,  -111,    20,   106,    47,  -111,   -10,    97,    96,
-    -111,  -111,  -111,    99,  -111,   115,  -111,  -111,     5,    50,
-    -111,    11,  -111,   102,  -111,  -111,  -111,  -111,   -22,   100,
-     103,   111,   104,  -111,  -111,  -111,  -111,  -111,   113,  -111,
-     121,  -111,  -111,   124,  -111,   303,  -111,    33,   132,  -111,
-     139,  -111,  -111,   349,  -111,  -111,   122,  -111,  -111,  -111,
-    -111,  -111,   442,  -111,  -111,   140,   143,  -111,  -111,  -111,
-     144,   145,  -111,  -111,  -111,  -111,  -111,  -111,  -111
+     -94,    15,   -94,   208,   -94,   -94,    34,   -94,   -94,   -94,
+     -94,   -94,   -27,   -94,    -5,   -94,   -94,   -94,   -94,   -94,
+     -94,   -94,   -94,   -94,   -25,   -94,   -16,   -94,   -94,   -94,
+      -4,   -94,    19,   -24,   -94,   -94,   -94,   -94,   -94,    24,
+     479,   -94,   -94,   -94,   -94,   -94,   -94,   -94,   -94,   -94,
+     -94,    29,    48,   -94,   -94,    37,   106,   -94,   479,    37,
+     -94,   479,    54,   -94,   -94,   -94,    24,    -2,    49,    53,
+     -94,    24,   -14,   -11,   -94,   -94,    47,    38,   -94,   479,
+     -94,    51,    23,    55,   157,   -94,   -94,    24,   -94,   393,
+      56,    58,    68,   -94,    -2,   -94,   -94,    24,   -94,   -94,
+     -94,   -94,   -94,   255,    67,   -94,     5,   -94,   -94,   -94,
+      50,   -94,     7,    69,    40,   -94,    -8,    83,    88,   -94,
+     -94,   -94,    91,   -94,   109,   -94,   -94,     4,    45,   -94,
+      16,   -94,    95,   -94,   -94,   -94,   -23,    92,    93,   108,
+      96,   -94,   -94,   -94,   -94,   -94,    97,   -94,    98,   -94,
+     -94,   118,   -94,   301,   -94,    23,   101,   -94,   104,   -94,
+     -94,   347,   -94,   -94,   120,   -94,   -94,   -94,   -94,   -94,
+     440,   -94,   -94,   111,   119,   -94,   -94,   -94,   130,   137,
+     -94,   -94,   -94,   -94,   -94,   -94,   -94
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int16 yypgoto[] =
 {
-    -111,  -111,   160,  -111,  -111,  -111,  -111,   -51,  -111,  -111,
-      98,    -1,   -61,   -37,  -111,  -111,  -111,   -78,  -111,  -111,
-     -53,   -30,  -111,   -66,  -111,  -110,  -111,  -111,   -60,   -63,
-    -111,  -111,  -111,  -111,   -21,  -111,  -111,   116,  -111,  -111,
-      40,    90,    83,   152,  -111,   105,  -111,  -111,  -111
+     -94,   -94,   158,   -94,   -94,   -94,   -94,   -45,   -94,   -94,
+      94,    -1,   -61,   -29,   -94,   -94,   -94,   -79,   -94,   -94,
+     -63,    -7,   -94,   -93,   -94,   -92,   -94,   -94,   -60,   -57,
+     -94,   -94,   -94,   -94,   -19,   -94,   -94,   110,   -94,   -94,
+      33,    82,    78,   144,   -94,    99,   -94,   -94,   -94
 };
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
    positive, shift that token.  If negative, reduce the rule which
    number is the opposite.  If YYTABLE_NINF, syntax error.  */
-#define YYTABLE_NINF -111
+#define YYTABLE_NINF -110
 static const yytype_int16 yytable[] =
 {
-      89,    90,    39,    74,   115,    60,   158,    86,    10,    72,
-     165,   129,    51,     4,    96,    55,    76,   103,    20,    59,
-      92,   148,   106,   107,   145,   154,    52,    29,   108,    56,
-     166,   104,    34,    56,    80,   115,    93,   115,    88,   155,
-     -95,    99,   136,    89,   126,   176,   162,   150,   159,   152,
-     129,   129,    74,   181,   128,   -95,    67,    87,    64,   149,
-     163,   100,    65,   112,   101,   160,   161,    54,    66,   113,
-      67,    67,   111,    64,    49,    50,   112,    65,    87,   115,
-      61,    62,   113,    66,    67,    67,   149,   114,    63,   126,
-     112,   109,   110,   159,    89,    76,   113,    91,    67,   128,
-      97,    67,    89,    98,    52,    56,   122,   132,   144,    81,
-     133,    89,   184,     7,     8,     9,    10,    11,    12,    13,
-     105,    15,    16,    17,    18,    19,    20,    21,    22,    23,
-      24,   134,    26,    27,    28,    29,    30,    31,   135,   114,
-      34,    35,   151,   156,   157,   109,   100,   -22,   164,   171,
-     169,    36,   172,   170,   -22,  -109,   165,   -22,   182,   -22,
-     123,     5,   -22,   173,     7,     8,     9,    10,    11,    12,
-      13,   174,    15,    16,    17,    18,    19,    20,    21,    22,
-      23,    24,   178,    26,    27,    28,    29,    30,    31,   179,
-     185,    34,    35,   186,   187,   188,   137,   177,   -22,   153,
-     124,   147,    36,    75,     0,   -22,  -110,     0,   -22,     0,
-     -22,     6,   146,   -22,     0,     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,     0,     0,     0,     0,     0,   -22,
-       0,     0,     0,    36,     0,     0,   -22,     0,   139,   -22,
-       0,   -22,     7,     8,     9,    10,    11,    12,    13,     0,
+      89,    90,    39,   114,    95,   156,    10,    60,   146,   163,
+     128,    74,    51,    86,    55,     4,    20,    99,    54,   148,
+     100,   150,    63,    59,   102,    29,    52,   152,    56,   164,
+      34,   134,    72,   114,   107,   114,    80,    56,   103,   -94,
+      88,   153,    89,   125,    76,    61,   147,   157,   128,   128,
+     111,   160,   143,   127,   -94,    67,   112,    87,    67,    92,
+      74,   174,   110,    64,    98,   161,   111,    65,    62,   179,
+     158,   159,   112,    66,    67,    67,   114,   113,    87,   147,
+      49,    50,    52,   111,   125,   105,   106,    76,   157,   112,
+      56,    67,    89,    91,   127,    96,    67,   108,   109,   104,
+      89,    97,   121,   142,   113,   149,   131,    81,   132,    89,
+     182,     7,     8,     9,    10,    11,    12,    13,   133,    15,
+      16,    17,    18,    19,    20,    21,    22,    23,    24,   154,
+      26,    27,    28,    29,    30,    31,   155,   108,    34,    35,
+      99,   162,   167,   168,   170,   -22,   169,   171,   172,    36,
+     163,   176,   -22,  -108,   177,   -22,   180,   -22,   122,     5,
+     -22,   183,     7,     8,     9,    10,    11,    12,    13,   184,
+      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
+     185,    26,    27,    28,    29,    30,    31,   186,   175,    34,
+      35,   135,   145,   151,   123,    75,   -22,     0,     0,     0,
+      36,     0,     0,   -22,  -109,   144,   -22,     0,   -22,     6,
+       0,   -22,     0,     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,     0,     0,     0,     0,     0,   -22,     0,     0,
+       0,    36,     0,     0,   -22,     0,   137,   -22,     0,   -22,
+       7,     8,     9,    10,    11,    12,    13,     0,    15,    16,
+      17,    18,    19,    20,    21,    22,    23,    24,     0,    26,
+      27,    28,    29,    30,    31,     0,     0,    34,    35,     0,
+       0,     0,     0,   -87,     0,     0,     0,     0,    36,     0,
+       0,     0,   173,     0,     0,   -87,     7,     8,     9,    10,
+      11,    12,    13,     0,    15,    16,    17,    18,    19,    20,
+      21,    22,    23,    24,     0,    26,    27,    28,    29,    30,
+      31,     0,     0,    34,    35,     0,     0,     0,     0,   -87,
+       0,     0,     0,     0,    36,     0,     0,     0,   178,     0,
+       0,   -87,     7,     8,     9,    10,    11,    12,    13,     0,
       15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
        0,    26,    27,    28,    29,    30,    31,     0,     0,    34,
-      35,     0,     0,     0,     0,   -88,     0,     0,     0,     0,
-      36,     0,     0,     0,   175,     0,     0,   -88,     7,     8,
+      35,     0,     0,     0,     0,   -87,     0,     0,     0,     0,
+      36,     0,     0,     0,     0,     0,     0,   -87,     7,     8,
        9,    10,    11,    12,    13,     0,    15,    16,    17,    18,
       19,    20,    21,    22,    23,    24,     0,    26,    27,    28,
       29,    30,    31,     0,     0,    34,    35,     0,     0,     0,
-       0,   -88,     0,     0,     0,     0,    36,     0,     0,     0,
-     180,     0,     0,   -88,     7,     8,     9,    10,    11,    12,
+       0,     0,   125,     0,     0,     0,   126,     0,     0,     0,
+       0,     0,   127,     0,    67,     7,     8,     9,    10,    11,
+      12,    13,     0,    15,    16,    17,    18,    19,    20,    21,
+      22,    23,    24,     0,    26,    27,    28,    29,    30,    31,
+       0,     0,    34,    35,     0,     0,     0,     0,   181,     0,
+       0,     0,     0,    36,     7,     8,     9,    10,    11,    12,
       13,     0,    15,    16,    17,    18,    19,    20,    21,    22,
       23,    24,     0,    26,    27,    28,    29,    30,    31,     0,
-       0,    34,    35,     0,     0,     0,     0,   -88,     0,     0,
-       0,     0,    36,     0,     0,     0,     0,     0,     0,   -88,
-       7,     8,     9,    10,    11,    12,    13,     0,    15,    16,
-      17,    18,    19,    20,    21,    22,    23,    24,     0,    26,
-      27,    28,    29,    30,    31,     0,     0,    34,    35,     0,
-       0,     0,     0,     0,   126,     0,     0,     0,   127,     0,
-       0,     0,     0,     0,   128,     0,    67,     7,     8,     9,
-      10,    11,    12,    13,     0,    15,    16,    17,    18,    19,
-      20,    21,    22,    23,    24,     0,    26,    27,    28,    29,
-      30,    31,     0,     0,    34,    35,     0,     0,     0,     0,
-     183,     0,     0,     0,     0,    36,     7,     8,     9,    10,
-      11,    12,    13,     0,    15,    16,    17,    18,    19,    20,
-      21,    22,    23,    24,     0,    26,    27,    28,    29,    30,
-      31,     0,     0,    34,    35,     0,     0,     0,     0,     0,
-       0,     0,     0,     0,    36
+       0,    34,    35,     0,     0,     0,     0,     0,     0,     0,
+       0,     0,    36
 };
 
 #define yypact_value_is_default(Yystate) \
-  (!!((Yystate) == (-111)))
+  (!!((Yystate) == (-94)))
 
 #define yytable_value_is_error(Yytable_value) \
   YYID (0)
 
 static const yytype_int16 yycheck[] =
 {
-      61,    61,     3,    40,    82,    26,     1,    58,     8,    39,
-      32,    89,    39,     0,    67,    39,    39,    35,    18,    39,
-       1,     1,    47,    48,    47,    35,    53,    27,    79,    53,
-      52,    49,    32,    53,    55,   113,    66,   115,    59,    49,
-      35,    71,    95,   104,    39,   155,    35,   113,    43,   115,
-     128,   129,    89,   163,    49,    50,    51,    58,    39,    39,
-      49,    31,    43,    43,    34,   128,   129,    23,    49,    49,
-      51,    51,    39,    39,    46,    47,    43,    43,    79,   157,
-      49,    49,    49,    49,    51,    51,    39,    54,    46,    39,
-      43,    46,    47,    43,   155,    39,    49,    39,    51,    49,
-      46,    51,   163,    48,    53,    53,    47,    50,    36,     1,
-      50,   172,   172,     5,     6,     7,     8,     9,    10,    11,
-      52,    13,    14,    15,    16,    17,    18,    19,    20,    21,
-      22,    50,    24,    25,    26,    27,    28,    29,    50,    54,
-      32,    33,    36,    46,    48,    46,    31,    39,    46,    38,
-      50,    43,    48,    50,    46,    47,    32,    49,    36,    51,
-       1,     1,    54,    50,     5,     6,     7,     8,     9,    10,
-      11,    50,    13,    14,    15,    16,    17,    18,    19,    20,
-      21,    22,    50,    24,    25,    26,    27,    28,    29,    50,
-      50,    32,    33,    50,    50,    50,    98,   157,    39,   116,
-      84,   111,    43,    51,    -1,    46,    47,    -1,    49,    -1,
-      51,     1,   107,    54,    -1,     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,    -1,    -1,    -1,    -1,    -1,    39,
-      -1,    -1,    -1,    43,    -1,    -1,    46,    -1,     1,    49,
-      -1,    51,     5,     6,     7,     8,     9,    10,    11,    -1,
+      61,    61,     3,    82,    67,     1,     8,    26,     1,    32,
+      89,    40,    39,    58,    39,     0,    18,    31,    23,   112,
+      34,   114,    46,    39,    35,    27,    53,    35,    53,    52,
+      32,    94,    39,   112,    79,   114,    55,    53,    49,    35,
+      59,    49,   103,    39,    39,    49,    39,    43,   127,   128,
+      43,    35,    47,    49,    50,    51,    49,    58,    51,    66,
+      89,   153,    39,    39,    71,    49,    43,    43,    49,   161,
+     127,   128,    49,    49,    51,    51,   155,    54,    79,    39,
+      46,    47,    53,    43,    39,    47,    48,    39,    43,    49,
+      53,    51,   153,    39,    49,    46,    51,    46,    47,    52,
+     161,    48,    47,    36,    54,    36,    50,     1,    50,   170,
+     170,     5,     6,     7,     8,     9,    10,    11,    50,    13,
+      14,    15,    16,    17,    18,    19,    20,    21,    22,    46,
+      24,    25,    26,    27,    28,    29,    48,    46,    32,    33,
+      31,    46,    50,    50,    48,    39,    38,    50,    50,    43,
+      32,    50,    46,    47,    50,    49,    36,    51,     1,     1,
+      54,    50,     5,     6,     7,     8,     9,    10,    11,    50,
+      13,    14,    15,    16,    17,    18,    19,    20,    21,    22,
+      50,    24,    25,    26,    27,    28,    29,    50,   155,    32,
+      33,    97,   110,   115,    84,    51,    39,    -1,    -1,    -1,
+      43,    -1,    -1,    46,    47,   106,    49,    -1,    51,     1,
+      -1,    54,    -1,     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,    -1,    -1,    -1,    -1,    -1,    39,    -1,    -1,
+      -1,    43,    -1,    -1,    46,    -1,     1,    49,    -1,    51,
+       5,     6,     7,     8,     9,    10,    11,    -1,    13,    14,
+      15,    16,    17,    18,    19,    20,    21,    22,    -1,    24,
+      25,    26,    27,    28,    29,    -1,    -1,    32,    33,    -1,
+      -1,    -1,    -1,    38,    -1,    -1,    -1,    -1,    43,    -1,
+      -1,    -1,     1,    -1,    -1,    50,     5,     6,     7,     8,
+       9,    10,    11,    -1,    13,    14,    15,    16,    17,    18,
+      19,    20,    21,    22,    -1,    24,    25,    26,    27,    28,
+      29,    -1,    -1,    32,    33,    -1,    -1,    -1,    -1,    38,
+      -1,    -1,    -1,    -1,    43,    -1,    -1,    -1,     1,    -1,
+      -1,    50,     5,     6,     7,     8,     9,    10,    11,    -1,
       13,    14,    15,    16,    17,    18,    19,    20,    21,    22,
       -1,    24,    25,    26,    27,    28,    29,    -1,    -1,    32,
       33,    -1,    -1,    -1,    -1,    38,    -1,    -1,    -1,    -1,
-      43,    -1,    -1,    -1,     1,    -1,    -1,    50,     5,     6,
+      43,    -1,    -1,    -1,    -1,    -1,    -1,    50,     5,     6,
        7,     8,     9,    10,    11,    -1,    13,    14,    15,    16,
       17,    18,    19,    20,    21,    22,    -1,    24,    25,    26,
       27,    28,    29,    -1,    -1,    32,    33,    -1,    -1,    -1,
-      -1,    38,    -1,    -1,    -1,    -1,    43,    -1,    -1,    -1,
-       1,    -1,    -1,    50,     5,     6,     7,     8,     9,    10,
+      -1,    -1,    39,    -1,    -1,    -1,    43,    -1,    -1,    -1,
+      -1,    -1,    49,    -1,    51,     5,     6,     7,     8,     9,
+      10,    11,    -1,    13,    14,    15,    16,    17,    18,    19,
+      20,    21,    22,    -1,    24,    25,    26,    27,    28,    29,
+      -1,    -1,    32,    33,    -1,    -1,    -1,    -1,    38,    -1,
+      -1,    -1,    -1,    43,     5,     6,     7,     8,     9,    10,
       11,    -1,    13,    14,    15,    16,    17,    18,    19,    20,
       21,    22,    -1,    24,    25,    26,    27,    28,    29,    -1,
-      -1,    32,    33,    -1,    -1,    -1,    -1,    38,    -1,    -1,
-      -1,    -1,    43,    -1,    -1,    -1,    -1,    -1,    -1,    50,
-       5,     6,     7,     8,     9,    10,    11,    -1,    13,    14,
-      15,    16,    17,    18,    19,    20,    21,    22,    -1,    24,
-      25,    26,    27,    28,    29,    -1,    -1,    32,    33,    -1,
-      -1,    -1,    -1,    -1,    39,    -1,    -1,    -1,    43,    -1,
-      -1,    -1,    -1,    -1,    49,    -1,    51,     5,     6,     7,
-       8,     9,    10,    11,    -1,    13,    14,    15,    16,    17,
-      18,    19,    20,    21,    22,    -1,    24,    25,    26,    27,
-      28,    29,    -1,    -1,    32,    33,    -1,    -1,    -1,    -1,
-      38,    -1,    -1,    -1,    -1,    43,     5,     6,     7,     8,
-       9,    10,    11,    -1,    13,    14,    15,    16,    17,    18,
-      19,    20,    21,    22,    -1,    24,    25,    26,    27,    28,
-      29,    -1,    -1,    32,    33,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    -1,    -1,    43
+      -1,    32,    33,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
+      -1,    -1,    43
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
@@ -873,16 +872,16 @@ static const yytype_uint8 yystos[] =
       89,    49,    49,    46,    39,    43,    49,    51,    63,    64,
       65,    72,    76,    77,    68,    98,    39,    99,   100,    60,
       89,     1,    66,    90,    91,    92,    62,    66,    89,    67,
-      83,    39,     1,    76,    73,    74,    75,    46,    48,    76,
-      31,    34,   102,    35,    49,    52,    47,    48,    62,    46,
-      47,    39,    43,    49,    54,    72,    78,    79,    93,    94,
-      95,    96,    47,     1,    92,    76,    39,    43,    49,    72,
-      84,    85,    50,    50,    50,    50,    75,    65,    97,     1,
-      80,    81,    82,    83,    36,    47,   100,    96,     1,    39,
-      78,    36,    78,    97,    35,    49,    46,    48,     1,    43,
-      84,    84,    35,    49,    46,    32,    52,    87,    88,    50,
-      50,    38,    48,    50,    50,     1,    80,    95,    50,    50,
-       1,    80,    36,    38,    83,    50,    50,    50,    50
+      83,    39,    76,    73,    74,    75,    46,    48,    76,    31,
+      34,   102,    35,    49,    52,    47,    48,    62,    46,    47,
+      39,    43,    49,    54,    72,    78,    79,    93,    94,    95,
+      96,    47,     1,    92,    76,    39,    43,    49,    72,    84,
+      85,    50,    50,    50,    75,    65,    97,     1,    80,    81,
+      82,    83,    36,    47,   100,    96,     1,    39,    78,    36,
+      78,    97,    35,    49,    46,    48,     1,    43,    84,    84,
+      35,    49,    46,    32,    52,    87,    88,    50,    50,    38,
+      48,    50,    50,     1,    80,    95,    50,    50,     1,    80,
+      36,    38,    83,    50,    50,    50,    50
 };
 
 #define yyerrok                (yyerrstatus = 0)
@@ -1928,12 +1927,12 @@ yyreduce:
 
   case 75:
 
-    { (yyval) = (yyvsp[(3) - (3)]); }
+    { (yyval) = (yyvsp[(2) - (2)]); }
     break;
 
-  case 76:
+  case 79:
 
-    { (yyval) = (yyvsp[(2) - (2)]); }
+    { (yyval) = (yyvsp[(4) - (4)]); }
     break;
 
   case 80:
@@ -1943,12 +1942,12 @@ yyreduce:
 
   case 81:
 
-    { (yyval) = (yyvsp[(4) - (4)]); }
+    { (yyval) = (yyvsp[(2) - (2)]); }
     break;
 
   case 82:
 
-    { (yyval) = (yyvsp[(2) - (2)]); }
+    { (yyval) = (yyvsp[(3) - (3)]); }
     break;
 
   case 83:
@@ -1958,45 +1957,40 @@ yyreduce:
 
   case 84:
 
-    { (yyval) = (yyvsp[(3) - (3)]); }
-    break;
-
-  case 85:
-
     { (yyval) = (yyvsp[(2) - (2)]); }
     break;
 
-  case 87:
+  case 86:
 
     { (yyval) = (yyvsp[(3) - (3)]); }
     break;
 
-  case 88:
+  case 87:
 
     { (yyval) = NULL; }
     break;
 
-  case 91:
+  case 90:
 
     { (yyval) = (yyvsp[(3) - (3)]); }
     break;
 
-  case 92:
+  case 91:
 
     { (yyval) = (yyvsp[(2) - (2)]) ? (yyvsp[(2) - (2)]) : (yyvsp[(1) - (2)]); }
     break;
 
-  case 93:
+  case 92:
 
     { (yyval) = (yyvsp[(2) - (2)]) ? (yyvsp[(2) - (2)]) : (yyvsp[(1) - (2)]); }
     break;
 
-  case 95:
+  case 94:
 
     { (yyval) = NULL; }
     break;
 
-  case 96:
+  case 95:
 
     { /* For version 2 checksums, we don't want to remember
                     private parameter names.  */
@@ -2005,39 +1999,39 @@ yyreduce:
                }
     break;
 
-  case 97:
+  case 96:
 
     { remove_node((yyvsp[(1) - (1)]));
                  (yyval) = (yyvsp[(1) - (1)]);
                }
     break;
 
-  case 98:
+  case 97:
 
     { (yyval) = (yyvsp[(4) - (4)]); }
     break;
 
-  case 99:
+  case 98:
 
     { (yyval) = (yyvsp[(4) - (4)]); }
     break;
 
-  case 100:
+  case 99:
 
     { (yyval) = (yyvsp[(2) - (2)]); }
     break;
 
-  case 101:
+  case 100:
 
     { (yyval) = (yyvsp[(3) - (3)]); }
     break;
 
-  case 102:
+  case 101:
 
     { (yyval) = (yyvsp[(3) - (3)]); }
     break;
 
-  case 103:
+  case 102:
 
     { struct string_list *decl = *(yyvsp[(2) - (3)]);
                  *(yyvsp[(2) - (3)]) = NULL;
@@ -2046,87 +2040,87 @@ yyreduce:
                }
     break;
 
-  case 104:
+  case 103:
 
     { (yyval) = NULL; }
     break;
 
-  case 106:
+  case 105:
 
     { remove_list((yyvsp[(2) - (2)]), &(*(yyvsp[(1) - (2)]))->next); (yyval) = (yyvsp[(2) - (2)]); }
     break;
 
-  case 107:
+  case 106:
 
     { (yyval) = (yyvsp[(3) - (3)]); }
     break;
 
-  case 108:
+  case 107:
 
     { (yyval) = (yyvsp[(3) - (3)]); }
     break;
 
-  case 109:
+  case 108:
 
     { (yyval) = NULL; }
     break;
 
-  case 112:
+  case 111:
 
     { (yyval) = (yyvsp[(2) - (2)]); }
     break;
 
-  case 113:
+  case 112:
 
     { (yyval) = (yyvsp[(3) - (3)]); }
     break;
 
-  case 114:
+  case 113:
 
     { (yyval) = (yyvsp[(2) - (2)]); }
     break;
 
-  case 115:
+  case 114:
 
     { (yyval) = NULL; }
     break;
 
-  case 118:
+  case 117:
 
     { (yyval) = (yyvsp[(3) - (3)]); }
     break;
 
-  case 119:
+  case 118:
 
     { (yyval) = (yyvsp[(2) - (2)]) ? (yyvsp[(2) - (2)]) : (yyvsp[(1) - (2)]); }
     break;
 
-  case 120:
+  case 119:
 
     { (yyval) = (yyvsp[(2) - (2)]); }
     break;
 
-  case 122:
+  case 121:
 
     { (yyval) = (yyvsp[(2) - (2)]); }
     break;
 
-  case 123:
+  case 122:
 
     { (yyval) = NULL; }
     break;
 
-  case 125:
+  case 124:
 
     { (yyval) = (yyvsp[(3) - (3)]); }
     break;
 
-  case 126:
+  case 125:
 
     { (yyval) = (yyvsp[(4) - (4)]); }
     break;
 
-  case 129:
+  case 128:
 
     {
                        const char *name = strdup((*(yyvsp[(1) - (1)]))->string);
@@ -2134,7 +2128,7 @@ yyreduce:
                }
     break;
 
-  case 130:
+  case 129:
 
     {
                        const char *name = strdup((*(yyvsp[(1) - (3)]))->string);
@@ -2143,17 +2137,17 @@ yyreduce:
                }
     break;
 
-  case 131:
+  case 130:
 
     { (yyval) = (yyvsp[(2) - (2)]); }
     break;
 
-  case 132:
+  case 131:
 
     { (yyval) = NULL; }
     break;
 
-  case 134:
+  case 133:
 
     { export_symbol((*(yyvsp[(3) - (5)]))->string); (yyval) = (yyvsp[(5) - (5)]); }
     break;
index 4fba255e54ae49ed0fcf196b4e72695624eab58b..00a6d7e5497126147dc0d9a564c4a6525fff6079 100644 (file)
@@ -322,8 +322,6 @@ direct_declarator:
                { $$ = $2; }
        | '(' declarator ')'
                { $$ = $3; }
-       | '(' error ')'
-               { $$ = $3; }
        ;
 
 /* Nested declarators differ from regular declarators in that they do
index 19d9bcadc0ccd448fd4cff3e687ec61e3f95001a..b497d9764dcf02e0dd1abab386faef3af8b65499 100644 (file)
@@ -7,32 +7,8 @@ modpost-objs   := modpost.o file2alias.o sumversion.o
 
 devicetable-offsets-file := devicetable-offsets.h
 
-define sed-y
-       "/^->/{s:->#\(.*\):/* \1 */:; \
-       s:^->\([^ ]*\) [\$$#]*\([-0-9]*\) \(.*\):#define \1 \2 /* \3 */:; \
-       s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \
-       s:->::; p;}"
-endef
-
-quiet_cmd_offsets = GEN     $@
-define cmd_offsets
-       (set -e; \
-        echo "#ifndef __DEVICETABLE_OFFSETS_H__"; \
-        echo "#define __DEVICETABLE_OFFSETS_H__"; \
-        echo "/*"; \
-        echo " * DO NOT MODIFY."; \
-        echo " *"; \
-        echo " * This file was generated by Kbuild"; \
-        echo " *"; \
-        echo " */"; \
-        echo ""; \
-        sed -ne $(sed-y) $<; \
-        echo ""; \
-        echo "#endif" ) > $@
-endef
-
-$(obj)/$(devicetable-offsets-file): $(obj)/devicetable-offsets.s
-       $(call if_changed,offsets)
+$(obj)/$(devicetable-offsets-file): $(obj)/devicetable-offsets.s FORCE
+       $(call filechk,offsets,__DEVICETABLE_OFFSETS_H__)
 
 targets += $(devicetable-offsets-file) devicetable-offsets.s
 
index 62e51dae2138db450555f3d15dbd14cc53c53652..4fb5d67968932bbf83fbdc63ee84c374d552fa41 100755 (executable)
@@ -57,13 +57,15 @@ get_output_dir() {
 do_objdump() {
        dir=$(get_output_dir $1)
        base=${1##*/}
+       stripped=$dir/${base%.o}.stripped
        dis=$dir/${base%.o}.dis
 
        [ ! -d "$dir" ] && mkdir -p $dir
 
        # remove addresses for a cleaner diff
        # http://dummdida.tumblr.com/post/60924060451/binary-diff-between-libc-from-scientificlinux-and
-       $OBJDUMP -D $1 | sed "s/^[[:space:]]\+[0-9a-f]\+//" > $dis
+       $STRIP -g $1 -R __bug_table -R .note -R .comment -o $stripped
+       $OBJDUMP -D $stripped | sed -e "s/^[[:space:]]\+[0-9a-f]\+//" -e "s:^$stripped:$1:" > $dis
 }
 
 dorecord() {
@@ -73,6 +75,7 @@ dorecord() {
 
        CMT="`git rev-parse --short HEAD`"
 
+       STRIP="${CROSS_COMPILE}strip"
        OBJDUMP="${CROSS_COMPILE}objdump"
 
        for d in $FILES; do
index 676fc10c9514c5370bcb2ecf2901e03baaf432a6..aad67000e4dd76796894cbd1975d087c559ecc5c 100755 (executable)
@@ -69,7 +69,7 @@ set_debarch() {
                echo "" >&2
                echo "** ** **  WARNING  ** ** **" >&2
                echo "" >&2
-               echo "Your architecture doesn't have it's equivalent" >&2
+               echo "Your architecture doesn't have its equivalent" >&2
                echo "Debian userspace architecture defined!" >&2
                echo "Falling back to using your current userspace instead!" >&2
                echo "Please add support for $UTS_MACHINE to ${0} ..." >&2
@@ -143,12 +143,7 @@ else
        cp System.map "$tmpdir/boot/System.map-$version"
        cp $KCONFIG_CONFIG "$tmpdir/boot/config-$version"
 fi
-# Not all arches include the boot path in KBUILD_IMAGE
-if [ -e $KBUILD_IMAGE ]; then
-       cp $KBUILD_IMAGE "$tmpdir/$installed_image_path"
-else
-       cp arch/$ARCH/boot/$KBUILD_IMAGE "$tmpdir/$installed_image_path"
-fi
+cp "$($MAKE -s image_name)" "$tmpdir/$installed_image_path"
 
 if grep -q "^CONFIG_OF=y" $KCONFIG_CONFIG ; then
        # Only some architectures with OF support have this target
@@ -265,7 +260,7 @@ This is a packacked upstream version of the Linux kernel.
 The sources may be found at most Linux archive sites, including:
 https://www.kernel.org/pub/linux/kernel
 
-Copyright: 1991 - 2015 Linus Torvalds and others.
+Copyright: 1991 - 2017 Linus Torvalds and others.
 
 The git repository for mainline kernel development is at:
 git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
@@ -288,7 +283,6 @@ Section: kernel
 Priority: optional
 Maintainer: $maintainer
 Build-Depends: $build_depends
-Standards-Version: 3.8.4
 Homepage: http://www.kernel.org/
 EOF
 
@@ -296,7 +290,6 @@ if [ "$ARCH" = "um" ]; then
        cat <<EOF >> debian/control
 
 Package: $packagename
-Provides: linux-image, linux-image-2.6, linux-modules-$version
 Architecture: any
 Description: User Mode Linux kernel, version $version
  User-mode Linux is a port of the Linux kernel to its own system call
@@ -313,7 +306,6 @@ else
        cat <<EOF >> debian/control
 
 Package: $packagename
-Provides: linux-image, linux-image-2.6, linux-modules-$version
 Suggests: $fwpackagename
 Architecture: any
 Description: Linux kernel, version $version
@@ -346,7 +338,6 @@ rm -f "$objtree/debian/hdrsrcfiles" "$objtree/debian/hdrobjfiles"
 cat <<EOF >> debian/control
 
 Package: $kernel_headers_packagename
-Provides: linux-headers, linux-headers-2.6
 Architecture: any
 Description: Linux kernel headers for $KERNELRELEASE on \${kernel:debarch}
  This package provides kernel header files for $KERNELRELEASE on \${kernel:debarch}
@@ -404,7 +395,6 @@ if [ -n "$BUILD_DEBUG" ] ; then
 
 Package: $dbg_packagename
 Section: debug
-Provides: linux-debug, linux-debug-$version
 Architecture: any
 Description: Linux kernel debugging symbols for $version
  This package will come in handy if you need to debug the kernel. It provides
index b67e74b22826d5f237d2eeaf16275c357ffcc20c..eb38f49d4b755a75787611ff533940cb5787da60 100644 (file)
@@ -179,6 +179,7 @@ bakup||backup
 baloon||balloon
 baloons||balloons
 bandwith||bandwidth
+banlance||balance
 batery||battery
 beacuse||because
 becasue||because
@@ -375,6 +376,8 @@ dictionnary||dictionary
 didnt||didn't
 diferent||different
 differrence||difference
+diffrent||different
+diffrentiate||differentiate
 difinition||definition
 diplay||display
 direectly||directly
@@ -605,6 +608,9 @@ interruptted||interrupted
 interupted||interrupted
 interupt||interrupt
 intial||initial
+intialisation||initialisation
+intialised||initialised
+intialise||initialise
 intialization||initialization
 intialized||initialized
 intialize||initialize
@@ -691,6 +697,7 @@ miximum||maximum
 mmnemonic||mnemonic
 mnay||many
 modulues||modules
+momery||memory
 monochorome||monochrome
 monochromo||monochrome
 monocrome||monochrome
@@ -890,6 +897,7 @@ registerd||registered
 registeresd||registered
 registes||registers
 registraration||registration
+regsiter||register
 regster||register
 regualar||regular
 reguator||regulator
index 41073f70eb41db135b8b68defa7523c161624991..4f6ac9dbc65ddcda1cfc0bd188c705505e2d368c 100644 (file)
@@ -98,7 +98,7 @@ static struct aa_loaddata *aa_simple_write_to_buffer(const char __user *userbuf,
                return ERR_PTR(-ESPIPE);
 
        /* freed by caller to simple_write_to_buffer */
-       data = kvmalloc(sizeof(*data) + alloc_size);
+       data = kvmalloc(sizeof(*data) + alloc_size, GFP_KERNEL);
        if (data == NULL)
                return ERR_PTR(-ENOMEM);
        kref_init(&data->count);
@@ -1357,7 +1357,7 @@ static int aa_mk_null_file(struct dentry *parent)
 
        inode->i_ino = get_next_ino();
        inode->i_mode = S_IFCHR | S_IRUGO | S_IWUGO;
-       inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+       inode->i_atime = inode->i_mtime = inode->i_ctime = current_time(inode);
        init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO,
                           MKDEV(MEM_MAJOR, 3));
        d_instantiate(dentry, inode);
index 0291ff3902f900e16882cf179e7dab7516fd1ecb..550a700563b43ecb6546509bd976998e3e2ac578 100644 (file)
@@ -64,17 +64,6 @@ char *aa_split_fqname(char *args, char **ns_name);
 const char *aa_splitn_fqname(const char *fqname, size_t n, const char **ns_name,
                             size_t *ns_len);
 void aa_info_message(const char *str);
-void *__aa_kvmalloc(size_t size, gfp_t flags);
-
-static inline void *kvmalloc(size_t size)
-{
-       return __aa_kvmalloc(size, 0);
-}
-
-static inline void *kvzalloc(size_t size)
-{
-       return __aa_kvmalloc(size, __GFP_ZERO);
-}
 
 /**
  * aa_strneq - compare null terminated @str to a non null terminated substring
index 32cafc12593ef8f52d3164c46a4c90fe6b9a1743..7cd788a9445be4c033e5e7f099ca26de5c678858 100644 (file)
@@ -128,36 +128,6 @@ void aa_info_message(const char *str)
        printk(KERN_INFO "AppArmor: %s\n", str);
 }
 
-/**
- * __aa_kvmalloc - do allocation preferring kmalloc but falling back to vmalloc
- * @size: how many bytes of memory are required
- * @flags: the type of memory to allocate (see kmalloc).
- *
- * Return: allocated buffer or NULL if failed
- *
- * It is possible that policy being loaded from the user is larger than
- * what can be allocated by kmalloc, in those cases fall back to vmalloc.
- */
-void *__aa_kvmalloc(size_t size, gfp_t flags)
-{
-       void *buffer = NULL;
-
-       if (size == 0)
-               return NULL;
-
-       /* do not attempt kmalloc if we need more than 16 pages at once */
-       if (size <= (16*PAGE_SIZE))
-               buffer = kmalloc(size, flags | GFP_KERNEL | __GFP_NORETRY |
-                                __GFP_NOWARN);
-       if (!buffer) {
-               if (flags & __GFP_ZERO)
-                       buffer = vzalloc(size);
-               else
-                       buffer = vmalloc(size);
-       }
-       return buffer;
-}
-
 /**
  * aa_policy_init - initialize a policy structure
  * @policy: policy to initialize  (NOT NULL)
index eb0efef746f56ff193e4b507c97c22c486ffbce9..960c913381e2b61780d1cd9640199538286c13b7 100644 (file)
@@ -88,7 +88,7 @@ static struct table_header *unpack_table(char *blob, size_t bsize)
        if (bsize < tsize)
                goto out;
 
-       table = kvzalloc(tsize);
+       table = kvzalloc(tsize, GFP_KERNEL);
        if (table) {
                table->td_id = th.td_id;
                table->td_flags = th.td_flags;
index 2e37c9c26bbd17e0affa3155384979f99953ffa7..f3422a91353c459b3f0a95448aaaff9b6164e1bd 100644 (file)
@@ -487,7 +487,7 @@ fail:
 
 static void *kvmemdup(const void *src, size_t len)
 {
-       void *p = kvmalloc(len);
+       void *p = kvmalloc(len, GFP_KERNEL);
 
        if (p)
                memcpy(p, src, len);
index 2cb14162ff8d5fa2f2ebfdd58061c07f4569f34c..eccd58ef2ae8456af7523414c5405024332e4731 100644 (file)
@@ -28,7 +28,7 @@ static int mount_count;
 
 static int fill_super(struct super_block *sb, void *data, int silent)
 {
-       static struct tree_descr files[] = {{""}};
+       static const struct tree_descr files[] = {{""}};
 
        return simple_fill_super(sb, SECURITYFS_MAGIC, files);
 }
index 82a9e18511089d12d0bf674b63d57f9aa6363ef5..447a7d5cee0f56ebcb1847d9442f6407e259be98 100644 (file)
@@ -101,14 +101,9 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type,
 
        if (_payload) {
                ret = -ENOMEM;
-               payload = kmalloc(plen, GFP_KERNEL | __GFP_NOWARN);
-               if (!payload) {
-                       if (plen <= PAGE_SIZE)
-                               goto error2;
-                       payload = vmalloc(plen);
-                       if (!payload)
-                               goto error2;
-               }
+               payload = kvmalloc(plen, GFP_KERNEL);
+               if (!payload)
+                       goto error2;
 
                ret = -EFAULT;
                if (copy_from_user(payload, _payload, plen) != 0)
@@ -1071,14 +1066,9 @@ long keyctl_instantiate_key_common(key_serial_t id,
 
        if (from) {
                ret = -ENOMEM;
-               payload = kmalloc(plen, GFP_KERNEL);
-               if (!payload) {
-                       if (plen <= PAGE_SIZE)
-                               goto error;
-                       payload = vmalloc(plen);
-                       if (!payload)
-                               goto error;
-               }
+               payload = kvmalloc(plen, GFP_KERNEL);
+               if (!payload)
+                       goto error;
 
                ret = -EFAULT;
                if (!copy_from_iter_full(payload, plen, from))
index ce71718842231309868c16598770c32867b3ee9b..50062e70140dcd2c80f88a0be2d1663b0f0c6d86 100644 (file)
@@ -1496,7 +1496,7 @@ static const struct file_operations sel_avc_cache_stats_ops = {
 static int sel_make_avc_files(struct dentry *dir)
 {
        int i;
-       static struct tree_descr files[] = {
+       static const struct tree_descr files[] = {
                { "cache_threshold",
                  &sel_avc_cache_threshold_ops, S_IRUGO|S_IWUSR },
                { "hash_stats", &sel_avc_hash_stats_ops, S_IRUGO },
@@ -1805,7 +1805,7 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent)
        struct inode *inode;
        struct inode_security_struct *isec;
 
-       static struct tree_descr selinux_files[] = {
+       static const struct tree_descr selinux_files[] = {
                [SEL_LOAD] = {"load", &sel_load_ops, S_IRUSR|S_IWUSR},
                [SEL_ENFORCE] = {"enforce", &sel_enforce_ops, S_IRUGO|S_IWUSR},
                [SEL_CONTEXT] = {"context", &transaction_ops, S_IRUGO|S_IWUGO},
index 366b8356f75b45315c43b6067aa569680c20eea4..f6482e53d55a82d97882d40d04736247281a4239 100644 (file)
@@ -2855,7 +2855,7 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
        int rc;
        struct inode *root_inode;
 
-       static struct tree_descr smack_files[] = {
+       static const struct tree_descr smack_files[] = {
                [SMK_LOAD] = {
                        "load", &smk_load_ops, S_IRUGO|S_IWUSR},
                [SMK_CIPSO] = {
index ee2e69a9ecd14ecd9fef1107c7a803f0b1a836de..6a215a8c0490dda16f094aa061bc9b9b1791a609 100644 (file)
@@ -115,6 +115,7 @@ endif # SND
 menuconfig SOUND_PRIME
        tristate "Open Sound System (DEPRECATED)"
        select SOUND_OSS_CORE
+       depends on BROKEN
        help
          Say 'Y' or 'M' to enable Open Sound System drivers.
 
index fed7e7e2177b7c0dbfc09c0fb20d8c15ad958b07..9b86e00d7d95ffada3ac89b52671be20a2d30d38 100644 (file)
@@ -53,9 +53,9 @@ MODULE_PARM_DESC(enable, "Enable MPU-401 device.");
 module_param_array(pnp, bool, NULL, 0444);
 MODULE_PARM_DESC(pnp, "PnP detection for MPU-401 device.");
 #endif
-module_param_array(port, long, NULL, 0444);
+module_param_hw_array(port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(port, "Port # for MPU-401 device.");
-module_param_array(irq, int, NULL, 0444);
+module_param_hw_array(irq, int, irq, NULL, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for MPU-401 device.");
 module_param_array(uart_enter, bool, NULL, 0444);
 MODULE_PARM_DESC(uart_enter, "Issue UART_ENTER command at open.");
index 00b31f92c504ddf7c7a9810b38d6b411a66a22a3..0f6392001e307ca008957d0760b76e1083d779ce 100644 (file)
@@ -86,9 +86,9 @@ module_param(index, int, 0444);
 MODULE_PARM_DESC(index, "Index value for MotuMTPAV MIDI.");
 module_param(id, charp, 0444);
 MODULE_PARM_DESC(id, "ID string for MotuMTPAV MIDI.");
-module_param(port, long, 0444);
+module_param_hw(port, long, ioport, 0444);
 MODULE_PARM_DESC(port, "Parallel port # for MotuMTPAV MIDI.");
-module_param(irq, int, 0444);
+module_param_hw(irq, int, irq, 0444);
 MODULE_PARM_DESC(irq, "Parallel IRQ # for MotuMTPAV MIDI.");
 module_param(hwports, int, 0444);
 MODULE_PARM_DESC(hwports, "Hardware ports # for MotuMTPAV MIDI.");
index 60d51ac4ccfebded6c55e47812fdd16c67ae4359..88e66ea0306dd820b82e6339c4e2640ffce426cc 100644 (file)
@@ -84,9 +84,9 @@ module_param_array(id, charp, NULL, 0444);
 MODULE_PARM_DESC(id, "ID string for Serial MIDI.");
 module_param_array(enable, bool, NULL, 0444);
 MODULE_PARM_DESC(enable, "Enable UART16550A chip.");
-module_param_array(port, long, NULL, 0444);
+module_param_hw_array(port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(port, "Port # for UART16550A chip.");
-module_param_array(irq, int, NULL, 0444);
+module_param_hw_array(irq, int, irq, NULL, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for UART16550A chip.");
 module_param_array(speed, int, NULL, 0444);
 MODULE_PARM_DESC(speed, "Speed in bauds.");
index ee08c389b4d68900c0065b346aeddb75a6e5eabc..978dc1801b3aceb8e2245b819097954c76595d77 100644 (file)
@@ -106,7 +106,11 @@ void snd_hdac_bus_stop_cmd_io(struct hdac_bus *bus)
        /* disable ringbuffer DMAs */
        snd_hdac_chip_writeb(bus, RIRBCTL, 0);
        snd_hdac_chip_writeb(bus, CORBCTL, 0);
+       spin_unlock_irq(&bus->reg_lock);
+
        hdac_wait_for_cmd_dmas(bus);
+
+       spin_lock_irq(&bus->reg_lock);
        /* disable unsolicited responses */
        snd_hdac_chip_updatel(bus, GCTL, AZX_GCTL_UNSOL, 0);
        spin_unlock_irq(&bus->reg_lock);
index a302d1f8d14f410dca12d4433b6b66cef7add47f..e739b1c85c25b98c43127d1afc6270195974296b 100644 (file)
@@ -55,11 +55,11 @@ module_param_array(id, charp, NULL, 0444);
 MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard.");
 module_param_array(enable, bool, NULL, 0444);
 MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
-module_param_array(port, long, NULL, 0444);
+module_param_hw_array(port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
-module_param_array(irq, int, NULL, 0444);
+module_param_hw_array(irq, int, irq, NULL, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver.");
-module_param_array(dma1, int, NULL, 0444);
+module_param_hw_array(dma1, int, dma, NULL, 0444);
 MODULE_PARM_DESC(dma1, "DMA1 # for " CRD_NAME " driver.");
 module_param_array(thinkpad, bool, NULL, 0444);
 MODULE_PARM_DESC(thinkpad, "Enable only for the onboard CS4248 of IBM Thinkpad 360/750/755 series.");
index 8d3060fd7ad7e3319553c4cf604d29dc7d73bd45..5fb619eca5c8decd5c3e94e7040de166e002fcae 100644 (file)
@@ -27,7 +27,7 @@ module_param_array(id, charp, NULL, 0444);
 MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard.");
 module_param_array(enable, bool, NULL, 0444);
 MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
-module_param_array(port, long, NULL, 0444);
+module_param_hw_array(port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
 
 static int snd_adlib_match(struct device *dev, unsigned int n)
index 787475084f4662cfd9fd03b5165d47c2f48477ea..8e1756c3b9bb9a5729bab4cf0f35f8e75c85d01a 100644 (file)
@@ -51,18 +51,18 @@ MODULE_PARM_DESC(index, "Index value for CMI8328 soundcard.");
 module_param_array(id, charp, NULL, 0444);
 MODULE_PARM_DESC(id, "ID string for CMI8328 soundcard.");
 
-module_param_array(port, long, NULL, 0444);
+module_param_hw_array(port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(port, "Port # for CMI8328 driver.");
-module_param_array(irq, int, NULL, 0444);
+module_param_hw_array(irq, int, irq, NULL, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for CMI8328 driver.");
-module_param_array(dma1, int, NULL, 0444);
+module_param_hw_array(dma1, int, dma, NULL, 0444);
 MODULE_PARM_DESC(dma1, "DMA1 for CMI8328 driver.");
-module_param_array(dma2, int, NULL, 0444);
+module_param_hw_array(dma2, int, dma, NULL, 0444);
 MODULE_PARM_DESC(dma2, "DMA2 for CMI8328 driver.");
 
-module_param_array(mpuport, long, NULL, 0444);
+module_param_hw_array(mpuport, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(mpuport, "MPU-401 port # for CMI8328 driver.");
-module_param_array(mpuirq, int, NULL, 0444);
+module_param_hw_array(mpuirq, int, irq, NULL, 0444);
 MODULE_PARM_DESC(mpuirq, "IRQ # for CMI8328 MPU-401 port.");
 #ifdef SUPPORT_JOYSTICK
 module_param_array(gameport, bool, NULL, 0444);
index dfedfd85f205460095ad09b1f0086c8f25925ea9..f64b29ab5cc7005eb4ea35bd76133e8a0a0d6d24 100644 (file)
@@ -95,27 +95,27 @@ module_param_array(isapnp, bool, NULL, 0444);
 MODULE_PARM_DESC(isapnp, "PnP detection for specified soundcard.");
 #endif
 
-module_param_array(sbport, long, NULL, 0444);
+module_param_hw_array(sbport, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(sbport, "Port # for CMI8330/CMI8329 SB driver.");
-module_param_array(sbirq, int, NULL, 0444);
+module_param_hw_array(sbirq, int, irq, NULL, 0444);
 MODULE_PARM_DESC(sbirq, "IRQ # for CMI8330/CMI8329 SB driver.");
-module_param_array(sbdma8, int, NULL, 0444);
+module_param_hw_array(sbdma8, int, dma, NULL, 0444);
 MODULE_PARM_DESC(sbdma8, "DMA8 for CMI8330/CMI8329 SB driver.");
-module_param_array(sbdma16, int, NULL, 0444);
+module_param_hw_array(sbdma16, int, dma, NULL, 0444);
 MODULE_PARM_DESC(sbdma16, "DMA16 for CMI8330/CMI8329 SB driver.");
 
-module_param_array(wssport, long, NULL, 0444);
+module_param_hw_array(wssport, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(wssport, "Port # for CMI8330/CMI8329 WSS driver.");
-module_param_array(wssirq, int, NULL, 0444);
+module_param_hw_array(wssirq, int, irq, NULL, 0444);
 MODULE_PARM_DESC(wssirq, "IRQ # for CMI8330/CMI8329 WSS driver.");
-module_param_array(wssdma, int, NULL, 0444);
+module_param_hw_array(wssdma, int, dma, NULL, 0444);
 MODULE_PARM_DESC(wssdma, "DMA for CMI8330/CMI8329 WSS driver.");
 
-module_param_array(fmport, long, NULL, 0444);
+module_param_hw_array(fmport, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(fmport, "FM port # for CMI8330/CMI8329 driver.");
-module_param_array(mpuport, long, NULL, 0444);
+module_param_hw_array(mpuport, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(mpuport, "MPU-401 port # for CMI8330/CMI8329 driver.");
-module_param_array(mpuirq, int, NULL, 0444);
+module_param_hw_array(mpuirq, int, irq, NULL, 0444);
 MODULE_PARM_DESC(mpuirq, "IRQ # for CMI8330/CMI8329 MPU-401 port.");
 #ifdef CONFIG_PNP
 static int isa_registered;
index ef7448e9f81300e40bf39ee760cbcad55b92600b..e8edd9017a2f22205b64a19b2adb68fe3f27beca 100644 (file)
@@ -55,17 +55,17 @@ module_param_array(id, charp, NULL, 0444);
 MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard.");
 module_param_array(enable, bool, NULL, 0444);
 MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
-module_param_array(port, long, NULL, 0444);
+module_param_hw_array(port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
-module_param_array(mpu_port, long, NULL, 0444);
+module_param_hw_array(mpu_port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " CRD_NAME " driver.");
-module_param_array(irq, int, NULL, 0444);
+module_param_hw_array(irq, int, irq, NULL, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver.");
-module_param_array(mpu_irq, int, NULL, 0444);
+module_param_hw_array(mpu_irq, int, irq, NULL, 0444);
 MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver.");
-module_param_array(dma1, int, NULL, 0444);
+module_param_hw_array(dma1, int, dma, NULL, 0444);
 MODULE_PARM_DESC(dma1, "DMA1 # for " CRD_NAME " driver.");
-module_param_array(dma2, int, NULL, 0444);
+module_param_hw_array(dma2, int, dma, NULL, 0444);
 MODULE_PARM_DESC(dma2, "DMA2 # for " CRD_NAME " driver.");
 
 static int snd_cs4231_match(struct device *dev, unsigned int n)
index 9d7582c90a95d90a66290c6e386aa4749b8ff056..1f9a3b2be7a1f705e40e15e8358a46b93e50a0f9 100644 (file)
@@ -98,23 +98,23 @@ MODULE_PARM_DESC(enable, "Enable " IDENT " soundcard.");
 module_param_array(isapnp, bool, NULL, 0444);
 MODULE_PARM_DESC(isapnp, "ISA PnP detection for specified soundcard.");
 #endif
-module_param_array(port, long, NULL, 0444);
+module_param_hw_array(port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(port, "Port # for " IDENT " driver.");
-module_param_array(cport, long, NULL, 0444);
+module_param_hw_array(cport, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(cport, "Control port # for " IDENT " driver.");
-module_param_array(mpu_port, long, NULL, 0444);
+module_param_hw_array(mpu_port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " IDENT " driver.");
-module_param_array(fm_port, long, NULL, 0444);
+module_param_hw_array(fm_port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(fm_port, "FM port # for " IDENT " driver.");
-module_param_array(sb_port, long, NULL, 0444);
+module_param_hw_array(sb_port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(sb_port, "SB port # for " IDENT " driver (optional).");
-module_param_array(irq, int, NULL, 0444);
+module_param_hw_array(irq, int, irq, NULL, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for " IDENT " driver.");
-module_param_array(mpu_irq, int, NULL, 0444);
+module_param_hw_array(mpu_irq, int, irq, NULL, 0444);
 MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " IDENT " driver.");
-module_param_array(dma1, int, NULL, 0444);
+module_param_hw_array(dma1, int, dma, NULL, 0444);
 MODULE_PARM_DESC(dma1, "DMA1 # for " IDENT " driver.");
-module_param_array(dma2, int, NULL, 0444);
+module_param_hw_array(dma2, int, dma, NULL, 0444);
 MODULE_PARM_DESC(dma2, "DMA2 # for " IDENT " driver.");
 
 #ifdef CONFIG_PNP
index 1901c2bb6c3bca0cb0ace9a95617f5137a6fa07a..36320e7f278931719d7b8f8adcb935967ce2ecab 100644 (file)
@@ -71,17 +71,17 @@ module_param_array(isapnp, bool, NULL, 0444);
 MODULE_PARM_DESC(isapnp, "PnP detection for specified soundcard.");
 #endif
 MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
-module_param_array(port, long, NULL, 0444);
+module_param_hw_array(port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
-module_param_array(mpu_port, long, NULL, 0444);
+module_param_hw_array(mpu_port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " CRD_NAME " driver.");
-module_param_array(irq, int, NULL, 0444);
-module_param_array(fm_port, long, NULL, 0444);
+module_param_hw_array(irq, int, irq, NULL, 0444);
+module_param_hw_array(fm_port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(fm_port, "FM port # for ES1688 driver.");
 MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver.");
-module_param_array(mpu_irq, int, NULL, 0444);
+module_param_hw_array(mpu_irq, int, irq, NULL, 0444);
 MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver.");
-module_param_array(dma8, int, NULL, 0444);
+module_param_hw_array(dma8, int, dma, NULL, 0444);
 MODULE_PARM_DESC(dma8, "8-bit DMA # for " CRD_NAME " driver.");
 
 #ifdef CONFIG_PNP
index 5094b62d8f7718c0888306b5fe4eeca60326c1e2..0cabe2b8974f574e0d4e42be908eaf58f462cb69 100644 (file)
@@ -1999,17 +1999,17 @@ MODULE_PARM_DESC(enable, "Enable ES18xx soundcard.");
 module_param_array(isapnp, bool, NULL, 0444);
 MODULE_PARM_DESC(isapnp, "PnP detection for specified soundcard.");
 #endif
-module_param_array(port, long, NULL, 0444);
+module_param_hw_array(port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(port, "Port # for ES18xx driver.");
-module_param_array(mpu_port, long, NULL, 0444);
+module_param_hw_array(mpu_port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for ES18xx driver.");
-module_param_array(fm_port, long, NULL, 0444);
+module_param_hw_array(fm_port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(fm_port, "FM port # for ES18xx driver.");
-module_param_array(irq, int, NULL, 0444);
+module_param_hw_array(irq, int, irq, NULL, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for ES18xx driver.");
-module_param_array(dma1, int, NULL, 0444);
+module_param_hw_array(dma1, int, dma, NULL, 0444);
 MODULE_PARM_DESC(dma1, "DMA 1 # for ES18xx driver.");
-module_param_array(dma2, int, NULL, 0444);
+module_param_hw_array(dma2, int, dma, NULL, 0444);
 MODULE_PARM_DESC(dma2, "DMA 2 # for ES18xx driver.");
 
 #ifdef CONFIG_PNP
index 379abe2cbeb2317345c14c6fdca684129e35e5c7..b9994cc9f5fb4f86c3644671545c56625adb926e 100644 (file)
@@ -53,21 +53,21 @@ static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
 static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
 static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
 
-module_param_array(port, long, NULL, 0444);
+module_param_hw_array(port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
-module_param_array(wss_port, long, NULL, 0444);
+module_param_hw_array(wss_port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(wss_port, "WSS port # for " CRD_NAME " driver.");
-module_param_array(mpu_port, long, NULL, 0444);
+module_param_hw_array(mpu_port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " CRD_NAME " driver.");
-module_param_array(fm_port, long, NULL, 0444);
+module_param_hw_array(fm_port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(fm_port, "FM port # for " CRD_NAME " driver.");
-module_param_array(irq, int, NULL, 0444);
+module_param_hw_array(irq, int, irq, NULL, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver.");
-module_param_array(mpu_irq, int, NULL, 0444);
+module_param_hw_array(mpu_irq, int, irq, NULL, 0444);
 MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver.");
-module_param_array(dma1, int, NULL, 0444);
+module_param_hw_array(dma1, int, dma, NULL, 0444);
 MODULE_PARM_DESC(dma1, "Playback DMA # for " CRD_NAME " driver.");
-module_param_array(dma2, int, NULL, 0444);
+module_param_hw_array(dma2, int, dma, NULL, 0444);
 MODULE_PARM_DESC(dma2, "Capture DMA # for " CRD_NAME " driver.");
 
 /*
index c169be49ed713f302e1b35d8541e431727a89f00..92a997ab1229184a5d01441ecadf1e91c7debbca 100644 (file)
@@ -58,13 +58,13 @@ module_param_array(id, charp, NULL, 0444);
 MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard.");
 module_param_array(enable, bool, NULL, 0444);
 MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
-module_param_array(port, long, NULL, 0444);
+module_param_hw_array(port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
-module_param_array(irq, int, NULL, 0444);
+module_param_hw_array(irq, int, irq, NULL, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver.");
-module_param_array(dma1, int, NULL, 0444);
+module_param_hw_array(dma1, int, dma, NULL, 0444);
 MODULE_PARM_DESC(dma1, "DMA1 # for " CRD_NAME " driver.");
-module_param_array(dma2, int, NULL, 0444);
+module_param_hw_array(dma2, int, dma, NULL, 0444);
 MODULE_PARM_DESC(dma2, "DMA2 # for " CRD_NAME " driver.");
 module_param_array(joystick_dac, int, NULL, 0444);
 MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for " CRD_NAME " driver.");
index 77ac2fd723b4a413c4f597d630ace5e80b2979d5..beb52c0f70ea09eb83050b94548cbad734fa7cf4 100644 (file)
@@ -66,21 +66,21 @@ module_param_array(id, charp, NULL, 0444);
 MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard.");
 module_param_array(enable, bool, NULL, 0444);
 MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
-module_param_array(port, long, NULL, 0444);
+module_param_hw_array(port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
-module_param_array(gf1_port, long, NULL, 0444);
+module_param_hw_array(gf1_port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(gf1_port, "GF1 port # for " CRD_NAME " driver (optional).");
-module_param_array(mpu_port, long, NULL, 0444);
+module_param_hw_array(mpu_port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " CRD_NAME " driver.");
-module_param_array(irq, int, NULL, 0444);
+module_param_hw_array(irq, int, irq, NULL, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver.");
-module_param_array(mpu_irq, int, NULL, 0444);
+module_param_hw_array(mpu_irq, int, irq, NULL, 0444);
 MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver.");
-module_param_array(gf1_irq, int, NULL, 0444);
+module_param_hw_array(gf1_irq, int, irq, NULL, 0444);
 MODULE_PARM_DESC(gf1_irq, "GF1 IRQ # for " CRD_NAME " driver.");
-module_param_array(dma8, int, NULL, 0444);
+module_param_hw_array(dma8, int, dma, NULL, 0444);
 MODULE_PARM_DESC(dma8, "8-bit DMA # for " CRD_NAME " driver.");
-module_param_array(dma1, int, NULL, 0444);
+module_param_hw_array(dma1, int, dma, NULL, 0444);
 MODULE_PARM_DESC(dma1, "GF1 DMA # for " CRD_NAME " driver.");
 module_param_array(joystick_dac, int, NULL, 0444);
 MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for " CRD_NAME " driver.");
index dd88c9d33492bba72365f9785319ee665e5d92cc..63309a4531402bf2ce82dcb7a5dff970cdcae0bc 100644 (file)
@@ -56,13 +56,13 @@ module_param_array(id, charp, NULL, 0444);
 MODULE_PARM_DESC(id, "ID string for GUS MAX soundcard.");
 module_param_array(enable, bool, NULL, 0444);
 MODULE_PARM_DESC(enable, "Enable GUS MAX soundcard.");
-module_param_array(port, long, NULL, 0444);
+module_param_hw_array(port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(port, "Port # for GUS MAX driver.");
-module_param_array(irq, int, NULL, 0444);
+module_param_hw_array(irq, int, irq, NULL, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for GUS MAX driver.");
-module_param_array(dma1, int, NULL, 0444);
+module_param_hw_array(dma1, int, dma, NULL, 0444);
 MODULE_PARM_DESC(dma1, "DMA1 # for GUS MAX driver.");
-module_param_array(dma2, int, NULL, 0444);
+module_param_hw_array(dma2, int, dma, NULL, 0444);
 MODULE_PARM_DESC(dma2, "DMA2 # for GUS MAX driver.");
 module_param_array(joystick_dac, int, NULL, 0444);
 MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for GUS MAX driver.");
index 70d0040484c89c7e2bd0d15303a917c71154b729..0687b7ef3e53b5f6a6b45d7aa3ed2b7654ce735b 100644 (file)
@@ -92,17 +92,17 @@ MODULE_PARM_DESC(enable, "Enable InterWave soundcard.");
 module_param_array(isapnp, bool, NULL, 0444);
 MODULE_PARM_DESC(isapnp, "ISA PnP detection for specified soundcard.");
 #endif
-module_param_array(port, long, NULL, 0444);
+module_param_hw_array(port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(port, "Port # for InterWave driver.");
 #ifdef SNDRV_STB
-module_param_array(port_tc, long, NULL, 0444);
+module_param_hw_array(port_tc, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(port_tc, "Tone control (TEA6330T - i2c bus) port # for InterWave driver.");
 #endif
-module_param_array(irq, int, NULL, 0444);
+module_param_hw_array(irq, int, irq, NULL, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for InterWave driver.");
-module_param_array(dma1, int, NULL, 0444);
+module_param_hw_array(dma1, int, dma, NULL, 0444);
 MODULE_PARM_DESC(dma1, "DMA1 # for InterWave driver.");
-module_param_array(dma2, int, NULL, 0444);
+module_param_hw_array(dma2, int, dma, NULL, 0444);
 MODULE_PARM_DESC(dma2, "DMA2 # for InterWave driver.");
 module_param_array(joystick_dac, int, NULL, 0444);
 MODULE_PARM_DESC(joystick_dac, "Joystick DAC level 0.59V-4.52V or 0.389V-2.98V for InterWave driver.");
index 4c072666115dbd1d2559974fb5701592e7b8ba2a..ad4897337df57ea71c2d08ac7c3fa82dd29be5fc 100644 (file)
@@ -800,22 +800,22 @@ MODULE_LICENSE("GPL");
 MODULE_FIRMWARE(INITCODEFILE);
 MODULE_FIRMWARE(PERMCODEFILE);
 
-module_param_array(io, long, NULL, S_IRUGO);
+module_param_hw_array(io, long, ioport, NULL, S_IRUGO);
 MODULE_PARM_DESC(io, "IO port #");
-module_param_array(irq, int, NULL, S_IRUGO);
-module_param_array(mem, long, NULL, S_IRUGO);
+module_param_hw_array(irq, int, irq, NULL, S_IRUGO);
+module_param_hw_array(mem, long, iomem, NULL, S_IRUGO);
 module_param_array(write_ndelay, int, NULL, S_IRUGO);
 module_param(calibrate_signal, int, S_IRUGO);
 #ifndef MSND_CLASSIC
 module_param_array(digital, int, NULL, S_IRUGO);
-module_param_array(cfg, long, NULL, S_IRUGO);
+module_param_hw_array(cfg, long, ioport, NULL, S_IRUGO);
 module_param_array(reset, int, 0, S_IRUGO);
-module_param_array(mpu_io, long, NULL, S_IRUGO);
-module_param_array(mpu_irq, int, NULL, S_IRUGO);
-module_param_array(ide_io0, long, NULL, S_IRUGO);
-module_param_array(ide_io1, long, NULL, S_IRUGO);
-module_param_array(ide_irq, int, NULL, S_IRUGO);
-module_param_array(joystick_io, long, NULL, S_IRUGO);
+module_param_hw_array(mpu_io, long, ioport, NULL, S_IRUGO);
+module_param_hw_array(mpu_irq, int, irq, NULL, S_IRUGO);
+module_param_hw_array(ide_io0, long, ioport, NULL, S_IRUGO);
+module_param_hw_array(ide_io1, long, ioport, NULL, S_IRUGO);
+module_param_hw_array(ide_irq, int, irq, NULL, S_IRUGO);
+module_param_hw_array(joystick_io, long, ioport, NULL, S_IRUGO);
 #endif
 
 
index ae133633a420c4886181326f933161820de85696..4098e3e0353d8f6d7e57428d70d491301585ac3e 100644 (file)
@@ -69,21 +69,21 @@ MODULE_PARM_DESC(enable, "Enable OPL3-SA soundcard.");
 module_param_array(isapnp, bool, NULL, 0444);
 MODULE_PARM_DESC(isapnp, "PnP detection for specified soundcard.");
 #endif
-module_param_array(port, long, NULL, 0444);
+module_param_hw_array(port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(port, "Port # for OPL3-SA driver.");
-module_param_array(sb_port, long, NULL, 0444);
+module_param_hw_array(sb_port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(sb_port, "SB port # for OPL3-SA driver.");
-module_param_array(wss_port, long, NULL, 0444);
+module_param_hw_array(wss_port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(wss_port, "WSS port # for OPL3-SA driver.");
-module_param_array(fm_port, long, NULL, 0444);
+module_param_hw_array(fm_port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(fm_port, "FM port # for OPL3-SA driver.");
-module_param_array(midi_port, long, NULL, 0444);
+module_param_hw_array(midi_port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(midi_port, "MIDI port # for OPL3-SA driver.");
-module_param_array(irq, int, NULL, 0444);
+module_param_hw_array(irq, int, irq, NULL, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for OPL3-SA driver.");
-module_param_array(dma1, int, NULL, 0444);
+module_param_hw_array(dma1, int, dma, NULL, 0444);
 MODULE_PARM_DESC(dma1, "DMA1 # for OPL3-SA driver.");
-module_param_array(dma2, int, NULL, 0444);
+module_param_hw_array(dma2, int, dma, NULL, 0444);
 MODULE_PARM_DESC(dma2, "DMA2 # for OPL3-SA driver.");
 module_param_array(opl3sa3_ymode, int, NULL, 0444);
 MODULE_PARM_DESC(opl3sa3_ymode, "Speaker size selection for 3D Enhancement mode: Desktop/Large Notebook/Small Notebook/HiFi.");
index 3a9067db1a842605518c70eabf84f5691413db00..bcbff56f060d04e3e55b0400b0c4be79f119b0cb 100644 (file)
@@ -69,19 +69,19 @@ module_param(index, int, 0444);
 MODULE_PARM_DESC(index, "Index value for miro soundcard.");
 module_param(id, charp, 0444);
 MODULE_PARM_DESC(id, "ID string for miro soundcard.");
-module_param(port, long, 0444);
+module_param_hw(port, long, ioport, 0444);
 MODULE_PARM_DESC(port, "WSS port # for miro driver.");
-module_param(mpu_port, long, 0444);
+module_param_hw(mpu_port, long, ioport, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for miro driver.");
-module_param(fm_port, long, 0444);
+module_param_hw(fm_port, long, ioport, 0444);
 MODULE_PARM_DESC(fm_port, "FM Port # for miro driver.");
-module_param(irq, int, 0444);
+module_param_hw(irq, int, irq, 0444);
 MODULE_PARM_DESC(irq, "WSS irq # for miro driver.");
-module_param(mpu_irq, int, 0444);
+module_param_hw(mpu_irq, int, irq, 0444);
 MODULE_PARM_DESC(mpu_irq, "MPU-401 irq # for miro driver.");
-module_param(dma1, int, 0444);
+module_param_hw(dma1, int, dma, 0444);
 MODULE_PARM_DESC(dma1, "1st dma # for miro driver.");
-module_param(dma2, int, 0444);
+module_param_hw(dma2, int, dma, 0444);
 MODULE_PARM_DESC(dma2, "2nd dma # for miro driver.");
 module_param(wss, int, 0444);
 MODULE_PARM_DESC(wss, "wss mode");
index 0a52660037866b75480f125d04d6ef9a96413bf6..ceddb392b1e336b1bb7db83d9c8823ec1d4571a9 100644 (file)
@@ -88,20 +88,20 @@ MODULE_PARM_DESC(id, "ID string for opti9xx based soundcard.");
 module_param(isapnp, bool, 0444);
 MODULE_PARM_DESC(isapnp, "Enable ISA PnP detection for specified soundcard.");
 #endif
-module_param(port, long, 0444);
+module_param_hw(port, long, ioport, 0444);
 MODULE_PARM_DESC(port, "WSS port # for opti9xx driver.");
-module_param(mpu_port, long, 0444);
+module_param_hw(mpu_port, long, ioport, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for opti9xx driver.");
-module_param(fm_port, long, 0444);
+module_param_hw(fm_port, long, ioport, 0444);
 MODULE_PARM_DESC(fm_port, "FM port # for opti9xx driver.");
-module_param(irq, int, 0444);
+module_param_hw(irq, int, irq, 0444);
 MODULE_PARM_DESC(irq, "WSS irq # for opti9xx driver.");
-module_param(mpu_irq, int, 0444);
+module_param_hw(mpu_irq, int, irq, 0444);
 MODULE_PARM_DESC(mpu_irq, "MPU-401 irq # for opti9xx driver.");
-module_param(dma1, int, 0444);
+module_param_hw(dma1, int, dma, 0444);
 MODULE_PARM_DESC(dma1, "1st dma # for opti9xx driver.");
 #if defined(CS4231) || defined(OPTi93X)
-module_param(dma2, int, 0444);
+module_param_hw(dma2, int, dma, 0444);
 MODULE_PARM_DESC(dma2, "2nd dma # for opti9xx driver.");
 #endif /* CS4231 || OPTi93X */
 
index 4d909971eedbb5b8ee458ec46d08162b2302bb44..bfa0055e1fd6677dc2395f8b45918454ee6b2619 100644 (file)
@@ -50,17 +50,17 @@ module_param_array(id, charp, NULL, 0444);
 MODULE_PARM_DESC(id, "ID string for Media Vision Jazz16 based soundcard.");
 module_param_array(enable, bool, NULL, 0444);
 MODULE_PARM_DESC(enable, "Enable Media Vision Jazz16 based soundcard.");
-module_param_array(port, long, NULL, 0444);
+module_param_hw_array(port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(port, "Port # for jazz16 driver.");
-module_param_array(mpu_port, long, NULL, 0444);
+module_param_hw_array(mpu_port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for jazz16 driver.");
-module_param_array(irq, int, NULL, 0444);
+module_param_hw_array(irq, int, irq, NULL, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for jazz16 driver.");
-module_param_array(mpu_irq, int, NULL, 0444);
+module_param_hw_array(mpu_irq, int, irq, NULL, 0444);
 MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for jazz16 driver.");
-module_param_array(dma8, int, NULL, 0444);
+module_param_hw_array(dma8, int, dma, NULL, 0444);
 MODULE_PARM_DESC(dma8, "DMA8 # for jazz16 driver.");
-module_param_array(dma16, int, NULL, 0444);
+module_param_hw_array(dma16, int, dma, NULL, 0444);
 MODULE_PARM_DESC(dma16, "DMA16 # for jazz16 driver.");
 
 #define SB_JAZZ16_WAKEUP       0xaf
index 4a7d7c89808fd0fbc574a0e3b66b4b31ea7c11e2..3b2e4f405ff27bdb60f622907bcdf594e7a59e2f 100644 (file)
@@ -99,21 +99,21 @@ MODULE_PARM_DESC(enable, "Enable SoundBlaster 16 soundcard.");
 module_param_array(isapnp, bool, NULL, 0444);
 MODULE_PARM_DESC(isapnp, "PnP detection for specified soundcard.");
 #endif
-module_param_array(port, long, NULL, 0444);
+module_param_hw_array(port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(port, "Port # for SB16 driver.");
-module_param_array(mpu_port, long, NULL, 0444);
+module_param_hw_array(mpu_port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for SB16 driver.");
-module_param_array(fm_port, long, NULL, 0444);
+module_param_hw_array(fm_port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(fm_port, "FM port # for SB16 PnP driver.");
 #ifdef SNDRV_SBAWE_EMU8000
-module_param_array(awe_port, long, NULL, 0444);
+module_param_hw_array(awe_port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(awe_port, "AWE port # for SB16 PnP driver.");
 #endif
-module_param_array(irq, int, NULL, 0444);
+module_param_hw_array(irq, int, irq, NULL, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for SB16 driver.");
-module_param_array(dma8, int, NULL, 0444);
+module_param_hw_array(dma8, int, dma, NULL, 0444);
 MODULE_PARM_DESC(dma8, "8-bit DMA # for SB16 driver.");
-module_param_array(dma16, int, NULL, 0444);
+module_param_hw_array(dma16, int, dma, NULL, 0444);
 MODULE_PARM_DESC(dma16, "16-bit DMA # for SB16 driver.");
 module_param_array(mic_agc, int, NULL, 0444);
 MODULE_PARM_DESC(mic_agc, "Mic Auto-Gain-Control switch.");
index ad42d2364199fd6a7200000b4f992ad9043c7f30..d77dcba276b544b750c452b622981c6c7a0ff585 100644 (file)
@@ -47,11 +47,11 @@ module_param_array(id, charp, NULL, 0444);
 MODULE_PARM_DESC(id, "ID string for Sound Blaster soundcard.");
 module_param_array(enable, bool, NULL, 0444);
 MODULE_PARM_DESC(enable, "Enable Sound Blaster soundcard.");
-module_param_array(port, long, NULL, 0444);
+module_param_hw_array(port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(port, "Port # for SB8 driver.");
-module_param_array(irq, int, NULL, 0444);
+module_param_hw_array(irq, int, irq, NULL, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for SB8 driver.");
-module_param_array(dma8, int, NULL, 0444);
+module_param_hw_array(dma8, int, dma, NULL, 0444);
 MODULE_PARM_DESC(dma8, "8-bit DMA # for SB8 driver.");
 
 struct snd_sb8 {
index b61a6633d8f2866ff9b3f586afad912abaccbb57..c09d9b914efe0dad0f4f82ff477910258e427b3e 100644 (file)
@@ -64,17 +64,17 @@ module_param_array(id, charp, NULL, 0444);
 MODULE_PARM_DESC(id, "ID string for sc-6000 based soundcard.");
 module_param_array(enable, bool, NULL, 0444);
 MODULE_PARM_DESC(enable, "Enable sc-6000 based soundcard.");
-module_param_array(port, long, NULL, 0444);
+module_param_hw_array(port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(port, "Port # for sc-6000 driver.");
-module_param_array(mss_port, long, NULL, 0444);
+module_param_hw_array(mss_port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(mss_port, "MSS Port # for sc-6000 driver.");
-module_param_array(mpu_port, long, NULL, 0444);
+module_param_hw_array(mpu_port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for sc-6000 driver.");
-module_param_array(irq, int, NULL, 0444);
+module_param_hw_array(irq, int, irq, NULL, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for sc-6000 driver.");
-module_param_array(mpu_irq, int, NULL, 0444);
+module_param_hw_array(mpu_irq, int, irq, NULL, 0444);
 MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for sc-6000 driver.");
-module_param_array(dma, int, NULL, 0444);
+module_param_hw_array(dma, int, dma, NULL, 0444);
 MODULE_PARM_DESC(dma, "DMA # for sc-6000 driver.");
 module_param_array(joystick, bool, NULL, 0444);
 MODULE_PARM_DESC(joystick, "Enable gameport.");
index fdcfa29e220551b473534938d8995c7abf7ebe84..54f5758a1bb3aaa41b463cd4b03d55dde2e84a7d 100644 (file)
@@ -63,22 +63,22 @@ MODULE_PARM_DESC(index, "Index number for SoundScape soundcard");
 module_param_array(id, charp, NULL, 0444);
 MODULE_PARM_DESC(id, "Description for SoundScape card");
 
-module_param_array(port, long, NULL, 0444);
+module_param_hw_array(port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(port, "Port # for SoundScape driver.");
 
-module_param_array(wss_port, long, NULL, 0444);
+module_param_hw_array(wss_port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(wss_port, "WSS Port # for SoundScape driver.");
 
-module_param_array(irq, int, NULL, 0444);
+module_param_hw_array(irq, int, irq, NULL, 0444);
 MODULE_PARM_DESC(irq, "IRQ # for SoundScape driver.");
 
-module_param_array(mpu_irq, int, NULL, 0444);
+module_param_hw_array(mpu_irq, int, irq, NULL, 0444);
 MODULE_PARM_DESC(mpu_irq, "MPU401 IRQ # for SoundScape driver.");
 
-module_param_array(dma, int, NULL, 0444);
+module_param_hw_array(dma, int, dma, NULL, 0444);
 MODULE_PARM_DESC(dma, "DMA # for SoundScape driver.");
 
-module_param_array(dma2, int, NULL, 0444);
+module_param_hw_array(dma2, int, dma, NULL, 0444);
 MODULE_PARM_DESC(dma2, "DMA2 # for SoundScape driver.");
 
 module_param_array(joystick, bool, NULL, 0444);
index a0987a57c8a918e6eff7fd94a871da35db0a3839..da4e9a85f0afe98402f8d12494d197d8660344ea 100644 (file)
@@ -63,23 +63,23 @@ MODULE_PARM_DESC(enable, "Enable WaveFront soundcard.");
 module_param_array(isapnp, bool, NULL, 0444);
 MODULE_PARM_DESC(isapnp, "ISA PnP detection for WaveFront soundcards.");
 #endif
-module_param_array(cs4232_pcm_port, long, NULL, 0444);
+module_param_hw_array(cs4232_pcm_port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(cs4232_pcm_port, "Port # for CS4232 PCM interface.");
-module_param_array(cs4232_pcm_irq, int, NULL, 0444);
+module_param_hw_array(cs4232_pcm_irq, int, irq, NULL, 0444);
 MODULE_PARM_DESC(cs4232_pcm_irq, "IRQ # for CS4232 PCM interface.");
-module_param_array(dma1, int, NULL, 0444);
+module_param_hw_array(dma1, int, dma, NULL, 0444);
 MODULE_PARM_DESC(dma1, "DMA1 # for CS4232 PCM interface.");
-module_param_array(dma2, int, NULL, 0444);
+module_param_hw_array(dma2, int, dma, NULL, 0444);
 MODULE_PARM_DESC(dma2, "DMA2 # for CS4232 PCM interface.");
-module_param_array(cs4232_mpu_port, long, NULL, 0444);
+module_param_hw_array(cs4232_mpu_port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(cs4232_mpu_port, "port # for CS4232 MPU-401 interface.");
-module_param_array(cs4232_mpu_irq, int, NULL, 0444);
+module_param_hw_array(cs4232_mpu_irq, int, irq, NULL, 0444);
 MODULE_PARM_DESC(cs4232_mpu_irq, "IRQ # for CS4232 MPU-401 interface.");
-module_param_array(ics2115_irq, int, NULL, 0444);
+module_param_hw_array(ics2115_irq, int, irq, NULL, 0444);
 MODULE_PARM_DESC(ics2115_irq, "IRQ # for ICS2115.");
-module_param_array(ics2115_port, long, NULL, 0444);
+module_param_hw_array(ics2115_port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(ics2115_port, "Port # for ICS2115.");
-module_param_array(fm_port, long, NULL, 0444);
+module_param_hw_array(fm_port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(fm_port, "FM port #.");
 module_param_array(use_cs4232_midi, bool, NULL, 0444);
 MODULE_PARM_DESC(use_cs4232_midi, "Use CS4232 MPU-401 interface (inaccessibly located inside your computer)");
index f6156d8169d05b259c1fb35219efa7d6e3def735..2421f59cf27996cb560f27fb90c6823ed69b67f0 100644 (file)
@@ -2805,10 +2805,10 @@ static int __initdata dma = -1;
 static int __initdata dma2 = -1;
 static int __initdata type = 0;
 
-module_param(io, int, 0);              /* I/O for a raw AD1848 card */
-module_param(irq, int, 0);             /* IRQ to use */
-module_param(dma, int, 0);             /* First DMA channel */
-module_param(dma2, int, 0);            /* Second DMA channel */
+module_param_hw(io, int, ioport, 0);   /* I/O for a raw AD1848 card */
+module_param_hw(irq, int, irq, 0);     /* IRQ to use */
+module_param_hw(dma, int, dma, 0);     /* First DMA channel */
+module_param_hw(dma2, int, dma, 0);    /* Second DMA channel */
 module_param(type, int, 0);            /* Card type */
 module_param(deskpro_xl, bool, 0);     /* Special magic for Deskpro XL boxen */
 module_param(deskpro_m, bool, 0);      /* Special magic for Deskpro M box */
index bb477d5c8528611776abee1fe7584f1d65389d89..f058ed6bdb697396c8b6c3f09b567c82be9626ac 100644 (file)
@@ -1303,17 +1303,17 @@ static int __initdata mpu_irq = -1;
 static int __initdata mss_base = -1;
 static int __initdata mpu_base = -1;
 
-module_param(io, int, 0);
+module_param_hw(io, int, ioport, 0);
 MODULE_PARM_DESC(io, "I/O base address (0x220 0x240)");
-module_param(irq, int, 0);
+module_param_hw(irq, int, irq, 0);
 MODULE_PARM_DESC(irq, "IRQ line (5 7 9 10 11)");
-module_param(dma, int, 0);
+module_param_hw(dma, int, dma, 0);
 MODULE_PARM_DESC(dma, "dma line (0 1 3)");
-module_param(mpu_irq, int, 0);
+module_param_hw(mpu_irq, int, irq, 0);
 MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ line (5 7 9 10 0)");
-module_param(mss_base, int, 0);
+module_param_hw(mss_base, int, ioport, 0);
 MODULE_PARM_DESC(mss_base, "MSS emulation I/O base address (0x530 0xE80)");
-module_param(mpu_base, int, 0);
+module_param_hw(mpu_base, int, ioport, 0);
 MODULE_PARM_DESC(mpu_base,"MPU-401 I/O base address (0x300 0x310 0x320 0x330)");
 MODULE_AUTHOR("Riccardo Facchetti <fizban@tin.it>");
 MODULE_DESCRIPTION("Audio Excel DSP 16 Driver Version " VERSION);
index 862735005b4318eff1cfb9ad7af95385c3f7a405..20e8fa46f6473ef7023452755090e5a77023d6cb 100644 (file)
@@ -1748,8 +1748,8 @@ static struct address_info cfg;
 static int io = -1;
 static int irq = -1;
 
-module_param(irq, int, 0);
-module_param(io, int, 0);
+module_param_hw(irq, int, irq, 0);
+module_param_hw(io, int, ioport, 0);
 
 static int __init init_mpu401(void)
 {
index f34ec01d22394d75987418564aa25785e3398929..d2abc2cf3213b7f3f94ac2a5e5eb889bc47eab53 100644 (file)
@@ -1727,22 +1727,22 @@ static int
 calibrate_signal __initdata =          CONFIG_MSND_CALSIGNAL;
 #endif /* MODULE */
 
-module_param                           (io, int, 0);
-module_param                           (irq, int, 0);
-module_param                           (mem, int, 0);
+module_param_hw                                (io, int, ioport, 0);
+module_param_hw                                (irq, int, irq, 0);
+module_param_hw                                (mem, int, iomem, 0);
 module_param                           (write_ndelay, int, 0);
 module_param                           (fifosize, int, 0);
 module_param                           (calibrate_signal, int, 0);
 #ifndef MSND_CLASSIC
 module_param                           (digital, bool, 0);
-module_param                           (cfg, int, 0);
+module_param_hw                                (cfg, int, ioport, 0);
 module_param                           (reset, int, 0);
-module_param                           (mpu_io, int, 0);
-module_param                           (mpu_irq, int, 0);
-module_param                           (ide_io0, int, 0);
-module_param                           (ide_io1, int, 0);
-module_param                           (ide_irq, int, 0);
-module_param                           (joystick_io, int, 0);
+module_param_hw                                (mpu_io, int, ioport, 0);
+module_param_hw                                (mpu_irq, int, irq, 0);
+module_param_hw                                (ide_io0, int, ioport, 0);
+module_param_hw                                (ide_io1, int, ioport, 0);
+module_param_hw                                (ide_irq, int, irq, 0);
+module_param_hw                                (joystick_io, int, ioport, 0);
 #endif
 
 static int __init msnd_init(void)
index b6d19adf8f4111d575c88b235142d6ed0580654f..f0f5b5be63140bdc11ad67334ebd7d51910d4f6b 100644 (file)
@@ -1200,7 +1200,7 @@ static int me;
 
 static int io = -1;
 
-module_param(io, int, 0);
+module_param_hw(io, int, ioport, 0);
 
 static int __init init_opl3 (void)
 {
index b07954a7953679b077b12b190343492a3271510f..769fca692d2aa7e5b51381cab8a7d4b37921610c 100644 (file)
@@ -383,15 +383,15 @@ static int __initdata sb_irq      = -1;
 static int __initdata sb_dma   = -1;
 static int __initdata sb_dma16 = -1;
 
-module_param(io, int, 0);
-module_param(irq, int, 0);
-module_param(dma, int, 0);
-module_param(dma16, int, 0);
-
-module_param(sb_io, int, 0);
-module_param(sb_irq, int, 0);
-module_param(sb_dma, int, 0);
-module_param(sb_dma16, int, 0);
+module_param_hw(io, int, ioport, 0);
+module_param_hw(irq, int, irq, 0);
+module_param_hw(dma, int, dma, 0);
+module_param_hw(dma16, int, dma, 0);
+
+module_param_hw(sb_io, int, ioport, 0);
+module_param_hw(sb_irq, int, irq, 0);
+module_param_hw(sb_dma, int, dma, 0);
+module_param_hw(sb_dma16, int, dma, 0);
 
 module_param(joystick, bool, 0);
 module_param(symphony, bool, 0);
index 81314f9e2ccb9c8bffccdc699cca698820081625..33c3a442e162616caf3ccee97d640e45f749414a 100644 (file)
@@ -1139,19 +1139,19 @@ static bool pss_no_sound = 0;   /* Just configure non-sound components */
 static bool pss_keep_settings  = 1;    /* Keep hardware settings at module exit */
 static char *pss_firmware = "/etc/sound/pss_synth";
 
-module_param(pss_io, int, 0);
+module_param_hw(pss_io, int, ioport, 0);
 MODULE_PARM_DESC(pss_io, "Set i/o base of PSS card (probably 0x220 or 0x240)");
-module_param(mss_io, int, 0);
+module_param_hw(mss_io, int, ioport, 0);
 MODULE_PARM_DESC(mss_io, "Set WSS (audio) i/o base (0x530, 0x604, 0xE80, 0xF40, or other. Address must end in 0 or 4 and must be from 0x100 to 0xFF4)");
-module_param(mss_irq, int, 0);
+module_param_hw(mss_irq, int, irq, 0);
 MODULE_PARM_DESC(mss_irq, "Set WSS (audio) IRQ (3, 5, 7, 9, 10, 11, 12)");
-module_param(mss_dma, int, 0);
+module_param_hw(mss_dma, int, dma, 0);
 MODULE_PARM_DESC(mss_dma, "Set WSS (audio) DMA (0, 1, 3)");
-module_param(mpu_io, int, 0);
+module_param_hw(mpu_io, int, ioport, 0);
 MODULE_PARM_DESC(mpu_io, "Set MIDI i/o base (0x330 or other. Address must be on 4 location boundaries and must be from 0x100 to 0xFFC)");
-module_param(mpu_irq, int, 0);
+module_param_hw(mpu_irq, int, irq, 0);
 MODULE_PARM_DESC(mpu_irq, "Set MIDI IRQ (3, 5, 7, 9, 10, 11, 12)");
-module_param(pss_cdrom_port, int, 0);
+module_param_hw(pss_cdrom_port, int, ioport, 0);
 MODULE_PARM_DESC(pss_cdrom_port, "Set the PSS CDROM port i/o base (0x340 or other)");
 module_param(pss_enable_joystick, bool, 0);
 MODULE_PARM_DESC(pss_enable_joystick, "Enables the PSS joystick port (1 to enable, 0 to disable)");
index fb5d7250de38d75f5f7b27cafcc7e674390ae7d0..2a92cfe6cfe97500511488708be3686ad4d2aa84 100644 (file)
@@ -61,15 +61,15 @@ static int __initdata uart401       = 0;
 static int __initdata pnp       = 0;
 #endif
 
-module_param(io, int, 000);
+module_param_hw(io, int, ioport, 000);
 MODULE_PARM_DESC(io,       "Soundblaster i/o base address (0x220,0x240,0x260,0x280)");
-module_param(irq, int, 000);
+module_param_hw(irq, int, irq, 000);
 MODULE_PARM_DESC(irq,     "IRQ (5,7,9,10)");
-module_param(dma, int, 000);
+module_param_hw(dma, int, dma, 000);
 MODULE_PARM_DESC(dma,     "8-bit DMA channel (0,1,3)");
-module_param(dma16, int, 000);
+module_param_hw(dma16, int, dma, 000);
 MODULE_PARM_DESC(dma16,           "16-bit DMA channel (5,6,7)");
-module_param(mpu_io, int, 000);
+module_param_hw(mpu_io, int, ioport, 000);
 MODULE_PARM_DESC(mpu_io,   "MPU base address");
 module_param(type, int, 000);
 MODULE_PARM_DESC(type,    "You can set this to specific card type (doesn't " \
index 3c494dc93b936d4680aca2a70ccee94d1fba7938..a57bc635d7585fe7a1bbed1e64a6b395861fd0fa 100644 (file)
@@ -413,15 +413,15 @@ static int __initdata sb_irq      = -1;
 static int __initdata mpu_io   = -1;
 static int __initdata mpu_irq  = -1;
 
-module_param(io, int, 0);
-module_param(irq, int, 0);
-module_param(dma, int, 0);
-module_param(dma2, int, 0);
-module_param(sb_io, int, 0);
-module_param(sb_dma, int, 0);
-module_param(sb_irq, int, 0);
-module_param(mpu_io, int, 0);
-module_param(mpu_irq, int, 0);
+module_param_hw(io, int, ioport, 0);
+module_param_hw(irq, int, irq, 0);
+module_param_hw(dma, int, dma, 0);
+module_param_hw(dma2, int, dma, 0);
+module_param_hw(sb_io, int, ioport, 0);
+module_param_hw(sb_dma, int, dma, 0);
+module_param_hw(sb_irq, int, irq, 0);
+module_param_hw(mpu_io, int, ioport, 0);
+module_param_hw(mpu_irq, int, irq, 0);
 module_param(joystick, bool, 0);
 
 static int __init init_trix(void)
index dae4d4344407875bb627acbe25b115b5fb734a19..83dcc85b86882af55cdb0c6de5f75b36c23857de 100644 (file)
@@ -429,8 +429,8 @@ static struct address_info cfg_mpu;
 static int io = -1;
 static int irq = -1;
 
-module_param(io, int, 0444);
-module_param(irq, int, 0444);
+module_param_hw(io, int, ioport, 0444);
+module_param_hw(irq, int, irq, 0444);
 
 
 static int __init init_uart401(void)
index 1079133dd6ab17fc856677a328ea54563028c555..eda32d7eddbdc89a9181e5e319cb1d65cf1d4b81 100644 (file)
@@ -315,8 +315,8 @@ static struct address_info cfg_mpu;
 static int __initdata io = -1;
 static int __initdata irq = -1;
 
-module_param(io, int, 0);
-module_param(irq, int, 0);
+module_param_hw(io, int, ioport, 0);
+module_param_hw(irq, int, irq, 0);
 
 static int __init init_uart6850(void)
 {
index 0b8d0de872732e618a55f6b26e9bec9935956d60..4f0c3a232e41a7686fb04795deb7300d03220ea6 100644 (file)
@@ -2036,8 +2036,8 @@ __setup("waveartist=", setup_waveartist);
 #endif
 
 MODULE_DESCRIPTION("Rockwell WaveArtist RWA-010 sound driver");
-module_param(io, int, 0);              /* IO base */
-module_param(irq, int, 0);             /* IRQ */
-module_param(dma, int, 0);             /* DMA */
-module_param(dma2, int, 0);            /* DMA2 */
+module_param_hw(io, int, ioport, 0);           /* IO base */
+module_param_hw(irq, int, irq, 0);             /* IRQ */
+module_param_hw(dma, int, dma, 0);             /* DMA */
+module_param_hw(dma2, int, dma, 0);            /* DMA2 */
 MODULE_LICENSE("GPL");
index 92bc06d0128833c96902c5684e75bfbc0af8a5f5..7844a75d8ed97f7a6bda5b747e2872600cca4da6 100644 (file)
@@ -102,7 +102,7 @@ MODULE_PARM_DESC(id, "ID string for ALS4000 soundcard.");
 module_param_array(enable, bool, NULL, 0444);
 MODULE_PARM_DESC(enable, "Enable ALS4000 soundcard.");
 #ifdef SUPPORT_JOYSTICK
-module_param_array(joystick_port, int, NULL, 0444);
+module_param_hw_array(joystick_port, int, ioport, NULL, 0444);
 MODULE_PARM_DESC(joystick_port, "Joystick port address for ALS4000 soundcard. (0 = disabled)");
 #endif
 
index 227c9d3802b80b2f74281c4ad6d277a0259aef50..745a0a3743b479cd9e8bd846fbec7e53f1b9eb53 100644 (file)
@@ -68,14 +68,14 @@ module_param_array(id, charp, NULL, 0444);
 MODULE_PARM_DESC(id, "ID string for C-Media PCI soundcard.");
 module_param_array(enable, bool, NULL, 0444);
 MODULE_PARM_DESC(enable, "Enable C-Media PCI soundcard.");
-module_param_array(mpu_port, long, NULL, 0444);
+module_param_hw_array(mpu_port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port.");
-module_param_array(fm_port, long, NULL, 0444);
+module_param_hw_array(fm_port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(fm_port, "FM port.");
 module_param_array(soft_ac3, bool, NULL, 0444);
 MODULE_PARM_DESC(soft_ac3, "Software-conversion of raw SPDIF packets (model 033 only).");
 #ifdef SUPPORT_JOYSTICK
-module_param_array(joystick_port, int, NULL, 0444);
+module_param_hw_array(joystick_port, int, ioport, NULL, 0444);
 MODULE_PARM_DESC(joystick_port, "Joystick port address.");
 #endif
 
index 5d10349d11ce5118d237dd451d71eacdee2c98e4..09a63ef41ef2ec56eca7c679fde580d968e906d7 100644 (file)
@@ -106,7 +106,7 @@ module_param_array(enable, bool, NULL, 0444);
 MODULE_PARM_DESC(enable, "Enable Ensoniq AudioPCI soundcard.");
 #ifdef SUPPORT_JOYSTICK
 #ifdef CHIP1371
-module_param_array(joystick_port, int, NULL, 0444);
+module_param_hw_array(joystick_port, int, ioport, NULL, 0444);
 MODULE_PARM_DESC(joystick_port, "Joystick port address.");
 #else
 module_param_array(joystick, bool, NULL, 0444);
index b786fbab029ff621a7c422581cc0442ecd6a1737..1770f085c2a694a398e2b30312cb79d6c3fd617a 100644 (file)
@@ -53,7 +53,7 @@
 #ifdef CONFIG_X86
 /* for snoop control */
 #include <asm/pgtable.h>
-#include <asm/cacheflush.h>
+#include <asm/set_memory.h>
 #include <asm/cpufeature.h>
 #endif
 #include <sound/core.h>
index e8253737c47a4080c36efb46b45b3228f7c7897a..63bc894ddf5e8102c3f1ed93c80fef50c3f95700 100644 (file)
@@ -860,7 +860,9 @@ static const struct hda_fixup cxt_fixups[] = {
                        { 0x16, 0x21011020 }, /* line-out */
                        { 0x18, 0x2181103f }, /* line-in */
                        { }
-               }
+               },
+               .chained = true,
+               .chain_id = CXT_FIXUP_MUTE_LED_GPIO,
        },
        [CXT_FIXUP_HP_SPECTRE] = {
                .type = HDA_FIXUP_PINS,
index 9720a30dbfff31fb412b385370647927e6ecef3a..6d17b171c17bfeee104eec7c9939aa45b3868f5d 100644 (file)
@@ -40,7 +40,9 @@
 #include <sound/initval.h>
 /* for 440MX workaround */
 #include <asm/pgtable.h>
-#include <asm/cacheflush.h>
+#ifdef CONFIG_X86
+#include <asm/set_memory.h>
+#endif
 
 MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
 MODULE_DESCRIPTION("Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; SiS 7012; Ali 5455");
index 19c9df6b0f3df2e5cc0b431c816e652b82dacc3a..f067c76d77f82978469f8d58aa0bc6960df95a7f 100644 (file)
@@ -137,12 +137,12 @@ MODULE_PARM_DESC(id, "ID string for Riptide soundcard.");
 module_param_array(enable, bool, NULL, 0444);
 MODULE_PARM_DESC(enable, "Enable Riptide soundcard.");
 #ifdef SUPPORT_JOYSTICK
-module_param_array(joystick_port, int, NULL, 0444);
+module_param_hw_array(joystick_port, int, ioport, NULL, 0444);
 MODULE_PARM_DESC(joystick_port, "Joystick port # for Riptide soundcard.");
 #endif
-module_param_array(mpu_port, int, NULL, 0444);
+module_param_hw_array(mpu_port, int, ioport, NULL, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU401 port # for Riptide driver.");
-module_param_array(opl3_port, int, NULL, 0444);
+module_param_hw_array(opl3_port, int, ioport, NULL, 0444);
 MODULE_PARM_DESC(opl3_port, "OPL3 port # for Riptide driver.");
 
 /*
index a6aa48c5b9693949d2544a285d1a13685ec5bf6b..8e3d4ec39c35cbdc5ba231f724403b9e0f33d859 100644 (file)
@@ -66,7 +66,7 @@ module_param_array(reverb, bool, NULL, 0444);
 MODULE_PARM_DESC(reverb, "Enable reverb (SRAM is present) for S3 SonicVibes soundcard.");
 module_param_array(mge, bool, NULL, 0444);
 MODULE_PARM_DESC(mge, "MIC Gain Enable for S3 SonicVibes soundcard.");
-module_param(dmaio, uint, 0444);
+module_param_hw(dmaio, uint, ioport, 0444);
 MODULE_PARM_DESC(dmaio, "DDMA i/o base address for S3 SonicVibes soundcard.");
 
 /*
index d078e86414c2798a1580e45d8b7e5856e34948c7..b6c84d15b10bbdcbb26ce71dbdd2d895f7a961a0 100644 (file)
@@ -92,7 +92,7 @@ module_param(index, int, 0444);
 MODULE_PARM_DESC(index, "Index value for VIA 82xx bridge.");
 module_param(id, charp, 0444);
 MODULE_PARM_DESC(id, "ID string for VIA 82xx bridge.");
-module_param(mpu_port, long, 0444);
+module_param_hw(mpu_port, long, ioport, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 port. (VT82C686x only)");
 #ifdef SUPPORT_JOYSTICK
 module_param(joystick, bool, 0444);
index 812e27a1bcbc04b0fbd7fbbab3efd44e41aded48..4faf3e1ed06a78ca3c1a46dc16fd596f51c7752b 100644 (file)
@@ -55,12 +55,12 @@ module_param_array(id, charp, NULL, 0444);
 MODULE_PARM_DESC(id, "ID string for the Yamaha DS-1 PCI soundcard.");
 module_param_array(enable, bool, NULL, 0444);
 MODULE_PARM_DESC(enable, "Enable Yamaha DS-1 soundcard.");
-module_param_array(mpu_port, long, NULL, 0444);
+module_param_hw_array(mpu_port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(mpu_port, "MPU-401 Port.");
-module_param_array(fm_port, long, NULL, 0444);
+module_param_hw_array(fm_port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(fm_port, "FM OPL-3 Port.");
 #ifdef SUPPORT_JOYSTICK
-module_param_array(joystick_port, long, NULL, 0444);
+module_param_hw_array(joystick_port, long, ioport, NULL, 0444);
 MODULE_PARM_DESC(joystick_port, "Joystick port address");
 #endif
 module_param_array(rear_switch, bool, NULL, 0444);
index 525f2f397b4c225208a6b82c94ae8c1addd2eeaf..aae099c0e50280d67f153d6769ac4237d531e169 100644 (file)
@@ -936,7 +936,7 @@ static struct snd_soc_component *soc_find_component(
  *
  * @dlc: name of the DAI and optional component info to match
  *
- * This function will search all regsitered components and their DAIs to
+ * This function will search all registered components and their DAIs to
  * find the DAI of the same name. The component's of_node and name
  * should also match if being specified.
  *
index c505b019e09ce0795cc8ddd79cf1f8c6a18d32ff..664b7fe206d65457cf3e7b1486a05b7e92493cb8 100644 (file)
@@ -30,7 +30,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
-#include <asm/cacheflush.h>
+#include <asm/set_memory.h>
 #include <sound/core.h>
 #include <sound/asoundef.h>
 #include <sound/pcm.h>
index ebc6dceddb58c00e4253e4fc3b37eda7a17b62be..7598361ef1f10898ea73d944ae0b0c02c4725d99 100644 (file)
@@ -29,6 +29,7 @@ int main(void)
        attr.log_size = 0;
        attr.log_level = 0;
        attr.kern_version = 0;
+       attr.prog_flags = 0;
 
        /*
         * Test existence of __NR_bpf and BPF_PROG_LOAD.
index c4a148dd71048a0fb89eb24ea4527976702110c2..9c6b4cbffb1cae2759a524b70d36cee1b8f9f02e 100644 (file)
@@ -1,4 +1,6 @@
+#ifndef _GNU_SOURCE
 #define _GNU_SOURCE
+#endif
 #include <sched.h>
 
 int main(void)
index f436d2420a18575095e66b7bfbf15b0abbe83fe8..d62b56cf8c12eedcdda935bc1180c4b4b70270b9 100644 (file)
@@ -18,4 +18,6 @@ extern size_t strlcpy(char *dest, const char *src, size_t size);
 
 char *str_error_r(int errnum, char *buf, size_t buflen);
 
+int prefixcmp(const char *str, const char *prefix);
+
 #endif /* _LINUX_STRING_H_ */
index e553529929f683c4c39ae336d10c6f670e589b54..94dfa9def355f7f52805bba5ade3a32c304f989a 100644 (file)
@@ -132,6 +132,13 @@ enum bpf_attach_type {
  */
 #define BPF_F_ALLOW_OVERRIDE   (1U << 0)
 
+/* If BPF_F_STRICT_ALIGNMENT is used in BPF_PROG_LOAD command, the
+ * verifier will perform strict alignment checking as if the kernel
+ * has been built with CONFIG_EFFICIENT_UNALIGNED_ACCESS not set,
+ * and NET_IP_ALIGN defined to 2.
+ */
+#define BPF_F_STRICT_ALIGNMENT (1U << 0)
+
 #define BPF_PSEUDO_MAP_FD      1
 
 /* flags for BPF_MAP_UPDATE_ELEM command */
@@ -177,6 +184,7 @@ union bpf_attr {
                __u32           log_size;       /* size of user buffer */
                __aligned_u64   log_buf;        /* user supplied buffer */
                __u32           kern_version;   /* checked when prog_type=kprobe */
+               __u32           prog_flags;
        };
 
        struct { /* anonymous struct used by BPF_OBJ_* commands */
@@ -481,8 +489,7 @@ union bpf_attr {
  * u32 bpf_get_socket_uid(skb)
  *     Get the owner uid of the socket stored inside sk_buff.
  *     @skb: pointer to skb
- *     Return: uid of the socket owner on success or 0 if the socket pointer
- *     inside sk_buff is NULL
+ *     Return: uid of the socket owner on success or overflowuid if failed.
  */
 #define __BPF_FUNC_MAPPER(FN)          \
        FN(unspec),                     \
index 4fe444b8092e2d6dc8aea6b7ce8349a64e439c44..6e178987af8e3f45d63da349e38c39b4e4cd6d84 100644 (file)
@@ -117,6 +117,28 @@ int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
        return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
 }
 
+int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns,
+                      size_t insns_cnt, int strict_alignment,
+                      const char *license, __u32 kern_version,
+                      char *log_buf, size_t log_buf_sz)
+{
+       union bpf_attr attr;
+
+       bzero(&attr, sizeof(attr));
+       attr.prog_type = type;
+       attr.insn_cnt = (__u32)insns_cnt;
+       attr.insns = ptr_to_u64(insns);
+       attr.license = ptr_to_u64(license);
+       attr.log_buf = ptr_to_u64(log_buf);
+       attr.log_size = log_buf_sz;
+       attr.log_level = 2;
+       log_buf[0] = 0;
+       attr.kern_version = kern_version;
+       attr.prog_flags = strict_alignment ? BPF_F_STRICT_ALIGNMENT : 0;
+
+       return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
+}
+
 int bpf_map_update_elem(int fd, const void *key, const void *value,
                        __u64 flags)
 {
index edb4daeff7a52c44f6bc366c265a7f5a3aadfc10..972bd8333eb72e982420abeac9f8ceff5a4ed1a3 100644 (file)
@@ -35,6 +35,10 @@ int bpf_load_program(enum bpf_prog_type type, const struct bpf_insn *insns,
                     size_t insns_cnt, const char *license,
                     __u32 kern_version, char *log_buf,
                     size_t log_buf_sz);
+int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns,
+                      size_t insns_cnt, int strict_alignment,
+                      const char *license, __u32 kern_version,
+                      char *log_buf, size_t log_buf_sz);
 
 int bpf_map_update_elem(int fd, const void *key, const void *value,
                        __u64 flags);
index bd239bc1d557dbde447e8128ac7cd3163dc11a04..8e678af1c6ee479eae333cf5766598db5dce5208 100644 (file)
@@ -87,3 +87,12 @@ size_t __weak strlcpy(char *dest, const char *src, size_t size)
        }
        return ret;
 }
+
+int prefixcmp(const char *str, const char *prefix)
+{
+       for (; ; str++, prefix++)
+               if (!*prefix)
+                       return 0;
+               else if (*str != *prefix)
+                       return (unsigned char)*prefix - (unsigned char)*str;
+}
index e228c3cb37160b8fd5bda5e3a7c9e76f89ea4537..ba970a73d053f3c019a318dbb7fa14b9dbab9b40 100644 (file)
@@ -1,6 +1,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <linux/string.h>
 #include <termios.h>
 #include <sys/ioctl.h>
 #include <sys/types.h>
index 6bc24025d05457098b504c3a1e9e5a1316b21817..359bfa77f39cdebac7df82876b227d1a63975c39 100644 (file)
@@ -1,4 +1,5 @@
 #include <linux/compiler.h>
+#include <linux/string.h>
 #include <linux/types.h>
 #include <stdio.h>
 #include <stdlib.h>
index fc2e45d8aaf1d04c09d53fd4db6478d60d066895..8fa5f036eff08002ee802dc6014f6689d790a80f 100644 (file)
@@ -79,13 +79,4 @@ static inline void astrcat(char **out, const char *add)
        free(tmp);
 }
 
-static inline int prefixcmp(const char *str, const char *prefix)
-{
-       for (; ; str++, prefix++)
-               if (!*prefix)
-                       return 0;
-               else if (*str != *prefix)
-                       return (unsigned char)*prefix - (unsigned char)*str;
-}
-
 #endif /* __SUBCMD_UTIL_H */
diff --git a/tools/pci/pcitest.c b/tools/pci/pcitest.c
new file mode 100644 (file)
index 0000000..ad54a58
--- /dev/null
@@ -0,0 +1,186 @@
+/**
+ * Userspace PCI Endpoint Test Module
+ *
+ * Copyright (C) 2017 Texas Instruments
+ * Author: Kishon Vijay Abraham I <kishon@ti.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 of
+ * the License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <linux/pcitest.h>
+
+#define BILLION 1E9
+
+static char *result[] = { "NOT OKAY", "OKAY" };
+
+struct pci_test {
+       char            *device;
+       char            barnum;
+       bool            legacyirq;
+       unsigned int    msinum;
+       bool            read;
+       bool            write;
+       bool            copy;
+       unsigned long   size;
+};
+
+static int run_test(struct pci_test *test)
+{
+       long ret;
+       int fd;
+       struct timespec start, end;
+       double time;
+
+       fd = open(test->device, O_RDWR);
+       if (fd < 0) {
+               perror("can't open PCI Endpoint Test device");
+               return fd;
+       }
+
+       if (test->barnum >= 0 && test->barnum <= 5) {
+               ret = ioctl(fd, PCITEST_BAR, test->barnum);
+               fprintf(stdout, "BAR%d:\t\t", test->barnum);
+               if (ret < 0)
+                       fprintf(stdout, "TEST FAILED\n");
+               else
+                       fprintf(stdout, "%s\n", result[ret]);
+       }
+
+       if (test->legacyirq) {
+               ret = ioctl(fd, PCITEST_LEGACY_IRQ, 0);
+               fprintf(stdout, "LEGACY IRQ:\t");
+               if (ret < 0)
+                       fprintf(stdout, "TEST FAILED\n");
+               else
+                       fprintf(stdout, "%s\n", result[ret]);
+       }
+
+       if (test->msinum > 0 && test->msinum <= 32) {
+               ret = ioctl(fd, PCITEST_MSI, test->msinum);
+               fprintf(stdout, "MSI%d:\t\t", test->msinum);
+               if (ret < 0)
+                       fprintf(stdout, "TEST FAILED\n");
+               else
+                       fprintf(stdout, "%s\n", result[ret]);
+       }
+
+       if (test->write) {
+               ret = ioctl(fd, PCITEST_WRITE, test->size);
+               fprintf(stdout, "WRITE (%7ld bytes):\t\t", test->size);
+               if (ret < 0)
+                       fprintf(stdout, "TEST FAILED\n");
+               else
+                       fprintf(stdout, "%s\n", result[ret]);
+       }
+
+       if (test->read) {
+               ret = ioctl(fd, PCITEST_READ, test->size);
+               fprintf(stdout, "READ (%7ld bytes):\t\t", test->size);
+               if (ret < 0)
+                       fprintf(stdout, "TEST FAILED\n");
+               else
+                       fprintf(stdout, "%s\n", result[ret]);
+       }
+
+       if (test->copy) {
+               ret = ioctl(fd, PCITEST_COPY, test->size);
+               fprintf(stdout, "COPY (%7ld bytes):\t\t", test->size);
+               if (ret < 0)
+                       fprintf(stdout, "TEST FAILED\n");
+               else
+                       fprintf(stdout, "%s\n", result[ret]);
+       }
+
+       fflush(stdout);
+}
+
+int main(int argc, char **argv)
+{
+       int c;
+       struct pci_test *test;
+
+       test = calloc(1, sizeof(*test));
+       if (!test) {
+               perror("Fail to allocate memory for pci_test\n");
+               return -ENOMEM;
+       }
+
+       /* since '0' is a valid BAR number, initialize it to -1 */
+       test->barnum = -1;
+
+       /* set default size as 100KB */
+       test->size = 0x19000;
+
+       /* set default endpoint device */
+       test->device = "/dev/pci-endpoint-test.0";
+
+       while ((c = getopt(argc, argv, "D:b:m:lrwcs:")) != EOF)
+       switch (c) {
+       case 'D':
+               test->device = optarg;
+               continue;
+       case 'b':
+               test->barnum = atoi(optarg);
+               if (test->barnum < 0 || test->barnum > 5)
+                       goto usage;
+               continue;
+       case 'l':
+               test->legacyirq = true;
+               continue;
+       case 'm':
+               test->msinum = atoi(optarg);
+               if (test->msinum < 1 || test->msinum > 32)
+                       goto usage;
+               continue;
+       case 'r':
+               test->read = true;
+               continue;
+       case 'w':
+               test->write = true;
+               continue;
+       case 'c':
+               test->copy = true;
+               continue;
+       case 's':
+               test->size = strtoul(optarg, NULL, 0);
+               continue;
+       case '?':
+       case 'h':
+       default:
+usage:
+               fprintf(stderr,
+                       "usage: %s [options]\n"
+                       "Options:\n"
+                       "\t-D <dev>             PCI endpoint test device {default: /dev/pci-endpoint-test.0}\n"
+                       "\t-b <bar num>         BAR test (bar number between 0..5)\n"
+                       "\t-m <msi num>         MSI test (msi number between 1..32)\n"
+                       "\t-r                   Read buffer test\n"
+                       "\t-w                   Write buffer test\n"
+                       "\t-c                   Copy buffer test\n"
+                       "\t-s <size>            Size of buffer {default: 100KB}\n",
+                       argv[0]);
+               return -EINVAL;
+       }
+
+       run_test(test);
+       return 0;
+}
diff --git a/tools/pci/pcitest.sh b/tools/pci/pcitest.sh
new file mode 100644 (file)
index 0000000..5442bbe
--- /dev/null
@@ -0,0 +1,56 @@
+#!/bin/sh
+
+echo "BAR tests"
+echo
+
+bar=0
+
+while [ $bar -lt 6 ]
+do
+       pcitest -b $bar
+       bar=`expr $bar + 1`
+done
+echo
+
+echo "Interrupt tests"
+echo
+
+pcitest -l
+msi=1
+
+while [ $msi -lt 33 ]
+do
+        pcitest -m $msi
+        msi=`expr $msi + 1`
+done
+echo
+
+echo "Read Tests"
+echo
+
+pcitest -r -s 1
+pcitest -r -s 1024
+pcitest -r -s 1025
+pcitest -r -s 1024000
+pcitest -r -s 1024001
+echo
+
+echo "Write Tests"
+echo
+
+pcitest -w -s 1
+pcitest -w -s 1024
+pcitest -w -s 1025
+pcitest -w -s 1024000
+pcitest -w -s 1024001
+echo
+
+echo "Copy Tests"
+echo
+
+pcitest -c -s 1
+pcitest -c -s 1024
+pcitest -c -s 1025
+pcitest -c -s 1024000
+pcitest -c -s 1024001
+echo
index 2da07e51e1190271dd0d74130baf4807b0b08031..82241423517051b1668564710063cd1797bcf327 100644 (file)
@@ -76,7 +76,7 @@ REPORT OPTIONS
 
 -c::
 --coalesce::
-       Specify sorintg fields for single cacheline display.
+       Specify sorting fields for single cacheline display.
        Following fields are available: tid,pid,iaddr,dso
        (see COALESCE)
 
@@ -106,7 +106,7 @@ REPORT OPTIONS
 
 -d::
 --display::
-       Siwtch to HITM type (rmt, lcl) to display and sort on. Total HITMs as default.
+       Switch to HITM type (rmt, lcl) to display and sort on. Total HITMs as default.
 
 C2C RECORD
 ----------
index ea3789d05e5e69fa60f2d8daf230f62aaae073c8..b0e9e921d534c46d79da49fe0641013a64caebb6 100644 (file)
@@ -225,7 +225,7 @@ OPTIONS
        the libunwind or libdw library) should be used instead.
        Using the "lbr" method doesn't require any compiler options. It
        will produce call graphs from the hardware LBR registers. The
-       main limition is that it is only available on new Intel
+       main limitation is that it is only available on new Intel
        platforms, such as Haswell. It can only get user call chain. It
        doesn't work with branch stack sampling at the same time.
 
index 37a1759141579b6fdf35ee1ebcb996060ef01c71..9fa84617181e47e00a93529b6a91fca3d3fbe9c2 100644 (file)
@@ -182,7 +182,7 @@ OPTIONS
 --parent=<regex>::
         A regex filter to identify parent. The parent is a caller of this
        function and searched through the callchain, thus it requires callchain
-       information recorded. The pattern is in the exteneded regex format and
+       information recorded. The pattern is in the extended regex format and
        defaults to "\^sys_|^do_page_fault", see '--sort parent'.
 
 -x::
@@ -207,8 +207,8 @@ OPTIONS
 -g::
 --call-graph=<print_type,threshold[,print_limit],order,sort_key[,branch],value>::
         Display call chains using type, min percent threshold, print limit,
-       call order, sort key, optional branch and value.  Note that ordering of
-       parameters is not fixed so any parement can be given in an arbitraty order.
+       call order, sort key, optional branch and value.  Note that ordering
+       is not fixed so any parameter can be given in an arbitrary order.
        One exception is the print_limit which should be preceded by threshold.
 
        print_type can be either:
index fa2a9132f0a9438d2637501c711c33d3a4e68ac9..de8b39dda7b828edf2d5acae5bd7ca6dae505369 100644 (file)
@@ -270,7 +270,7 @@ When the event stream contains multiple events each event is identified
 by an ID. This can be either through the PERF_SAMPLE_ID or the
 PERF_SAMPLE_IDENTIFIER header. The PERF_SAMPLE_IDENTIFIER header is
 at a fixed offset from the event header, which allows reliable
-parsing of the header. Relying on ID may be ambigious.
+parsing of the header. Relying on ID may be ambiguous.
 IDENTIFIER is only supported by newer Linux kernels.
 
 Perf record specific events:
@@ -288,7 +288,7 @@ struct attr_event {
        uint64_t id[];
 };
 
-       PERF_RECORD_HEADER_EVENT_TYPE           = 65, /* depreceated */
+       PERF_RECORD_HEADER_EVENT_TYPE           = 65, /* deprecated */
 
 #define MAX_EVENT_NAME 64
 
index 170b0289a7bcd3682b3c67249bb0eac2384b70d1..db0ca3063eaebc83d483465a2e0e9bfdaf5e4387 100644 (file)
@@ -23,7 +23,7 @@ For memory address profiling, try: perf mem record / perf mem report
 For tracepoint events, try: perf report -s trace_fields
 To record callchains for each sample: perf record -g
 To record every process run by a user: perf record -u <user>
-Skip collecing build-id when recording: perf record -B
+Skip collecting build-id when recording: perf record -B
 To change sampling frequency to 100 Hz: perf record -F 100
 See assembly instructions with percentage: perf annotate <symbol>
 If you prefer Intel style assembly, try: perf annotate -M intel
index 44eafd6f2d5008e62aa68b21a2b415d1db736a49..8f1908756cb69bd6b452aec963650b5bebe2ffea 100644 (file)
@@ -50,7 +50,7 @@ static int arm64__annotate_init(struct arch *arch)
        arch->initialized = true;
        arch->priv        = arm;
        arch->associate_instruction_ops   = arm64__associate_instruction_ops;
-       arch->objdump.comment_char        = ';';
+       arch->objdump.comment_char        = '/';
        arch->objdump.skip_functions_char = '+';
        return 0;
 
index 39dbe512b9fcf3c8caeda0cebc5dea32d9696bec..bf9a2594572c7ff3e94adfab36dce813476bb6a9 100644 (file)
@@ -52,6 +52,18 @@ int arch__compare_symbol_names(const char *namea, const char *nameb)
 
        return strcmp(namea, nameb);
 }
+
+int arch__compare_symbol_names_n(const char *namea, const char *nameb,
+                                unsigned int n)
+{
+       /* Skip over initial dot */
+       if (*namea == '.')
+               namea++;
+       if (*nameb == '.')
+               nameb++;
+
+       return strncmp(namea, nameb, n);
+}
 #endif
 
 #if defined(_CALL_ELF) && _CALL_ELF == 2
index 64b44e81c7715a1c38df8e0309bde80b7d24bf86..9eba7f1add1f9706f2b8153fb33f3574b362d5ee 100644 (file)
@@ -49,19 +49,22 @@ static bool same_kallsyms_reloc(const char *from_dir, char *to_dir)
        char to[PATH_MAX];
        const char *name;
        u64 addr1 = 0, addr2 = 0;
-       int i;
+       int i, err = -1;
 
        scnprintf(from, sizeof(from), "%s/kallsyms", from_dir);
        scnprintf(to, sizeof(to), "%s/kallsyms", to_dir);
 
        for (i = 0; (name = ref_reloc_sym_names[i]) != NULL; i++) {
-               addr1 = kallsyms__get_function_start(from, name);
-               if (addr1)
+               err = kallsyms__get_function_start(from, name, &addr1);
+               if (!err)
                        break;
        }
 
-       if (name)
-               addr2 = kallsyms__get_function_start(to, name);
+       if (err)
+               return false;
+
+       if (kallsyms__get_function_start(to, name, &addr2))
+               return false;
 
        return addr1 == addr2;
 }
index e33b4acece90aca126a50a91321bbd0cd3a533aa..620a467ee3043c5cadfedd02c87c0195bb681413 100644 (file)
@@ -27,6 +27,7 @@
 #include "tool.h"
 #include "data.h"
 #include "sort.h"
+#include "event.h"
 #include "evlist.h"
 #include "evsel.h"
 #include <asm/bug.h>
index 55f04f85b04945a1b9635857b91e3e5e03c7e3ba..80668fa7556ef5731b97c795c5a3a760134a9d8f 100644 (file)
@@ -159,6 +159,7 @@ int cmd_config(int argc, const char **argv)
        int i, ret = 0;
        struct perf_config_set *set;
        char *user_config = mkpath("%s/.perfconfig", getenv("HOME"));
+       const char *config_filename;
 
        argc = parse_options(argc, argv, config_options, config_usage,
                             PARSE_OPT_STOP_AT_NON_OPTION);
@@ -175,6 +176,11 @@ int cmd_config(int argc, const char **argv)
        else if (use_user_config)
                config_exclusive_filename = user_config;
 
+       if (!config_exclusive_filename)
+               config_filename = user_config;
+       else
+               config_filename = config_exclusive_filename;
+
        /*
         * At only 'config' sub-command, individually use the config set
         * because of reinitializing with options config file location.
@@ -192,13 +198,9 @@ int cmd_config(int argc, const char **argv)
                        parse_options_usage(config_usage, config_options, "l", 1);
                } else {
                        ret = show_config(set);
-                       if (ret < 0) {
-                               const char * config_filename = config_exclusive_filename;
-                               if (!config_exclusive_filename)
-                                       config_filename = user_config;
+                       if (ret < 0)
                                pr_err("Nothing configured, "
                                       "please check your %s \n", config_filename);
-                       }
                }
                break;
        default:
@@ -221,13 +223,8 @@ int cmd_config(int argc, const char **argv)
 
                                if (value == NULL)
                                        ret = show_spec_config(set, var);
-                               else {
-                                       const char *config_filename = config_exclusive_filename;
-
-                                       if (!config_exclusive_filename)
-                                               config_filename = user_config;
+                               else
                                        ret = set_config(set, config_filename, var, value);
-                               }
                                free(arg);
                        }
                } else
index 7ab42b8311a10c18f1be6241337fe15097af23a2..10b6362ca0bf7e0b6d5fce4697b15645ba816f02 100644 (file)
 #include "util/drv_configs.h"
 #include "util/evlist.h"
 #include "util/evsel.h"
+#include "util/event.h"
 #include "util/machine.h"
 #include "util/session.h"
 #include "util/symbol.h"
 #include "util/thread.h"
 #include "util/thread_map.h"
 #include "util/top.h"
-#include "util/util.h"
 #include <linux/rbtree.h>
 #include <subcmd/parse-options.h>
 #include "util/parse-events.h"
index eaa66fb57347642a617026d5423e3ad57b73a979..d014350adc526722da3a12f29421cd6d3c00f4af 100644 (file)
@@ -21,6 +21,7 @@
 #include "builtin.h"
 #include "util/color.h"
 #include "util/debug.h"
+#include "util/event.h"
 #include "util/evlist.h"
 #include <subcmd/exec-cmd.h>
 #include "util/machine.h"
index 4cc6960f6226289926dcee7f60ba0a6c7796332b..628a5e412cb14b00d9ead40bdcbb13db4c82bd75 100644 (file)
@@ -17,6 +17,7 @@
 #include <subcmd/parse-options.h>
 #include "util/bpf-loader.h"
 #include "util/debug.h"
+#include "util/event.h"
 #include <api/fs/fs.h>
 #include <api/fs/tracing_path.h>
 #include <errno.h>
index 70918b9865681b5e01d9ad5e2f4512b2a6edb2fb..d549a9f2c41b30f4d35eae742dbdfcb584ee804d 100644 (file)
@@ -1,5 +1,6 @@
 #include "perf.h"
 #include "util/debug.h"
+#include "util/event.h"
 #include "util/symbol.h"
 #include "util/sort.h"
 #include "util/evsel.h"
index f171b2da48990510a32bb00bc17016bf04af4471..df9c91f49af19927ad48bc9c103aaf8bd43e0c40 100644 (file)
@@ -3,6 +3,7 @@
 #include "util/symbol.h"
 #include "util/sort.h"
 #include "util/evsel.h"
+#include "util/event.h"
 #include "util/evlist.h"
 #include "util/machine.h"
 #include "util/thread.h"
index cdf0dde5fe9712b803bffcf98617dcb73fcbb2d3..06e5080182d31e879b25d2cabfc43c7a9a552097 100644 (file)
@@ -1,5 +1,6 @@
 #include "perf.h"
 #include "util/debug.h"
+#include "util/event.h"
 #include "util/symbol.h"
 #include "util/sort.h"
 #include "util/evsel.h"
index 76f41f249944ccaa3af8de50256f8a24faf22f6b..6cd9e5107f7784ab4c340f80a03bc786b7c264b4 100644 (file)
@@ -61,6 +61,7 @@ int test__kmod_path__parse(int subtest __maybe_unused)
        M("/xxxx/xxxx/x-x.ko", PERF_RECORD_MISC_KERNEL, true);
        M("/xxxx/xxxx/x-x.ko", PERF_RECORD_MISC_USER, false);
 
+#ifdef HAVE_ZLIB_SUPPORT
        /* path                alloc_name  alloc_ext   kmod  comp  name   ext */
        T("/xxxx/xxxx/x.ko.gz", true     , true      , true, true, "[x]", "gz");
        T("/xxxx/xxxx/x.ko.gz", false    , true      , true, true, NULL , "gz");
@@ -96,6 +97,7 @@ int test__kmod_path__parse(int subtest __maybe_unused)
        M("x.ko.gz", PERF_RECORD_MISC_CPUMODE_UNKNOWN, true);
        M("x.ko.gz", PERF_RECORD_MISC_KERNEL, true);
        M("x.ko.gz", PERF_RECORD_MISC_USER, false);
+#endif
 
        /* path            alloc_name  alloc_ext  kmod  comp   name             ext */
        T("[test_module]", true      , true     , true, false, "[test_module]", NULL);
index f73b3c5e125dc9e84ad3bb14c4da05e983111b5b..06eda675ae2c1ee3a59758c00285dc1a1f793230 100644 (file)
@@ -1,7 +1,6 @@
 #include <errno.h>
 #include <stdio.h>
 #include <sys/epoll.h>
-#include <util/util.h>
 #include <util/evlist.h>
 #include <linux/filter.h>
 #include "tests.h"
index 5ea0b40c4fc2175b27886916ff1fbe1717d0d7e6..caf1ce6f51527ba5e542caacfb26d06c37829674 100644 (file)
@@ -10,7 +10,10 @@ pthread_mutex_t ui__lock = PTHREAD_MUTEX_INITIALIZER;
 void *perf_gtk_handle;
 int use_browser = -1;
 
+#define PERF_GTK_DSO "libperf-gtk.so"
+
 #ifdef HAVE_GTK2_SUPPORT
+
 static int setup_gtk_browser(void)
 {
        int (*perf_ui_init)(void);
index 069583bdc670f0bf05c3f48762a53dc412a67fae..79dea95a7f688ca9fa9b16346b3fae25af797f5c 100644 (file)
@@ -13,6 +13,7 @@ libperf-y += find_bit.o
 libperf-y += kallsyms.o
 libperf-y += levenshtein.o
 libperf-y += llvm-utils.o
+libperf-y += memswap.o
 libperf-y += parse-events.o
 libperf-y += perf_regs.o
 libperf-y += path.o
index a96081121179697525d9de77cb14c36797c5027f..8a89b195c1fc3a5c36d7ca260dafe9c6b3fa8262 100644 (file)
@@ -44,6 +44,10 @@ bool build_id_cache__cached(const char *sbuild_id);
 int build_id_cache__add_s(const char *sbuild_id,
                          const char *name, bool is_kallsyms, bool is_vdso);
 int build_id_cache__remove_s(const char *sbuild_id);
+
+extern char buildid_dir[];
+
+void set_buildid_dir(const char *dir);
 void disable_buildid_cache(void);
 
 #endif
index 142835c0ca0a7dd76b1e7106b32dc60d63384c83..dc5c3bb69d73882ebbac88dfec2d16c55b56355e 100644 (file)
@@ -8,6 +8,7 @@
 #include <unistd.h>
 #include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */
 #include <api/fs/fs.h>
+#include <linux/perf_event.h>
 #include "event.h"
 #include "debug.h"
 #include "hist.h"
@@ -767,15 +768,16 @@ static int find_symbol_cb(void *arg, const char *name, char type,
        return 1;
 }
 
-u64 kallsyms__get_function_start(const char *kallsyms_filename,
-                                const char *symbol_name)
+int kallsyms__get_function_start(const char *kallsyms_filename,
+                                const char *symbol_name, u64 *addr)
 {
        struct process_symbol_args args = { .name = symbol_name, };
 
        if (kallsyms__parse(kallsyms_filename, &args, find_symbol_cb) <= 0)
-               return 0;
+               return -1;
 
-       return args.start;
+       *addr = args.start;
+       return 0;
 }
 
 int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
index db2de6413518adffc63e8c0c57d2b304696760df..7c3fa1c8cbcd4fdcde2074f354798adf59f01e67 100644 (file)
@@ -229,7 +229,7 @@ struct build_id_event {
 enum perf_user_event_type { /* above any possible kernel type */
        PERF_RECORD_USER_TYPE_START             = 64,
        PERF_RECORD_HEADER_ATTR                 = 64,
-       PERF_RECORD_HEADER_EVENT_TYPE           = 65, /* depreceated */
+       PERF_RECORD_HEADER_EVENT_TYPE           = 65, /* deprecated */
        PERF_RECORD_HEADER_TRACING_DATA         = 66,
        PERF_RECORD_HEADER_BUILD_ID             = 67,
        PERF_RECORD_FINISHED_ROUND              = 68,
@@ -675,10 +675,18 @@ size_t perf_event__fprintf_cpu_map(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf_namespaces(union perf_event *event, FILE *fp);
 size_t perf_event__fprintf(union perf_event *event, FILE *fp);
 
-u64 kallsyms__get_function_start(const char *kallsyms_filename,
-                                const char *symbol_name);
+int kallsyms__get_function_start(const char *kallsyms_filename,
+                                const char *symbol_name, u64 *addr);
 
 void *cpu_map_data__alloc(struct cpu_map *map, size_t *size, u16 *type, int *max);
 void  cpu_map_data__synthesize(struct cpu_map_data *data, struct cpu_map *map,
                               u16 type, int max);
+
+void event_attr_init(struct perf_event_attr *attr);
+
+int perf_event_paranoid(void);
+
+extern int sysctl_perf_event_max_stack;
+extern int sysctl_perf_event_max_contexts_per_stack;
+
 #endif /* __PERF_RECORD_H */
index 0e879097adfb33b455d16aa31099e698ee34db04..e4f7902d5afa62f0aecab1103bc05ca4bcb226e9 100644 (file)
@@ -21,6 +21,7 @@
 #include "asm/bug.h"
 #include "callchain.h"
 #include "cgroup.h"
+#include "event.h"
 #include "evsel.h"
 #include "evlist.h"
 #include "util.h"
index 948b2c5efb658e419114680ff07f4bf32cd70871..314a07151fb772377752dae62658b79ffdc87cd6 100644 (file)
@@ -19,6 +19,7 @@
 #include "evlist.h"
 #include "evsel.h"
 #include "header.h"
+#include "memswap.h"
 #include "../perf.h"
 #include "trace-event.h"
 #include "session.h"
index bdd4a28c6cee13e296b425d40343fb3b6e11a861..4c7718f87a0890ee64e2f78e0b97291b67ecf33e 100644 (file)
@@ -23,6 +23,7 @@
 #include "../perf.h"
 #include "session.h"
 #include "machine.h"
+#include "memswap.h"
 #include "sort.h"
 #include "tool.h"
 #include "event.h"
index 7a47f52ccfccf5de627f023e78ee554359639224..d97e014c3df395e51e61da31f9624e12927a43b2 100644 (file)
@@ -796,11 +796,11 @@ const char *ref_reloc_sym_names[] = {"_text", "_stext", NULL};
  * Returns the name of the start symbol in *symbol_name. Pass in NULL as
  * symbol_name if it's not that important.
  */
-static u64 machine__get_running_kernel_start(struct machine *machine,
-                                            const char **symbol_name)
+static int machine__get_running_kernel_start(struct machine *machine,
+                                            const char **symbol_name, u64 *start)
 {
        char filename[PATH_MAX];
-       int i;
+       int i, err = -1;
        const char *name;
        u64 addr = 0;
 
@@ -810,21 +810,28 @@ static u64 machine__get_running_kernel_start(struct machine *machine,
                return 0;
 
        for (i = 0; (name = ref_reloc_sym_names[i]) != NULL; i++) {
-               addr = kallsyms__get_function_start(filename, name);
-               if (addr)
+               err = kallsyms__get_function_start(filename, name, &addr);
+               if (!err)
                        break;
        }
 
+       if (err)
+               return -1;
+
        if (symbol_name)
                *symbol_name = name;
 
-       return addr;
+       *start = addr;
+       return 0;
 }
 
 int __machine__create_kernel_maps(struct machine *machine, struct dso *kernel)
 {
        int type;
-       u64 start = machine__get_running_kernel_start(machine, NULL);
+       u64 start = 0;
+
+       if (machine__get_running_kernel_start(machine, NULL, &start))
+               return -1;
 
        /* In case of renewal the kernel map, destroy previous one */
        machine__destroy_kernel_maps(machine);
@@ -1185,8 +1192,8 @@ static int machine__create_modules(struct machine *machine)
 int machine__create_kernel_maps(struct machine *machine)
 {
        struct dso *kernel = machine__get_kernel(machine);
-       const char *name;
-       u64 addr;
+       const char *name = NULL;
+       u64 addr = 0;
        int ret;
 
        if (kernel == NULL)
@@ -1211,8 +1218,7 @@ int machine__create_kernel_maps(struct machine *machine)
         */
        map_groups__fixup_end(&machine->kmaps);
 
-       addr = machine__get_running_kernel_start(machine, &name);
-       if (!addr) {
+       if (machine__get_running_kernel_start(machine, &name, &addr)) {
        } else if (maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name, addr)) {
                machine__destroy_kernel_maps(machine);
                return -1;
index ebfa5d92358acd609269dd38e03a656d96ec43f7..2179b2deb7307c749fb171e48c784e4bc158b028 100644 (file)
@@ -325,11 +325,6 @@ int map__load(struct map *map)
        return 0;
 }
 
-int __weak arch__compare_symbol_names(const char *namea, const char *nameb)
-{
-       return strcmp(namea, nameb);
-}
-
 struct symbol *map__find_symbol(struct map *map, u64 addr)
 {
        if (map__load(map) < 0)
index c8a5a644c0a9797f309fb58d9d2f69bd163cb598..f9e8ac8a52cde5fefb74cb87464c1346e3d08431 100644 (file)
@@ -130,13 +130,14 @@ struct thread;
  */
 #define __map__for_each_symbol_by_name(map, sym_name, pos)     \
        for (pos = map__find_symbol_by_name(map, sym_name);     \
-            pos && arch__compare_symbol_names(pos->name, sym_name) == 0;       \
+            pos &&                                             \
+            !symbol__match_symbol_name(pos->name, sym_name,    \
+                                       SYMBOL_TAG_INCLUDE__DEFAULT_ONLY); \
             pos = symbol__next_by_name(pos))
 
 #define map__for_each_symbol_by_name(map, sym_name, pos)               \
        __map__for_each_symbol_by_name(map, sym_name, (pos))
 
-int arch__compare_symbol_names(const char *namea, const char *nameb);
 void map__init(struct map *map, enum map_type type,
               u64 start, u64 end, u64 pgoff, struct dso *dso);
 struct map *map__new(struct machine *machine, u64 start, u64 len,
diff --git a/tools/perf/util/memswap.c b/tools/perf/util/memswap.c
new file mode 100644 (file)
index 0000000..55f7faa
--- /dev/null
@@ -0,0 +1,24 @@
+#include <byteswap.h>
+#include "memswap.h"
+#include <linux/types.h>
+
+void mem_bswap_32(void *src, int byte_size)
+{
+       u32 *m = src;
+       while (byte_size > 0) {
+               *m = bswap_32(*m);
+               byte_size -= sizeof(u32);
+               ++m;
+       }
+}
+
+void mem_bswap_64(void *src, int byte_size)
+{
+       u64 *m = src;
+
+       while (byte_size > 0) {
+               *m = bswap_64(*m);
+               byte_size -= sizeof(u64);
+               ++m;
+       }
+}
diff --git a/tools/perf/util/memswap.h b/tools/perf/util/memswap.h
new file mode 100644 (file)
index 0000000..7d1b1c3
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef PERF_MEMSWAP_H_
+#define PERF_MEMSWAP_H_
+
+void mem_bswap_64(void *src, int byte_size);
+void mem_bswap_32(void *src, int byte_size);
+
+#endif /* PERF_MEMSWAP_H_ */
index 2b12bdb3ce33d0fbc9b8d5387fc5323153511b6e..7b79c413486b3a6ef8b0f6c32e330911c5ce7638 100644 (file)
@@ -28,7 +28,9 @@
 #include <linux/bitmap.h>
 #include <linux/time64.h>
 
-#include "../util.h"
+#include <stdbool.h>
+/* perl needs the following define, right after including stdbool.h */
+#define HAS_BOOL
 #include <EXTERN.h>
 #include <perl.h>
 
index 3041c6b9819152cdd8ad5e856c735d2c7073d903..7dc1096264c575cbbd1cd41d07f041585a997453 100644 (file)
@@ -11,6 +11,7 @@
 
 #include "evlist.h"
 #include "evsel.h"
+#include "memswap.h"
 #include "session.h"
 #include "tool.h"
 #include "sort.h"
index e91b5e86f0274c0cb3d9e5c44df5d2513e2564f5..aafe908b82b5720b4487c242370ed326ec520e2c 100644 (file)
@@ -3,15 +3,6 @@
 #include <linux/kernel.h>
 #include <errno.h>
 
-int prefixcmp(const char *str, const char *prefix)
-{
-       for (; ; str++, prefix++)
-               if (!*prefix)
-                       return 0;
-               else if (*str != *prefix)
-                       return (unsigned char)*prefix - (unsigned char)*str;
-}
-
 /*
  * Used as the default ->buf value, so that people can always assume
  * buf is non NULL and ->buf is NUL terminated even for a freshly
index 2cb7665e99739932e6d9330754f6fb8c67aa0c24..8f2b068ff7564900c989d1cdec96757c1b3ab45b 100644 (file)
@@ -90,6 +90,17 @@ static int prefix_underscores_count(const char *str)
        return tail - str;
 }
 
+int __weak arch__compare_symbol_names(const char *namea, const char *nameb)
+{
+       return strcmp(namea, nameb);
+}
+
+int __weak arch__compare_symbol_names_n(const char *namea, const char *nameb,
+                                       unsigned int n)
+{
+       return strncmp(namea, nameb, n);
+}
+
 int __weak arch__choose_best_symbol(struct symbol *syma,
                                    struct symbol *symb __maybe_unused)
 {
@@ -399,8 +410,26 @@ static void symbols__sort_by_name(struct rb_root *symbols,
        }
 }
 
+int symbol__match_symbol_name(const char *name, const char *str,
+                             enum symbol_tag_include includes)
+{
+       const char *versioning;
+
+       if (includes == SYMBOL_TAG_INCLUDE__DEFAULT_ONLY &&
+           (versioning = strstr(name, "@@"))) {
+               int len = strlen(str);
+
+               if (len < versioning - name)
+                       len = versioning - name;
+
+               return arch__compare_symbol_names_n(name, str, len);
+       } else
+               return arch__compare_symbol_names(name, str);
+}
+
 static struct symbol *symbols__find_by_name(struct rb_root *symbols,
-                                           const char *name)
+                                           const char *name,
+                                           enum symbol_tag_include includes)
 {
        struct rb_node *n;
        struct symbol_name_rb_node *s = NULL;
@@ -414,11 +443,11 @@ static struct symbol *symbols__find_by_name(struct rb_root *symbols,
                int cmp;
 
                s = rb_entry(n, struct symbol_name_rb_node, rb_node);
-               cmp = arch__compare_symbol_names(name, s->sym.name);
+               cmp = symbol__match_symbol_name(s->sym.name, name, includes);
 
-               if (cmp < 0)
+               if (cmp > 0)
                        n = n->rb_left;
-               else if (cmp > 0)
+               else if (cmp < 0)
                        n = n->rb_right;
                else
                        break;
@@ -427,16 +456,17 @@ static struct symbol *symbols__find_by_name(struct rb_root *symbols,
        if (n == NULL)
                return NULL;
 
-       /* return first symbol that has same name (if any) */
-       for (n = rb_prev(n); n; n = rb_prev(n)) {
-               struct symbol_name_rb_node *tmp;
+       if (includes != SYMBOL_TAG_INCLUDE__DEFAULT_ONLY)
+               /* return first symbol that has same name (if any) */
+               for (n = rb_prev(n); n; n = rb_prev(n)) {
+                       struct symbol_name_rb_node *tmp;
 
-               tmp = rb_entry(n, struct symbol_name_rb_node, rb_node);
-               if (arch__compare_symbol_names(tmp->sym.name, s->sym.name))
-                       break;
+                       tmp = rb_entry(n, struct symbol_name_rb_node, rb_node);
+                       if (arch__compare_symbol_names(tmp->sym.name, s->sym.name))
+                               break;
 
-               s = tmp;
-       }
+                       s = tmp;
+               }
 
        return &s->sym;
 }
@@ -466,7 +496,7 @@ void dso__insert_symbol(struct dso *dso, enum map_type type, struct symbol *sym)
 struct symbol *dso__find_symbol(struct dso *dso,
                                enum map_type type, u64 addr)
 {
-       if (dso->last_find_result[type].addr != addr) {
+       if (dso->last_find_result[type].addr != addr || dso->last_find_result[type].symbol == NULL) {
                dso->last_find_result[type].addr   = addr;
                dso->last_find_result[type].symbol = symbols__find(&dso->symbols[type], addr);
        }
@@ -503,7 +533,12 @@ struct symbol *symbol__next_by_name(struct symbol *sym)
 struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,
                                        const char *name)
 {
-       return symbols__find_by_name(&dso->symbol_names[type], name);
+       struct symbol *s = symbols__find_by_name(&dso->symbol_names[type], name,
+                                                SYMBOL_TAG_INCLUDE__NONE);
+       if (!s)
+               s = symbols__find_by_name(&dso->symbol_names[type], name,
+                                         SYMBOL_TAG_INCLUDE__DEFAULT_ONLY);
+       return s;
 }
 
 void dso__sort_by_name(struct dso *dso, enum map_type type)
@@ -1075,8 +1110,9 @@ static int validate_kcore_addresses(const char *kallsyms_filename,
        if (kmap->ref_reloc_sym && kmap->ref_reloc_sym->name) {
                u64 start;
 
-               start = kallsyms__get_function_start(kallsyms_filename,
-                                                    kmap->ref_reloc_sym->name);
+               if (kallsyms__get_function_start(kallsyms_filename,
+                                                kmap->ref_reloc_sym->name, &start))
+                       return -ENOENT;
                if (start != kmap->ref_reloc_sym->addr)
                        return -EINVAL;
        }
@@ -1248,9 +1284,7 @@ static int kallsyms__delta(struct map *map, const char *filename, u64 *delta)
        if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->name)
                return 0;
 
-       addr = kallsyms__get_function_start(filename,
-                                           kmap->ref_reloc_sym->name);
-       if (!addr)
+       if (kallsyms__get_function_start(filename, kmap->ref_reloc_sym->name, &addr))
                return -1;
 
        *delta = addr - kmap->ref_reloc_sym->addr;
index 7acd70fce68ef1ca7ecb6149a971184c6686dc5a..41ebba9a2eb2f3849635daf67125a851ff717d95 100644 (file)
@@ -348,8 +348,19 @@ void arch__sym_update(struct symbol *s, GElf_Sym *sym);
 #define SYMBOL_A 0
 #define SYMBOL_B 1
 
+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);
 int arch__choose_best_symbol(struct symbol *syma, struct symbol *symb);
 
+enum symbol_tag_include {
+       SYMBOL_TAG_INCLUDE__NONE = 0,
+       SYMBOL_TAG_INCLUDE__DEFAULT_ONLY
+};
+
+int symbol__match_symbol_name(const char *namea, const char *nameb,
+                             enum symbol_tag_include includes);
+
 /* structure containing an SDT note's info */
 struct sdt_note {
        char *name;                     /* name of the note*/
index f6a2a3d117d5857143ccc92508d370d8c32c64a0..4767ec2c5ef63cefbb03464fd244002ae6f5d54e 100644 (file)
@@ -1,8 +1,37 @@
 #include "units.h"
 #include <inttypes.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
 #include <linux/kernel.h>
 #include <linux/time64.h>
 
+unsigned long parse_tag_value(const char *str, struct parse_tag *tags)
+{
+       struct parse_tag *i = tags;
+
+       while (i->tag) {
+               char *s = strchr(str, i->tag);
+
+               if (s) {
+                       unsigned long int value;
+                       char *endptr;
+
+                       value = strtoul(str, &endptr, 10);
+                       if (s != endptr)
+                               break;
+
+                       if (value > ULONG_MAX / i->mult)
+                               break;
+                       value *= i->mult;
+                       return value;
+               }
+               i++;
+       }
+
+       return (unsigned long) -1;
+}
+
 unsigned long convert_unit(unsigned long value, char *unit)
 {
        *unit = ' ';
index 3ed7774afaa98b93f168659535f77eeacb4080b7..f02c87317150e0d5f50296b33bb29fd96b6b9edb 100644 (file)
@@ -4,6 +4,13 @@
 #include <stddef.h>
 #include <linux/types.h>
 
+struct parse_tag {
+       char tag;
+       int  mult;
+};
+
+unsigned long parse_tag_value(const char *str, struct parse_tag *tags);
+
 unsigned long convert_unit(unsigned long value, char *unit);
 int unit_number__scnprintf(char *buf, size_t size, u64 n);
 
index 6450c75a6f5b40bc28e9fe5f98cb98960cec1d10..28c9f335006c962a5df924e30d9a45687775c201 100644 (file)
@@ -13,7 +13,6 @@
 #include <string.h>
 #include <errno.h>
 #include <limits.h>
-#include <byteswap.h>
 #include <linux/kernel.h>
 #include <linux/log2.h>
 #include <linux/time64.h>
@@ -335,33 +334,6 @@ int hex2u64(const char *ptr, u64 *long_val)
        return p - ptr;
 }
 
-unsigned long parse_tag_value(const char *str, struct parse_tag *tags)
-{
-       struct parse_tag *i = tags;
-
-       while (i->tag) {
-               char *s;
-
-               s = strchr(str, i->tag);
-               if (s) {
-                       unsigned long int value;
-                       char *endptr;
-
-                       value = strtoul(str, &endptr, 10);
-                       if (s != endptr)
-                               break;
-
-                       if (value > ULONG_MAX / i->mult)
-                               break;
-                       value *= i->mult;
-                       return value;
-               }
-               i++;
-       }
-
-       return (unsigned long) -1;
-}
-
 int perf_event_paranoid(void)
 {
        int value;
@@ -372,27 +344,6 @@ int perf_event_paranoid(void)
        return value;
 }
 
-void mem_bswap_32(void *src, int byte_size)
-{
-       u32 *m = src;
-       while (byte_size > 0) {
-               *m = bswap_32(*m);
-               byte_size -= sizeof(u32);
-               ++m;
-       }
-}
-
-void mem_bswap_64(void *src, int byte_size)
-{
-       u64 *m = src;
-
-       while (byte_size > 0) {
-               *m = bswap_64(*m);
-               byte_size -= sizeof(u64);
-               ++m;
-       }
-}
-
 bool find_process(const char *name)
 {
        size_t len = strlen(name);
index 3852b6d3270a06067560d3f854aa29c8289854b8..5dfb9bb6482d3103d494a9234fef50b308b3d7ef 100644 (file)
@@ -5,7 +5,6 @@
 #define _BSD_SOURCE 1
 /* glibc 2.20 deprecates _BSD_SOURCE in favour of _DEFAULT_SOURCE */
 #define _DEFAULT_SOURCE 1
-#define HAS_BOOL
 
 #include <fcntl.h>
 #include <stdbool.h>
@@ -14,8 +13,6 @@
 #include <stdarg.h>
 #include <linux/types.h>
 
-extern char buildid_dir[];
-
 #ifdef __GNUC__
 #define NORETURN __attribute__((__noreturn__))
 #else
@@ -25,8 +22,6 @@ extern char buildid_dir[];
 #endif
 #endif
 
-#define PERF_GTK_DSO  "libperf-gtk.so"
-
 /* General helper functions */
 void usage(const char *err) NORETURN;
 void die(const char *err, ...) NORETURN __attribute__((format (printf, 1, 2)));
@@ -35,9 +30,6 @@ void warning(const char *err, ...) __attribute__((format (printf, 1, 2)));
 
 void set_warning_routine(void (*routine)(const char *err, va_list params));
 
-int prefixcmp(const char *str, const char *prefix);
-void set_buildid_dir(const char *dir);
-
 static inline void *zalloc(size_t size)
 {
        return calloc(1, size);
@@ -59,29 +51,11 @@ int copyfile_offset(int fromfd, loff_t from_ofs, int tofd, loff_t to_ofs, u64 si
 ssize_t readn(int fd, void *buf, size_t n);
 ssize_t writen(int fd, void *buf, size_t n);
 
-struct perf_event_attr;
-
-void event_attr_init(struct perf_event_attr *attr);
-
 size_t hex_width(u64 v);
 int hex2u64(const char *ptr, u64 *val);
 
 extern unsigned int page_size;
 extern int cacheline_size;
-extern int sysctl_perf_event_max_stack;
-extern int sysctl_perf_event_max_contexts_per_stack;
-
-struct parse_tag {
-       char tag;
-       int mult;
-};
-
-unsigned long parse_tag_value(const char *str, struct parse_tag *tags);
-
-int perf_event_paranoid(void);
-
-void mem_bswap_64(void *src, int byte_size);
-void mem_bswap_32(void *src, int byte_size);
 
 bool find_process(const char *name);
 
index f0600d20ce7d6f305d5d02b477fa804fcec91935..91750352459dfd9c3cc2bb81f99f5f9ef74ed7f3 100644 (file)
@@ -1 +1,5 @@
 kselftest
+gpiogpio-event-mon
+gpiogpio-hammer
+gpioinclude/
+gpiolsgpio
index d8593f1251ecce4c750fc54086ba3fc2b0b7c90a..26ce4f7168be534de2eef4be6650de9617b03b33 100644 (file)
@@ -39,7 +39,7 @@ TARGETS += x86
 TARGETS += zram
 #Please keep the TARGETS list alphabetically sorted
 # Run "make quicktest=1 run_tests" or
-# "make quicktest=1 kselftest from top level Makefile
+# "make quicktest=1 kselftest" from top level Makefile
 
 TARGETS_HOTPLUG = cpu-hotplug
 TARGETS_HOTPLUG += memory-hotplug
@@ -133,4 +133,4 @@ clean:
                make OUTPUT=$$BUILD_TARGET -C $$TARGET clean;\
        done;
 
-.PHONY: install
+.PHONY: all run_tests hotplug run_hotplug clean_hotplug run_pstore_crash install clean
index 91edd056623789fb5585bd774b6d98eb5dba1cc2..f389b02d43a004e90aed9acd68148875af3beba2 100644 (file)
@@ -11,7 +11,8 @@ endif
 CFLAGS += -Wall -O2 -I$(APIDIR) -I$(LIBDIR) -I$(GENDIR) $(GENFLAGS) -I../../../include
 LDLIBS += -lcap -lelf
 
-TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test_progs
+TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test_progs \
+       test_align
 
 TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o
 
@@ -34,6 +35,7 @@ $(BPFOBJ): force
 CLANG ?= clang
 
 %.o: %.c
-       $(CLANG) -I. -I../../../include/uapi -I../../../../samples/bpf/ \
+       $(CLANG) -I. -I./include/uapi -I../../../include/uapi \
+               -I../../../../samples/bpf/ \
                -Wno-compare-distinct-pointer-types \
                -O2 -target bpf -c $< -o $@
diff --git a/tools/testing/selftests/bpf/include/uapi/linux/types.h b/tools/testing/selftests/bpf/include/uapi/linux/types.h
new file mode 100644 (file)
index 0000000..5184184
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef _UAPI_LINUX_TYPES_H
+#define _UAPI_LINUX_TYPES_H
+
+#include <asm-generic/int-ll64.h>
+
+/* copied from linux:include/uapi/linux/types.h */
+#define __bitwise
+typedef __u16 __bitwise __le16;
+typedef __u16 __bitwise __be16;
+typedef __u32 __bitwise __le32;
+typedef __u32 __bitwise __be32;
+typedef __u64 __bitwise __le64;
+typedef __u64 __bitwise __be64;
+
+typedef __u16 __bitwise __sum16;
+typedef __u32 __bitwise __wsum;
+
+#define __aligned_u64 __u64 __attribute__((aligned(8)))
+#define __aligned_be64 __be64 __attribute__((aligned(8)))
+#define __aligned_le64 __le64 __attribute__((aligned(8)))
+
+#endif /* _UAPI_LINUX_TYPES_H */
diff --git a/tools/testing/selftests/bpf/test_align.c b/tools/testing/selftests/bpf/test_align.c
new file mode 100644 (file)
index 0000000..9644d4e
--- /dev/null
@@ -0,0 +1,453 @@
+#include <asm/types.h>
+#include <linux/types.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <stddef.h>
+#include <stdbool.h>
+
+#include <linux/unistd.h>
+#include <linux/filter.h>
+#include <linux/bpf_perf_event.h>
+#include <linux/bpf.h>
+
+#include <bpf/bpf.h>
+
+#include "../../../include/linux/filter.h"
+
+#ifndef ARRAY_SIZE
+# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+#endif
+
+#define MAX_INSNS      512
+#define MAX_MATCHES    16
+
+struct bpf_align_test {
+       const char *descr;
+       struct bpf_insn insns[MAX_INSNS];
+       enum {
+               UNDEF,
+               ACCEPT,
+               REJECT
+       } result;
+       enum bpf_prog_type prog_type;
+       const char *matches[MAX_MATCHES];
+};
+
+static struct bpf_align_test tests[] = {
+       {
+               .descr = "mov",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_3, 2),
+                       BPF_MOV64_IMM(BPF_REG_3, 4),
+                       BPF_MOV64_IMM(BPF_REG_3, 8),
+                       BPF_MOV64_IMM(BPF_REG_3, 16),
+                       BPF_MOV64_IMM(BPF_REG_3, 32),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+               .matches = {
+                       "1: R1=ctx R3=imm2,min_value=2,max_value=2,min_align=2 R10=fp",
+                       "2: R1=ctx R3=imm4,min_value=4,max_value=4,min_align=4 R10=fp",
+                       "3: R1=ctx R3=imm8,min_value=8,max_value=8,min_align=8 R10=fp",
+                       "4: R1=ctx R3=imm16,min_value=16,max_value=16,min_align=16 R10=fp",
+                       "5: R1=ctx R3=imm32,min_value=32,max_value=32,min_align=32 R10=fp",
+               },
+       },
+       {
+               .descr = "shift",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_3, 1),
+                       BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
+                       BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
+                       BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
+                       BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
+                       BPF_ALU64_IMM(BPF_RSH, BPF_REG_3, 4),
+                       BPF_MOV64_IMM(BPF_REG_4, 32),
+                       BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
+                       BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
+                       BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
+                       BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+               .matches = {
+                       "1: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R10=fp",
+                       "2: R1=ctx R3=imm2,min_value=2,max_value=2,min_align=2 R10=fp",
+                       "3: R1=ctx R3=imm4,min_value=4,max_value=4,min_align=4 R10=fp",
+                       "4: R1=ctx R3=imm8,min_value=8,max_value=8,min_align=8 R10=fp",
+                       "5: R1=ctx R3=imm16,min_value=16,max_value=16,min_align=16 R10=fp",
+                       "6: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R10=fp",
+                       "7: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm32,min_value=32,max_value=32,min_align=32 R10=fp",
+                       "8: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm16,min_value=16,max_value=16,min_align=16 R10=fp",
+                       "9: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm8,min_value=8,max_value=8,min_align=8 R10=fp",
+                       "10: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm4,min_value=4,max_value=4,min_align=4 R10=fp",
+                       "11: R1=ctx R3=imm1,min_value=1,max_value=1,min_align=1 R4=imm2,min_value=2,max_value=2,min_align=2 R10=fp",
+               },
+       },
+       {
+               .descr = "addsub",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_3, 4),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 4),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_3, 2),
+                       BPF_MOV64_IMM(BPF_REG_4, 8),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 2),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+               .matches = {
+                       "1: R1=ctx R3=imm4,min_value=4,max_value=4,min_align=4 R10=fp",
+                       "2: R1=ctx R3=imm8,min_value=8,max_value=8,min_align=4 R10=fp",
+                       "3: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R10=fp",
+                       "4: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R4=imm8,min_value=8,max_value=8,min_align=8 R10=fp",
+                       "5: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R4=imm12,min_value=12,max_value=12,min_align=4 R10=fp",
+                       "6: R1=ctx R3=imm10,min_value=10,max_value=10,min_align=2 R4=imm14,min_value=14,max_value=14,min_align=2 R10=fp",
+               },
+       },
+       {
+               .descr = "mul",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_3, 7),
+                       BPF_ALU64_IMM(BPF_MUL, BPF_REG_3, 1),
+                       BPF_ALU64_IMM(BPF_MUL, BPF_REG_3, 2),
+                       BPF_ALU64_IMM(BPF_MUL, BPF_REG_3, 4),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+               .matches = {
+                       "1: R1=ctx R3=imm7,min_value=7,max_value=7,min_align=1 R10=fp",
+                       "2: R1=ctx R3=imm7,min_value=7,max_value=7,min_align=1 R10=fp",
+                       "3: R1=ctx R3=imm14,min_value=14,max_value=14,min_align=2 R10=fp",
+                       "4: R1=ctx R3=imm56,min_value=56,max_value=56,min_align=4 R10=fp",
+               },
+       },
+
+#define PREP_PKT_POINTERS \
+       BPF_LDX_MEM(BPF_W, BPF_REG_2, BPF_REG_1, \
+                   offsetof(struct __sk_buff, data)), \
+       BPF_LDX_MEM(BPF_W, BPF_REG_3, BPF_REG_1, \
+                   offsetof(struct __sk_buff, data_end))
+
+#define LOAD_UNKNOWN(DST_REG) \
+       PREP_PKT_POINTERS, \
+       BPF_MOV64_REG(BPF_REG_0, BPF_REG_2), \
+       BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 8), \
+       BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_0, 1), \
+       BPF_EXIT_INSN(), \
+       BPF_LDX_MEM(BPF_B, DST_REG, BPF_REG_2, 0)
+
+       {
+               .descr = "unknown shift",
+               .insns = {
+                       LOAD_UNKNOWN(BPF_REG_3),
+                       BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
+                       BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
+                       BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
+                       BPF_ALU64_IMM(BPF_LSH, BPF_REG_3, 1),
+                       LOAD_UNKNOWN(BPF_REG_4),
+                       BPF_ALU64_IMM(BPF_LSH, BPF_REG_4, 5),
+                       BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
+                       BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
+                       BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
+                       BPF_ALU64_IMM(BPF_RSH, BPF_REG_4, 1),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+               .matches = {
+                       "7: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R10=fp",
+                       "8: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv55,min_align=2 R10=fp",
+                       "9: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv54,min_align=4 R10=fp",
+                       "10: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv53,min_align=8 R10=fp",
+                       "11: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv52,min_align=16 R10=fp",
+                       "18: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv56 R10=fp",
+                       "19: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv51,min_align=32 R10=fp",
+                       "20: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv52,min_align=16 R10=fp",
+                       "21: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv53,min_align=8 R10=fp",
+                       "22: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv54,min_align=4 R10=fp",
+                       "23: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv55,min_align=2 R10=fp",
+               },
+       },
+       {
+               .descr = "unknown mul",
+               .insns = {
+                       LOAD_UNKNOWN(BPF_REG_3),
+                       BPF_MOV64_REG(BPF_REG_4, BPF_REG_3),
+                       BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 1),
+                       BPF_MOV64_REG(BPF_REG_4, BPF_REG_3),
+                       BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 2),
+                       BPF_MOV64_REG(BPF_REG_4, BPF_REG_3),
+                       BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 4),
+                       BPF_MOV64_REG(BPF_REG_4, BPF_REG_3),
+                       BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 8),
+                       BPF_ALU64_IMM(BPF_MUL, BPF_REG_4, 2),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+               .matches = {
+                       "7: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R10=fp",
+                       "8: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp",
+                       "9: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv55,min_align=1 R10=fp",
+                       "10: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp",
+                       "11: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv54,min_align=2 R10=fp",
+                       "12: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp",
+                       "13: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv53,min_align=4 R10=fp",
+                       "14: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv56 R10=fp",
+                       "15: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv52,min_align=8 R10=fp",
+                       "16: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=inv56 R4=inv50,min_align=8 R10=fp"
+               },
+       },
+       {
+               .descr = "packet const offset",
+               .insns = {
+                       PREP_PKT_POINTERS,
+                       BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
+
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+
+                       /* Skip over ethernet header.  */
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14),
+                       BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
+                       BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
+                       BPF_EXIT_INSN(),
+
+                       BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 0),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 1),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 2),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_4, BPF_REG_5, 3),
+                       BPF_LDX_MEM(BPF_H, BPF_REG_4, BPF_REG_5, 0),
+                       BPF_LDX_MEM(BPF_H, BPF_REG_4, BPF_REG_5, 2),
+                       BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0),
+
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+               .matches = {
+                       "4: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=0) R3=pkt_end R5=pkt(id=0,off=0,r=0) R10=fp",
+                       "5: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=0) R3=pkt_end R5=pkt(id=0,off=14,r=0) R10=fp",
+                       "6: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=0) R3=pkt_end R4=pkt(id=0,off=14,r=0) R5=pkt(id=0,off=14,r=0) R10=fp",
+                       "10: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=18) R3=pkt_end R4=inv56 R5=pkt(id=0,off=14,r=18) R10=fp",
+                       "14: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=18) R3=pkt_end R4=inv48 R5=pkt(id=0,off=14,r=18) R10=fp",
+                       "15: R0=imm0,min_value=0,max_value=0,min_align=2147483648 R1=ctx R2=pkt(id=0,off=0,r=18) R3=pkt_end R4=inv48 R5=pkt(id=0,off=14,r=18) R10=fp",
+               },
+       },
+       {
+               .descr = "packet variable offset",
+               .insns = {
+                       LOAD_UNKNOWN(BPF_REG_6),
+                       BPF_ALU64_IMM(BPF_LSH, BPF_REG_6, 2),
+
+                       /* First, add a constant to the R5 packet pointer,
+                        * then a variable with a known alignment.
+                        */
+                       BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14),
+                       BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
+                       BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
+                       BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
+                       BPF_EXIT_INSN(),
+                       BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0),
+
+                       /* Now, test in the other direction.  Adding first
+                        * the variable offset to R5, then the constant.
+                        */
+                       BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
+                       BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14),
+                       BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
+                       BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
+                       BPF_EXIT_INSN(),
+                       BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0),
+
+                       /* Test multiple accumulations of unknown values
+                        * into a packet pointer.
+                        */
+                       BPF_MOV64_REG(BPF_REG_5, BPF_REG_2),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 14),
+                       BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_5, 4),
+                       BPF_ALU64_REG(BPF_ADD, BPF_REG_5, BPF_REG_6),
+                       BPF_MOV64_REG(BPF_REG_4, BPF_REG_5),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_4, 4),
+                       BPF_JMP_REG(BPF_JGE, BPF_REG_3, BPF_REG_4, 1),
+                       BPF_EXIT_INSN(),
+                       BPF_LDX_MEM(BPF_W, BPF_REG_4, BPF_REG_5, 0),
+
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .prog_type = BPF_PROG_TYPE_SCHED_CLS,
+               .matches = {
+                       /* Calculated offset in R6 has unknown value, but known
+                        * alignment of 4.
+                        */
+                       "8: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R6=inv54,min_align=4 R10=fp",
+
+                       /* Offset is added to packet pointer R5, resulting in known
+                        * auxiliary alignment and offset.
+                        */
+                       "11: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R5=pkt(id=1,off=0,r=0),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
+
+                       /* At the time the word size load is performed from R5,
+                        * it's total offset is NET_IP_ALIGN + reg->off (0) +
+                        * reg->aux_off (14) which is 16.  Then the variable
+                        * offset is considered using reg->aux_off_align which
+                        * is 4 and meets the load's requirements.
+                        */
+                       "15: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=pkt(id=1,off=4,r=4),aux_off=14,aux_off_align=4 R5=pkt(id=1,off=0,r=4),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
+
+
+                       /* Variable offset is added to R5 packet pointer,
+                        * resulting in auxiliary alignment of 4.
+                        */
+                       "18: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off=14,aux_off_align=4 R5=pkt(id=2,off=0,r=0),aux_off_align=4 R6=inv54,min_align=4 R10=fp",
+
+                       /* Constant offset is added to R5, resulting in
+                        * reg->off of 14.
+                        */
+                       "19: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off=14,aux_off_align=4 R5=pkt(id=2,off=14,r=0),aux_off_align=4 R6=inv54,min_align=4 R10=fp",
+
+                       /* At the time the word size load is performed from R5,
+                        * it's total offset is NET_IP_ALIGN + reg->off (14) which
+                        * is 16.  Then the variable offset is considered using
+                        * reg->aux_off_align which is 4 and meets the load's
+                        * requirements.
+                        */
+                       "23: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=pkt(id=2,off=18,r=18),aux_off_align=4 R5=pkt(id=2,off=14,r=18),aux_off_align=4 R6=inv54,min_align=4 R10=fp",
+
+                       /* Constant offset is added to R5 packet pointer,
+                        * resulting in reg->off value of 14.
+                        */
+                       "26: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=0,off=14,r=8) R6=inv54,min_align=4 R10=fp",
+                       /* Variable offset is added to R5, resulting in an
+                        * auxiliary offset of 14, and an auxiliary alignment of 4.
+                        */
+                       "27: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=3,off=0,r=0),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
+                       /* Constant is added to R5 again, setting reg->off to 4. */
+                       "28: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=3,off=4,r=0),aux_off=14,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
+                       /* And once more we add a variable, which causes an accumulation
+                        * of reg->off into reg->aux_off_align, with resulting value of
+                        * 18.  The auxiliary alignment stays at 4.
+                        */
+                       "29: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=inv,aux_off_align=4 R5=pkt(id=4,off=0,r=0),aux_off=18,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
+                       /* At the time the word size load is performed from R5,
+                        * it's total offset is NET_IP_ALIGN + reg->off (0) +
+                        * reg->aux_off (18) which is 20.  Then the variable offset
+                        * is considered using reg->aux_off_align which is 4 and meets
+                        * the load's requirements.
+                        */
+                       "33: R0=pkt(id=0,off=8,r=8) R1=ctx R2=pkt(id=0,off=0,r=8) R3=pkt_end R4=pkt(id=4,off=4,r=4),aux_off=18,aux_off_align=4 R5=pkt(id=4,off=0,r=4),aux_off=18,aux_off_align=4 R6=inv54,min_align=4 R10=fp",
+               },
+       },
+};
+
+static int probe_filter_length(const struct bpf_insn *fp)
+{
+       int len;
+
+       for (len = MAX_INSNS - 1; len > 0; --len)
+               if (fp[len].code != 0 || fp[len].imm != 0)
+                       break;
+       return len + 1;
+}
+
+static char bpf_vlog[32768];
+
+static int do_test_single(struct bpf_align_test *test)
+{
+       struct bpf_insn *prog = test->insns;
+       int prog_type = test->prog_type;
+       int prog_len, i;
+       int fd_prog;
+       int ret;
+
+       prog_len = probe_filter_length(prog);
+       fd_prog = bpf_verify_program(prog_type ? : BPF_PROG_TYPE_SOCKET_FILTER,
+                                    prog, prog_len, 1, "GPL", 0,
+                                    bpf_vlog, sizeof(bpf_vlog));
+       if (fd_prog < 0) {
+               printf("Failed to load program.\n");
+               printf("%s", bpf_vlog);
+               ret = 1;
+       } else {
+               ret = 0;
+               for (i = 0; i < MAX_MATCHES; i++) {
+                       const char *t, *m = test->matches[i];
+
+                       if (!m)
+                               break;
+                       t = strstr(bpf_vlog, m);
+                       if (!t) {
+                               printf("Failed to find match: %s\n", m);
+                               ret = 1;
+                               printf("%s", bpf_vlog);
+                               break;
+                       }
+               }
+               close(fd_prog);
+       }
+       return ret;
+}
+
+static int do_test(unsigned int from, unsigned int to)
+{
+       int all_pass = 0;
+       int all_fail = 0;
+       unsigned int i;
+
+       for (i = from; i < to; i++) {
+               struct bpf_align_test *test = &tests[i];
+               int fail;
+
+               printf("Test %3d: %s ... ",
+                      i, test->descr);
+               fail = do_test_single(test);
+               if (fail) {
+                       all_fail++;
+                       printf("FAIL\n");
+               } else {
+                       all_pass++;
+                       printf("PASS\n");
+               }
+       }
+       printf("Results: %d pass %d fail\n",
+              all_pass, all_fail);
+       return 0;
+}
+
+int main(int argc, char **argv)
+{
+       unsigned int from = 0, to = ARRAY_SIZE(tests);
+
+       if (argc == 3) {
+               unsigned int l = atoi(argv[argc - 2]);
+               unsigned int u = atoi(argv[argc - 1]);
+
+               if (l < to && u < to) {
+                       from = l;
+                       to   = u + 1;
+               }
+       } else if (argc == 2) {
+               unsigned int t = atoi(argv[argc - 1]);
+
+               if (t < to) {
+                       from = t;
+                       to   = t + 1;
+               }
+       }
+       return do_test(from, to);
+}
index 39387bb7e08ca79be1ebd94452c0c126abd2316c..6e11ba11709e5cfcba232be08e706622515cdcef 100644 (file)
@@ -5,6 +5,7 @@
  * License as published by the Free Software Foundation.
  */
 #include <stddef.h>
+#include <string.h>
 #include <linux/bpf.h>
 #include <linux/if_ether.h>
 #include <linux/if_packet.h>
index 72aa103e4141d3b252c00a8bcf680edc4cd2dfbb..6b214b7b10fb7c1c7ad6330c3769fbd1c46838d7 100644 (file)
@@ -5,7 +5,7 @@ ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/)
 ifeq ($(ARCH),x86)
 TEST_GEN_PROGS := breakpoint_test
 endif
-ifeq ($(ARCH),aarch64)
+ifneq (,$(filter $(ARCH),aarch64 arm64))
 TEST_GEN_PROGS := breakpoint_test_arm64
 endif
 
diff --git a/tools/testing/selftests/cpufreq/config b/tools/testing/selftests/cpufreq/config
new file mode 100644 (file)
index 0000000..27ff72e
--- /dev/null
@@ -0,0 +1,15 @@
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_PI_LIST=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_LOCK_ALLOC=y
+CONFIG_PROVE_LOCKING=y
+CONFIG_LOCKDEP=y
+CONFIG_DEBUG_ATOMIC_SLEEP=y
index ef8214661612f892070a3eaa788779e11235c600..8a1c9f949fe082889aa4057ed1886c16249ef2b9 100644 (file)
@@ -1 +1,2 @@
+CONFIG_KPROBES=y
 CONFIG_FTRACE=y
index 0a78705b43b258a84195a038482ce6b0f4837778..c75faefb4fffcb617383f9aebab0d40270f58743 100644 (file)
@@ -26,7 +26,7 @@ check_types() {
   test $X2 = $X3
   test 0x$X3 = $3
 
-  B4=`printf "%x" $4`
+  B4=`printf "%02x" $4`
   B3=`echo -n $X3 | tail -c 3 | head -c 2`
   test $B3 = $B4
 }
index 653c5cd9e44d6bc4fba89b79ae8d1d707993e542..e2fbb890aef9549281318a4241a2e5a8ad68b9d1 100644 (file)
@@ -8,7 +8,7 @@ include ../lib.mk
 
 all:
        for DIR in $(SUBDIRS); do               \
-               BUILD_TARGET=$$OUTPUT/$$DIR;    \
+               BUILD_TARGET=$(OUTPUT)/$$DIR;   \
                mkdir $$BUILD_TARGET  -p;       \
                make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\
        done
@@ -22,7 +22,7 @@ override define INSTALL_RULE
        install -t $(INSTALL_PATH) $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES)
 
        @for SUBDIR in $(SUBDIRS); do \
-               BUILD_TARGET=$$OUTPUT/$$SUBDIR; \
+               BUILD_TARGET=$(OUTPUT)/$$SUBDIR;        \
                mkdir $$BUILD_TARGET  -p;       \
                $(MAKE) OUTPUT=$$BUILD_TARGET -C $$SUBDIR INSTALL_PATH=$(INSTALL_PATH)/$$SUBDIR install; \
        done;
@@ -32,9 +32,10 @@ override define EMIT_TESTS
        echo "./run.sh"
 endef
 
-clean:
+override define CLEAN
        for DIR in $(SUBDIRS); do               \
-               BUILD_TARGET=$$OUTPUT/$$DIR;    \
+               BUILD_TARGET=$(OUTPUT)/$$DIR;   \
                mkdir $$BUILD_TARGET  -p;       \
                make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\
        done
+endef
index 205e4d10e0853c7b8d20342b21111a8693701834..298929df97e695b5be640a47d51b84d173f5da5f 100644 (file)
@@ -2,13 +2,20 @@
 TEST_PROGS := gpio-mockup.sh
 TEST_FILES := gpio-mockup-sysfs.sh $(BINARIES)
 BINARIES := gpio-mockup-chardev
+EXTRA_PROGS := ../gpiogpio-event-mon ../gpiogpio-hammer ../gpiolsgpio
+EXTRA_DIRS := ../gpioinclude/
+EXTRA_OBJS := ../gpiogpio-event-mon-in.o ../gpiogpio-event-mon.o
+EXTRA_OBJS += ../gpiogpio-hammer-in.o ../gpiogpio-utils.o ../gpiolsgpio-in.o
+EXTRA_OBJS += ../gpiolsgpio.o
 
 include ../lib.mk
 
 all: $(BINARIES)
 
-clean:
-       $(RM) $(BINARIES)
+override define CLEAN
+       $(RM) $(BINARIES) $(EXTRA_PROGS) $(EXTRA_OBJS)
+       $(RM) -r $(EXTRA_DIRS)
+endef
 
 CFLAGS += -O2 -g -std=gnu99 -Wall -I../../../../usr/include/
 LDLIBS += -lmount -I/usr/include/libmount
diff --git a/tools/testing/selftests/gpio/config b/tools/testing/selftests/gpio/config
new file mode 100644 (file)
index 0000000..abaa690
--- /dev/null
@@ -0,0 +1,2 @@
+CONFIG_GPIOLIB=y
+CONFIG_GPIO_MOCKUP=m
index 775c589ac3c0a24f470a8f53ae52f6c82cc17193..959273c3a52e10f5895735b047a3de389e4f161a 100644 (file)
@@ -51,8 +51,12 @@ endef
 emit_tests:
        $(EMIT_TESTS)
 
-clean:
+define CLEAN
        $(RM) -r $(TEST_GEN_PROGS) $(TEST_GEN_PROGS_EXTENDED) $(TEST_GEN_FILES) $(EXTRA_CLEAN)
+endef
+
+clean:
+       $(CLEAN)
 
 $(OUTPUT)/%:%.c
        $(LINK.c) $^ $(LDLIBS) -o $@
diff --git a/tools/testing/selftests/lib/config b/tools/testing/selftests/lib/config
new file mode 100644 (file)
index 0000000..126933b
--- /dev/null
@@ -0,0 +1,3 @@
+CONFIG_TEST_PRINTF=m
+CONFIG_TEST_BITMAP=m
+CONFIG_PRIME_NUMBERS=m
index 03e1617367d35a3306e2e71bed076393a89f5051..72c3ac2323e15faaeaf2d160063facfa74323a7c 100644 (file)
@@ -60,12 +60,13 @@ override define EMIT_TESTS
        done;
 endef
 
-clean:
+override define CLEAN
        @for TARGET in $(SUB_DIRS); do \
                BUILD_TARGET=$(OUTPUT)/$$TARGET;        \
                $(MAKE) OUTPUT=$$BUILD_TARGET -C $$TARGET clean; \
        done;
        rm -f tags
+endef
 
 tags:
        find . -name '*.c' -o -name '*.h' | xargs ctags
index 427621792229e68c7fcdaff89f28782bda14c1da..2f1f7b013293491b2845f68fa03dbc591c8d5412 100644 (file)
@@ -11,3 +11,4 @@ tm-signal-context-chk-fpu
 tm-signal-context-chk-gpr
 tm-signal-context-chk-vmx
 tm-signal-context-chk-vsx
+tm-vmx-unavail
index 5576ee6a51f21bb32a0ede4337d9da049e37fd42..958c11c14acd017a6c3afe79f02d9c6e8fad2240 100644 (file)
@@ -2,7 +2,8 @@ SIGNAL_CONTEXT_CHK_TESTS := tm-signal-context-chk-gpr tm-signal-context-chk-fpu
        tm-signal-context-chk-vmx tm-signal-context-chk-vsx
 
 TEST_GEN_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack \
-       tm-vmxcopy tm-fork tm-tar tm-tmspr $(SIGNAL_CONTEXT_CHK_TESTS)
+       tm-vmxcopy tm-fork tm-tar tm-tmspr tm-vmx-unavail \
+       $(SIGNAL_CONTEXT_CHK_TESTS)
 
 include ../../lib.mk
 
@@ -13,6 +14,7 @@ CFLAGS += -mhtm
 $(OUTPUT)/tm-syscall: tm-syscall-asm.S
 $(OUTPUT)/tm-syscall: CFLAGS += -I../../../../../usr/include
 $(OUTPUT)/tm-tmspr: CFLAGS += -pthread
+$(OUTPUT)/tm-vmx-unavail: CFLAGS += -pthread -m64
 
 SIGNAL_CONTEXT_CHK_TESTS := $(patsubst %,$(OUTPUT)/%,$(SIGNAL_CONTEXT_CHK_TESTS))
 $(SIGNAL_CONTEXT_CHK_TESTS): tm-signal.S
diff --git a/tools/testing/selftests/powerpc/tm/tm-vmx-unavail.c b/tools/testing/selftests/powerpc/tm/tm-vmx-unavail.c
new file mode 100644 (file)
index 0000000..137185b
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2017, Michael Neuling, IBM Corp.
+ * Licensed under GPLv2.
+ * Original: Breno Leitao <brenohl@br.ibm.com> &
+ *           Gustavo Bueno Romero <gromero@br.ibm.com>
+ * Edited: Michael Neuling
+ *
+ * Force VMX unavailable during a transaction and see if it corrupts
+ * the checkpointed VMX register state after the abort.
+ */
+
+#include <inttypes.h>
+#include <htmintrin.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <pthread.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <pthread.h>
+
+#include "tm.h"
+#include "utils.h"
+
+int passed;
+
+void *worker(void *unused)
+{
+       __int128 vmx0;
+       uint64_t texasr;
+
+       asm goto (
+               "li       3, 1;"  /* Stick non-zero value in VMX0 */
+               "std      3, 0(%[vmx0_ptr]);"
+               "lvx      0, 0, %[vmx0_ptr];"
+
+               /* Wait here a bit so we get scheduled out 255 times */
+               "lis      3, 0x3fff;"
+               "1: ;"
+               "addi     3, 3, -1;"
+               "cmpdi    3, 0;"
+               "bne      1b;"
+
+               /* Kernel will hopefully turn VMX off now */
+
+               "tbegin. ;"
+               "beq      failure;"
+
+               /* Cause VMX unavail. Any VMX instruction */
+               "vaddcuw  0,0,0;"
+
+               "tend. ;"
+               "b        %l[success];"
+
+               /* Check VMX0 sanity after abort */
+               "failure: ;"
+               "lvx       1,  0, %[vmx0_ptr];"
+               "vcmpequb. 2,  0, 1;"
+               "bc        4, 24, %l[value_mismatch];"
+               "b        %l[value_match];"
+               :
+               : [vmx0_ptr] "r"(&vmx0)
+               : "r3"
+               : success, value_match, value_mismatch
+               );
+
+       /* HTM aborted and VMX0 is corrupted */
+value_mismatch:
+       texasr = __builtin_get_texasr();
+
+       printf("\n\n==============\n\n");
+       printf("Failure with error: %lx\n",   _TEXASR_FAILURE_CODE(texasr));
+       printf("Summary error     : %lx\n",   _TEXASR_FAILURE_SUMMARY(texasr));
+       printf("TFIAR exact       : %lx\n\n", _TEXASR_TFIAR_EXACT(texasr));
+
+       passed = 0;
+       return NULL;
+
+       /* HTM aborted but VMX0 is correct */
+value_match:
+//     printf("!");
+       return NULL;
+
+success:
+//     printf(".");
+       return NULL;
+}
+
+int tm_vmx_unavail_test()
+{
+       int threads;
+       pthread_t *thread;
+
+       SKIP_IF(!have_htm());
+
+       passed = 1;
+
+       threads = sysconf(_SC_NPROCESSORS_ONLN) * 4;
+       thread = malloc(sizeof(pthread_t)*threads);
+       if (!thread)
+               return EXIT_FAILURE;
+
+       for (uint64_t i = 0; i < threads; i++)
+               pthread_create(&thread[i], NULL, &worker, NULL);
+
+       for (uint64_t i = 0; i < threads; i++)
+               pthread_join(thread[i], NULL);
+
+       free(thread);
+
+       return passed ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
+
+int main(int argc, char **argv)
+{
+       return test_harness(tm_vmx_unavail_test, "tm_vmx_unavail_test");
+}
index ea6e373edc27255efe7dccccd86b12b9eb97c189..93eede4e8fbea050ce79bf67a1f04807acd53a31 100755 (executable)
@@ -170,7 +170,7 @@ qemu_append="`identify_qemu_append "$QEMU"`"
 # Pull in Kconfig-fragment boot parameters
 boot_args="`configfrag_boot_params "$boot_args" "$config_template"`"
 # Generate kernel-version-specific boot parameters
-boot_args="`per_version_boot_params "$boot_args" $builddir/.config $seconds`"
+boot_args="`per_version_boot_params "$boot_args" $resdir/.config $seconds`"
 
 if test -n "$TORTURE_BUILDONLY"
 then
index de51f439d4a6a3832755c8272d608566a04f6c93..9fc78e5e5451038dd0ce4b0c4fa25a95e7707249 100644 (file)
@@ -4,5 +4,4 @@ all: $(TEST_PROGS) $(EXTRA)
 
 include ../lib.mk
 
-clean:
-       rm -fr $(TEST_PROGS) $(EXTRA)
+EXTRA_CLEAN := $(EXTRA)
index 87ac400507c005db3affec4a395f49960b1126ef..4981c6b6d050e95b77fa1540640a4b71770179f2 100644 (file)
@@ -20,5 +20,4 @@ TESTS += sync_stress_merge.o
 
 sync_test: $(OBJS) $(TESTS)
 
-clean:
-       $(RM) sync_test $(OBJS) $(TESTS)
+EXTRA_CLEAN := sync_test $(OBJS) $(TESTS)
index fd88e3025bedc17d44c1537b8279aa6068d3ff47..5ff165373f8ba1b51502ca28a7d0324dc671a4e9 100644 (file)
@@ -159,7 +159,7 @@ int main(int argv, char **argc)
        }
 
 
-       printf("Running Asyncrhonous Switching Tests...\n");
+       printf("Running Asynchronous Switching Tests...\n");
        pid = fork();
        if (!pid)
                return run_tests(60);
index dba889004ea1298248b70e09fccb4f46141df1c7..cbb29e41ef2b3af6f0b53c18e54d30489c2fb395 100644 (file)
@@ -16,6 +16,7 @@ TEST_GEN_FILES += thuge-gen
 TEST_GEN_FILES += transhuge-stress
 TEST_GEN_FILES += userfaultfd
 TEST_GEN_FILES += mlock-random-test
+TEST_GEN_FILES += virtual_address_range
 
 TEST_PROGS := run_vmtests
 
index 698c7ed28a26719878b28131c7070adee2ff26fd..1c0d76cb5adfd9698502b62bbea1ccea5bb074e9 100644 (file)
@@ -1 +1,2 @@
+CONFIG_SYSVIPC=y
 CONFIG_USERFAULTFD=y
index addcd6fc1ecc674684bd8c68e4839faa134433f9..77687ab59f77321b3858128c553d73271ac1b618 100644 (file)
@@ -62,7 +62,7 @@ int main(void)
        void *addr;
        int ret;
 
-       addr = mmap(ADDR, LENGTH, PROTECTION, FLAGS, 0, 0);
+       addr = mmap(ADDR, LENGTH, PROTECTION, FLAGS, -1, 0);
        if (addr == MAP_FAILED) {
                perror("mmap");
                exit(1);
index ff0cda2b19c97fd0ad7f75906e9c348094934a7b..e5dbc87b4297778520bf1cc4a2475774410f1bca 100644 (file)
@@ -293,7 +293,7 @@ static int test_mlock_lock()
        unsigned long page_size = getpagesize();
 
        map = mmap(NULL, 2 * page_size, PROT_READ | PROT_WRITE,
-                  MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
+                  MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
        if (map == MAP_FAILED) {
                perror("test_mlock_locked mmap");
                goto out;
@@ -402,7 +402,7 @@ static int test_mlock_onfault()
        unsigned long page_size = getpagesize();
 
        map = mmap(NULL, 2 * page_size, PROT_READ | PROT_WRITE,
-                  MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
+                  MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
        if (map == MAP_FAILED) {
                perror("test_mlock_locked mmap");
                goto out;
@@ -445,7 +445,7 @@ static int test_lock_onfault_of_present()
        uint64_t page1_flags, page2_flags;
 
        map = mmap(NULL, 2 * page_size, PROT_READ | PROT_WRITE,
-                  MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
+                  MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
        if (map == MAP_FAILED) {
                perror("test_mlock_locked mmap");
                goto out;
@@ -492,7 +492,7 @@ static int test_munlockall()
        unsigned long page_size = getpagesize();
 
        map = mmap(NULL, 2 * page_size, PROT_READ | PROT_WRITE,
-                  MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
+                  MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
 
        if (map == MAP_FAILED) {
                perror("test_munlockall mmap");
@@ -518,7 +518,7 @@ static int test_munlockall()
        munmap(map, 2 * page_size);
 
        map = mmap(NULL, 2 * page_size, PROT_READ | PROT_WRITE,
-                  MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
+                  MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
 
        if (map == MAP_FAILED) {
                perror("test_munlockall second mmap");
@@ -573,7 +573,7 @@ static int test_vma_management(bool call_mlock)
        struct vm_boundaries page3;
 
        map = mmap(NULL, 3 * page_size, PROT_READ | PROT_WRITE,
-                  MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
+                  MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
        if (map == MAP_FAILED) {
                perror("mmap()");
                return ret;
index 0ae458f32fdb90c0ad0ac7c05086c5e4f34d7ed4..7f96a5c2e2924ccfe0ec3b67b617ab014c56c81c 100644 (file)
@@ -26,7 +26,7 @@ static int test_limit(void)
        }
 
        map = mmap(NULL, 2 * lims.rlim_max, PROT_READ | PROT_WRITE,
-                  MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE, 0, 0);
+                  MAP_PRIVATE | MAP_ANONYMOUS | MAP_POPULATE, -1, 0);
        if (map != MAP_FAILED)
                printf("mmap should have failed, but didn't\n");
        else {
index 3214a6456d1301a9c6158f66b2d8ad04257518fb..07548a1fa901ca109dad1e4e89accdfaa1815677 100755 (executable)
@@ -49,9 +49,9 @@ fi
 mkdir $mnt
 mount -t hugetlbfs none $mnt
 
-echo "--------------------"
+echo "---------------------"
 echo "running hugepage-mmap"
-echo "--------------------"
+echo "---------------------"
 ./hugepage-mmap
 if [ $? -ne 0 ]; then
        echo "[FAIL]"
@@ -77,9 +77,9 @@ fi
 echo $shmmax > /proc/sys/kernel/shmmax
 echo $shmall > /proc/sys/kernel/shmall
 
-echo "--------------------"
+echo "-------------------"
 echo "running map_hugetlb"
-echo "--------------------"
+echo "-------------------"
 ./map_hugetlb
 if [ $? -ne 0 ]; then
        echo "[FAIL]"
@@ -92,9 +92,9 @@ echo "NOTE: The above hugetlb tests provide minimal coverage.  Use"
 echo "      https://github.com/libhugetlbfs/libhugetlbfs.git for"
 echo "      hugetlb regression testing."
 
-echo "--------------------"
+echo "-------------------"
 echo "running userfaultfd"
-echo "--------------------"
+echo "-------------------"
 ./userfaultfd anon 128 32
 if [ $? -ne 0 ]; then
        echo "[FAIL]"
@@ -103,10 +103,10 @@ else
        echo "[PASS]"
 fi
 
-echo "----------------------------"
+echo "---------------------------"
 echo "running userfaultfd_hugetlb"
-echo "----------------------------"
-# 258MB total huge pages == 128MB src and 128MB dst
+echo "---------------------------"
+# 256MB total huge pages == 128MB src and 128MB dst
 ./userfaultfd hugetlb 128 32 $mnt/ufd_test_file
 if [ $? -ne 0 ]; then
        echo "[FAIL]"
@@ -116,9 +116,9 @@ else
 fi
 rm -f $mnt/ufd_test_file
 
-echo "----------------------------"
+echo "-------------------------"
 echo "running userfaultfd_shmem"
-echo "----------------------------"
+echo "-------------------------"
 ./userfaultfd shmem 128 32
 if [ $? -ne 0 ]; then
        echo "[FAIL]"
@@ -143,9 +143,9 @@ else
        echo "[PASS]"
 fi
 
-echo "--------------------"
+echo "----------------------"
 echo "running on-fault-limit"
-echo "--------------------"
+echo "----------------------"
 sudo -u nobody ./on-fault-limit
 if [ $? -ne 0 ]; then
        echo "[FAIL]"
@@ -165,4 +165,15 @@ else
        echo "[PASS]"
 fi
 
+echo "-----------------------------"
+echo "running virtual_address_range"
+echo "-----------------------------"
+./virtual_address_range
+if [ $? -ne 0 ]; then
+       echo "[FAIL]"
+       exitcode=1
+else
+       echo "[PASS]"
+fi
+
 exit $exitcode
index 0bc737a75150bf225f6b3508182341536b66c88e..88a2ab535e0129106dcdca2d7acb4235cd0557ce 100644 (file)
@@ -146,7 +146,7 @@ void test_mmap(unsigned long size, unsigned flags)
 
        before = read_free(size);
        map = mmap(NULL, size*NUM_PAGES, PROT_READ|PROT_WRITE,
-                       MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB|flags, 0, 0);
+                       MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB|flags, -1, 0);
 
        if (map == (char *)-1) err("mmap");
        memset(map, 0xff, size*NUM_PAGES);
diff --git a/tools/testing/selftests/vm/virtual_address_range.c b/tools/testing/selftests/vm/virtual_address_range.c
new file mode 100644 (file)
index 0000000..3b02aa6
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2017, Anshuman Khandual, IBM Corp.
+ * Licensed under GPLv2.
+ *
+ * Works on architectures which support 128TB virtual
+ * address range and beyond.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <numaif.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+
+/*
+ * Maximum address range mapped with a single mmap()
+ * call is little bit more than 16GB. Hence 16GB is
+ * chosen as the single chunk size for address space
+ * mapping.
+ */
+#define MAP_CHUNK_SIZE   17179869184UL /* 16GB */
+
+/*
+ * Address space till 128TB is mapped without any hint
+ * and is enabled by default. Address space beyond 128TB
+ * till 512TB is obtained by passing hint address as the
+ * first argument into mmap() system call.
+ *
+ * The process heap address space is divided into two
+ * different areas one below 128TB and one above 128TB
+ * till it reaches 512TB. One with size 128TB and the
+ * other being 384TB.
+ */
+#define NR_CHUNKS_128TB   8192UL /* Number of 16GB chunks for 128TB */
+#define NR_CHUNKS_384TB  24576UL /* Number of 16GB chunks for 384TB */
+
+#define ADDR_MARK_128TB  (1UL << 47) /* First address beyond 128TB */
+
+static char *hind_addr(void)
+{
+       int bits = 48 + rand() % 15;
+
+       return (char *) (1UL << bits);
+}
+
+static int validate_addr(char *ptr, int high_addr)
+{
+       unsigned long addr = (unsigned long) ptr;
+
+       if (high_addr) {
+               if (addr < ADDR_MARK_128TB) {
+                       printf("Bad address %lx\n", addr);
+                       return 1;
+               }
+               return 0;
+       }
+
+       if (addr > ADDR_MARK_128TB) {
+               printf("Bad address %lx\n", addr);
+               return 1;
+       }
+       return 0;
+}
+
+static int validate_lower_address_hint(void)
+{
+       char *ptr;
+
+       ptr = mmap((void *) (1UL << 45), MAP_CHUNK_SIZE, PROT_READ |
+                       PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+
+       if (ptr == MAP_FAILED)
+               return 0;
+
+       return 1;
+}
+
+int main(int argc, char *argv[])
+{
+       char *ptr[NR_CHUNKS_128TB];
+       char *hptr[NR_CHUNKS_384TB];
+       char *hint;
+       unsigned long i, lchunks, hchunks;
+
+       for (i = 0; i < NR_CHUNKS_128TB; i++) {
+               ptr[i] = mmap(NULL, MAP_CHUNK_SIZE, PROT_READ | PROT_WRITE,
+                                       MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+
+               if (ptr[i] == MAP_FAILED) {
+                       if (validate_lower_address_hint())
+                               return 1;
+                       break;
+               }
+
+               if (validate_addr(ptr[i], 0))
+                       return 1;
+       }
+       lchunks = i;
+
+       for (i = 0; i < NR_CHUNKS_384TB; i++) {
+               hint = hind_addr();
+               hptr[i] = mmap(hint, MAP_CHUNK_SIZE, PROT_READ | PROT_WRITE,
+                                       MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+
+               if (hptr[i] == MAP_FAILED)
+                       break;
+
+               if (validate_addr(hptr[i], 1))
+                       return 1;
+       }
+       hchunks = i;
+
+       for (i = 0; i < lchunks; i++)
+               munmap(ptr[i], MAP_CHUNK_SIZE);
+
+       for (i = 0; i < hchunks; i++)
+               munmap(hptr[i], MAP_CHUNK_SIZE);
+
+       return 0;
+}
index 6983d05097e25e2afcaeb788ed306ab19c104495..a74c9d739d0745b2aaa644c0c467c6eaba1194a4 100644 (file)
@@ -24,9 +24,11 @@ const char v = 'V';
 static void keep_alive(void)
 {
     int dummy;
+    int ret;
 
-    printf(".");
-    ioctl(fd, WDIOC_KEEPALIVE, &dummy);
+    ret = ioctl(fd, WDIOC_KEEPALIVE, &dummy);
+    if (!ret)
+        printf(".");
 }
 
 /*
@@ -51,6 +53,7 @@ int main(int argc, char *argv[])
     int flags;
     unsigned int ping_rate = 1;
     int ret;
+    int i;
 
     setbuf(stdout, NULL);
 
@@ -61,31 +64,35 @@ int main(int argc, char *argv[])
        exit(-1);
     }
 
-    if (argc > 1) {
-       if (!strncasecmp(argv[1], "-d", 2)) {
-           flags = WDIOS_DISABLECARD;
-           ioctl(fd, WDIOC_SETOPTIONS, &flags);
-           printf("Watchdog card disabled.\n");
-           goto end;
-       } else if (!strncasecmp(argv[1], "-e", 2)) {
-           flags = WDIOS_ENABLECARD;
-           ioctl(fd, WDIOC_SETOPTIONS, &flags);
-           printf("Watchdog card enabled.\n");
-           goto end;
-       } else if (!strncasecmp(argv[1], "-t", 2) && argv[2]) {
-           flags = atoi(argv[2]);
-           ioctl(fd, WDIOC_SETTIMEOUT, &flags);
-           printf("Watchdog timeout set to %u seconds.\n", flags);
-           goto end;
-       } else if (!strncasecmp(argv[1], "-p", 2) && argv[2]) {
-           ping_rate = strtoul(argv[2], NULL, 0);
-           printf("Watchdog ping rate set to %u seconds.\n", ping_rate);
-       } else {
-           printf("-d to disable, -e to enable, -t <n> to set " \
-               "the timeout,\n-p <n> to set the ping rate, and \n");
-           printf("run by itself to tick the card.\n");
-           goto end;
-       }
+    for (i = 1; i < argc; i++) {
+        if (!strncasecmp(argv[i], "-d", 2)) {
+            flags = WDIOS_DISABLECARD;
+            ret = ioctl(fd, WDIOC_SETOPTIONS, &flags);
+            if (!ret)
+                printf("Watchdog card disabled.\n");
+        } else if (!strncasecmp(argv[i], "-e", 2)) {
+            flags = WDIOS_ENABLECARD;
+            ret = ioctl(fd, WDIOC_SETOPTIONS, &flags);
+            if (!ret)
+                printf("Watchdog card enabled.\n");
+        } else if (!strncasecmp(argv[i], "-t", 2) && argv[2]) {
+            flags = atoi(argv[i + 1]);
+            ret = ioctl(fd, WDIOC_SETTIMEOUT, &flags);
+            if (!ret)
+                printf("Watchdog timeout set to %u seconds.\n", flags);
+            i++;
+        } else if (!strncasecmp(argv[i], "-p", 2) && argv[2]) {
+            ping_rate = strtoul(argv[i + 1], NULL, 0);
+            printf("Watchdog ping rate set to %u seconds.\n", ping_rate);
+            i++;
+        } else {
+            printf("-d to disable, -e to enable, -t <n> to set "
+                "the timeout,\n-p <n> to set the ping rate, and ");
+            printf("run by itself to tick the card.\n");
+            printf("Parameters are parsed left-to-right in real-time.\n");
+            printf("Example: %s -d -t 10 -p 5 -e\n", argv[0]);
+            goto end;
+        }
     }
 
     printf("Watchdog Ticking Away!\n");
index 15034fef9698fcb71e72f2cc763ade6491247551..7757f73ff9a32397c97718d3302749b4d93a6016 100644 (file)
@@ -1,2 +1,15 @@
 *_32
 *_64
+single_step_syscall
+sysret_ss_attrs
+syscall_nt
+ptrace_syscall
+test_mremap_vdso
+check_initial_reg_state
+sigreturn
+ldt_gdt
+iopl
+mpx-mini-test
+ioperm
+protection_keys
+test_vdso
index 38e0a9ca5d71154c4d1d32ad7af9ca9154893a33..97f187e2663f3adaf37a50674c36aafec11d291f 100644 (file)
@@ -40,8 +40,7 @@ all_32: $(BINARIES_32)
 
 all_64: $(BINARIES_64)
 
-clean:
-       $(RM) $(BINARIES_32) $(BINARIES_64)
+EXTRA_CLEAN := $(BINARIES_32) $(BINARIES_64)
 
 $(BINARIES_32): $(OUTPUT)/%_32: %.c
        $(CC) -m32 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl -lm
index 9377c8b4ac167723de43088e96e5b5f0effcf4b2..d8f534025b7f7bd3cb27d663f78de9b232fa85d3 100644 (file)
@@ -57,6 +57,7 @@ struct virtqueue *vring_new_virtqueue(unsigned int index,
                                      unsigned int vring_align,
                                      struct virtio_device *vdev,
                                      bool weak_barriers,
+                                     bool ctx,
                                      void *pages,
                                      bool (*notify)(struct virtqueue *vq),
                                      void (*callback)(struct virtqueue *vq),
index f31353fac5415d8b9f5614e6f46f71a8f062f09b..453ca3c211933d12a5b7933852043f7154434fe6 100644 (file)
@@ -20,6 +20,7 @@
 int runcycles = 10000000;
 int max_outstanding = INT_MAX;
 int batch = 1;
+int param = 0;
 
 bool do_sleep = false;
 bool do_relax = false;
@@ -86,7 +87,7 @@ void set_affinity(const char *arg)
        cpu = strtol(arg, &endptr, 0);
        assert(!*endptr);
 
-       assert(cpu >= 0 || cpu < CPU_SETSIZE);
+       assert(cpu >= 0 && cpu < CPU_SETSIZE);
 
        self = pthread_self();
        CPU_ZERO(&cpuset);
@@ -246,6 +247,11 @@ static const struct option longopts[] = {
                .has_arg = required_argument,
                .val = 'b',
        },
+       {
+               .name = "param",
+               .has_arg = required_argument,
+               .val = 'p',
+       },
        {
                .name = "sleep",
                .has_arg = no_argument,
@@ -274,6 +280,7 @@ static void help(void)
                " [--run-cycles C (default: %d)]"
                " [--batch b]"
                " [--outstanding o]"
+               " [--param p]"
                " [--sleep]"
                " [--relax]"
                " [--exit]"
@@ -328,6 +335,12 @@ int main(int argc, char **argv)
                        assert(c > 0 && c < INT_MAX);
                        max_outstanding = c;
                        break;
+               case 'p':
+                       c = strtol(optarg, &endptr, 0);
+                       assert(!*endptr);
+                       assert(c > 0 && c < INT_MAX);
+                       param = c;
+                       break;
                case 'b':
                        c = strtol(optarg, &endptr, 0);
                        assert(!*endptr);
index 14142faf040b7e81a1c38a983aa76d9ae50ee4e1..90b0133004e17ddbc48b90a9eab2e6a489da13b0 100644 (file)
@@ -10,6 +10,8 @@
 
 #include <stdbool.h>
 
+extern int param;
+
 extern bool do_exit;
 
 #if defined(__x86_64__) || defined(__i386__)
index 635b07b4fdd3949c7883a2775575c0ff4d8ce228..7b22f1b20652082b606e4ee55dae31b56f670ef3 100644 (file)
@@ -97,6 +97,9 @@ void alloc_ring(void)
 {
        int ret = ptr_ring_init(&array, ring_size, 0);
        assert(!ret);
+       /* Hacky way to poke at ring internals. Useful for testing though. */
+       if (param)
+               array.batch = param;
 }
 
 /* guest side */
index e0445898f08fa981d372d4de6bad4eebe265cb15..0fecaec90d0d69cf622555104cf9b5f66001b68d 100644 (file)
@@ -100,7 +100,7 @@ static void vq_info_add(struct vdev_info *dev, int num)
        vring_init(&info->vring, num, info->ring, 4096);
        info->vq = vring_new_virtqueue(info->idx,
                                       info->vring.num, 4096, &dev->vdev,
-                                      true, info->ring,
+                                      true, false, info->ring,
                                       vq_notify, vq_callback, "test");
        assert(info->vq);
        info->vq->priv = info;
@@ -202,7 +202,7 @@ static void run_test(struct vdev_info *dev, struct vq_info *vq,
        test = 0;
        r = ioctl(dev->control, VHOST_TEST_RUN, &test);
        assert(r >= 0);
-       fprintf(stderr, "spurious wakeus: 0x%llx\n", spurious);
+       fprintf(stderr, "spurious wakeups: 0x%llx\n", spurious);
 }
 
 const char optstring[] = "h";
index 5f94f51056781e1f8a662be8db245cfd0285b5a8..9476c616d0642c5e2f0162d4fabd3945a98d4f32 100644 (file)
@@ -314,7 +314,8 @@ static int parallel_test(u64 features,
                        err(1, "Could not set affinity to cpu %u", first_cpu);
 
                vq = vring_new_virtqueue(0, RINGSIZE, ALIGN, &gvdev.vdev, true,
-                                        guest_map, fast_vringh ? no_notify_host
+                                        false, guest_map,
+                                        fast_vringh ? no_notify_host
                                         : parallel_notify_host,
                                         never_callback_guest, "guest vq");
 
@@ -479,7 +480,7 @@ int main(int argc, char *argv[])
        memset(__user_addr_min, 0, vring_size(RINGSIZE, ALIGN));
 
        /* Set up guest side. */
-       vq = vring_new_virtqueue(0, RINGSIZE, ALIGN, &vdev, true,
+       vq = vring_new_virtqueue(0, RINGSIZE, ALIGN, &vdev, true, false,
                                 __user_addr_min,
                                 never_notify_host, never_callback_guest,
                                 "guest vq");
@@ -663,7 +664,7 @@ int main(int argc, char *argv[])
                /* Force creation of direct, which we modify. */
                __virtio_clear_bit(&vdev, VIRTIO_RING_F_INDIRECT_DESC);
                vq = vring_new_virtqueue(0, RINGSIZE, ALIGN, &vdev, true,
-                                        __user_addr_min,
+                                        false, __user_addr_min,
                                         never_notify_host,
                                         never_callback_guest,
                                         "guest vq");
index 6278f135256d424c153d3fadc48f8636ecd24ec1..c0c48507e44e2992b3624b2374cd08769a8bb607 100644 (file)
@@ -21,6 +21,16 @@ config INITRAMFS_SOURCE
 
          If you are not sure, leave it blank.
 
+config INITRAMFS_FORCE
+       bool "Ignore the initramfs passed by the bootloader"
+       depends on CMDLINE_EXTEND || CMDLINE_FORCE
+       help
+         This option causes the kernel to ignore the initramfs image
+         (or initrd image) passed to it by the bootloader. This is
+         analogous to CMDLINE_FORCE, which is found on some architectures,
+         and is useful if you cannot or don't want to change the image
+         your bootloader passes to the kernel.
+
 config INITRAMFS_ROOT_UID
        int "User ID to map to 0 (user root)"
        depends on INITRAMFS_SOURCE!=""
similarity index 99%
rename from arch/arm/kvm/arm.c
rename to virt/kvm/arm/arm.c
index 8a31906bdc9b94ca153f7ea2bc811666e6b9524b..3417e184c8e144d32e4d1fa3983b454754b51670 100644 (file)
@@ -332,7 +332,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 
        kvm_arm_reset_debug_ptr(vcpu);
 
-       return 0;
+       return kvm_vgic_vcpu_init(vcpu);
 }
 
 void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
index bce6037cf01d31a73178e44b911dc25c2b6d5929..32c3295929b01b47d2071f372a458fa7b8e5d60d 100644 (file)
@@ -22,7 +22,7 @@
 #include <asm/kvm_hyp.h>
 
 #define vtr_to_max_lr_idx(v)           ((v) & 0xf)
-#define vtr_to_nr_pri_bits(v)          (((u32)(v) >> 29) + 1)
+#define vtr_to_nr_pre_bits(v)          (((u32)(v) >> 26) + 1)
 
 static u64 __hyp_text __gic_v3_get_lr(unsigned int lr)
 {
@@ -135,13 +135,13 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
 
        if (used_lrs) {
                int i;
-               u32 nr_pri_bits;
+               u32 nr_pre_bits;
 
                cpu_if->vgic_elrsr = read_gicreg(ICH_ELSR_EL2);
 
                write_gicreg(0, ICH_HCR_EL2);
                val = read_gicreg(ICH_VTR_EL2);
-               nr_pri_bits = vtr_to_nr_pri_bits(val);
+               nr_pre_bits = vtr_to_nr_pre_bits(val);
 
                for (i = 0; i < used_lrs; i++) {
                        if (cpu_if->vgic_elrsr & (1 << i))
@@ -152,7 +152,7 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
                        __gic_v3_set_lr(0, i);
                }
 
-               switch (nr_pri_bits) {
+               switch (nr_pre_bits) {
                case 7:
                        cpu_if->vgic_ap0r[3] = read_gicreg(ICH_AP0R3_EL2);
                        cpu_if->vgic_ap0r[2] = read_gicreg(ICH_AP0R2_EL2);
@@ -162,7 +162,7 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
                        cpu_if->vgic_ap0r[0] = read_gicreg(ICH_AP0R0_EL2);
                }
 
-               switch (nr_pri_bits) {
+               switch (nr_pre_bits) {
                case 7:
                        cpu_if->vgic_ap1r[3] = read_gicreg(ICH_AP1R3_EL2);
                        cpu_if->vgic_ap1r[2] = read_gicreg(ICH_AP1R2_EL2);
@@ -198,7 +198,7 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
        struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
        u64 used_lrs = vcpu->arch.vgic_cpu.used_lrs;
        u64 val;
-       u32 nr_pri_bits;
+       u32 nr_pre_bits;
        int i;
 
        /*
@@ -217,12 +217,12 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
        }
 
        val = read_gicreg(ICH_VTR_EL2);
-       nr_pri_bits = vtr_to_nr_pri_bits(val);
+       nr_pre_bits = vtr_to_nr_pre_bits(val);
 
        if (used_lrs) {
                write_gicreg(cpu_if->vgic_hcr, ICH_HCR_EL2);
 
-               switch (nr_pri_bits) {
+               switch (nr_pre_bits) {
                case 7:
                        write_gicreg(cpu_if->vgic_ap0r[3], ICH_AP0R3_EL2);
                        write_gicreg(cpu_if->vgic_ap0r[2], ICH_AP0R2_EL2);
@@ -232,7 +232,7 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
                        write_gicreg(cpu_if->vgic_ap0r[0], ICH_AP0R0_EL2);
                }
 
-               switch (nr_pri_bits) {
+               switch (nr_pre_bits) {
                case 7:
                        write_gicreg(cpu_if->vgic_ap1r[3], ICH_AP1R3_EL2);
                        write_gicreg(cpu_if->vgic_ap1r[2], ICH_AP1R2_EL2);
similarity index 100%
rename from arch/arm/kvm/mmio.c
rename to virt/kvm/arm/mmio.c
similarity index 98%
rename from arch/arm/kvm/mmu.c
rename to virt/kvm/arm/mmu.c
index 313ee646480f4d88264664d7393fcb39969609ba..a2d63247d1bbe00ca2693197c3f1e73963ad1c62 100644 (file)
@@ -295,6 +295,13 @@ static void unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size)
        assert_spin_locked(&kvm->mmu_lock);
        pgd = kvm->arch.pgd + stage2_pgd_index(addr);
        do {
+               /*
+                * Make sure the page table is still active, as another thread
+                * could have possibly freed the page table, while we released
+                * the lock.
+                */
+               if (!READ_ONCE(kvm->arch.pgd))
+                       break;
                next = stage2_pgd_addr_end(addr, end);
                if (!stage2_pgd_none(*pgd))
                        unmap_stage2_puds(kvm, pgd, addr, next);
@@ -829,22 +836,22 @@ void stage2_unmap_vm(struct kvm *kvm)
  * Walks the level-1 page table pointed to by kvm->arch.pgd and frees all
  * underlying level-2 and level-3 tables before freeing the actual level-1 table
  * and setting the struct pointer to NULL.
- *
- * Note we don't need locking here as this is only called when the VM is
- * destroyed, which can only be done once.
  */
 void kvm_free_stage2_pgd(struct kvm *kvm)
 {
-       if (kvm->arch.pgd == NULL)
-               return;
+       void *pgd = NULL;
 
        spin_lock(&kvm->mmu_lock);
-       unmap_stage2_range(kvm, 0, KVM_PHYS_SIZE);
+       if (kvm->arch.pgd) {
+               unmap_stage2_range(kvm, 0, KVM_PHYS_SIZE);
+               pgd = READ_ONCE(kvm->arch.pgd);
+               kvm->arch.pgd = NULL;
+       }
        spin_unlock(&kvm->mmu_lock);
 
        /* Free the HW pgd, one page at a time */
-       free_pages_exact(kvm->arch.pgd, S2_PGD_SIZE);
-       kvm->arch.pgd = NULL;
+       if (pgd)
+               free_pages_exact(pgd, S2_PGD_SIZE);
 }
 
 static pud_t *stage2_get_pud(struct kvm *kvm, struct kvm_mmu_memory_cache *cache,
@@ -1170,11 +1177,13 @@ static void stage2_wp_range(struct kvm *kvm, phys_addr_t addr, phys_addr_t end)
                 * large. Otherwise, we may see kernel panics with
                 * CONFIG_DETECT_HUNG_TASK, CONFIG_LOCKUP_DETECTOR,
                 * CONFIG_LOCKDEP. Additionally, holding the lock too long
-                * will also starve other vCPUs.
+                * will also starve other vCPUs. We have to also make sure
+                * that the page tables are not freed while we released
+                * the lock.
                 */
-               if (need_resched() || spin_needbreak(&kvm->mmu_lock))
-                       cond_resched_lock(&kvm->mmu_lock);
-
+               cond_resched_lock(&kvm->mmu_lock);
+               if (!READ_ONCE(kvm->arch.pgd))
+                       break;
                next = stage2_pgd_addr_end(addr, end);
                if (stage2_pgd_present(*pgd))
                        stage2_wp_puds(pgd, addr, next);
similarity index 100%
rename from arch/arm/kvm/perf.c
rename to virt/kvm/arm/perf.c
similarity index 100%
rename from arch/arm/kvm/psci.c
rename to virt/kvm/arm/psci.c
index 37d8b98867d5a04fd814ac89be30c1a44e0f213c..f7dc5ddd6847ba09a6ced07403cba502bb4f8e4b 100644 (file)
 #define TRACE_SYSTEM kvm
 
 /*
- * Tracepoints for vgic
+ * Tracepoints for entry/exit to guest
  */
-TRACE_EVENT(vgic_update_irq_pending,
-       TP_PROTO(unsigned long vcpu_id, __u32 irq, bool level),
-       TP_ARGS(vcpu_id, irq, level),
+TRACE_EVENT(kvm_entry,
+       TP_PROTO(unsigned long vcpu_pc),
+       TP_ARGS(vcpu_pc),
 
        TP_STRUCT__entry(
-               __field(        unsigned long,  vcpu_id )
-               __field(        __u32,          irq     )
-               __field(        bool,           level   )
+               __field(        unsigned long,  vcpu_pc         )
        ),
 
        TP_fast_assign(
-               __entry->vcpu_id        = vcpu_id;
-               __entry->irq            = irq;
+               __entry->vcpu_pc                = vcpu_pc;
+       ),
+
+       TP_printk("PC: 0x%08lx", __entry->vcpu_pc)
+);
+
+TRACE_EVENT(kvm_exit,
+       TP_PROTO(int idx, unsigned int exit_reason, unsigned long vcpu_pc),
+       TP_ARGS(idx, exit_reason, vcpu_pc),
+
+       TP_STRUCT__entry(
+               __field(        int,            idx             )
+               __field(        unsigned int,   exit_reason     )
+               __field(        unsigned long,  vcpu_pc         )
+       ),
+
+       TP_fast_assign(
+               __entry->idx                    = idx;
+               __entry->exit_reason            = exit_reason;
+               __entry->vcpu_pc                = vcpu_pc;
+       ),
+
+       TP_printk("%s: HSR_EC: 0x%04x (%s), PC: 0x%08lx",
+                 __print_symbolic(__entry->idx, kvm_arm_exception_type),
+                 __entry->exit_reason,
+                 __print_symbolic(__entry->exit_reason, kvm_arm_exception_class),
+                 __entry->vcpu_pc)
+);
+
+TRACE_EVENT(kvm_guest_fault,
+       TP_PROTO(unsigned long vcpu_pc, unsigned long hsr,
+                unsigned long hxfar,
+                unsigned long long ipa),
+       TP_ARGS(vcpu_pc, hsr, hxfar, ipa),
+
+       TP_STRUCT__entry(
+               __field(        unsigned long,  vcpu_pc         )
+               __field(        unsigned long,  hsr             )
+               __field(        unsigned long,  hxfar           )
+               __field(   unsigned long long,  ipa             )
+       ),
+
+       TP_fast_assign(
+               __entry->vcpu_pc                = vcpu_pc;
+               __entry->hsr                    = hsr;
+               __entry->hxfar                  = hxfar;
+               __entry->ipa                    = ipa;
+       ),
+
+       TP_printk("ipa %#llx, hsr %#08lx, hxfar %#08lx, pc %#08lx",
+                 __entry->ipa, __entry->hsr,
+                 __entry->hxfar, __entry->vcpu_pc)
+);
+
+TRACE_EVENT(kvm_access_fault,
+       TP_PROTO(unsigned long ipa),
+       TP_ARGS(ipa),
+
+       TP_STRUCT__entry(
+               __field(        unsigned long,  ipa             )
+       ),
+
+       TP_fast_assign(
+               __entry->ipa            = ipa;
+       ),
+
+       TP_printk("IPA: %lx", __entry->ipa)
+);
+
+TRACE_EVENT(kvm_irq_line,
+       TP_PROTO(unsigned int type, int vcpu_idx, int irq_num, int level),
+       TP_ARGS(type, vcpu_idx, irq_num, level),
+
+       TP_STRUCT__entry(
+               __field(        unsigned int,   type            )
+               __field(        int,            vcpu_idx        )
+               __field(        int,            irq_num         )
+               __field(        int,            level           )
+       ),
+
+       TP_fast_assign(
+               __entry->type           = type;
+               __entry->vcpu_idx       = vcpu_idx;
+               __entry->irq_num        = irq_num;
                __entry->level          = level;
        ),
 
-       TP_printk("VCPU: %ld, IRQ %d, level: %d",
-                 __entry->vcpu_id, __entry->irq, __entry->level)
+       TP_printk("Inject %s interrupt (%d), vcpu->idx: %d, num: %d, level: %d",
+                 (__entry->type == KVM_ARM_IRQ_TYPE_CPU) ? "CPU" :
+                 (__entry->type == KVM_ARM_IRQ_TYPE_PPI) ? "VGIC PPI" :
+                 (__entry->type == KVM_ARM_IRQ_TYPE_SPI) ? "VGIC SPI" : "UNKNOWN",
+                 __entry->type, __entry->vcpu_idx, __entry->irq_num, __entry->level)
+);
+
+TRACE_EVENT(kvm_mmio_emulate,
+       TP_PROTO(unsigned long vcpu_pc, unsigned long instr,
+                unsigned long cpsr),
+       TP_ARGS(vcpu_pc, instr, cpsr),
+
+       TP_STRUCT__entry(
+               __field(        unsigned long,  vcpu_pc         )
+               __field(        unsigned long,  instr           )
+               __field(        unsigned long,  cpsr            )
+       ),
+
+       TP_fast_assign(
+               __entry->vcpu_pc                = vcpu_pc;
+               __entry->instr                  = instr;
+               __entry->cpsr                   = cpsr;
+       ),
+
+       TP_printk("Emulate MMIO at: 0x%08lx (instr: %08lx, cpsr: %08lx)",
+                 __entry->vcpu_pc, __entry->instr, __entry->cpsr)
+);
+
+TRACE_EVENT(kvm_unmap_hva,
+       TP_PROTO(unsigned long hva),
+       TP_ARGS(hva),
+
+       TP_STRUCT__entry(
+               __field(        unsigned long,  hva             )
+       ),
+
+       TP_fast_assign(
+               __entry->hva            = hva;
+       ),
+
+       TP_printk("mmu notifier unmap hva: %#08lx", __entry->hva)
+);
+
+TRACE_EVENT(kvm_unmap_hva_range,
+       TP_PROTO(unsigned long start, unsigned long end),
+       TP_ARGS(start, end),
+
+       TP_STRUCT__entry(
+               __field(        unsigned long,  start           )
+               __field(        unsigned long,  end             )
+       ),
+
+       TP_fast_assign(
+               __entry->start          = start;
+               __entry->end            = end;
+       ),
+
+       TP_printk("mmu notifier unmap range: %#08lx -- %#08lx",
+                 __entry->start, __entry->end)
+);
+
+TRACE_EVENT(kvm_set_spte_hva,
+       TP_PROTO(unsigned long hva),
+       TP_ARGS(hva),
+
+       TP_STRUCT__entry(
+               __field(        unsigned long,  hva             )
+       ),
+
+       TP_fast_assign(
+               __entry->hva            = hva;
+       ),
+
+       TP_printk("mmu notifier set pte hva: %#08lx", __entry->hva)
+);
+
+TRACE_EVENT(kvm_age_hva,
+       TP_PROTO(unsigned long start, unsigned long end),
+       TP_ARGS(start, end),
+
+       TP_STRUCT__entry(
+               __field(        unsigned long,  start           )
+               __field(        unsigned long,  end             )
+       ),
+
+       TP_fast_assign(
+               __entry->start          = start;
+               __entry->end            = end;
+       ),
+
+       TP_printk("mmu notifier age hva: %#08lx -- %#08lx",
+                 __entry->start, __entry->end)
+);
+
+TRACE_EVENT(kvm_test_age_hva,
+       TP_PROTO(unsigned long hva),
+       TP_ARGS(hva),
+
+       TP_STRUCT__entry(
+               __field(        unsigned long,  hva             )
+       ),
+
+       TP_fast_assign(
+               __entry->hva            = hva;
+       ),
+
+       TP_printk("mmu notifier test age hva: %#08lx", __entry->hva)
+);
+
+TRACE_EVENT(kvm_set_way_flush,
+           TP_PROTO(unsigned long vcpu_pc, bool cache),
+           TP_ARGS(vcpu_pc, cache),
+
+           TP_STRUCT__entry(
+                   __field(    unsigned long,  vcpu_pc         )
+                   __field(    bool,           cache           )
+           ),
+
+           TP_fast_assign(
+                   __entry->vcpu_pc            = vcpu_pc;
+                   __entry->cache              = cache;
+           ),
+
+           TP_printk("S/W flush at 0x%016lx (cache %s)",
+                     __entry->vcpu_pc, __entry->cache ? "on" : "off")
+);
+
+TRACE_EVENT(kvm_toggle_cache,
+           TP_PROTO(unsigned long vcpu_pc, bool was, bool now),
+           TP_ARGS(vcpu_pc, was, now),
+
+           TP_STRUCT__entry(
+                   __field(    unsigned long,  vcpu_pc         )
+                   __field(    bool,           was             )
+                   __field(    bool,           now             )
+           ),
+
+           TP_fast_assign(
+                   __entry->vcpu_pc            = vcpu_pc;
+                   __entry->was                = was;
+                   __entry->now                = now;
+           ),
+
+           TP_printk("VM op at 0x%016lx (cache was %s, now %s)",
+                     __entry->vcpu_pc, __entry->was ? "on" : "off",
+                     __entry->now ? "on" : "off")
 );
 
 /*
diff --git a/virt/kvm/arm/vgic/trace.h b/virt/kvm/arm/vgic/trace.h
new file mode 100644 (file)
index 0000000..ed32292
--- /dev/null
@@ -0,0 +1,37 @@
+#if !defined(_TRACE_VGIC_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_VGIC_H
+
+#include <linux/tracepoint.h>
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM kvm
+
+TRACE_EVENT(vgic_update_irq_pending,
+       TP_PROTO(unsigned long vcpu_id, __u32 irq, bool level),
+       TP_ARGS(vcpu_id, irq, level),
+
+       TP_STRUCT__entry(
+               __field(        unsigned long,  vcpu_id )
+               __field(        __u32,          irq     )
+               __field(        bool,           level   )
+       ),
+
+       TP_fast_assign(
+               __entry->vcpu_id        = vcpu_id;
+               __entry->irq            = irq;
+               __entry->level          = level;
+       ),
+
+       TP_printk("VCPU: %ld, IRQ %d, level: %d",
+                 __entry->vcpu_id, __entry->irq, __entry->level)
+);
+
+#endif /* _TRACE_VGIC_H */
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH ../../../virt/kvm/arm/vgic
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE trace
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
index 25fd1b942c11e1f9e6567b275d03acf64a02633d..3a0b8999f011c6e3e1ff6ea7699577879a651fd3 100644 (file)
@@ -227,10 +227,30 @@ static int kvm_vgic_dist_init(struct kvm *kvm, unsigned int nr_spis)
 }
 
 /**
- * kvm_vgic_vcpu_init() - Enable the VCPU interface
- * @vcpu: the VCPU which's VGIC should be enabled
+ * kvm_vgic_vcpu_init() - Register VCPU-specific KVM iodevs
+ * @vcpu: pointer to the VCPU being created and initialized
  */
-static void kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
+int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
+{
+       int ret = 0;
+       struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
+
+       if (!irqchip_in_kernel(vcpu->kvm))
+               return 0;
+
+       /*
+        * If we are creating a VCPU with a GICv3 we must also register the
+        * KVM io device for the redistributor that belongs to this VCPU.
+        */
+       if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) {
+               mutex_lock(&vcpu->kvm->lock);
+               ret = vgic_register_redist_iodev(vcpu);
+               mutex_unlock(&vcpu->kvm->lock);
+       }
+       return ret;
+}
+
+static void kvm_vgic_vcpu_enable(struct kvm_vcpu *vcpu)
 {
        if (kvm_vgic_global_state.type == VGIC_V2)
                vgic_v2_enable(vcpu);
@@ -269,7 +289,7 @@ int vgic_init(struct kvm *kvm)
                dist->msis_require_devid = true;
 
        kvm_for_each_vcpu(i, vcpu, kvm)
-               kvm_vgic_vcpu_init(vcpu);
+               kvm_vgic_vcpu_enable(vcpu);
 
        ret = kvm_vgic_setup_default_irq_routing(kvm);
        if (ret)
index 8d1da1af4b09e47c174cf7151b37b98666f03953..2dff288b3a668e401d924e52cee10b9e85ecd8df 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/interrupt.h>
 #include <linux/list.h>
 #include <linux/uaccess.h>
+#include <linux/list_sort.h>
 
 #include <linux/irqchip/arm-gic-v3.h>
 
 #include "vgic.h"
 #include "vgic-mmio.h"
 
+static int vgic_its_save_tables_v0(struct vgic_its *its);
+static int vgic_its_restore_tables_v0(struct vgic_its *its);
+static int vgic_its_commit_v0(struct vgic_its *its);
+static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
+                            struct kvm_vcpu *filter_vcpu);
+
 /*
  * Creates a new (reference to a) struct vgic_irq for a given LPI.
  * If this LPI is already mapped on another ITS, we increase its refcount
  * If this is a "new" LPI, we allocate and initialize a new struct vgic_irq.
  * This function returns a pointer to the _unlocked_ structure.
  */
-static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid)
+static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid,
+                                    struct kvm_vcpu *vcpu)
 {
        struct vgic_dist *dist = &kvm->arch.vgic;
        struct vgic_irq *irq = vgic_get_irq(kvm, NULL, intid), *oldirq;
+       int ret;
 
        /* In this case there is no put, since we keep the reference. */
        if (irq)
@@ -60,6 +69,7 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid)
        irq->config = VGIC_CONFIG_EDGE;
        kref_init(&irq->refcount);
        irq->intid = intid;
+       irq->target_vcpu = vcpu;
 
        spin_lock(&dist->lpi_list_lock);
 
@@ -91,6 +101,19 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid)
 out_unlock:
        spin_unlock(&dist->lpi_list_lock);
 
+       /*
+        * We "cache" the configuration table entries in our struct vgic_irq's.
+        * However we only have those structs for mapped IRQs, so we read in
+        * the respective config data from memory here upon mapping the LPI.
+        */
+       ret = update_lpi_config(kvm, irq, NULL);
+       if (ret)
+               return ERR_PTR(ret);
+
+       ret = vgic_v3_lpi_sync_pending_status(kvm, irq);
+       if (ret)
+               return ERR_PTR(ret);
+
        return irq;
 }
 
@@ -99,6 +122,8 @@ struct its_device {
 
        /* the head for the list of ITTEs */
        struct list_head itt_head;
+       u32 num_eventid_bits;
+       gpa_t itt_addr;
        u32 device_id;
 };
 
@@ -114,8 +139,8 @@ struct its_collection {
 #define its_is_collection_mapped(coll) ((coll) && \
                                ((coll)->target_addr != COLLECTION_NOT_MAPPED))
 
-struct its_itte {
-       struct list_head itte_list;
+struct its_ite {
+       struct list_head ite_list;
 
        struct vgic_irq *irq;
        struct its_collection *collection;
@@ -123,6 +148,50 @@ struct its_itte {
        u32 event_id;
 };
 
+/**
+ * struct vgic_its_abi - ITS abi ops and settings
+ * @cte_esz: collection table entry size
+ * @dte_esz: device table entry size
+ * @ite_esz: interrupt translation table entry size
+ * @save tables: save the ITS tables into guest RAM
+ * @restore_tables: restore the ITS internal structs from tables
+ *  stored in guest RAM
+ * @commit: initialize the registers which expose the ABI settings,
+ *  especially the entry sizes
+ */
+struct vgic_its_abi {
+       int cte_esz;
+       int dte_esz;
+       int ite_esz;
+       int (*save_tables)(struct vgic_its *its);
+       int (*restore_tables)(struct vgic_its *its);
+       int (*commit)(struct vgic_its *its);
+};
+
+static const struct vgic_its_abi its_table_abi_versions[] = {
+       [0] = {.cte_esz = 8, .dte_esz = 8, .ite_esz = 8,
+        .save_tables = vgic_its_save_tables_v0,
+        .restore_tables = vgic_its_restore_tables_v0,
+        .commit = vgic_its_commit_v0,
+       },
+};
+
+#define NR_ITS_ABIS    ARRAY_SIZE(its_table_abi_versions)
+
+inline const struct vgic_its_abi *vgic_its_get_abi(struct vgic_its *its)
+{
+       return &its_table_abi_versions[its->abi_rev];
+}
+
+int vgic_its_set_abi(struct vgic_its *its, int rev)
+{
+       const struct vgic_its_abi *abi;
+
+       its->abi_rev = rev;
+       abi = vgic_its_get_abi(its);
+       return abi->commit(its);
+}
+
 /*
  * Find and returns a device in the device table for an ITS.
  * Must be called with the its_lock mutex held.
@@ -143,27 +212,27 @@ static struct its_device *find_its_device(struct vgic_its *its, u32 device_id)
  * Device ID/Event ID pair on an ITS.
  * Must be called with the its_lock mutex held.
  */
-static struct its_itte *find_itte(struct vgic_its *its, u32 device_id,
+static struct its_ite *find_ite(struct vgic_its *its, u32 device_id,
                                  u32 event_id)
 {
        struct its_device *device;
-       struct its_itte *itte;
+       struct its_ite *ite;
 
        device = find_its_device(its, device_id);
        if (device == NULL)
                return NULL;
 
-       list_for_each_entry(itte, &device->itt_head, itte_list)
-               if (itte->event_id == event_id)
-                       return itte;
+       list_for_each_entry(ite, &device->itt_head, ite_list)
+               if (ite->event_id == event_id)
+                       return ite;
 
        return NULL;
 }
 
 /* To be used as an iterator this macro misses the enclosing parentheses */
-#define for_each_lpi_its(dev, itte, its) \
+#define for_each_lpi_its(dev, ite, its) \
        list_for_each_entry(dev, &(its)->device_list, dev_list) \
-               list_for_each_entry(itte, &(dev)->itt_head, itte_list)
+               list_for_each_entry(ite, &(dev)->itt_head, ite_list)
 
 /*
  * We only implement 48 bits of PA at the moment, although the ITS
@@ -171,11 +240,14 @@ static struct its_itte *find_itte(struct vgic_its *its, u32 device_id,
  */
 #define BASER_ADDRESS(x)       ((x) & GENMASK_ULL(47, 16))
 #define CBASER_ADDRESS(x)      ((x) & GENMASK_ULL(47, 12))
-#define PENDBASER_ADDRESS(x)   ((x) & GENMASK_ULL(47, 16))
-#define PROPBASER_ADDRESS(x)   ((x) & GENMASK_ULL(47, 12))
 
 #define GIC_LPI_OFFSET 8192
 
+#define VITS_TYPER_IDBITS 16
+#define VITS_TYPER_DEVBITS 16
+#define VITS_DTE_MAX_DEVID_OFFSET      (BIT(14) - 1)
+#define VITS_ITE_MAX_EVENTID_OFFSET    (BIT(16) - 1)
+
 /*
  * Finds and returns a collection in the ITS collection table.
  * Must be called with the its_lock mutex held.
@@ -204,7 +276,7 @@ static struct its_collection *find_collection(struct vgic_its *its, int coll_id)
 static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
                             struct kvm_vcpu *filter_vcpu)
 {
-       u64 propbase = PROPBASER_ADDRESS(kvm->arch.vgic.propbaser);
+       u64 propbase = GICR_PROPBASER_ADDRESS(kvm->arch.vgic.propbaser);
        u8 prop;
        int ret;
 
@@ -229,13 +301,13 @@ static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
 }
 
 /*
- * Create a snapshot of the current LPI list, so that we can enumerate all
- * LPIs without holding any lock.
- * Returns the array length and puts the kmalloc'ed array into intid_ptr.
+ * Create a snapshot of the current LPIs targeting @vcpu, so that we can
+ * enumerate those LPIs without holding any lock.
+ * Returns their number and puts the kmalloc'ed array into intid_ptr.
  */
-static int vgic_copy_lpi_list(struct kvm *kvm, u32 **intid_ptr)
+static int vgic_copy_lpi_list(struct kvm_vcpu *vcpu, u32 **intid_ptr)
 {
-       struct vgic_dist *dist = &kvm->arch.vgic;
+       struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
        struct vgic_irq *irq;
        u32 *intids;
        int irq_count = dist->lpi_list_count, i = 0;
@@ -254,14 +326,14 @@ static int vgic_copy_lpi_list(struct kvm *kvm, u32 **intid_ptr)
        spin_lock(&dist->lpi_list_lock);
        list_for_each_entry(irq, &dist->lpi_list_head, lpi_list) {
                /* We don't need to "get" the IRQ, as we hold the list lock. */
-               intids[i] = irq->intid;
-               if (++i == irq_count)
-                       break;
+               if (irq->target_vcpu != vcpu)
+                       continue;
+               intids[i++] = irq->intid;
        }
        spin_unlock(&dist->lpi_list_lock);
 
        *intid_ptr = intids;
-       return irq_count;
+       return i;
 }
 
 /*
@@ -270,18 +342,18 @@ static int vgic_copy_lpi_list(struct kvm *kvm, u32 **intid_ptr)
  * Needs to be called whenever either the collection for a LPIs has
  * changed or the collection itself got retargeted.
  */
-static void update_affinity_itte(struct kvm *kvm, struct its_itte *itte)
+static void update_affinity_ite(struct kvm *kvm, struct its_ite *ite)
 {
        struct kvm_vcpu *vcpu;
 
-       if (!its_is_collection_mapped(itte->collection))
+       if (!its_is_collection_mapped(ite->collection))
                return;
 
-       vcpu = kvm_get_vcpu(kvm, itte->collection->target_addr);
+       vcpu = kvm_get_vcpu(kvm, ite->collection->target_addr);
 
-       spin_lock(&itte->irq->irq_lock);
-       itte->irq->target_vcpu = vcpu;
-       spin_unlock(&itte->irq->irq_lock);
+       spin_lock(&ite->irq->irq_lock);
+       ite->irq->target_vcpu = vcpu;
+       spin_unlock(&ite->irq->irq_lock);
 }
 
 /*
@@ -292,13 +364,13 @@ static void update_affinity_collection(struct kvm *kvm, struct vgic_its *its,
                                       struct its_collection *coll)
 {
        struct its_device *device;
-       struct its_itte *itte;
+       struct its_ite *ite;
 
-       for_each_lpi_its(device, itte, its) {
-               if (!itte->collection || coll != itte->collection)
+       for_each_lpi_its(device, ite, its) {
+               if (!ite->collection || coll != ite->collection)
                        continue;
 
-               update_affinity_itte(kvm, itte);
+               update_affinity_ite(kvm, ite);
        }
 }
 
@@ -310,20 +382,20 @@ static u32 max_lpis_propbaser(u64 propbaser)
 }
 
 /*
- * Scan the whole LPI pending table and sync the pending bit in there
+ * Sync the pending table pending bit of LPIs targeting @vcpu
  * with our own data structures. This relies on the LPI being
  * mapped before.
  */
 static int its_sync_lpi_pending_table(struct kvm_vcpu *vcpu)
 {
-       gpa_t pendbase = PENDBASER_ADDRESS(vcpu->arch.vgic_cpu.pendbaser);
+       gpa_t pendbase = GICR_PENDBASER_ADDRESS(vcpu->arch.vgic_cpu.pendbaser);
        struct vgic_irq *irq;
        int last_byte_offset = -1;
        int ret = 0;
        u32 *intids;
        int nr_irqs, i;
 
-       nr_irqs = vgic_copy_lpi_list(vcpu->kvm, &intids);
+       nr_irqs = vgic_copy_lpi_list(vcpu, &intids);
        if (nr_irqs < 0)
                return nr_irqs;
 
@@ -364,6 +436,7 @@ static unsigned long vgic_mmio_read_its_typer(struct kvm *kvm,
                                              struct vgic_its *its,
                                              gpa_t addr, unsigned int len)
 {
+       const struct vgic_its_abi *abi = vgic_its_get_abi(its);
        u64 reg = GITS_TYPER_PLPIS;
 
        /*
@@ -374,8 +447,9 @@ static unsigned long vgic_mmio_read_its_typer(struct kvm *kvm,
         * To avoid memory waste in the guest, we keep the number of IDBits and
         * DevBits low - as least for the time being.
         */
-       reg |= 0x0f << GITS_TYPER_DEVBITS_SHIFT;
-       reg |= 0x0f << GITS_TYPER_IDBITS_SHIFT;
+       reg |= GIC_ENCODE_SZ(VITS_TYPER_DEVBITS, 5) << GITS_TYPER_DEVBITS_SHIFT;
+       reg |= GIC_ENCODE_SZ(VITS_TYPER_IDBITS, 5) << GITS_TYPER_IDBITS_SHIFT;
+       reg |= GIC_ENCODE_SZ(abi->ite_esz, 4) << GITS_TYPER_ITT_ENTRY_SIZE_SHIFT;
 
        return extract_bytes(reg, addr & 7, len);
 }
@@ -384,7 +458,23 @@ static unsigned long vgic_mmio_read_its_iidr(struct kvm *kvm,
                                             struct vgic_its *its,
                                             gpa_t addr, unsigned int len)
 {
-       return (PRODUCT_ID_KVM << 24) | (IMPLEMENTER_ARM << 0);
+       u32 val;
+
+       val = (its->abi_rev << GITS_IIDR_REV_SHIFT) & GITS_IIDR_REV_MASK;
+       val |= (PRODUCT_ID_KVM << GITS_IIDR_PRODUCTID_SHIFT) | IMPLEMENTER_ARM;
+       return val;
+}
+
+static int vgic_mmio_uaccess_write_its_iidr(struct kvm *kvm,
+                                           struct vgic_its *its,
+                                           gpa_t addr, unsigned int len,
+                                           unsigned long val)
+{
+       u32 rev = GITS_IIDR_REV(val);
+
+       if (rev >= NR_ITS_ABIS)
+               return -EINVAL;
+       return vgic_its_set_abi(its, rev);
 }
 
 static unsigned long vgic_mmio_read_its_idregs(struct kvm *kvm,
@@ -425,25 +515,25 @@ static int vgic_its_trigger_msi(struct kvm *kvm, struct vgic_its *its,
                                u32 devid, u32 eventid)
 {
        struct kvm_vcpu *vcpu;
-       struct its_itte *itte;
+       struct its_ite *ite;
 
        if (!its->enabled)
                return -EBUSY;
 
-       itte = find_itte(its, devid, eventid);
-       if (!itte || !its_is_collection_mapped(itte->collection))
+       ite = find_ite(its, devid, eventid);
+       if (!ite || !its_is_collection_mapped(ite->collection))
                return E_ITS_INT_UNMAPPED_INTERRUPT;
 
-       vcpu = kvm_get_vcpu(kvm, itte->collection->target_addr);
+       vcpu = kvm_get_vcpu(kvm, ite->collection->target_addr);
        if (!vcpu)
                return E_ITS_INT_UNMAPPED_INTERRUPT;
 
        if (!vcpu->arch.vgic_cpu.lpis_enabled)
                return -EBUSY;
 
-       spin_lock(&itte->irq->irq_lock);
-       itte->irq->pending_latch = true;
-       vgic_queue_irq_unlock(kvm, itte->irq);
+       spin_lock(&ite->irq->irq_lock);
+       ite->irq->pending_latch = true;
+       vgic_queue_irq_unlock(kvm, ite->irq);
 
        return 0;
 }
@@ -511,15 +601,15 @@ int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi)
 }
 
 /* Requires the its_lock to be held. */
-static void its_free_itte(struct kvm *kvm, struct its_itte *itte)
+static void its_free_ite(struct kvm *kvm, struct its_ite *ite)
 {
-       list_del(&itte->itte_list);
+       list_del(&ite->ite_list);
 
        /* This put matches the get in vgic_add_lpi. */
-       if (itte->irq)
-               vgic_put_irq(kvm, itte->irq);
+       if (ite->irq)
+               vgic_put_irq(kvm, ite->irq);
 
-       kfree(itte);
+       kfree(ite);
 }
 
 static u64 its_cmd_mask_field(u64 *its_cmd, int word, int shift, int size)
@@ -529,9 +619,11 @@ static u64 its_cmd_mask_field(u64 *its_cmd, int word, int shift, int size)
 
 #define its_cmd_get_command(cmd)       its_cmd_mask_field(cmd, 0,  0,  8)
 #define its_cmd_get_deviceid(cmd)      its_cmd_mask_field(cmd, 0, 32, 32)
+#define its_cmd_get_size(cmd)          (its_cmd_mask_field(cmd, 1,  0,  5) + 1)
 #define its_cmd_get_id(cmd)            its_cmd_mask_field(cmd, 1,  0, 32)
 #define its_cmd_get_physical_id(cmd)   its_cmd_mask_field(cmd, 1, 32, 32)
 #define its_cmd_get_collection(cmd)    its_cmd_mask_field(cmd, 2,  0, 16)
+#define its_cmd_get_ittaddr(cmd)       (its_cmd_mask_field(cmd, 2,  8, 44) << 8)
 #define its_cmd_get_target_addr(cmd)   its_cmd_mask_field(cmd, 2, 16, 32)
 #define its_cmd_get_validbit(cmd)      its_cmd_mask_field(cmd, 2, 63,  1)
 
@@ -544,17 +636,17 @@ static int vgic_its_cmd_handle_discard(struct kvm *kvm, struct vgic_its *its,
 {
        u32 device_id = its_cmd_get_deviceid(its_cmd);
        u32 event_id = its_cmd_get_id(its_cmd);
-       struct its_itte *itte;
+       struct its_ite *ite;
 
 
-       itte = find_itte(its, device_id, event_id);
-       if (itte && itte->collection) {
+       ite = find_ite(its, device_id, event_id);
+       if (ite && ite->collection) {
                /*
                 * Though the spec talks about removing the pending state, we
                 * don't bother here since we clear the ITTE anyway and the
                 * pending state is a property of the ITTE struct.
                 */
-               its_free_itte(kvm, itte);
+               its_free_ite(kvm, ite);
                return 0;
        }
 
@@ -572,26 +664,26 @@ static int vgic_its_cmd_handle_movi(struct kvm *kvm, struct vgic_its *its,
        u32 event_id = its_cmd_get_id(its_cmd);
        u32 coll_id = its_cmd_get_collection(its_cmd);
        struct kvm_vcpu *vcpu;
-       struct its_itte *itte;
+       struct its_ite *ite;
        struct its_collection *collection;
 
-       itte = find_itte(its, device_id, event_id);
-       if (!itte)
+       ite = find_ite(its, device_id, event_id);
+       if (!ite)
                return E_ITS_MOVI_UNMAPPED_INTERRUPT;
 
-       if (!its_is_collection_mapped(itte->collection))
+       if (!its_is_collection_mapped(ite->collection))
                return E_ITS_MOVI_UNMAPPED_COLLECTION;
 
        collection = find_collection(its, coll_id);
        if (!its_is_collection_mapped(collection))
                return E_ITS_MOVI_UNMAPPED_COLLECTION;
 
-       itte->collection = collection;
+       ite->collection = collection;
        vcpu = kvm_get_vcpu(kvm, collection->target_addr);
 
-       spin_lock(&itte->irq->irq_lock);
-       itte->irq->target_vcpu = vcpu;
-       spin_unlock(&itte->irq->irq_lock);
+       spin_lock(&ite->irq->irq_lock);
+       ite->irq->target_vcpu = vcpu;
+       spin_unlock(&ite->irq->irq_lock);
 
        return 0;
 }
@@ -600,16 +692,31 @@ static int vgic_its_cmd_handle_movi(struct kvm *kvm, struct vgic_its *its,
  * Check whether an ID can be stored into the corresponding guest table.
  * For a direct table this is pretty easy, but gets a bit nasty for
  * indirect tables. We check whether the resulting guest physical address
- * is actually valid (covered by a memslot and guest accessbible).
+ * is actually valid (covered by a memslot and guest accessible).
  * For this we have to read the respective first level entry.
  */
-static bool vgic_its_check_id(struct vgic_its *its, u64 baser, int id)
+static bool vgic_its_check_id(struct vgic_its *its, u64 baser, u32 id,
+                             gpa_t *eaddr)
 {
        int l1_tbl_size = GITS_BASER_NR_PAGES(baser) * SZ_64K;
+       u64 indirect_ptr, type = GITS_BASER_TYPE(baser);
+       int esz = GITS_BASER_ENTRY_SIZE(baser);
        int index;
-       u64 indirect_ptr;
        gfn_t gfn;
-       int esz = GITS_BASER_ENTRY_SIZE(baser);
+
+       switch (type) {
+       case GITS_BASER_TYPE_DEVICE:
+               if (id >= BIT_ULL(VITS_TYPER_DEVBITS))
+                       return false;
+               break;
+       case GITS_BASER_TYPE_COLLECTION:
+               /* as GITS_TYPER.CIL == 0, ITS supports 16-bit collection ID */
+               if (id >= BIT_ULL(16))
+                       return false;
+               break;
+       default:
+               return false;
+       }
 
        if (!(baser & GITS_BASER_INDIRECT)) {
                phys_addr_t addr;
@@ -620,6 +727,8 @@ static bool vgic_its_check_id(struct vgic_its *its, u64 baser, int id)
                addr = BASER_ADDRESS(baser) + id * esz;
                gfn = addr >> PAGE_SHIFT;
 
+               if (eaddr)
+                       *eaddr = addr;
                return kvm_is_visible_gfn(its->dev->kvm, gfn);
        }
 
@@ -652,6 +761,8 @@ static bool vgic_its_check_id(struct vgic_its *its, u64 baser, int id)
        indirect_ptr += index * esz;
        gfn = indirect_ptr >> PAGE_SHIFT;
 
+       if (eaddr)
+               *eaddr = indirect_ptr;
        return kvm_is_visible_gfn(its->dev->kvm, gfn);
 }
 
@@ -661,7 +772,7 @@ static int vgic_its_alloc_collection(struct vgic_its *its,
 {
        struct its_collection *collection;
 
-       if (!vgic_its_check_id(its, its->baser_coll_table, coll_id))
+       if (!vgic_its_check_id(its, its->baser_coll_table, coll_id, NULL))
                return E_ITS_MAPC_COLLECTION_OOR;
 
        collection = kzalloc(sizeof(*collection), GFP_KERNEL);
@@ -679,7 +790,7 @@ static void vgic_its_free_collection(struct vgic_its *its, u32 coll_id)
 {
        struct its_collection *collection;
        struct its_device *device;
-       struct its_itte *itte;
+       struct its_ite *ite;
 
        /*
         * Clearing the mapping for that collection ID removes the
@@ -690,15 +801,34 @@ static void vgic_its_free_collection(struct vgic_its *its, u32 coll_id)
        if (!collection)
                return;
 
-       for_each_lpi_its(device, itte, its)
-               if (itte->collection &&
-                   itte->collection->collection_id == coll_id)
-                       itte->collection = NULL;
+       for_each_lpi_its(device, ite, its)
+               if (ite->collection &&
+                   ite->collection->collection_id == coll_id)
+                       ite->collection = NULL;
 
        list_del(&collection->coll_list);
        kfree(collection);
 }
 
+/* Must be called with its_lock mutex held */
+static struct its_ite *vgic_its_alloc_ite(struct its_device *device,
+                                         struct its_collection *collection,
+                                         u32 lpi_id, u32 event_id)
+{
+       struct its_ite *ite;
+
+       ite = kzalloc(sizeof(*ite), GFP_KERNEL);
+       if (!ite)
+               return ERR_PTR(-ENOMEM);
+
+       ite->event_id   = event_id;
+       ite->collection = collection;
+       ite->lpi = lpi_id;
+
+       list_add_tail(&ite->ite_list, &device->itt_head);
+       return ite;
+}
+
 /*
  * The MAPTI and MAPI commands map LPIs to ITTEs.
  * Must be called with its_lock mutex held.
@@ -709,16 +839,20 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
        u32 device_id = its_cmd_get_deviceid(its_cmd);
        u32 event_id = its_cmd_get_id(its_cmd);
        u32 coll_id = its_cmd_get_collection(its_cmd);
-       struct its_itte *itte;
+       struct its_ite *ite;
+       struct kvm_vcpu *vcpu = NULL;
        struct its_device *device;
        struct its_collection *collection, *new_coll = NULL;
-       int lpi_nr;
        struct vgic_irq *irq;
+       int lpi_nr;
 
        device = find_its_device(its, device_id);
        if (!device)
                return E_ITS_MAPTI_UNMAPPED_DEVICE;
 
+       if (event_id >= BIT_ULL(device->num_eventid_bits))
+               return E_ITS_MAPTI_ID_OOR;
+
        if (its_cmd_get_command(its_cmd) == GITS_CMD_MAPTI)
                lpi_nr = its_cmd_get_physical_id(its_cmd);
        else
@@ -728,7 +862,7 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
                return E_ITS_MAPTI_PHYSICALID_OOR;
 
        /* If there is an existing mapping, behavior is UNPREDICTABLE. */
-       if (find_itte(its, device_id, event_id))
+       if (find_ite(its, device_id, event_id))
                return 0;
 
        collection = find_collection(its, coll_id);
@@ -739,36 +873,24 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
                new_coll = collection;
        }
 
-       itte = kzalloc(sizeof(struct its_itte), GFP_KERNEL);
-       if (!itte) {
+       ite = vgic_its_alloc_ite(device, collection, lpi_nr, event_id);
+       if (IS_ERR(ite)) {
                if (new_coll)
                        vgic_its_free_collection(its, coll_id);
-               return -ENOMEM;
+               return PTR_ERR(ite);
        }
 
-       itte->event_id  = event_id;
-       list_add_tail(&itte->itte_list, &device->itt_head);
-
-       itte->collection = collection;
-       itte->lpi = lpi_nr;
+       if (its_is_collection_mapped(collection))
+               vcpu = kvm_get_vcpu(kvm, collection->target_addr);
 
-       irq = vgic_add_lpi(kvm, lpi_nr);
+       irq = vgic_add_lpi(kvm, lpi_nr, vcpu);
        if (IS_ERR(irq)) {
                if (new_coll)
                        vgic_its_free_collection(its, coll_id);
-               its_free_itte(kvm, itte);
+               its_free_ite(kvm, ite);
                return PTR_ERR(irq);
        }
-       itte->irq = irq;
-
-       update_affinity_itte(kvm, itte);
-
-       /*
-        * We "cache" the configuration table entries in out struct vgic_irq's.
-        * However we only have those structs for mapped IRQs, so we read in
-        * the respective config data from memory here upon mapping the LPI.
-        */
-       update_lpi_config(kvm, itte->irq, NULL);
+       ite->irq = irq;
 
        return 0;
 }
@@ -776,20 +898,40 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its,
 /* Requires the its_lock to be held. */
 static void vgic_its_unmap_device(struct kvm *kvm, struct its_device *device)
 {
-       struct its_itte *itte, *temp;
+       struct its_ite *ite, *temp;
 
        /*
         * The spec says that unmapping a device with still valid
         * ITTEs associated is UNPREDICTABLE. We remove all ITTEs,
         * since we cannot leave the memory unreferenced.
         */
-       list_for_each_entry_safe(itte, temp, &device->itt_head, itte_list)
-               its_free_itte(kvm, itte);
+       list_for_each_entry_safe(ite, temp, &device->itt_head, ite_list)
+               its_free_ite(kvm, ite);
 
        list_del(&device->dev_list);
        kfree(device);
 }
 
+/* Must be called with its_lock mutex held */
+static struct its_device *vgic_its_alloc_device(struct vgic_its *its,
+                                               u32 device_id, gpa_t itt_addr,
+                                               u8 num_eventid_bits)
+{
+       struct its_device *device;
+
+       device = kzalloc(sizeof(*device), GFP_KERNEL);
+       if (!device)
+               return ERR_PTR(-ENOMEM);
+
+       device->device_id = device_id;
+       device->itt_addr = itt_addr;
+       device->num_eventid_bits = num_eventid_bits;
+       INIT_LIST_HEAD(&device->itt_head);
+
+       list_add_tail(&device->dev_list, &its->device_list);
+       return device;
+}
+
 /*
  * MAPD maps or unmaps a device ID to Interrupt Translation Tables (ITTs).
  * Must be called with the its_lock mutex held.
@@ -799,11 +941,16 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
 {
        u32 device_id = its_cmd_get_deviceid(its_cmd);
        bool valid = its_cmd_get_validbit(its_cmd);
+       u8 num_eventid_bits = its_cmd_get_size(its_cmd);
+       gpa_t itt_addr = its_cmd_get_ittaddr(its_cmd);
        struct its_device *device;
 
-       if (!vgic_its_check_id(its, its->baser_device_table, device_id))
+       if (!vgic_its_check_id(its, its->baser_device_table, device_id, NULL))
                return E_ITS_MAPD_DEVICE_OOR;
 
+       if (valid && num_eventid_bits > VITS_TYPER_IDBITS)
+               return E_ITS_MAPD_ITTSIZE_OOR;
+
        device = find_its_device(its, device_id);
 
        /*
@@ -821,14 +968,10 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
        if (!valid)
                return 0;
 
-       device = kzalloc(sizeof(struct its_device), GFP_KERNEL);
-       if (!device)
-               return -ENOMEM;
-
-       device->device_id = device_id;
-       INIT_LIST_HEAD(&device->itt_head);
-
-       list_add_tail(&device->dev_list, &its->device_list);
+       device = vgic_its_alloc_device(its, device_id, itt_addr,
+                                      num_eventid_bits);
+       if (IS_ERR(device))
+               return PTR_ERR(device);
 
        return 0;
 }
@@ -883,14 +1026,14 @@ static int vgic_its_cmd_handle_clear(struct kvm *kvm, struct vgic_its *its,
 {
        u32 device_id = its_cmd_get_deviceid(its_cmd);
        u32 event_id = its_cmd_get_id(its_cmd);
-       struct its_itte *itte;
+       struct its_ite *ite;
 
 
-       itte = find_itte(its, device_id, event_id);
-       if (!itte)
+       ite = find_ite(its, device_id, event_id);
+       if (!ite)
                return E_ITS_CLEAR_UNMAPPED_INTERRUPT;
 
-       itte->irq->pending_latch = false;
+       ite->irq->pending_latch = false;
 
        return 0;
 }
@@ -904,14 +1047,14 @@ static int vgic_its_cmd_handle_inv(struct kvm *kvm, struct vgic_its *its,
 {
        u32 device_id = its_cmd_get_deviceid(its_cmd);
        u32 event_id = its_cmd_get_id(its_cmd);
-       struct its_itte *itte;
+       struct its_ite *ite;
 
 
-       itte = find_itte(its, device_id, event_id);
-       if (!itte)
+       ite = find_ite(its, device_id, event_id);
+       if (!ite)
                return E_ITS_INV_UNMAPPED_INTERRUPT;
 
-       return update_lpi_config(kvm, itte->irq, NULL);
+       return update_lpi_config(kvm, ite->irq, NULL);
 }
 
 /*
@@ -938,7 +1081,7 @@ static int vgic_its_cmd_handle_invall(struct kvm *kvm, struct vgic_its *its,
 
        vcpu = kvm_get_vcpu(kvm, collection->target_addr);
 
-       irq_count = vgic_copy_lpi_list(kvm, &intids);
+       irq_count = vgic_copy_lpi_list(vcpu, &intids);
        if (irq_count < 0)
                return irq_count;
 
@@ -1213,6 +1356,33 @@ static unsigned long vgic_mmio_read_its_creadr(struct kvm *kvm,
        return extract_bytes(its->creadr, addr & 0x7, len);
 }
 
+static int vgic_mmio_uaccess_write_its_creadr(struct kvm *kvm,
+                                             struct vgic_its *its,
+                                             gpa_t addr, unsigned int len,
+                                             unsigned long val)
+{
+       u32 cmd_offset;
+       int ret = 0;
+
+       mutex_lock(&its->cmd_lock);
+
+       if (its->enabled) {
+               ret = -EBUSY;
+               goto out;
+       }
+
+       cmd_offset = ITS_CMD_OFFSET(val);
+       if (cmd_offset >= ITS_CMD_BUFFER_SIZE(its->cbaser)) {
+               ret = -EINVAL;
+               goto out;
+       }
+
+       its->creadr = cmd_offset;
+out:
+       mutex_unlock(&its->cmd_lock);
+       return ret;
+}
+
 #define BASER_INDEX(addr) (((addr) / sizeof(u64)) & 0x7)
 static unsigned long vgic_mmio_read_its_baser(struct kvm *kvm,
                                              struct vgic_its *its,
@@ -1241,6 +1411,7 @@ static void vgic_mmio_write_its_baser(struct kvm *kvm,
                                      gpa_t addr, unsigned int len,
                                      unsigned long val)
 {
+       const struct vgic_its_abi *abi = vgic_its_get_abi(its);
        u64 entry_size, device_type;
        u64 reg, *regptr, clearbits = 0;
 
@@ -1251,12 +1422,12 @@ static void vgic_mmio_write_its_baser(struct kvm *kvm,
        switch (BASER_INDEX(addr)) {
        case 0:
                regptr = &its->baser_device_table;
-               entry_size = 8;
+               entry_size = abi->dte_esz;
                device_type = GITS_BASER_TYPE_DEVICE;
                break;
        case 1:
                regptr = &its->baser_coll_table;
-               entry_size = 8;
+               entry_size = abi->cte_esz;
                device_type = GITS_BASER_TYPE_COLLECTION;
                clearbits = GITS_BASER_INDIRECT;
                break;
@@ -1317,6 +1488,16 @@ static void vgic_mmio_write_its_ctlr(struct kvm *kvm, struct vgic_its *its,
        .its_write = wr,                                        \
 }
 
+#define REGISTER_ITS_DESC_UACCESS(off, rd, wr, uwr, length, acc)\
+{                                                              \
+       .reg_offset = off,                                      \
+       .len = length,                                          \
+       .access_flags = acc,                                    \
+       .its_read = rd,                                         \
+       .its_write = wr,                                        \
+       .uaccess_its_write = uwr,                               \
+}
+
 static void its_mmio_write_wi(struct kvm *kvm, struct vgic_its *its,
                              gpa_t addr, unsigned int len, unsigned long val)
 {
@@ -1327,8 +1508,9 @@ static struct vgic_register_region its_registers[] = {
        REGISTER_ITS_DESC(GITS_CTLR,
                vgic_mmio_read_its_ctlr, vgic_mmio_write_its_ctlr, 4,
                VGIC_ACCESS_32bit),
-       REGISTER_ITS_DESC(GITS_IIDR,
-               vgic_mmio_read_its_iidr, its_mmio_write_wi, 4,
+       REGISTER_ITS_DESC_UACCESS(GITS_IIDR,
+               vgic_mmio_read_its_iidr, its_mmio_write_wi,
+               vgic_mmio_uaccess_write_its_iidr, 4,
                VGIC_ACCESS_32bit),
        REGISTER_ITS_DESC(GITS_TYPER,
                vgic_mmio_read_its_typer, its_mmio_write_wi, 8,
@@ -1339,8 +1521,9 @@ static struct vgic_register_region its_registers[] = {
        REGISTER_ITS_DESC(GITS_CWRITER,
                vgic_mmio_read_its_cwriter, vgic_mmio_write_its_cwriter, 8,
                VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
-       REGISTER_ITS_DESC(GITS_CREADR,
-               vgic_mmio_read_its_creadr, its_mmio_write_wi, 8,
+       REGISTER_ITS_DESC_UACCESS(GITS_CREADR,
+               vgic_mmio_read_its_creadr, its_mmio_write_wi,
+               vgic_mmio_uaccess_write_its_creadr, 8,
                VGIC_ACCESS_64bit | VGIC_ACCESS_32bit),
        REGISTER_ITS_DESC(GITS_BASER,
                vgic_mmio_read_its_baser, vgic_mmio_write_its_baser, 0x40,
@@ -1357,17 +1540,19 @@ void vgic_enable_lpis(struct kvm_vcpu *vcpu)
                its_sync_lpi_pending_table(vcpu);
 }
 
-static int vgic_register_its_iodev(struct kvm *kvm, struct vgic_its *its)
+static int vgic_register_its_iodev(struct kvm *kvm, struct vgic_its *its,
+                                  u64 addr)
 {
        struct vgic_io_device *iodev = &its->iodev;
        int ret;
 
-       if (!its->initialized)
-               return -EBUSY;
-
-       if (IS_VGIC_ADDR_UNDEF(its->vgic_its_base))
-               return -ENXIO;
+       mutex_lock(&kvm->slots_lock);
+       if (!IS_VGIC_ADDR_UNDEF(its->vgic_its_base)) {
+               ret = -EBUSY;
+               goto out;
+       }
 
+       its->vgic_its_base = addr;
        iodev->regions = its_registers;
        iodev->nr_regions = ARRAY_SIZE(its_registers);
        kvm_iodevice_init(&iodev->dev, &kvm_io_gic_ops);
@@ -1375,9 +1560,9 @@ static int vgic_register_its_iodev(struct kvm *kvm, struct vgic_its *its)
        iodev->base_addr = its->vgic_its_base;
        iodev->iodev_type = IODEV_ITS;
        iodev->its = its;
-       mutex_lock(&kvm->slots_lock);
        ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, iodev->base_addr,
                                      KVM_VGIC_V3_ITS_SIZE, &iodev->dev);
+out:
        mutex_unlock(&kvm->slots_lock);
 
        return ret;
@@ -1387,7 +1572,6 @@ static int vgic_register_its_iodev(struct kvm *kvm, struct vgic_its *its)
        (GIC_BASER_CACHEABILITY(GITS_BASER, INNER, RaWb)                | \
         GIC_BASER_CACHEABILITY(GITS_BASER, OUTER, SameAsInner)         | \
         GIC_BASER_SHAREABILITY(GITS_BASER, InnerShareable)             | \
-        ((8ULL - 1) << GITS_BASER_ENTRY_SIZE_SHIFT)                    | \
         GITS_BASER_PAGE_SIZE_64K)
 
 #define INITIAL_PROPBASER_VALUE                                                  \
@@ -1415,7 +1599,6 @@ static int vgic_its_create(struct kvm_device *dev, u32 type)
        INIT_LIST_HEAD(&its->collection_list);
 
        dev->kvm->arch.vgic.has_its = true;
-       its->initialized = false;
        its->enabled = false;
        its->dev = dev;
 
@@ -1427,16 +1610,23 @@ static int vgic_its_create(struct kvm_device *dev, u32 type)
 
        dev->private = its;
 
-       return 0;
+       return vgic_its_set_abi(its, NR_ITS_ABIS - 1);
+}
+
+static void vgic_its_free_device(struct kvm *kvm, struct its_device *dev)
+{
+       struct its_ite *ite, *tmp;
+
+       list_for_each_entry_safe(ite, tmp, &dev->itt_head, ite_list)
+               its_free_ite(kvm, ite);
+       list_del(&dev->dev_list);
+       kfree(dev);
 }
 
 static void vgic_its_destroy(struct kvm_device *kvm_dev)
 {
        struct kvm *kvm = kvm_dev->kvm;
        struct vgic_its *its = kvm_dev->private;
-       struct its_device *dev;
-       struct its_itte *itte;
-       struct list_head *dev_cur, *dev_temp;
        struct list_head *cur, *temp;
 
        /*
@@ -1447,25 +1637,710 @@ static void vgic_its_destroy(struct kvm_device *kvm_dev)
                return;
 
        mutex_lock(&its->its_lock);
-       list_for_each_safe(dev_cur, dev_temp, &its->device_list) {
-               dev = container_of(dev_cur, struct its_device, dev_list);
-               list_for_each_safe(cur, temp, &dev->itt_head) {
-                       itte = (container_of(cur, struct its_itte, itte_list));
-                       its_free_itte(kvm, itte);
-               }
-               list_del(dev_cur);
-               kfree(dev);
+       list_for_each_safe(cur, temp, &its->device_list) {
+               struct its_device *dev;
+
+               dev = list_entry(cur, struct its_device, dev_list);
+               vgic_its_free_device(kvm, dev);
        }
 
        list_for_each_safe(cur, temp, &its->collection_list) {
+               struct its_collection *coll;
+
+               coll = list_entry(cur, struct its_collection, coll_list);
                list_del(cur);
-               kfree(container_of(cur, struct its_collection, coll_list));
+               kfree(coll);
        }
        mutex_unlock(&its->its_lock);
 
        kfree(its);
 }
 
+int vgic_its_has_attr_regs(struct kvm_device *dev,
+                          struct kvm_device_attr *attr)
+{
+       const struct vgic_register_region *region;
+       gpa_t offset = attr->attr;
+       int align;
+
+       align = (offset < GITS_TYPER) || (offset >= GITS_PIDR4) ? 0x3 : 0x7;
+
+       if (offset & align)
+               return -EINVAL;
+
+       region = vgic_find_mmio_region(its_registers,
+                                      ARRAY_SIZE(its_registers),
+                                      offset);
+       if (!region)
+               return -ENXIO;
+
+       return 0;
+}
+
+int vgic_its_attr_regs_access(struct kvm_device *dev,
+                             struct kvm_device_attr *attr,
+                             u64 *reg, bool is_write)
+{
+       const struct vgic_register_region *region;
+       struct vgic_its *its;
+       gpa_t addr, offset;
+       unsigned int len;
+       int align, ret = 0;
+
+       its = dev->private;
+       offset = attr->attr;
+
+       /*
+        * Although the spec supports upper/lower 32-bit accesses to
+        * 64-bit ITS registers, the userspace ABI requires 64-bit
+        * accesses to all 64-bit wide registers. We therefore only
+        * support 32-bit accesses to GITS_CTLR, GITS_IIDR and GITS ID
+        * registers
+        */
+       if ((offset < GITS_TYPER) || (offset >= GITS_PIDR4))
+               align = 0x3;
+       else
+               align = 0x7;
+
+       if (offset & align)
+               return -EINVAL;
+
+       mutex_lock(&dev->kvm->lock);
+
+       if (IS_VGIC_ADDR_UNDEF(its->vgic_its_base)) {
+               ret = -ENXIO;
+               goto out;
+       }
+
+       region = vgic_find_mmio_region(its_registers,
+                                      ARRAY_SIZE(its_registers),
+                                      offset);
+       if (!region) {
+               ret = -ENXIO;
+               goto out;
+       }
+
+       if (!lock_all_vcpus(dev->kvm)) {
+               ret = -EBUSY;
+               goto out;
+       }
+
+       addr = its->vgic_its_base + offset;
+
+       len = region->access_flags & VGIC_ACCESS_64bit ? 8 : 4;
+
+       if (is_write) {
+               if (region->uaccess_its_write)
+                       ret = region->uaccess_its_write(dev->kvm, its, addr,
+                                                       len, *reg);
+               else
+                       region->its_write(dev->kvm, its, addr, len, *reg);
+       } else {
+               *reg = region->its_read(dev->kvm, its, addr, len);
+       }
+       unlock_all_vcpus(dev->kvm);
+out:
+       mutex_unlock(&dev->kvm->lock);
+       return ret;
+}
+
+static u32 compute_next_devid_offset(struct list_head *h,
+                                    struct its_device *dev)
+{
+       struct its_device *next;
+       u32 next_offset;
+
+       if (list_is_last(&dev->dev_list, h))
+               return 0;
+       next = list_next_entry(dev, dev_list);
+       next_offset = next->device_id - dev->device_id;
+
+       return min_t(u32, next_offset, VITS_DTE_MAX_DEVID_OFFSET);
+}
+
+static u32 compute_next_eventid_offset(struct list_head *h, struct its_ite *ite)
+{
+       struct its_ite *next;
+       u32 next_offset;
+
+       if (list_is_last(&ite->ite_list, h))
+               return 0;
+       next = list_next_entry(ite, ite_list);
+       next_offset = next->event_id - ite->event_id;
+
+       return min_t(u32, next_offset, VITS_ITE_MAX_EVENTID_OFFSET);
+}
+
+/**
+ * entry_fn_t - Callback called on a table entry restore path
+ * @its: its handle
+ * @id: id of the entry
+ * @entry: pointer to the entry
+ * @opaque: pointer to an opaque data
+ *
+ * Return: < 0 on error, 0 if last element was identified, id offset to next
+ * element otherwise
+ */
+typedef int (*entry_fn_t)(struct vgic_its *its, u32 id, void *entry,
+                         void *opaque);
+
+/**
+ * scan_its_table - Scan a contiguous table in guest RAM and applies a function
+ * to each entry
+ *
+ * @its: its handle
+ * @base: base gpa of the table
+ * @size: size of the table in bytes
+ * @esz: entry size in bytes
+ * @start_id: the ID of the first entry in the table
+ * (non zero for 2d level tables)
+ * @fn: function to apply on each entry
+ *
+ * Return: < 0 on error, 0 if last element was identified, 1 otherwise
+ * (the last element may not be found on second level tables)
+ */
+static int scan_its_table(struct vgic_its *its, gpa_t base, int size, int esz,
+                         int start_id, entry_fn_t fn, void *opaque)
+{
+       void *entry = kzalloc(esz, GFP_KERNEL);
+       struct kvm *kvm = its->dev->kvm;
+       unsigned long len = size;
+       int id = start_id;
+       gpa_t gpa = base;
+       int ret;
+
+       while (len > 0) {
+               int next_offset;
+               size_t byte_offset;
+
+               ret = kvm_read_guest(kvm, gpa, entry, esz);
+               if (ret)
+                       goto out;
+
+               next_offset = fn(its, id, entry, opaque);
+               if (next_offset <= 0) {
+                       ret = next_offset;
+                       goto out;
+               }
+
+               byte_offset = next_offset * esz;
+               id += next_offset;
+               gpa += byte_offset;
+               len -= byte_offset;
+       }
+       ret =  1;
+
+out:
+       kfree(entry);
+       return ret;
+}
+
+/**
+ * vgic_its_save_ite - Save an interrupt translation entry at @gpa
+ */
+static int vgic_its_save_ite(struct vgic_its *its, struct its_device *dev,
+                             struct its_ite *ite, gpa_t gpa, int ite_esz)
+{
+       struct kvm *kvm = its->dev->kvm;
+       u32 next_offset;
+       u64 val;
+
+       next_offset = compute_next_eventid_offset(&dev->itt_head, ite);
+       val = ((u64)next_offset << KVM_ITS_ITE_NEXT_SHIFT) |
+              ((u64)ite->lpi << KVM_ITS_ITE_PINTID_SHIFT) |
+               ite->collection->collection_id;
+       val = cpu_to_le64(val);
+       return kvm_write_guest(kvm, gpa, &val, ite_esz);
+}
+
+/**
+ * vgic_its_restore_ite - restore an interrupt translation entry
+ * @event_id: id used for indexing
+ * @ptr: pointer to the ITE entry
+ * @opaque: pointer to the its_device
+ */
+static int vgic_its_restore_ite(struct vgic_its *its, u32 event_id,
+                               void *ptr, void *opaque)
+{
+       struct its_device *dev = (struct its_device *)opaque;
+       struct its_collection *collection;
+       struct kvm *kvm = its->dev->kvm;
+       struct kvm_vcpu *vcpu = NULL;
+       u64 val;
+       u64 *p = (u64 *)ptr;
+       struct vgic_irq *irq;
+       u32 coll_id, lpi_id;
+       struct its_ite *ite;
+       u32 offset;
+
+       val = *p;
+
+       val = le64_to_cpu(val);
+
+       coll_id = val & KVM_ITS_ITE_ICID_MASK;
+       lpi_id = (val & KVM_ITS_ITE_PINTID_MASK) >> KVM_ITS_ITE_PINTID_SHIFT;
+
+       if (!lpi_id)
+               return 1; /* invalid entry, no choice but to scan next entry */
+
+       if (lpi_id < VGIC_MIN_LPI)
+               return -EINVAL;
+
+       offset = val >> KVM_ITS_ITE_NEXT_SHIFT;
+       if (event_id + offset >= BIT_ULL(dev->num_eventid_bits))
+               return -EINVAL;
+
+       collection = find_collection(its, coll_id);
+       if (!collection)
+               return -EINVAL;
+
+       ite = vgic_its_alloc_ite(dev, collection, lpi_id, event_id);
+       if (IS_ERR(ite))
+               return PTR_ERR(ite);
+
+       if (its_is_collection_mapped(collection))
+               vcpu = kvm_get_vcpu(kvm, collection->target_addr);
+
+       irq = vgic_add_lpi(kvm, lpi_id, vcpu);
+       if (IS_ERR(irq))
+               return PTR_ERR(irq);
+       ite->irq = irq;
+
+       return offset;
+}
+
+static int vgic_its_ite_cmp(void *priv, struct list_head *a,
+                           struct list_head *b)
+{
+       struct its_ite *itea = container_of(a, struct its_ite, ite_list);
+       struct its_ite *iteb = container_of(b, struct its_ite, ite_list);
+
+       if (itea->event_id < iteb->event_id)
+               return -1;
+       else
+               return 1;
+}
+
+static int vgic_its_save_itt(struct vgic_its *its, struct its_device *device)
+{
+       const struct vgic_its_abi *abi = vgic_its_get_abi(its);
+       gpa_t base = device->itt_addr;
+       struct its_ite *ite;
+       int ret;
+       int ite_esz = abi->ite_esz;
+
+       list_sort(NULL, &device->itt_head, vgic_its_ite_cmp);
+
+       list_for_each_entry(ite, &device->itt_head, ite_list) {
+               gpa_t gpa = base + ite->event_id * ite_esz;
+
+               ret = vgic_its_save_ite(its, device, ite, gpa, ite_esz);
+               if (ret)
+                       return ret;
+       }
+       return 0;
+}
+
+static int vgic_its_restore_itt(struct vgic_its *its, struct its_device *dev)
+{
+       const struct vgic_its_abi *abi = vgic_its_get_abi(its);
+       gpa_t base = dev->itt_addr;
+       int ret;
+       int ite_esz = abi->ite_esz;
+       size_t max_size = BIT_ULL(dev->num_eventid_bits) * ite_esz;
+
+       ret = scan_its_table(its, base, max_size, ite_esz, 0,
+                            vgic_its_restore_ite, dev);
+
+       return ret;
+}
+
+/**
+ * vgic_its_save_dte - Save a device table entry at a given GPA
+ *
+ * @its: ITS handle
+ * @dev: ITS device
+ * @ptr: GPA
+ */
+static int vgic_its_save_dte(struct vgic_its *its, struct its_device *dev,
+                            gpa_t ptr, int dte_esz)
+{
+       struct kvm *kvm = its->dev->kvm;
+       u64 val, itt_addr_field;
+       u32 next_offset;
+
+       itt_addr_field = dev->itt_addr >> 8;
+       next_offset = compute_next_devid_offset(&its->device_list, dev);
+       val = (1ULL << KVM_ITS_DTE_VALID_SHIFT |
+              ((u64)next_offset << KVM_ITS_DTE_NEXT_SHIFT) |
+              (itt_addr_field << KVM_ITS_DTE_ITTADDR_SHIFT) |
+               (dev->num_eventid_bits - 1));
+       val = cpu_to_le64(val);
+       return kvm_write_guest(kvm, ptr, &val, dte_esz);
+}
+
+/**
+ * vgic_its_restore_dte - restore a device table entry
+ *
+ * @its: its handle
+ * @id: device id the DTE corresponds to
+ * @ptr: kernel VA where the 8 byte DTE is located
+ * @opaque: unused
+ *
+ * Return: < 0 on error, 0 if the dte is the last one, id offset to the
+ * next dte otherwise
+ */
+static int vgic_its_restore_dte(struct vgic_its *its, u32 id,
+                               void *ptr, void *opaque)
+{
+       struct its_device *dev;
+       gpa_t itt_addr;
+       u8 num_eventid_bits;
+       u64 entry = *(u64 *)ptr;
+       bool valid;
+       u32 offset;
+       int ret;
+
+       entry = le64_to_cpu(entry);
+
+       valid = entry >> KVM_ITS_DTE_VALID_SHIFT;
+       num_eventid_bits = (entry & KVM_ITS_DTE_SIZE_MASK) + 1;
+       itt_addr = ((entry & KVM_ITS_DTE_ITTADDR_MASK)
+                       >> KVM_ITS_DTE_ITTADDR_SHIFT) << 8;
+
+       if (!valid)
+               return 1;
+
+       /* dte entry is valid */
+       offset = (entry & KVM_ITS_DTE_NEXT_MASK) >> KVM_ITS_DTE_NEXT_SHIFT;
+
+       dev = vgic_its_alloc_device(its, id, itt_addr, num_eventid_bits);
+       if (IS_ERR(dev))
+               return PTR_ERR(dev);
+
+       ret = vgic_its_restore_itt(its, dev);
+       if (ret) {
+               vgic_its_free_device(its->dev->kvm, dev);
+               return ret;
+       }
+
+       return offset;
+}
+
+static int vgic_its_device_cmp(void *priv, struct list_head *a,
+                              struct list_head *b)
+{
+       struct its_device *deva = container_of(a, struct its_device, dev_list);
+       struct its_device *devb = container_of(b, struct its_device, dev_list);
+
+       if (deva->device_id < devb->device_id)
+               return -1;
+       else
+               return 1;
+}
+
+/**
+ * vgic_its_save_device_tables - Save the device table and all ITT
+ * into guest RAM
+ *
+ * L1/L2 handling is hidden by vgic_its_check_id() helper which directly
+ * returns the GPA of the device entry
+ */
+static int vgic_its_save_device_tables(struct vgic_its *its)
+{
+       const struct vgic_its_abi *abi = vgic_its_get_abi(its);
+       struct its_device *dev;
+       int dte_esz = abi->dte_esz;
+       u64 baser;
+
+       baser = its->baser_device_table;
+
+       list_sort(NULL, &its->device_list, vgic_its_device_cmp);
+
+       list_for_each_entry(dev, &its->device_list, dev_list) {
+               int ret;
+               gpa_t eaddr;
+
+               if (!vgic_its_check_id(its, baser,
+                                      dev->device_id, &eaddr))
+                       return -EINVAL;
+
+               ret = vgic_its_save_itt(its, dev);
+               if (ret)
+                       return ret;
+
+               ret = vgic_its_save_dte(its, dev, eaddr, dte_esz);
+               if (ret)
+                       return ret;
+       }
+       return 0;
+}
+
+/**
+ * handle_l1_dte - callback used for L1 device table entries (2 stage case)
+ *
+ * @its: its handle
+ * @id: index of the entry in the L1 table
+ * @addr: kernel VA
+ * @opaque: unused
+ *
+ * L1 table entries are scanned by steps of 1 entry
+ * Return < 0 if error, 0 if last dte was found when scanning the L2
+ * table, +1 otherwise (meaning next L1 entry must be scanned)
+ */
+static int handle_l1_dte(struct vgic_its *its, u32 id, void *addr,
+                        void *opaque)
+{
+       const struct vgic_its_abi *abi = vgic_its_get_abi(its);
+       int l2_start_id = id * (SZ_64K / abi->dte_esz);
+       u64 entry = *(u64 *)addr;
+       int dte_esz = abi->dte_esz;
+       gpa_t gpa;
+       int ret;
+
+       entry = le64_to_cpu(entry);
+
+       if (!(entry & KVM_ITS_L1E_VALID_MASK))
+               return 1;
+
+       gpa = entry & KVM_ITS_L1E_ADDR_MASK;
+
+       ret = scan_its_table(its, gpa, SZ_64K, dte_esz,
+                            l2_start_id, vgic_its_restore_dte, NULL);
+
+       if (ret <= 0)
+               return ret;
+
+       return 1;
+}
+
+/**
+ * vgic_its_restore_device_tables - Restore the device table and all ITT
+ * from guest RAM to internal data structs
+ */
+static int vgic_its_restore_device_tables(struct vgic_its *its)
+{
+       const struct vgic_its_abi *abi = vgic_its_get_abi(its);
+       u64 baser = its->baser_device_table;
+       int l1_esz, ret;
+       int l1_tbl_size = GITS_BASER_NR_PAGES(baser) * SZ_64K;
+       gpa_t l1_gpa;
+
+       if (!(baser & GITS_BASER_VALID))
+               return 0;
+
+       l1_gpa = BASER_ADDRESS(baser);
+
+       if (baser & GITS_BASER_INDIRECT) {
+               l1_esz = GITS_LVL1_ENTRY_SIZE;
+               ret = scan_its_table(its, l1_gpa, l1_tbl_size, l1_esz, 0,
+                                    handle_l1_dte, NULL);
+       } else {
+               l1_esz = abi->dte_esz;
+               ret = scan_its_table(its, l1_gpa, l1_tbl_size, l1_esz, 0,
+                                    vgic_its_restore_dte, NULL);
+       }
+
+       if (ret > 0)
+               ret = -EINVAL;
+
+       return ret;
+}
+
+static int vgic_its_save_cte(struct vgic_its *its,
+                            struct its_collection *collection,
+                            gpa_t gpa, int esz)
+{
+       u64 val;
+
+       val = (1ULL << KVM_ITS_CTE_VALID_SHIFT |
+              ((u64)collection->target_addr << KVM_ITS_CTE_RDBASE_SHIFT) |
+              collection->collection_id);
+       val = cpu_to_le64(val);
+       return kvm_write_guest(its->dev->kvm, gpa, &val, esz);
+}
+
+static int vgic_its_restore_cte(struct vgic_its *its, gpa_t gpa, int esz)
+{
+       struct its_collection *collection;
+       struct kvm *kvm = its->dev->kvm;
+       u32 target_addr, coll_id;
+       u64 val;
+       int ret;
+
+       BUG_ON(esz > sizeof(val));
+       ret = kvm_read_guest(kvm, gpa, &val, esz);
+       if (ret)
+               return ret;
+       val = le64_to_cpu(val);
+       if (!(val & KVM_ITS_CTE_VALID_MASK))
+               return 0;
+
+       target_addr = (u32)(val >> KVM_ITS_CTE_RDBASE_SHIFT);
+       coll_id = val & KVM_ITS_CTE_ICID_MASK;
+
+       if (target_addr >= atomic_read(&kvm->online_vcpus))
+               return -EINVAL;
+
+       collection = find_collection(its, coll_id);
+       if (collection)
+               return -EEXIST;
+       ret = vgic_its_alloc_collection(its, &collection, coll_id);
+       if (ret)
+               return ret;
+       collection->target_addr = target_addr;
+       return 1;
+}
+
+/**
+ * vgic_its_save_collection_table - Save the collection table into
+ * guest RAM
+ */
+static int vgic_its_save_collection_table(struct vgic_its *its)
+{
+       const struct vgic_its_abi *abi = vgic_its_get_abi(its);
+       struct its_collection *collection;
+       u64 val;
+       gpa_t gpa;
+       size_t max_size, filled = 0;
+       int ret, cte_esz = abi->cte_esz;
+
+       gpa = BASER_ADDRESS(its->baser_coll_table);
+       if (!gpa)
+               return 0;
+
+       max_size = GITS_BASER_NR_PAGES(its->baser_coll_table) * SZ_64K;
+
+       list_for_each_entry(collection, &its->collection_list, coll_list) {
+               ret = vgic_its_save_cte(its, collection, gpa, cte_esz);
+               if (ret)
+                       return ret;
+               gpa += cte_esz;
+               filled += cte_esz;
+       }
+
+       if (filled == max_size)
+               return 0;
+
+       /*
+        * table is not fully filled, add a last dummy element
+        * with valid bit unset
+        */
+       val = 0;
+       BUG_ON(cte_esz > sizeof(val));
+       ret = kvm_write_guest(its->dev->kvm, gpa, &val, cte_esz);
+       return ret;
+}
+
+/**
+ * vgic_its_restore_collection_table - reads the collection table
+ * in guest memory and restores the ITS internal state. Requires the
+ * BASER registers to be restored before.
+ */
+static int vgic_its_restore_collection_table(struct vgic_its *its)
+{
+       const struct vgic_its_abi *abi = vgic_its_get_abi(its);
+       int cte_esz = abi->cte_esz;
+       size_t max_size, read = 0;
+       gpa_t gpa;
+       int ret;
+
+       if (!(its->baser_coll_table & GITS_BASER_VALID))
+               return 0;
+
+       gpa = BASER_ADDRESS(its->baser_coll_table);
+
+       max_size = GITS_BASER_NR_PAGES(its->baser_coll_table) * SZ_64K;
+
+       while (read < max_size) {
+               ret = vgic_its_restore_cte(its, gpa, cte_esz);
+               if (ret <= 0)
+                       break;
+               gpa += cte_esz;
+               read += cte_esz;
+       }
+       return ret;
+}
+
+/**
+ * vgic_its_save_tables_v0 - Save the ITS tables into guest ARM
+ * according to v0 ABI
+ */
+static int vgic_its_save_tables_v0(struct vgic_its *its)
+{
+       struct kvm *kvm = its->dev->kvm;
+       int ret;
+
+       mutex_lock(&kvm->lock);
+       mutex_lock(&its->its_lock);
+
+       if (!lock_all_vcpus(kvm)) {
+               mutex_unlock(&its->its_lock);
+               mutex_unlock(&kvm->lock);
+               return -EBUSY;
+       }
+
+       ret = vgic_its_save_device_tables(its);
+       if (ret)
+               goto out;
+
+       ret = vgic_its_save_collection_table(its);
+
+out:
+       unlock_all_vcpus(kvm);
+       mutex_unlock(&its->its_lock);
+       mutex_unlock(&kvm->lock);
+       return ret;
+}
+
+/**
+ * vgic_its_restore_tables_v0 - Restore the ITS tables from guest RAM
+ * to internal data structs according to V0 ABI
+ *
+ */
+static int vgic_its_restore_tables_v0(struct vgic_its *its)
+{
+       struct kvm *kvm = its->dev->kvm;
+       int ret;
+
+       mutex_lock(&kvm->lock);
+       mutex_lock(&its->its_lock);
+
+       if (!lock_all_vcpus(kvm)) {
+               mutex_unlock(&its->its_lock);
+               mutex_unlock(&kvm->lock);
+               return -EBUSY;
+       }
+
+       ret = vgic_its_restore_collection_table(its);
+       if (ret)
+               goto out;
+
+       ret = vgic_its_restore_device_tables(its);
+out:
+       unlock_all_vcpus(kvm);
+       mutex_unlock(&its->its_lock);
+       mutex_unlock(&kvm->lock);
+
+       return ret;
+}
+
+static int vgic_its_commit_v0(struct vgic_its *its)
+{
+       const struct vgic_its_abi *abi;
+
+       abi = vgic_its_get_abi(its);
+       its->baser_coll_table &= ~GITS_BASER_ENTRY_SIZE_MASK;
+       its->baser_device_table &= ~GITS_BASER_ENTRY_SIZE_MASK;
+
+       its->baser_coll_table |= (GIC_ENCODE_SZ(abi->cte_esz, 5)
+                                       << GITS_BASER_ENTRY_SIZE_SHIFT);
+
+       its->baser_device_table |= (GIC_ENCODE_SZ(abi->dte_esz, 5)
+                                       << GITS_BASER_ENTRY_SIZE_SHIFT);
+       return 0;
+}
+
 static int vgic_its_has_attr(struct kvm_device *dev,
                             struct kvm_device_attr *attr)
 {
@@ -1480,8 +2355,14 @@ static int vgic_its_has_attr(struct kvm_device *dev,
                switch (attr->attr) {
                case KVM_DEV_ARM_VGIC_CTRL_INIT:
                        return 0;
+               case KVM_DEV_ARM_ITS_SAVE_TABLES:
+                       return 0;
+               case KVM_DEV_ARM_ITS_RESTORE_TABLES:
+                       return 0;
                }
                break;
+       case KVM_DEV_ARM_VGIC_GRP_ITS_REGS:
+               return vgic_its_has_attr_regs(dev, attr);
        }
        return -ENXIO;
 }
@@ -1509,18 +2390,30 @@ static int vgic_its_set_attr(struct kvm_device *dev,
                if (ret)
                        return ret;
 
-               its->vgic_its_base = addr;
-
-               return 0;
+               return vgic_register_its_iodev(dev->kvm, its, addr);
        }
-       case KVM_DEV_ARM_VGIC_GRP_CTRL:
+       case KVM_DEV_ARM_VGIC_GRP_CTRL: {
+               const struct vgic_its_abi *abi = vgic_its_get_abi(its);
+
                switch (attr->attr) {
                case KVM_DEV_ARM_VGIC_CTRL_INIT:
-                       its->initialized = true;
-
+                       /* Nothing to do */
                        return 0;
+               case KVM_DEV_ARM_ITS_SAVE_TABLES:
+                       return abi->save_tables(its);
+               case KVM_DEV_ARM_ITS_RESTORE_TABLES:
+                       return abi->restore_tables(its);
                }
-               break;
+       }
+       case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: {
+               u64 __user *uaddr = (u64 __user *)(long)attr->addr;
+               u64 reg;
+
+               if (get_user(reg, uaddr))
+                       return -EFAULT;
+
+               return vgic_its_attr_regs_access(dev, attr, &reg, true);
+       }
        }
        return -ENXIO;
 }
@@ -1541,10 +2434,20 @@ static int vgic_its_get_attr(struct kvm_device *dev,
                if (copy_to_user(uaddr, &addr, sizeof(addr)))
                        return -EFAULT;
                break;
+       }
+       case KVM_DEV_ARM_VGIC_GRP_ITS_REGS: {
+               u64 __user *uaddr = (u64 __user *)(long)attr->addr;
+               u64 reg;
+               int ret;
+
+               ret = vgic_its_attr_regs_access(dev, attr, &reg, false);
+               if (ret)
+                       return ret;
+               return put_user(reg, uaddr);
+       }
        default:
                return -ENXIO;
        }
-       }
 
        return 0;
 }
@@ -1563,30 +2466,3 @@ int kvm_vgic_register_its_device(void)
        return kvm_register_device_ops(&kvm_arm_vgic_its_ops,
                                       KVM_DEV_TYPE_ARM_VGIC_ITS);
 }
-
-/*
- * Registers all ITSes with the kvm_io_bus framework.
- * To follow the existing VGIC initialization sequence, this has to be
- * done as late as possible, just before the first VCPU runs.
- */
-int vgic_register_its_iodevs(struct kvm *kvm)
-{
-       struct kvm_device *dev;
-       int ret = 0;
-
-       list_for_each_entry(dev, &kvm->devices, vm_node) {
-               if (dev->ops != &kvm_arm_vgic_its_ops)
-                       continue;
-
-               ret = vgic_register_its_iodev(kvm, dev->private);
-               if (ret)
-                       return ret;
-               /*
-                * We don't need to care about tearing down previously
-                * registered ITSes, as the kvm_io_bus framework removes
-                * them for us if the VM gets destroyed.
-                */
-       }
-
-       return ret;
-}
index d181d2baee9c4d6c5a5d93a569110e9030bc5e7a..10ae6f394b718d8e49805d23481974b0526764d1 100644 (file)
@@ -37,6 +37,14 @@ int vgic_check_ioaddr(struct kvm *kvm, phys_addr_t *ioaddr,
        return 0;
 }
 
+static int vgic_check_type(struct kvm *kvm, int type_needed)
+{
+       if (kvm->arch.vgic.vgic_model != type_needed)
+               return -ENODEV;
+       else
+               return 0;
+}
+
 /**
  * kvm_vgic_addr - set or get vgic VM base addresses
  * @kvm:   pointer to the vm struct
@@ -57,40 +65,41 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
 {
        int r = 0;
        struct vgic_dist *vgic = &kvm->arch.vgic;
-       int type_needed;
        phys_addr_t *addr_ptr, alignment;
 
        mutex_lock(&kvm->lock);
        switch (type) {
        case KVM_VGIC_V2_ADDR_TYPE_DIST:
-               type_needed = KVM_DEV_TYPE_ARM_VGIC_V2;
+               r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V2);
                addr_ptr = &vgic->vgic_dist_base;
                alignment = SZ_4K;
                break;
        case KVM_VGIC_V2_ADDR_TYPE_CPU:
-               type_needed = KVM_DEV_TYPE_ARM_VGIC_V2;
+               r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V2);
                addr_ptr = &vgic->vgic_cpu_base;
                alignment = SZ_4K;
                break;
        case KVM_VGIC_V3_ADDR_TYPE_DIST:
-               type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
+               r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V3);
                addr_ptr = &vgic->vgic_dist_base;
                alignment = SZ_64K;
                break;
        case KVM_VGIC_V3_ADDR_TYPE_REDIST:
-               type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
+               r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V3);
+               if (r)
+                       break;
+               if (write) {
+                       r = vgic_v3_set_redist_base(kvm, *addr);
+                       goto out;
+               }
                addr_ptr = &vgic->vgic_redist_base;
-               alignment = SZ_64K;
                break;
        default:
                r = -ENODEV;
-               goto out;
        }
 
-       if (vgic->vgic_model != type_needed) {
-               r = -ENODEV;
+       if (r)
                goto out;
-       }
 
        if (write) {
                r = vgic_check_ioaddr(kvm, addr_ptr, *addr, alignment);
@@ -259,13 +268,13 @@ static void unlock_vcpus(struct kvm *kvm, int vcpu_lock_idx)
        }
 }
 
-static void unlock_all_vcpus(struct kvm *kvm)
+void unlock_all_vcpus(struct kvm *kvm)
 {
        unlock_vcpus(kvm, atomic_read(&kvm->online_vcpus) - 1);
 }
 
 /* Returns true if all vcpus were locked, false otherwise */
-static bool lock_all_vcpus(struct kvm *kvm)
+bool lock_all_vcpus(struct kvm *kvm)
 {
        struct kvm_vcpu *tmp_vcpu;
        int c;
@@ -580,6 +589,24 @@ static int vgic_v3_set_attr(struct kvm_device *dev,
                reg = tmp32;
                return vgic_v3_attr_regs_access(dev, attr, &reg, true);
        }
+       case KVM_DEV_ARM_VGIC_GRP_CTRL: {
+               int ret;
+
+               switch (attr->attr) {
+               case KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES:
+                       mutex_lock(&dev->kvm->lock);
+
+                       if (!lock_all_vcpus(dev->kvm)) {
+                               mutex_unlock(&dev->kvm->lock);
+                               return -EBUSY;
+                       }
+                       ret = vgic_v3_save_pending_tables(dev->kvm);
+                       unlock_all_vcpus(dev->kvm);
+                       mutex_unlock(&dev->kvm->lock);
+                       return ret;
+               }
+               break;
+       }
        }
        return -ENXIO;
 }
@@ -658,6 +685,8 @@ static int vgic_v3_has_attr(struct kvm_device *dev,
                switch (attr->attr) {
                case KVM_DEV_ARM_VGIC_CTRL_INIT:
                        return 0;
+               case KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES:
+                       return 0;
                }
        }
        return -ENXIO;
index 6afb3b484886336b963cbcc1cb6d2d7cb89ba2d1..201d5e2e973dd4504c1f41747b2f07bb797ade11 100644 (file)
@@ -556,67 +556,136 @@ unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev)
        return SZ_64K;
 }
 
-int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t redist_base_address)
+/**
+ * vgic_register_redist_iodev - register a single redist iodev
+ * @vcpu:    The VCPU to which the redistributor belongs
+ *
+ * Register a KVM iodev for this VCPU's redistributor using the address
+ * provided.
+ *
+ * Return 0 on success, -ERRNO otherwise.
+ */
+int vgic_register_redist_iodev(struct kvm_vcpu *vcpu)
 {
-       struct kvm_vcpu *vcpu;
-       int c, ret = 0;
+       struct kvm *kvm = vcpu->kvm;
+       struct vgic_dist *vgic = &kvm->arch.vgic;
+       struct vgic_io_device *rd_dev = &vcpu->arch.vgic_cpu.rd_iodev;
+       struct vgic_io_device *sgi_dev = &vcpu->arch.vgic_cpu.sgi_iodev;
+       gpa_t rd_base, sgi_base;
+       int ret;
 
-       kvm_for_each_vcpu(c, vcpu, kvm) {
-               gpa_t rd_base = redist_base_address + c * SZ_64K * 2;
-               gpa_t sgi_base = rd_base + SZ_64K;
-               struct vgic_io_device *rd_dev = &vcpu->arch.vgic_cpu.rd_iodev;
-               struct vgic_io_device *sgi_dev = &vcpu->arch.vgic_cpu.sgi_iodev;
-
-               kvm_iodevice_init(&rd_dev->dev, &kvm_io_gic_ops);
-               rd_dev->base_addr = rd_base;
-               rd_dev->iodev_type = IODEV_REDIST;
-               rd_dev->regions = vgic_v3_rdbase_registers;
-               rd_dev->nr_regions = ARRAY_SIZE(vgic_v3_rdbase_registers);
-               rd_dev->redist_vcpu = vcpu;
+       /*
+        * We may be creating VCPUs before having set the base address for the
+        * redistributor region, in which case we will come back to this
+        * function for all VCPUs when the base address is set.  Just return
+        * without doing any work for now.
+        */
+       if (IS_VGIC_ADDR_UNDEF(vgic->vgic_redist_base))
+               return 0;
 
-               mutex_lock(&kvm->slots_lock);
-               ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, rd_base,
-                                             SZ_64K, &rd_dev->dev);
-               mutex_unlock(&kvm->slots_lock);
+       if (!vgic_v3_check_base(kvm))
+               return -EINVAL;
 
-               if (ret)
-                       break;
+       rd_base = vgic->vgic_redist_base + vgic->vgic_redist_free_offset;
+       sgi_base = rd_base + SZ_64K;
 
-               kvm_iodevice_init(&sgi_dev->dev, &kvm_io_gic_ops);
-               sgi_dev->base_addr = sgi_base;
-               sgi_dev->iodev_type = IODEV_REDIST;
-               sgi_dev->regions = vgic_v3_sgibase_registers;
-               sgi_dev->nr_regions = ARRAY_SIZE(vgic_v3_sgibase_registers);
-               sgi_dev->redist_vcpu = vcpu;
+       kvm_iodevice_init(&rd_dev->dev, &kvm_io_gic_ops);
+       rd_dev->base_addr = rd_base;
+       rd_dev->iodev_type = IODEV_REDIST;
+       rd_dev->regions = vgic_v3_rdbase_registers;
+       rd_dev->nr_regions = ARRAY_SIZE(vgic_v3_rdbase_registers);
+       rd_dev->redist_vcpu = vcpu;
 
-               mutex_lock(&kvm->slots_lock);
-               ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, sgi_base,
-                                             SZ_64K, &sgi_dev->dev);
-               mutex_unlock(&kvm->slots_lock);
-               if (ret) {
-                       kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
-                                                 &rd_dev->dev);
+       mutex_lock(&kvm->slots_lock);
+       ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, rd_base,
+                                     SZ_64K, &rd_dev->dev);
+       mutex_unlock(&kvm->slots_lock);
+
+       if (ret)
+               return ret;
+
+       kvm_iodevice_init(&sgi_dev->dev, &kvm_io_gic_ops);
+       sgi_dev->base_addr = sgi_base;
+       sgi_dev->iodev_type = IODEV_REDIST;
+       sgi_dev->regions = vgic_v3_sgibase_registers;
+       sgi_dev->nr_regions = ARRAY_SIZE(vgic_v3_sgibase_registers);
+       sgi_dev->redist_vcpu = vcpu;
+
+       mutex_lock(&kvm->slots_lock);
+       ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, sgi_base,
+                                     SZ_64K, &sgi_dev->dev);
+       if (ret) {
+               kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
+                                         &rd_dev->dev);
+               goto out;
+       }
+
+       vgic->vgic_redist_free_offset += 2 * SZ_64K;
+out:
+       mutex_unlock(&kvm->slots_lock);
+       return ret;
+}
+
+static void vgic_unregister_redist_iodev(struct kvm_vcpu *vcpu)
+{
+       struct vgic_io_device *rd_dev = &vcpu->arch.vgic_cpu.rd_iodev;
+       struct vgic_io_device *sgi_dev = &vcpu->arch.vgic_cpu.sgi_iodev;
+
+       kvm_io_bus_unregister_dev(vcpu->kvm, KVM_MMIO_BUS, &rd_dev->dev);
+       kvm_io_bus_unregister_dev(vcpu->kvm, KVM_MMIO_BUS, &sgi_dev->dev);
+}
+
+static int vgic_register_all_redist_iodevs(struct kvm *kvm)
+{
+       struct kvm_vcpu *vcpu;
+       int c, ret = 0;
+
+       kvm_for_each_vcpu(c, vcpu, kvm) {
+               ret = vgic_register_redist_iodev(vcpu);
+               if (ret)
                        break;
-               }
        }
 
        if (ret) {
                /* The current c failed, so we start with the previous one. */
+               mutex_lock(&kvm->slots_lock);
                for (c--; c >= 0; c--) {
-                       struct vgic_cpu *vgic_cpu;
-
                        vcpu = kvm_get_vcpu(kvm, c);
-                       vgic_cpu = &vcpu->arch.vgic_cpu;
-                       kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
-                                                 &vgic_cpu->rd_iodev.dev);
-                       kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
-                                                 &vgic_cpu->sgi_iodev.dev);
+                       vgic_unregister_redist_iodev(vcpu);
                }
+               mutex_unlock(&kvm->slots_lock);
        }
 
        return ret;
 }
 
+int vgic_v3_set_redist_base(struct kvm *kvm, u64 addr)
+{
+       struct vgic_dist *vgic = &kvm->arch.vgic;
+       int ret;
+
+       /* vgic_check_ioaddr makes sure we don't do this twice */
+       ret = vgic_check_ioaddr(kvm, &vgic->vgic_redist_base, addr, SZ_64K);
+       if (ret)
+               return ret;
+
+       vgic->vgic_redist_base = addr;
+       if (!vgic_v3_check_base(kvm)) {
+               vgic->vgic_redist_base = VGIC_ADDR_UNDEF;
+               return -EINVAL;
+       }
+
+       /*
+        * Register iodevs for each existing VCPU.  Adding more VCPUs
+        * afterwards will register the iodevs when needed.
+        */
+       ret = vgic_register_all_redist_iodevs(kvm);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
 int vgic_v3_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
 {
        const struct vgic_register_region *region;
index 2a5db135272215d5c9d4bfa544b7d3ed11a9b9c3..1c17b2a2f105c0a11cbe1083088e71d94c3e3b51 100644 (file)
@@ -446,13 +446,12 @@ static int match_region(const void *key, const void *elt)
        return 0;
 }
 
-/* Find the proper register handler entry given a certain address offset. */
-static const struct vgic_register_region *
-vgic_find_mmio_region(const struct vgic_register_region *region, int nr_regions,
-                     unsigned int offset)
+const struct vgic_register_region *
+vgic_find_mmio_region(const struct vgic_register_region *regions,
+                     int nr_regions, unsigned int offset)
 {
-       return bsearch((void *)(uintptr_t)offset, region, nr_regions,
-                      sizeof(region[0]), match_region);
+       return bsearch((void *)(uintptr_t)offset, regions, nr_regions,
+                      sizeof(regions[0]), match_region);
 }
 
 void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr)
index 98bb566b660a29c85614beb22fe01659f5e74513..ea4171acdef3b2da35326fb2ded7dd1b37b8eaa1 100644 (file)
@@ -36,8 +36,13 @@ struct vgic_register_region {
        };
        unsigned long (*uaccess_read)(struct kvm_vcpu *vcpu, gpa_t addr,
                                      unsigned int len);
-       void (*uaccess_write)(struct kvm_vcpu *vcpu, gpa_t addr,
-                             unsigned int len, unsigned long val);
+       union {
+               void (*uaccess_write)(struct kvm_vcpu *vcpu, gpa_t addr,
+                                     unsigned int len, unsigned long val);
+               int (*uaccess_its_write)(struct kvm *kvm, struct vgic_its *its,
+                                        gpa_t addr, unsigned int len,
+                                        unsigned long val);
+       };
 };
 
 extern struct kvm_io_device_ops kvm_io_gic_ops;
@@ -192,4 +197,9 @@ u64 vgic_sanitise_shareability(u64 reg);
 u64 vgic_sanitise_field(u64 reg, u64 field_mask, int field_shift,
                        u64 (*sanitise_fn)(u64));
 
+/* Find the proper register handler entry given a certain address offset */
+const struct vgic_register_region *
+vgic_find_mmio_region(const struct vgic_register_region *regions,
+                     int nr_regions, unsigned int offset);
+
 #endif
index a65757aab6d32cef8fff2306e80fb6df0486bbc7..504b4bd0d651cf820eec843a325c649e0d1bd181 100644 (file)
@@ -149,6 +149,13 @@ void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
        if (irq->hw) {
                val |= GICH_LR_HW;
                val |= irq->hwintid << GICH_LR_PHYSID_CPUID_SHIFT;
+               /*
+                * Never set pending+active on a HW interrupt, as the
+                * pending state is kept at the physical distributor
+                * level.
+                */
+               if (irq->active && irq_is_pending(irq))
+                       val &= ~GICH_LR_PENDING_BIT;
        } else {
                if (irq->config == VGIC_CONFIG_LEVEL)
                        val |= GICH_LR_EOI;
index df1503650300767f774e711fcadf98037f60fcfd..6fe3f003636a311d055581ee6a8133d0951fd3f2 100644 (file)
@@ -127,6 +127,13 @@ void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
        if (irq->hw) {
                val |= ICH_LR_HW;
                val |= ((u64)irq->hwintid) << ICH_LR_PHYS_ID_SHIFT;
+               /*
+                * Never set pending+active on a HW interrupt, as the
+                * pending state is kept at the physical distributor
+                * level.
+                */
+               if (irq->active && irq_is_pending(irq))
+                       val &= ~ICH_LR_PENDING_BIT;
        } else {
                if (irq->config == VGIC_CONFIG_LEVEL)
                        val |= ICH_LR_EOI;
@@ -234,19 +241,125 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu)
        vgic_v3->vgic_hcr = ICH_HCR_EN;
 }
 
-/* check for overlapping regions and for regions crossing the end of memory */
-static bool vgic_v3_check_base(struct kvm *kvm)
+int vgic_v3_lpi_sync_pending_status(struct kvm *kvm, struct vgic_irq *irq)
+{
+       struct kvm_vcpu *vcpu;
+       int byte_offset, bit_nr;
+       gpa_t pendbase, ptr;
+       bool status;
+       u8 val;
+       int ret;
+
+retry:
+       vcpu = irq->target_vcpu;
+       if (!vcpu)
+               return 0;
+
+       pendbase = GICR_PENDBASER_ADDRESS(vcpu->arch.vgic_cpu.pendbaser);
+
+       byte_offset = irq->intid / BITS_PER_BYTE;
+       bit_nr = irq->intid % BITS_PER_BYTE;
+       ptr = pendbase + byte_offset;
+
+       ret = kvm_read_guest(kvm, ptr, &val, 1);
+       if (ret)
+               return ret;
+
+       status = val & (1 << bit_nr);
+
+       spin_lock(&irq->irq_lock);
+       if (irq->target_vcpu != vcpu) {
+               spin_unlock(&irq->irq_lock);
+               goto retry;
+       }
+       irq->pending_latch = status;
+       vgic_queue_irq_unlock(vcpu->kvm, irq);
+
+       if (status) {
+               /* clear consumed data */
+               val &= ~(1 << bit_nr);
+               ret = kvm_write_guest(kvm, ptr, &val, 1);
+               if (ret)
+                       return ret;
+       }
+       return 0;
+}
+
+/**
+ * vgic_its_save_pending_tables - Save the pending tables into guest RAM
+ * kvm lock and all vcpu lock must be held
+ */
+int vgic_v3_save_pending_tables(struct kvm *kvm)
+{
+       struct vgic_dist *dist = &kvm->arch.vgic;
+       int last_byte_offset = -1;
+       struct vgic_irq *irq;
+       int ret;
+
+       list_for_each_entry(irq, &dist->lpi_list_head, lpi_list) {
+               int byte_offset, bit_nr;
+               struct kvm_vcpu *vcpu;
+               gpa_t pendbase, ptr;
+               bool stored;
+               u8 val;
+
+               vcpu = irq->target_vcpu;
+               if (!vcpu)
+                       continue;
+
+               pendbase = GICR_PENDBASER_ADDRESS(vcpu->arch.vgic_cpu.pendbaser);
+
+               byte_offset = irq->intid / BITS_PER_BYTE;
+               bit_nr = irq->intid % BITS_PER_BYTE;
+               ptr = pendbase + byte_offset;
+
+               if (byte_offset != last_byte_offset) {
+                       ret = kvm_read_guest(kvm, ptr, &val, 1);
+                       if (ret)
+                               return ret;
+                       last_byte_offset = byte_offset;
+               }
+
+               stored = val & (1U << bit_nr);
+               if (stored == irq->pending_latch)
+                       continue;
+
+               if (irq->pending_latch)
+                       val |= 1 << bit_nr;
+               else
+                       val &= ~(1 << bit_nr);
+
+               ret = kvm_write_guest(kvm, ptr, &val, 1);
+               if (ret)
+                       return ret;
+       }
+       return 0;
+}
+
+/*
+ * Check for overlapping regions and for regions crossing the end of memory
+ * for base addresses which have already been set.
+ */
+bool vgic_v3_check_base(struct kvm *kvm)
 {
        struct vgic_dist *d = &kvm->arch.vgic;
        gpa_t redist_size = KVM_VGIC_V3_REDIST_SIZE;
 
        redist_size *= atomic_read(&kvm->online_vcpus);
 
-       if (d->vgic_dist_base + KVM_VGIC_V3_DIST_SIZE < d->vgic_dist_base)
+       if (!IS_VGIC_ADDR_UNDEF(d->vgic_dist_base) &&
+           d->vgic_dist_base + KVM_VGIC_V3_DIST_SIZE < d->vgic_dist_base)
                return false;
-       if (d->vgic_redist_base + redist_size < d->vgic_redist_base)
+
+       if (!IS_VGIC_ADDR_UNDEF(d->vgic_redist_base) &&
+           d->vgic_redist_base + redist_size < d->vgic_redist_base)
                return false;
 
+       /* Both base addresses must be set to check if they overlap */
+       if (IS_VGIC_ADDR_UNDEF(d->vgic_dist_base) ||
+           IS_VGIC_ADDR_UNDEF(d->vgic_redist_base))
+               return true;
+
        if (d->vgic_dist_base + KVM_VGIC_V3_DIST_SIZE <= d->vgic_redist_base)
                return true;
        if (d->vgic_redist_base + redist_size <= d->vgic_dist_base)
@@ -291,20 +404,6 @@ int vgic_v3_map_resources(struct kvm *kvm)
                goto out;
        }
 
-       ret = vgic_register_redist_iodevs(kvm, dist->vgic_redist_base);
-       if (ret) {
-               kvm_err("Unable to register VGICv3 redist MMIO regions\n");
-               goto out;
-       }
-
-       if (vgic_has_its(kvm)) {
-               ret = vgic_register_its_iodevs(kvm);
-               if (ret) {
-                       kvm_err("Unable to register VGIC ITS MMIO regions\n");
-                       goto out;
-               }
-       }
-
        dist->ready = true;
 
 out:
index 4346bc7d08dc38a187e3c19359402ba9e0e06eaa..83b24d20ff8f817e688548d69e50e00d25699210 100644 (file)
@@ -21,7 +21,7 @@
 #include "vgic.h"
 
 #define CREATE_TRACE_POINTS
-#include "../trace.h"
+#include "trace.h"
 
 #ifdef CONFIG_DEBUG_SPINLOCK
 #define DEBUG_SPINLOCK_BUG_ON(p) BUG_ON(p)
index 799fd651b2605d92ae3982c2e314b36d6486a8db..da83e4caa272f2621b840123e79dfbc3e5ceaead 100644 (file)
                                      KVM_REG_ARM_VGIC_SYSREG_CRM_MASK | \
                                      KVM_REG_ARM_VGIC_SYSREG_OP2_MASK)
 
+/*
+ * As per Documentation/virtual/kvm/devices/arm-vgic-its.txt,
+ * below macros are defined for ITS table entry encoding.
+ */
+#define KVM_ITS_CTE_VALID_SHIFT                63
+#define KVM_ITS_CTE_VALID_MASK         BIT_ULL(63)
+#define KVM_ITS_CTE_RDBASE_SHIFT       16
+#define KVM_ITS_CTE_ICID_MASK          GENMASK_ULL(15, 0)
+#define KVM_ITS_ITE_NEXT_SHIFT         48
+#define KVM_ITS_ITE_PINTID_SHIFT       16
+#define KVM_ITS_ITE_PINTID_MASK                GENMASK_ULL(47, 16)
+#define KVM_ITS_ITE_ICID_MASK          GENMASK_ULL(15, 0)
+#define KVM_ITS_DTE_VALID_SHIFT                63
+#define KVM_ITS_DTE_VALID_MASK         BIT_ULL(63)
+#define KVM_ITS_DTE_NEXT_SHIFT         49
+#define KVM_ITS_DTE_NEXT_MASK          GENMASK_ULL(62, 49)
+#define KVM_ITS_DTE_ITTADDR_SHIFT      5
+#define KVM_ITS_DTE_ITTADDR_MASK       GENMASK_ULL(48, 5)
+#define KVM_ITS_DTE_SIZE_MASK          GENMASK_ULL(4, 0)
+#define KVM_ITS_L1E_VALID_MASK         BIT_ULL(63)
+/* we only support 64 kB translation table page size */
+#define KVM_ITS_L1E_ADDR_MASK          GENMASK_ULL(51, 16)
+
 static inline bool irq_is_pending(struct vgic_irq *irq)
 {
        if (irq->config == VGIC_CONFIG_EDGE)
@@ -157,12 +180,15 @@ void vgic_v3_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_v3_enable(struct kvm_vcpu *vcpu);
 int vgic_v3_probe(const struct gic_kvm_info *info);
 int vgic_v3_map_resources(struct kvm *kvm);
-int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
+int vgic_v3_lpi_sync_pending_status(struct kvm *kvm, struct vgic_irq *irq);
+int vgic_v3_save_pending_tables(struct kvm *kvm);
+int vgic_v3_set_redist_base(struct kvm *kvm, u64 addr);
+int vgic_register_redist_iodev(struct kvm_vcpu *vcpu);
+bool vgic_v3_check_base(struct kvm *kvm);
 
 void vgic_v3_load(struct kvm_vcpu *vcpu);
 void vgic_v3_put(struct kvm_vcpu *vcpu);
 
-int vgic_register_its_iodevs(struct kvm *kvm);
 bool vgic_has_its(struct kvm *kvm);
 int kvm_vgic_register_its_device(void);
 void vgic_enable_lpis(struct kvm_vcpu *vcpu);
@@ -187,4 +213,7 @@ int vgic_init(struct kvm *kvm);
 int vgic_debug_init(struct kvm *kvm);
 int vgic_debug_destroy(struct kvm *kvm);
 
+bool lock_all_vcpus(struct kvm *kvm);
+void unlock_all_vcpus(struct kvm *kvm);
+
 #endif
index 6e3b12c1925a00a13fabfebd808faf357783a0a5..f0fe9d02f6bb2c47d909cf493ad6e19778cc666c 100644 (file)
@@ -523,7 +523,7 @@ static struct kvm_memslots *kvm_alloc_memslots(void)
        int i;
        struct kvm_memslots *slots;
 
-       slots = kvm_kvzalloc(sizeof(struct kvm_memslots));
+       slots = kvzalloc(sizeof(struct kvm_memslots), GFP_KERNEL);
        if (!slots)
                return NULL;
 
@@ -708,18 +708,6 @@ out_err_no_disable:
        return ERR_PTR(r);
 }
 
-/*
- * Avoid using vmalloc for a small buffer.
- * Should not be used when the size is statically known.
- */
-void *kvm_kvzalloc(unsigned long size)
-{
-       if (size > PAGE_SIZE)
-               return vzalloc(size);
-       else
-               return kzalloc(size, GFP_KERNEL);
-}
-
 static void kvm_destroy_devices(struct kvm *kvm)
 {
        struct kvm_device *dev, *tmp;
@@ -801,7 +789,7 @@ static int kvm_create_dirty_bitmap(struct kvm_memory_slot *memslot)
 {
        unsigned long dirty_bytes = 2 * kvm_dirty_bitmap_bytes(memslot);
 
-       memslot->dirty_bitmap = kvm_kvzalloc(dirty_bytes);
+       memslot->dirty_bitmap = kvzalloc(dirty_bytes, GFP_KERNEL);
        if (!memslot->dirty_bitmap)
                return -ENOMEM;
 
@@ -1027,7 +1015,7 @@ int __kvm_set_memory_region(struct kvm *kvm,
                        goto out_free;
        }
 
-       slots = kvm_kvzalloc(sizeof(struct kvm_memslots));
+       slots = kvzalloc(sizeof(struct kvm_memslots), GFP_KERNEL);
        if (!slots)
                goto out_free;
        memcpy(slots, __kvm_memslots(kvm, as_id), sizeof(struct kvm_memslots));
@@ -2848,10 +2836,6 @@ static struct kvm_device_ops *kvm_device_ops_table[KVM_DEV_TYPE_MAX] = {
        [KVM_DEV_TYPE_FSL_MPIC_20]      = &kvm_mpic_ops,
        [KVM_DEV_TYPE_FSL_MPIC_42]      = &kvm_mpic_ops,
 #endif
-
-#ifdef CONFIG_KVM_XICS
-       [KVM_DEV_TYPE_XICS]             = &kvm_xics_ops,
-#endif
 };
 
 int kvm_register_device_ops(struct kvm_device_ops *ops, u32 type)
@@ -3727,7 +3711,7 @@ static const struct file_operations vm_stat_get_per_vm_fops = {
        .release = kvm_debugfs_release,
        .read    = simple_attr_read,
        .write   = simple_attr_write,
-       .llseek  = generic_file_llseek,
+       .llseek  = no_llseek,
 };
 
 static int vcpu_stat_get_per_vm(void *data, u64 *val)
@@ -3772,7 +3756,7 @@ static const struct file_operations vcpu_stat_get_per_vm_fops = {
        .release = kvm_debugfs_release,
        .read    = simple_attr_read,
        .write   = simple_attr_write,
-       .llseek  = generic_file_llseek,
+       .llseek  = no_llseek,
 };
 
 static const struct file_operations *stat_fops_per_vm[] = {